Skip to content

Commit 3d4bfb0

Browse files
committed
feat: implement "Hide Seen Repositories" and Flatpak packaging
- **New Feature: Seen Repositories** - Implement a tracking system to mark GitHub repositories as "seen" once viewed in the details screen. - Add a toggle in Profile settings to hide previously seen repositories from discovery and search feeds. - Provide a "Clear Seen History" option in settings to reset the seen status of all repositories. - Update `HomeViewModel`, `SearchViewModel`, and `DetailsViewModel` to handle seen repository state and filtering logic. - **Database & Data Layer** - Perform a Room database migration (version 5 to 6) to add the `seen_repos` table. - Create `SeenRepoDao`, `SeenRepoEntity`, and `SeenReposRepository` to manage persistent seen status. - Update `TweaksRepository` to store the "Hide Seen" user preference. - **Flatpak Packaging** - Add initial Flatpak packaging support including build manifest (`.yml`), AppStream metadata, desktop entry, and launcher scripts. - Include a comprehensive `README.md` in the packaging directory detailing build requirements and local installation steps. - **UI & Localization** - Add localized strings for "Hide Seen Repositories" and "Clear Seen History" features. - Enhance the Profile screen with new toggle and action cards for managing seen repository history.
1 parent 6e24d9d commit 3d4bfb0

27 files changed

Lines changed: 1416 additions & 5 deletions

File tree

core/data/schemas/zed.rainxch.core.data.local.db.AppDatabase/4.json

Lines changed: 499 additions & 0 deletions
Large diffs are not rendered by default.

core/data/schemas/zed.rainxch.core.data.local.db.AppDatabase/5.json

Lines changed: 504 additions & 0 deletions
Large diffs are not rendered by default.

core/data/src/androidMain/kotlin/zed/rainxch/core/data/local/db/initDatabase.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import zed.rainxch.core.data.local.db.migrations.MIGRATION_1_2
77
import zed.rainxch.core.data.local.db.migrations.MIGRATION_2_3
88
import zed.rainxch.core.data.local.db.migrations.MIGRATION_3_4
99
import zed.rainxch.core.data.local.db.migrations.MIGRATION_4_5
10+
import zed.rainxch.core.data.local.db.migrations.MIGRATION_5_6
1011

1112
fun initDatabase(context: Context): AppDatabase {
1213
val appContext = context.applicationContext
@@ -21,5 +22,6 @@ fun initDatabase(context: Context): AppDatabase {
2122
MIGRATION_2_3,
2223
MIGRATION_3_4,
2324
MIGRATION_4_5,
25+
MIGRATION_5_6,
2426
).build()
2527
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package zed.rainxch.core.data.local.db.migrations
2+
3+
import androidx.room.migration.Migration
4+
import androidx.sqlite.db.SupportSQLiteDatabase
5+
6+
val MIGRATION_5_6 =
7+
object : Migration(5, 6) {
8+
override fun migrate(db: SupportSQLiteDatabase) {
9+
db.execSQL(
10+
"""
11+
CREATE TABLE IF NOT EXISTS seen_repos (
12+
repoId INTEGER NOT NULL PRIMARY KEY,
13+
seenAt INTEGER NOT NULL
14+
)
15+
""".trimIndent(),
16+
)
17+
}
18+
}

core/data/src/commonMain/kotlin/zed/rainxch/core/data/di/SharedModule.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import zed.rainxch.core.data.local.db.AppDatabase
1515
import zed.rainxch.core.data.local.db.dao.CacheDao
1616
import zed.rainxch.core.data.local.db.dao.FavoriteRepoDao
1717
import zed.rainxch.core.data.local.db.dao.InstalledAppDao
18+
import zed.rainxch.core.data.local.db.dao.SeenRepoDao
1819
import zed.rainxch.core.data.local.db.dao.StarredRepoDao
1920
import zed.rainxch.core.data.local.db.dao.UpdateHistoryDao
2021
import zed.rainxch.core.data.logging.KermitLogger
@@ -26,6 +27,7 @@ import zed.rainxch.core.data.repository.FavouritesRepositoryImpl
2627
import zed.rainxch.core.data.repository.InstalledAppsRepositoryImpl
2728
import zed.rainxch.core.data.repository.ProxyRepositoryImpl
2829
import zed.rainxch.core.data.repository.RateLimitRepositoryImpl
30+
import zed.rainxch.core.data.repository.SeenReposRepositoryImpl
2931
import zed.rainxch.core.data.repository.StarredRepositoryImpl
3032
import zed.rainxch.core.data.repository.TweaksRepositoryImpl
3133
import zed.rainxch.core.domain.getPlatform
@@ -37,6 +39,7 @@ import zed.rainxch.core.domain.repository.FavouritesRepository
3739
import zed.rainxch.core.domain.repository.InstalledAppsRepository
3840
import zed.rainxch.core.domain.repository.ProxyRepository
3941
import zed.rainxch.core.domain.repository.RateLimitRepository
42+
import zed.rainxch.core.domain.repository.SeenReposRepository
4043
import zed.rainxch.core.domain.repository.StarredRepository
4144
import zed.rainxch.core.domain.repository.TweaksRepository
4245
import zed.rainxch.core.domain.use_cases.SyncInstalledAppsUseCase
@@ -94,6 +97,12 @@ val coreModule =
9497
)
9598
}
9699

100+
single<SeenReposRepository> {
101+
SeenReposRepositoryImpl(
102+
seenRepoDao = get(),
103+
)
104+
}
105+
97106
single<ProxyRepository> {
98107
ProxyRepositoryImpl(
99108
preferences = get(),
@@ -203,4 +212,8 @@ val databaseModule =
203212
single<CacheDao> {
204213
get<AppDatabase>().cacheDao
205214
}
215+
216+
single<SeenRepoDao> {
217+
get<AppDatabase>().seenRepoDao
218+
}
206219
}

core/data/src/commonMain/kotlin/zed/rainxch/core/data/local/db/AppDatabase.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ import androidx.room.RoomDatabase
55
import zed.rainxch.core.data.local.db.dao.CacheDao
66
import zed.rainxch.core.data.local.db.dao.FavoriteRepoDao
77
import zed.rainxch.core.data.local.db.dao.InstalledAppDao
8+
import zed.rainxch.core.data.local.db.dao.SeenRepoDao
89
import zed.rainxch.core.data.local.db.dao.StarredRepoDao
910
import zed.rainxch.core.data.local.db.dao.UpdateHistoryDao
1011
import zed.rainxch.core.data.local.db.entities.CacheEntryEntity
1112
import zed.rainxch.core.data.local.db.entities.FavoriteRepoEntity
1213
import zed.rainxch.core.data.local.db.entities.InstalledAppEntity
14+
import zed.rainxch.core.data.local.db.entities.SeenRepoEntity
1315
import zed.rainxch.core.data.local.db.entities.StarredRepositoryEntity
1416
import zed.rainxch.core.data.local.db.entities.UpdateHistoryEntity
1517

@@ -20,8 +22,9 @@ import zed.rainxch.core.data.local.db.entities.UpdateHistoryEntity
2022
UpdateHistoryEntity::class,
2123
StarredRepositoryEntity::class,
2224
CacheEntryEntity::class,
25+
SeenRepoEntity::class,
2326
],
24-
version = 5,
27+
version = 6,
2528
exportSchema = true,
2629
)
2730
abstract class AppDatabase : RoomDatabase() {
@@ -30,4 +33,5 @@ abstract class AppDatabase : RoomDatabase() {
3033
abstract val updateHistoryDao: UpdateHistoryDao
3134
abstract val starredReposDao: StarredRepoDao
3235
abstract val cacheDao: CacheDao
36+
abstract val seenRepoDao: SeenRepoDao
3337
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package zed.rainxch.core.data.local.db.dao
2+
3+
import androidx.room.Dao
4+
import androidx.room.Insert
5+
import androidx.room.OnConflictStrategy
6+
import androidx.room.Query
7+
import kotlinx.coroutines.flow.Flow
8+
import zed.rainxch.core.data.local.db.entities.SeenRepoEntity
9+
10+
@Dao
11+
interface SeenRepoDao {
12+
@Query("SELECT repoId FROM seen_repos")
13+
fun getAllSeenRepoIds(): Flow<List<Long>>
14+
15+
@Insert(onConflict = OnConflictStrategy.IGNORE)
16+
suspend fun insert(entity: SeenRepoEntity)
17+
18+
@Query("DELETE FROM seen_repos")
19+
suspend fun clearAll()
20+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package zed.rainxch.core.data.local.db.entities
2+
3+
import androidx.room.Entity
4+
import androidx.room.PrimaryKey
5+
6+
@Entity(tableName = "seen_repos")
7+
data class SeenRepoEntity(
8+
@PrimaryKey
9+
val repoId: Long,
10+
val seenAt: Long,
11+
)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package zed.rainxch.core.data.repository
2+
3+
import kotlinx.coroutines.flow.Flow
4+
import kotlinx.coroutines.flow.map
5+
import zed.rainxch.core.data.local.db.dao.SeenRepoDao
6+
import zed.rainxch.core.data.local.db.entities.SeenRepoEntity
7+
import zed.rainxch.core.domain.repository.SeenReposRepository
8+
9+
class SeenReposRepositoryImpl(
10+
private val seenRepoDao: SeenRepoDao,
11+
) : SeenReposRepository {
12+
override fun getAllSeenRepoIds(): Flow<Set<Long>> =
13+
seenRepoDao.getAllSeenRepoIds().map { it.toSet() }
14+
15+
override suspend fun markAsSeen(repoId: Long) {
16+
seenRepoDao.insert(
17+
SeenRepoEntity(
18+
repoId = repoId,
19+
seenAt = System.currentTimeMillis(),
20+
),
21+
)
22+
}
23+
24+
override suspend fun clearAll() {
25+
seenRepoDao.clearAll()
26+
}
27+
}

core/data/src/commonMain/kotlin/zed/rainxch/core/data/repository/TweaksRepositoryImpl.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class TweaksRepositoryImpl(
2626
private val UPDATE_CHECK_INTERVAL_KEY = longPreferencesKey("update_check_interval_hours")
2727
private val INCLUDE_PRE_RELEASES_KEY = booleanPreferencesKey("include_pre_releases")
2828
private val LIQUID_GLASS_ENABLED_KEY = booleanPreferencesKey("liquid_glass_enabled")
29+
private val HIDE_SEEN_ENABLED_KEY = booleanPreferencesKey("hide_seen_enabled")
2930

3031
override fun getThemeColor(): Flow<AppTheme> =
3132
preferences.data.map { prefs ->
@@ -144,6 +145,17 @@ class TweaksRepositoryImpl(
144145
}
145146
}
146147

148+
override fun getHideSeenEnabled(): Flow<Boolean> =
149+
preferences.data.map { prefs ->
150+
prefs[HIDE_SEEN_ENABLED_KEY] ?: false
151+
}
152+
153+
override suspend fun setHideSeenEnabled(enabled: Boolean) {
154+
preferences.edit { prefs ->
155+
prefs[HIDE_SEEN_ENABLED_KEY] = enabled
156+
}
157+
}
158+
147159
companion object {
148160
const val DEFAULT_UPDATE_CHECK_INTERVAL_HOURS = 6L
149161
}

0 commit comments

Comments
 (0)