From e08a4c1768cc2f3836d6d2a875a66e5d2a47fe7c Mon Sep 17 00:00:00 2001 From: rainxchzed Date: Tue, 24 Feb 2026 11:02:23 +0500 Subject: [PATCH 1/3] refactor(settings): Relocate Settings feature to Profile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit refactors the `settings` feature module into a new `profile` module. This change better reflects the content and purpose of the screen, which includes user profile information, settings, and other related actions. All existing functionality from the `settings` module—including appearance settings, about section, and logout logic—has been migrated to the new `profile` module. Corresponding package names, class names, and Gradle module dependencies have been updated throughout the codebase to reflect this change. - **refactor(module)**: Renamed the `feature/settings` module to `feature/profile`. - **refactor(navigation)**: Updated `AppNavigation` and `GithubStoreGraph` to use `ProfileScreen` instead of `SettingsScreen`. - **refactor(di)**: Renamed `SettingsViewModel` to `ProfileViewModel` and updated the dependency injection configuration. - **chore(build)**: Updated `settings.gradle.kts` and `composeApp/build.gradle.kts` to reflect the module rename. - **chore(db)**: Added a new Room schema for version 3. --- composeApp/build.gradle.kts | 6 +- .../githubstore/app/di/ViewModelsModule.kt | 4 +- .../app/navigation/AppNavigation.kt | 8 +- .../app/navigation/BottomNavigationUtils.kt | 2 +- .../app/navigation/GithubStoreGraph.kt | 2 +- .../app/navigation/NavigationUtils.kt | 2 +- .../3.json | 463 ++++++++++++++++++ feature/{settings => profile}/data/.gitignore | 0 .../data/build.gradle.kts | 2 +- .../data/src/androidMain/AndroidManifest.xml | 0 .../rainxch/settings/data/di/SharedModule.kt | 0 .../data/repository/SettingsRepositoryImpl.kt | 2 +- .../{settings => profile}/domain/.gitignore | 0 .../domain/build.gradle.kts | 0 .../src/androidMain/AndroidManifest.xml | 0 .../domain/repository/SettingsRepository.kt | 0 .../presentation/.gitignore | 0 .../presentation/build.gradle.kts | 2 +- .../src/androidMain/AndroidManifest.xml | 0 .../profile/presentation/ProfileAction.kt | 16 + .../profile/presentation/ProfileEvent.kt | 6 + .../profile/presentation/ProfileRoot.kt} | 40 +- .../profile/presentation/ProfileState.kt} | 4 +- .../profile/presentation/ProfileViewModel.kt} | 42 +- .../presentation/components/LogoutDialog.kt | 0 .../presentation/components/sections/About.kt | 6 +- .../components/sections/Account.kt | 8 +- .../components/sections/Appearance.kt | 0 .../settings/presentation/SettingsAction.kt | 16 - .../settings/presentation/SettingsEvent.kt | 6 - settings.gradle.kts | 6 +- 31 files changed, 554 insertions(+), 89 deletions(-) create mode 100644 core/data/schemas/zed.rainxch.core.data.local.db.AppDatabase/3.json rename feature/{settings => profile}/data/.gitignore (100%) rename feature/{settings => profile}/data/build.gradle.kts (89%) rename feature/{settings => profile}/data/src/androidMain/AndroidManifest.xml (100%) rename feature/{settings => profile}/data/src/commonMain/kotlin/zed/rainxch/settings/data/di/SharedModule.kt (100%) rename feature/{settings => profile}/data/src/commonMain/kotlin/zed/rainxch/settings/data/repository/SettingsRepositoryImpl.kt (93%) rename feature/{settings => profile}/domain/.gitignore (100%) rename feature/{settings => profile}/domain/build.gradle.kts (100%) rename feature/{settings => profile}/domain/src/androidMain/AndroidManifest.xml (100%) rename feature/{settings => profile}/domain/src/commonMain/kotlin/zed/rainxch/settings/domain/repository/SettingsRepository.kt (100%) rename feature/{settings => profile}/presentation/.gitignore (100%) rename feature/{settings => profile}/presentation/build.gradle.kts (90%) rename feature/{settings => profile}/presentation/src/androidMain/AndroidManifest.xml (100%) create mode 100644 feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileAction.kt create mode 100644 feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileEvent.kt rename feature/{settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/SettingsRoot.kt => profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileRoot.kt} (86%) rename feature/{settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/SettingsState.kt => profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileState.kt} (85%) rename feature/{settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/SettingsViewModel.kt => profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileViewModel.kt} (80%) rename feature/{settings/presentation/src/commonMain/kotlin/zed/rainxch/settings => profile/presentation/src/commonMain/kotlin/zed/rainxch/profile}/presentation/components/LogoutDialog.kt (100%) rename feature/{settings/presentation/src/commonMain/kotlin/zed/rainxch/settings => profile/presentation/src/commonMain/kotlin/zed/rainxch/profile}/presentation/components/sections/About.kt (96%) rename feature/{settings/presentation/src/commonMain/kotlin/zed/rainxch/settings => profile/presentation/src/commonMain/kotlin/zed/rainxch/profile}/presentation/components/sections/Account.kt (94%) rename feature/{settings/presentation/src/commonMain/kotlin/zed/rainxch/settings => profile/presentation/src/commonMain/kotlin/zed/rainxch/profile}/presentation/components/sections/Appearance.kt (100%) delete mode 100644 feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/SettingsAction.kt delete mode 100644 feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/SettingsEvent.kt diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts index 7b4809308..555e78346 100644 --- a/composeApp/build.gradle.kts +++ b/composeApp/build.gradle.kts @@ -49,9 +49,9 @@ kotlin { implementation(projects.feature.search.data) implementation(projects.feature.search.presentation) - implementation(projects.feature.settings.domain) - implementation(projects.feature.settings.data) - implementation(projects.feature.settings.presentation) + implementation(projects.feature.profile.domain) + implementation(projects.feature.profile.data) + implementation(projects.feature.profile.presentation) implementation(projects.feature.starred.domain) implementation(projects.feature.starred.data) diff --git a/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/di/ViewModelsModule.kt b/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/di/ViewModelsModule.kt index eb89d332f..d9c3493de 100644 --- a/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/di/ViewModelsModule.kt +++ b/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/di/ViewModelsModule.kt @@ -8,8 +8,8 @@ import zed.rainxch.details.presentation.DetailsViewModel import zed.rainxch.devprofile.presentation.DeveloperProfileViewModel import zed.rainxch.favourites.presentation.FavouritesViewModel import zed.rainxch.home.presentation.HomeViewModel +import zed.rainxch.profile.presentation.ProfileViewModel import zed.rainxch.search.presentation.SearchViewModel -import zed.rainxch.settings.presentation.SettingsViewModel import zed.rainxch.starred.presentation.StarredReposViewModel val viewModelsModule = module { @@ -20,6 +20,6 @@ val viewModelsModule = module { viewModelOf(::FavouritesViewModel) viewModelOf(::HomeViewModel) viewModelOf(::SearchViewModel) - viewModelOf(::SettingsViewModel) + viewModelOf(::ProfileViewModel) viewModelOf(::StarredReposViewModel) } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/AppNavigation.kt b/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/AppNavigation.kt index 07874eeaf..70f3d3b0a 100644 --- a/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/AppNavigation.kt +++ b/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/AppNavigation.kt @@ -27,7 +27,7 @@ import zed.rainxch.devprofile.presentation.DeveloperProfileRoot import zed.rainxch.favourites.presentation.FavouritesRoot import zed.rainxch.home.presentation.HomeRoot import zed.rainxch.search.presentation.SearchRoot -import zed.rainxch.settings.presentation.SettingsRoot +import zed.rainxch.profile.presentation.ProfileRoot import zed.rainxch.starred.presentation.StarredReposRoot @Composable @@ -53,7 +53,7 @@ fun AppNavigation( navController.navigate(GithubStoreGraph.SearchScreen) }, onNavigateToSettings = { - navController.navigate(GithubStoreGraph.SettingsScreen) + navController.navigate(GithubStoreGraph.ProfileScreen) }, onNavigateToApps = { navController.navigate(GithubStoreGraph.AppsScreen) @@ -199,8 +199,8 @@ fun AppNavigation( ) } - composable { - SettingsRoot( + composable { + ProfileRoot( onNavigateBack = { navController.navigateUp() } diff --git a/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/BottomNavigationUtils.kt b/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/BottomNavigationUtils.kt index 8563be0e7..d91abb750 100644 --- a/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/BottomNavigationUtils.kt +++ b/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/BottomNavigationUtils.kt @@ -46,7 +46,7 @@ object BottomNavigationUtils { titleRes = Res.string.bottom_nav_profile_title, iconOutlined = Icons.Outlined.Person2, iconFilled = Icons.Filled.Person2, - screen = GithubStoreGraph.SettingsScreen + screen = GithubStoreGraph.ProfileScreen ) ) diff --git a/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/GithubStoreGraph.kt b/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/GithubStoreGraph.kt index 6ec8640fd..33d30e99b 100644 --- a/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/GithubStoreGraph.kt +++ b/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/GithubStoreGraph.kt @@ -26,7 +26,7 @@ sealed interface GithubStoreGraph { ) : GithubStoreGraph @Serializable - data object SettingsScreen : GithubStoreGraph + data object ProfileScreen : GithubStoreGraph @Serializable data object FavouritesScreen : GithubStoreGraph diff --git a/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/NavigationUtils.kt b/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/NavigationUtils.kt index b12605dd4..4cb2ca874 100644 --- a/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/NavigationUtils.kt +++ b/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/navigation/NavigationUtils.kt @@ -13,7 +13,7 @@ fun NavBackStackEntry?.getCurrentScreen(): GithubStoreGraph? { route.contains("AuthenticationScreen") -> GithubStoreGraph.AuthenticationScreen route.contains("DetailsScreen") -> toRoute() route.contains("DeveloperProfileScreen") -> toRoute() - route.contains("SettingsScreen") -> GithubStoreGraph.SettingsScreen + route.contains("ProfileScreen") -> GithubStoreGraph.ProfileScreen route.contains("FavouritesScreen") -> GithubStoreGraph.FavouritesScreen route.contains("StarredReposScreen") -> GithubStoreGraph.StarredReposScreen route.contains("AppsScreen") -> GithubStoreGraph.AppsScreen diff --git a/core/data/schemas/zed.rainxch.core.data.local.db.AppDatabase/3.json b/core/data/schemas/zed.rainxch.core.data.local.db.AppDatabase/3.json new file mode 100644 index 000000000..92f628cd9 --- /dev/null +++ b/core/data/schemas/zed.rainxch.core.data.local.db.AppDatabase/3.json @@ -0,0 +1,463 @@ +{ + "formatVersion": 1, + "database": { + "version": 3, + "identityHash": "81a8b0bb930a5c839e0da7a5335e4991", + "entities": [ + { + "tableName": "installed_apps", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`packageName` TEXT NOT NULL, `repoId` INTEGER NOT NULL, `repoName` TEXT NOT NULL, `repoOwner` TEXT NOT NULL, `repoOwnerAvatarUrl` TEXT NOT NULL, `repoDescription` TEXT, `primaryLanguage` TEXT, `repoUrl` TEXT NOT NULL, `installedVersion` TEXT NOT NULL, `installedAssetName` TEXT, `installedAssetUrl` TEXT, `latestVersion` TEXT, `latestAssetName` TEXT, `latestAssetUrl` TEXT, `latestAssetSize` INTEGER, `appName` TEXT NOT NULL, `installSource` TEXT NOT NULL, `installedAt` INTEGER NOT NULL, `lastCheckedAt` INTEGER NOT NULL, `lastUpdatedAt` INTEGER NOT NULL, `isUpdateAvailable` INTEGER NOT NULL, `updateCheckEnabled` INTEGER NOT NULL, `releaseNotes` TEXT, `systemArchitecture` TEXT NOT NULL, `fileExtension` TEXT NOT NULL, `isPendingInstall` INTEGER NOT NULL, `installedVersionName` TEXT, `installedVersionCode` INTEGER NOT NULL, `latestVersionName` TEXT, `latestVersionCode` INTEGER, PRIMARY KEY(`packageName`))", + "fields": [ + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "repoId", + "columnName": "repoId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "repoName", + "columnName": "repoName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "repoOwner", + "columnName": "repoOwner", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "repoOwnerAvatarUrl", + "columnName": "repoOwnerAvatarUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "repoDescription", + "columnName": "repoDescription", + "affinity": "TEXT" + }, + { + "fieldPath": "primaryLanguage", + "columnName": "primaryLanguage", + "affinity": "TEXT" + }, + { + "fieldPath": "repoUrl", + "columnName": "repoUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "installedVersion", + "columnName": "installedVersion", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "installedAssetName", + "columnName": "installedAssetName", + "affinity": "TEXT" + }, + { + "fieldPath": "installedAssetUrl", + "columnName": "installedAssetUrl", + "affinity": "TEXT" + }, + { + "fieldPath": "latestVersion", + "columnName": "latestVersion", + "affinity": "TEXT" + }, + { + "fieldPath": "latestAssetName", + "columnName": "latestAssetName", + "affinity": "TEXT" + }, + { + "fieldPath": "latestAssetUrl", + "columnName": "latestAssetUrl", + "affinity": "TEXT" + }, + { + "fieldPath": "latestAssetSize", + "columnName": "latestAssetSize", + "affinity": "INTEGER" + }, + { + "fieldPath": "appName", + "columnName": "appName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "installSource", + "columnName": "installSource", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "installedAt", + "columnName": "installedAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastCheckedAt", + "columnName": "lastCheckedAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastUpdatedAt", + "columnName": "lastUpdatedAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isUpdateAvailable", + "columnName": "isUpdateAvailable", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updateCheckEnabled", + "columnName": "updateCheckEnabled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "releaseNotes", + "columnName": "releaseNotes", + "affinity": "TEXT" + }, + { + "fieldPath": "systemArchitecture", + "columnName": "systemArchitecture", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "fileExtension", + "columnName": "fileExtension", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isPendingInstall", + "columnName": "isPendingInstall", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "installedVersionName", + "columnName": "installedVersionName", + "affinity": "TEXT" + }, + { + "fieldPath": "installedVersionCode", + "columnName": "installedVersionCode", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "latestVersionName", + "columnName": "latestVersionName", + "affinity": "TEXT" + }, + { + "fieldPath": "latestVersionCode", + "columnName": "latestVersionCode", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "packageName" + ] + } + }, + { + "tableName": "favorite_repos", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`repoId` INTEGER NOT NULL, `repoName` TEXT NOT NULL, `repoOwner` TEXT NOT NULL, `repoOwnerAvatarUrl` TEXT NOT NULL, `repoDescription` TEXT, `primaryLanguage` TEXT, `repoUrl` TEXT NOT NULL, `isInstalled` INTEGER NOT NULL, `installedPackageName` TEXT, `latestVersion` TEXT, `latestReleaseUrl` TEXT, `addedAt` INTEGER NOT NULL, `lastSyncedAt` INTEGER NOT NULL, PRIMARY KEY(`repoId`))", + "fields": [ + { + "fieldPath": "repoId", + "columnName": "repoId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "repoName", + "columnName": "repoName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "repoOwner", + "columnName": "repoOwner", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "repoOwnerAvatarUrl", + "columnName": "repoOwnerAvatarUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "repoDescription", + "columnName": "repoDescription", + "affinity": "TEXT" + }, + { + "fieldPath": "primaryLanguage", + "columnName": "primaryLanguage", + "affinity": "TEXT" + }, + { + "fieldPath": "repoUrl", + "columnName": "repoUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "isInstalled", + "columnName": "isInstalled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "installedPackageName", + "columnName": "installedPackageName", + "affinity": "TEXT" + }, + { + "fieldPath": "latestVersion", + "columnName": "latestVersion", + "affinity": "TEXT" + }, + { + "fieldPath": "latestReleaseUrl", + "columnName": "latestReleaseUrl", + "affinity": "TEXT" + }, + { + "fieldPath": "addedAt", + "columnName": "addedAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastSyncedAt", + "columnName": "lastSyncedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "repoId" + ] + } + }, + { + "tableName": "update_history", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `packageName` TEXT NOT NULL, `appName` TEXT NOT NULL, `repoOwner` TEXT NOT NULL, `repoName` TEXT NOT NULL, `fromVersion` TEXT NOT NULL, `toVersion` TEXT NOT NULL, `updatedAt` INTEGER NOT NULL, `updateSource` TEXT NOT NULL, `success` INTEGER NOT NULL, `errorMessage` TEXT)", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "packageName", + "columnName": "packageName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "appName", + "columnName": "appName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "repoOwner", + "columnName": "repoOwner", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "repoName", + "columnName": "repoName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "fromVersion", + "columnName": "fromVersion", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "toVersion", + "columnName": "toVersion", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "updatedAt", + "columnName": "updatedAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "updateSource", + "columnName": "updateSource", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "success", + "columnName": "success", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "errorMessage", + "columnName": "errorMessage", + "affinity": "TEXT" + } + ], + "primaryKey": { + "autoGenerate": true, + "columnNames": [ + "id" + ] + } + }, + { + "tableName": "starred_repos", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`repoId` INTEGER NOT NULL, `repoName` TEXT NOT NULL, `repoOwner` TEXT NOT NULL, `repoOwnerAvatarUrl` TEXT NOT NULL, `repoDescription` TEXT, `primaryLanguage` TEXT, `repoUrl` TEXT NOT NULL, `stargazersCount` INTEGER NOT NULL, `forksCount` INTEGER NOT NULL, `openIssuesCount` INTEGER NOT NULL, `isInstalled` INTEGER NOT NULL, `installedPackageName` TEXT, `latestVersion` TEXT, `latestReleaseUrl` TEXT, `starredAt` INTEGER, `addedAt` INTEGER NOT NULL, `lastSyncedAt` INTEGER NOT NULL, PRIMARY KEY(`repoId`))", + "fields": [ + { + "fieldPath": "repoId", + "columnName": "repoId", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "repoName", + "columnName": "repoName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "repoOwner", + "columnName": "repoOwner", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "repoOwnerAvatarUrl", + "columnName": "repoOwnerAvatarUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "repoDescription", + "columnName": "repoDescription", + "affinity": "TEXT" + }, + { + "fieldPath": "primaryLanguage", + "columnName": "primaryLanguage", + "affinity": "TEXT" + }, + { + "fieldPath": "repoUrl", + "columnName": "repoUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "stargazersCount", + "columnName": "stargazersCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "forksCount", + "columnName": "forksCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "openIssuesCount", + "columnName": "openIssuesCount", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isInstalled", + "columnName": "isInstalled", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "installedPackageName", + "columnName": "installedPackageName", + "affinity": "TEXT" + }, + { + "fieldPath": "latestVersion", + "columnName": "latestVersion", + "affinity": "TEXT" + }, + { + "fieldPath": "latestReleaseUrl", + "columnName": "latestReleaseUrl", + "affinity": "TEXT" + }, + { + "fieldPath": "starredAt", + "columnName": "starredAt", + "affinity": "INTEGER" + }, + { + "fieldPath": "addedAt", + "columnName": "addedAt", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "lastSyncedAt", + "columnName": "lastSyncedAt", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "repoId" + ] + } + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '81a8b0bb930a5c839e0da7a5335e4991')" + ] + } +} \ No newline at end of file diff --git a/feature/settings/data/.gitignore b/feature/profile/data/.gitignore similarity index 100% rename from feature/settings/data/.gitignore rename to feature/profile/data/.gitignore diff --git a/feature/settings/data/build.gradle.kts b/feature/profile/data/build.gradle.kts similarity index 89% rename from feature/settings/data/build.gradle.kts rename to feature/profile/data/build.gradle.kts index a0851b0dc..83c828a03 100644 --- a/feature/settings/data/build.gradle.kts +++ b/feature/profile/data/build.gradle.kts @@ -11,7 +11,7 @@ kotlin { implementation(projects.core.domain) implementation(projects.core.data) - implementation(projects.feature.settings.domain) + implementation(projects.feature.profile.domain) implementation(libs.bundles.koin.common) } diff --git a/feature/settings/data/src/androidMain/AndroidManifest.xml b/feature/profile/data/src/androidMain/AndroidManifest.xml similarity index 100% rename from feature/settings/data/src/androidMain/AndroidManifest.xml rename to feature/profile/data/src/androidMain/AndroidManifest.xml diff --git a/feature/settings/data/src/commonMain/kotlin/zed/rainxch/settings/data/di/SharedModule.kt b/feature/profile/data/src/commonMain/kotlin/zed/rainxch/settings/data/di/SharedModule.kt similarity index 100% rename from feature/settings/data/src/commonMain/kotlin/zed/rainxch/settings/data/di/SharedModule.kt rename to feature/profile/data/src/commonMain/kotlin/zed/rainxch/settings/data/di/SharedModule.kt diff --git a/feature/settings/data/src/commonMain/kotlin/zed/rainxch/settings/data/repository/SettingsRepositoryImpl.kt b/feature/profile/data/src/commonMain/kotlin/zed/rainxch/settings/data/repository/SettingsRepositoryImpl.kt similarity index 93% rename from feature/settings/data/src/commonMain/kotlin/zed/rainxch/settings/data/repository/SettingsRepositoryImpl.kt rename to feature/profile/data/src/commonMain/kotlin/zed/rainxch/settings/data/repository/SettingsRepositoryImpl.kt index 064b58309..06dee3951 100644 --- a/feature/settings/data/src/commonMain/kotlin/zed/rainxch/settings/data/repository/SettingsRepositoryImpl.kt +++ b/feature/profile/data/src/commonMain/kotlin/zed/rainxch/settings/data/repository/SettingsRepositoryImpl.kt @@ -5,7 +5,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOn import zed.rainxch.core.data.data_source.TokenStore import zed.rainxch.core.domain.repository.AuthenticationState -import zed.rainxch.feature.settings.data.BuildKonfig +import zed.rainxch.feature.profile.data.BuildKonfig import zed.rainxch.settings.domain.repository.SettingsRepository class SettingsRepositoryImpl( diff --git a/feature/settings/domain/.gitignore b/feature/profile/domain/.gitignore similarity index 100% rename from feature/settings/domain/.gitignore rename to feature/profile/domain/.gitignore diff --git a/feature/settings/domain/build.gradle.kts b/feature/profile/domain/build.gradle.kts similarity index 100% rename from feature/settings/domain/build.gradle.kts rename to feature/profile/domain/build.gradle.kts diff --git a/feature/settings/domain/src/androidMain/AndroidManifest.xml b/feature/profile/domain/src/androidMain/AndroidManifest.xml similarity index 100% rename from feature/settings/domain/src/androidMain/AndroidManifest.xml rename to feature/profile/domain/src/androidMain/AndroidManifest.xml diff --git a/feature/settings/domain/src/commonMain/kotlin/zed/rainxch/settings/domain/repository/SettingsRepository.kt b/feature/profile/domain/src/commonMain/kotlin/zed/rainxch/settings/domain/repository/SettingsRepository.kt similarity index 100% rename from feature/settings/domain/src/commonMain/kotlin/zed/rainxch/settings/domain/repository/SettingsRepository.kt rename to feature/profile/domain/src/commonMain/kotlin/zed/rainxch/settings/domain/repository/SettingsRepository.kt diff --git a/feature/settings/presentation/.gitignore b/feature/profile/presentation/.gitignore similarity index 100% rename from feature/settings/presentation/.gitignore rename to feature/profile/presentation/.gitignore diff --git a/feature/settings/presentation/build.gradle.kts b/feature/profile/presentation/build.gradle.kts similarity index 90% rename from feature/settings/presentation/build.gradle.kts rename to feature/profile/presentation/build.gradle.kts index fac42f998..3c7687e0c 100644 --- a/feature/settings/presentation/build.gradle.kts +++ b/feature/profile/presentation/build.gradle.kts @@ -10,7 +10,7 @@ kotlin { implementation(projects.core.domain) implementation(projects.core.presentation) - implementation(projects.feature.settings.domain) + implementation(projects.feature.profile.domain) implementation(compose.components.uiToolingPreview) implementation(compose.components.resources) diff --git a/feature/settings/presentation/src/androidMain/AndroidManifest.xml b/feature/profile/presentation/src/androidMain/AndroidManifest.xml similarity index 100% rename from feature/settings/presentation/src/androidMain/AndroidManifest.xml rename to feature/profile/presentation/src/androidMain/AndroidManifest.xml diff --git a/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileAction.kt b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileAction.kt new file mode 100644 index 000000000..746f2d710 --- /dev/null +++ b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileAction.kt @@ -0,0 +1,16 @@ +package zed.rainxch.profile.presentation + +import zed.rainxch.core.domain.model.AppTheme +import zed.rainxch.core.domain.model.FontTheme + +sealed interface ProfileAction { + data object OnNavigateBackClick : ProfileAction + data class OnThemeColorSelected(val themeColor: AppTheme) : ProfileAction + data class OnAmoledThemeToggled(val enabled: Boolean) : ProfileAction + data class OnDarkThemeChange(val isDarkTheme: Boolean?) : ProfileAction + data object OnLogoutClick : ProfileAction + data object OnLogoutConfirmClick : ProfileAction + data object OnLogoutDismiss : ProfileAction + data object OnHelpClick : ProfileAction + data class OnFontThemeSelected(val fontTheme: FontTheme) : ProfileAction +} \ No newline at end of file diff --git a/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileEvent.kt b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileEvent.kt new file mode 100644 index 000000000..e77a358c4 --- /dev/null +++ b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileEvent.kt @@ -0,0 +1,6 @@ +package zed.rainxch.profile.presentation + +sealed interface ProfileEvent { + data object OnLogoutSuccessful : ProfileEvent + data class OnLogoutError(val message: String) : ProfileEvent +} \ No newline at end of file diff --git a/feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/SettingsRoot.kt b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileRoot.kt similarity index 86% rename from feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/SettingsRoot.kt rename to feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileRoot.kt index 14faceff5..a77c3b28d 100644 --- a/feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/SettingsRoot.kt +++ b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileRoot.kt @@ -1,4 +1,4 @@ -package zed.rainxch.settings.presentation +package zed.rainxch.profile.presentation import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -44,9 +44,9 @@ import zed.rainxch.settings.presentation.components.sections.appearance import zed.rainxch.settings.presentation.components.sections.logout @Composable -fun SettingsRoot( +fun ProfileRoot( onNavigateBack: () -> Unit, - viewModel: SettingsViewModel = koinViewModel() + viewModel: ProfileViewModel = koinViewModel() ) { val state by viewModel.state.collectAsStateWithLifecycle() val snackbarState = remember { SnackbarHostState() } @@ -54,7 +54,7 @@ fun SettingsRoot( ObserveAsEvents(viewModel.events) { event -> when (event) { - SettingsEvent.OnLogoutSuccessful -> { + ProfileEvent.OnLogoutSuccessful -> { coroutineScope.launch { snackbarState.showSnackbar(getString(Res.string.logout_success)) @@ -62,7 +62,7 @@ fun SettingsRoot( } } - is SettingsEvent.OnLogoutError -> { + is ProfileEvent.OnLogoutError -> { coroutineScope.launch { snackbarState.showSnackbar(event.message) } @@ -70,11 +70,11 @@ fun SettingsRoot( } } - SettingsScreen( + ProfileScreen( state = state, onAction = { action -> when (action) { - SettingsAction.OnNavigateBackClick -> { + ProfileAction.OnNavigateBackClick -> { onNavigateBack() } @@ -89,10 +89,10 @@ fun SettingsRoot( if (state.isLogoutDialogVisible) { LogoutDialog( onDismissRequest = { - viewModel.onAction(SettingsAction.OnLogoutDismiss) + viewModel.onAction(ProfileAction.OnLogoutDismiss) }, onLogout = { - viewModel.onAction(SettingsAction.OnLogoutConfirmClick) + viewModel.onAction(ProfileAction.OnLogoutConfirmClick) } ) } @@ -100,9 +100,9 @@ fun SettingsRoot( @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable -fun SettingsScreen( - state: SettingsState, - onAction: (SettingsAction) -> Unit, +fun ProfileScreen( + state: ProfileState, + onAction: (ProfileAction) -> Unit, snackbarState: SnackbarHostState ) { val liquidState = LocalBottomNavigationLiquid.current @@ -125,20 +125,20 @@ fun SettingsScreen( appearance( selectedThemeColor = state.selectedThemeColor, onThemeColorSelected = { theme -> - onAction(SettingsAction.OnThemeColorSelected(theme)) + onAction(ProfileAction.OnThemeColorSelected(theme)) }, isAmoledThemeEnabled = state.isAmoledThemeEnabled, onAmoledThemeToggled = { enabled -> - onAction(SettingsAction.OnAmoledThemeToggled(enabled)) + onAction(ProfileAction.OnAmoledThemeToggled(enabled)) }, isDarkTheme = state.isDarkTheme, onDarkThemeChange = { isDarkTheme -> - onAction(SettingsAction.OnDarkThemeChange(isDarkTheme)) + onAction(ProfileAction.OnDarkThemeChange(isDarkTheme)) }, isUsingSystemFont = state.selectedFontTheme == FontTheme.SYSTEM, onUseSystemFontToggled = { enabled -> onAction( - SettingsAction.OnFontThemeSelected( + ProfileAction.OnFontThemeSelected( if (enabled) { FontTheme.SYSTEM } else FontTheme.CUSTOM @@ -171,13 +171,13 @@ fun SettingsScreen( @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable -private fun TopAppBar(onAction: (SettingsAction) -> Unit) { +private fun TopAppBar(onAction: (ProfileAction) -> Unit) { TopAppBar( navigationIcon = { IconButton( shapes = IconButtonDefaults.shapes(), onClick = { - onAction(SettingsAction.OnNavigateBackClick) + onAction(ProfileAction.OnNavigateBackClick) } ) { Icon( @@ -202,8 +202,8 @@ private fun TopAppBar(onAction: (SettingsAction) -> Unit) { @Composable private fun Preview() { GithubStoreTheme { - SettingsScreen( - state = SettingsState(), + ProfileScreen( + state = ProfileState(), onAction = {}, snackbarState = SnackbarHostState() ) diff --git a/feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/SettingsState.kt b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileState.kt similarity index 85% rename from feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/SettingsState.kt rename to feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileState.kt index d19edc944..1bfa7cd49 100644 --- a/feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/SettingsState.kt +++ b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileState.kt @@ -1,9 +1,9 @@ -package zed.rainxch.settings.presentation +package zed.rainxch.profile.presentation import zed.rainxch.core.domain.model.AppTheme import zed.rainxch.core.domain.model.FontTheme -data class SettingsState( +data class ProfileState( val selectedThemeColor: AppTheme = AppTheme.OCEAN, val selectedFontTheme: FontTheme = FontTheme.CUSTOM, val isLogoutDialogVisible: Boolean = false, diff --git a/feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/SettingsViewModel.kt b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileViewModel.kt similarity index 80% rename from feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/SettingsViewModel.kt rename to feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileViewModel.kt index 9b516b5f4..0270df6b6 100644 --- a/feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/SettingsViewModel.kt +++ b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileViewModel.kt @@ -1,4 +1,4 @@ -package zed.rainxch.settings.presentation +package zed.rainxch.profile.presentation import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -14,7 +14,7 @@ import zed.rainxch.core.domain.repository.ThemesRepository import zed.rainxch.core.domain.utils.BrowserHelper import zed.rainxch.settings.domain.repository.SettingsRepository -class SettingsViewModel( +class ProfileViewModel( private val browserHelper: BrowserHelper, private val themesRepository: ThemesRepository, private val settingsRepository: SettingsRepository @@ -22,7 +22,7 @@ class SettingsViewModel( private var hasLoadedInitialData = false - private val _state = MutableStateFlow(SettingsState()) + private val _state = MutableStateFlow(ProfileState()) val state = _state .onStart { if (!hasLoadedInitialData) { @@ -36,17 +36,19 @@ class SettingsViewModel( .stateIn( scope = viewModelScope, started = SharingStarted.WhileSubscribed(5_000L), - initialValue = SettingsState() + initialValue = ProfileState() ) - private val _events = Channel() + private val _events = Channel() val events = _events.receiveAsFlow() private fun loadVersionName() { viewModelScope.launch { - _state.update { it.copy( - versionName = settingsRepository.getVersionName() - ) } + _state.update { + it.copy( + versionName = settingsRepository.getVersionName() + ) + } } } @@ -93,27 +95,27 @@ class SettingsViewModel( } } - fun onAction(action: SettingsAction) { + fun onAction(action: ProfileAction) { when (action) { - SettingsAction.OnHelpClick -> { + ProfileAction.OnHelpClick -> { browserHelper.openUrl( url = "https://github.com/rainxchzed/Github-Store/issues" ) } - is SettingsAction.OnThemeColorSelected -> { + is ProfileAction.OnThemeColorSelected -> { viewModelScope.launch { themesRepository.setThemeColor(action.themeColor) } } - is SettingsAction.OnAmoledThemeToggled -> { + is ProfileAction.OnAmoledThemeToggled -> { viewModelScope.launch { themesRepository.setAmoledTheme(action.enabled) } } - SettingsAction.OnLogoutClick -> { + ProfileAction.OnLogoutClick -> { _state.update { it.copy( isLogoutDialogVisible = true @@ -121,23 +123,23 @@ class SettingsViewModel( } } - SettingsAction.OnLogoutConfirmClick -> { + ProfileAction.OnLogoutConfirmClick -> { viewModelScope.launch { runCatching { settingsRepository.logout() }.onSuccess { _state.update { it.copy(isLogoutDialogVisible = false) } - _events.send(SettingsEvent.OnLogoutSuccessful) + _events.send(ProfileEvent.OnLogoutSuccessful) }.onFailure { error -> _state.update { it.copy(isLogoutDialogVisible = false) } error.message?.let { - _events.send(SettingsEvent.OnLogoutError(it)) + _events.send(ProfileEvent.OnLogoutError(it)) } } } } - SettingsAction.OnLogoutDismiss -> { + ProfileAction.OnLogoutDismiss -> { _state.update { it.copy( isLogoutDialogVisible = false @@ -145,17 +147,17 @@ class SettingsViewModel( } } - SettingsAction.OnNavigateBackClick -> { + ProfileAction.OnNavigateBackClick -> { /* Handed in composable */ } - is SettingsAction.OnFontThemeSelected -> { + is ProfileAction.OnFontThemeSelected -> { viewModelScope.launch { themesRepository.setFontTheme(action.fontTheme) } } - is SettingsAction.OnDarkThemeChange -> { + is ProfileAction.OnDarkThemeChange -> { viewModelScope.launch { themesRepository.setDarkTheme(action.isDarkTheme) } diff --git a/feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/components/LogoutDialog.kt b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/LogoutDialog.kt similarity index 100% rename from feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/components/LogoutDialog.kt rename to feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/LogoutDialog.kt diff --git a/feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/components/sections/About.kt b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/About.kt similarity index 96% rename from feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/components/sections/About.kt rename to feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/About.kt index 358a8d63d..622472f2e 100644 --- a/feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/components/sections/About.kt +++ b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/About.kt @@ -30,12 +30,12 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import zed.rainxch.githubstore.core.presentation.res.* import org.jetbrains.compose.resources.stringResource -import zed.rainxch.settings.presentation.SettingsAction +import zed.rainxch.profile.presentation.ProfileAction @OptIn(ExperimentalMaterial3ExpressiveApi::class) fun LazyListScope.about( versionName: String, - onAction: (SettingsAction) -> Unit, + onAction: (ProfileAction) -> Unit, ) { item { Text( @@ -76,7 +76,7 @@ fun LazyListScope.about( IconButton( shape = IconButtonDefaults.shapes().shape, onClick = { - onAction(SettingsAction.OnHelpClick) + onAction(ProfileAction.OnHelpClick) }, colors = IconButtonDefaults.iconButtonColors( contentColor = MaterialTheme.colorScheme.onSurface diff --git a/feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/components/sections/Account.kt b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/Account.kt similarity index 94% rename from feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/components/sections/Account.kt rename to feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/Account.kt index baa411bb0..ff89482af 100644 --- a/feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/components/sections/Account.kt +++ b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/Account.kt @@ -28,11 +28,11 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import zed.rainxch.githubstore.core.presentation.res.* import org.jetbrains.compose.resources.stringResource -import zed.rainxch.settings.presentation.SettingsAction +import zed.rainxch.profile.presentation.ProfileAction @OptIn(ExperimentalMaterial3ExpressiveApi::class) fun LazyListScope.logout( - onAction: (SettingsAction) -> Unit, + onAction: (ProfileAction) -> Unit, ) { item { Spacer(Modifier.height(8.dp)) @@ -44,7 +44,7 @@ fun LazyListScope.logout( ), shape = RoundedCornerShape(16.dp), onClick = { - onAction(SettingsAction.OnLogoutClick) + onAction(ProfileAction.OnLogoutClick) } ) { AccountItem( @@ -54,7 +54,7 @@ fun LazyListScope.logout( IconButton( shapes = IconButtonDefaults.shapes(), onClick = { - onAction(SettingsAction.OnLogoutClick) + onAction(ProfileAction.OnLogoutClick) }, colors = IconButtonDefaults.iconButtonColors( contentColor = MaterialTheme.colorScheme.onSurface diff --git a/feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/components/sections/Appearance.kt b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/Appearance.kt similarity index 100% rename from feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/components/sections/Appearance.kt rename to feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/Appearance.kt diff --git a/feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/SettingsAction.kt b/feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/SettingsAction.kt deleted file mode 100644 index 1af549d86..000000000 --- a/feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/SettingsAction.kt +++ /dev/null @@ -1,16 +0,0 @@ -package zed.rainxch.settings.presentation - -import zed.rainxch.core.domain.model.AppTheme -import zed.rainxch.core.domain.model.FontTheme - -sealed interface SettingsAction { - data object OnNavigateBackClick : SettingsAction - data class OnThemeColorSelected(val themeColor: AppTheme) : SettingsAction - data class OnAmoledThemeToggled(val enabled: Boolean) : SettingsAction - data class OnDarkThemeChange(val isDarkTheme: Boolean?) : SettingsAction - data object OnLogoutClick : SettingsAction - data object OnLogoutConfirmClick : SettingsAction - data object OnLogoutDismiss : SettingsAction - data object OnHelpClick : SettingsAction - data class OnFontThemeSelected(val fontTheme: FontTheme) : SettingsAction -} \ No newline at end of file diff --git a/feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/SettingsEvent.kt b/feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/SettingsEvent.kt deleted file mode 100644 index 4b2137199..000000000 --- a/feature/settings/presentation/src/commonMain/kotlin/zed/rainxch/settings/presentation/SettingsEvent.kt +++ /dev/null @@ -1,6 +0,0 @@ -package zed.rainxch.settings.presentation - -sealed interface SettingsEvent { - data object OnLogoutSuccessful : SettingsEvent - data class OnLogoutError(val message: String) : SettingsEvent -} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index b994c6927..8d6a92d4f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -62,6 +62,6 @@ include(":feature:starred:presentation") include(":feature:search:domain") include(":feature:search:data") include(":feature:search:presentation") -include(":feature:settings:domain") -include(":feature:settings:data") -include(":feature:settings:presentation") +include(":feature:profile:domain") +include(":feature:profile:data") +include(":feature:profile:presentation") From 709e9148a637b12bff42367e664df52ca81aa841 Mon Sep 17 00:00:00 2001 From: rainxchzed Date: Tue, 24 Feb 2026 16:58:55 +0500 Subject: [PATCH 2/3] refactor(profile): Rename Settings to Profile and implement user profile UI This commit refactors the "Settings" feature into "Profile", including renaming repositories, data models, and UI components. It also introduces a new user profile section in the UI and updates translations across multiple languages. - **refactor**: Renamed `SettingsRepository` to `ProfileRepository` and updated its implementation and DI modules. - **feat(profile)**: Added `UserProfile` domain model and `accountSection` to display user information (avatar, etc.) in `ProfileRoot`. - **feat(profile)**: Reorganized `ProfileRoot` into modular sections: `profile`, `settings`, `about`, and `logout`. - **feat(i18n)**: Renamed `settings_title` to `profile_title` and updated translations for `ru`, `tr`, `bn`, `zh-rCN`, `es`, `fr`, `it`, `hi`, `ja`, `kr`, and `pl`. - **refactor(presentation)**: Created `GitHubStoreImage` component to unify image loading logic using Coil and shared it across `RepositoryCard` and profile sections. - **ui**: Added `SectionHeader` and `SectionTitle` components for consistent layout in the profile screen. --- .../rainxch/githubstore/app/di/initKoin.kt | 2 +- .../composeResources/values-bn/strings-bn.xml | 2 +- .../composeResources/values-es/strings-es.xml | 2 +- .../composeResources/values-fr/strings-fr.xml | 2 +- .../composeResources/values-hi/strings-hi.xml | 2 +- .../composeResources/values-it/strings-it.xml | 2 +- .../composeResources/values-ja/strings-ja.xml | 2 +- .../composeResources/values-kr/strings-kr.xml | 2 +- .../composeResources/values-pl/strings-pl.xml | 2 +- .../composeResources/values-ru/strings-ru.xml | 2 +- .../composeResources/values-tr/strings-tr.xml | 2 +- .../values-zh-rCN/strings-zh-rCN.xml | 2 +- .../composeResources/values/strings.xml | 4 +- .../components/GitHubStoreImage.kt | 56 ++++++++++++++++ .../presentation/components/RepositoryCard.kt | 20 ++---- .../rainxch/profile/data/di/SharedModule.kt | 14 ++++ .../data/repository/ProfileRepositoryImpl.kt} | 8 +-- .../rainxch/settings/data/di/SharedModule.kt | 14 ---- .../profile/domain/model/UserProfile.kt | 12 ++++ .../domain/repository/ProfileRepository.kt | 11 ++++ .../domain/repository/SettingsRepository.kt | 9 --- .../profile/presentation/ProfileRoot.kt | 51 +++++++------- .../profile/presentation/ProfileState.kt | 2 + .../profile/presentation/ProfileViewModel.kt | 10 +-- .../presentation/components/LogoutDialog.kt | 2 +- .../presentation/components/SectionText.kt | 33 ++++++++++ .../presentation/components/sections/About.kt | 2 +- .../components/sections/Account.kt | 2 +- .../components/sections/AccountSection.kt | 66 +++++++++++++++++++ .../components/sections/Appearance.kt | 66 ++++++++++--------- .../components/sections/ProfileSection.kt | 15 +++++ .../components/sections/SettingsSection.kt | 15 +++++ 32 files changed, 312 insertions(+), 124 deletions(-) create mode 100644 core/presentation/src/commonMain/kotlin/zed/rainxch/core/presentation/components/GitHubStoreImage.kt create mode 100644 feature/profile/data/src/commonMain/kotlin/zed/rainxch/profile/data/di/SharedModule.kt rename feature/profile/data/src/commonMain/kotlin/zed/rainxch/{settings/data/repository/SettingsRepositoryImpl.kt => profile/data/repository/ProfileRepositoryImpl.kt} (80%) delete mode 100644 feature/profile/data/src/commonMain/kotlin/zed/rainxch/settings/data/di/SharedModule.kt create mode 100644 feature/profile/domain/src/commonMain/kotlin/zed/rainxch/profile/domain/model/UserProfile.kt create mode 100644 feature/profile/domain/src/commonMain/kotlin/zed/rainxch/profile/domain/repository/ProfileRepository.kt delete mode 100644 feature/profile/domain/src/commonMain/kotlin/zed/rainxch/settings/domain/repository/SettingsRepository.kt create mode 100644 feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/SectionText.kt create mode 100644 feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/AccountSection.kt create mode 100644 feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/ProfileSection.kt create mode 100644 feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/SettingsSection.kt diff --git a/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/di/initKoin.kt b/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/di/initKoin.kt index 8096c3127..8924f4e6f 100644 --- a/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/di/initKoin.kt +++ b/composeApp/src/commonMain/kotlin/zed/rainxch/githubstore/app/di/initKoin.kt @@ -12,7 +12,7 @@ import zed.rainxch.details.data.di.detailsModule import zed.rainxch.devprofile.data.di.devProfileModule import zed.rainxch.home.data.di.homeModule import zed.rainxch.search.data.di.searchModule -import zed.rainxch.settings.data.di.settingsModule +import zed.rainxch.profile.data.di.settingsModule fun initKoin(config: KoinAppDeclaration? = null) { startKoin { diff --git a/core/presentation/src/commonMain/composeResources/values-bn/strings-bn.xml b/core/presentation/src/commonMain/composeResources/values-bn/strings-bn.xml index ae77c890b..bc09ee534 100644 --- a/core/presentation/src/commonMain/composeResources/values-bn/strings-bn.xml +++ b/core/presentation/src/commonMain/composeResources/values-bn/strings-bn.xml @@ -104,7 +104,7 @@ কোনো রিপোজিটরি পাওয়া যায়নি - সেটিংস + প্রোফাইল চেহারা diff --git a/core/presentation/src/commonMain/composeResources/values-es/strings-es.xml b/core/presentation/src/commonMain/composeResources/values-es/strings-es.xml index b8db96bf2..18760f52f 100644 --- a/core/presentation/src/commonMain/composeResources/values-es/strings-es.xml +++ b/core/presentation/src/commonMain/composeResources/values-es/strings-es.xml @@ -87,7 +87,7 @@ La búsqueda falló No se encontraron repositorios - Configuración + Perfil APARIENCIA ACERCA DE diff --git a/core/presentation/src/commonMain/composeResources/values-fr/strings-fr.xml b/core/presentation/src/commonMain/composeResources/values-fr/strings-fr.xml index 31df05cea..bdd14de57 100644 --- a/core/presentation/src/commonMain/composeResources/values-fr/strings-fr.xml +++ b/core/presentation/src/commonMain/composeResources/values-fr/strings-fr.xml @@ -87,7 +87,7 @@ La recherche a échoué Aucun dépôt trouvé - Paramètres + Profil APPARENCE À PROPOS diff --git a/core/presentation/src/commonMain/composeResources/values-hi/strings-hi.xml b/core/presentation/src/commonMain/composeResources/values-hi/strings-hi.xml index dfe2da022..9a8d3b058 100644 --- a/core/presentation/src/commonMain/composeResources/values-hi/strings-hi.xml +++ b/core/presentation/src/commonMain/composeResources/values-hi/strings-hi.xml @@ -104,7 +104,7 @@ कोई रिपॉजिटरी नहीं मिली - सेटिंग्स + प्रोफ़ाइल उपस्थिति diff --git a/core/presentation/src/commonMain/composeResources/values-it/strings-it.xml b/core/presentation/src/commonMain/composeResources/values-it/strings-it.xml index b9aee12f0..965762924 100644 --- a/core/presentation/src/commonMain/composeResources/values-it/strings-it.xml +++ b/core/presentation/src/commonMain/composeResources/values-it/strings-it.xml @@ -104,7 +104,7 @@ Nessuna repository trovata - Impostazioni + Profilo ASPETTO diff --git a/core/presentation/src/commonMain/composeResources/values-ja/strings-ja.xml b/core/presentation/src/commonMain/composeResources/values-ja/strings-ja.xml index 79d014476..9bfa17a0c 100644 --- a/core/presentation/src/commonMain/composeResources/values-ja/strings-ja.xml +++ b/core/presentation/src/commonMain/composeResources/values-ja/strings-ja.xml @@ -87,7 +87,7 @@ 検索に失敗しました リポジトリが見つかりませんでした - 設定 + プロフィール 外観 情報 diff --git a/core/presentation/src/commonMain/composeResources/values-kr/strings-kr.xml b/core/presentation/src/commonMain/composeResources/values-kr/strings-kr.xml index 271956568..a7fbad230 100644 --- a/core/presentation/src/commonMain/composeResources/values-kr/strings-kr.xml +++ b/core/presentation/src/commonMain/composeResources/values-kr/strings-kr.xml @@ -102,7 +102,7 @@ 저장소를 찾을 수 없습니다 - 설정 + 프로필 외관 diff --git a/core/presentation/src/commonMain/composeResources/values-pl/strings-pl.xml b/core/presentation/src/commonMain/composeResources/values-pl/strings-pl.xml index d9e9edab1..68802d1b8 100644 --- a/core/presentation/src/commonMain/composeResources/values-pl/strings-pl.xml +++ b/core/presentation/src/commonMain/composeResources/values-pl/strings-pl.xml @@ -88,7 +88,7 @@ Wyszukiwanie nie powiodło się Nie znaleziono repozytoriów - Ustawienia + Profil WYGLĄD O APLIKACJI diff --git a/core/presentation/src/commonMain/composeResources/values-ru/strings-ru.xml b/core/presentation/src/commonMain/composeResources/values-ru/strings-ru.xml index 30c3991fb..024ecb30b 100644 --- a/core/presentation/src/commonMain/composeResources/values-ru/strings-ru.xml +++ b/core/presentation/src/commonMain/composeResources/values-ru/strings-ru.xml @@ -87,7 +87,7 @@ Поиск не удался Репозитории не найдены - Настройки + Профиль ВНЕШНИЙ ВИД О ПРИЛОЖЕНИИ diff --git a/core/presentation/src/commonMain/composeResources/values-tr/strings-tr.xml b/core/presentation/src/commonMain/composeResources/values-tr/strings-tr.xml index 0b43b9138..59274cd83 100644 --- a/core/presentation/src/commonMain/composeResources/values-tr/strings-tr.xml +++ b/core/presentation/src/commonMain/composeResources/values-tr/strings-tr.xml @@ -103,7 +103,7 @@ Repo bulunamadı - Ayarlar + Profil GÖRÜNÜM diff --git a/core/presentation/src/commonMain/composeResources/values-zh-rCN/strings-zh-rCN.xml b/core/presentation/src/commonMain/composeResources/values-zh-rCN/strings-zh-rCN.xml index 4fe5e750f..04b000ad4 100644 --- a/core/presentation/src/commonMain/composeResources/values-zh-rCN/strings-zh-rCN.xml +++ b/core/presentation/src/commonMain/composeResources/values-zh-rCN/strings-zh-rCN.xml @@ -89,7 +89,7 @@ 搜索失败 未找到仓库 - 设置 + 个人资料 外观 关于 diff --git a/core/presentation/src/commonMain/composeResources/values/strings.xml b/core/presentation/src/commonMain/composeResources/values/strings.xml index 86b001fe8..7f90bf066 100644 --- a/core/presentation/src/commonMain/composeResources/values/strings.xml +++ b/core/presentation/src/commonMain/composeResources/values/strings.xml @@ -103,8 +103,8 @@ Search failed No repositories found - - Settings + + Profile APPEARANCE diff --git a/core/presentation/src/commonMain/kotlin/zed/rainxch/core/presentation/components/GitHubStoreImage.kt b/core/presentation/src/commonMain/kotlin/zed/rainxch/core/presentation/components/GitHubStoreImage.kt new file mode 100644 index 000000000..50c9267c9 --- /dev/null +++ b/core/presentation/src/commonMain/kotlin/zed/rainxch/core/presentation/components/GitHubStoreImage.kt @@ -0,0 +1,56 @@ +package zed.rainxch.core.presentation.components + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Warning +import androidx.compose.material3.CircularWavyProgressIndicator +import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.unit.dp +import com.skydoves.landscapist.coil3.CoilImage +import com.skydoves.landscapist.components.rememberImageComponent +import com.skydoves.landscapist.crossfade.CrossfadePlugin + +@OptIn(ExperimentalMaterial3ExpressiveApi::class) +@Composable +fun GitHubStoreImage( + imageModel: () -> Any?, + modifier: Modifier = Modifier +) { + CoilImage( + imageModel = imageModel, + modifier = modifier, + loading = { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + CircularWavyProgressIndicator() + } + }, + failure = { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center + ) { + Icon( + imageVector = Icons.Default.Warning, + contentDescription = null, + tint = MaterialTheme.colorScheme.error, + modifier = Modifier.fillMaxSize(.5f) + ) + } + }, + component = rememberImageComponent { + CrossfadePlugin() + } + ) +} \ No newline at end of file diff --git a/core/presentation/src/commonMain/kotlin/zed/rainxch/core/presentation/components/RepositoryCard.kt b/core/presentation/src/commonMain/kotlin/zed/rainxch/core/presentation/components/RepositoryCard.kt index 35e5ae7bf..b2745c4a8 100644 --- a/core/presentation/src/commonMain/kotlin/zed/rainxch/core/presentation/components/RepositoryCard.kt +++ b/core/presentation/src/commonMain/kotlin/zed/rainxch/core/presentation/components/RepositoryCard.kt @@ -106,31 +106,21 @@ fun RepositoryCard( verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(12.dp) ) { - Row ( + Row( modifier = Modifier.clickable(onClick = { - onDeveloperClick(discoveryRepository.repository.owner.login ) + onDeveloperClick(discoveryRepository.repository.owner.login) }), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(12.dp) ) { - CoilImage( + GitHubStoreImage( imageModel = { discoveryRepository.repository.owner.avatarUrl }, modifier = Modifier .size(32.dp) - .clip(CircleShape), - loading = { - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center - ) { - CircularWavyProgressIndicator() - } - }, - component = rememberImageComponent { - CrossfadePlugin() - } + .clip(CircleShape) ) + Text( text = discoveryRepository.repository.owner.login, style = MaterialTheme.typography.titleMedium, diff --git a/feature/profile/data/src/commonMain/kotlin/zed/rainxch/profile/data/di/SharedModule.kt b/feature/profile/data/src/commonMain/kotlin/zed/rainxch/profile/data/di/SharedModule.kt new file mode 100644 index 000000000..7b77b2475 --- /dev/null +++ b/feature/profile/data/src/commonMain/kotlin/zed/rainxch/profile/data/di/SharedModule.kt @@ -0,0 +1,14 @@ +package zed.rainxch.profile.data.di + +import org.koin.dsl.module +import zed.rainxch.profile.data.repository.ProfileRepositoryImpl +import zed.rainxch.profile.domain.repository.ProfileRepository + +val settingsModule = module { + single { + ProfileRepositoryImpl( + authenticationState = get(), + tokenStore = get() + ) + } +} \ No newline at end of file diff --git a/feature/profile/data/src/commonMain/kotlin/zed/rainxch/settings/data/repository/SettingsRepositoryImpl.kt b/feature/profile/data/src/commonMain/kotlin/zed/rainxch/profile/data/repository/ProfileRepositoryImpl.kt similarity index 80% rename from feature/profile/data/src/commonMain/kotlin/zed/rainxch/settings/data/repository/SettingsRepositoryImpl.kt rename to feature/profile/data/src/commonMain/kotlin/zed/rainxch/profile/data/repository/ProfileRepositoryImpl.kt index 06dee3951..04edca35c 100644 --- a/feature/profile/data/src/commonMain/kotlin/zed/rainxch/settings/data/repository/SettingsRepositoryImpl.kt +++ b/feature/profile/data/src/commonMain/kotlin/zed/rainxch/profile/data/repository/ProfileRepositoryImpl.kt @@ -1,4 +1,4 @@ -package zed.rainxch.settings.data.repository +package zed.rainxch.profile.data.repository import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow @@ -6,12 +6,12 @@ import kotlinx.coroutines.flow.flowOn import zed.rainxch.core.data.data_source.TokenStore import zed.rainxch.core.domain.repository.AuthenticationState import zed.rainxch.feature.profile.data.BuildKonfig -import zed.rainxch.settings.domain.repository.SettingsRepository +import zed.rainxch.profile.domain.repository.ProfileRepository -class SettingsRepositoryImpl( +class ProfileRepositoryImpl( private val authenticationState: AuthenticationState, private val tokenStore: TokenStore -) : SettingsRepository { +) : ProfileRepository { override val isUserLoggedIn: Flow get() = authenticationState .isUserLoggedIn() diff --git a/feature/profile/data/src/commonMain/kotlin/zed/rainxch/settings/data/di/SharedModule.kt b/feature/profile/data/src/commonMain/kotlin/zed/rainxch/settings/data/di/SharedModule.kt deleted file mode 100644 index 9bec0b7df..000000000 --- a/feature/profile/data/src/commonMain/kotlin/zed/rainxch/settings/data/di/SharedModule.kt +++ /dev/null @@ -1,14 +0,0 @@ -package zed.rainxch.settings.data.di - -import org.koin.dsl.module -import zed.rainxch.settings.data.repository.SettingsRepositoryImpl -import zed.rainxch.settings.domain.repository.SettingsRepository - -val settingsModule = module { - single { - SettingsRepositoryImpl( - authenticationState = get(), - tokenStore = get() - ) - } -} \ No newline at end of file diff --git a/feature/profile/domain/src/commonMain/kotlin/zed/rainxch/profile/domain/model/UserProfile.kt b/feature/profile/domain/src/commonMain/kotlin/zed/rainxch/profile/domain/model/UserProfile.kt new file mode 100644 index 000000000..e7f3756c2 --- /dev/null +++ b/feature/profile/domain/src/commonMain/kotlin/zed/rainxch/profile/domain/model/UserProfile.kt @@ -0,0 +1,12 @@ +package zed.rainxch.profile.domain.model + +data class UserProfile( + val id: Int, + val imageUrl: String, + val name: String, + val username: String, + val bio: String, + val repositoryCount: Int, + val followers: Int, + val following: Int, +) diff --git a/feature/profile/domain/src/commonMain/kotlin/zed/rainxch/profile/domain/repository/ProfileRepository.kt b/feature/profile/domain/src/commonMain/kotlin/zed/rainxch/profile/domain/repository/ProfileRepository.kt new file mode 100644 index 000000000..369fa9316 --- /dev/null +++ b/feature/profile/domain/src/commonMain/kotlin/zed/rainxch/profile/domain/repository/ProfileRepository.kt @@ -0,0 +1,11 @@ +package zed.rainxch.profile.domain.repository + +import kotlinx.coroutines.flow.Flow +import zed.rainxch.profile.domain.model.UserProfile + +interface ProfileRepository { + val isUserLoggedIn: Flow + fun getUser(): Flow + fun getVersionName(): String + suspend fun logout() +} \ No newline at end of file diff --git a/feature/profile/domain/src/commonMain/kotlin/zed/rainxch/settings/domain/repository/SettingsRepository.kt b/feature/profile/domain/src/commonMain/kotlin/zed/rainxch/settings/domain/repository/SettingsRepository.kt deleted file mode 100644 index 9c47e223c..000000000 --- a/feature/profile/domain/src/commonMain/kotlin/zed/rainxch/settings/domain/repository/SettingsRepository.kt +++ /dev/null @@ -1,9 +0,0 @@ -package zed.rainxch.settings.domain.repository - -import kotlinx.coroutines.flow.Flow - -interface SettingsRepository { - val isUserLoggedIn: Flow - suspend fun logout() - fun getVersionName() : String -} \ No newline at end of file diff --git a/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileRoot.kt b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileRoot.kt index a77c3b28d..e1e719eaf 100644 --- a/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileRoot.kt +++ b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileRoot.kt @@ -34,14 +34,14 @@ import org.jetbrains.compose.resources.getString import org.jetbrains.compose.resources.stringResource import org.jetbrains.compose.ui.tooling.preview.Preview import org.koin.compose.viewmodel.koinViewModel -import zed.rainxch.core.domain.model.FontTheme import zed.rainxch.core.presentation.locals.LocalBottomNavigationLiquid import zed.rainxch.core.presentation.theme.GithubStoreTheme import zed.rainxch.core.presentation.utils.ObserveAsEvents -import zed.rainxch.settings.presentation.components.LogoutDialog -import zed.rainxch.settings.presentation.components.sections.about -import zed.rainxch.settings.presentation.components.sections.appearance -import zed.rainxch.settings.presentation.components.sections.logout +import zed.rainxch.profile.presentation.components.LogoutDialog +import zed.rainxch.profile.presentation.components.sections.about +import zed.rainxch.profile.presentation.components.sections.logout +import zed.rainxch.profile.presentation.components.sections.profile +import zed.rainxch.profile.presentation.components.sections.settings @Composable fun ProfileRoot( @@ -122,29 +122,18 @@ fun ProfileScreen( .padding(innerPadding) .padding(16.dp) ) { - appearance( - selectedThemeColor = state.selectedThemeColor, - onThemeColorSelected = { theme -> - onAction(ProfileAction.OnThemeColorSelected(theme)) - }, - isAmoledThemeEnabled = state.isAmoledThemeEnabled, - onAmoledThemeToggled = { enabled -> - onAction(ProfileAction.OnAmoledThemeToggled(enabled)) - }, - isDarkTheme = state.isDarkTheme, - onDarkThemeChange = { isDarkTheme -> - onAction(ProfileAction.OnDarkThemeChange(isDarkTheme)) - }, - isUsingSystemFont = state.selectedFontTheme == FontTheme.SYSTEM, - onUseSystemFontToggled = { enabled -> - onAction( - ProfileAction.OnFontThemeSelected( - if (enabled) { - FontTheme.SYSTEM - } else FontTheme.CUSTOM - ) - ) - } + profile( + state = state, + onAction = onAction + ) + + item { + Spacer(Modifier.height(24.dp)) + } + + settings( + state = state, + onAction = onAction ) item { @@ -165,6 +154,10 @@ fun ProfileScreen( onAction = onAction ) } + + item { + Spacer(Modifier.height(64.dp)) + } } } } @@ -189,7 +182,7 @@ private fun TopAppBar(onAction: (ProfileAction) -> Unit) { }, title = { Text( - text = stringResource(Res.string.settings_title), + text = stringResource(Res.string.profile_title), style = MaterialTheme.typography.titleMediumEmphasized, fontWeight = FontWeight.SemiBold, color = MaterialTheme.colorScheme.onSurface diff --git a/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileState.kt b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileState.kt index 1bfa7cd49..fd676000f 100644 --- a/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileState.kt +++ b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileState.kt @@ -2,8 +2,10 @@ package zed.rainxch.profile.presentation import zed.rainxch.core.domain.model.AppTheme import zed.rainxch.core.domain.model.FontTheme +import zed.rainxch.profile.domain.model.UserProfile data class ProfileState( + val userProfile: UserProfile? = null, val selectedThemeColor: AppTheme = AppTheme.OCEAN, val selectedFontTheme: FontTheme = FontTheme.CUSTOM, val isLogoutDialogVisible: Boolean = false, diff --git a/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileViewModel.kt b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileViewModel.kt index 0270df6b6..c08726bf9 100644 --- a/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileViewModel.kt +++ b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/ProfileViewModel.kt @@ -12,12 +12,12 @@ import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import zed.rainxch.core.domain.repository.ThemesRepository import zed.rainxch.core.domain.utils.BrowserHelper -import zed.rainxch.settings.domain.repository.SettingsRepository +import zed.rainxch.profile.domain.repository.ProfileRepository class ProfileViewModel( private val browserHelper: BrowserHelper, private val themesRepository: ThemesRepository, - private val settingsRepository: SettingsRepository + private val profileRepository: ProfileRepository ) : ViewModel() { private var hasLoadedInitialData = false @@ -46,7 +46,7 @@ class ProfileViewModel( viewModelScope.launch { _state.update { it.copy( - versionName = settingsRepository.getVersionName() + versionName = profileRepository.getVersionName() ) } } @@ -54,7 +54,7 @@ class ProfileViewModel( private fun collectIsUserLoggedIn() { viewModelScope.launch { - settingsRepository.isUserLoggedIn + profileRepository.isUserLoggedIn .collect { isLoggedIn -> _state.update { it.copy(isUserLoggedIn = isLoggedIn) } } @@ -126,7 +126,7 @@ class ProfileViewModel( ProfileAction.OnLogoutConfirmClick -> { viewModelScope.launch { runCatching { - settingsRepository.logout() + profileRepository.logout() }.onSuccess { _state.update { it.copy(isLogoutDialogVisible = false) } _events.send(ProfileEvent.OnLogoutSuccessful) diff --git a/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/LogoutDialog.kt b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/LogoutDialog.kt index 79571af2f..d203f13d0 100644 --- a/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/LogoutDialog.kt +++ b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/LogoutDialog.kt @@ -1,4 +1,4 @@ -package zed.rainxch.settings.presentation.components +package zed.rainxch.profile.presentation.components import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement diff --git a/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/SectionText.kt b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/SectionText.kt new file mode 100644 index 000000000..f37f59210 --- /dev/null +++ b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/SectionText.kt @@ -0,0 +1,33 @@ +package zed.rainxch.profile.presentation.components + +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp + +@OptIn(ExperimentalMaterial3ExpressiveApi::class) +@Composable +fun SectionTitle(text: String) { + Text( + text = text, + style = MaterialTheme.typography.titleMediumEmphasized, + color = MaterialTheme.colorScheme.primary, + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(start = 8.dp) + ) +} + +@Composable +fun SectionHeader(text: String) { + Text( + text = text, + style = MaterialTheme.typography.titleSmall, + color = MaterialTheme.colorScheme.secondary, + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(start = 8.dp) + ) +} diff --git a/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/About.kt b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/About.kt index 622472f2e..79a6cca73 100644 --- a/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/About.kt +++ b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/About.kt @@ -1,4 +1,4 @@ -package zed.rainxch.settings.presentation.components.sections +package zed.rainxch.profile.presentation.components.sections import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row diff --git a/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/Account.kt b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/Account.kt index ff89482af..5c6dc026b 100644 --- a/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/Account.kt +++ b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/Account.kt @@ -1,4 +1,4 @@ -package zed.rainxch.settings.presentation.components.sections +package zed.rainxch.profile.presentation.components.sections import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row diff --git a/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/AccountSection.kt b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/AccountSection.kt new file mode 100644 index 000000000..a1b689a59 --- /dev/null +++ b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/AccountSection.kt @@ -0,0 +1,66 @@ +package zed.rainxch.profile.presentation.components.sections + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListScope +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.AccountCircle +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.unit.dp +import org.jetbrains.compose.ui.tooling.preview.Preview +import zed.rainxch.core.presentation.components.GitHubStoreImage +import zed.rainxch.core.presentation.theme.GithubStoreTheme +import zed.rainxch.profile.presentation.ProfileAction +import zed.rainxch.profile.presentation.ProfileState + +fun LazyListScope.accountSection( + state: ProfileState, + onAction: (ProfileAction) -> Unit, +) { + item { + Column ( + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(4.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + GitHubStoreImage( + imageModel = { + if (state.userProfile == null) { + Icons.Outlined.AccountCircle + } else { + state.userProfile.imageUrl + } + }, + modifier = Modifier + .size(100.dp) + .clip(CircleShape) + .background(MaterialTheme.colorScheme.surfaceContainerHigh) + ) + + + } + + } +} + +@Preview(showBackground = true) +@Composable +fun AccountSectionPreview() { + GithubStoreTheme { + LazyColumn { + accountSection( + state = ProfileState(), + onAction = { } + ) + } + } +} \ No newline at end of file diff --git a/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/Appearance.kt b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/Appearance.kt index 3f6f54689..32ad70d9d 100644 --- a/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/Appearance.kt +++ b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/Appearance.kt @@ -1,4 +1,4 @@ -package zed.rainxch.settings.presentation.components.sections +package zed.rainxch.profile.presentation.components.sections import androidx.compose.animation.core.Spring import androidx.compose.animation.core.animateFloatAsState @@ -54,49 +54,55 @@ import androidx.compose.ui.semantics.Role import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -import zed.rainxch.githubstore.core.presentation.res.* import org.jetbrains.compose.resources.stringResource import zed.rainxch.core.domain.model.AppTheme +import zed.rainxch.core.domain.model.FontTheme import zed.rainxch.core.presentation.theme.isDynamicColorAvailable import zed.rainxch.core.presentation.utils.displayName import zed.rainxch.core.presentation.utils.primaryColor +import zed.rainxch.githubstore.core.presentation.res.* +import zed.rainxch.profile.presentation.ProfileAction +import zed.rainxch.profile.presentation.ProfileState +import zed.rainxch.profile.presentation.components.SectionHeader @OptIn(ExperimentalMaterial3ExpressiveApi::class) -fun LazyListScope.appearance( - selectedThemeColor: AppTheme, - isAmoledThemeEnabled: Boolean, - onAmoledThemeToggled: (Boolean) -> Unit, - isDarkTheme: Boolean?, - onDarkThemeChange: (Boolean?) -> Unit, - onThemeColorSelected: (AppTheme) -> Unit, - isUsingSystemFont: Boolean, - onUseSystemFontToggled: (Boolean) -> Unit, +fun LazyListScope.appearanceSection( + state: ProfileState, + onAction: (ProfileAction) -> Unit, ) { item { - SectionHeader(stringResource(Res.string.section_appearance)) + SectionHeader( + text = stringResource(Res.string.section_appearance) + ) VerticalSpacer(8.dp) ThemeSelectionCard( - isDarkTheme = isDarkTheme, - onDarkThemeChange = onDarkThemeChange + isDarkTheme = state.isDarkTheme, + onDarkThemeChange = { isDarkTheme -> + onAction(ProfileAction.OnDarkThemeChange(isDarkTheme)) + } ) VerticalSpacer(16.dp) ThemeColorCard( - selectedThemeColor = selectedThemeColor, - onThemeColorSelected = onThemeColorSelected + selectedThemeColor = state.selectedThemeColor, + onThemeColorSelected = { theme -> + onAction(ProfileAction.OnThemeColorSelected(theme)) + } ) VerticalSpacer(16.dp) - if (isDarkTheme == true || (isDarkTheme == null && isSystemInDarkTheme())) { + if (state.isDarkTheme == true || (state.isDarkTheme == null && isSystemInDarkTheme())) { ToggleSettingCard( title = stringResource(Res.string.amoled_black_theme), description = stringResource(Res.string.amoled_black_description), - checked = isAmoledThemeEnabled, - onCheckedChange = onAmoledThemeToggled + checked = state.isAmoledThemeEnabled, + onCheckedChange = { enabled -> + onAction(ProfileAction.OnAmoledThemeToggled(enabled)) + } ) VerticalSpacer(16.dp) @@ -105,22 +111,20 @@ fun LazyListScope.appearance( ToggleSettingCard( title = stringResource(Res.string.system_font), description = stringResource(Res.string.system_font_description), - checked = isUsingSystemFont, - onCheckedChange = onUseSystemFontToggled + checked = state.selectedFontTheme == FontTheme.SYSTEM, + onCheckedChange = { enabled -> + onAction( + ProfileAction.OnFontThemeSelected( + if (enabled) { + FontTheme.SYSTEM + } else FontTheme.CUSTOM + ) + ) + } ) } } -@Composable -private fun SectionHeader(text: String) { - Text( - text = text, - style = MaterialTheme.typography.titleSmall, - color = MaterialTheme.colorScheme.primary, - fontWeight = FontWeight.Bold, - modifier = Modifier.padding(start = 8.dp) - ) -} @Composable private fun VerticalSpacer(height: Dp) { diff --git a/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/ProfileSection.kt b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/ProfileSection.kt new file mode 100644 index 000000000..0cefc41ee --- /dev/null +++ b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/ProfileSection.kt @@ -0,0 +1,15 @@ +package zed.rainxch.profile.presentation.components.sections + +import androidx.compose.foundation.lazy.LazyListScope +import zed.rainxch.profile.presentation.ProfileAction +import zed.rainxch.profile.presentation.ProfileState + +fun LazyListScope.profile( + state: ProfileState, + onAction: (ProfileAction) -> Unit, +) { + accountSection( + state = state, + onAction = onAction + ) +} \ No newline at end of file diff --git a/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/SettingsSection.kt b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/SettingsSection.kt new file mode 100644 index 000000000..681fd6ae8 --- /dev/null +++ b/feature/profile/presentation/src/commonMain/kotlin/zed/rainxch/profile/presentation/components/sections/SettingsSection.kt @@ -0,0 +1,15 @@ +package zed.rainxch.profile.presentation.components.sections + +import androidx.compose.foundation.lazy.LazyListScope +import zed.rainxch.profile.presentation.ProfileAction +import zed.rainxch.profile.presentation.ProfileState + +fun LazyListScope.settings( + state: ProfileState, + onAction: (ProfileAction) -> Unit, +) { + appearanceSection( + state = state, + onAction = onAction + ) +} \ No newline at end of file From 2318eabd37439b2f8059d3dcc393466ce5bb2396 Mon Sep 17 00:00:00 2001 From: rainxchzed Date: Wed, 25 Feb 2026 20:37:02 +0500 Subject: [PATCH 3/3] Return null on getUser --- .../profile/data/repository/ProfileRepositoryImpl.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/feature/profile/data/src/commonMain/kotlin/zed/rainxch/profile/data/repository/ProfileRepositoryImpl.kt b/feature/profile/data/src/commonMain/kotlin/zed/rainxch/profile/data/repository/ProfileRepositoryImpl.kt index 04edca35c..e37e89339 100644 --- a/feature/profile/data/src/commonMain/kotlin/zed/rainxch/profile/data/repository/ProfileRepositoryImpl.kt +++ b/feature/profile/data/src/commonMain/kotlin/zed/rainxch/profile/data/repository/ProfileRepositoryImpl.kt @@ -2,10 +2,12 @@ package zed.rainxch.profile.data.repository import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOn import zed.rainxch.core.data.data_source.TokenStore import zed.rainxch.core.domain.repository.AuthenticationState import zed.rainxch.feature.profile.data.BuildKonfig +import zed.rainxch.profile.domain.model.UserProfile import zed.rainxch.profile.domain.repository.ProfileRepository class ProfileRepositoryImpl( @@ -17,6 +19,10 @@ class ProfileRepositoryImpl( .isUserLoggedIn() .flowOn(Dispatchers.IO) + override fun getUser(): Flow { + return flowOf(null) + } + override fun getVersionName(): String { return BuildKonfig.VERSION_NAME }