Skip to content

Commit 75e3e07

Browse files
committed
Refactor frontend modularization by migrating multiple features (profile, security, change password, licenses, sync, activity, admin, plugins, shares, shared with me) into their own modules. Update Koin dependency injection to include the new feature modules and remove obsolete components from the composeApp. Adjust Gradle configurations to reflect the new structure, enhancing code clarity and organization. Update documentation to reflect changes in module ownership and implementation status.
1 parent 49b448a commit 75e3e07

95 files changed

Lines changed: 680 additions & 1861 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/architecture/FRONTEND_MODULARISATION_AND_STANDALONE_BUILDS.md

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Frontend modularisation and standalone projects (backend / frontend)
22

3-
**Last updated**: 2026-02-19 (source layout src/main + src/test, ThemeMode in core:resources, :feature:settings migrated)
3+
**Last updated**: 2026-02-20 (source layout src/main + src/test, ThemeMode in core:resources, feature:settings/profile/security/changepassword/licenses/sync/activity/admin/plugins/shares/sharedwithme migrated)
44

55
### Current implementation status
66

@@ -35,9 +35,19 @@
3535
- **:data:storage** – DTOs split to one file per DTO (StorageItemDTO, CreateFolderRequestDTO, etc.); StorageDTOs.kt removed.
3636
- **:feature:auth** – Done. Full screen in module: `AuthViewModel`, `AuthError`, `AuthSuccessCallback`, `AuthComponent`, `DefaultAuthComponent`, `AuthContent` (one file per class). Depends on `:core:resources`, `:domain:auth`, Koin Compose ViewModel, Material3; composeApp only wires navigation (RootContent uses AuthContent from module).
3737
- **:feature:settings** – Done. Full screen in module: `SettingsComponent`, `DefaultSettingsComponent`, `SettingsViewModel`, `SettingsContent`, `SettingsScreen`, `SettingsDialogs`, `SettingsComponents` (one file per class/group). Theme/language via component callbacks; `ThemeMode` in `:core:resources`. Depends on `:core:resources`, `:domain:auth`, Koin Compose ViewModel, Material3. `featureSettingsModule` loaded in all entry points.
38+
- **:feature:profile** – Done. Full screen in module: `ProfileComponent`, `DefaultProfileComponent`, `ProfileViewModel`, `ProfileContent`, `ProfileScreen`, `ProfileComponents`, `ProfileDialogs`; export wiring delegated through component callback so module remains composeApp-independent.
39+
- **:feature:security** – Done. Full screen in module: `SecurityComponent`, `DefaultSecurityComponent`, `SecurityViewModel`, `SecurityContent`, `SecurityScreen`, `SecurityComponents`, `SecurityDialogs`.
40+
- **:feature:changepassword** – Done. Full screen in module: `ChangePasswordComponent`, `DefaultChangePasswordComponent`, `ChangePasswordViewModel`, `ChangePasswordContent`, `ChangePasswordScreen`.
41+
- **:feature:licenses** – Done. Full screen in module: `LicensesComponent`, `DefaultLicensesComponent`, `LicensesContent`, `LicensesScreen`.
42+
- **:feature:sync** – Done. Full screen in module: `SyncComponent`, `DefaultSyncComponent`, `SyncViewModel`, `SyncContent`, `SyncScreen`, `SyncComponents`, `SyncDialogs`, `SyncTabs`.
43+
- **:feature:activity** – Done. Full screen in module: `ActivityComponent`, `DefaultActivityComponent`, `ActivityViewModel`, `ActivityContent`, `ActivityScreen`, `ActivityComponents`.
44+
- **:feature:admin** – Done. Full screen in module: `AdminComponent`, `DefaultAdminComponent`, `AdminViewModel`, `AdminContent`, `AdminScreen`, `AdminComponents`, `AdminDialogs`.
45+
- **:feature:plugins** – Done. Full screen in module: `PluginsComponent`, `DefaultPluginsComponent`, `PluginsViewModel`, `PluginsContent`, `PluginsScreen`.
46+
- **:feature:shares** – Done. Full screen in module: `SharesComponent`, `DefaultSharesComponent`, `SharesViewModel`, `SharesContent`, `SharedScreen`, `SharedComponents`, `SharedDialogs`.
47+
- **:feature:sharedwithme** – Done. Full screen in module: `SharedWithMeComponent`, `DefaultSharedWithMeComponent`, `SharedWithMeViewModel`, `SharedWithMeContent`, `SharedWithMeScreen`, `SharedWithMeComponents`, `SharedDialogs`.
3848
- **:feature:*** (rest) – Placeholder only; ViewModels/screens still in composeApp.
3949

40-
Next: migrate remaining feature modules (profile, security, changepassword, licenses, then sync, shares, sharedwithme, activity, admin, plugins, versionhistory, files, collaboration, federation, ai, main). Use `:core:resources` for strings; follow :feature:auth / :feature:settings as reference (ViewModel, Component, Content in module; depend on :core:resources, :domain:*, Koin Compose, Material3).
50+
Next: migrate remaining feature modules (versionhistory, files, collaboration, federation, ai, main). Use `:core:resources` for strings; follow :feature:auth / :feature:settings as reference (ViewModel, Component, Content in module; depend on :core:resources, :domain:*, Koin Compose, Material3).
4151

4252
### Koin module ownership
4353

@@ -60,7 +70,16 @@ Each **feature**, **data**, **domain**, and **core** module that exposes or cons
6070
| Data | :data:collaboration | collaborationModule | CollaborationApi, CollaborationRepository, collaboration use-case impls |
6171
| Feature | :feature:auth | featureAuthModule | AuthViewModel (param: AuthSuccessCallback) |
6272
| Feature | :feature:settings | featureSettingsModule | SettingsViewModel (param: SettingsComponent) |
63-
| App | composeApp | appModule | UploadManager; ViewModels still in composeApp (profile, sync, federation, ai, admin, activity, plugins, changepassword, versionhistory, files, collaboration) until their features are migrated |
73+
| Feature | :feature:profile | featureProfileModule | ProfileViewModel (param: ProfileComponent) |
74+
| Feature | :feature:security | featureSecurityModule | SecurityViewModel |
75+
| Feature | :feature:changepassword | featureChangePasswordModule | ChangePasswordViewModel |
76+
| Feature | :feature:sync | featureSyncModule | SyncViewModel |
77+
| Feature | :feature:activity | featureActivityModule | ActivityViewModel |
78+
| Feature | :feature:admin | featureAdminModule | AdminViewModel |
79+
| Feature | :feature:plugins | featurePluginsModule | PluginsViewModel |
80+
| Feature | :feature:shares | featureSharesModule | SharesViewModel |
81+
| Feature | :feature:sharedwithme | featureSharedWithMeModule | SharedWithMeViewModel |
82+
| App | composeApp | appModule | UploadManager; ViewModels still in composeApp (federation, ai, versionhistory, files, collaboration) until their features are migrated |
6483

6584
Domain and core modules typically do not define Koin modules (they expose interfaces/types; data/feature modules provide implementations and register them).
6685

frontend/androidApp/src/main/kotlin/com/vaultstadio/app/VaultStadioApplication.kt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,16 @@ import com.vaultstadio.app.data.activity.di.activityModule
1111
import com.vaultstadio.app.data.admin.di.adminModule
1212
import com.vaultstadio.app.data.auth.di.authModule
1313
import com.vaultstadio.app.feature.auth.di.featureAuthModule
14+
import com.vaultstadio.app.feature.activity.di.featureActivityModule
15+
import com.vaultstadio.app.feature.admin.di.featureAdminModule
16+
import com.vaultstadio.app.feature.changepassword.di.featureChangePasswordModule
17+
import com.vaultstadio.app.feature.profile.di.featureProfileModule
18+
import com.vaultstadio.app.feature.security.di.featureSecurityModule
1419
import com.vaultstadio.app.feature.settings.di.featureSettingsModule
20+
import com.vaultstadio.app.feature.sharedwithme.di.featureSharedWithMeModule
21+
import com.vaultstadio.app.feature.shares.di.featureSharesModule
22+
import com.vaultstadio.app.feature.sync.di.featureSyncModule
23+
import com.vaultstadio.app.feature.plugins.di.featurePluginsModule
1524
import com.vaultstadio.app.data.config.di.configModule
1625
import com.vaultstadio.app.data.share.di.shareModule
1726
import com.vaultstadio.app.data.plugin.di.pluginModule
@@ -49,7 +58,14 @@ class VaultStadioApplication : Application() {
4958
androidLogger(Level.INFO)
5059
androidContext(this@VaultStadioApplication)
5160
modules(
52-
runtimeModules(getServerUrl()) + listOf(androidModule, activityModule, adminModule, authModule, featureAuthModule, featureSettingsModule, aiModule, collaborationModule, configModule, shareModule, pluginModule, storageModule, metadataModule, syncModule, federationModule, versionModule),
61+
runtimeModules(getServerUrl()) + listOf(
62+
androidModule, activityModule, adminModule, authModule,
63+
featureAuthModule, featureActivityModule, featureAdminModule, featureSettingsModule,
64+
featureProfileModule, featureSecurityModule, featureChangePasswordModule,
65+
featureSyncModule, featurePluginsModule, featureSharesModule, featureSharedWithMeModule,
66+
aiModule, collaborationModule, configModule, shareModule, pluginModule,
67+
storageModule, metadataModule, syncModule, federationModule, versionModule,
68+
),
5369
)
5470
}
5571
}

frontend/composeApp/build.gradle.kts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,16 @@ kotlin {
6363
implementation(project(":core:resources"))
6464
implementation(project(":feature:auth"))
6565
implementation(project(":feature:settings"))
66+
implementation(project(":feature:profile"))
67+
implementation(project(":feature:security"))
68+
implementation(project(":feature:changepassword"))
69+
implementation(project(":feature:licenses"))
70+
implementation(project(":feature:sync"))
71+
implementation(project(":feature:activity"))
72+
implementation(project(":feature:admin"))
73+
implementation(project(":feature:plugins"))
74+
implementation(project(":feature:shares"))
75+
implementation(project(":feature:sharedwithme"))
6676
implementation(project(":data:network"))
6777
implementation(project(":data:sync"))
6878
implementation(project(":data:metadata"))

frontend/composeApp/src/desktopMain/kotlin/com/vaultstadio/app/Main.kt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,16 @@ import com.vaultstadio.app.data.activity.di.activityModule
1717
import com.vaultstadio.app.data.admin.di.adminModule
1818
import com.vaultstadio.app.data.auth.di.authModule
1919
import com.vaultstadio.app.feature.auth.di.featureAuthModule
20+
import com.vaultstadio.app.feature.activity.di.featureActivityModule
21+
import com.vaultstadio.app.feature.admin.di.featureAdminModule
22+
import com.vaultstadio.app.feature.changepassword.di.featureChangePasswordModule
23+
import com.vaultstadio.app.feature.profile.di.featureProfileModule
24+
import com.vaultstadio.app.feature.security.di.featureSecurityModule
2025
import com.vaultstadio.app.feature.settings.di.featureSettingsModule
26+
import com.vaultstadio.app.feature.sharedwithme.di.featureSharedWithMeModule
27+
import com.vaultstadio.app.feature.shares.di.featureSharesModule
28+
import com.vaultstadio.app.feature.sync.di.featureSyncModule
29+
import com.vaultstadio.app.feature.plugins.di.featurePluginsModule
2130
import com.vaultstadio.app.data.config.di.configModule
2231
import com.vaultstadio.app.data.share.di.shareModule
2332
import com.vaultstadio.app.data.plugin.di.pluginModule
@@ -33,7 +42,15 @@ import org.koin.core.context.startKoin
3342

3443
fun main() {
3544
startKoin {
36-
modules(runtimeModules("http://localhost:8080/api") + activityModule + adminModule + authModule + featureAuthModule + featureSettingsModule + aiModule + collaborationModule + configModule + shareModule + pluginModule + storageModule + metadataModule + syncModule + federationModule + versionModule)
45+
modules(
46+
runtimeModules("http://localhost:8080/api") +
47+
activityModule + adminModule + authModule +
48+
featureAuthModule + featureActivityModule + featureAdminModule + featureSettingsModule +
49+
featureProfileModule + featureSecurityModule + featureChangePasswordModule + featureSyncModule +
50+
featurePluginsModule + featureSharesModule + featureSharedWithMeModule +
51+
aiModule + collaborationModule + configModule + shareModule + pluginModule +
52+
storageModule + metadataModule + syncModule + federationModule + versionModule,
53+
)
3754
}
3855
application {
3956
Window(

frontend/composeApp/src/main/kotlin/com/vaultstadio/app/di/AppModuleDsl.kt

Lines changed: 9 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -41,27 +41,11 @@ import com.vaultstadio.app.domain.federation.usecase.RemoveInstanceUseCase
4141
import com.vaultstadio.app.domain.federation.usecase.RequestFederationUseCase
4242
import com.vaultstadio.app.domain.federation.usecase.RevokeFederatedShareUseCase
4343
import com.vaultstadio.app.domain.federation.usecase.UnlinkIdentityUseCase
44-
import com.vaultstadio.app.feature.activity.ActivityViewModel
45-
import com.vaultstadio.app.feature.admin.AdminViewModel
4644
import com.vaultstadio.app.feature.ai.AIViewModel
47-
import com.vaultstadio.app.feature.changepassword.ChangePasswordViewModel
4845
import com.vaultstadio.app.feature.collaboration.CollaborationViewModel
4946
import com.vaultstadio.app.feature.federation.FederationViewModel
5047
import com.vaultstadio.app.feature.files.FilesViewModel
5148
import com.vaultstadio.app.feature.main.MainComponent
52-
import com.vaultstadio.app.feature.plugins.PluginsViewModel
53-
import com.vaultstadio.app.feature.profile.ProfileViewModel
54-
import com.vaultstadio.app.feature.security.SecurityViewModel
55-
import com.vaultstadio.app.feature.shares.SharesViewModel
56-
import com.vaultstadio.app.feature.sharedwithme.SharedWithMeViewModel
57-
import com.vaultstadio.app.domain.sync.usecase.DeactivateDeviceUseCase
58-
import com.vaultstadio.app.domain.sync.usecase.GetConflictsUseCase
59-
import com.vaultstadio.app.domain.sync.usecase.GetDevicesUseCase
60-
import com.vaultstadio.app.domain.sync.usecase.PullChangesUseCase
61-
import com.vaultstadio.app.domain.sync.usecase.RegisterDeviceUseCase
62-
import com.vaultstadio.app.domain.sync.usecase.RemoveDeviceUseCase
63-
import com.vaultstadio.app.domain.sync.usecase.ResolveConflictUseCase
64-
import com.vaultstadio.app.feature.sync.SyncViewModel
6549
import com.vaultstadio.app.feature.upload.UploadManager
6650
import com.vaultstadio.app.feature.versionhistory.VersionHistoryViewModel
6751
import io.ktor.client.HttpClient
@@ -78,22 +62,12 @@ val appModule = module {
7862
single { UploadManager(get()) }
7963

8064
// --- ViewModels (no params) ---
81-
viewModel { ProfileViewModel(get(), get(), get(), get()) }
65+
// ProfileViewModel is in featureProfileModule (:feature:profile)
8266
// SettingsViewModel is in featureSettingsModule (:feature:settings)
83-
viewModel { SecurityViewModel(get(), get(), get(), get()) }
84-
viewModel { SharesViewModel(get(), get(), get()) }
85-
viewModel { SharedWithMeViewModel(get(), get(), get(), get()) }
86-
viewModel {
87-
SyncViewModel(
88-
get<GetDevicesUseCase>(),
89-
get<GetConflictsUseCase>(),
90-
get<RegisterDeviceUseCase>(),
91-
get<DeactivateDeviceUseCase>(),
92-
get<RemoveDeviceUseCase>(),
93-
get<ResolveConflictUseCase>(),
94-
get<PullChangesUseCase>(),
95-
)
96-
}
67+
// SecurityViewModel is in featureSecurityModule (:feature:security)
68+
// SharesViewModel is in featureSharesModule (:feature:shares)
69+
// SharedWithMeViewModel is in featureSharedWithMeModule (:feature:sharedwithme)
70+
// SyncViewModel is in featureSyncModule (:feature:sync)
9771
viewModel {
9872
FederationViewModel(
9973
get<GetFederatedInstancesUseCase>(),
@@ -117,10 +91,10 @@ val appModule = module {
11791
get(), get(), get(), get(), get(), get(), get(), get(), get(), get(),
11892
)
11993
}
120-
viewModel { AdminViewModel(get(), get(), get(), get()) }
121-
viewModel { ActivityViewModel(get()) }
122-
viewModel { PluginsViewModel(get(), get(), get()) }
123-
viewModel { ChangePasswordViewModel(get()) }
94+
// AdminViewModel is in featureAdminModule (:feature:admin)
95+
// ActivityViewModel is in featureActivityModule (:feature:activity)
96+
// PluginsViewModel is in featurePluginsModule (:feature:plugins)
97+
// ChangePasswordViewModel is in featureChangePasswordModule (:feature:changepassword)
12498

12599
// --- ViewModels (with params) ---
126100
// AuthViewModel is in featureAuthModule (:feature:auth)

frontend/composeApp/src/main/kotlin/com/vaultstadio/app/feature/activity/ActivityComponent.kt

Lines changed: 0 additions & 20 deletions
This file was deleted.

frontend/composeApp/src/main/kotlin/com/vaultstadio/app/feature/main/MainComponent.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,9 @@ class DefaultMainComponent(
244244
onNavigateBack = ::goBack,
245245
onNavigateToChangePassword = { navigateTo(MainDestination.CHANGE_PASSWORD) },
246246
onNavigateToSecurity = { navigateTo(MainDestination.SECURITY) },
247-
onExportData = { /* Will be handled in ProfileViewModel */ },
247+
onExportData = { fileName, data, mimeType ->
248+
com.vaultstadio.app.platform.downloadFile(fileName, data, mimeType)
249+
},
248250
),
249251
)
250252
is Config.Admin -> MainComponent.Child.Admin(

frontend/composeApp/src/main/kotlin/com/vaultstadio/app/feature/shares/SharesComponent.kt

Lines changed: 0 additions & 20 deletions
This file was deleted.

frontend/composeApp/src/main/kotlin/com/vaultstadio/app/feature/sync/SyncComponent.kt

Lines changed: 0 additions & 20 deletions
This file was deleted.

0 commit comments

Comments
 (0)