summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJonatan Rhodin <jonatan.rhodin@mullvad.net>2026-02-13 14:31:01 +0100
committerJonatan Rhodin <jonatan.rhodin@mullvad.net>2026-02-13 14:31:01 +0100
commit46bd6d2d116cf2b6279df738b646d0a11b029cb4 (patch)
treec96e0f81347f6cbe6a314f11db09c3cf555fca2d
parentbd3fc2ac81101df3bd2f52e8a4a2d5400929b20e (diff)
parentc17fd90f2f52acb8724c7bc3ba73ca29e4bfae6a (diff)
downloadmullvadvpn-46bd6d2d116cf2b6279df738b646d0a11b029cb4.tar.xz
mullvadvpn-46bd6d2d116cf2b6279df738b646d0a11b029cb4.zip
Merge branch 'refactor-connect-login-account'
-rw-r--r--android/app/build.gradle.kts5
-rw-r--r--android/app/src/main/AndroidManifest.xml2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/MullvadApplication.kt8
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ExternalActionButton.kt74
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/MullvadSegmentedButton.kt121
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SelectObfuscationCellPreviewParameterProvider.kt23
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/ShadowsocksSettingsUiStatePreviewParameterProvider.kt18
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/MullvadApp.kt38
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/PrivacyDisclaimerScreen.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplashScreen.kt8
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/ConnectNotificationState.kt1
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/ShadowsocksSettingsUiState.kt11
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/util/Navigation.kt17
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/AppModule.kt12
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt30
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/receiver/ScheduleNotificationBootCompletedReceiver.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt2
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/notification/StatusLevel.kt7
-rw-r--r--android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManager.kt1
-rw-r--r--android/lib/common-compose/src/main/kotlin/net/mullvad/mullvadvpn/common/compose/Keyboard.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/util/Keyboard.kt)2
-rw-r--r--android/lib/common-compose/src/main/kotlin/net/mullvad/mullvadvpn/common/compose/Shared.kt10
-rw-r--r--android/lib/common/src/main/kotlin/net/mullvad/mullvadvpn/lib/common/serviceconnection/EmptyServiceConnection.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/EmptyServiceConnection.kt)2
-rw-r--r--android/lib/common/src/main/kotlin/net/mullvad/mullvadvpn/lib/common/util/CreateVpnProfile.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/util/CreateVpnProfile.kt)2
-rw-r--r--android/lib/feature/account/impl/build.gradle.kts29
-rw-r--r--android/lib/feature/account/impl/src/androidTest/kotlin/net/mullvad/mullvadvpn/feature/account/impl/AccountScreenTest.kt (renamed from android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreenTest.kt)3
-rw-r--r--android/lib/feature/account/impl/src/main/AndroidManifest.xml4
-rw-r--r--android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/AccountNumberView.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/AccountNumberView.kt)2
-rw-r--r--android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/AccountScreen.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreen.kt)22
-rw-r--r--android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/AccountUiStatePreviewParameterProvider.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/AccountUiStatePreviewParameterProvider.kt)3
-rw-r--r--android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/AccountViewModel.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModel.kt)2
-rw-r--r--android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/AnimatedIconButton.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/AnimatedIconButton.kt)2
-rw-r--r--android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/CopyableObfuscationView.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/CopyableObfuscationView.kt)4
-rw-r--r--android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/InformationView.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/InformationView.kt)2
-rw-r--r--android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/Text.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/Text.kt)2
-rw-r--r--android/lib/feature/account/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/account/impl/AccountViewModelTest.kt (renamed from android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt)4
-rw-r--r--android/lib/feature/home/impl/build.gradle.kts51
-rw-r--r--android/lib/feature/home/impl/src/androidTest/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectScreenTest.kt (renamed from android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreenTest.kt)3
-rw-r--r--android/lib/feature/home/impl/src/androidTest/kotlin/net/mullvad/mullvadvpn/feature/home/impl/devicerevoked/DeviceRevokedScreenTest.kt (renamed from android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreenTest.kt)3
-rw-r--r--android/lib/feature/home/impl/src/androidTest/kotlin/net/mullvad/mullvadvpn/feature/home/impl/outoftime/OutOfTimeScreenTest.kt (renamed from android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreenTest.kt)3
-rw-r--r--android/lib/feature/home/impl/src/androidTest/kotlin/net/mullvad/mullvadvpn/feature/home/impl/welcome/WelcomeScreenTest.kt (renamed from android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreenTest.kt)3
-rw-r--r--android/lib/feature/home/impl/src/main/AndroidManifest.xml4
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/HomeTransition.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/transitions/HomeTransition.kt)7
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/TunnelStatePreviewData.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/TunnelStatePreviewData.kt)2
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/Android16UpgradeWarningInfoDialog.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/info/Android16UpgradeWarningInfoDialog.kt)8
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectScreen.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt)49
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectUiState.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/ConnectUiState.kt)2
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectUiStatePreviewParameterProvider.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/ConnectUiStatePreviewParameterProvider.kt)4
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectViewModel.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModel.kt)9
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectionStatusText.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/ConnectionStatusText.kt)5
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/TunnelStatePreviewParameterProvider.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/TunnelStatePreviewParameterProvider.kt)12
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/button/ConnectionButton.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ConnectionButton.kt)6
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/button/SwitchLocationButton.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/SwitchLocationButton.kt)4
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/connectioninfo/ConnectionDetailPanel.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/connectioninfo/ConnectionDetailPanel.kt)6
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/connectioninfo/ConnectionInfoHeader.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/connectioninfo/ConnectionInfoHeader.kt)2
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/connectioninfo/FeatureIndicatorsPanel.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/connectioninfo/FeatureIndicatorsPanel.kt)8
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/notificationbanner/InAppNotificationController.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/InAppNotificationController.kt)2
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/notificationbanner/NotificationBanner.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/notificationbanner/NotificationBanner.kt)2
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/devicerevoked/DeviceRevokedLoginButton.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/DeviceRevokedLoginButton.kt)5
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/devicerevoked/DeviceRevokedScreen.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreen.kt)22
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/devicerevoked/DeviceRevokedUiState.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/DeviceRevokedUiState.kt)2
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/devicerevoked/DeviceRevokedUiStatePreviewParameterProvider.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/DeviceRevokedUiStatePreviewParameterProvider.kt)3
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/devicerevoked/DeviceRevokedViewModel.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceRevokedViewModel.kt)7
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/outoftime/OutOfTimeScreen.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreen.kt)24
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/outoftime/OutOfTimeScreenPreviewParameterProvider.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/OutOfTimeScreenPreviewParameterProvider.kt)9
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/outoftime/OutOfTimeUiState.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/OutOfTimeUiState.kt)2
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/outoftime/OutOfTimeViewModel.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/OutOfTimeViewModel.kt)3
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/welcome/DeviceNameInfoDialog.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/info/DeviceNameInfoDialog.kt)8
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/welcome/WelcomeScreen.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreen.kt)28
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/welcome/WelcomeScreenUiStatePreviewParameterProvider.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/WelcomeScreenUiStatePreviewParameterProvider.kt)4
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/welcome/WelcomeUiState.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/WelcomeUiState.kt)2
-rw-r--r--android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/welcome/WelcomeViewModel.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModel.kt)3
-rw-r--r--android/lib/feature/home/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectViewModelTest.kt (renamed from android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModelTest.kt)13
-rw-r--r--android/lib/feature/home/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/notificationbanner/InAppNotificationControllerTest.kt (renamed from android/app/src/test/kotlin/net/mullvad/mullvadvpn/InAppNotificationControllerTest.kt)3
-rw-r--r--android/lib/feature/home/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/home/impl/data/AccountData.kt12
-rw-r--r--android/lib/feature/home/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/home/impl/devicerevoked/DeviceRevokedViewModelTest.kt (renamed from android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceRevokedViewModelTest.kt)9
-rw-r--r--android/lib/feature/home/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/home/impl/outoftime/OutOfTimeViewModelTest.kt (renamed from android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/OutOfTimeViewModelTest.kt)10
-rw-r--r--android/lib/feature/home/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/home/impl/welcome/WelcomeViewModelTest.kt (renamed from android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModelTest.kt)12
-rw-r--r--android/lib/feature/location/impl/build.gradle.kts30
-rw-r--r--android/lib/feature/location/impl/src/androidTest/kotlin/net/mullvad/mullvadvpn/feature/location/impl/SelectLocationScreenTest.kt (renamed from android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationScreenTest.kt)14
-rw-r--r--android/lib/feature/location/impl/src/androidTest/kotlin/net/mullvad/mullvadvpn/feature/location/impl/search/SearchLocationScreenTest.kt (renamed from android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SearchLocationScreenTest.kt)5
-rw-r--r--android/lib/feature/location/impl/src/main/AndroidManifest.xml4
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/ContentType.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/constant/ContentType.kt)2
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/CustomListEdit.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/CustomListEdit.kt)2
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/EmptyRelayListText.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/EmptyRelayListText.kt)3
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/Expand.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/Expand.kt)3
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/FilterRow.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/FilterRow.kt)3
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/RelayListContent.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/RelayListContent.kt)30
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/RelayListScrollConnection.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/RelayListScrollConnection.kt)2
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/SelectLocationScreen.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationScreen.kt)20
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/SelectLocationUiState.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SelectLocationUiState.kt)2
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/SelectLocationViewModel.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationViewModel.kt)5
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/SelectLocationsUiStatePreviewParameterProvider.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SelectLocationsUiStatePreviewParameterProvider.kt)3
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/UndoChangeMultihopAction.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/UndoChangeMultihopAction.kt)2
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/bottomsheet/LocationBottomSheet.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/LocationBottomSheet.kt)9
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/bottomsheet/LocationBottomSheetUiState.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/LocationBottomSheetUiState.kt)2
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/bottomsheet/LocationBottomSheetViewModel.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/LocationBottomSheetViewModel.kt)8
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/list/SelectLocationList.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationList.kt)14
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/list/SelectLocationListUiState.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SelectLocationListUiState.kt)2
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/list/SelectLocationListViewModel.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationListViewModel.kt)14
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/list/SelectLocationsListUiStatePreviewParameterProvider.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SearchLocationsListUiStatePreviewParameterProvider.kt)5
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/search/RelayItemListCreator.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/RelayItemListCreator.kt)2
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/search/SearchLocationScreen.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SearchLocationScreen.kt)28
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/search/SearchLocationUiState.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SearchLocationUiState.kt)2
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/search/SearchLocationViewModel.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SearchLocationViewModel.kt)9
-rw-r--r--android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/search/SearchLocationsUiStatePreviewParameterProvider.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SearchLocationsUiStatePreviewParameterProvider.kt)3
-rw-r--r--android/lib/feature/location/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/location/impl/SelectLocationViewModelTest.kt (renamed from android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationViewModelTest.kt)4
-rw-r--r--android/lib/feature/location/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/location/impl/list/SelectLocationListViewModelTest.kt (renamed from android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationListViewModelTest.kt)12
-rw-r--r--android/lib/feature/location/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/location/impl/search/SearchLocationViewModelTest.kt (renamed from android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SearchLocationViewModelTest.kt)8
-rw-r--r--android/lib/feature/login/impl/build.gradle.kts29
-rw-r--r--android/lib/feature/login/impl/src/main/AndroidManifest.xml4
-rw-r--r--android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/CreateAccountConfirmationDialog.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/CreateAccountConfirmationDialog.kt)7
-rw-r--r--android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/LoginScreen.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt)93
-rw-r--r--android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/LoginUiState.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/LoginUiState.kt)2
-rw-r--r--android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/LoginUiStatePreviewParameterProvider.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/LoginUiStatePreviewParameterProvider.kt)5
-rw-r--r--android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/LoginViewModel.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModel.kt)47
-rw-r--r--android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/apiunreachable/ApiUnreachableInfoDialog.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/info/ApiUnreachableInfoDialog.kt)13
-rw-r--r--android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/apiunreachable/ApiUnreachableUiState.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/ApiUnreachableUiState.kt)4
-rw-r--r--android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/apiunreachable/ApiUnreachableViewModel.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/ApiUnreachableViewModel.kt)6
-rw-r--r--android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/apiunreachable/SendEmail.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/util/SendEmail.kt)2
-rw-r--r--android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/devicelist/DeviceListScreen.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceListScreen.kt)20
-rw-r--r--android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/devicelist/DeviceListUiState.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/DeviceListUiState.kt)2
-rw-r--r--android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/devicelist/DeviceListUiStatePreviewParameterProvider.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/DeviceListUiStatePreviewParameterProvider.kt)5
-rw-r--r--android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/devicelist/DeviceListViewModel.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceListViewModel.kt)6
-rw-r--r--android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/devicelist/DevicePreviewData.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/DevicePreviewData.kt)3
-rw-r--r--android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/devicelist/RemoveDeviceConfirmationDialog.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/RemoveDeviceConfirmationDialog.kt)8
-rw-r--r--android/lib/feature/login/impl/src/test/java/net/mullvad/mullvadvpn/feature/login/impl/DeviceListViewModelTest.kt (renamed from android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceListViewModelTest.kt)10
-rw-r--r--android/lib/feature/login/impl/src/test/java/net/mullvad/mullvadvpn/feature/login/impl/LoginViewModelTest.kt (renamed from android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModelTest.kt)16
-rw-r--r--android/lib/feature/login/impl/src/test/java/net/mullvad/mullvadvpn/feature/login/impl/data/AccountData.kt12
-rw-r--r--android/lib/navigation/src/main/kotlin/net/mullvad/mullvadvpn/core/Navigation.kt (renamed from android/lib/navigation/src/main/java/net/mullvad/mullvadvpn/core/Navigation.kt)0
-rw-r--r--android/lib/navigation/src/main/kotlin/net/mullvad/mullvadvpn/core/animation/AccountTransition.kt (renamed from android/lib/navigation/src/main/java/net/mullvad/mullvadvpn/core/animation/AccountTransition.kt)0
-rw-r--r--android/lib/navigation/src/main/kotlin/net/mullvad/mullvadvpn/core/animation/AnimationConstant.kt (renamed from android/lib/navigation/src/main/java/net/mullvad/mullvadvpn/core/animation/AnimationConstant.kt)0
-rw-r--r--android/lib/navigation/src/main/kotlin/net/mullvad/mullvadvpn/core/animation/DefaultTransition.kt (renamed from android/lib/navigation/src/main/java/net/mullvad/mullvadvpn/core/animation/DefaultTransition.kt)0
-rw-r--r--android/lib/navigation/src/main/kotlin/net/mullvad/mullvadvpn/core/animation/LoginTransition.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/transitions/LoginTransition.kt)17
-rw-r--r--android/lib/navigation/src/main/kotlin/net/mullvad/mullvadvpn/core/animation/SlideInFromRightTransition.kt (renamed from android/lib/navigation/src/main/java/net/mullvad/mullvadvpn/core/animation/SlideInFromRightTransition.kt)0
-rw-r--r--android/lib/navigation/src/main/kotlin/net/mullvad/mullvadvpn/core/animation/TopLevelTransition.kt (renamed from android/lib/navigation/src/main/java/net/mullvad/mullvadvpn/core/animation/TopLevelTransition.kt)0
-rw-r--r--android/lib/push-notification/build.gradle.kts22
-rw-r--r--android/lib/push-notification/src/main/AndroidManifest.xml4
-rw-r--r--android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/NotificationChannelFactory.kt (renamed from android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/NotificationChannelFactory.kt)2
-rw-r--r--android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/NotificationManager.kt (renamed from android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/NotificationManager.kt)8
-rw-r--r--android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/NotificationProvider.kt (renamed from android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/NotificationProvider.kt)2
-rw-r--r--android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/ScheduleNotificationAlarmUseCase.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/ScheduleNotificationAlarmUseCase.kt)4
-rw-r--r--android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/ShouldBeOnForegroundProvider.kt (renamed from android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/ShouldBeOnForegroundProvider.kt)2
-rw-r--r--android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/accountexpiry/AccountExpiryAndroidNotification.kt (renamed from android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/accountexpiry/AccountExpiryAndroidNotification.kt)4
-rw-r--r--android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/accountexpiry/AccountExpiryNotificationProvider.kt (renamed from android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/accountexpiry/AccountExpiryNotificationProvider.kt)4
-rw-r--r--android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/receiver/NotificationAlarmReceiver.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/receiver/NotificationAlarmReceiver.kt)9
-rw-r--r--android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/tunnelstate/TunnelStateNotificationAction.kt (renamed from android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/tunnelstate/TunnelStateNotificationAction.kt)6
-rw-r--r--android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/tunnelstate/TunnelStateNotificationProvider.kt (renamed from android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/tunnelstate/TunnelStateNotificationProvider.kt)6
-rw-r--r--android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/worker/ExpiryNotificationWorker.kt (renamed from android/app/src/main/kotlin/net/mullvad/mullvadvpn/worker/ExpiryNotificationWorker.kt)10
-rw-r--r--android/service/build.gradle.kts1
-rw-r--r--android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt4
-rw-r--r--android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/ForegroundNotificationManager.kt4
-rw-r--r--android/service/src/test/kotlin/net/mullvad/mullvadvpn/service/notifications/tunnelstate/TunnelStateNotificationProviderTest.kt1
-rw-r--r--android/settings.gradle.kts5
153 files changed, 703 insertions, 811 deletions
diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts
index 7f26d4d61c..75a18966f1 100644
--- a/android/app/build.gradle.kts
+++ b/android/app/build.gradle.kts
@@ -387,6 +387,7 @@ dependencies {
implementation(project(":lib:common-compose"))
implementation(projects.lib.grpc)
implementation(projects.lib.endpoint)
+ implementation(projects.lib.feature.account.impl)
implementation(projects.lib.feature.addtime.impl)
implementation(projects.lib.feature.anticensorship.impl)
implementation(projects.lib.feature.apiaccess.impl)
@@ -396,6 +397,9 @@ dependencies {
implementation(projects.lib.feature.customlist.impl)
implementation(projects.lib.feature.daita.impl)
implementation(projects.lib.feature.filter.impl)
+ implementation(projects.lib.feature.home.impl)
+ implementation(projects.lib.feature.location.impl)
+ implementation(projects.lib.feature.login.impl)
implementation(projects.lib.feature.managedevices.impl)
implementation(projects.lib.feature.multihop.impl)
implementation(projects.lib.feature.notification.impl)
@@ -407,6 +411,7 @@ dependencies {
implementation(projects.lib.feature.vpnsettings.impl)
implementation(projects.lib.map)
implementation(projects.lib.model)
+ implementation(projects.lib.pushNotification)
implementation(projects.lib.navigation)
implementation(projects.lib.payment)
implementation(projects.lib.repository)
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index b4fd266f2f..3d5137200e 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -274,7 +274,7 @@
</intent-filter>
</receiver>
<receiver
- android:name=".receiver.NotificationAlarmReceiver"
+ android:name=".lib.pushnotification.receiver.NotificationAlarmReceiver"
android:exported="false" />
<receiver
android:name=".receiver.AutoStartVpnBootCompletedReceiver"
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/MullvadApplication.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/MullvadApplication.kt
index 2fce5e116b..7992d2692f 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/MullvadApplication.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/MullvadApplication.kt
@@ -12,12 +12,12 @@ import kotlinx.coroutines.launch
import net.mullvad.mullvadvpn.di.ApplicationScope
import net.mullvad.mullvadvpn.di.KERMIT_FILE_LOG_DIR_NAME
import net.mullvad.mullvadvpn.di.appModule
+import net.mullvad.mullvadvpn.lib.pushnotification.NotificationChannelFactory
+import net.mullvad.mullvadvpn.lib.pushnotification.NotificationManager
+import net.mullvad.mullvadvpn.lib.pushnotification.ScheduleNotificationAlarmUseCase
+import net.mullvad.mullvadvpn.lib.pushnotification.accountexpiry.AccountExpiryNotificationProvider
import net.mullvad.mullvadvpn.lib.usecase.AccountExpiryNotificationActionUseCase
import net.mullvad.mullvadvpn.lib.usecase.NotificationAction
-import net.mullvad.mullvadvpn.service.notifications.NotificationChannelFactory
-import net.mullvad.mullvadvpn.service.notifications.NotificationManager
-import net.mullvad.mullvadvpn.service.notifications.accountexpiry.AccountExpiryNotificationProvider
-import net.mullvad.mullvadvpn.usecase.ScheduleNotificationAlarmUseCase
import net.mullvad.mullvadvpn.util.FileLogWriter
import org.koin.android.ext.android.getKoin
import org.koin.android.ext.koin.androidContext
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ExternalActionButton.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ExternalActionButton.kt
deleted file mode 100644
index 7b7c092205..0000000000
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ExternalActionButton.kt
+++ /dev/null
@@ -1,74 +0,0 @@
-package net.mullvad.mullvadvpn.compose.button
-
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.automirrored.rounded.OpenInNew
-import androidx.compose.material3.Icon
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.tooling.preview.Preview
-import net.mullvad.mullvadvpn.lib.ui.designsystem.VariantButton
-import net.mullvad.mullvadvpn.lib.ui.theme.AppTheme
-
-@Preview
-@Composable
-private fun PreviewExternalButtonEnabled() {
- AppTheme { ExternalButton(onClick = {}, text = "Button", isEnabled = true) }
-}
-
-@Preview
-@Composable
-private fun PreviewExternalButtonDisabled() {
- AppTheme { ExternalButton(onClick = {}, text = "Button", isEnabled = false) }
-}
-
-@Preview
-@Composable
-private fun PreviewExternalButtonLongText() {
- AppTheme {
- ExternalButton(
- onClick = {},
- text = "Button text is long and is trying to take up space that is large",
- isEnabled = true,
- )
- }
-}
-
-@Preview
-@Composable
-private fun PreviewExternalButtonSpinner() {
- AppTheme {
- ExternalButton(
- onClick = {},
- text = "Button text is long and is trying to take up space that is large",
- isEnabled = true,
- isLoading = true,
- )
- }
-}
-
-@Composable
-fun ExternalButton(
- onClick: () -> Unit,
- text: String,
- modifier: Modifier = Modifier,
- isEnabled: Boolean = true,
- isLoading: Boolean = false,
-) {
- VariantButton(
- text = text,
- onClick = onClick,
- modifier = modifier,
- isEnabled = isEnabled,
- isLoading = isLoading,
- icon = {
- if (!isLoading) {
- Icon(
- imageVector = Icons.AutoMirrored.Rounded.OpenInNew,
- tint = MaterialTheme.colorScheme.onTertiary,
- contentDescription = null,
- )
- }
- },
- )
-}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/MullvadSegmentedButton.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/MullvadSegmentedButton.kt
deleted file mode 100644
index 9a854dc2da..0000000000
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/MullvadSegmentedButton.kt
+++ /dev/null
@@ -1,121 +0,0 @@
-package net.mullvad.mullvadvpn.compose.button
-
-import androidx.compose.foundation.BorderStroke
-import androidx.compose.foundation.shape.RoundedCornerShape
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.SegmentedButton
-import androidx.compose.material3.SegmentedButtonDefaults
-import androidx.compose.material3.SingleChoiceSegmentedButtonRow
-import androidx.compose.material3.SingleChoiceSegmentedButtonRowScope
-import androidx.compose.material3.Text
-import androidx.compose.runtime.Composable
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.graphics.Shape
-import androidx.compose.ui.graphics.compositeOver
-import androidx.compose.ui.text.style.TextAlign
-import androidx.compose.ui.text.style.TextOverflow
-import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.dp
-import net.mullvad.mullvadvpn.lib.ui.theme.AppTheme
-import net.mullvad.mullvadvpn.lib.ui.theme.color.onSelected
-import net.mullvad.mullvadvpn.lib.ui.theme.color.selected
-
-@Preview
-@Composable
-private fun PreviewMullvadSegmentedButton() {
- AppTheme {
- SingleChoiceSegmentedButtonRow {
- MullvadSegmentedStartButton(selected = true, text = "Start", onClick = {})
- MullvadSegmentedMiddleButton(selected = false, text = "Middle", onClick = {})
- MullvadSegmentedEndButton(selected = false, text = "End", onClick = {})
- }
- }
-}
-
-@Composable
-private fun SingleChoiceSegmentedButtonRowScope.MullvadSegmentedButton(
- selected: Boolean,
- text: String,
- onClick: () -> Unit,
- shape: Shape,
- selectedProgress: Float = 1f,
-) {
- SegmentedButton(
- onClick = onClick,
- selected = selected,
- colors =
- SegmentedButtonDefaults.colors()
- .copy(
- activeContainerColor =
- MaterialTheme.colorScheme.selected
- .copy(alpha = selectedProgress)
- .compositeOver(MaterialTheme.colorScheme.primary),
- activeContentColor =
- MaterialTheme.colorScheme.onSelected
- .copy(alpha = selectedProgress)
- .compositeOver(MaterialTheme.colorScheme.onPrimary),
- inactiveContainerColor = MaterialTheme.colorScheme.primary,
- inactiveContentColor = MaterialTheme.colorScheme.onPrimary,
- ),
- border = BorderStroke(0.dp, Color.Unspecified),
- label = {
- Text(
- text = text,
- textAlign = TextAlign.Center,
- style = MaterialTheme.typography.titleMedium,
- maxLines = 1,
- overflow = TextOverflow.Ellipsis,
- )
- },
- icon = {},
- shape = shape,
- )
-}
-
-@Composable
-fun SingleChoiceSegmentedButtonRowScope.MullvadSegmentedStartButton(
- selected: Boolean,
- selectedProgress: Float = 1f,
- text: String,
- onClick: () -> Unit,
-) {
- MullvadSegmentedButton(
- selected = selected,
- selectedProgress = selectedProgress,
- text = text,
- onClick = onClick,
- shape = RoundedCornerShape(topStart = 8.dp, bottomStart = 8.dp),
- )
-}
-
-@Composable
-fun SingleChoiceSegmentedButtonRowScope.MullvadSegmentedMiddleButton(
- selected: Boolean,
- selectedProgress: Float = 1f,
- text: String,
- onClick: () -> Unit,
-) {
- MullvadSegmentedButton(
- selected = selected,
- selectedProgress = selectedProgress,
- text = text,
- onClick = onClick,
- shape = RoundedCornerShape(0.dp), // Square
- )
-}
-
-@Composable
-fun SingleChoiceSegmentedButtonRowScope.MullvadSegmentedEndButton(
- selected: Boolean,
- selectedProgress: Float = 1f,
- text: String,
- onClick: () -> Unit,
-) {
- MullvadSegmentedButton(
- selected = selected,
- selectedProgress = selectedProgress,
- text = text,
- onClick = onClick,
- shape = RoundedCornerShape(topEnd = 8.dp, bottomEnd = 8.dp),
- )
-}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SelectObfuscationCellPreviewParameterProvider.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SelectObfuscationCellPreviewParameterProvider.kt
deleted file mode 100644
index 646d4eb6e4..0000000000
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SelectObfuscationCellPreviewParameterProvider.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package net.mullvad.mullvadvpn.compose.preview
-
-import androidx.compose.ui.tooling.preview.PreviewParameterProvider
-import net.mullvad.mullvadvpn.lib.model.Constraint
-import net.mullvad.mullvadvpn.lib.model.ObfuscationMode
-import net.mullvad.mullvadvpn.lib.model.Port
-
-class SelectObfuscationCellPreviewParameterProvider :
- PreviewParameterProvider<Triple<ObfuscationMode, Constraint<Port>, Boolean>> {
- override val values: Sequence<Triple<ObfuscationMode, Constraint<Port>, Boolean>> =
- sequenceOf(
- Triple(ObfuscationMode.Shadowsocks, Constraint.Any, false),
- Triple(ObfuscationMode.Shadowsocks, Constraint.Any, true),
- Triple(ObfuscationMode.Shadowsocks, Constraint.Only(Port(PORT)), false),
- Triple(ObfuscationMode.Shadowsocks, Constraint.Only(Port(PORT)), true),
- Triple(ObfuscationMode.Udp2Tcp, Constraint.Any, false),
- Triple(ObfuscationMode.Udp2Tcp, Constraint.Any, true),
- Triple(ObfuscationMode.Udp2Tcp, Constraint.Only(Port(PORT)), false),
- Triple(ObfuscationMode.Udp2Tcp, Constraint.Only(Port(PORT)), true),
- )
-}
-
-private const val PORT = 44
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/ShadowsocksSettingsUiStatePreviewParameterProvider.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/ShadowsocksSettingsUiStatePreviewParameterProvider.kt
deleted file mode 100644
index c01a12f0f6..0000000000
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/ShadowsocksSettingsUiStatePreviewParameterProvider.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package net.mullvad.mullvadvpn.compose.preview
-
-import androidx.compose.ui.tooling.preview.PreviewParameterProvider
-import net.mullvad.mullvadvpn.compose.state.ShadowsocksSettingsUiState
-import net.mullvad.mullvadvpn.lib.common.Lc
-import net.mullvad.mullvadvpn.lib.common.toLc
-import net.mullvad.mullvadvpn.lib.model.Constraint
-import net.mullvad.mullvadvpn.lib.model.Port
-
-class ShadowsocksSettingsUiStatePreviewParameterProvider :
- PreviewParameterProvider<Lc<Unit, ShadowsocksSettingsUiState>> {
- override val values: Sequence<Lc<Unit, ShadowsocksSettingsUiState>> =
- sequenceOf(
- Lc.Loading(Unit),
- ShadowsocksSettingsUiState(port = Constraint.Any).toLc(),
- ShadowsocksSettingsUiState(port = Constraint.Only(Port(1)), customPort = Port(1)).toLc(),
- )
-}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/MullvadApp.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/MullvadApp.kt
index 16d8d2ef8c..8f8bdbfdc8 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/MullvadApp.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/MullvadApp.kt
@@ -1,15 +1,14 @@
+@file:Suppress("MatchingDeclarationName")
+
package net.mullvad.mullvadvpn.compose.screen
-import androidx.compose.animation.AnimatedVisibilityScope
import androidx.compose.animation.ExperimentalSharedTransitionApi
import androidx.compose.animation.SharedTransitionLayout
-import androidx.compose.animation.SharedTransitionScope
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
-import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.semantics.semantics
@@ -20,6 +19,7 @@ import com.ramcosta.composedestinations.DestinationsNavHost
import com.ramcosta.composedestinations.annotation.ExternalDestination
import com.ramcosta.composedestinations.annotation.NavHostGraph
import com.ramcosta.composedestinations.generated.NavGraphs
+import com.ramcosta.composedestinations.generated.account.destinations.AccountDestination
import com.ramcosta.composedestinations.generated.addtime.destinations.VerificationPendingDestination
import com.ramcosta.composedestinations.generated.anticensorship.destinations.AntiCensorshipSettingsDestination
import com.ramcosta.composedestinations.generated.anticensorship.destinations.CustomPortDestination
@@ -47,6 +47,19 @@ import com.ramcosta.composedestinations.generated.daita.destinations.DaitaDirect
import com.ramcosta.composedestinations.generated.daita.destinations.DaitaDirectOnlyInfoDestination
import com.ramcosta.composedestinations.generated.destinations.NoDaemonDestination
import com.ramcosta.composedestinations.generated.filter.destinations.FilterDestination
+import com.ramcosta.composedestinations.generated.home.destinations.Android16UpgradeWarningInfoDestination
+import com.ramcosta.composedestinations.generated.home.destinations.ConnectDestination
+import com.ramcosta.composedestinations.generated.home.destinations.DeviceNameInfoDestination
+import com.ramcosta.composedestinations.generated.home.destinations.DeviceRevokedDestination
+import com.ramcosta.composedestinations.generated.home.destinations.OutOfTimeDestination
+import com.ramcosta.composedestinations.generated.home.destinations.WelcomeDestination
+import com.ramcosta.composedestinations.generated.location.destinations.SearchLocationDestination
+import com.ramcosta.composedestinations.generated.location.destinations.SelectLocationDestination
+import com.ramcosta.composedestinations.generated.login.destinations.ApiUnreachableInfoDestination
+import com.ramcosta.composedestinations.generated.login.destinations.CreateAccountConfirmationDestination
+import com.ramcosta.composedestinations.generated.login.destinations.DeviceListDestination
+import com.ramcosta.composedestinations.generated.login.destinations.LoginDestination
+import com.ramcosta.composedestinations.generated.login.destinations.RemoveDeviceConfirmationDestination
import com.ramcosta.composedestinations.generated.managedevices.destinations.ManageDevicesDestination
import com.ramcosta.composedestinations.generated.managedevices.destinations.ManageDevicesRemoveConfirmationDestination
import com.ramcosta.composedestinations.generated.multihop.destinations.MultihopDestination
@@ -76,28 +89,30 @@ import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.navigation.dependency
import com.ramcosta.composedestinations.rememberNavHostEngine
import com.ramcosta.composedestinations.utils.rememberDestinationsNavigator
+import net.mullvad.mullvadvpn.common.compose.LocalSharedTransitionScope
import net.mullvad.mullvadvpn.common.compose.accessibilityDataSensitive
import net.mullvad.mullvadvpn.util.BackstackObserver
import net.mullvad.mullvadvpn.viewmodel.DaemonScreenEvent
import net.mullvad.mullvadvpn.viewmodel.MullvadAppViewModel
import org.koin.androidx.compose.koinViewModel
-val LocalNavAnimatedVisibilityScope = compositionLocalOf<AnimatedVisibilityScope?> { null }
-@OptIn(ExperimentalSharedTransitionApi::class)
-val LocalSharedTransitionScope = compositionLocalOf<SharedTransitionScope?> { null }
-
@NavHostGraph
annotation class MainGraph {
+ @ExternalDestination<AccountDestination>
+ @ExternalDestination<Android16UpgradeWarningInfoDestination>
@ExternalDestination<AntiCensorshipSettingsDestination>
@ExternalDestination<ApiAccessListDestination>
@ExternalDestination<ApiAccessMethodDetailsDestination>
@ExternalDestination<ApiAccessMethodInfoDestination>
+ @ExternalDestination<ApiUnreachableInfoDestination>
@ExternalDestination<AppInfoDestination>
@ExternalDestination<AppearanceDestination>
@ExternalDestination<AutoConnectAndLockdownModeDestination>
@ExternalDestination<ChangelogDestination>
+ @ExternalDestination<ConnectDestination>
@ExternalDestination<ConnectOnStartupInfoDestination>
@ExternalDestination<ContentBlockersInfoDestination>
+ @ExternalDestination<CreateAccountConfirmationDestination>
@ExternalDestination<CreateCustomListDestination>
@ExternalDestination<CustomDnsInfoDestination>
@ExternalDestination<CustomListLocationsDestination>
@@ -109,6 +124,9 @@ annotation class MainGraph {
@ExternalDestination<DeleteApiAccessMethodConfirmationDestination>
@ExternalDestination<DeleteCustomListDestination>
@ExternalDestination<DeviceIpInfoDestination>
+ @ExternalDestination<DeviceListDestination>
+ @ExternalDestination<DeviceNameInfoDestination>
+ @ExternalDestination<DeviceRevokedDestination>
@ExternalDestination<DiscardApiAccessChangesDestination>
@ExternalDestination<DiscardChangesDestination>
@ExternalDestination<DnsDestination>
@@ -119,18 +137,23 @@ annotation class MainGraph {
@ExternalDestination<ImportOverridesByTextDestination>
@ExternalDestination<Ipv6InfoDestination>
@ExternalDestination<LocalNetworkSharingInfoDestination>
+ @ExternalDestination<LoginDestination>
@ExternalDestination<MalwareInfoDestination>
@ExternalDestination<ManageDevicesDestination>
@ExternalDestination<ManageDevicesRemoveConfirmationDestination>
@ExternalDestination<MtuDestination>
@ExternalDestination<MultihopDestination>
@ExternalDestination<NotificationSettingsDestination>
+ @ExternalDestination<OutOfTimeDestination>
@ExternalDestination<QuantumResistanceInfoDestination>
@ExternalDestination<RedeemVoucherDestination>
+ @ExternalDestination<RemoveDeviceConfirmationDestination>
@ExternalDestination<ReportProblemDestination>
@ExternalDestination<ReportProblemNoEmailDestination>
@ExternalDestination<ResetServerIpOverridesConfirmationDestination>
@ExternalDestination<SaveApiAccessMethodDestination>
+ @ExternalDestination<SearchLocationDestination>
+ @ExternalDestination<SelectLocationDestination>
@ExternalDestination<SelectPortDestination>
@ExternalDestination<ServerIpOverridesDestination>
@ExternalDestination<ServerIpOverridesInfoDestination>
@@ -139,6 +162,7 @@ annotation class MainGraph {
@ExternalDestination<VerificationPendingDestination>
@ExternalDestination<ViewLogsDestination>
@ExternalDestination<VpnSettingsDestination>
+ @ExternalDestination<WelcomeDestination>
companion object Includes
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/PrivacyDisclaimerScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/PrivacyDisclaimerScreen.kt
index 4a4694c839..0dd1583928 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/PrivacyDisclaimerScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/PrivacyDisclaimerScreen.kt
@@ -33,8 +33,8 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.generated.NavGraphs
-import com.ramcosta.composedestinations.generated.destinations.LoginDestination
import com.ramcosta.composedestinations.generated.destinations.SplashDestination
+import com.ramcosta.composedestinations.generated.login.destinations.LoginDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.launch
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplashScreen.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplashScreen.kt
index 827a280190..a57e59f5cb 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplashScreen.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/SplashScreen.kt
@@ -19,11 +19,11 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.generated.NavGraphs
-import com.ramcosta.composedestinations.generated.destinations.ConnectDestination
-import com.ramcosta.composedestinations.generated.destinations.DeviceRevokedDestination
-import com.ramcosta.composedestinations.generated.destinations.LoginDestination
-import com.ramcosta.composedestinations.generated.destinations.OutOfTimeDestination
import com.ramcosta.composedestinations.generated.destinations.PrivacyDisclaimerDestination
+import com.ramcosta.composedestinations.generated.home.destinations.ConnectDestination
+import com.ramcosta.composedestinations.generated.home.destinations.DeviceRevokedDestination
+import com.ramcosta.composedestinations.generated.home.destinations.OutOfTimeDestination
+import com.ramcosta.composedestinations.generated.login.destinations.LoginDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.common.compose.CollectSideEffectWithLifecycle
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/ConnectNotificationState.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/ConnectNotificationState.kt
deleted file mode 100644
index 8439680500..0000000000
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/ConnectNotificationState.kt
+++ /dev/null
@@ -1 +0,0 @@
-package net.mullvad.mullvadvpn.compose.state
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/ShadowsocksSettingsUiState.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/ShadowsocksSettingsUiState.kt
deleted file mode 100644
index 351f7e1e02..0000000000
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/ShadowsocksSettingsUiState.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package net.mullvad.mullvadvpn.compose.state
-
-import net.mullvad.mullvadvpn.lib.model.Constraint
-import net.mullvad.mullvadvpn.lib.model.Port
-
-data class ShadowsocksSettingsUiState(
- val port: Constraint<Port> = Constraint.Any,
- val customPort: Port? = null,
-) {
- val isCustom = port is Constraint.Only && port.value == customPort
-}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/util/Navigation.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/util/Navigation.kt
deleted file mode 100644
index 0d08e331e9..0000000000
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/util/Navigation.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package net.mullvad.mullvadvpn.compose.util
-
-import androidx.compose.runtime.Composable
-import androidx.compose.runtime.DisallowComposableCalls
-import com.ramcosta.composedestinations.result.NavResult
-import com.ramcosta.composedestinations.result.ResultRecipient
-import com.ramcosta.composedestinations.spec.DestinationSpec
-
-@Composable
-fun <D : DestinationSpec, V> ResultRecipient<D, V>.OnNavResultValue(
- onValue: @DisallowComposableCalls (value: V) -> Unit
-) = onNavResult {
- when (it) {
- NavResult.Canceled -> Unit
- is NavResult.Value -> onValue(it.value)
- }
-}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/AppModule.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/AppModule.kt
index 32855e88f6..e8f66b9518 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/AppModule.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/AppModule.kt
@@ -16,6 +16,12 @@ import net.mullvad.mullvadvpn.lib.endpoint.ApiEndpointOverride
import net.mullvad.mullvadvpn.lib.grpc.ManagementService
import net.mullvad.mullvadvpn.lib.model.BuildVersion
import net.mullvad.mullvadvpn.lib.model.NotificationChannel
+import net.mullvad.mullvadvpn.lib.pushnotification.NotificationChannelFactory
+import net.mullvad.mullvadvpn.lib.pushnotification.NotificationManager
+import net.mullvad.mullvadvpn.lib.pushnotification.NotificationProvider
+import net.mullvad.mullvadvpn.lib.pushnotification.ScheduleNotificationAlarmUseCase
+import net.mullvad.mullvadvpn.lib.pushnotification.accountexpiry.AccountExpiryNotificationProvider
+import net.mullvad.mullvadvpn.lib.pushnotification.tunnelstate.TunnelStateNotificationProvider
import net.mullvad.mullvadvpn.lib.repository.AccountRepository
import net.mullvad.mullvadvpn.lib.repository.AppObfuscationRepository
import net.mullvad.mullvadvpn.lib.repository.ConnectionProxy
@@ -27,12 +33,6 @@ import net.mullvad.mullvadvpn.lib.repository.UserPreferencesRepository
import net.mullvad.mullvadvpn.lib.repository.UserPreferencesSerializer
import net.mullvad.mullvadvpn.lib.usecase.AccountExpiryNotificationActionUseCase
import net.mullvad.mullvadvpn.repository.UserPreferences
-import net.mullvad.mullvadvpn.service.notifications.NotificationChannelFactory
-import net.mullvad.mullvadvpn.service.notifications.NotificationManager
-import net.mullvad.mullvadvpn.service.notifications.NotificationProvider
-import net.mullvad.mullvadvpn.service.notifications.accountexpiry.AccountExpiryNotificationProvider
-import net.mullvad.mullvadvpn.service.notifications.tunnelstate.TunnelStateNotificationProvider
-import net.mullvad.mullvadvpn.usecase.ScheduleNotificationAlarmUseCase
import org.koin.android.ext.koin.androidContext
import org.koin.core.module.dsl.createdAtStart
import org.koin.core.module.dsl.withOptions
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt
index ae91016f73..d1c7649436 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/di/UiModule.kt
@@ -16,17 +16,30 @@ import net.mullvad.mullvadvpn.apiaccess.impl.screen.save.SaveApiAccessMethodView
import net.mullvad.mullvadvpn.appearance.impl.AppearanceViewModel
import net.mullvad.mullvadvpn.appinfo.impl.AppInfoViewModel
import net.mullvad.mullvadvpn.appinfo.impl.changelog.ChangelogViewModel
-import net.mullvad.mullvadvpn.compose.screen.location.LocationBottomSheetState
-import net.mullvad.mullvadvpn.compose.screen.location.RelayListScrollConnection
import net.mullvad.mullvadvpn.customlist.impl.screen.create.CreateCustomListDialogViewModel
import net.mullvad.mullvadvpn.customlist.impl.screen.delete.DeleteCustomListConfirmationViewModel
import net.mullvad.mullvadvpn.customlist.impl.screen.editlist.EditCustomListViewModel
import net.mullvad.mullvadvpn.customlist.impl.screen.editlocations.CustomListLocationsViewModel
import net.mullvad.mullvadvpn.customlist.impl.screen.editname.EditCustomListNameDialogViewModel
import net.mullvad.mullvadvpn.customlist.impl.screen.lists.CustomListsViewModel
+import net.mullvad.mullvadvpn.feature.account.impl.AccountViewModel
import net.mullvad.mullvadvpn.feature.addtime.impl.AddTimeViewModel
import net.mullvad.mullvadvpn.feature.autoconnect.impl.AutoConnectAndLockdownModeViewModel
import net.mullvad.mullvadvpn.feature.daita.impl.DaitaViewModel
+import net.mullvad.mullvadvpn.feature.home.impl.connect.ConnectViewModel
+import net.mullvad.mullvadvpn.feature.home.impl.connect.notificationbanner.InAppNotificationController
+import net.mullvad.mullvadvpn.feature.home.impl.devicerevoked.DeviceRevokedViewModel
+import net.mullvad.mullvadvpn.feature.home.impl.outoftime.OutOfTimeViewModel
+import net.mullvad.mullvadvpn.feature.home.impl.welcome.WelcomeViewModel
+import net.mullvad.mullvadvpn.feature.location.impl.RelayListScrollConnection
+import net.mullvad.mullvadvpn.feature.location.impl.SelectLocationViewModel
+import net.mullvad.mullvadvpn.feature.location.impl.bottomsheet.LocationBottomSheetState
+import net.mullvad.mullvadvpn.feature.location.impl.bottomsheet.LocationBottomSheetViewModel
+import net.mullvad.mullvadvpn.feature.location.impl.list.SelectLocationListViewModel
+import net.mullvad.mullvadvpn.feature.location.impl.search.SearchLocationViewModel
+import net.mullvad.mullvadvpn.feature.login.impl.LoginViewModel
+import net.mullvad.mullvadvpn.feature.login.impl.apiunreachable.ApiUnreachableViewModel
+import net.mullvad.mullvadvpn.feature.login.impl.devicelist.DeviceListViewModel
import net.mullvad.mullvadvpn.feature.managedevices.impl.ManageDevicesViewModel
import net.mullvad.mullvadvpn.feature.notification.impl.NotificationSettingsViewModel
import net.mullvad.mullvadvpn.feature.problemreport.impl.ReportProblemViewModel
@@ -93,27 +106,14 @@ import net.mullvad.mullvadvpn.lib.usecase.inappnotification.TunnelStateNotificat
import net.mullvad.mullvadvpn.lib.usecase.inappnotification.VersionNotificationUseCase
import net.mullvad.mullvadvpn.multihop.impl.MultihopViewModel
import net.mullvad.mullvadvpn.receiver.AutoStartVpnBootCompletedReceiver
-import net.mullvad.mullvadvpn.repository.InAppNotificationController
import net.mullvad.mullvadvpn.serveripoverride.impl.ServerIpOverridesViewModel
import net.mullvad.mullvadvpn.serveripoverride.impl.reset.ResetServerIpOverridesConfirmationViewModel
import net.mullvad.mullvadvpn.ui.MainActivity
import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager
import net.mullvad.mullvadvpn.util.BackstackObserver
-import net.mullvad.mullvadvpn.viewmodel.AccountViewModel
-import net.mullvad.mullvadvpn.viewmodel.ApiUnreachableViewModel
-import net.mullvad.mullvadvpn.viewmodel.ConnectViewModel
-import net.mullvad.mullvadvpn.viewmodel.DeviceListViewModel
-import net.mullvad.mullvadvpn.viewmodel.DeviceRevokedViewModel
-import net.mullvad.mullvadvpn.viewmodel.LoginViewModel
import net.mullvad.mullvadvpn.viewmodel.MullvadAppViewModel
-import net.mullvad.mullvadvpn.viewmodel.OutOfTimeViewModel
import net.mullvad.mullvadvpn.viewmodel.PrivacyDisclaimerViewModel
import net.mullvad.mullvadvpn.viewmodel.SplashViewModel
-import net.mullvad.mullvadvpn.viewmodel.WelcomeViewModel
-import net.mullvad.mullvadvpn.viewmodel.location.LocationBottomSheetViewModel
-import net.mullvad.mullvadvpn.viewmodel.location.SearchLocationViewModel
-import net.mullvad.mullvadvpn.viewmodel.location.SelectLocationListViewModel
-import net.mullvad.mullvadvpn.viewmodel.location.SelectLocationViewModel
import org.apache.commons.validator.routines.InetAddressValidator
import org.koin.android.ext.koin.androidContext
import org.koin.core.module.dsl.viewModel
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/receiver/ScheduleNotificationBootCompletedReceiver.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/receiver/ScheduleNotificationBootCompletedReceiver.kt
index f5a37c86e5..dd745c2ebb 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/receiver/ScheduleNotificationBootCompletedReceiver.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/receiver/ScheduleNotificationBootCompletedReceiver.kt
@@ -4,8 +4,8 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import co.touchlab.kermit.Logger
+import net.mullvad.mullvadvpn.lib.pushnotification.ScheduleNotificationAlarmUseCase
import net.mullvad.mullvadvpn.lib.repository.UserPreferencesRepository
-import net.mullvad.mullvadvpn.usecase.ScheduleNotificationAlarmUseCase
import net.mullvad.mullvadvpn.util.goAsync
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt
index b6af4b4fae..a3ff3255cc 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/MainActivity.kt
@@ -22,10 +22,10 @@ import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import net.mullvad.mullvadvpn.compose.screen.MullvadApp
-import net.mullvad.mullvadvpn.compose.util.CreateVpnProfile
import net.mullvad.mullvadvpn.di.paymentModule
import net.mullvad.mullvadvpn.di.uiModule
import net.mullvad.mullvadvpn.lib.common.constant.KEY_REQUEST_VPN_PROFILE
+import net.mullvad.mullvadvpn.lib.common.util.CreateVpnProfile
import net.mullvad.mullvadvpn.lib.common.util.SdkUtils.requestNotificationPermissionIfMissing
import net.mullvad.mullvadvpn.lib.common.util.prepareVpnSafe
import net.mullvad.mullvadvpn.lib.endpoint.ApiEndpointFromIntentHolder
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/notification/StatusLevel.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/notification/StatusLevel.kt
deleted file mode 100644
index acac4ae7f6..0000000000
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/notification/StatusLevel.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package net.mullvad.mullvadvpn.ui.notification
-
-enum class StatusLevel {
- Error,
- Warning,
- Info,
-}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManager.kt b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManager.kt
index a8e054e00a..ca6f4f9d84 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManager.kt
+++ b/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/ServiceConnectionManager.kt
@@ -7,6 +7,7 @@ import android.content.pm.ServiceInfo
import android.os.Build
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
+import net.mullvad.mullvadvpn.lib.common.serviceconnection.EmptyServiceConnection
import net.mullvad.mullvadvpn.service.MullvadVpnService
class ServiceConnectionManager(private val context: Context) {
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/util/Keyboard.kt b/android/lib/common-compose/src/main/kotlin/net/mullvad/mullvadvpn/common/compose/Keyboard.kt
index ce2e9206cc..85830e6497 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/util/Keyboard.kt
+++ b/android/lib/common-compose/src/main/kotlin/net/mullvad/mullvadvpn/common/compose/Keyboard.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.util
+package net.mullvad.mullvadvpn.common.compose
import android.content.Context
import androidx.compose.ui.text.input.KeyboardType
diff --git a/android/lib/common-compose/src/main/kotlin/net/mullvad/mullvadvpn/common/compose/Shared.kt b/android/lib/common-compose/src/main/kotlin/net/mullvad/mullvadvpn/common/compose/Shared.kt
new file mode 100644
index 0000000000..fe9f0a99de
--- /dev/null
+++ b/android/lib/common-compose/src/main/kotlin/net/mullvad/mullvadvpn/common/compose/Shared.kt
@@ -0,0 +1,10 @@
+package net.mullvad.mullvadvpn.common.compose
+
+import androidx.compose.animation.AnimatedVisibilityScope
+import androidx.compose.animation.ExperimentalSharedTransitionApi
+import androidx.compose.animation.SharedTransitionScope
+import androidx.compose.runtime.compositionLocalOf
+
+val LocalNavAnimatedVisibilityScope = compositionLocalOf<AnimatedVisibilityScope?> { null }
+@OptIn(ExperimentalSharedTransitionApi::class)
+val LocalSharedTransitionScope = compositionLocalOf<SharedTransitionScope?> { null }
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/EmptyServiceConnection.kt b/android/lib/common/src/main/kotlin/net/mullvad/mullvadvpn/lib/common/serviceconnection/EmptyServiceConnection.kt
index 28819f7aa0..b83bfea2e5 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/ui/serviceconnection/EmptyServiceConnection.kt
+++ b/android/lib/common/src/main/kotlin/net/mullvad/mullvadvpn/lib/common/serviceconnection/EmptyServiceConnection.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.ui.serviceconnection
+package net.mullvad.mullvadvpn.lib.common.serviceconnection
import android.content.ComponentName
import android.content.ServiceConnection
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/util/CreateVpnProfile.kt b/android/lib/common/src/main/kotlin/net/mullvad/mullvadvpn/lib/common/util/CreateVpnProfile.kt
index 750ca6485c..2f1b6167d9 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/util/CreateVpnProfile.kt
+++ b/android/lib/common/src/main/kotlin/net/mullvad/mullvadvpn/lib/common/util/CreateVpnProfile.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.util
+package net.mullvad.mullvadvpn.lib.common.util
import android.app.Activity
import android.content.Context
diff --git a/android/lib/feature/account/impl/build.gradle.kts b/android/lib/feature/account/impl/build.gradle.kts
new file mode 100644
index 0000000000..8c99f8daa0
--- /dev/null
+++ b/android/lib/feature/account/impl/build.gradle.kts
@@ -0,0 +1,29 @@
+plugins {
+ alias(libs.plugins.mullvad.android.library)
+ alias(libs.plugins.mullvad.android.library.feature.impl)
+ alias(libs.plugins.mullvad.android.library.compose)
+ alias(libs.plugins.kotlin.android)
+ alias(libs.plugins.kotlin.parcelize)
+ alias(libs.plugins.kotlin.ksp)
+}
+
+android {
+ namespace = "net.mullvad.mullvadvpn.feature.account.impl"
+ ksp { arg("compose-destinations.moduleName", "account") }
+}
+
+dependencies {
+ implementation(projects.lib.repository)
+ implementation(projects.lib.payment)
+ implementation(projects.lib.feature.addtime.impl)
+ implementation(projects.lib.feature.login.impl)
+ implementation(projects.lib.feature.managedevices.impl)
+ implementation(projects.lib.feature.redeemvoucher.impl)
+
+ implementation(libs.koin.compose)
+ implementation(libs.arrow)
+
+ // Destinations
+ implementation(libs.compose.destinations)
+ ksp(libs.compose.destinations.ksp)
+}
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreenTest.kt b/android/lib/feature/account/impl/src/androidTest/kotlin/net/mullvad/mullvadvpn/feature/account/impl/AccountScreenTest.kt
index 6f9ec792d6..dccdd7269b 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreenTest.kt
+++ b/android/lib/feature/account/impl/src/androidTest/kotlin/net/mullvad/mullvadvpn/feature/account/impl/AccountScreenTest.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.screen
+package net.mullvad.mullvadvpn.feature.account.impl
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.ui.test.ExperimentalTestApi
@@ -16,7 +16,6 @@ import net.mullvad.mullvadvpn.lib.common.Lc
import net.mullvad.mullvadvpn.lib.model.AccountNumber
import net.mullvad.mullvadvpn.screen.test.createEdgeToEdgeComposeExtension
import net.mullvad.mullvadvpn.screen.test.setContentWithTheme
-import net.mullvad.mullvadvpn.viewmodel.AccountUiState
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.RegisterExtension
diff --git a/android/lib/feature/account/impl/src/main/AndroidManifest.xml b/android/lib/feature/account/impl/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..8bdb7e14b3
--- /dev/null
+++ b/android/lib/feature/account/impl/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+
+</manifest>
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/AccountNumberView.kt b/android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/AccountNumberView.kt
index bb261acb15..a2e4de851f 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/AccountNumberView.kt
+++ b/android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/AccountNumberView.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.component
+package net.mullvad.mullvadvpn.feature.account.impl
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreen.kt b/android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/AccountScreen.kt
index 59a3391cb7..0c3924c895 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/AccountScreen.kt
+++ b/android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/AccountScreen.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.screen
+package net.mullvad.mullvadvpn.feature.account.impl
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.layout.Arrangement
@@ -35,25 +35,21 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.LayoutDirection
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.compose.dropUnlessResumed
+import androidx.navigation.NavController
import com.ramcosta.composedestinations.annotation.Destination
-import com.ramcosta.composedestinations.generated.NavGraphs
+import com.ramcosta.composedestinations.annotation.ExternalModuleGraph
import com.ramcosta.composedestinations.generated.addtime.destinations.VerificationPendingDestination
-import com.ramcosta.composedestinations.generated.destinations.LoginDestination
+import com.ramcosta.composedestinations.generated.login.destinations.LoginDestination
import com.ramcosta.composedestinations.generated.managedevices.destinations.ManageDevicesDestination
import com.ramcosta.composedestinations.generated.redeemvoucher.destinations.RedeemVoucherDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import java.time.ZonedDateTime
import kotlinx.coroutines.launch
-import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.common.compose.CollectSideEffectWithLifecycle
import net.mullvad.mullvadvpn.common.compose.SecureScreenWhileInView
import net.mullvad.mullvadvpn.common.compose.createCopyToClipboardHandle
import net.mullvad.mullvadvpn.common.compose.createOpenAccountPageHook
import net.mullvad.mullvadvpn.common.compose.showSnackbarImmediately
-import net.mullvad.mullvadvpn.compose.component.CopyableObfuscationView
-import net.mullvad.mullvadvpn.compose.component.InformationView
-import net.mullvad.mullvadvpn.compose.component.MissingPolicy
-import net.mullvad.mullvadvpn.compose.preview.AccountUiStatePreviewParameterProvider
import net.mullvad.mullvadvpn.core.animation.AccountTransition
import net.mullvad.mullvadvpn.feature.addtime.impl.AddTimeBottomSheet
import net.mullvad.mullvadvpn.lib.common.Lc
@@ -65,8 +61,6 @@ import net.mullvad.mullvadvpn.lib.ui.designsystem.PrimaryTextButton
import net.mullvad.mullvadvpn.lib.ui.tag.MANAGE_DEVICES_BUTTON_TEST_TAG
import net.mullvad.mullvadvpn.lib.ui.theme.AppTheme
import net.mullvad.mullvadvpn.lib.ui.theme.Dimens
-import net.mullvad.mullvadvpn.viewmodel.AccountUiState
-import net.mullvad.mullvadvpn.viewmodel.AccountViewModel
import org.koin.androidx.compose.koinViewModel
@OptIn(ExperimentalMaterial3Api::class)
@@ -90,9 +84,9 @@ private fun PreviewAccountScreen(
}
@OptIn(ExperimentalMaterial3Api::class)
-@Destination<MainGraph>(style = AccountTransition::class)
+@Destination<ExternalModuleGraph>(style = AccountTransition::class)
@Composable
-fun Account(navigator: DestinationsNavigator) {
+fun Account(navController: NavController, navigator: DestinationsNavigator) {
val vm = koinViewModel<AccountViewModel>()
val state by vm.uiState.collectAsStateWithLifecycle()
@@ -106,9 +100,9 @@ fun Account(navigator: DestinationsNavigator) {
CollectSideEffectWithLifecycle(vm.uiSideEffect) { sideEffect ->
when (sideEffect) {
AccountViewModel.UiSideEffect.NavigateToLogin -> {
- navigator.navigate(LoginDestination(null)) {
+ navController.navigate(LoginDestination.baseRoute) {
launchSingleTop = true
- popUpTo(NavGraphs.main) { inclusive = true }
+ popUpTo("main") { inclusive = true }
}
}
is AccountViewModel.UiSideEffect.OpenAccountManagementPageInBrowser ->
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/AccountUiStatePreviewParameterProvider.kt b/android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/AccountUiStatePreviewParameterProvider.kt
index ebea5d2266..305f5b0898 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/AccountUiStatePreviewParameterProvider.kt
+++ b/android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/AccountUiStatePreviewParameterProvider.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.preview
+package net.mullvad.mullvadvpn.feature.account.impl
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import java.time.ZonedDateTime
@@ -6,7 +6,6 @@ import java.time.format.DateTimeFormatter
import net.mullvad.mullvadvpn.lib.common.Lc
import net.mullvad.mullvadvpn.lib.common.toLc
import net.mullvad.mullvadvpn.lib.model.AccountNumber
-import net.mullvad.mullvadvpn.viewmodel.AccountUiState
class AccountUiStatePreviewParameterProvider : PreviewParameterProvider<Lc<Unit, AccountUiState>> {
override val values =
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModel.kt b/android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/AccountViewModel.kt
index 33f014a59f..ba7bb84c72 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModel.kt
+++ b/android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/AccountViewModel.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.viewmodel
+package net.mullvad.mullvadvpn.feature.account.impl
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/AnimatedIconButton.kt b/android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/AnimatedIconButton.kt
index dd91846c8c..e0eaaff03f 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/AnimatedIconButton.kt
+++ b/android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/AnimatedIconButton.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.button
+package net.mullvad.mullvadvpn.feature.account.impl
import androidx.compose.animation.AnimatedContent
import androidx.compose.material3.Icon
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/CopyableObfuscationView.kt b/android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/CopyableObfuscationView.kt
index 60f47ab133..41af898a2b 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/CopyableObfuscationView.kt
+++ b/android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/CopyableObfuscationView.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.component
+package net.mullvad.mullvadvpn.feature.account.impl
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
@@ -17,8 +17,6 @@ import androidx.compose.ui.Alignment.Companion.CenterVertically
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
-import net.mullvad.mullvadvpn.R
-import net.mullvad.mullvadvpn.compose.button.AnimatedIconButton
import net.mullvad.mullvadvpn.lib.ui.theme.AppTheme
@Preview
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/InformationView.kt b/android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/InformationView.kt
index e46ca2cd7c..14cf201bb9 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/InformationView.kt
+++ b/android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/InformationView.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.component
+package net.mullvad.mullvadvpn.feature.account.impl
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/Text.kt b/android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/Text.kt
index 17fdc39ae1..333bf95f94 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/Text.kt
+++ b/android/lib/feature/account/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/account/impl/Text.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.component
+package net.mullvad.mullvadvpn.feature.account.impl
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt b/android/lib/feature/account/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/account/impl/AccountViewModelTest.kt
index 8a44c03e36..c94d097e9d 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/AccountViewModelTest.kt
+++ b/android/lib/feature/account/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/account/impl/AccountViewModelTest.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.viewmodel
+package net.mullvad.mullvadvpn.feature.account.impl
import app.cash.turbine.test
import arrow.core.right
@@ -14,7 +14,6 @@ import kotlin.test.assertEquals
import kotlin.test.assertIs
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest
-import net.mullvad.mullvadvpn.data.UUID
import net.mullvad.mullvadvpn.lib.common.Lc
import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule
import net.mullvad.mullvadvpn.lib.model.AccountNumber
@@ -127,5 +126,6 @@ class AccountViewModelTest {
companion object {
private const val DUMMY_DEVICE_NAME = "fake_name"
+ private const val UUID = "12345678-1234-5678-1234-567812345678"
}
}
diff --git a/android/lib/feature/home/impl/build.gradle.kts b/android/lib/feature/home/impl/build.gradle.kts
new file mode 100644
index 0000000000..970ed2cdeb
--- /dev/null
+++ b/android/lib/feature/home/impl/build.gradle.kts
@@ -0,0 +1,51 @@
+plugins {
+ alias(libs.plugins.mullvad.android.library)
+ alias(libs.plugins.mullvad.android.library.feature.impl)
+ alias(libs.plugins.mullvad.android.library.compose)
+ alias(libs.plugins.kotlin.android)
+ alias(libs.plugins.kotlin.parcelize)
+ alias(libs.plugins.kotlin.ksp)
+}
+
+android {
+ namespace = "net.mullvad.mullvadvpn.feature.home.impl"
+ ksp { arg("compose-destinations.moduleName", "home") }
+}
+
+dependencies {
+ implementation(projects.lib.map)
+ implementation(projects.lib.payment)
+ implementation(projects.lib.pushNotification)
+ implementation(projects.lib.repository)
+ implementation(projects.lib.tv)
+ implementation(projects.lib.usecase)
+ implementation(projects.lib.feature.account.impl)
+ implementation(projects.lib.feature.addtime.impl)
+ implementation(projects.lib.feature.anticensorship.impl)
+ implementation(projects.lib.feature.appinfo.impl)
+ implementation(projects.lib.feature.daita.impl)
+ implementation(projects.lib.feature.location.impl)
+ implementation(projects.lib.feature.login.impl)
+ implementation(projects.lib.feature.multihop.impl)
+ implementation(projects.lib.feature.redeemvoucher.impl)
+ implementation(projects.lib.feature.serveripoverride.impl)
+ implementation(projects.lib.feature.settings.impl)
+ implementation(projects.lib.feature.splittunneling.impl)
+ implementation(projects.lib.feature.vpnsettings.impl)
+
+ implementation(libs.androidx.animation)
+ implementation(libs.koin.compose)
+ implementation(libs.arrow)
+ implementation(libs.compose.constrainlayout)
+ implementation(libs.androidx.credentials) {
+ // This dependency adds a lot of unused permissions to the app.
+ // It is not used so let's exclude it.
+ // Unfortunately, this is not possible to do using libs.version.toml
+ // https://github.com/gradle/gradle/issues/26367#issuecomment-2120830998
+ exclude("androidx.biometric", "biometric")
+ }
+
+ // Destinations
+ implementation(libs.compose.destinations)
+ ksp(libs.compose.destinations.ksp)
+}
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreenTest.kt b/android/lib/feature/home/impl/src/androidTest/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectScreenTest.kt
index 3a93a9361a..defb896fd8 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreenTest.kt
+++ b/android/lib/feature/home/impl/src/androidTest/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectScreenTest.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.screen
+package net.mullvad.mullvadvpn.feature.home.impl.connect
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.onNodeWithTag
@@ -13,7 +13,6 @@ import io.mockk.verify
import java.time.Duration
import java.time.Instant
import java.time.ZonedDateTime
-import net.mullvad.mullvadvpn.compose.state.ConnectUiState
import net.mullvad.mullvadvpn.lib.model.ActionAfterDisconnect
import net.mullvad.mullvadvpn.lib.model.ErrorState
import net.mullvad.mullvadvpn.lib.model.ErrorStateCause
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreenTest.kt b/android/lib/feature/home/impl/src/androidTest/kotlin/net/mullvad/mullvadvpn/feature/home/impl/devicerevoked/DeviceRevokedScreenTest.kt
index 159c26e420..8b5c2af47e 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreenTest.kt
+++ b/android/lib/feature/home/impl/src/androidTest/kotlin/net/mullvad/mullvadvpn/feature/home/impl/devicerevoked/DeviceRevokedScreenTest.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.screen
+package net.mullvad.mullvadvpn.feature.home.impl.devicerevoked
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.onNodeWithText
@@ -7,7 +7,6 @@ import de.mannodermaus.junit5.compose.ComposeContext
import io.mockk.MockKAnnotations
import io.mockk.mockk
import io.mockk.verify
-import net.mullvad.mullvadvpn.compose.state.DeviceRevokedUiState
import net.mullvad.mullvadvpn.screen.test.createEdgeToEdgeComposeExtension
import net.mullvad.mullvadvpn.screen.test.setContentWithTheme
import org.junit.jupiter.api.BeforeEach
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreenTest.kt b/android/lib/feature/home/impl/src/androidTest/kotlin/net/mullvad/mullvadvpn/feature/home/impl/outoftime/OutOfTimeScreenTest.kt
index 6941b96c1f..19d0977cb9 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreenTest.kt
+++ b/android/lib/feature/home/impl/src/androidTest/kotlin/net/mullvad/mullvadvpn/feature/home/impl/outoftime/OutOfTimeScreenTest.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.screen
+package net.mullvad.mullvadvpn.feature.home.impl.outoftime
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.onNodeWithContentDescription
@@ -11,7 +11,6 @@ import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import kotlinx.coroutines.flow.MutableStateFlow
-import net.mullvad.mullvadvpn.compose.state.OutOfTimeUiState
import net.mullvad.mullvadvpn.feature.addtime.impl.AddTimeUiState
import net.mullvad.mullvadvpn.feature.addtime.impl.AddTimeViewModel
import net.mullvad.mullvadvpn.lib.common.Lc
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreenTest.kt b/android/lib/feature/home/impl/src/androidTest/kotlin/net/mullvad/mullvadvpn/feature/home/impl/welcome/WelcomeScreenTest.kt
index 11ffab3985..c4553d3193 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreenTest.kt
+++ b/android/lib/feature/home/impl/src/androidTest/kotlin/net/mullvad/mullvadvpn/feature/home/impl/welcome/WelcomeScreenTest.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.screen
+package net.mullvad.mullvadvpn.feature.home.impl.welcome
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.onNodeWithTag
@@ -10,7 +10,6 @@ import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import kotlinx.coroutines.flow.MutableStateFlow
-import net.mullvad.mullvadvpn.compose.state.WelcomeUiState
import net.mullvad.mullvadvpn.feature.addtime.impl.AddTimeUiState
import net.mullvad.mullvadvpn.feature.addtime.impl.AddTimeViewModel
import net.mullvad.mullvadvpn.lib.common.Lc
diff --git a/android/lib/feature/home/impl/src/main/AndroidManifest.xml b/android/lib/feature/home/impl/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..8bdb7e14b3
--- /dev/null
+++ b/android/lib/feature/home/impl/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+
+</manifest>
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/transitions/HomeTransition.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/HomeTransition.kt
index ab837f091d..9a6bfde4c5 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/transitions/HomeTransition.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/HomeTransition.kt
@@ -1,13 +1,12 @@
-package net.mullvad.mullvadvpn.compose.transitions
+package net.mullvad.mullvadvpn.feature.home.impl
import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.fadeIn
import androidx.navigation.NavBackStackEntry
-import com.ramcosta.composedestinations.generated.destinations.LoginDestination
+import com.ramcosta.composedestinations.generated.login.destinations.LoginDestination
import com.ramcosta.composedestinations.spec.DestinationStyle
-import com.ramcosta.composedestinations.utils.destination
// This is used for OutOfTime, Welcome, and Connect destinations.
object HomeTransition : DestinationStyle.Animated() {
@@ -15,7 +14,7 @@ object HomeTransition : DestinationStyle.Animated() {
override val enterTransition:
AnimatedContentTransitionScope<NavBackStackEntry>.() -> EnterTransition =
{
- when (initialState.destination()) {
+ when (initialState.destination) {
LoginDestination -> fadeIn()
else -> EnterTransition.None
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/TunnelStatePreviewData.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/TunnelStatePreviewData.kt
index a35de85e4c..f3dd7f33b6 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/TunnelStatePreviewData.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/TunnelStatePreviewData.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.preview
+package net.mullvad.mullvadvpn.feature.home.impl
import java.net.InetSocketAddress
import net.mullvad.mullvadvpn.lib.model.ActionAfterDisconnect
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/info/Android16UpgradeWarningInfoDialog.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/Android16UpgradeWarningInfoDialog.kt
index 7d3fe27ced..8f56fbae85 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/info/Android16UpgradeWarningInfoDialog.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/Android16UpgradeWarningInfoDialog.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.dialog.info
+package net.mullvad.mullvadvpn.feature.home.impl.connect
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
@@ -7,13 +7,13 @@ import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.tooling.preview.Preview
import com.ramcosta.composedestinations.annotation.Destination
+import com.ramcosta.composedestinations.annotation.ExternalModuleGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.spec.DestinationStyle
-import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.common.compose.clickableAnnotatedString
import net.mullvad.mullvadvpn.common.compose.createCopyToClipboardHandle
-import net.mullvad.mullvadvpn.compose.screen.MainGraph
import net.mullvad.mullvadvpn.lib.ui.component.dialog.InfoDialog
+import net.mullvad.mullvadvpn.lib.ui.resource.R
import net.mullvad.mullvadvpn.lib.ui.theme.AppTheme
@Preview
@@ -22,7 +22,7 @@ private fun PreviewAndroid16UpgradeWarningInfoDialog() {
AppTheme { Android16UpgradeWarningInfoDialog(onDismiss = {}, onClickEmail = {}) }
}
-@Destination<MainGraph>(style = DestinationStyle.Dialog::class)
+@Destination<ExternalModuleGraph>(style = DestinationStyle.Dialog::class)
@Composable
fun Android16UpgradeWarningInfo(navigator: DestinationsNavigator) {
val copyToClipboard = createCopyToClipboardHandle(isSensitive = false)
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectScreen.kt
index 73b229dad2..615f8c0639 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/ConnectScreen.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectScreen.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.screen
+package net.mullvad.mullvadvpn.feature.home.impl.connect
import android.content.res.Resources
import androidx.activity.compose.rememberLauncherForActivityResult
@@ -64,16 +64,17 @@ import androidx.compose.ui.unit.dp
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.compose.dropUnlessResumed
+import androidx.navigation.NavController
import com.ramcosta.composedestinations.annotation.Destination
-import com.ramcosta.composedestinations.generated.NavGraphs
+import com.ramcosta.composedestinations.annotation.ExternalModuleGraph
+import com.ramcosta.composedestinations.generated.account.destinations.AccountDestination
import com.ramcosta.composedestinations.generated.anticensorship.destinations.AntiCensorshipSettingsDestination
import com.ramcosta.composedestinations.generated.appinfo.destinations.ChangelogDestination
import com.ramcosta.composedestinations.generated.daita.destinations.DaitaDestination
-import com.ramcosta.composedestinations.generated.destinations.AccountDestination
-import com.ramcosta.composedestinations.generated.destinations.Android16UpgradeWarningInfoDestination
-import com.ramcosta.composedestinations.generated.destinations.DeviceRevokedDestination
-import com.ramcosta.composedestinations.generated.destinations.OutOfTimeDestination
-import com.ramcosta.composedestinations.generated.destinations.SelectLocationDestination
+import com.ramcosta.composedestinations.generated.home.destinations.Android16UpgradeWarningInfoDestination
+import com.ramcosta.composedestinations.generated.home.destinations.DeviceRevokedDestination
+import com.ramcosta.composedestinations.generated.home.destinations.OutOfTimeDestination
+import com.ramcosta.composedestinations.generated.location.destinations.SelectLocationDestination
import com.ramcosta.composedestinations.generated.multihop.destinations.MultihopDestination
import com.ramcosta.composedestinations.generated.serveripoverride.destinations.ServerIpOverridesDestination
import com.ramcosta.composedestinations.generated.settings.destinations.SettingsDestination
@@ -82,9 +83,9 @@ import com.ramcosta.composedestinations.generated.vpnsettings.destinations.VpnSe
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.result.ResultRecipient
import kotlinx.coroutines.launch
-import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.appinfo.impl.changelog.ChangelogNavArgs
import net.mullvad.mullvadvpn.common.compose.CollectSideEffectWithLifecycle
+import net.mullvad.mullvadvpn.common.compose.LocalNavAnimatedVisibilityScope
import net.mullvad.mullvadvpn.common.compose.SECURE_ZOOM
import net.mullvad.mullvadvpn.common.compose.SECURE_ZOOM_ANIMATION_MILLIS
import net.mullvad.mullvadvpn.common.compose.UNSECURE_ZOOM
@@ -94,18 +95,15 @@ import net.mullvad.mullvadvpn.common.compose.fallbackLatLong
import net.mullvad.mullvadvpn.common.compose.isTv
import net.mullvad.mullvadvpn.common.compose.safeOpenUri
import net.mullvad.mullvadvpn.common.compose.showSnackbarImmediately
-import net.mullvad.mullvadvpn.compose.button.ConnectionButton
-import net.mullvad.mullvadvpn.compose.button.SwitchLocationButton
-import net.mullvad.mullvadvpn.compose.component.ConnectionStatusText
-import net.mullvad.mullvadvpn.compose.component.connectioninfo.ConnectionDetailPanel
-import net.mullvad.mullvadvpn.compose.component.connectioninfo.FeatureIndicatorsPanel
-import net.mullvad.mullvadvpn.compose.component.connectioninfo.toInAddress
-import net.mullvad.mullvadvpn.compose.component.notificationbanner.NotificationBanner
-import net.mullvad.mullvadvpn.compose.preview.ConnectUiStatePreviewParameterProvider
-import net.mullvad.mullvadvpn.compose.state.ConnectUiState
-import net.mullvad.mullvadvpn.compose.transitions.HomeTransition
-import net.mullvad.mullvadvpn.compose.util.CreateVpnProfile
import net.mullvad.mullvadvpn.core.OnNavResultValue
+import net.mullvad.mullvadvpn.feature.home.impl.HomeTransition
+import net.mullvad.mullvadvpn.feature.home.impl.connect.button.ConnectionButton
+import net.mullvad.mullvadvpn.feature.home.impl.connect.button.SwitchLocationButton
+import net.mullvad.mullvadvpn.feature.home.impl.connect.connectioninfo.ConnectionDetailPanel
+import net.mullvad.mullvadvpn.feature.home.impl.connect.connectioninfo.FeatureIndicatorsPanel
+import net.mullvad.mullvadvpn.feature.home.impl.connect.connectioninfo.toInAddress
+import net.mullvad.mullvadvpn.feature.home.impl.connect.notificationbanner.NotificationBanner
+import net.mullvad.mullvadvpn.lib.common.util.CreateVpnProfile
import net.mullvad.mullvadvpn.lib.common.util.openVpnSettings
import net.mullvad.mullvadvpn.lib.common.util.removeHtmlTags
import net.mullvad.mullvadvpn.lib.map.AnimatedMap
@@ -125,6 +123,7 @@ import net.mullvad.mullvadvpn.lib.ui.component.ScaffoldWithTopBarAndDeviceName
import net.mullvad.mullvadvpn.lib.ui.component.drawVerticalScrollbar
import net.mullvad.mullvadvpn.lib.ui.designsystem.MullvadCircularProgressIndicatorLarge
import net.mullvad.mullvadvpn.lib.ui.designsystem.MullvadSnackbar
+import net.mullvad.mullvadvpn.lib.ui.resource.R
import net.mullvad.mullvadvpn.lib.ui.tag.CONNECT_BUTTON_TEST_TAG
import net.mullvad.mullvadvpn.lib.ui.tag.CONNECT_CARD_HEADER_TEST_TAG
import net.mullvad.mullvadvpn.lib.ui.tag.RECONNECT_BUTTON_TEST_TAG
@@ -137,7 +136,6 @@ import net.mullvad.mullvadvpn.lib.ui.theme.color.Alpha80
import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaInvisible
import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaScrollbar
import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaVisible
-import net.mullvad.mullvadvpn.viewmodel.ConnectViewModel
import org.koin.androidx.compose.koinViewModel
private const val CONNECT_BUTTON_THROTTLE_MILLIS = 1000
@@ -175,9 +173,10 @@ private fun PreviewAccountScreen(
}
@Suppress("LongMethod")
-@Destination<MainGraph>(style = HomeTransition::class)
+@Destination<ExternalModuleGraph>(style = HomeTransition::class)
@Composable
fun Connect(
+ navController: NavController,
navigator: DestinationsNavigator,
animatedVisibilityScope: AnimatedVisibilityScope,
selectLocationResultRecipient: ResultRecipient<SelectLocationDestination, Boolean>,
@@ -207,15 +206,15 @@ fun Connect(
openAccountPage(sideEffect.token)
is ConnectViewModel.UiSideEffect.OutOfTime ->
- navigator.navigate(OutOfTimeDestination) {
+ navController.navigate(OutOfTimeDestination.route) {
launchSingleTop = true
- popUpTo(NavGraphs.main) { inclusive = true }
+ popUpTo("main") { inclusive = true }
}
ConnectViewModel.UiSideEffect.RevokedDevice ->
- navigator.navigate(DeviceRevokedDestination) {
+ navController.navigate(DeviceRevokedDestination.route) {
launchSingleTop = true
- popUpTo(NavGraphs.main) { inclusive = true }
+ popUpTo("main") { inclusive = true }
}
is ConnectViewModel.UiSideEffect.NotPrepared ->
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/ConnectUiState.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectUiState.kt
index 956b1506a7..2c97b44f3f 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/ConnectUiState.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectUiState.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.state
+package net.mullvad.mullvadvpn.feature.home.impl.connect
import net.mullvad.mullvadvpn.lib.model.GeoIpLocation
import net.mullvad.mullvadvpn.lib.model.InAppNotification
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/ConnectUiStatePreviewParameterProvider.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectUiStatePreviewParameterProvider.kt
index 0a332ba385..b362099faf 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/ConnectUiStatePreviewParameterProvider.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectUiStatePreviewParameterProvider.kt
@@ -1,8 +1,8 @@
-package net.mullvad.mullvadvpn.compose.preview
+package net.mullvad.mullvadvpn.feature.home.impl.connect
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import java.net.InetAddress
-import net.mullvad.mullvadvpn.compose.state.ConnectUiState
+import net.mullvad.mullvadvpn.feature.home.impl.TunnelStatePreviewData
import net.mullvad.mullvadvpn.lib.model.ActionAfterDisconnect
import net.mullvad.mullvadvpn.lib.model.GeoIpLocation
import net.mullvad.mullvadvpn.lib.model.InAppNotification
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModel.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectViewModel.kt
index 6e5234f09d..0e2c187ecf 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModel.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectViewModel.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.viewmodel
+package net.mullvad.mullvadvpn.feature.home.impl.connect
import android.content.res.Resources
import android.net.Uri
@@ -18,9 +18,8 @@ import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
-import net.mullvad.mullvadvpn.R
-import net.mullvad.mullvadvpn.compose.state.ConnectUiState
import net.mullvad.mullvadvpn.feature.addtime.impl.isSuccess
+import net.mullvad.mullvadvpn.feature.home.impl.connect.notificationbanner.InAppNotificationController
import net.mullvad.mullvadvpn.lib.common.constant.VIEW_MODEL_STOP_TIMEOUT
import net.mullvad.mullvadvpn.lib.common.util.combine
import net.mullvad.mullvadvpn.lib.common.util.daysFromNow
@@ -38,11 +37,11 @@ import net.mullvad.mullvadvpn.lib.repository.DeviceRepository
import net.mullvad.mullvadvpn.lib.repository.NewDeviceRepository
import net.mullvad.mullvadvpn.lib.repository.PaymentLogic
import net.mullvad.mullvadvpn.lib.repository.UserPreferencesRepository
+import net.mullvad.mullvadvpn.lib.ui.resource.R
import net.mullvad.mullvadvpn.lib.usecase.LastKnownLocationUseCase
import net.mullvad.mullvadvpn.lib.usecase.OutOfTimeUseCase
import net.mullvad.mullvadvpn.lib.usecase.SelectedLocationTitleUseCase
import net.mullvad.mullvadvpn.lib.usecase.SystemVpnSettingsAvailableUseCase
-import net.mullvad.mullvadvpn.repository.InAppNotificationController
@Suppress("LongParameterList")
class ConnectViewModel(
@@ -89,6 +88,7 @@ class ConnectViewModel(
when (tunnelState) {
is TunnelState.Disconnected ->
tunnelState.location ?: lastKnownDisconnectedLocation
+
is TunnelState.Connecting -> tunnelState.location
is TunnelState.Connected -> tunnelState.location
is TunnelState.Disconnecting ->
@@ -100,6 +100,7 @@ class ConnectViewModel(
// location
ActionAfterDisconnect.Reconnect -> prevTunnelState?.location()
}
+
is TunnelState.Error -> lastKnownDisconnectedLocation
},
selectedRelayItemTitle =
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/ConnectionStatusText.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectionStatusText.kt
index 43610312c0..347202c39e 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/ConnectionStatusText.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectionStatusText.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.component
+package net.mullvad.mullvadvpn.feature.home.impl.connect
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
@@ -10,10 +10,9 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
-import net.mullvad.mullvadvpn.R
-import net.mullvad.mullvadvpn.compose.preview.TunnelStatePreviewParameterProvider
import net.mullvad.mullvadvpn.lib.model.ActionAfterDisconnect
import net.mullvad.mullvadvpn.lib.model.TunnelState
+import net.mullvad.mullvadvpn.lib.ui.resource.R
import net.mullvad.mullvadvpn.lib.ui.theme.AppTheme
@Preview
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/TunnelStatePreviewParameterProvider.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/TunnelStatePreviewParameterProvider.kt
index f9390e9986..e9bb06d47d 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/TunnelStatePreviewParameterProvider.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/TunnelStatePreviewParameterProvider.kt
@@ -1,11 +1,11 @@
-package net.mullvad.mullvadvpn.compose.preview
+package net.mullvad.mullvadvpn.feature.home.impl.connect
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
-import net.mullvad.mullvadvpn.compose.preview.TunnelStatePreviewData.generateConnectedState
-import net.mullvad.mullvadvpn.compose.preview.TunnelStatePreviewData.generateConnectingState
-import net.mullvad.mullvadvpn.compose.preview.TunnelStatePreviewData.generateDisconnectedState
-import net.mullvad.mullvadvpn.compose.preview.TunnelStatePreviewData.generateDisconnectingState
-import net.mullvad.mullvadvpn.compose.preview.TunnelStatePreviewData.generateErrorState
+import net.mullvad.mullvadvpn.feature.home.impl.TunnelStatePreviewData.generateConnectedState
+import net.mullvad.mullvadvpn.feature.home.impl.TunnelStatePreviewData.generateConnectingState
+import net.mullvad.mullvadvpn.feature.home.impl.TunnelStatePreviewData.generateDisconnectedState
+import net.mullvad.mullvadvpn.feature.home.impl.TunnelStatePreviewData.generateDisconnectingState
+import net.mullvad.mullvadvpn.feature.home.impl.TunnelStatePreviewData.generateErrorState
import net.mullvad.mullvadvpn.lib.model.ActionAfterDisconnect
import net.mullvad.mullvadvpn.lib.model.TunnelState
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ConnectionButton.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/button/ConnectionButton.kt
index cbad605ba5..5611a61e13 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/ConnectionButton.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/button/ConnectionButton.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.button
+package net.mullvad.mullvadvpn.feature.home.impl.connect.button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
@@ -7,10 +7,10 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
-import net.mullvad.mullvadvpn.R
-import net.mullvad.mullvadvpn.compose.preview.TunnelStatePreviewParameterProvider
+import net.mullvad.mullvadvpn.feature.home.impl.connect.TunnelStatePreviewParameterProvider
import net.mullvad.mullvadvpn.lib.model.TunnelState
import net.mullvad.mullvadvpn.lib.ui.designsystem.PrimaryButton
+import net.mullvad.mullvadvpn.lib.ui.resource.R
import net.mullvad.mullvadvpn.lib.ui.theme.AppTheme
@Composable
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/SwitchLocationButton.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/button/SwitchLocationButton.kt
index e26120a906..f30fd345f6 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/SwitchLocationButton.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/button/SwitchLocationButton.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.button
+package net.mullvad.mullvadvpn.feature.home.impl.connect.button
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -32,7 +32,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.constraintlayout.compose.Dimension
-import net.mullvad.mullvadvpn.R
+import net.mullvad.mullvadvpn.lib.ui.resource.R
import net.mullvad.mullvadvpn.lib.ui.theme.AppTheme
import net.mullvad.mullvadvpn.lib.ui.theme.Dimens
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/connectioninfo/ConnectionDetailPanel.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/connectioninfo/ConnectionDetailPanel.kt
index f593b3a632..4473ace88b 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/connectioninfo/ConnectionDetailPanel.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/connectioninfo/ConnectionDetailPanel.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.component.connectioninfo
+package net.mullvad.mullvadvpn.feature.home.impl.connect.connectioninfo
import androidx.compose.animation.AnimatedContent
import androidx.compose.foundation.layout.Box
@@ -15,11 +15,11 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.constraintlayout.compose.ConstraintLayout
import androidx.constraintlayout.compose.Dimension
-import net.mullvad.mullvadvpn.R
-import net.mullvad.mullvadvpn.compose.screen.ConnectionDetails
+import net.mullvad.mullvadvpn.feature.home.impl.connect.ConnectionDetails
import net.mullvad.mullvadvpn.lib.model.TransportProtocol
import net.mullvad.mullvadvpn.lib.model.TunnelEndpoint
import net.mullvad.mullvadvpn.lib.ui.component.SPACE_CHAR
+import net.mullvad.mullvadvpn.lib.ui.resource.R
import net.mullvad.mullvadvpn.lib.ui.tag.LOCATION_INFO_CONNECTION_IN_TEST_TAG
import net.mullvad.mullvadvpn.lib.ui.tag.LOCATION_INFO_CONNECTION_OUT_TEST_TAG
import net.mullvad.mullvadvpn.lib.ui.theme.Dimens
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/connectioninfo/ConnectionInfoHeader.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/connectioninfo/ConnectionInfoHeader.kt
index 49a42ebc9a..c68272a667 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/connectioninfo/ConnectionInfoHeader.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/connectioninfo/ConnectionInfoHeader.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.component.connectioninfo
+package net.mullvad.mullvadvpn.feature.home.impl.connect.connectioninfo
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/connectioninfo/FeatureIndicatorsPanel.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/connectioninfo/FeatureIndicatorsPanel.kt
index b15c8e5473..f41634048b 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/connectioninfo/FeatureIndicatorsPanel.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/connectioninfo/FeatureIndicatorsPanel.kt
@@ -1,7 +1,7 @@
@file:OptIn(ExperimentalSharedTransitionApi::class)
@file:Suppress("DEPRECATION")
-package net.mullvad.mullvadvpn.compose.component.connectioninfo
+package net.mullvad.mullvadvpn.feature.home.impl.connect.connectioninfo
import androidx.compose.animation.ExperimentalSharedTransitionApi
import androidx.compose.animation.core.EaseInQuart
@@ -20,12 +20,12 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
-import net.mullvad.mullvadvpn.R
-import net.mullvad.mullvadvpn.compose.screen.LocalNavAnimatedVisibilityScope
-import net.mullvad.mullvadvpn.compose.screen.LocalSharedTransitionScope
+import net.mullvad.mullvadvpn.common.compose.LocalNavAnimatedVisibilityScope
+import net.mullvad.mullvadvpn.common.compose.LocalSharedTransitionScope
import net.mullvad.mullvadvpn.lib.model.FeatureIndicator
import net.mullvad.mullvadvpn.lib.ui.designsystem.MullvadFeatureChip
import net.mullvad.mullvadvpn.lib.ui.designsystem.MullvadMoreChip
+import net.mullvad.mullvadvpn.lib.ui.resource.R
import net.mullvad.mullvadvpn.lib.ui.theme.Dimens
@Composable
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/InAppNotificationController.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/notificationbanner/InAppNotificationController.kt
index 3a74348e84..1633686c63 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/repository/InAppNotificationController.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/notificationbanner/InAppNotificationController.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.repository
+package net.mullvad.mullvadvpn.feature.home.impl.connect.notificationbanner
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/notificationbanner/NotificationBanner.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/notificationbanner/NotificationBanner.kt
index 67bcb1dfa5..cdc2819d7b 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/notificationbanner/NotificationBanner.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/notificationbanner/NotificationBanner.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.component.notificationbanner
+package net.mullvad.mullvadvpn.feature.home.impl.connect.notificationbanner
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/DeviceRevokedLoginButton.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/devicerevoked/DeviceRevokedLoginButton.kt
index fbf360d3ba..ca86e3ae3e 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/button/DeviceRevokedLoginButton.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/devicerevoked/DeviceRevokedLoginButton.kt
@@ -1,11 +1,10 @@
-package net.mullvad.mullvadvpn.compose.button
+package net.mullvad.mullvadvpn.feature.home.impl.devicerevoked
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
-import net.mullvad.mullvadvpn.R
-import net.mullvad.mullvadvpn.compose.state.DeviceRevokedUiState
import net.mullvad.mullvadvpn.lib.ui.designsystem.NegativeButton
import net.mullvad.mullvadvpn.lib.ui.designsystem.VariantButton
+import net.mullvad.mullvadvpn.lib.ui.resource.R
@Composable
fun DeviceRevokedLoginButton(onClick: () -> Unit, state: DeviceRevokedUiState) {
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreen.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/devicerevoked/DeviceRevokedScreen.kt
index b1c5f491c5..5621faaa11 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceRevokedScreen.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/devicerevoked/DeviceRevokedScreen.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.screen
+package net.mullvad.mullvadvpn.feature.home.impl.devicerevoked
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
@@ -21,23 +21,19 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.compose.dropUnlessResumed
+import androidx.navigation.NavController
import com.ramcosta.composedestinations.annotation.Destination
-import com.ramcosta.composedestinations.generated.NavGraphs
-import com.ramcosta.composedestinations.generated.destinations.LoginDestination
+import com.ramcosta.composedestinations.annotation.ExternalModuleGraph
+import com.ramcosta.composedestinations.generated.login.destinations.LoginDestination
import com.ramcosta.composedestinations.generated.settings.destinations.SettingsDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
-import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.common.compose.CollectSideEffectWithLifecycle
-import net.mullvad.mullvadvpn.compose.button.DeviceRevokedLoginButton
-import net.mullvad.mullvadvpn.compose.preview.DeviceRevokedUiStatePreviewParameterProvider
-import net.mullvad.mullvadvpn.compose.state.DeviceRevokedUiState
import net.mullvad.mullvadvpn.lib.ui.component.ScaffoldWithTopBar
import net.mullvad.mullvadvpn.lib.ui.component.drawVerticalScrollbar
+import net.mullvad.mullvadvpn.lib.ui.resource.R
import net.mullvad.mullvadvpn.lib.ui.theme.AppTheme
import net.mullvad.mullvadvpn.lib.ui.theme.Dimens
import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaScrollbar
-import net.mullvad.mullvadvpn.viewmodel.DeviceRevokedSideEffect
-import net.mullvad.mullvadvpn.viewmodel.DeviceRevokedViewModel
import org.koin.androidx.compose.koinViewModel
@Preview("Secured|Unsecured|Unknown")
@@ -49,9 +45,9 @@ private fun PreviewDeviceRevokedScreen(
AppTheme { DeviceRevokedScreen(state = state, onSettingsClicked = {}, onGoToLoginClicked = {}) }
}
-@Destination<MainGraph>
+@Destination<ExternalModuleGraph>
@Composable
-fun DeviceRevoked(navigator: DestinationsNavigator) {
+fun DeviceRevoked(navController: NavController, navigator: DestinationsNavigator) {
val viewModel = koinViewModel<DeviceRevokedViewModel>()
val state by viewModel.uiState.collectAsStateWithLifecycle()
@@ -59,9 +55,9 @@ fun DeviceRevoked(navigator: DestinationsNavigator) {
CollectSideEffectWithLifecycle(viewModel.uiSideEffect) { sideEffect ->
when (sideEffect) {
DeviceRevokedSideEffect.NavigateToLogin ->
- navigator.navigate(LoginDestination()) {
+ navController.navigate(LoginDestination.baseRoute) {
launchSingleTop = true
- popUpTo(NavGraphs.main) { inclusive = true }
+ popUpTo("main") { inclusive = true }
}
}
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/DeviceRevokedUiState.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/devicerevoked/DeviceRevokedUiState.kt
index 4bc32ae757..9c42c854a6 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/DeviceRevokedUiState.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/devicerevoked/DeviceRevokedUiState.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.state
+package net.mullvad.mullvadvpn.feature.home.impl.devicerevoked
enum class DeviceRevokedUiState {
SECURED,
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/DeviceRevokedUiStatePreviewParameterProvider.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/devicerevoked/DeviceRevokedUiStatePreviewParameterProvider.kt
index 018a160686..a5f8715f62 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/DeviceRevokedUiStatePreviewParameterProvider.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/devicerevoked/DeviceRevokedUiStatePreviewParameterProvider.kt
@@ -1,7 +1,6 @@
-package net.mullvad.mullvadvpn.compose.preview
+package net.mullvad.mullvadvpn.feature.home.impl.devicerevoked
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
-import net.mullvad.mullvadvpn.compose.state.DeviceRevokedUiState
class DeviceRevokedUiStatePreviewParameterProvider :
PreviewParameterProvider<DeviceRevokedUiState> {
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceRevokedViewModel.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/devicerevoked/DeviceRevokedViewModel.kt
index 14a8de9f6b..32888ec86a 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceRevokedViewModel.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/devicerevoked/DeviceRevokedViewModel.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.viewmodel
+package net.mullvad.mullvadvpn.feature.home.impl.devicerevoked
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
@@ -10,12 +10,11 @@ import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
-import net.mullvad.mullvadvpn.compose.state.DeviceRevokedUiState
import net.mullvad.mullvadvpn.lib.common.constant.VIEW_MODEL_STOP_TIMEOUT
+import net.mullvad.mullvadvpn.lib.pushnotification.ScheduleNotificationAlarmUseCase
+import net.mullvad.mullvadvpn.lib.pushnotification.accountexpiry.AccountExpiryNotificationProvider
import net.mullvad.mullvadvpn.lib.repository.AccountRepository
import net.mullvad.mullvadvpn.lib.repository.ConnectionProxy
-import net.mullvad.mullvadvpn.service.notifications.accountexpiry.AccountExpiryNotificationProvider
-import net.mullvad.mullvadvpn.usecase.ScheduleNotificationAlarmUseCase
class DeviceRevokedViewModel(
private val accountRepository: AccountRepository,
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreen.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/outoftime/OutOfTimeScreen.kt
index 41cf615665..9993c06edf 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/OutOfTimeScreen.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/outoftime/OutOfTimeScreen.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.screen
+package net.mullvad.mullvadvpn.feature.home.impl.outoftime
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
@@ -37,32 +37,30 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.compose.dropUnlessResumed
+import androidx.navigation.NavController
import com.ramcosta.composedestinations.annotation.Destination
-import com.ramcosta.composedestinations.generated.NavGraphs
+import com.ramcosta.composedestinations.annotation.ExternalModuleGraph
+import com.ramcosta.composedestinations.generated.account.destinations.AccountDestination
import com.ramcosta.composedestinations.generated.addtime.destinations.VerificationPendingDestination
-import com.ramcosta.composedestinations.generated.destinations.AccountDestination
-import com.ramcosta.composedestinations.generated.destinations.ConnectDestination
+import com.ramcosta.composedestinations.generated.home.destinations.ConnectDestination
import com.ramcosta.composedestinations.generated.redeemvoucher.destinations.RedeemVoucherDestination
import com.ramcosta.composedestinations.generated.settings.destinations.SettingsDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
-import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.common.compose.CollectSideEffectWithLifecycle
import net.mullvad.mullvadvpn.common.compose.createOpenAccountPageHook
import net.mullvad.mullvadvpn.common.compose.showSnackbarImmediately
-import net.mullvad.mullvadvpn.compose.preview.OutOfTimeScreenPreviewParameterProvider
-import net.mullvad.mullvadvpn.compose.state.OutOfTimeUiState
-import net.mullvad.mullvadvpn.compose.transitions.HomeTransition
import net.mullvad.mullvadvpn.feature.addtime.impl.AddTimeBottomSheet
+import net.mullvad.mullvadvpn.feature.home.impl.HomeTransition
import net.mullvad.mullvadvpn.lib.ui.component.ScaffoldWithTopBarAndDeviceName
import net.mullvad.mullvadvpn.lib.ui.component.drawVerticalScrollbar
import net.mullvad.mullvadvpn.lib.ui.designsystem.NegativeButton
import net.mullvad.mullvadvpn.lib.ui.designsystem.VariantButton
+import net.mullvad.mullvadvpn.lib.ui.resource.R
import net.mullvad.mullvadvpn.lib.ui.tag.OUT_OF_TIME_SCREEN_TITLE_TEST_TAG
import net.mullvad.mullvadvpn.lib.ui.tag.PLAY_PAYMENT_INFO_ICON_TEST_TAG
import net.mullvad.mullvadvpn.lib.ui.theme.AppTheme
import net.mullvad.mullvadvpn.lib.ui.theme.Dimens
import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaScrollbar
-import net.mullvad.mullvadvpn.viewmodel.OutOfTimeViewModel
import org.koin.androidx.compose.koinViewModel
@Preview("Disconnected|Connecting|Error")
@@ -83,9 +81,9 @@ private fun PreviewOutOfTimeScreen(
}
}
-@Destination<MainGraph>(style = HomeTransition::class)
+@Destination<ExternalModuleGraph>(style = HomeTransition::class)
@Composable
-fun OutOfTime(navigator: DestinationsNavigator) {
+fun OutOfTime(navController: NavController, navigator: DestinationsNavigator) {
val vm = koinViewModel<OutOfTimeViewModel>()
val state by vm.uiState.collectAsStateWithLifecycle()
@@ -97,9 +95,9 @@ fun OutOfTime(navigator: DestinationsNavigator) {
is OutOfTimeViewModel.UiSideEffect.OpenAccountView ->
openAccountPage(uiSideEffect.token)
OutOfTimeViewModel.UiSideEffect.OpenConnectScreen ->
- navigator.navigate(ConnectDestination) {
+ navController.navigate(ConnectDestination.route) {
launchSingleTop = true
- popUpTo(NavGraphs.main) { inclusive = true }
+ popUpTo("main") { inclusive = true }
}
OutOfTimeViewModel.UiSideEffect.GenericError ->
snackbarHostState.showSnackbarImmediately(
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/OutOfTimeScreenPreviewParameterProvider.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/outoftime/OutOfTimeScreenPreviewParameterProvider.kt
index 91b05970a5..6927199ff2 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/OutOfTimeScreenPreviewParameterProvider.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/outoftime/OutOfTimeScreenPreviewParameterProvider.kt
@@ -1,10 +1,9 @@
-package net.mullvad.mullvadvpn.compose.preview
+package net.mullvad.mullvadvpn.feature.home.impl.outoftime
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
-import net.mullvad.mullvadvpn.compose.preview.TunnelStatePreviewData.generateConnectingState
-import net.mullvad.mullvadvpn.compose.preview.TunnelStatePreviewData.generateDisconnectedState
-import net.mullvad.mullvadvpn.compose.preview.TunnelStatePreviewData.generateErrorState
-import net.mullvad.mullvadvpn.compose.state.OutOfTimeUiState
+import net.mullvad.mullvadvpn.feature.home.impl.TunnelStatePreviewData.generateConnectingState
+import net.mullvad.mullvadvpn.feature.home.impl.TunnelStatePreviewData.generateDisconnectedState
+import net.mullvad.mullvadvpn.feature.home.impl.TunnelStatePreviewData.generateErrorState
class OutOfTimeScreenPreviewParameterProvider : PreviewParameterProvider<OutOfTimeUiState> {
override val values: Sequence<OutOfTimeUiState> =
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/OutOfTimeUiState.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/outoftime/OutOfTimeUiState.kt
index 89708d95eb..993bf60381 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/OutOfTimeUiState.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/outoftime/OutOfTimeUiState.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.state
+package net.mullvad.mullvadvpn.feature.home.impl.outoftime
import net.mullvad.mullvadvpn.lib.model.TunnelState
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/OutOfTimeViewModel.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/outoftime/OutOfTimeViewModel.kt
index 79556f982b..454ca48625 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/OutOfTimeViewModel.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/outoftime/OutOfTimeViewModel.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.viewmodel
+package net.mullvad.mullvadvpn.feature.home.impl.outoftime
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
@@ -13,7 +13,6 @@ import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
-import net.mullvad.mullvadvpn.compose.state.OutOfTimeUiState
import net.mullvad.mullvadvpn.feature.addtime.impl.hasPendingPayment
import net.mullvad.mullvadvpn.feature.addtime.impl.isSuccess
import net.mullvad.mullvadvpn.lib.common.constant.VIEW_MODEL_STOP_TIMEOUT
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/info/DeviceNameInfoDialog.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/welcome/DeviceNameInfoDialog.kt
index 9a8aad66d3..5ff3fd6dda 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/info/DeviceNameInfoDialog.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/welcome/DeviceNameInfoDialog.kt
@@ -1,16 +1,16 @@
-package net.mullvad.mullvadvpn.compose.dialog.info
+package net.mullvad.mullvadvpn.feature.home.impl.welcome
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import androidx.lifecycle.compose.dropUnlessResumed
import com.ramcosta.composedestinations.annotation.Destination
+import com.ramcosta.composedestinations.annotation.ExternalModuleGraph
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.spec.DestinationStyle
-import net.mullvad.mullvadvpn.R
-import net.mullvad.mullvadvpn.compose.screen.MainGraph
import net.mullvad.mullvadvpn.lib.ui.component.dialog.InfoDialog
+import net.mullvad.mullvadvpn.lib.ui.resource.R
-@Destination<MainGraph>(style = DestinationStyle.Dialog::class)
+@Destination<ExternalModuleGraph>(style = DestinationStyle.Dialog::class)
@Composable
fun DeviceNameInfo(navigator: DestinationsNavigator) {
InfoDialog(
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreen.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/welcome/WelcomeScreen.kt
index 7a4348ee81..38ef6721ba 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/WelcomeScreen.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/welcome/WelcomeScreen.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.screen
+package net.mullvad.mullvadvpn.feature.home.impl.welcome
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@@ -43,26 +43,24 @@ import androidx.credentials.exceptions.CreateCredentialException
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.compose.dropUnlessResumed
+import androidx.navigation.NavController
import co.touchlab.kermit.Logger
import com.ramcosta.composedestinations.annotation.Destination
-import com.ramcosta.composedestinations.generated.NavGraphs
+import com.ramcosta.composedestinations.annotation.ExternalModuleGraph
+import com.ramcosta.composedestinations.generated.account.destinations.AccountDestination
import com.ramcosta.composedestinations.generated.addtime.destinations.VerificationPendingDestination
-import com.ramcosta.composedestinations.generated.destinations.AccountDestination
-import com.ramcosta.composedestinations.generated.destinations.ConnectDestination
-import com.ramcosta.composedestinations.generated.destinations.DeviceNameInfoDestination
+import com.ramcosta.composedestinations.generated.home.destinations.ConnectDestination
+import com.ramcosta.composedestinations.generated.home.destinations.DeviceNameInfoDestination
import com.ramcosta.composedestinations.generated.redeemvoucher.destinations.RedeemVoucherDestination
import com.ramcosta.composedestinations.generated.settings.destinations.SettingsDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
-import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.common.compose.CollectSideEffectWithLifecycle
import net.mullvad.mullvadvpn.common.compose.createCopyToClipboardHandle
import net.mullvad.mullvadvpn.common.compose.createOpenAccountPageHook
import net.mullvad.mullvadvpn.common.compose.showSnackbarImmediately
-import net.mullvad.mullvadvpn.compose.component.CopyAnimatedIconButton
-import net.mullvad.mullvadvpn.compose.preview.WelcomeScreenUiStatePreviewParameterProvider
-import net.mullvad.mullvadvpn.compose.state.WelcomeUiState
-import net.mullvad.mullvadvpn.compose.transitions.HomeTransition
+import net.mullvad.mullvadvpn.feature.account.impl.CopyAnimatedIconButton
import net.mullvad.mullvadvpn.feature.addtime.impl.AddTimeBottomSheet
+import net.mullvad.mullvadvpn.feature.home.impl.HomeTransition
import net.mullvad.mullvadvpn.lib.common.Lc
import net.mullvad.mullvadvpn.lib.common.util.groupWithSpaces
import net.mullvad.mullvadvpn.lib.ui.component.ScaffoldWithTopBar
@@ -70,11 +68,11 @@ import net.mullvad.mullvadvpn.lib.ui.component.drawVerticalScrollbar
import net.mullvad.mullvadvpn.lib.ui.designsystem.MullvadCircularProgressIndicatorMedium
import net.mullvad.mullvadvpn.lib.ui.designsystem.NegativeButton
import net.mullvad.mullvadvpn.lib.ui.designsystem.VariantButton
+import net.mullvad.mullvadvpn.lib.ui.resource.R
import net.mullvad.mullvadvpn.lib.ui.tag.PLAY_PAYMENT_INFO_ICON_TEST_TAG
import net.mullvad.mullvadvpn.lib.ui.theme.AppTheme
import net.mullvad.mullvadvpn.lib.ui.theme.Dimens
import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaScrollbar
-import net.mullvad.mullvadvpn.viewmodel.WelcomeViewModel
import org.koin.androidx.compose.koinViewModel
@Preview("Loading|Content|TunnelConnected")
@@ -96,9 +94,9 @@ private fun PreviewWelcomeScreen(
}
}
-@Destination<MainGraph>(style = HomeTransition::class)
+@Destination<ExternalModuleGraph>(style = HomeTransition::class)
@Composable
-fun Welcome(navigator: DestinationsNavigator) {
+fun Welcome(navController: NavController, navigator: DestinationsNavigator) {
val vm = koinViewModel<WelcomeViewModel>()
val state by vm.uiState.collectAsStateWithLifecycle()
@@ -111,9 +109,9 @@ fun Welcome(navigator: DestinationsNavigator) {
when (uiSideEffect) {
is WelcomeViewModel.UiSideEffect.OpenAccountView -> openAccountPage(uiSideEffect.token)
WelcomeViewModel.UiSideEffect.OpenConnectScreen ->
- navigator.navigate(ConnectDestination) {
+ navController.navigate(ConnectDestination.route) {
launchSingleTop = true
- popUpTo(NavGraphs.main) { inclusive = true }
+ popUpTo("main") { inclusive = true }
}
WelcomeViewModel.UiSideEffect.GenericError ->
snackbarHostState.showSnackbarImmediately(
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/WelcomeScreenUiStatePreviewParameterProvider.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/welcome/WelcomeScreenUiStatePreviewParameterProvider.kt
index 129d866daa..4f5ef3745c 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/WelcomeScreenUiStatePreviewParameterProvider.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/welcome/WelcomeScreenUiStatePreviewParameterProvider.kt
@@ -1,7 +1,7 @@
-package net.mullvad.mullvadvpn.compose.preview
+package net.mullvad.mullvadvpn.feature.home.impl.welcome
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
-import net.mullvad.mullvadvpn.compose.state.WelcomeUiState
+import net.mullvad.mullvadvpn.feature.home.impl.TunnelStatePreviewData
import net.mullvad.mullvadvpn.lib.common.Lc
import net.mullvad.mullvadvpn.lib.common.toLc
import net.mullvad.mullvadvpn.lib.model.AccountNumber
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/WelcomeUiState.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/welcome/WelcomeUiState.kt
index 880c2b9dcf..64801e5db8 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/WelcomeUiState.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/welcome/WelcomeUiState.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.state
+package net.mullvad.mullvadvpn.feature.home.impl.welcome
import net.mullvad.mullvadvpn.lib.model.AccountNumber
import net.mullvad.mullvadvpn.lib.model.TunnelState
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModel.kt b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/welcome/WelcomeViewModel.kt
index dd299ba6cc..9ec73dd6fe 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModel.kt
+++ b/android/lib/feature/home/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/home/impl/welcome/WelcomeViewModel.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.viewmodel
+package net.mullvad.mullvadvpn.feature.home.impl.welcome
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
@@ -16,7 +16,6 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
-import net.mullvad.mullvadvpn.compose.state.WelcomeUiState
import net.mullvad.mullvadvpn.feature.addtime.impl.hasPendingPayment
import net.mullvad.mullvadvpn.feature.addtime.impl.isSuccess
import net.mullvad.mullvadvpn.lib.common.Lc
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModelTest.kt b/android/lib/feature/home/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectViewModelTest.kt
index 3956056f48..c1147e9ae7 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/ConnectViewModelTest.kt
+++ b/android/lib/feature/home/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/ConnectViewModelTest.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.viewmodel
+package net.mullvad.mullvadvpn.feature.home.impl.connect
import androidx.lifecycle.viewModelScope
import app.cash.turbine.test
@@ -18,7 +18,7 @@ import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
-import net.mullvad.mullvadvpn.compose.state.ConnectUiState
+import net.mullvad.mullvadvpn.feature.home.impl.connect.notificationbanner.InAppNotificationController
import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule
import net.mullvad.mullvadvpn.lib.model.AccountData
import net.mullvad.mullvadvpn.lib.model.DeviceState
@@ -37,9 +37,6 @@ import net.mullvad.mullvadvpn.lib.usecase.LastKnownLocationUseCase
import net.mullvad.mullvadvpn.lib.usecase.OutOfTimeUseCase
import net.mullvad.mullvadvpn.lib.usecase.SelectedLocationTitleUseCase
import net.mullvad.mullvadvpn.lib.usecase.SystemVpnSettingsAvailableUseCase
-import net.mullvad.mullvadvpn.repository.InAppNotificationController
-import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager
-import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
@@ -47,12 +44,8 @@ import org.junit.jupiter.api.extension.ExtendWith
@ExtendWith(TestCoroutineRule::class)
class ConnectViewModelTest {
-
- private val mockServiceConnectionManager: ServiceConnectionManager = mockk()
private lateinit var viewModel: ConnectViewModel
- private val serviceConnectionState =
- MutableStateFlow<ServiceConnectionState>(ServiceConnectionState.Unbound)
private val accountExpiryState = MutableStateFlow<AccountData?>(null)
private val device = MutableStateFlow<DeviceState?>(null)
private val notifications = MutableStateFlow<List<InAppNotification>>(emptyList())
@@ -96,8 +89,6 @@ class ConnectViewModelTest {
@BeforeEach
fun setup() {
- every { mockServiceConnectionManager.connectionState } returns serviceConnectionState
-
every { mockAccountRepository.accountData } returns accountExpiryState
every { mockDeviceRepository.deviceState } returns device
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/InAppNotificationControllerTest.kt b/android/lib/feature/home/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/notificationbanner/InAppNotificationControllerTest.kt
index 3e4c0be96f..442a2fb661 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/InAppNotificationControllerTest.kt
+++ b/android/lib/feature/home/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/home/impl/connect/notificationbanner/InAppNotificationControllerTest.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn
+package net.mullvad.mullvadvpn.feature.home.impl.connect.notificationbanner
import app.cash.turbine.test
import io.mockk.MockKAnnotations
@@ -21,7 +21,6 @@ import net.mullvad.mullvadvpn.lib.usecase.inappnotification.NewChangelogNotifica
import net.mullvad.mullvadvpn.lib.usecase.inappnotification.NewDeviceNotificationUseCase
import net.mullvad.mullvadvpn.lib.usecase.inappnotification.TunnelStateNotificationUseCase
import net.mullvad.mullvadvpn.lib.usecase.inappnotification.VersionNotificationUseCase
-import net.mullvad.mullvadvpn.repository.InAppNotificationController
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
diff --git a/android/lib/feature/home/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/home/impl/data/AccountData.kt b/android/lib/feature/home/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/home/impl/data/AccountData.kt
new file mode 100644
index 0000000000..121ff29ee4
--- /dev/null
+++ b/android/lib/feature/home/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/home/impl/data/AccountData.kt
@@ -0,0 +1,12 @@
+package net.mullvad.mullvadvpn.feature.home.impl.data
+
+import io.mockk.mockk
+import java.time.ZonedDateTime
+import net.mullvad.mullvadvpn.lib.model.AccountData
+
+fun AccountData.Companion.mock(expiry: ZonedDateTime): AccountData =
+ AccountData(
+ id = mockk(relaxed = true),
+ accountNumber = mockk(relaxed = true),
+ expiryDate = expiry,
+ )
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceRevokedViewModelTest.kt b/android/lib/feature/home/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/home/impl/devicerevoked/DeviceRevokedViewModelTest.kt
index c71a6efa4b..306cc13555 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceRevokedViewModelTest.kt
+++ b/android/lib/feature/home/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/home/impl/devicerevoked/DeviceRevokedViewModelTest.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.viewmodel
+package net.mullvad.mullvadvpn.feature.home.impl.devicerevoked
import app.cash.turbine.test
import arrow.core.right
@@ -10,18 +10,17 @@ import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.mockk
import io.mockk.unmockkAll
+import kotlin.test.assertEquals
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.test.runTest
-import net.mullvad.mullvadvpn.compose.state.DeviceRevokedUiState
import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule
import net.mullvad.mullvadvpn.lib.model.TunnelState
+import net.mullvad.mullvadvpn.lib.pushnotification.ScheduleNotificationAlarmUseCase
+import net.mullvad.mullvadvpn.lib.pushnotification.accountexpiry.AccountExpiryNotificationProvider
import net.mullvad.mullvadvpn.lib.repository.AccountRepository
import net.mullvad.mullvadvpn.lib.repository.ConnectionProxy
-import net.mullvad.mullvadvpn.service.notifications.accountexpiry.AccountExpiryNotificationProvider
-import net.mullvad.mullvadvpn.usecase.ScheduleNotificationAlarmUseCase
import org.junit.jupiter.api.AfterEach
-import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/OutOfTimeViewModelTest.kt b/android/lib/feature/home/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/home/impl/outoftime/OutOfTimeViewModelTest.kt
index 1b46f83870..db018630bd 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/OutOfTimeViewModelTest.kt
+++ b/android/lib/feature/home/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/home/impl/outoftime/OutOfTimeViewModelTest.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.viewmodel
+package net.mullvad.mullvadvpn.feature.home.impl.outoftime
import androidx.lifecycle.viewModelScope
import app.cash.turbine.test
@@ -13,7 +13,6 @@ import kotlin.test.assertIs
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest
-import net.mullvad.mullvadvpn.compose.state.OutOfTimeUiState
import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule
import net.mullvad.mullvadvpn.lib.model.AccountData
import net.mullvad.mullvadvpn.lib.model.DeviceState
@@ -30,8 +29,6 @@ import net.mullvad.mullvadvpn.lib.repository.ConnectionProxy
import net.mullvad.mullvadvpn.lib.repository.DeviceRepository
import net.mullvad.mullvadvpn.lib.repository.PaymentLogic
import net.mullvad.mullvadvpn.lib.usecase.OutOfTimeUseCase
-import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager
-import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
@@ -40,8 +37,6 @@ import org.junit.jupiter.api.extension.ExtendWith
@ExtendWith(TestCoroutineRule::class)
class OutOfTimeViewModelTest {
- private val serviceConnectionStateFlow =
- MutableStateFlow<ServiceConnectionState>(ServiceConnectionState.Unbound)
private val accountExpiryStateFlow = MutableStateFlow<AccountData?>(null)
private val accountStateFlow = MutableStateFlow<DeviceState?>(null)
private val paymentAvailabilityFlow = MutableStateFlow<PaymentAvailability?>(null)
@@ -56,7 +51,6 @@ class OutOfTimeViewModelTest {
private val mockAccountRepository: AccountRepository = mockk(relaxed = true)
private val mockDeviceRepository: DeviceRepository = mockk(relaxed = true)
- private val mockServiceConnectionManager: ServiceConnectionManager = mockk()
private val mockPaymentUseCase: PaymentLogic = mockk(relaxed = true)
private val mockOutOfTimeUseCase: OutOfTimeUseCase = mockk(relaxed = true)
@@ -64,8 +58,6 @@ class OutOfTimeViewModelTest {
@BeforeEach
fun setup() {
- every { mockServiceConnectionManager.connectionState } returns serviceConnectionStateFlow
-
every { mockConnectionProxy.tunnelState } returns tunnelState
every { mockAccountRepository.accountData } returns accountExpiryStateFlow
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModelTest.kt b/android/lib/feature/home/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/home/impl/welcome/WelcomeViewModelTest.kt
index 48361180bd..86aeac41ae 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/WelcomeViewModelTest.kt
+++ b/android/lib/feature/home/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/home/impl/welcome/WelcomeViewModelTest.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.viewmodel
+package net.mullvad.mullvadvpn.feature.home.impl.welcome
import androidx.lifecycle.viewModelScope
import app.cash.turbine.test
@@ -14,8 +14,7 @@ import kotlin.test.assertIs
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest
-import net.mullvad.mullvadvpn.compose.state.WelcomeUiState
-import net.mullvad.mullvadvpn.data.mock
+import net.mullvad.mullvadvpn.feature.home.impl.data.mock
import net.mullvad.mullvadvpn.lib.common.Lc
import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule
import net.mullvad.mullvadvpn.lib.model.AccountData
@@ -34,8 +33,6 @@ import net.mullvad.mullvadvpn.lib.repository.AccountRepository
import net.mullvad.mullvadvpn.lib.repository.ConnectionProxy
import net.mullvad.mullvadvpn.lib.repository.DeviceRepository
import net.mullvad.mullvadvpn.lib.repository.PaymentLogic
-import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionManager
-import net.mullvad.mullvadvpn.ui.serviceconnection.ServiceConnectionState
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
@@ -44,8 +41,6 @@ import org.junit.jupiter.api.extension.ExtendWith
@ExtendWith(TestCoroutineRule::class)
class WelcomeViewModelTest {
- private val serviceConnectionStateFlow =
- MutableStateFlow<ServiceConnectionState>(ServiceConnectionState.Unbound)
private val deviceStateFlow = MutableStateFlow<DeviceState?>(DeviceState.LoggedOut)
private val accountExpiryStateFlow = MutableStateFlow<AccountData?>(null)
private val purchaseResultFlow = MutableStateFlow<PurchaseResult?>(null)
@@ -59,7 +54,6 @@ class WelcomeViewModelTest {
private val mockAccountRepository: AccountRepository = mockk(relaxed = true)
private val mockDeviceRepository: DeviceRepository = mockk(relaxed = true)
- private val mockServiceConnectionManager: ServiceConnectionManager = mockk()
private val mockPaymentUseCase: PaymentLogic = mockk(relaxed = true)
private lateinit var viewModel: WelcomeViewModel
@@ -68,8 +62,6 @@ class WelcomeViewModelTest {
fun setup() {
every { mockDeviceRepository.deviceState } returns deviceStateFlow
- every { mockServiceConnectionManager.connectionState } returns serviceConnectionStateFlow
-
every { mockConnectionProxy.tunnelState } returns tunnelState
every { mockAccountRepository.accountData } returns accountExpiryStateFlow
diff --git a/android/lib/feature/location/impl/build.gradle.kts b/android/lib/feature/location/impl/build.gradle.kts
new file mode 100644
index 0000000000..852dae4b98
--- /dev/null
+++ b/android/lib/feature/location/impl/build.gradle.kts
@@ -0,0 +1,30 @@
+plugins {
+ alias(libs.plugins.mullvad.android.library)
+ alias(libs.plugins.mullvad.android.library.feature.impl)
+ alias(libs.plugins.mullvad.android.library.compose)
+ alias(libs.plugins.kotlin.android)
+ alias(libs.plugins.kotlin.parcelize)
+ alias(libs.plugins.kotlin.ksp)
+}
+
+android {
+ namespace = "net.mullvad.mullvadvpn.feature.location.impl"
+ ksp { arg("compose-destinations.moduleName", "location") }
+}
+
+dependencies {
+ implementation(projects.lib.ui.icon)
+ implementation(projects.lib.repository)
+ implementation(projects.lib.usecase)
+ implementation(projects.lib.feature.customlist.impl)
+ implementation(projects.lib.feature.daita.impl)
+ implementation(projects.lib.feature.filter.impl)
+
+ implementation(libs.compose.constrainlayout)
+ implementation(libs.koin.compose)
+ implementation(libs.arrow)
+
+ // Destinations
+ implementation(libs.compose.destinations)
+ ksp(libs.compose.destinations.ksp)
+}
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationScreenTest.kt b/android/lib/feature/location/impl/src/androidTest/kotlin/net/mullvad/mullvadvpn/feature/location/impl/SelectLocationScreenTest.kt
index 5faaa3d3de..4ac721d03a 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationScreenTest.kt
+++ b/android/lib/feature/location/impl/src/androidTest/kotlin/net/mullvad/mullvadvpn/feature/location/impl/SelectLocationScreenTest.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.screen.location
+package net.mullvad.mullvadvpn.feature.location.impl
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.hasAnyAncestor
@@ -17,10 +17,11 @@ import kotlinx.coroutines.flow.MutableStateFlow
import net.mullvad.mullvadvpn.compose.data.DUMMY_RELAY_COUNTRIES
import net.mullvad.mullvadvpn.compose.data.DUMMY_RELAY_ITEM_CUSTOM_LISTS
import net.mullvad.mullvadvpn.compose.data.createSimpleRelayListItemList
-import net.mullvad.mullvadvpn.compose.state.LocationBottomSheetUiState
-import net.mullvad.mullvadvpn.compose.state.SelectLocationListUiState
-import net.mullvad.mullvadvpn.compose.state.SelectLocationUiState
-import net.mullvad.mullvadvpn.compose.state.SetAsState
+import net.mullvad.mullvadvpn.feature.location.impl.bottomsheet.LocationBottomSheetUiState
+import net.mullvad.mullvadvpn.feature.location.impl.bottomsheet.LocationBottomSheetViewModel
+import net.mullvad.mullvadvpn.feature.location.impl.bottomsheet.SetAsState
+import net.mullvad.mullvadvpn.feature.location.impl.list.SelectLocationListUiState
+import net.mullvad.mullvadvpn.feature.location.impl.list.SelectLocationListViewModel
import net.mullvad.mullvadvpn.lib.common.Lc
import net.mullvad.mullvadvpn.lib.common.Lce
import net.mullvad.mullvadvpn.lib.model.CustomListId
@@ -41,9 +42,6 @@ import net.mullvad.mullvadvpn.onNodeWithTagAndText
import net.mullvad.mullvadvpn.performLongClick
import net.mullvad.mullvadvpn.screen.test.createEdgeToEdgeComposeExtension
import net.mullvad.mullvadvpn.screen.test.setContentWithTheme
-import net.mullvad.mullvadvpn.viewmodel.location.LocationBottomSheetViewModel
-import net.mullvad.mullvadvpn.viewmodel.location.SelectLocationListViewModel
-import net.mullvad.mullvadvpn.viewmodel.location.UndoChangeMultihopAction
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
diff --git a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SearchLocationScreenTest.kt b/android/lib/feature/location/impl/src/androidTest/kotlin/net/mullvad/mullvadvpn/feature/location/impl/search/SearchLocationScreenTest.kt
index 7775b7fcce..936eaa18cf 100644
--- a/android/app/src/androidTest/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SearchLocationScreenTest.kt
+++ b/android/lib/feature/location/impl/src/androidTest/kotlin/net/mullvad/mullvadvpn/feature/location/impl/search/SearchLocationScreenTest.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.screen.location
+package net.mullvad.mullvadvpn.feature.location.impl.search
import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.onNodeWithTag
@@ -10,7 +10,7 @@ import io.mockk.mockk
import io.mockk.unmockkAll
import io.mockk.verify
import net.mullvad.mullvadvpn.compose.data.DUMMY_RELAY_ITEM_CUSTOM_LISTS
-import net.mullvad.mullvadvpn.compose.state.SearchLocationUiState
+import net.mullvad.mullvadvpn.feature.location.impl.UndoChangeMultihopAction
import net.mullvad.mullvadvpn.lib.common.Lce
import net.mullvad.mullvadvpn.lib.model.CustomListId
import net.mullvad.mullvadvpn.lib.model.RelayItem
@@ -23,7 +23,6 @@ import net.mullvad.mullvadvpn.lib.usecase.MultihopChange
import net.mullvad.mullvadvpn.lib.usecase.SelectRelayItemError
import net.mullvad.mullvadvpn.screen.test.createEdgeToEdgeComposeExtension
import net.mullvad.mullvadvpn.screen.test.setContentWithTheme
-import net.mullvad.mullvadvpn.viewmodel.location.UndoChangeMultihopAction
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
diff --git a/android/lib/feature/location/impl/src/main/AndroidManifest.xml b/android/lib/feature/location/impl/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..8bdb7e14b3
--- /dev/null
+++ b/android/lib/feature/location/impl/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+
+</manifest>
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/constant/ContentType.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/ContentType.kt
index 47b6ba7923..e520b095c2 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/constant/ContentType.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/ContentType.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.constant
+package net.mullvad.mullvadvpn.feature.location.impl
// Content types, to improve the ability to reuse views
object ContentType {
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/CustomListEdit.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/CustomListEdit.kt
index f723414ab4..6d7083c63f 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/CustomListEdit.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/CustomListEdit.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.viewmodel.location
+package net.mullvad.mullvadvpn.feature.location.impl
import arrow.core.Either
import arrow.core.getOrElse
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/EmptyRelayListText.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/EmptyRelayListText.kt
index e7aa8ba3d6..a81c150e8e 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/component/EmptyRelayListText.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/EmptyRelayListText.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.component
+package net.mullvad.mullvadvpn.feature.location.impl
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
@@ -8,7 +8,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
-import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.lib.ui.theme.Dimens
@Composable
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/Expand.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/Expand.kt
index 726aa79674..c57ebc3a64 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/Expand.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/Expand.kt
@@ -1,7 +1,8 @@
-package net.mullvad.mullvadvpn.viewmodel.location
+package net.mullvad.mullvadvpn.feature.location.impl
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.update
+import net.mullvad.mullvadvpn.feature.location.impl.search.expandKey
import net.mullvad.mullvadvpn.lib.model.CustomListId
import net.mullvad.mullvadvpn.lib.model.RelayItemId
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/FilterRow.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/FilterRow.kt
index 46285f3eca..6cca9012c7 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/cell/FilterRow.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/FilterRow.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.cell
+package net.mullvad.mullvadvpn.feature.location.impl
import androidx.compose.foundation.background
import androidx.compose.foundation.horizontalScroll
@@ -15,7 +15,6 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
-import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.lib.model.Ownership
import net.mullvad.mullvadvpn.lib.ui.designsystem.MullvadFilterChip
import net.mullvad.mullvadvpn.lib.ui.theme.AppTheme
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/RelayListContent.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/RelayListContent.kt
index e7f5465781..9c6a056d82 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/RelayListContent.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/RelayListContent.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.screen.location
+package net.mullvad.mullvadvpn.feature.location.impl
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
@@ -20,11 +20,7 @@ import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
-import net.mullvad.mullvadvpn.R
-import net.mullvad.mullvadvpn.compose.component.EmptyRelayListText
-import net.mullvad.mullvadvpn.compose.screen.location.LocationBottomSheetState.ShowCustomListsEntryBottomSheet
-import net.mullvad.mullvadvpn.compose.screen.location.LocationBottomSheetState.ShowEditCustomListBottomSheet
-import net.mullvad.mullvadvpn.compose.screen.location.LocationBottomSheetState.ShowLocationBottomSheet
+import net.mullvad.mullvadvpn.feature.location.impl.bottomsheet.LocationBottomSheetState
import net.mullvad.mullvadvpn.lib.model.CustomListId
import net.mullvad.mullvadvpn.lib.model.RelayItem
import net.mullvad.mullvadvpn.lib.model.RelayItemId
@@ -138,7 +134,10 @@ private fun GeoLocationItem(
onClick = { onSelect(listItem.item) },
onLongClick = {
onUpdateBottomSheetState(
- ShowLocationBottomSheet(item = listItem.item, relayListType = relayListType)
+ LocationBottomSheetState.ShowLocationBottomSheet(
+ item = listItem.item,
+ relayListType = relayListType,
+ )
)
},
onToggleExpand = { onToggleExpand(listItem.item.id, null, it) },
@@ -178,11 +177,17 @@ private fun RecentListItem(
when (val entry = listItem.item) {
is RelayItem.CustomList ->
onUpdateBottomSheetState(
- ShowEditCustomListBottomSheet(item = entry, relayListType = relayListType)
+ LocationBottomSheetState.ShowEditCustomListBottomSheet(
+ item = entry,
+ relayListType = relayListType,
+ )
)
is RelayItem.Location ->
onUpdateBottomSheetState(
- ShowLocationBottomSheet(item = entry, relayListType = relayListType)
+ LocationBottomSheetState.ShowLocationBottomSheet(
+ item = entry,
+ relayListType = relayListType,
+ )
)
}
},
@@ -202,7 +207,10 @@ private fun CustomListItem(
onClick = { onSelect(listItem.item) },
onLongClick = {
onUpdateBottomSheetState(
- ShowEditCustomListBottomSheet(item = listItem.item, relayListType = relayListType)
+ LocationBottomSheetState.ShowEditCustomListBottomSheet(
+ item = listItem.item,
+ relayListType = relayListType,
+ )
)
},
onToggleExpand = { onToggleExpand(listItem.item.id, null, it) },
@@ -226,7 +234,7 @@ private fun CustomListEntryItem(
if (listItem.depth == 1) {
{
onUpdateBottomSheetState(
- ShowCustomListsEntryBottomSheet(
+ LocationBottomSheetState.ShowCustomListsEntryBottomSheet(
customListId = listItem.parentId,
item = listItem.item,
relayListType = relayListType,
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/RelayListScrollConnection.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/RelayListScrollConnection.kt
index 1dadd863e5..3811aeabbb 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/RelayListScrollConnection.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/RelayListScrollConnection.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.screen.location
+package net.mullvad.mullvadvpn.feature.location.impl
import kotlinx.coroutines.channels.Channel
import net.mullvad.mullvadvpn.lib.model.RelayItem
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationScreen.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/SelectLocationScreen.kt
index 7f5c1c447d..0c74ee46d5 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationScreen.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/SelectLocationScreen.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.screen.location
+package net.mullvad.mullvadvpn.feature.location.impl
import android.annotation.SuppressLint
import androidx.compose.animation.AnimatedContent
@@ -69,30 +69,31 @@ import androidx.constraintlayout.compose.layoutId
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.compose.dropUnlessResumed
import com.ramcosta.composedestinations.annotation.Destination
+import com.ramcosta.composedestinations.annotation.ExternalModuleGraph
import com.ramcosta.composedestinations.generated.customlist.destinations.CreateCustomListDestination
import com.ramcosta.composedestinations.generated.customlist.destinations.CustomListLocationsDestination
import com.ramcosta.composedestinations.generated.customlist.destinations.CustomListsDestination
import com.ramcosta.composedestinations.generated.customlist.destinations.DeleteCustomListDestination
import com.ramcosta.composedestinations.generated.customlist.destinations.EditCustomListNameDestination
import com.ramcosta.composedestinations.generated.daita.destinations.DaitaDestination
-import com.ramcosta.composedestinations.generated.destinations.SearchLocationDestination
import com.ramcosta.composedestinations.generated.filter.destinations.FilterDestination
+import com.ramcosta.composedestinations.generated.location.destinations.SearchLocationDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.result.ResultBackNavigator
import com.ramcosta.composedestinations.result.ResultRecipient
import com.ramcosta.composedestinations.result.onResult
import kotlin.math.roundToInt
import kotlinx.coroutines.launch
-import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.common.compose.CollectSideEffectWithLifecycle
import net.mullvad.mullvadvpn.common.compose.dropUnlessResumed
import net.mullvad.mullvadvpn.common.compose.isTv
import net.mullvad.mullvadvpn.common.compose.showSnackbarImmediately
-import net.mullvad.mullvadvpn.compose.cell.FilterRow
-import net.mullvad.mullvadvpn.compose.preview.SelectLocationsUiStatePreviewParameterProvider
-import net.mullvad.mullvadvpn.compose.screen.MainGraph
-import net.mullvad.mullvadvpn.compose.state.SelectLocationUiState
import net.mullvad.mullvadvpn.core.animation.TopLevelTransition
+import net.mullvad.mullvadvpn.feature.location.impl.bottomsheet.LocationBottomSheetState
+import net.mullvad.mullvadvpn.feature.location.impl.bottomsheet.LocationBottomSheets
+import net.mullvad.mullvadvpn.feature.location.impl.bottomsheet.OnCustomListNavResult
+import net.mullvad.mullvadvpn.feature.location.impl.bottomsheet.showResultSnackbar
+import net.mullvad.mullvadvpn.feature.location.impl.list.SelectLocationList
import net.mullvad.mullvadvpn.lib.common.Lc
import net.mullvad.mullvadvpn.lib.model.Constraint
import net.mullvad.mullvadvpn.lib.model.CustomListId
@@ -118,9 +119,6 @@ import net.mullvad.mullvadvpn.lib.usecase.FilterChip
import net.mullvad.mullvadvpn.lib.usecase.ModifyMultihopError
import net.mullvad.mullvadvpn.lib.usecase.MultihopChange
import net.mullvad.mullvadvpn.lib.usecase.SelectRelayItemError
-import net.mullvad.mullvadvpn.viewmodel.location.SelectLocationSideEffect
-import net.mullvad.mullvadvpn.viewmodel.location.SelectLocationViewModel
-import net.mullvad.mullvadvpn.viewmodel.location.UndoChangeMultihopAction
import org.koin.androidx.compose.koinViewModel
val SCROLL_COLLAPSE_DISTANCE = 150.dp
@@ -164,7 +162,7 @@ private fun PreviewSelectLocationScreen(
}
@SuppressLint("CheckResult")
-@Destination<MainGraph>(style = TopLevelTransition::class)
+@Destination<ExternalModuleGraph>(style = TopLevelTransition::class)
@Suppress("LongMethod", "CyclomaticComplexMethod")
@Composable
fun SelectLocation(
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SelectLocationUiState.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/SelectLocationUiState.kt
index 22c6effd30..6600618a10 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SelectLocationUiState.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/SelectLocationUiState.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.state
+package net.mullvad.mullvadvpn.feature.location.impl
import net.mullvad.mullvadvpn.lib.model.ErrorStateCause
import net.mullvad.mullvadvpn.lib.model.HopSelection
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationViewModel.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/SelectLocationViewModel.kt
index da613131af..41eb8c522e 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationViewModel.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/SelectLocationViewModel.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.viewmodel.location
+package net.mullvad.mullvadvpn.feature.location.impl
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
@@ -14,9 +14,6 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
-import net.mullvad.mullvadvpn.compose.screen.location.RelayListScrollConnection
-import net.mullvad.mullvadvpn.compose.screen.location.ScrollEvent
-import net.mullvad.mullvadvpn.compose.state.SelectLocationUiState
import net.mullvad.mullvadvpn.lib.common.Lc
import net.mullvad.mullvadvpn.lib.common.constant.VIEW_MODEL_STOP_TIMEOUT
import net.mullvad.mullvadvpn.lib.common.util.combine
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SelectLocationsUiStatePreviewParameterProvider.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/SelectLocationsUiStatePreviewParameterProvider.kt
index 92f2ac162b..02ac2cecb2 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SelectLocationsUiStatePreviewParameterProvider.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/SelectLocationsUiStatePreviewParameterProvider.kt
@@ -1,7 +1,6 @@
-package net.mullvad.mullvadvpn.compose.preview
+package net.mullvad.mullvadvpn.feature.location.impl
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
-import net.mullvad.mullvadvpn.compose.state.SelectLocationUiState
import net.mullvad.mullvadvpn.lib.common.Lc
import net.mullvad.mullvadvpn.lib.common.toLc
import net.mullvad.mullvadvpn.lib.model.HopSelection
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/UndoChangeMultihopAction.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/UndoChangeMultihopAction.kt
index f18d13046d..1365aeb453 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/UndoChangeMultihopAction.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/UndoChangeMultihopAction.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.viewmodel.location
+package net.mullvad.mullvadvpn.feature.location.impl
import net.mullvad.mullvadvpn.lib.model.RelayItemId
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/LocationBottomSheet.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/bottomsheet/LocationBottomSheet.kt
index 444f7b7321..43e78cd327 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/LocationBottomSheet.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/bottomsheet/LocationBottomSheet.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.screen.location
+package net.mullvad.mullvadvpn.feature.location.impl.bottomsheet
import android.content.res.Resources
import androidx.compose.foundation.layout.Column
@@ -42,10 +42,9 @@ import com.ramcosta.composedestinations.result.NavResult
import com.ramcosta.composedestinations.result.ResultRecipient
import com.ramcosta.composedestinations.spec.DestinationSpec
import kotlinx.coroutines.launch
-import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.common.compose.showSnackbarImmediately
-import net.mullvad.mullvadvpn.compose.state.LocationBottomSheetUiState
-import net.mullvad.mullvadvpn.compose.state.SetAsState
+import net.mullvad.mullvadvpn.feature.location.impl.R
+import net.mullvad.mullvadvpn.feature.location.impl.UndoChangeMultihopAction
import net.mullvad.mullvadvpn.lib.common.Lc
import net.mullvad.mullvadvpn.lib.common.util.relaylist.canAddLocation
import net.mullvad.mullvadvpn.lib.model.CustomListId
@@ -66,8 +65,6 @@ import net.mullvad.mullvadvpn.lib.ui.theme.Dimens
import net.mullvad.mullvadvpn.lib.usecase.ModifyMultihopError
import net.mullvad.mullvadvpn.lib.usecase.MultihopChange
import net.mullvad.mullvadvpn.lib.usecase.SelectRelayItemError
-import net.mullvad.mullvadvpn.viewmodel.location.LocationBottomSheetViewModel
-import net.mullvad.mullvadvpn.viewmodel.location.UndoChangeMultihopAction
import org.koin.androidx.compose.koinViewModel
import org.koin.core.parameter.parametersOf
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/LocationBottomSheetUiState.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/bottomsheet/LocationBottomSheetUiState.kt
index ec6e15ac30..26c0a015b7 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/LocationBottomSheetUiState.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/bottomsheet/LocationBottomSheetUiState.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.state
+package net.mullvad.mullvadvpn.feature.location.impl.bottomsheet
import net.mullvad.mullvadvpn.lib.model.CustomListId
import net.mullvad.mullvadvpn.lib.model.CustomListName
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/LocationBottomSheetViewModel.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/bottomsheet/LocationBottomSheetViewModel.kt
index b854a80a8c..81f211150c 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/LocationBottomSheetViewModel.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/bottomsheet/LocationBottomSheetViewModel.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.viewmodel.location
+package net.mullvad.mullvadvpn.feature.location.impl.bottomsheet
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
@@ -12,9 +12,7 @@ import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.take
import kotlinx.coroutines.launch
-import net.mullvad.mullvadvpn.compose.screen.location.LocationBottomSheetState
-import net.mullvad.mullvadvpn.compose.state.LocationBottomSheetUiState
-import net.mullvad.mullvadvpn.compose.state.SetAsState
+import net.mullvad.mullvadvpn.feature.location.impl.UndoChangeMultihopAction
import net.mullvad.mullvadvpn.lib.common.Lc
import net.mullvad.mullvadvpn.lib.common.constant.VIEW_MODEL_STOP_TIMEOUT
import net.mullvad.mullvadvpn.lib.common.util.relaylist.withDescendants
@@ -75,6 +73,7 @@ class LocationBottomSheetViewModel(
),
)
)
+
is LocationBottomSheetState.ShowEditCustomListBottomSheet ->
Lc.Content(
LocationBottomSheetUiState.CustomList(
@@ -91,6 +90,7 @@ class LocationBottomSheetViewModel(
locationBottomSheetState.item.id,
)
)
+
is LocationBottomSheetState.ShowLocationBottomSheet ->
Lc.Content(
LocationBottomSheetUiState.Location(
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationList.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/list/SelectLocationList.kt
index ac3ec1db9f..fb353910ee 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SelectLocationList.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/list/SelectLocationList.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.screen.location
+package net.mullvad.mullvadvpn.feature.location.impl.list
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues
@@ -32,13 +32,13 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import kotlinx.coroutines.flow.first
-import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.common.compose.CollectSideEffectWithLifecycle
import net.mullvad.mullvadvpn.common.compose.animateScrollAndCentralizeItem
import net.mullvad.mullvadvpn.common.compose.animateScrollCentralizeItem
-import net.mullvad.mullvadvpn.compose.constant.ContentType
-import net.mullvad.mullvadvpn.compose.preview.SearchLocationsListUiStatePreviewParameterProvider
-import net.mullvad.mullvadvpn.compose.state.SelectLocationListUiState
+import net.mullvad.mullvadvpn.feature.location.impl.ContentType
+import net.mullvad.mullvadvpn.feature.location.impl.CustomListHeader
+import net.mullvad.mullvadvpn.feature.location.impl.bottomsheet.LocationBottomSheetState
+import net.mullvad.mullvadvpn.feature.location.impl.relayListContent
import net.mullvad.mullvadvpn.lib.common.Lce
import net.mullvad.mullvadvpn.lib.model.CustomListId
import net.mullvad.mullvadvpn.lib.model.GeoLocationId
@@ -49,18 +49,18 @@ import net.mullvad.mullvadvpn.lib.ui.component.drawVerticalScrollbar
import net.mullvad.mullvadvpn.lib.ui.component.relaylist.RelayListItem
import net.mullvad.mullvadvpn.lib.ui.designsystem.MullvadCircularProgressIndicatorLarge
import net.mullvad.mullvadvpn.lib.ui.designsystem.PrimaryButton
+import net.mullvad.mullvadvpn.lib.ui.resource.R
import net.mullvad.mullvadvpn.lib.ui.tag.SELECT_LOCATION_LIST_TEST_TAG
import net.mullvad.mullvadvpn.lib.ui.theme.AppTheme
import net.mullvad.mullvadvpn.lib.ui.theme.Dimens
import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaScrollbar
-import net.mullvad.mullvadvpn.viewmodel.location.SelectLocationListViewModel
import org.koin.androidx.compose.koinViewModel
import org.koin.core.parameter.parametersOf
@Preview("Content|Loading|Error")
@Composable
private fun PreviewSelectLocationList(
- @PreviewParameter(SearchLocationsListUiStatePreviewParameterProvider::class)
+ @PreviewParameter(SelectLocationsListUiStatePreviewParameterProvider::class)
state: Lce<Unit, SelectLocationListUiState, Unit>
) {
AppTheme {
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SelectLocationListUiState.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/list/SelectLocationListUiState.kt
index 7f72218f7c..0f79b6d33b 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SelectLocationListUiState.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/list/SelectLocationListUiState.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.state
+package net.mullvad.mullvadvpn.feature.location.impl.list
import net.mullvad.mullvadvpn.lib.model.RelayItem
import net.mullvad.mullvadvpn.lib.model.RelayListType
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationListViewModel.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/list/SelectLocationListViewModel.kt
index 5a89db1e73..92c9e45049 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationListViewModel.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/list/SelectLocationListViewModel.kt
@@ -1,7 +1,8 @@
-package net.mullvad.mullvadvpn.viewmodel.location
+package net.mullvad.mullvadvpn.feature.location.impl.list
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@@ -11,8 +12,12 @@ import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.stateIn
-import net.mullvad.mullvadvpn.compose.screen.location.RelayListScrollConnection
-import net.mullvad.mullvadvpn.compose.state.SelectLocationListUiState
+import net.mullvad.mullvadvpn.feature.location.impl.RelayListScrollConnection
+import net.mullvad.mullvadvpn.feature.location.impl.onToggleExpandSet
+import net.mullvad.mullvadvpn.feature.location.impl.search.emptyLocationsRelayListItems
+import net.mullvad.mullvadvpn.feature.location.impl.search.relayListItems
+import net.mullvad.mullvadvpn.feature.location.impl.search.selectedByOtherEntryExitList
+import net.mullvad.mullvadvpn.feature.location.impl.search.selectedByThisEntryExitList
import net.mullvad.mullvadvpn.lib.common.Lce
import net.mullvad.mullvadvpn.lib.common.constant.VIEW_MODEL_STOP_TIMEOUT
import net.mullvad.mullvadvpn.lib.common.util.ignoreEntrySelection
@@ -26,6 +31,7 @@ import net.mullvad.mullvadvpn.lib.model.RelayListType
import net.mullvad.mullvadvpn.lib.repository.RelayListRepository
import net.mullvad.mullvadvpn.lib.repository.SettingsRepository
import net.mullvad.mullvadvpn.lib.repository.WireguardConstraintsRepository
+import net.mullvad.mullvadvpn.lib.ui.component.relaylist.RelayListItem
import net.mullvad.mullvadvpn.lib.usecase.FilteredRelayListUseCase
import net.mullvad.mullvadvpn.lib.usecase.RecentsUseCase
import net.mullvad.mullvadvpn.lib.usecase.SelectedLocationUseCase
@@ -81,7 +87,7 @@ class SelectLocationListViewModel(
_expandedItems.onToggleExpandSet(item, parent, expand)
}
- private fun relayListItems() =
+ private fun relayListItems(): Flow<List<RelayListItem>> =
combine(
filteredRelayListUseCase(relayListType = relayListType),
filteredCustomListRelayItemsUseCase(relayListType = relayListType),
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SearchLocationsListUiStatePreviewParameterProvider.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/list/SelectLocationsListUiStatePreviewParameterProvider.kt
index 78821247c0..a8d3160af2 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SearchLocationsListUiStatePreviewParameterProvider.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/list/SelectLocationsListUiStatePreviewParameterProvider.kt
@@ -1,13 +1,12 @@
-package net.mullvad.mullvadvpn.compose.preview
+package net.mullvad.mullvadvpn.feature.location.impl.list
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
-import net.mullvad.mullvadvpn.compose.state.SelectLocationListUiState
import net.mullvad.mullvadvpn.lib.common.Lce
import net.mullvad.mullvadvpn.lib.model.MultihopRelayListType
import net.mullvad.mullvadvpn.lib.model.RelayListType
import net.mullvad.mullvadvpn.lib.ui.component.relaylist.RelayListItemPreviewData
-class SearchLocationsListUiStatePreviewParameterProvider :
+class SelectLocationsListUiStatePreviewParameterProvider :
PreviewParameterProvider<Lce<Unit, SelectLocationListUiState, Unit>> {
override val values =
sequenceOf(
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/RelayItemListCreator.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/search/RelayItemListCreator.kt
index 5eb1cafd3a..4ce6c6ff03 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/RelayItemListCreator.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/search/RelayItemListCreator.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.viewmodel.location
+package net.mullvad.mullvadvpn.feature.location.impl.search
import net.mullvad.mullvadvpn.lib.common.util.relaylist.filterOnSearchTerm
import net.mullvad.mullvadvpn.lib.model.CustomListId
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SearchLocationScreen.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/search/SearchLocationScreen.kt
index ef24d73bfb..40df302939 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/location/SearchLocationScreen.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/search/SearchLocationScreen.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.screen.location
+package net.mullvad.mullvadvpn.feature.location.impl.search
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
@@ -44,6 +44,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.compose.dropUnlessResumed
import com.ramcosta.composedestinations.annotation.Destination
+import com.ramcosta.composedestinations.annotation.ExternalModuleGraph
import com.ramcosta.composedestinations.generated.customlist.destinations.CreateCustomListDestination
import com.ramcosta.composedestinations.generated.customlist.destinations.CustomListLocationsDestination
import com.ramcosta.composedestinations.generated.customlist.destinations.DeleteCustomListDestination
@@ -52,17 +53,19 @@ import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.result.ResultBackNavigator
import com.ramcosta.composedestinations.result.ResultRecipient
import kotlinx.coroutines.launch
-import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.common.compose.CollectSideEffectWithLifecycle
import net.mullvad.mullvadvpn.common.compose.dropUnlessResumed
import net.mullvad.mullvadvpn.common.compose.showSnackbarImmediately
-import net.mullvad.mullvadvpn.compose.cell.FilterRow
-import net.mullvad.mullvadvpn.compose.component.EmptyRelayListText
-import net.mullvad.mullvadvpn.compose.constant.ContentType
-import net.mullvad.mullvadvpn.compose.preview.SearchLocationsUiStatePreviewParameterProvider
-import net.mullvad.mullvadvpn.compose.screen.MainGraph
-import net.mullvad.mullvadvpn.compose.state.SearchLocationUiState
import net.mullvad.mullvadvpn.core.animation.TopLevelTransition
+import net.mullvad.mullvadvpn.feature.location.impl.ContentType
+import net.mullvad.mullvadvpn.feature.location.impl.EmptyRelayListText
+import net.mullvad.mullvadvpn.feature.location.impl.FilterRow
+import net.mullvad.mullvadvpn.feature.location.impl.UndoChangeMultihopAction
+import net.mullvad.mullvadvpn.feature.location.impl.bottomsheet.LocationBottomSheetState
+import net.mullvad.mullvadvpn.feature.location.impl.bottomsheet.LocationBottomSheets
+import net.mullvad.mullvadvpn.feature.location.impl.bottomsheet.OnCustomListNavResult
+import net.mullvad.mullvadvpn.feature.location.impl.bottomsheet.showResultSnackbar
+import net.mullvad.mullvadvpn.feature.location.impl.relayListContent
import net.mullvad.mullvadvpn.lib.common.Lce
import net.mullvad.mullvadvpn.lib.model.CustomListId
import net.mullvad.mullvadvpn.lib.model.RelayItem
@@ -73,6 +76,7 @@ import net.mullvad.mullvadvpn.lib.ui.component.drawVerticalScrollbar
import net.mullvad.mullvadvpn.lib.ui.designsystem.ListHeader
import net.mullvad.mullvadvpn.lib.ui.designsystem.MullvadCircularProgressIndicatorLarge
import net.mullvad.mullvadvpn.lib.ui.designsystem.MullvadSnackbar
+import net.mullvad.mullvadvpn.lib.ui.resource.R
import net.mullvad.mullvadvpn.lib.ui.theme.AppTheme
import net.mullvad.mullvadvpn.lib.ui.theme.Dimens
import net.mullvad.mullvadvpn.lib.ui.theme.color.AlphaScrollbar
@@ -80,9 +84,6 @@ import net.mullvad.mullvadvpn.lib.usecase.FilterChip
import net.mullvad.mullvadvpn.lib.usecase.ModifyMultihopError
import net.mullvad.mullvadvpn.lib.usecase.MultihopChange
import net.mullvad.mullvadvpn.lib.usecase.SelectRelayItemError
-import net.mullvad.mullvadvpn.viewmodel.location.SearchLocationSideEffect
-import net.mullvad.mullvadvpn.viewmodel.location.SearchLocationViewModel
-import net.mullvad.mullvadvpn.viewmodel.location.UndoChangeMultihopAction
import org.koin.androidx.compose.koinViewModel
@Preview("Loading|Default|No Locations|Not found|Results")
@@ -118,7 +119,10 @@ data class SearchLocationNavArgs(val relayListType: RelayListType)
@Suppress("LongMethod")
@Composable
-@Destination<MainGraph>(style = TopLevelTransition::class, navArgs = SearchLocationNavArgs::class)
+@Destination<ExternalModuleGraph>(
+ style = TopLevelTransition::class,
+ navArgs = SearchLocationNavArgs::class,
+)
fun SearchLocation(
navigator: DestinationsNavigator,
backNavigator: ResultBackNavigator<RelayListType>,
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SearchLocationUiState.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/search/SearchLocationUiState.kt
index fe7d0d9cca..2a8c40ee9b 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/SearchLocationUiState.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/search/SearchLocationUiState.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.state
+package net.mullvad.mullvadvpn.feature.location.impl.search
import net.mullvad.mullvadvpn.lib.model.RelayItem
import net.mullvad.mullvadvpn.lib.model.RelayListType
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SearchLocationViewModel.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/search/SearchLocationViewModel.kt
index e0e37fa96a..1d8dce7e71 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SearchLocationViewModel.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/search/SearchLocationViewModel.kt
@@ -1,9 +1,9 @@
-package net.mullvad.mullvadvpn.viewmodel.location
+package net.mullvad.mullvadvpn.feature.location.impl.search
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
-import com.ramcosta.composedestinations.generated.destinations.SearchLocationDestination
+import com.ramcosta.composedestinations.generated.location.destinations.SearchLocationDestination
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
@@ -13,7 +13,10 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
-import net.mullvad.mullvadvpn.compose.state.SearchLocationUiState
+import net.mullvad.mullvadvpn.feature.location.impl.UndoChangeMultihopAction
+import net.mullvad.mullvadvpn.feature.location.impl.addLocationToCustomList
+import net.mullvad.mullvadvpn.feature.location.impl.onToggleExpandMap
+import net.mullvad.mullvadvpn.feature.location.impl.removeLocationFromCustomList
import net.mullvad.mullvadvpn.lib.common.Lce
import net.mullvad.mullvadvpn.lib.common.constant.VIEW_MODEL_STOP_TIMEOUT
import net.mullvad.mullvadvpn.lib.common.util.combine
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SearchLocationsUiStatePreviewParameterProvider.kt b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/search/SearchLocationsUiStatePreviewParameterProvider.kt
index c7c27a24d2..a283fb29d0 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/SearchLocationsUiStatePreviewParameterProvider.kt
+++ b/android/lib/feature/location/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/location/impl/search/SearchLocationsUiStatePreviewParameterProvider.kt
@@ -1,7 +1,6 @@
-package net.mullvad.mullvadvpn.compose.preview
+package net.mullvad.mullvadvpn.feature.location.impl.search
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
-import net.mullvad.mullvadvpn.compose.state.SearchLocationUiState
import net.mullvad.mullvadvpn.lib.common.Lce
import net.mullvad.mullvadvpn.lib.model.MultihopRelayListType
import net.mullvad.mullvadvpn.lib.model.RelayListType
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationViewModelTest.kt b/android/lib/feature/location/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/location/impl/SelectLocationViewModelTest.kt
index d1c30a397a..42a6709ffd 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationViewModelTest.kt
+++ b/android/lib/feature/location/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/location/impl/SelectLocationViewModelTest.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.viewmodel.location
+package net.mullvad.mullvadvpn.feature.location.impl
import androidx.lifecycle.viewModelScope
import app.cash.turbine.test
@@ -15,8 +15,6 @@ import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runTest
-import net.mullvad.mullvadvpn.compose.screen.location.RelayListScrollConnection
-import net.mullvad.mullvadvpn.compose.state.SelectLocationUiState
import net.mullvad.mullvadvpn.lib.common.Lc
import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule
import net.mullvad.mullvadvpn.lib.common.test.assertLists
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationListViewModelTest.kt b/android/lib/feature/location/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/location/impl/list/SelectLocationListViewModelTest.kt
index 3db935322a..64984834d5 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SelectLocationListViewModelTest.kt
+++ b/android/lib/feature/location/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/location/impl/list/SelectLocationListViewModelTest.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.viewmodel.location
+package net.mullvad.mullvadvpn.feature.location.impl.list
import app.cash.turbine.test
import io.mockk.every
@@ -6,11 +6,13 @@ import io.mockk.mockk
import io.mockk.mockkStatic
import io.mockk.unmockkAll
import io.mockk.verify
+import kotlin.test.assertEquals
import kotlin.test.assertIs
+import kotlin.test.assertTrue
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest
-import net.mullvad.mullvadvpn.compose.screen.location.RelayListScrollConnection
-import net.mullvad.mullvadvpn.compose.state.SelectLocationListUiState
+import net.mullvad.mullvadvpn.feature.location.impl.RelayListScrollConnection
+import net.mullvad.mullvadvpn.feature.location.impl.search.relayListItems
import net.mullvad.mullvadvpn.lib.common.Lce
import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule
import net.mullvad.mullvadvpn.lib.common.test.assertLists
@@ -32,8 +34,6 @@ import net.mullvad.mullvadvpn.lib.usecase.SelectedLocationUseCase
import net.mullvad.mullvadvpn.lib.usecase.customlists.CustomListsRelayItemUseCase
import net.mullvad.mullvadvpn.lib.usecase.customlists.FilterCustomListsRelayItemUseCase
import org.junit.jupiter.api.AfterEach
-import org.junit.jupiter.api.Assertions.assertEquals
-import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
@@ -272,7 +272,7 @@ class SelectLocationListViewModelTest {
companion object {
private const val RELAY_ITEM_LIST_CREATOR_CLASS =
- "net.mullvad.mullvadvpn.viewmodel.location.RelayItemListCreatorKt"
+ "net.mullvad.mullvadvpn.feature.location.impl.search.RelayItemListCreatorKt"
private const val LOCATION_UTIL_CLASS =
"net.mullvad.mullvadvpn.lib.common.util.LocationUtilKt"
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SearchLocationViewModelTest.kt b/android/lib/feature/location/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/location/impl/search/SearchLocationViewModelTest.kt
index efe3fb3d62..a872495fd9 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/location/SearchLocationViewModelTest.kt
+++ b/android/lib/feature/location/impl/src/test/kotlin/net/mullvad/mullvadvpn/feature/location/impl/search/SearchLocationViewModelTest.kt
@@ -1,14 +1,13 @@
-package net.mullvad.mullvadvpn.viewmodel.location
+package net.mullvad.mullvadvpn.feature.location.impl.search
import app.cash.turbine.test
-import com.ramcosta.composedestinations.generated.navargs.toSavedStateHandle
+import com.ramcosta.composedestinations.generated.location.navargs.toSavedStateHandle
import io.mockk.every
import io.mockk.mockk
import kotlin.test.assertIs
+import kotlin.test.assertTrue
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.runTest
-import net.mullvad.mullvadvpn.compose.screen.location.SearchLocationNavArgs
-import net.mullvad.mullvadvpn.compose.state.SearchLocationUiState
import net.mullvad.mullvadvpn.lib.common.Lce
import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule
import net.mullvad.mullvadvpn.lib.common.test.assertLists
@@ -34,7 +33,6 @@ import net.mullvad.mullvadvpn.lib.usecase.SelectedLocationUseCase
import net.mullvad.mullvadvpn.lib.usecase.customlists.CustomListActionUseCase
import net.mullvad.mullvadvpn.lib.usecase.customlists.CustomListsRelayItemUseCase
import net.mullvad.mullvadvpn.lib.usecase.customlists.FilterCustomListsRelayItemUseCase
-import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
diff --git a/android/lib/feature/login/impl/build.gradle.kts b/android/lib/feature/login/impl/build.gradle.kts
new file mode 100644
index 0000000000..96ccad3540
--- /dev/null
+++ b/android/lib/feature/login/impl/build.gradle.kts
@@ -0,0 +1,29 @@
+plugins {
+ alias(libs.plugins.mullvad.android.library)
+ alias(libs.plugins.mullvad.android.library.feature.impl)
+ alias(libs.plugins.mullvad.android.library.compose)
+ alias(libs.plugins.kotlin.android)
+ alias(libs.plugins.kotlin.parcelize)
+ alias(libs.plugins.kotlin.ksp)
+}
+
+android {
+ namespace = "net.mullvad.mullvadvpn.feature.login.impl"
+ ksp { arg("compose-destinations.moduleName", "login") }
+}
+
+dependencies {
+ implementation(projects.lib.pushNotification)
+ implementation(projects.lib.repository)
+ implementation(projects.lib.usecase)
+ implementation(projects.lib.feature.managedevices.impl)
+ implementation(projects.lib.feature.problemreport.impl)
+ implementation(projects.lib.feature.settings.impl)
+
+ implementation(libs.koin.compose)
+ implementation(libs.arrow)
+
+ // Destinations
+ implementation(libs.compose.destinations)
+ ksp(libs.compose.destinations.ksp)
+}
diff --git a/android/lib/feature/login/impl/src/main/AndroidManifest.xml b/android/lib/feature/login/impl/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..7425a54c56
--- /dev/null
+++ b/android/lib/feature/login/impl/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+</manifest>
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/CreateAccountConfirmationDialog.kt b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/CreateAccountConfirmationDialog.kt
index 9ef731ee5d..4cc5ecd460 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/CreateAccountConfirmationDialog.kt
+++ b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/CreateAccountConfirmationDialog.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.dialog
+package net.mullvad.mullvadvpn.feature.login.impl
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
@@ -10,11 +10,10 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import com.ramcosta.composedestinations.annotation.Destination
+import com.ramcosta.composedestinations.annotation.ExternalModuleGraph
import com.ramcosta.composedestinations.result.EmptyResultBackNavigator
import com.ramcosta.composedestinations.result.ResultBackNavigator
import com.ramcosta.composedestinations.spec.DestinationStyle
-import net.mullvad.mullvadvpn.R
-import net.mullvad.mullvadvpn.compose.screen.MainGraph
import net.mullvad.mullvadvpn.lib.ui.component.dialog.Confirmed
import net.mullvad.mullvadvpn.lib.ui.component.dialog.InfoConfirmationDialog
import net.mullvad.mullvadvpn.lib.ui.component.dialog.InfoConfirmationDialogTitleType
@@ -28,7 +27,7 @@ private fun PreviewCreateAccountConfirmationDialog() {
}
@Composable
-@Destination<MainGraph>(style = DestinationStyle.Dialog::class)
+@Destination<ExternalModuleGraph>(style = DestinationStyle.Dialog::class)
fun CreateAccountConfirmation(navigator: ResultBackNavigator<Confirmed>) {
InfoConfirmationDialog(
onResult = {
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/LoginScreen.kt
index 31654af42d..2d45db3745 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/LoginScreen.kt
+++ b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/LoginScreen.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.screen
+package net.mullvad.mullvadvpn.feature.login.impl
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.Image
@@ -62,50 +62,39 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.LayoutDirection
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.compose.dropUnlessResumed
+import androidx.navigation.NavController
import com.ramcosta.composedestinations.annotation.Destination
-import com.ramcosta.composedestinations.generated.NavGraphs
-import com.ramcosta.composedestinations.generated.destinations.ApiUnreachableInfoDestination
-import com.ramcosta.composedestinations.generated.destinations.ConnectDestination
-import com.ramcosta.composedestinations.generated.destinations.CreateAccountConfirmationDestination
-import com.ramcosta.composedestinations.generated.destinations.DeviceListDestination
-import com.ramcosta.composedestinations.generated.destinations.OutOfTimeDestination
-import com.ramcosta.composedestinations.generated.destinations.WelcomeDestination
+import com.ramcosta.composedestinations.annotation.ExternalModuleGraph
+import com.ramcosta.composedestinations.generated.login.destinations.ApiUnreachableInfoDestination
+import com.ramcosta.composedestinations.generated.login.destinations.CreateAccountConfirmationDestination
+import com.ramcosta.composedestinations.generated.login.destinations.DeviceListDestination
import com.ramcosta.composedestinations.generated.settings.destinations.SettingsDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.result.ResultRecipient
import kotlinx.coroutines.launch
-import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.common.compose.CollectSideEffectWithLifecycle
+import net.mullvad.mullvadvpn.common.compose.accountNumberKeyboardType
import net.mullvad.mullvadvpn.common.compose.accountNumberVisualTransformation
import net.mullvad.mullvadvpn.common.compose.clickableAnnotatedString
import net.mullvad.mullvadvpn.common.compose.dropUnlessResumed
import net.mullvad.mullvadvpn.common.compose.showSnackbarImmediately
-import net.mullvad.mullvadvpn.compose.dialog.info.ApiUnreachableInfoDialogNavArgs
-import net.mullvad.mullvadvpn.compose.dialog.info.ApiUnreachableInfoDialogResult
-import net.mullvad.mullvadvpn.compose.dialog.info.LoginAction
-import net.mullvad.mullvadvpn.compose.preview.LoginUiStatePreviewParameterProvider
-import net.mullvad.mullvadvpn.compose.state.LoginState
-import net.mullvad.mullvadvpn.compose.state.LoginState.Idle
-import net.mullvad.mullvadvpn.compose.state.LoginState.Loading
-import net.mullvad.mullvadvpn.compose.state.LoginState.Success
-import net.mullvad.mullvadvpn.compose.state.LoginUiState
-import net.mullvad.mullvadvpn.compose.state.LoginUiStateError
-import net.mullvad.mullvadvpn.compose.transitions.LoginTransition
-import net.mullvad.mullvadvpn.compose.util.OnNavResultValue
-import net.mullvad.mullvadvpn.compose.util.accountNumberKeyboardType
+import net.mullvad.mullvadvpn.core.OnNavResultValue
+import net.mullvad.mullvadvpn.core.animation.LoginTransition
+import net.mullvad.mullvadvpn.feature.login.impl.apiunreachable.ApiUnreachableInfoDialogNavArgs
+import net.mullvad.mullvadvpn.feature.login.impl.apiunreachable.ApiUnreachableInfoDialogResult
+import net.mullvad.mullvadvpn.feature.login.impl.apiunreachable.LoginAction
import net.mullvad.mullvadvpn.lib.ui.component.ScaffoldWithTopBar
import net.mullvad.mullvadvpn.lib.ui.component.dialog.Confirmed
import net.mullvad.mullvadvpn.lib.ui.component.textfield.mullvadWhiteTextFieldColors
import net.mullvad.mullvadvpn.lib.ui.designsystem.MullvadCircularProgressIndicatorLarge
import net.mullvad.mullvadvpn.lib.ui.designsystem.PrimaryButton
import net.mullvad.mullvadvpn.lib.ui.designsystem.VariantButton
+import net.mullvad.mullvadvpn.lib.ui.resource.R
import net.mullvad.mullvadvpn.lib.ui.tag.LOGIN_INPUT_TEST_TAG
import net.mullvad.mullvadvpn.lib.ui.tag.LOGIN_SCREEN_DELETE_ACCOUNT_HISTORY_TEST_TAG
import net.mullvad.mullvadvpn.lib.ui.tag.LOGIN_TITLE_TEST_TAG
import net.mullvad.mullvadvpn.lib.ui.theme.AppTheme
import net.mullvad.mullvadvpn.lib.ui.theme.Dimens
-import net.mullvad.mullvadvpn.viewmodel.LoginUiSideEffect
-import net.mullvad.mullvadvpn.viewmodel.LoginViewModel
import org.koin.androidx.compose.koinViewModel
@Preview("Default|Loading.LoggingIn|Loading.CreatingAccount|LoginError|Success")
@@ -130,9 +119,10 @@ private fun PreviewLoginScreen(
private const val TOP_SPACER_WEIGHT = 1f
private const val BOTTOM_SPACER_WEIGHT = 3f
-@Destination<MainGraph>(style = LoginTransition::class)
+@Destination<ExternalModuleGraph>(style = LoginTransition::class)
@Composable
fun Login(
+ navController: NavController,
navigator: DestinationsNavigator,
accountNumber: String? = null,
vm: LoginViewModel = koinViewModel(),
@@ -177,23 +167,23 @@ fun Login(
CollectSideEffectWithLifecycle(vm.uiSideEffect) {
when (it) {
LoginUiSideEffect.NavigateToWelcome ->
- navigator.navigate(WelcomeDestination) {
+ navController.navigate("home/welcome") {
launchSingleTop = true
- popUpTo(NavGraphs.main) { inclusive = true }
+ popUpTo("main") { inclusive = true }
}
is LoginUiSideEffect.NavigateToConnect ->
- navigator.navigate(ConnectDestination) {
+ navController.navigate("home/connect") {
launchSingleTop = true
- popUpTo(NavGraphs.main) { inclusive = true }
+ popUpTo("main") { inclusive = true }
}
is LoginUiSideEffect.TooManyDevices ->
navigator.navigate(DeviceListDestination(it.accountNumber)) {
launchSingleTop = true
}
LoginUiSideEffect.NavigateToOutOfTime ->
- navigator.navigate(OutOfTimeDestination) {
+ navController.navigate("home/out_of_time") {
launchSingleTop = true
- popUpTo(NavGraphs.main) { inclusive = true }
+ popUpTo("main") { inclusive = true }
}
LoginUiSideEffect.NavigateToCreateAccountConfirmation ->
navigator.navigate(CreateAccountConfirmationDestination)
@@ -234,7 +224,7 @@ private fun LoginScreen(
topBarColor = MaterialTheme.colorScheme.primary,
iconTintColor = MaterialTheme.colorScheme.onPrimary,
onSettingsClicked = onSettingsClick,
- enabled = state.loginState is Idle,
+ enabled = state.loginState is LoginState.Idle,
onAccountClicked = null,
) {
val scrollState = rememberScrollState()
@@ -260,7 +250,10 @@ private fun LoginScreen(
onShowApiUnreachableDialog,
)
Spacer(modifier = Modifier.weight(BOTTOM_SPACER_WEIGHT))
- CreateAccountPanel(onCreateAccountClick, isEnabled = state.loginState is Idle)
+ CreateAccountPanel(
+ onCreateAccountClick,
+ isEnabled = state.loginState is LoginState.Idle,
+ )
}
}
}
@@ -352,13 +345,15 @@ private fun ColumnScope.LoginInput(
singleLine = true,
maxLines = 1,
visualTransformation = accountNumberVisualTransformation(),
- enabled = state.loginState is Idle,
+ enabled = state.loginState is LoginState.Idle,
colors = mullvadWhiteTextFieldColors(),
textStyle = MaterialTheme.typography.bodyLarge.copy(textDirection = TextDirection.Ltr),
isError = state.loginState.isError(),
)
- AnimatedVisibility(visible = state.lastUsedAccount != null && state.loginState is Idle) {
+ AnimatedVisibility(
+ visible = state.lastUsedAccount != null && state.loginState is LoginState.Idle
+ ) {
val token = state.lastUsedAccount?.value.orEmpty()
val accountTransformation = remember { accountNumberVisualTransformation() }
val transformedText =
@@ -374,7 +369,7 @@ private fun ColumnScope.LoginInput(
onLoginClick(it.value)
}
},
- enabled = state.loginState is Idle,
+ enabled = state.loginState is LoginState.Idle,
onDeleteClick = onDeleteHistoryClick,
)
}
@@ -385,7 +380,7 @@ private fun ColumnScope.LoginInput(
private fun LoginIcon(loginState: LoginState, modifier: Modifier = Modifier) {
Box(contentAlignment = Alignment.Center, modifier = modifier) {
when (loginState) {
- is Idle ->
+ is LoginState.Idle ->
if (loginState.loginUiStateError != null) {
Image(
painter = painterResource(id = R.drawable.icon_fail),
@@ -394,8 +389,8 @@ private fun LoginIcon(loginState: LoginState, modifier: Modifier = Modifier) {
} else {
// If view is Idle, we display empty box to keep the same size as other states
}
- is Loading -> MullvadCircularProgressIndicatorLarge()
- Success ->
+ is LoginState.Loading -> MullvadCircularProgressIndicatorLarge()
+ LoginState.Success ->
Image(
painter = painterResource(id = R.drawable.icon_success),
contentDescription = stringResource(id = R.string.logged_in_title),
@@ -409,15 +404,15 @@ private fun LoginState.title(): String =
stringResource(
id =
when (this) {
- is Idle ->
+ is LoginState.Idle ->
when (this.loginUiStateError) {
is LoginUiStateError.LoginError -> R.string.login_fail_title
is LoginUiStateError.CreateAccountError ->
R.string.create_account_fail_title
null -> R.string.log_in
}
- is Loading -> R.string.logging_in_title
- Success -> R.string.logged_in_title
+ is LoginState.Loading -> R.string.logging_in_title
+ LoginState.Success -> R.string.logged_in_title
}
)
@@ -446,11 +441,11 @@ private fun LoginState.supportingText(
onShowApiUnreachableDialog: (LoginUiStateError) -> Unit
): AnnotatedString? =
when (this) {
- is Idle if
- loginUiStateError is LoginUiStateError.LoginError.ApiUnreachable ||
- loginUiStateError is LoginUiStateError.CreateAccountError.ApiUnreachable
+ is LoginState.Idle if
+ (loginUiStateError is LoginUiStateError.LoginError.ApiUnreachable ||
+ loginUiStateError is LoginUiStateError.CreateAccountError.ApiUnreachable)
-> apiUnreachableText(loginUiStateError, onShowApiUnreachableDialog)
- is Idle -> {
+ is LoginState.Idle -> {
when (loginUiStateError) {
LoginUiStateError.LoginError.InvalidCredentials -> R.string.login_fail_description
is LoginUiStateError.LoginError.InvalidInput -> R.string.login_error_invalid_input
@@ -467,9 +462,9 @@ private fun LoginState.supportingText(
null -> null
}?.toAnnotatedString()
}
- is Loading.CreatingAccount -> R.string.creating_new_account.toAnnotatedString()
- is Loading.LoggingIn -> R.string.logging_in_description.toAnnotatedString()
- Success -> R.string.logged_in_description.toAnnotatedString()
+ is LoginState.Loading.CreatingAccount -> R.string.creating_new_account.toAnnotatedString()
+ is LoginState.Loading.LoggingIn -> R.string.logging_in_description.toAnnotatedString()
+ LoginState.Success -> R.string.logged_in_description.toAnnotatedString()
}
@Composable
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/LoginUiState.kt b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/LoginUiState.kt
index 2dbde070f4..7bc16301a6 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/LoginUiState.kt
+++ b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/LoginUiState.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.state
+package net.mullvad.mullvadvpn.feature.login.impl
import net.mullvad.mullvadvpn.lib.model.AccountNumber
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/LoginUiStatePreviewParameterProvider.kt b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/LoginUiStatePreviewParameterProvider.kt
index a0e8ebbee4..9936772c3e 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/LoginUiStatePreviewParameterProvider.kt
+++ b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/LoginUiStatePreviewParameterProvider.kt
@@ -1,9 +1,6 @@
-package net.mullvad.mullvadvpn.compose.preview
+package net.mullvad.mullvadvpn.feature.login.impl
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
-import net.mullvad.mullvadvpn.compose.state.LoginState
-import net.mullvad.mullvadvpn.compose.state.LoginUiState
-import net.mullvad.mullvadvpn.compose.state.LoginUiStateError
class LoginUiStatePreviewParameterProvider : PreviewParameterProvider<LoginUiState> {
override val values: Sequence<LoginUiState>
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModel.kt b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/LoginViewModel.kt
index 7d8149c02e..6152058478 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModel.kt
+++ b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/LoginViewModel.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.viewmodel
+package net.mullvad.mullvadvpn.feature.login.impl
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
@@ -20,12 +20,8 @@ import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
-import net.mullvad.mullvadvpn.compose.state.LoginState
-import net.mullvad.mullvadvpn.compose.state.LoginState.Idle
-import net.mullvad.mullvadvpn.compose.state.LoginState.Loading
-import net.mullvad.mullvadvpn.compose.state.LoginState.Success
-import net.mullvad.mullvadvpn.compose.state.LoginUiState
-import net.mullvad.mullvadvpn.compose.state.LoginUiStateError
+import net.mullvad.mullvadvpn.feature.login.impl.LoginUiSideEffect.NavigateToWelcome
+import net.mullvad.mullvadvpn.feature.login.impl.LoginUiSideEffect.TooManyDevices
import net.mullvad.mullvadvpn.lib.common.constant.VIEW_MODEL_STOP_TIMEOUT
import net.mullvad.mullvadvpn.lib.common.util.delayAtLeast
import net.mullvad.mullvadvpn.lib.common.util.getOrDefault
@@ -33,13 +29,11 @@ import net.mullvad.mullvadvpn.lib.common.util.isBeforeNowInstant
import net.mullvad.mullvadvpn.lib.model.AccountNumber
import net.mullvad.mullvadvpn.lib.model.CreateAccountError
import net.mullvad.mullvadvpn.lib.model.LoginAccountError
+import net.mullvad.mullvadvpn.lib.pushnotification.ScheduleNotificationAlarmUseCase
+import net.mullvad.mullvadvpn.lib.pushnotification.accountexpiry.AccountExpiryNotificationProvider
import net.mullvad.mullvadvpn.lib.repository.AccountRepository
import net.mullvad.mullvadvpn.lib.repository.NewDeviceRepository
import net.mullvad.mullvadvpn.lib.usecase.InternetAvailableUseCase
-import net.mullvad.mullvadvpn.service.notifications.accountexpiry.AccountExpiryNotificationProvider
-import net.mullvad.mullvadvpn.usecase.ScheduleNotificationAlarmUseCase
-import net.mullvad.mullvadvpn.viewmodel.LoginUiSideEffect.NavigateToWelcome
-import net.mullvad.mullvadvpn.viewmodel.LoginUiSideEffect.TooManyDevices
private const val MINIMUM_LOADING_SPINNER_TIME_MILLIS = 500L
@@ -116,7 +110,7 @@ class LoginViewModel(
}
private fun createAccount() {
- _loginState.value = Loading.CreatingAccount
+ _loginState.value = LoginState.Loading.CreatingAccount
viewModelScope.launch(dispatcher) {
accountRepository
.createAccount()
@@ -128,7 +122,7 @@ class LoginViewModel(
}
fun login(accountNumber: String) {
- _loginState.value = Loading.LoggingIn
+ _loginState.value = LoginState.Loading.LoggingIn
viewModelScope.launch(dispatcher) {
val uiState =
// Ensure we always take at least MINIMUM_LOADING_SPINNER_TIME_MILLIS to show the
@@ -140,7 +134,7 @@ class LoginViewModel(
{ it.toUiState() },
{
onSuccessfulLogin()
- Success
+ LoginState.Success
},
)
@@ -176,27 +170,28 @@ class LoginViewModel(
fun onAccountNumberChange(accountNumber: String) {
_loginInput.value = accountNumber.filter { it.isDigit() }
// If there is an error, clear it
- _loginState.update { if (it is Idle) Idle() else it }
+ _loginState.update { if (it is LoginState.Idle) LoginState.Idle() else it }
}
private suspend fun LoginAccountError.toUiState(): LoginState =
when (this) {
LoginAccountError.InvalidAccount ->
- Idle(LoginUiStateError.LoginError.InvalidCredentials)
+ LoginState.Idle(LoginUiStateError.LoginError.InvalidCredentials)
is LoginAccountError.MaxDevicesReached ->
- Idle().also { _uiSideEffect.send(TooManyDevices(accountNumber)) }
+ LoginState.Idle().also { _uiSideEffect.send(TooManyDevices(accountNumber)) }
is LoginAccountError.InvalidInput ->
- Idle(LoginUiStateError.LoginError.InvalidInput(accountNumber))
+ LoginState.Idle(LoginUiStateError.LoginError.InvalidInput(accountNumber))
LoginAccountError.Timeout,
LoginAccountError.ApiUnreachable ->
if (isInternetAvailable()) {
- Idle(LoginUiStateError.LoginError.ApiUnreachable)
+ LoginState.Idle(LoginUiStateError.LoginError.ApiUnreachable)
} else {
- Idle(LoginUiStateError.LoginError.NoInternetConnection)
+ LoginState.Idle(LoginUiStateError.LoginError.NoInternetConnection)
}
- LoginAccountError.TooManyAttempts -> Idle(LoginUiStateError.LoginError.TooManyAttempts)
+ LoginAccountError.TooManyAttempts ->
+ LoginState.Idle(LoginUiStateError.LoginError.TooManyAttempts)
is LoginAccountError.Unknown ->
- Idle(LoginUiStateError.LoginError.Unknown(this.toString())).also {
+ LoginState.Idle(LoginUiStateError.LoginError.Unknown(this.toString())).also {
Logger.w("Login failed with error: $this", error)
}
}
@@ -206,14 +201,14 @@ class LoginViewModel(
CreateAccountError.ApiUnreachable,
CreateAccountError.TimeOut ->
if (isInternetAvailable()) {
- Idle(LoginUiStateError.CreateAccountError.ApiUnreachable)
+ LoginState.Idle(LoginUiStateError.CreateAccountError.ApiUnreachable)
} else {
- Idle(LoginUiStateError.CreateAccountError.NoInternetConnection)
+ LoginState.Idle(LoginUiStateError.CreateAccountError.NoInternetConnection)
}
CreateAccountError.TooManyAttempts ->
- Idle(LoginUiStateError.CreateAccountError.TooManyAttempts)
+ LoginState.Idle(LoginUiStateError.CreateAccountError.TooManyAttempts)
is CreateAccountError.Unknown ->
- Idle(LoginUiStateError.CreateAccountError.Unknown).also {
+ LoginState.Idle(LoginUiStateError.CreateAccountError.Unknown).also {
Logger.w("Create account failed with error: $this", error)
}
}
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/info/ApiUnreachableInfoDialog.kt b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/apiunreachable/ApiUnreachableInfoDialog.kt
index 6fd6f4b527..1bb5ed19b9 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/info/ApiUnreachableInfoDialog.kt
+++ b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/apiunreachable/ApiUnreachableInfoDialog.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.dialog.info
+package net.mullvad.mullvadvpn.feature.login.impl.apiunreachable
import android.content.ActivityNotFoundException
import android.os.Parcelable
@@ -17,23 +17,18 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import co.touchlab.kermit.Logger
import com.ramcosta.composedestinations.annotation.Destination
+import com.ramcosta.composedestinations.annotation.ExternalModuleGraph
import com.ramcosta.composedestinations.result.ResultBackNavigator
import com.ramcosta.composedestinations.spec.DestinationStyle
import kotlinx.parcelize.Parcelize
-import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.common.compose.CollectSideEffectWithLifecycle
-import net.mullvad.mullvadvpn.compose.screen.MainGraph
-import net.mullvad.mullvadvpn.compose.state.ApiUnreachableUiState
-import net.mullvad.mullvadvpn.compose.util.EmailData
-import net.mullvad.mullvadvpn.compose.util.SendEmail
import net.mullvad.mullvadvpn.feature.problemreport.impl.provider.createShareLogFile
import net.mullvad.mullvadvpn.lib.ui.component.dialog.InfoDialog
import net.mullvad.mullvadvpn.lib.ui.component.textfield.ErrorSupportingText
import net.mullvad.mullvadvpn.lib.ui.designsystem.PrimaryButton
+import net.mullvad.mullvadvpn.lib.ui.resource.R
import net.mullvad.mullvadvpn.lib.ui.theme.AppTheme
import net.mullvad.mullvadvpn.lib.ui.theme.Dimens
-import net.mullvad.mullvadvpn.viewmodel.ApiUnreachableSideEffect
-import net.mullvad.mullvadvpn.viewmodel.ApiUnreachableViewModel
import org.koin.androidx.compose.koinViewModel
@Preview
@@ -69,7 +64,7 @@ sealed interface ApiUnreachableInfoDialogResult : Parcelable {
@Parcelize data object Error : ApiUnreachableInfoDialogResult
}
-@Destination<MainGraph>(
+@Destination<ExternalModuleGraph>(
style = DestinationStyle.Dialog::class,
navArgs = ApiUnreachableInfoDialogNavArgs::class,
)
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/ApiUnreachableUiState.kt b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/apiunreachable/ApiUnreachableUiState.kt
index 2a4f407934..304552ee66 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/ApiUnreachableUiState.kt
+++ b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/apiunreachable/ApiUnreachableUiState.kt
@@ -1,6 +1,4 @@
-package net.mullvad.mullvadvpn.compose.state
-
-import net.mullvad.mullvadvpn.compose.dialog.info.LoginAction
+package net.mullvad.mullvadvpn.feature.login.impl.apiunreachable
data class ApiUnreachableUiState(
val showEnableAllAccessMethodsButton: Boolean,
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/ApiUnreachableViewModel.kt b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/apiunreachable/ApiUnreachableViewModel.kt
index 6d5b1c2d85..a3dd4b1bf4 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/ApiUnreachableViewModel.kt
+++ b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/apiunreachable/ApiUnreachableViewModel.kt
@@ -1,9 +1,9 @@
-package net.mullvad.mullvadvpn.viewmodel
+package net.mullvad.mullvadvpn.feature.login.impl.apiunreachable
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
-import com.ramcosta.composedestinations.generated.destinations.ApiUnreachableInfoDestination
+import com.ramcosta.composedestinations.generated.login.destinations.ApiUnreachableInfoDestination
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
@@ -14,8 +14,6 @@ import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
-import net.mullvad.mullvadvpn.compose.dialog.info.ApiUnreachableInfoDialogNavArgs
-import net.mullvad.mullvadvpn.compose.state.ApiUnreachableUiState
import net.mullvad.mullvadvpn.lib.common.constant.VIEW_MODEL_STOP_TIMEOUT
import net.mullvad.mullvadvpn.lib.repository.ApiAccessRepository
import net.mullvad.mullvadvpn.lib.ui.component.NEWLINE_STRING
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/util/SendEmail.kt b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/apiunreachable/SendEmail.kt
index 5d02ad555f..b595c3234a 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/util/SendEmail.kt
+++ b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/apiunreachable/SendEmail.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.util
+package net.mullvad.mullvadvpn.feature.login.impl.apiunreachable
import android.content.Context
import android.content.Intent
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceListScreen.kt b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/devicelist/DeviceListScreen.kt
index 6b5eb9005b..f8cd65a73b 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/screen/DeviceListScreen.kt
+++ b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/devicelist/DeviceListScreen.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.screen
+package net.mullvad.mullvadvpn.feature.login.impl.devicelist
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.Image
@@ -29,19 +29,17 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.compose.dropUnlessResumed
import com.ramcosta.composedestinations.annotation.Destination
-import com.ramcosta.composedestinations.generated.destinations.LoginDestination
-import com.ramcosta.composedestinations.generated.destinations.RemoveDeviceConfirmationDestination
+import com.ramcosta.composedestinations.annotation.ExternalModuleGraph
+import com.ramcosta.composedestinations.generated.login.destinations.LoginDestination
+import com.ramcosta.composedestinations.generated.login.destinations.RemoveDeviceConfirmationDestination
import com.ramcosta.composedestinations.generated.settings.destinations.SettingsDestination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.result.NavResult
import com.ramcosta.composedestinations.result.ResultRecipient
import kotlinx.coroutines.launch
-import net.mullvad.mullvadvpn.R
import net.mullvad.mullvadvpn.common.compose.CollectSideEffectWithLifecycle
import net.mullvad.mullvadvpn.common.compose.dropUnlessResumed
import net.mullvad.mullvadvpn.common.compose.showSnackbarImmediately
-import net.mullvad.mullvadvpn.compose.preview.DeviceListUiStatePreviewParameterProvider
-import net.mullvad.mullvadvpn.compose.state.DeviceListUiState
import net.mullvad.mullvadvpn.core.animation.DefaultTransition
import net.mullvad.mullvadvpn.lib.model.AccountNumber
import net.mullvad.mullvadvpn.lib.model.Device
@@ -53,11 +51,10 @@ import net.mullvad.mullvadvpn.lib.ui.component.positionForIndex
import net.mullvad.mullvadvpn.lib.ui.designsystem.MullvadCircularProgressIndicatorLarge
import net.mullvad.mullvadvpn.lib.ui.designsystem.PrimaryButton
import net.mullvad.mullvadvpn.lib.ui.designsystem.VariantButton
+import net.mullvad.mullvadvpn.lib.ui.resource.R
import net.mullvad.mullvadvpn.lib.ui.theme.AppTheme
import net.mullvad.mullvadvpn.lib.ui.theme.Dimens
import net.mullvad.mullvadvpn.lib.ui.theme.color.selected
-import net.mullvad.mullvadvpn.viewmodel.DeviceListSideEffect
-import net.mullvad.mullvadvpn.viewmodel.DeviceListViewModel
import org.koin.androidx.compose.koinViewModel
@Composable
@@ -80,7 +77,10 @@ private fun PreviewDeviceListScreenContent(
data class DeviceListNavArgs(val accountNumber: AccountNumber)
-@Destination<MainGraph>(style = DefaultTransition::class, navArgs = DeviceListNavArgs::class)
+@Destination<ExternalModuleGraph>(
+ style = DefaultTransition::class,
+ navArgs = DeviceListNavArgs::class,
+)
@Composable
fun DeviceList(
navigator: DestinationsNavigator,
@@ -207,7 +207,7 @@ private fun ColumnScope.DeviceListError(tryAgain: () -> Unit) {
}
@Composable
-private fun ColumnScope.DeviceListContent(
+private fun DeviceListContent(
state: DeviceListUiState.Content,
navigateToRemoveDeviceConfirmationDialog: (Device) -> Unit,
) {
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/DeviceListUiState.kt b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/devicelist/DeviceListUiState.kt
index adc5e3d07d..5da1312a44 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/state/DeviceListUiState.kt
+++ b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/devicelist/DeviceListUiState.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.state
+package net.mullvad.mullvadvpn.feature.login.impl.devicelist
import net.mullvad.mullvadvpn.lib.model.Device
import net.mullvad.mullvadvpn.lib.model.GetDeviceListError
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/DeviceListUiStatePreviewParameterProvider.kt b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/devicelist/DeviceListUiStatePreviewParameterProvider.kt
index 53102efb21..3d846bc7d0 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/DeviceListUiStatePreviewParameterProvider.kt
+++ b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/devicelist/DeviceListUiStatePreviewParameterProvider.kt
@@ -1,8 +1,7 @@
-package net.mullvad.mullvadvpn.compose.preview
+package net.mullvad.mullvadvpn.feature.login.impl.devicelist
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
-import net.mullvad.mullvadvpn.compose.preview.DevicePreviewData.generateDevices
-import net.mullvad.mullvadvpn.compose.state.DeviceListUiState
+import net.mullvad.mullvadvpn.feature.login.impl.devicelist.DevicePreviewData.generateDevices
import net.mullvad.mullvadvpn.lib.model.GetDeviceListError
class DeviceListUiStatePreviewParameterProvider : PreviewParameterProvider<DeviceListUiState> {
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceListViewModel.kt b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/devicelist/DeviceListViewModel.kt
index a1178cc2b8..341fe1c844 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceListViewModel.kt
+++ b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/devicelist/DeviceListViewModel.kt
@@ -1,9 +1,9 @@
-package net.mullvad.mullvadvpn.viewmodel
+package net.mullvad.mullvadvpn.feature.login.impl.devicelist
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
-import com.ramcosta.composedestinations.generated.destinations.DeviceListDestination
+import com.ramcosta.composedestinations.generated.login.destinations.DeviceListDestination
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
@@ -18,8 +18,6 @@ import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
-import net.mullvad.mullvadvpn.compose.state.DeviceItemUiState
-import net.mullvad.mullvadvpn.compose.state.DeviceListUiState
import net.mullvad.mullvadvpn.lib.common.constant.VIEW_MODEL_STOP_TIMEOUT
import net.mullvad.mullvadvpn.lib.model.AccountNumber
import net.mullvad.mullvadvpn.lib.model.Device
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/DevicePreviewData.kt b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/devicelist/DevicePreviewData.kt
index 138706930f..edefed7687 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/preview/DevicePreviewData.kt
+++ b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/devicelist/DevicePreviewData.kt
@@ -1,8 +1,7 @@
-package net.mullvad.mullvadvpn.compose.preview
+package net.mullvad.mullvadvpn.feature.login.impl.devicelist
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
-import net.mullvad.mullvadvpn.compose.state.DeviceItemUiState
import net.mullvad.mullvadvpn.lib.model.Device
import net.mullvad.mullvadvpn.lib.model.DeviceId
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/RemoveDeviceConfirmationDialog.kt b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/devicelist/RemoveDeviceConfirmationDialog.kt
index 0715eec43d..79aaab0c05 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/dialog/RemoveDeviceConfirmationDialog.kt
+++ b/android/lib/feature/login/impl/src/main/kotlin/net/mullvad/mullvadvpn/feature/login/impl/devicelist/RemoveDeviceConfirmationDialog.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.dialog
+package net.mullvad.mullvadvpn.feature.login.impl.devicelist
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
@@ -10,16 +10,16 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.core.text.HtmlCompat
import androidx.lifecycle.compose.dropUnlessResumed
import com.ramcosta.composedestinations.annotation.Destination
+import com.ramcosta.composedestinations.annotation.ExternalModuleGraph
import com.ramcosta.composedestinations.result.EmptyResultBackNavigator
import com.ramcosta.composedestinations.result.ResultBackNavigator
import com.ramcosta.composedestinations.spec.DestinationStyle
-import net.mullvad.mullvadvpn.R
-import net.mullvad.mullvadvpn.compose.screen.MainGraph
import net.mullvad.mullvadvpn.feature.managedevices.impl.confirmation.ManageDeviceRemoveConfirmationPreviewParameterProvider
import net.mullvad.mullvadvpn.lib.model.Device
import net.mullvad.mullvadvpn.lib.model.DeviceId
import net.mullvad.mullvadvpn.lib.ui.component.dialog.NegativeConfirmationDialog
import net.mullvad.mullvadvpn.lib.ui.component.toAnnotatedString
+import net.mullvad.mullvadvpn.lib.ui.resource.R
import net.mullvad.mullvadvpn.lib.ui.theme.AppTheme
@Preview
@@ -30,7 +30,7 @@ private fun PreviewRemoveDeviceConfirmationDialog(
AppTheme { RemoveDeviceConfirmation(EmptyResultBackNavigator(), device = device) }
}
-@Destination<MainGraph>(style = DestinationStyle.Dialog::class)
+@Destination<ExternalModuleGraph>(style = DestinationStyle.Dialog::class)
@Composable
fun RemoveDeviceConfirmation(navigator: ResultBackNavigator<DeviceId>, device: Device) {
val htmlFormattedString =
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceListViewModelTest.kt b/android/lib/feature/login/impl/src/test/java/net/mullvad/mullvadvpn/feature/login/impl/DeviceListViewModelTest.kt
index fc9e244faa..f6d5f2f192 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/DeviceListViewModelTest.kt
+++ b/android/lib/feature/login/impl/src/test/java/net/mullvad/mullvadvpn/feature/login/impl/DeviceListViewModelTest.kt
@@ -1,11 +1,11 @@
-package net.mullvad.mullvadvpn.viewmodel
+package net.mullvad.mullvadvpn.feature.login.impl
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.viewModelScope
import app.cash.turbine.test
import arrow.core.left
import arrow.core.right
-import com.ramcosta.composedestinations.generated.navargs.toSavedStateHandle
+import com.ramcosta.composedestinations.generated.login.navargs.toSavedStateHandle
import io.mockk.coEvery
import io.mockk.every
import io.mockk.mockk
@@ -18,8 +18,10 @@ import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
-import net.mullvad.mullvadvpn.compose.screen.DeviceListNavArgs
-import net.mullvad.mullvadvpn.compose.state.DeviceListUiState
+import net.mullvad.mullvadvpn.feature.login.impl.devicelist.DeviceListNavArgs
+import net.mullvad.mullvadvpn.feature.login.impl.devicelist.DeviceListSideEffect
+import net.mullvad.mullvadvpn.feature.login.impl.devicelist.DeviceListUiState
+import net.mullvad.mullvadvpn.feature.login.impl.devicelist.DeviceListViewModel
import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule
import net.mullvad.mullvadvpn.lib.model.AccountNumber
import net.mullvad.mullvadvpn.lib.model.DeleteDeviceError
diff --git a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModelTest.kt b/android/lib/feature/login/impl/src/test/java/net/mullvad/mullvadvpn/feature/login/impl/LoginViewModelTest.kt
index 7a49b3289d..409ba1ea27 100644
--- a/android/app/src/test/kotlin/net/mullvad/mullvadvpn/viewmodel/LoginViewModelTest.kt
+++ b/android/lib/feature/login/impl/src/test/java/net/mullvad/mullvadvpn/feature/login/impl/LoginViewModelTest.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.viewmodel
+package net.mullvad.mullvadvpn.feature.login.impl
import app.cash.turbine.ReceiveTurbine
import app.cash.turbine.test
@@ -17,21 +17,19 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runTest
-import net.mullvad.mullvadvpn.compose.state.LoginState.Idle
-import net.mullvad.mullvadvpn.compose.state.LoginState.Loading
-import net.mullvad.mullvadvpn.compose.state.LoginState.Success
-import net.mullvad.mullvadvpn.compose.state.LoginUiState
-import net.mullvad.mullvadvpn.compose.state.LoginUiStateError
-import net.mullvad.mullvadvpn.data.mock
+import net.mullvad.mullvadvpn.feature.login.impl.LoginState.Idle
+import net.mullvad.mullvadvpn.feature.login.impl.LoginState.Loading
+import net.mullvad.mullvadvpn.feature.login.impl.LoginState.Success
+import net.mullvad.mullvadvpn.feature.login.impl.data.mock
import net.mullvad.mullvadvpn.lib.common.test.TestCoroutineRule
import net.mullvad.mullvadvpn.lib.model.AccountData
import net.mullvad.mullvadvpn.lib.model.AccountNumber
import net.mullvad.mullvadvpn.lib.model.CreateAccountError
import net.mullvad.mullvadvpn.lib.model.LoginAccountError
+import net.mullvad.mullvadvpn.lib.pushnotification.ScheduleNotificationAlarmUseCase
+import net.mullvad.mullvadvpn.lib.pushnotification.accountexpiry.AccountExpiryNotificationProvider
import net.mullvad.mullvadvpn.lib.repository.AccountRepository
import net.mullvad.mullvadvpn.lib.usecase.InternetAvailableUseCase
-import net.mullvad.mullvadvpn.service.notifications.accountexpiry.AccountExpiryNotificationProvider
-import net.mullvad.mullvadvpn.usecase.ScheduleNotificationAlarmUseCase
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
diff --git a/android/lib/feature/login/impl/src/test/java/net/mullvad/mullvadvpn/feature/login/impl/data/AccountData.kt b/android/lib/feature/login/impl/src/test/java/net/mullvad/mullvadvpn/feature/login/impl/data/AccountData.kt
new file mode 100644
index 0000000000..d9e03e76ce
--- /dev/null
+++ b/android/lib/feature/login/impl/src/test/java/net/mullvad/mullvadvpn/feature/login/impl/data/AccountData.kt
@@ -0,0 +1,12 @@
+package net.mullvad.mullvadvpn.feature.login.impl.data
+
+import io.mockk.mockk
+import java.time.ZonedDateTime
+import net.mullvad.mullvadvpn.lib.model.AccountData
+
+fun AccountData.Companion.mock(expiry: ZonedDateTime): AccountData =
+ AccountData(
+ id = mockk(relaxed = true),
+ accountNumber = mockk(relaxed = true),
+ expiryDate = expiry,
+ )
diff --git a/android/lib/navigation/src/main/java/net/mullvad/mullvadvpn/core/Navigation.kt b/android/lib/navigation/src/main/kotlin/net/mullvad/mullvadvpn/core/Navigation.kt
index ab94081b7f..ab94081b7f 100644
--- a/android/lib/navigation/src/main/java/net/mullvad/mullvadvpn/core/Navigation.kt
+++ b/android/lib/navigation/src/main/kotlin/net/mullvad/mullvadvpn/core/Navigation.kt
diff --git a/android/lib/navigation/src/main/java/net/mullvad/mullvadvpn/core/animation/AccountTransition.kt b/android/lib/navigation/src/main/kotlin/net/mullvad/mullvadvpn/core/animation/AccountTransition.kt
index e4fa8e72f8..e4fa8e72f8 100644
--- a/android/lib/navigation/src/main/java/net/mullvad/mullvadvpn/core/animation/AccountTransition.kt
+++ b/android/lib/navigation/src/main/kotlin/net/mullvad/mullvadvpn/core/animation/AccountTransition.kt
diff --git a/android/lib/navigation/src/main/java/net/mullvad/mullvadvpn/core/animation/AnimationConstant.kt b/android/lib/navigation/src/main/kotlin/net/mullvad/mullvadvpn/core/animation/AnimationConstant.kt
index 12eb6e2215..12eb6e2215 100644
--- a/android/lib/navigation/src/main/java/net/mullvad/mullvadvpn/core/animation/AnimationConstant.kt
+++ b/android/lib/navigation/src/main/kotlin/net/mullvad/mullvadvpn/core/animation/AnimationConstant.kt
diff --git a/android/lib/navigation/src/main/java/net/mullvad/mullvadvpn/core/animation/DefaultTransition.kt b/android/lib/navigation/src/main/kotlin/net/mullvad/mullvadvpn/core/animation/DefaultTransition.kt
index cc45ab55fe..cc45ab55fe 100644
--- a/android/lib/navigation/src/main/java/net/mullvad/mullvadvpn/core/animation/DefaultTransition.kt
+++ b/android/lib/navigation/src/main/kotlin/net/mullvad/mullvadvpn/core/animation/DefaultTransition.kt
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/transitions/LoginTransition.kt b/android/lib/navigation/src/main/kotlin/net/mullvad/mullvadvpn/core/animation/LoginTransition.kt
index 2c82d24d7c..863ee93916 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/compose/transitions/LoginTransition.kt
+++ b/android/lib/navigation/src/main/kotlin/net/mullvad/mullvadvpn/core/animation/LoginTransition.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.compose.transitions
+package net.mullvad.mullvadvpn.core.animation
import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.EnterTransition
@@ -7,12 +7,7 @@ import androidx.compose.animation.core.spring
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.navigation.NavBackStackEntry
-import com.ramcosta.composedestinations.generated.destinations.ConnectDestination
-import com.ramcosta.composedestinations.generated.destinations.DeviceListDestination
-import com.ramcosta.composedestinations.generated.destinations.OutOfTimeDestination
-import com.ramcosta.composedestinations.generated.destinations.WelcomeDestination
import com.ramcosta.composedestinations.spec.DestinationStyle
-import com.ramcosta.composedestinations.utils.destination
object LoginTransition : DestinationStyle.Animated() {
override val enterTransition:
@@ -24,11 +19,11 @@ object LoginTransition : DestinationStyle.Animated() {
override val exitTransition:
AnimatedContentTransitionScope<NavBackStackEntry>.() -> ExitTransition =
{
- when (this.targetState.destination()) {
- is OutOfTimeDestination,
- is WelcomeDestination,
- is ConnectDestination,
- is DeviceListDestination -> fadeOut(spring())
+ when (this.targetState.destination.route) {
+ "home/out_of_time",
+ "home/welcome",
+ "home/connect",
+ "login/device_list" -> fadeOut(spring())
else -> ExitTransition.None
}
}
diff --git a/android/lib/navigation/src/main/java/net/mullvad/mullvadvpn/core/animation/SlideInFromRightTransition.kt b/android/lib/navigation/src/main/kotlin/net/mullvad/mullvadvpn/core/animation/SlideInFromRightTransition.kt
index 79587f47c2..79587f47c2 100644
--- a/android/lib/navigation/src/main/java/net/mullvad/mullvadvpn/core/animation/SlideInFromRightTransition.kt
+++ b/android/lib/navigation/src/main/kotlin/net/mullvad/mullvadvpn/core/animation/SlideInFromRightTransition.kt
diff --git a/android/lib/navigation/src/main/java/net/mullvad/mullvadvpn/core/animation/TopLevelTransition.kt b/android/lib/navigation/src/main/kotlin/net/mullvad/mullvadvpn/core/animation/TopLevelTransition.kt
index 3297be9627..3297be9627 100644
--- a/android/lib/navigation/src/main/java/net/mullvad/mullvadvpn/core/animation/TopLevelTransition.kt
+++ b/android/lib/navigation/src/main/kotlin/net/mullvad/mullvadvpn/core/animation/TopLevelTransition.kt
diff --git a/android/lib/push-notification/build.gradle.kts b/android/lib/push-notification/build.gradle.kts
new file mode 100644
index 0000000000..72f1751647
--- /dev/null
+++ b/android/lib/push-notification/build.gradle.kts
@@ -0,0 +1,22 @@
+plugins {
+ alias(libs.plugins.mullvad.android.library)
+ alias(libs.plugins.kotlin.android)
+ alias(libs.plugins.kotlin.parcelize)
+}
+
+android { namespace = "net.mullvad.mullvadvpn.feature.pushnotifications" }
+
+dependencies {
+ implementation(projects.lib.common)
+ implementation(projects.lib.model)
+ implementation(projects.lib.repository)
+ implementation(projects.lib.ui.resource)
+
+ implementation(libs.androidx.ktx)
+ implementation(libs.androidx.lifecycle.service)
+ implementation(libs.androidx.work.runtime.ktx)
+ implementation(libs.arrow)
+ implementation(libs.kermit)
+ implementation(libs.koin.android)
+ implementation(libs.protobuf.kotlin.lite)
+}
diff --git a/android/lib/push-notification/src/main/AndroidManifest.xml b/android/lib/push-notification/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..fdd2360d8e
--- /dev/null
+++ b/android/lib/push-notification/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+ <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
+</manifest>
diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/NotificationChannelFactory.kt b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/NotificationChannelFactory.kt
index 72539e8e94..c8ec728937 100644
--- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/NotificationChannelFactory.kt
+++ b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/NotificationChannelFactory.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.service.notifications
+package net.mullvad.mullvadvpn.lib.pushnotification
import android.app.NotificationManager
import android.content.res.Resources
diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/NotificationManager.kt b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/NotificationManager.kt
index ed2d2f053a..6ca4f33007 100644
--- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/NotificationManager.kt
+++ b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/NotificationManager.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.service.notifications
+package net.mullvad.mullvadvpn.lib.pushnotification
import android.Manifest
import android.content.Context
@@ -13,15 +13,15 @@ import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.launch
import net.mullvad.mullvadvpn.lib.model.Notification
import net.mullvad.mullvadvpn.lib.model.NotificationUpdate
-import net.mullvad.mullvadvpn.service.notifications.accountexpiry.toNotification
-import net.mullvad.mullvadvpn.service.notifications.tunnelstate.toNotification
+import net.mullvad.mullvadvpn.lib.pushnotification.accountexpiry.toNotification
+import net.mullvad.mullvadvpn.lib.pushnotification.tunnelstate.toNotification
@OptIn(FlowPreview::class)
class NotificationManager(
private val notificationManagerCompat: NotificationManagerCompat,
notificationProviders: List<NotificationProvider<Notification>>,
context: Context,
- val scope: CoroutineScope,
+ scope: CoroutineScope,
) {
init {
diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/NotificationProvider.kt b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/NotificationProvider.kt
index ecdde13d7a..71d587e030 100644
--- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/NotificationProvider.kt
+++ b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/NotificationProvider.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.service.notifications
+package net.mullvad.mullvadvpn.lib.pushnotification
import kotlinx.coroutines.flow.Flow
import net.mullvad.mullvadvpn.lib.model.NotificationUpdate
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/ScheduleNotificationAlarmUseCase.kt b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/ScheduleNotificationAlarmUseCase.kt
index 1d178a15bf..5b40970a67 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/usecase/ScheduleNotificationAlarmUseCase.kt
+++ b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/ScheduleNotificationAlarmUseCase.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.usecase
+package net.mullvad.mullvadvpn.lib.pushnotification
import android.app.AlarmManager
import android.app.PendingIntent
@@ -8,8 +8,8 @@ import co.touchlab.kermit.Logger
import java.time.ZoneOffset
import java.time.ZonedDateTime
import net.mullvad.mullvadvpn.lib.common.util.accountExpiryNotificationTriggerAt
+import net.mullvad.mullvadvpn.lib.pushnotification.receiver.NotificationAlarmReceiver
import net.mullvad.mullvadvpn.lib.repository.UserPreferencesRepository
-import net.mullvad.mullvadvpn.receiver.NotificationAlarmReceiver
class ScheduleNotificationAlarmUseCase(
private val applicationContext: Context,
diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/ShouldBeOnForegroundProvider.kt b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/ShouldBeOnForegroundProvider.kt
index 1fdfb1ecb0..7caa49b3c8 100644
--- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/ShouldBeOnForegroundProvider.kt
+++ b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/ShouldBeOnForegroundProvider.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.service.notifications
+package net.mullvad.mullvadvpn.lib.pushnotification
import kotlinx.coroutines.flow.Flow
diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/accountexpiry/AccountExpiryAndroidNotification.kt b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/accountexpiry/AccountExpiryAndroidNotification.kt
index 97212797cd..c167a14870 100644
--- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/accountexpiry/AccountExpiryAndroidNotification.kt
+++ b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/accountexpiry/AccountExpiryAndroidNotification.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.service.notifications.accountexpiry
+package net.mullvad.mullvadvpn.lib.pushnotification.accountexpiry
import android.app.PendingIntent
import android.content.Context
@@ -9,7 +9,7 @@ import java.time.Duration
import net.mullvad.mullvadvpn.lib.common.constant.MAIN_ACTIVITY_CLASS
import net.mullvad.mullvadvpn.lib.common.util.SdkUtils
import net.mullvad.mullvadvpn.lib.model.Notification
-import net.mullvad.mullvadvpn.service.R
+import net.mullvad.mullvadvpn.lib.ui.resource.R
internal fun Notification.AccountExpiry.toNotification(context: Context) =
NotificationCompat.Builder(context, channelId.value)
diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/accountexpiry/AccountExpiryNotificationProvider.kt b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/accountexpiry/AccountExpiryNotificationProvider.kt
index 0be99896c9..2b72c0aac5 100644
--- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/accountexpiry/AccountExpiryNotificationProvider.kt
+++ b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/accountexpiry/AccountExpiryNotificationProvider.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.service.notifications.accountexpiry
+package net.mullvad.mullvadvpn.lib.pushnotification.accountexpiry
import co.touchlab.kermit.Logger
import java.time.Duration
@@ -9,7 +9,7 @@ import net.mullvad.mullvadvpn.lib.model.Notification
import net.mullvad.mullvadvpn.lib.model.NotificationChannelId
import net.mullvad.mullvadvpn.lib.model.NotificationId
import net.mullvad.mullvadvpn.lib.model.NotificationUpdate
-import net.mullvad.mullvadvpn.service.notifications.NotificationProvider
+import net.mullvad.mullvadvpn.lib.pushnotification.NotificationProvider
class AccountExpiryNotificationProvider(private val channelId: NotificationChannelId) :
NotificationProvider<Notification.AccountExpiry> {
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/receiver/NotificationAlarmReceiver.kt b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/receiver/NotificationAlarmReceiver.kt
index 39f92f47f0..1f5df775b8 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/receiver/NotificationAlarmReceiver.kt
+++ b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/receiver/NotificationAlarmReceiver.kt
@@ -1,15 +1,16 @@
-package net.mullvad.mullvadvpn.receiver
+package net.mullvad.mullvadvpn.lib.pushnotification.receiver
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
+import android.os.Build
import androidx.work.Constraints
import androidx.work.NetworkType
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.OutOfQuotaPolicy
import androidx.work.WorkManager
import co.touchlab.kermit.Logger
-import net.mullvad.mullvadvpn.worker.ExpiryNotificationWorker
+import net.mullvad.mullvadvpn.lib.pushnotification.worker.ExpiryNotificationWorker
import org.koin.core.component.KoinComponent
class NotificationAlarmReceiver : BroadcastReceiver(), KoinComponent {
@@ -25,9 +26,7 @@ class NotificationAlarmReceiver : BroadcastReceiver(), KoinComponent {
// Setting expedited on android 12 or lower will cause the work manager to
// request a wake lock. We want to avoid using wakelocks so we disable expedited
// on android 12 and lower.
- if (
- android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU
- ) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
}
}
diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/tunnelstate/TunnelStateNotificationAction.kt b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/tunnelstate/TunnelStateNotificationAction.kt
index b799de0943..05eea1c666 100644
--- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/tunnelstate/TunnelStateNotificationAction.kt
+++ b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/tunnelstate/TunnelStateNotificationAction.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.service.notifications.tunnelstate
+package net.mullvad.mullvadvpn.lib.pushnotification.tunnelstate
import android.app.PendingIntent
import android.content.Context
@@ -13,9 +13,9 @@ import net.mullvad.mullvadvpn.lib.model.Notification
import net.mullvad.mullvadvpn.lib.model.NotificationAction
import net.mullvad.mullvadvpn.lib.model.NotificationTunnelState
import net.mullvad.mullvadvpn.lib.model.PrepareError
-import net.mullvad.mullvadvpn.service.R
+import net.mullvad.mullvadvpn.lib.ui.resource.R
-internal fun Notification.Tunnel.toNotification(context: Context) =
+fun Notification.Tunnel.toNotification(context: Context) =
NotificationCompat.Builder(context, channelId.value)
.setContentIntent(contentIntent(context))
.setContentTitle(state.contentTitleResourceId(context))
diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/tunnelstate/TunnelStateNotificationProvider.kt b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/tunnelstate/TunnelStateNotificationProvider.kt
index e3f985acd8..f75deb7258 100644
--- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/tunnelstate/TunnelStateNotificationProvider.kt
+++ b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/tunnelstate/TunnelStateNotificationProvider.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.service.notifications.tunnelstate
+package net.mullvad.mullvadvpn.lib.pushnotification.tunnelstate
import android.content.Context
import kotlinx.coroutines.CoroutineScope
@@ -18,10 +18,10 @@ import net.mullvad.mullvadvpn.lib.model.NotificationTunnelState
import net.mullvad.mullvadvpn.lib.model.NotificationUpdate
import net.mullvad.mullvadvpn.lib.model.PrepareError
import net.mullvad.mullvadvpn.lib.model.TunnelState
+import net.mullvad.mullvadvpn.lib.pushnotification.NotificationProvider
import net.mullvad.mullvadvpn.lib.repository.ConnectionProxy
import net.mullvad.mullvadvpn.lib.repository.DeviceRepository
import net.mullvad.mullvadvpn.lib.repository.UserPreferencesRepository
-import net.mullvad.mullvadvpn.service.notifications.NotificationProvider
class TunnelStateNotificationProvider(
context: Context,
@@ -31,7 +31,7 @@ class TunnelStateNotificationProvider(
channelId: NotificationChannelId,
scope: CoroutineScope,
) : NotificationProvider<Notification.Tunnel> {
- internal val notificationId = NotificationId(2)
+ val notificationId = NotificationId(2)
override val notifications: StateFlow<NotificationUpdate<Notification.Tunnel>> =
combine(
diff --git a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/worker/ExpiryNotificationWorker.kt b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/worker/ExpiryNotificationWorker.kt
index 902ccbb50c..b4988933cb 100644
--- a/android/app/src/main/kotlin/net/mullvad/mullvadvpn/worker/ExpiryNotificationWorker.kt
+++ b/android/lib/push-notification/src/main/kotlin/net/mullvad/mullvadvpn/lib/pushnotification/worker/ExpiryNotificationWorker.kt
@@ -1,4 +1,4 @@
-package net.mullvad.mullvadvpn.worker
+package net.mullvad.mullvadvpn.lib.pushnotification.worker
import android.app.Notification
import android.content.Context
@@ -16,13 +16,13 @@ import java.time.ZonedDateTime
import kotlin.getValue
import kotlinx.coroutines.withTimeoutOrNull
import net.mullvad.mullvadvpn.lib.common.constant.VPN_SERVICE_CLASS
+import net.mullvad.mullvadvpn.lib.common.serviceconnection.EmptyServiceConnection
import net.mullvad.mullvadvpn.lib.common.util.ACCOUNT_EXPIRY_CLOSE_TO_EXPIRY_THRESHOLD
import net.mullvad.mullvadvpn.lib.model.NotificationChannel
+import net.mullvad.mullvadvpn.lib.pushnotification.ScheduleNotificationAlarmUseCase
+import net.mullvad.mullvadvpn.lib.pushnotification.accountexpiry.AccountExpiryNotificationProvider
import net.mullvad.mullvadvpn.lib.repository.AccountRepository
-import net.mullvad.mullvadvpn.service.R
-import net.mullvad.mullvadvpn.service.notifications.accountexpiry.AccountExpiryNotificationProvider
-import net.mullvad.mullvadvpn.ui.serviceconnection.EmptyServiceConnection
-import net.mullvad.mullvadvpn.usecase.ScheduleNotificationAlarmUseCase
+import net.mullvad.mullvadvpn.lib.ui.resource.R
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject
diff --git a/android/service/build.gradle.kts b/android/service/build.gradle.kts
index a3928105bd..14f1b7ed28 100644
--- a/android/service/build.gradle.kts
+++ b/android/service/build.gradle.kts
@@ -80,6 +80,7 @@ dependencies {
implementation(projects.lib.grpc)
implementation(projects.lib.endpoint)
implementation(projects.lib.model)
+ implementation(projects.lib.pushNotification)
implementation(projects.lib.repository)
implementation(projects.lib.talpid)
diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt
index caaf7e127b..fd9af163f3 100644
--- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt
+++ b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt
@@ -19,12 +19,12 @@ import net.mullvad.mullvadvpn.lib.common.constant.KEY_DISCONNECT_ACTION
import net.mullvad.mullvadvpn.lib.endpoint.ApiEndpointFromIntentHolder
import net.mullvad.mullvadvpn.lib.grpc.ManagementService
import net.mullvad.mullvadvpn.lib.model.TunnelState
+import net.mullvad.mullvadvpn.lib.pushnotification.NotificationChannelFactory
+import net.mullvad.mullvadvpn.lib.pushnotification.NotificationManager
import net.mullvad.mullvadvpn.lib.repository.ConnectionProxy
import net.mullvad.mullvadvpn.service.di.vpnServiceModule
import net.mullvad.mullvadvpn.service.migration.MigrateSplitTunneling
import net.mullvad.mullvadvpn.service.notifications.ForegroundNotificationManager
-import net.mullvad.mullvadvpn.service.notifications.NotificationChannelFactory
-import net.mullvad.mullvadvpn.service.notifications.NotificationManager
import net.mullvad.mullvadvpn.service.util.extractAndOverwriteIfAssetMoreRecent
import net.mullvad.talpid.TalpidVpnService
import org.koin.android.ext.android.getKoin
diff --git a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/ForegroundNotificationManager.kt b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/ForegroundNotificationManager.kt
index cf324e6023..a63cb64f9a 100644
--- a/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/ForegroundNotificationManager.kt
+++ b/android/service/src/main/kotlin/net/mullvad/mullvadvpn/service/notifications/ForegroundNotificationManager.kt
@@ -9,9 +9,9 @@ import net.mullvad.mullvadvpn.lib.model.Notification
import net.mullvad.mullvadvpn.lib.model.NotificationChannel
import net.mullvad.mullvadvpn.lib.model.NotificationTunnelState
import net.mullvad.mullvadvpn.lib.model.NotificationUpdate
+import net.mullvad.mullvadvpn.lib.pushnotification.tunnelstate.TunnelStateNotificationProvider
+import net.mullvad.mullvadvpn.lib.pushnotification.tunnelstate.toNotification
import net.mullvad.mullvadvpn.service.MullvadVpnService
-import net.mullvad.mullvadvpn.service.notifications.tunnelstate.TunnelStateNotificationProvider
-import net.mullvad.mullvadvpn.service.notifications.tunnelstate.toNotification
class ForegroundNotificationManager(
private val vpnService: MullvadVpnService,
diff --git a/android/service/src/test/kotlin/net/mullvad/mullvadvpn/service/notifications/tunnelstate/TunnelStateNotificationProviderTest.kt b/android/service/src/test/kotlin/net/mullvad/mullvadvpn/service/notifications/tunnelstate/TunnelStateNotificationProviderTest.kt
index 0595b3ac16..481c89956c 100644
--- a/android/service/src/test/kotlin/net/mullvad/mullvadvpn/service/notifications/tunnelstate/TunnelStateNotificationProviderTest.kt
+++ b/android/service/src/test/kotlin/net/mullvad/mullvadvpn/service/notifications/tunnelstate/TunnelStateNotificationProviderTest.kt
@@ -29,6 +29,7 @@ import net.mullvad.mullvadvpn.lib.model.NotificationUpdate
import net.mullvad.mullvadvpn.lib.model.PrepareError
import net.mullvad.mullvadvpn.lib.model.Prepared
import net.mullvad.mullvadvpn.lib.model.TunnelState
+import net.mullvad.mullvadvpn.lib.pushnotification.tunnelstate.TunnelStateNotificationProvider
import net.mullvad.mullvadvpn.lib.repository.ConnectionProxy
import net.mullvad.mullvadvpn.lib.repository.DeviceRepository
import net.mullvad.mullvadvpn.lib.repository.UserPreferencesRepository
diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts
index 51778bd6fa..dc349597f4 100644
--- a/android/settings.gradle.kts
+++ b/android/settings.gradle.kts
@@ -38,6 +38,7 @@ include(
":lib:common-test",
":lib:grpc",
":lib:endpoint",
+ ":lib:feature:account:impl",
":lib:feature:addtime:impl",
":lib:feature:anticensorship:impl",
":lib:feature:apiaccess:impl",
@@ -47,6 +48,9 @@ include(
":lib:feature:customlist:impl",
":lib:feature:daita:impl",
":lib:feature:filter:impl",
+ ":lib:feature:home:impl",
+ ":lib:feature:location:impl",
+ ":lib:feature:login:impl",
":lib:feature:managedevices:impl",
":lib:feature:multihop:impl",
":lib:feature:notification:impl",
@@ -60,6 +64,7 @@ include(
":lib:model",
":lib:navigation",
":lib:payment",
+ ":lib:push-notification",
":lib:repository",
":lib:screen-test",
":lib:talpid",