From 483c0fd1f158ef961e44688b7e39cb8b534f9dc8 Mon Sep 17 00:00:00 2001 From: Nikita Kulikov Date: Mon, 13 Jan 2025 13:09:32 +0000 Subject: [PATCH] Add desktop target to connection sample (#1009) **Background** Experimental desktop support added to sample to support KMP **Changes** - Add desktop target to sample - Remove unnecessary dependendencies **Test plan** Launch desktop and android project ```bash ./gradlew :components:bridge:connection:sample:desktop:run ``` --- .../flipperdevices/buildlogic/ApkConfig.kt | 2 +- ...ipper.android-app-multiplatform.gradle.kts | 100 +++++++++ .../analytics/metric/noop/build.gradle.kts | 7 +- .../metric/noop/NoopMetricAndroidApiImpl.kt | 0 .../metric/noop/NoopMetricApiImpl.kt | 0 .../shake2report/impl/build.gradle.kts | 1 - .../shake2report/noop/build.gradle.kts | 11 +- .../Shake2ReportDecomposeComponentStub.kt | 0 .../shake2report/noop/Shake2ReportStub.kt | 0 components/archive/category/build.gradle.kts | 1 - components/archive/impl/build.gradle.kts | 2 +- components/archive/search/build.gradle.kts | 1 - components/bottombar/impl/build.gradle.kts | 1 - .../api/FlipperActionNotifier.kt | 2 +- .../connection/sample/android/.gitignore | 2 + .../sample/android/build.gradle.kts | 23 +++ .../sample/{ => android}/proguard-rules.pro | 0 .../src/androidMain/AndroidManifest.xml | 3 + .../connection/ConnectionTestApplication.kt | 0 .../connection/di/AndroidAppComponent.kt | 14 ++ .../bridge/connection/sample/build.gradle.kts | 128 ------------ .../sample/desktop/build.gradle.kts | 62 ++++++ .../flipperdevices/bridge/connection/Main.kt | 19 ++ .../connection/di/DesktopAppComponent.kt | 18 ++ .../connection/sample/shared/build.gradle.kts | 121 +++++++++++ .../src/androidMain}/AndroidManifest.xml | 4 +- .../connection/ConnectionTestActivity.kt | 5 + .../bridge/connection/di/AppComponent.kt | 7 + ...ConnectionSearchDecomposeComponentImpl.kt} | 28 ++- .../screens/search/ConnectionSearchItem.kt | 0 .../search/ConnectionSearchViewModel.kt | 4 +- .../connection/utils/PermissionCheckerImpl.kt | 25 +++ .../src/androidMain/res/values/strings.xml | 2 +- .../composeResources/drawable/ic_more.xml | 10 + .../composeResources}/values/strings.xml | 0 .../ConnectionRootDecomposeComponent.kt | 27 +-- ...onnectionDeviceScreenDecomposeComponent.kt | 0 .../composable/FCurrentDeviceComposable.kt | 0 .../composable/FDeviceDropdownComposable.kt | 13 +- .../device/composable/FPingComposable.kt | 0 .../viewmodel/FCurrentDeviceViewModel.kt | 0 .../device/viewmodel/FDevicesViewModel.kt | 0 .../screens/device/viewmodel/PingViewModel.kt | 0 .../screens/models/ConnectionRootConfig.kt | 0 ...onnectionNoPermissionDecomposeComponent.kt | 7 +- .../ConnectionSearchDecomposeComponent.kt | 14 ++ .../screens/utils/PermissionChecker.kt | 5 + .../flipperdevices/bridge/connection/App.kt | 53 +++++ .../bridge/connection/di/AppComponent.kt | 10 + .../ConnectionSearchDecomposeComponentNoop.kt | 19 ++ .../connection/utils/PermissionCheckerNoop.kt | 11 + .../bridge/connection/utils/Utils.kt | 25 +++ .../bridge/connection/di/AppComponent.kt | 25 --- .../{sample => transport/usb/api}/.gitignore | 0 .../transport/usb/api/build.gradle.kts | 12 ++ .../connection/transport/usb/api/FUSBApi.kt | 5 + .../usb/api/FUSBDeviceConnectionConfig.kt | 7 + .../usb/api/USBDeviceConnectionApi.kt | 13 ++ .../connection/transport/usb/impl/.gitignore | 1 + .../transport/usb/impl/build.gradle.kts | 26 +++ .../usb/impl/USBDeviceConnectionApiImpl.kt | 101 ++++++++++ .../usb/impl/di/BleDeviceConnectionModule.kt | 25 +++ .../usb/impl/serial/FUSBSerialDeviceApi.kt | 67 +++++++ .../transport/usb/impl/serial/SpeedMeter.kt | 42 ++++ components/bridge/pbutils/src/main/proto | 2 +- .../bridge/service/impl/build.gradle.kts | 2 +- components/connection/impl/build.gradle.kts | 2 +- components/core/data/build.gradle.kts | 3 +- .../FlipperSharedPreferenceModule.kt | 4 +- components/core/ui/decompose/build.gradle.kts | 4 - components/core/ui/dialog/build.gradle.kts | 6 - .../core/ui/flippermockup/build.gradle.kts | 6 - components/core/ui/ktx/build.gradle.kts | 2 +- components/core/ui/lifecycle/build.gradle.kts | 7 +- .../drawable/material_ic_close.xml | 9 + .../drawable/material_ic_folder.xml | 9 + components/core/ui/scrollbar/build.gradle.kts | 6 - components/core/ui/searchbar/build.gradle.kts | 6 - components/core/ui/tabswitch/build.gradle.kts | 6 - components/core/ui/theme/build.gradle.kts | 3 - components/debug/stresstest/build.gradle.kts | 1 - components/deeplink/api/build.gradle.kts | 3 +- .../faphub/catalogtab/impl/build.gradle.kts | 2 - .../faphub/category/impl/build.gradle.kts | 2 - .../faphub/fapscreen/impl/build.gradle.kts | 2 +- .../installation/button/impl/build.gradle.kts | 2 +- .../faphub/installedtab/impl/build.gradle.kts | 2 - .../faphub/report/impl/build.gradle.kts | 1 - .../screenshotspreview/impl/build.gradle.kts | 2 +- .../faphub/search/impl/build.gradle.kts | 1 - .../uninstallbutton/impl/build.gradle.kts | 1 - components/filemanager/impl/build.gradle.kts | 1 - .../filemngr/create/api/build.gradle.kts | 3 +- .../filemngr/create/impl/build.gradle.kts | 4 - .../filemngr/download/api/build.gradle.kts | 2 +- .../filemngr/download/impl/build.gradle.kts | 4 - .../api/DownloadDecomposeComponentImpl.kt | 8 +- .../filemngr/editor/api/build.gradle.kts | 1 - .../filemngr/editor/impl/build.gradle.kts | 9 - .../filemngr/listing/api/build.gradle.kts | 1 - .../filemngr/listing/impl/build.gradle.kts | 17 +- .../composable/appbar/CloseSelectionAppBar.kt | 8 +- components/filemngr/main/api/build.gradle.kts | 1 - .../filemngr/main/impl/build.gradle.kts | 8 - .../filemngr/rename/api/build.gradle.kts | 1 - .../filemngr/rename/impl/build.gradle.kts | 4 - .../filemngr/search/api/build.gradle.kts | 1 - .../filemngr/search/impl/build.gradle.kts | 9 - .../filemngr/transfer/api/build.gradle.kts | 1 - .../filemngr/transfer/impl/build.gradle.kts | 9 - .../filemngr/ui-components/build.gradle.kts | 7 - .../FolderCardListComposablePreview.kt | 9 +- .../ui/components/name/NameDialog.kt | 8 +- .../filemngr/upload/api/build.gradle.kts | 1 - .../filemngr/upload/impl/build.gradle.kts | 11 +- .../impl/api/UploadDecomposeComponentNoop.kt | 28 +++ components/info/impl/build.gradle.kts | 2 +- components/infrared/editor/build.gradle.kts | 1 - components/infrared/impl/build.gradle.kts | 2 +- components/keyedit/impl/build.gradle.kts | 1 - components/keyemulate/impl/build.gradle.kts | 2 +- components/keyscreen/impl/build.gradle.kts | 2 +- components/newfilemanager/api/.gitignore | 1 - .../newfilemanager/api/build.gradle.kts | 15 -- .../FileManagerDecomposeComponent.kt | 14 -- components/newfilemanager/impl/.gitignore | 1 - .../newfilemanager/impl/build.gradle.kts | 53 ----- .../composeResources/values/strings.xml | 32 --- .../api/FileManagerDecomposeComponentImpl.kt | 65 ------ .../impl/api/FileManagerDownloadComponent.kt | 64 ------ .../impl/api/FileManagerEditingComponent.kt | 45 ----- .../impl/api/FileManagerListingComponent.kt | 68 ------- .../impl/api/FileManagerUploadingComponent.kt | 54 ----- .../ComposableFileManagerDownloadScreen.kt | 47 ----- .../ComposableFileManagerEditorScreen.kt | 157 --------------- .../composable/ComposableFileManagerScreen.kt | 189 ------------------ .../ComposableFileManagerUploadedScreen.kt | 48 ----- .../composable/bar/ComposableEditorTopBar.kt | 41 ---- .../bar/ComposableEllipsizeStartText.kt | 81 -------- .../bar/ComposableFileManagerTopBar.kt | 66 ------ .../dialog/ComposableInputDialog.kt | 102 ---------- .../dialog/ComposableProgressDialog.kt | 164 --------------- .../dialog/ComposableSelectDialog.kt | 61 ------ .../composable/list/ComposableFileItem.kt | 103 ---------- .../list/ComposableFileManagerContent.kt | 71 ------- .../impl/model/CreateFileManagerAction.kt | 6 - .../impl/model/DownloadProgress.kt | 24 --- .../newfilemanager/impl/model/EditorState.kt | 21 -- .../newfilemanager/impl/model/FileItem.kt | 27 --- .../impl/model/FileManagerNavigationConfig.kt | 25 --- .../impl/model/FileManagerState.kt | 18 -- .../newfilemanager/impl/model/ShareFile.kt | 12 -- .../newfilemanager/impl/model/ShareState.kt | 11 - .../newfilemanager/impl/model/SpeedState.kt | 17 -- .../impl/viewmodels/CommonShareViewModel.kt | 73 ------- .../impl/viewmodels/EditorViewModel.kt | 160 --------------- .../impl/viewmodels/FileManagerViewModel.kt | 188 ----------------- .../impl/viewmodels/ReceiveViewModel.kt | 92 --------- .../impl/viewmodels/ShareViewModel.kt | 87 -------- .../src/androidMain/res/drawable/ic_file.xml | 11 - .../androidMain/res/drawable/ic_folder.xml | 10 - .../src/androidMain/res/drawable/ic_ok.xml | 10 - .../src/androidMain/res/drawable/ic_plus.xml | 10 - .../nfc/mfkey32/screen/build.gradle.kts | 1 - .../screenstreaming/impl/build.gradle.kts | 2 +- components/settings/impl/build.gradle.kts | 1 - components/share/receive/build.gradle.kts | 2 +- components/share/uploader/build.gradle.kts | 2 +- components/updater/card/build.gradle.kts | 1 - components/widget/screen/build.gradle.kts | 2 - .../root/impl.build.gradle.kts.ftl | 2 +- .../root/impl.build.gradle.kts.ftl | 2 +- .../Simple Module/root/build.gradle.kts.ftl | 2 +- gradle/libs.versions.toml | 13 +- settings.gradle.kts | 8 +- 175 files changed, 1007 insertions(+), 2748 deletions(-) create mode 100644 build-logic/plugins/convention/src/main/kotlin/flipper.android-app-multiplatform.gradle.kts rename components/analytics/metric/noop/src/{main/java => androidMain/kotlin}/com/flipperdevices/metric/noop/NoopMetricAndroidApiImpl.kt (100%) rename components/analytics/metric/noop/src/{main/java => commonMain/kotlin}/com/flipperdevices/metric/noop/NoopMetricApiImpl.kt (100%) rename components/analytics/shake2report/noop/src/{main/java => commonMain/kotlin}/com/flipperdevices/shake2report/noop/Shake2ReportDecomposeComponentStub.kt (100%) rename components/analytics/shake2report/noop/src/{main/java => commonMain/kotlin}/com/flipperdevices/shake2report/noop/Shake2ReportStub.kt (100%) create mode 100644 components/bridge/connection/sample/android/.gitignore create mode 100644 components/bridge/connection/sample/android/build.gradle.kts rename components/bridge/connection/sample/{ => android}/proguard-rules.pro (100%) create mode 100644 components/bridge/connection/sample/android/src/androidMain/AndroidManifest.xml rename components/bridge/connection/sample/{src/main => android/src/androidMain}/kotlin/com/flipperdevices/bridge/connection/ConnectionTestApplication.kt (100%) create mode 100644 components/bridge/connection/sample/android/src/androidMain/kotlin/com/flipperdevices/bridge/connection/di/AndroidAppComponent.kt delete mode 100644 components/bridge/connection/sample/build.gradle.kts create mode 100644 components/bridge/connection/sample/desktop/build.gradle.kts create mode 100644 components/bridge/connection/sample/desktop/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/Main.kt create mode 100644 components/bridge/connection/sample/desktop/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/di/DesktopAppComponent.kt create mode 100644 components/bridge/connection/sample/shared/build.gradle.kts rename components/bridge/connection/sample/{src/main => shared/src/androidMain}/AndroidManifest.xml (78%) rename components/bridge/connection/sample/{src/main => shared/src/androidMain}/kotlin/com/flipperdevices/bridge/connection/ConnectionTestActivity.kt (91%) create mode 100644 components/bridge/connection/sample/shared/src/androidMain/kotlin/com/flipperdevices/bridge/connection/di/AppComponent.kt rename components/bridge/connection/sample/{src/main/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchDecomposeComponent.kt => shared/src/androidMain/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchDecomposeComponentImpl.kt} (77%) rename components/bridge/connection/sample/{src/main => shared/src/androidMain}/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchItem.kt (100%) rename components/bridge/connection/sample/{src/main => shared/src/androidMain}/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchViewModel.kt (95%) create mode 100644 components/bridge/connection/sample/shared/src/androidMain/kotlin/com/flipperdevices/bridge/connection/utils/PermissionCheckerImpl.kt rename components/{newfilemanager/impl => bridge/connection/sample/shared}/src/androidMain/res/values/strings.xml (50%) create mode 100644 components/bridge/connection/sample/shared/src/commonMain/composeResources/drawable/ic_more.xml rename components/bridge/connection/sample/{src/main/res => shared/src/commonMain/composeResources}/values/strings.xml (100%) rename components/bridge/connection/sample/{src/main => shared/src/commonMain}/kotlin/com/flipperdevices/bridge/connection/screens/ConnectionRootDecomposeComponent.kt (74%) rename components/bridge/connection/sample/{src/main => shared/src/commonMain}/kotlin/com/flipperdevices/bridge/connection/screens/device/ConnectionDeviceScreenDecomposeComponent.kt (100%) rename components/bridge/connection/sample/{src/main => shared/src/commonMain}/kotlin/com/flipperdevices/bridge/connection/screens/device/composable/FCurrentDeviceComposable.kt (100%) rename components/bridge/connection/sample/{src/main => shared/src/commonMain}/kotlin/com/flipperdevices/bridge/connection/screens/device/composable/FDeviceDropdownComposable.kt (86%) rename components/bridge/connection/sample/{src/main => shared/src/commonMain}/kotlin/com/flipperdevices/bridge/connection/screens/device/composable/FPingComposable.kt (100%) rename components/bridge/connection/sample/{src/main => shared/src/commonMain}/kotlin/com/flipperdevices/bridge/connection/screens/device/viewmodel/FCurrentDeviceViewModel.kt (100%) rename components/bridge/connection/sample/{src/main => shared/src/commonMain}/kotlin/com/flipperdevices/bridge/connection/screens/device/viewmodel/FDevicesViewModel.kt (100%) rename components/bridge/connection/sample/{src/main => shared/src/commonMain}/kotlin/com/flipperdevices/bridge/connection/screens/device/viewmodel/PingViewModel.kt (100%) rename components/bridge/connection/sample/{src/main => shared/src/commonMain}/kotlin/com/flipperdevices/bridge/connection/screens/models/ConnectionRootConfig.kt (100%) rename components/bridge/connection/sample/{src/main => shared/src/commonMain}/kotlin/com/flipperdevices/bridge/connection/screens/nopermission/ConnectionNoPermissionDecomposeComponent.kt (72%) create mode 100644 components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchDecomposeComponent.kt create mode 100644 components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/utils/PermissionChecker.kt create mode 100644 components/bridge/connection/sample/shared/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/App.kt create mode 100644 components/bridge/connection/sample/shared/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/di/AppComponent.kt create mode 100644 components/bridge/connection/sample/shared/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchDecomposeComponentNoop.kt create mode 100644 components/bridge/connection/sample/shared/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/utils/PermissionCheckerNoop.kt create mode 100644 components/bridge/connection/sample/shared/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/utils/Utils.kt delete mode 100644 components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/di/AppComponent.kt rename components/bridge/connection/{sample => transport/usb/api}/.gitignore (100%) create mode 100644 components/bridge/connection/transport/usb/api/build.gradle.kts create mode 100644 components/bridge/connection/transport/usb/api/src/commonMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/api/FUSBApi.kt create mode 100644 components/bridge/connection/transport/usb/api/src/commonMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/api/FUSBDeviceConnectionConfig.kt create mode 100644 components/bridge/connection/transport/usb/api/src/commonMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/api/USBDeviceConnectionApi.kt create mode 100644 components/bridge/connection/transport/usb/impl/.gitignore create mode 100644 components/bridge/connection/transport/usb/impl/build.gradle.kts create mode 100644 components/bridge/connection/transport/usb/impl/src/jvmSharedMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/impl/USBDeviceConnectionApiImpl.kt create mode 100644 components/bridge/connection/transport/usb/impl/src/jvmSharedMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/impl/di/BleDeviceConnectionModule.kt create mode 100644 components/bridge/connection/transport/usb/impl/src/jvmSharedMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/impl/serial/FUSBSerialDeviceApi.kt create mode 100644 components/bridge/connection/transport/usb/impl/src/jvmSharedMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/impl/serial/SpeedMeter.kt create mode 100644 components/core/ui/res/src/commonMain/composeResources/drawable/material_ic_close.xml create mode 100644 components/core/ui/res/src/commonMain/composeResources/drawable/material_ic_folder.xml create mode 100644 components/filemngr/upload/impl/src/desktopMain/kotlin/com/flipperdevices/filemanager/upload/impl/api/UploadDecomposeComponentNoop.kt delete mode 100644 components/newfilemanager/api/.gitignore delete mode 100644 components/newfilemanager/api/build.gradle.kts delete mode 100644 components/newfilemanager/api/src/commonMain/kotlin/com/flipperdevices/newfilemanager/api/navigation/FileManagerDecomposeComponent.kt delete mode 100644 components/newfilemanager/impl/.gitignore delete mode 100644 components/newfilemanager/impl/build.gradle.kts delete mode 100644 components/newfilemanager/impl/src/androidMain/composeResources/values/strings.xml delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/api/FileManagerDecomposeComponentImpl.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/api/FileManagerDownloadComponent.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/api/FileManagerEditingComponent.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/api/FileManagerListingComponent.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/api/FileManagerUploadingComponent.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/ComposableFileManagerDownloadScreen.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/ComposableFileManagerEditorScreen.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/ComposableFileManagerScreen.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/ComposableFileManagerUploadedScreen.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/bar/ComposableEditorTopBar.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/bar/ComposableEllipsizeStartText.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/bar/ComposableFileManagerTopBar.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/dialog/ComposableInputDialog.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/dialog/ComposableProgressDialog.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/dialog/ComposableSelectDialog.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/list/ComposableFileItem.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/list/ComposableFileManagerContent.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/CreateFileManagerAction.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/DownloadProgress.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/EditorState.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/FileItem.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/FileManagerNavigationConfig.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/FileManagerState.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/ShareFile.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/ShareState.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/SpeedState.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/viewmodels/CommonShareViewModel.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/viewmodels/EditorViewModel.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/viewmodels/FileManagerViewModel.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/viewmodels/ReceiveViewModel.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/viewmodels/ShareViewModel.kt delete mode 100644 components/newfilemanager/impl/src/androidMain/res/drawable/ic_file.xml delete mode 100644 components/newfilemanager/impl/src/androidMain/res/drawable/ic_folder.xml delete mode 100644 components/newfilemanager/impl/src/androidMain/res/drawable/ic_ok.xml delete mode 100644 components/newfilemanager/impl/src/androidMain/res/drawable/ic_plus.xml diff --git a/build-logic/plugins/convention/src/main/kotlin/com/flipperdevices/buildlogic/ApkConfig.kt b/build-logic/plugins/convention/src/main/kotlin/com/flipperdevices/buildlogic/ApkConfig.kt index 6e8ec6ea21..b44e3e9043 100644 --- a/build-logic/plugins/convention/src/main/kotlin/com/flipperdevices/buildlogic/ApkConfig.kt +++ b/build-logic/plugins/convention/src/main/kotlin/com/flipperdevices/buildlogic/ApkConfig.kt @@ -12,7 +12,7 @@ object ApkConfig { const val COMPILE_SDK_VERSION = 35 const val ROBOELECTRIC_SDK_VERSION = 34 - private const val DEBUG_VERSION = "DEBUG_VERSION" + private const val DEBUG_VERSION = "1.0.0" val Project.VERSION_CODE get() = prop("version_code", Integer.MAX_VALUE).toInt() diff --git a/build-logic/plugins/convention/src/main/kotlin/flipper.android-app-multiplatform.gradle.kts b/build-logic/plugins/convention/src/main/kotlin/flipper.android-app-multiplatform.gradle.kts new file mode 100644 index 0000000000..ce288aead3 --- /dev/null +++ b/build-logic/plugins/convention/src/main/kotlin/flipper.android-app-multiplatform.gradle.kts @@ -0,0 +1,100 @@ +import com.android.build.gradle.BaseExtension +import com.flipperdevices.buildlogic.ApkConfig +import com.flipperdevices.buildlogic.ApkConfig.IS_SENTRY_PUBLISH +import gradle.kotlin.dsl.accessors._7a4d13f58a317316fed3ebe1f66c7d31.compose +import gradle.kotlin.dsl.accessors._7a4d13f58a317316fed3ebe1f66c7d31.kotlin +import gradle.kotlin.dsl.accessors._7a4d13f58a317316fed3ebe1f66c7d31.sourceSets +import io.sentry.android.gradle.extensions.SentryPluginExtension +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + id("com.android.application") + id("org.jetbrains.kotlin.multiplatform") + id("io.sentry.android.gradle") + id("flipper.lint") + id("org.jetbrains.compose") + id("org.jetbrains.kotlin.plugin.compose") +} + +@Suppress("UnstableApiUsage") +configure { + commonAndroid(project) + + defaultConfig { + applicationId = ApkConfig.APPLICATION_ID + } + + buildTypes { + internal { + isShrinkResources = true + isMinifyEnabled = true + consumerProguardFile( + "proguard-rules.pro" + ) + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + release { + isShrinkResources = true + isMinifyEnabled = true + consumerProguardFile( + "proguard-rules.pro" + ) + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } +} + +@OptIn(ExperimentalKotlinGradlePluginApi::class) +kotlin { + androidTarget { + compilerOptions { + jvmTarget = JvmTarget.JVM_1_8 + } + } + jvm("desktop") + + applyDefaultHierarchyTemplate { + common { + group("jvmShared") { + withAndroidTarget() + withJvm() + } + } + } + + sourceSets { + androidMain.dependencies { + implementation(libs.compose.tooling) + } + commonMain.dependencies { + implementation(compose.runtime) + implementation(compose.foundation) + implementation(compose.material) + implementation(compose.ui) + implementation(compose.components.resources) + implementation(compose.components.uiToolingPreview) + } + val desktopMain by getting + desktopMain.dependencies { + implementation(compose.desktop.currentOs) + } + } +} + +includeCommonKspConfigurationTo("kspAndroid", "kspDesktop") + +configure { + autoUploadProguardMapping.set(IS_SENTRY_PUBLISH) + telemetry.set(false) + + ignoredBuildTypes.set(setOf("release", "debug")) + + autoInstallation.enabled.set(false) +} diff --git a/components/analytics/metric/noop/build.gradle.kts b/components/analytics/metric/noop/build.gradle.kts index 5021ef0fc7..9d40e5ae44 100644 --- a/components/analytics/metric/noop/build.gradle.kts +++ b/components/analytics/metric/noop/build.gradle.kts @@ -1,11 +1,12 @@ plugins { - id("flipper.android-lib") - id("flipper.anvil") + id("flipper.multiplatform") + id("flipper.multiplatform-dependencies") + id("flipper.anvil-multiplatform") } android.namespace = "com.flipperdevices.metric.noop" -dependencies { +commonDependencies { implementation(projects.components.analytics.metric.api) implementation(projects.components.core.di) diff --git a/components/analytics/metric/noop/src/main/java/com/flipperdevices/metric/noop/NoopMetricAndroidApiImpl.kt b/components/analytics/metric/noop/src/androidMain/kotlin/com/flipperdevices/metric/noop/NoopMetricAndroidApiImpl.kt similarity index 100% rename from components/analytics/metric/noop/src/main/java/com/flipperdevices/metric/noop/NoopMetricAndroidApiImpl.kt rename to components/analytics/metric/noop/src/androidMain/kotlin/com/flipperdevices/metric/noop/NoopMetricAndroidApiImpl.kt diff --git a/components/analytics/metric/noop/src/main/java/com/flipperdevices/metric/noop/NoopMetricApiImpl.kt b/components/analytics/metric/noop/src/commonMain/kotlin/com/flipperdevices/metric/noop/NoopMetricApiImpl.kt similarity index 100% rename from components/analytics/metric/noop/src/main/java/com/flipperdevices/metric/noop/NoopMetricApiImpl.kt rename to components/analytics/metric/noop/src/commonMain/kotlin/com/flipperdevices/metric/noop/NoopMetricApiImpl.kt diff --git a/components/analytics/shake2report/impl/build.gradle.kts b/components/analytics/shake2report/impl/build.gradle.kts index d5a614adfc..6425dfc5bf 100644 --- a/components/analytics/shake2report/impl/build.gradle.kts +++ b/components/analytics/shake2report/impl/build.gradle.kts @@ -25,7 +25,6 @@ dependencies { implementation(libs.kotlin.coroutines) implementation(libs.kotlin.immutable.collections) implementation(libs.lifecycle.runtime.ktx) - implementation(libs.lifecycle.viewmodel.ktx) implementation(libs.timber) implementation(libs.timber.tressence) diff --git a/components/analytics/shake2report/noop/build.gradle.kts b/components/analytics/shake2report/noop/build.gradle.kts index 394fedb7b5..88331432b9 100644 --- a/components/analytics/shake2report/noop/build.gradle.kts +++ b/components/analytics/shake2report/noop/build.gradle.kts @@ -1,20 +1,17 @@ plugins { - id("flipper.android-compose") - id("flipper.anvil") + id("flipper.multiplatform-compose") + id("flipper.multiplatform-dependencies") + id("flipper.anvil-multiplatform") } android.namespace = "com.flipperdevices.shake2report.noop" -dependencies { +commonDependencies { implementation(projects.components.analytics.shake2report.api) - implementation(projects.components.bridge.api) implementation(projects.components.core.di) implementation(projects.components.core.ui.decompose) implementation(libs.annotations) - implementation(libs.appcompat) - - implementation(libs.compose.ui) implementation(libs.bundles.decompose) } diff --git a/components/analytics/shake2report/noop/src/main/java/com/flipperdevices/shake2report/noop/Shake2ReportDecomposeComponentStub.kt b/components/analytics/shake2report/noop/src/commonMain/kotlin/com/flipperdevices/shake2report/noop/Shake2ReportDecomposeComponentStub.kt similarity index 100% rename from components/analytics/shake2report/noop/src/main/java/com/flipperdevices/shake2report/noop/Shake2ReportDecomposeComponentStub.kt rename to components/analytics/shake2report/noop/src/commonMain/kotlin/com/flipperdevices/shake2report/noop/Shake2ReportDecomposeComponentStub.kt diff --git a/components/analytics/shake2report/noop/src/main/java/com/flipperdevices/shake2report/noop/Shake2ReportStub.kt b/components/analytics/shake2report/noop/src/commonMain/kotlin/com/flipperdevices/shake2report/noop/Shake2ReportStub.kt similarity index 100% rename from components/analytics/shake2report/noop/src/main/java/com/flipperdevices/shake2report/noop/Shake2ReportStub.kt rename to components/analytics/shake2report/noop/src/commonMain/kotlin/com/flipperdevices/shake2report/noop/Shake2ReportStub.kt diff --git a/components/archive/category/build.gradle.kts b/components/archive/category/build.gradle.kts index 7baead7a71..31934dc50d 100644 --- a/components/archive/category/build.gradle.kts +++ b/components/archive/category/build.gradle.kts @@ -38,7 +38,6 @@ dependencies { implementation(libs.compose.material) implementation(libs.bundles.decompose) - implementation(libs.lifecycle.viewmodel.ktx) implementation(libs.lifecycle.compose) implementation(libs.kotlin.immutable.collections) diff --git a/components/archive/impl/build.gradle.kts b/components/archive/impl/build.gradle.kts index c191367d79..e49c134e88 100644 --- a/components/archive/impl/build.gradle.kts +++ b/components/archive/impl/build.gradle.kts @@ -54,6 +54,6 @@ dependencies { // Lifecycle implementation(libs.lifecycle.runtime.ktx) - implementation(libs.lifecycle.viewmodel.ktx) + implementation(libs.lifecycle.compose) } diff --git a/components/archive/search/build.gradle.kts b/components/archive/search/build.gradle.kts index 19cd0d22ff..f17e0eb2e2 100644 --- a/components/archive/search/build.gradle.kts +++ b/components/archive/search/build.gradle.kts @@ -37,7 +37,6 @@ dependencies { implementation(libs.bundles.decompose) implementation(libs.lifecycle.compose) - implementation(libs.lifecycle.viewmodel.ktx) implementation(libs.kotlin.immutable.collections) } diff --git a/components/bottombar/impl/build.gradle.kts b/components/bottombar/impl/build.gradle.kts index ea16fb584f..ebb21c3de2 100644 --- a/components/bottombar/impl/build.gradle.kts +++ b/components/bottombar/impl/build.gradle.kts @@ -45,5 +45,4 @@ dependencies { implementation(libs.kotlin.coroutines) implementation(libs.kotlin.immutable.collections) implementation(libs.lifecycle.runtime.ktx) - implementation(libs.lifecycle.viewmodel.ktx) } diff --git a/components/bridge/connection/feature/actionnotifier/api/src/commonMain/kotlin/com/flipperdevices/bridge/connection/feature/actionnotifier/api/FlipperActionNotifier.kt b/components/bridge/connection/feature/actionnotifier/api/src/commonMain/kotlin/com/flipperdevices/bridge/connection/feature/actionnotifier/api/FlipperActionNotifier.kt index 61f495e5cc..2087d8a359 100644 --- a/components/bridge/connection/feature/actionnotifier/api/src/commonMain/kotlin/com/flipperdevices/bridge/connection/feature/actionnotifier/api/FlipperActionNotifier.kt +++ b/components/bridge/connection/feature/actionnotifier/api/src/commonMain/kotlin/com/flipperdevices/bridge/connection/feature/actionnotifier/api/FlipperActionNotifier.kt @@ -9,6 +9,6 @@ interface FlipperActionNotifier { fun notifyAboutAction() fun interface Factory { - fun invoke(scope: CoroutineScope): FlipperActionNotifier + operator fun invoke(scope: CoroutineScope): FlipperActionNotifier } } diff --git a/components/bridge/connection/sample/android/.gitignore b/components/bridge/connection/sample/android/.gitignore new file mode 100644 index 0000000000..da1989017e --- /dev/null +++ b/components/bridge/connection/sample/android/.gitignore @@ -0,0 +1,2 @@ +/build +internal \ No newline at end of file diff --git a/components/bridge/connection/sample/android/build.gradle.kts b/components/bridge/connection/sample/android/build.gradle.kts new file mode 100644 index 0000000000..9f3d162e62 --- /dev/null +++ b/components/bridge/connection/sample/android/build.gradle.kts @@ -0,0 +1,23 @@ +plugins { + id("flipper.android-app-multiplatform") + id("com.google.devtools.ksp") + id("flipper.anvil.entrypoint") + id("kotlinx-serialization") + id("flipper.multiplatform-dependencies") +} + +android.namespace = "com.flipperdevices.bridge.connection.sample.android" + +android { + defaultConfig { + applicationId = "com.flipperdevices.bridge.connection" + } +} + +commonDependencies { + implementation(projects.components.bridge.connection.sample.shared) +} + +dependencies { + commonKsp(libs.dagger.compiler) +} diff --git a/components/bridge/connection/sample/proguard-rules.pro b/components/bridge/connection/sample/android/proguard-rules.pro similarity index 100% rename from components/bridge/connection/sample/proguard-rules.pro rename to components/bridge/connection/sample/android/proguard-rules.pro diff --git a/components/bridge/connection/sample/android/src/androidMain/AndroidManifest.xml b/components/bridge/connection/sample/android/src/androidMain/AndroidManifest.xml new file mode 100644 index 0000000000..8fc9bb4f45 --- /dev/null +++ b/components/bridge/connection/sample/android/src/androidMain/AndroidManifest.xml @@ -0,0 +1,3 @@ + + \ No newline at end of file diff --git a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/ConnectionTestApplication.kt b/components/bridge/connection/sample/android/src/androidMain/kotlin/com/flipperdevices/bridge/connection/ConnectionTestApplication.kt similarity index 100% rename from components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/ConnectionTestApplication.kt rename to components/bridge/connection/sample/android/src/androidMain/kotlin/com/flipperdevices/bridge/connection/ConnectionTestApplication.kt diff --git a/components/bridge/connection/sample/android/src/androidMain/kotlin/com/flipperdevices/bridge/connection/di/AndroidAppComponent.kt b/components/bridge/connection/sample/android/src/androidMain/kotlin/com/flipperdevices/bridge/connection/di/AndroidAppComponent.kt new file mode 100644 index 0000000000..175ce43341 --- /dev/null +++ b/components/bridge/connection/sample/android/src/androidMain/kotlin/com/flipperdevices/bridge/connection/di/AndroidAppComponent.kt @@ -0,0 +1,14 @@ +package com.flipperdevices.bridge.connection.di + +@Singleton +@MergeComponent(AppGraph::class) +interface AndroidAppComponent : AppComponent { + @MergeComponent.Factory + interface Factory { + fun create( + @BindsInstance context: Context, + @BindsInstance application: Application, + @BindsInstance applicationParams: ApplicationParams + ): AndroidAppComponent + } +} diff --git a/components/bridge/connection/sample/build.gradle.kts b/components/bridge/connection/sample/build.gradle.kts deleted file mode 100644 index f4f02c79fc..0000000000 --- a/components/bridge/connection/sample/build.gradle.kts +++ /dev/null @@ -1,128 +0,0 @@ -plugins { - id("flipper.android-app") - id("flipper.anvil.entrypoint") - id("kotlinx-serialization") -} - -android.namespace = "com.flipperdevices.bridge.connection" - -android { - buildFeatures.compose = true -} - -android { - defaultConfig { - applicationId = "com.flipperdevices.bridge.connection" - } -} - -dependencies { - implementation(projects.components.core.ui.res) - implementation(projects.components.core.ui.theme) - implementation(projects.components.core.ui.lifecycle) - implementation(projects.components.core.ui.decompose) - implementation(projects.components.core.ui.ktx) - implementation(projects.components.core.di) - implementation(projects.components.core.log) - implementation(projects.components.core.preference) - implementation(projects.components.core.storage) - implementation(projects.components.core.share) - - implementation(projects.components.bridge.connection.transport.ble.api) - implementation(projects.components.bridge.connection.transport.ble.impl) - implementation(projects.components.bridge.connection.transport.common.api) - implementation(projects.components.bridge.connection.transport.common.impl) - implementation(projects.components.bridge.connection.orchestrator.api) - implementation(projects.components.bridge.connection.orchestrator.impl) - implementation(projects.components.bridge.connection.connectionbuilder.api) - implementation(projects.components.bridge.connection.connectionbuilder.impl) - implementation(projects.components.bridge.connection.config.api) - implementation(projects.components.bridge.connection.config.impl) - implementation(projects.components.bridge.connection.transportconfigbuilder.api) - implementation(projects.components.bridge.connection.transportconfigbuilder.impl) - implementation(projects.components.bridge.connection.device.common.api) - implementation(projects.components.bridge.connection.device.fzero.api) - implementation(projects.components.bridge.connection.device.fzero.impl) - implementation(projects.components.bridge.connection.feature.common.api) - implementation(projects.components.bridge.connection.feature.getinfo.api) - implementation(projects.components.bridge.connection.feature.getinfo.impl) - implementation(projects.components.bridge.connection.feature.lagsdetector.api) - implementation(projects.components.bridge.connection.feature.lagsdetector.impl) - implementation(projects.components.bridge.connection.feature.actionnotifier.api) - implementation(projects.components.bridge.connection.feature.protocolversion.api) - implementation(projects.components.bridge.connection.feature.protocolversion.impl) - implementation(projects.components.bridge.connection.feature.provider.api) - implementation(projects.components.bridge.connection.feature.provider.impl) - implementation(projects.components.bridge.connection.feature.restartrpc.api) - implementation(projects.components.bridge.connection.feature.restartrpc.impl) - implementation(projects.components.bridge.connection.feature.rpc.api) - implementation(projects.components.bridge.connection.feature.rpc.impl) - implementation(projects.components.bridge.connection.feature.rpcinfo.api) - implementation(projects.components.bridge.connection.feature.rpcinfo.impl) - implementation(projects.components.bridge.connection.feature.rpcstats.api) - implementation(projects.components.bridge.connection.feature.rpcstats.impl) - implementation(projects.components.bridge.connection.feature.serialspeed.api) - implementation(projects.components.bridge.connection.feature.serialspeed.impl) - implementation(projects.components.bridge.connection.feature.storage.api) - implementation(projects.components.bridge.connection.feature.storage.impl) - implementation(projects.components.bridge.connection.feature.storageinfo.api) - implementation(projects.components.bridge.connection.feature.storageinfo.impl) - - implementation(projects.components.analytics.shake2report.api) - implementation(projects.components.analytics.shake2report.noop) - - implementation(projects.components.analytics.metric.api) - implementation(projects.components.analytics.metric.noop) - - implementation(projects.components.bridge.api) - implementation(projects.components.bridge.connection.pbutils) - - implementation(projects.components.filemngr.main.api) - implementation(projects.components.filemngr.main.impl) - implementation(projects.components.filemngr.listing.api) - implementation(projects.components.filemngr.listing.impl) - implementation(projects.components.filemngr.upload.api) - implementation(projects.components.filemngr.upload.impl) - implementation(projects.components.filemngr.search.api) - implementation(projects.components.filemngr.search.impl) - implementation(projects.components.filemngr.editor.api) - implementation(projects.components.filemngr.editor.impl) - implementation(projects.components.filemngr.download.api) - implementation(projects.components.filemngr.download.impl) - implementation(projects.components.filemngr.rename.api) - implementation(projects.components.filemngr.rename.impl) - implementation(projects.components.filemngr.create.api) - implementation(projects.components.filemngr.create.impl) - implementation(projects.components.filemngr.transfer.api) - implementation(projects.components.filemngr.transfer.impl) - - implementation(projects.components.newfilemanager.api) - implementation(projects.components.newfilemanager.impl) - - implementation(projects.components.keyparser.api) - implementation(projects.components.keyparser.impl) - - implementation(projects.components.deeplink.api) - implementation(projects.components.deeplink.impl) - - implementation(libs.appcompat) - - // Dagger deps - implementation(libs.dagger) - commonKsp(libs.dagger.compiler) - - implementation(libs.timber) - - implementation(libs.ble.kotlin.scanner) - implementation(libs.ble.kotlin.client) - - implementation(libs.kotlin.immutable.collections) - - // Compose - implementation(libs.compose.activity) - implementation(libs.compose.ui) - implementation(libs.compose.tooling) - implementation(libs.bundles.decompose) - implementation(libs.compose.foundation) - implementation(libs.compose.material) -} diff --git a/components/bridge/connection/sample/desktop/build.gradle.kts b/components/bridge/connection/sample/desktop/build.gradle.kts new file mode 100644 index 0000000000..6d42495f3a --- /dev/null +++ b/components/bridge/connection/sample/desktop/build.gradle.kts @@ -0,0 +1,62 @@ +import com.flipperdevices.buildlogic.ApkConfig.VERSION_NAME +import org.jetbrains.compose.desktop.application.dsl.TargetFormat + +plugins { + id("org.jetbrains.kotlin.multiplatform") + id("flipper.lint") + id("org.jetbrains.compose") + id("org.jetbrains.kotlin.plugin.compose") + id("flipper.multiplatform-dependencies") + id("com.google.devtools.ksp") + id("dev.zacsweers.anvil") +} + +kotlin { + jvm("desktop") { + withJava() + } + + sourceSets { + val desktopMain by getting + desktopMain.dependencies { + implementation(compose.desktop.currentOs) + } + } +} + +includeCommonKspConfigurationTo("kspDesktop") + +compose.desktop { + application { + mainClass = "com.flipperdevices.bridge.connection.MainKt" + + nativeDistributions { + targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb) + packageName = "Flipper App" + packageVersion = project.VERSION_NAME + } + } +} + +commonDependencies { + implementation(projects.components.bridge.connection.sample.shared) + + implementation(libs.kotlin.coroutines.swing) +} + +anvil { + useKsp( + contributesAndFactoryGeneration = true, + componentMerging = true, + ) +} + +dependencies { + "implementation"(libs.dagger) + "implementation"(libs.anvil.utils.annotations) + "commonKsp"(libs.anvil.utils.compiler) +} + +dependencies { + ksp(libs.dagger.compiler) +} diff --git a/components/bridge/connection/sample/desktop/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/Main.kt b/components/bridge/connection/sample/desktop/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/Main.kt new file mode 100644 index 0000000000..e532a45094 --- /dev/null +++ b/components/bridge/connection/sample/desktop/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/Main.kt @@ -0,0 +1,19 @@ +package com.flipperdevices.bridge.connection + +import com.flipperdevices.bridge.connection.di.DaggerMergedDesktopAppComponent +import com.flipperdevices.core.ktx.jre.FlipperDispatchers +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.SupervisorJob + +fun main() { + val applicationScope = CoroutineScope( + SupervisorJob() + FlipperDispatchers.workStealingDispatcher + ) + // Always create the root component outside Compose on the UI thread + val appComponent = DaggerMergedDesktopAppComponent.factory() + .create( + scope = applicationScope + ) + + launch(appComponent) +} diff --git a/components/bridge/connection/sample/desktop/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/di/DesktopAppComponent.kt b/components/bridge/connection/sample/desktop/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/di/DesktopAppComponent.kt new file mode 100644 index 0000000000..01b1e2377e --- /dev/null +++ b/components/bridge/connection/sample/desktop/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/di/DesktopAppComponent.kt @@ -0,0 +1,18 @@ +package com.flipperdevices.bridge.connection.di + +import com.flipperdevices.core.di.AppGraph +import com.squareup.anvil.annotations.MergeComponent +import dagger.BindsInstance +import kotlinx.coroutines.CoroutineScope +import javax.inject.Singleton + +@Singleton +@MergeComponent(AppGraph::class) +interface DesktopAppComponent : AppComponent { + @MergeComponent.Factory + interface Factory { + fun create( + @BindsInstance scope: CoroutineScope + ): DesktopAppComponent + } +} diff --git a/components/bridge/connection/sample/shared/build.gradle.kts b/components/bridge/connection/sample/shared/build.gradle.kts new file mode 100644 index 0000000000..e22d91ea2b --- /dev/null +++ b/components/bridge/connection/sample/shared/build.gradle.kts @@ -0,0 +1,121 @@ +plugins { + id("flipper.multiplatform-compose") + id("flipper.multiplatform-dependencies") + id("com.google.devtools.ksp") + id("flipper.anvil") + id("kotlinx-serialization") +} + +android.namespace = "com.flipperdevices.bridge.connection.sample.shared" + +commonDependencies { + api(projects.components.core.di) + api(projects.components.core.log) + api(projects.components.core.preference) + api(projects.components.core.storage) + api(projects.components.core.share) + api(projects.components.core.ktx) + api(projects.components.core.ui.lifecycle) + api(projects.components.core.ui.decompose) + api(projects.components.core.ui.ktx) + api(projects.components.core.ui.theme) + + api(libs.dagger) + api(libs.anvil.utils.annotations) + + api(projects.components.bridge.connection.pbutils) + api(projects.components.bridge.connection.transport.common.api) + api(projects.components.bridge.connection.transport.common.impl) + api(projects.components.bridge.connection.orchestrator.api) + api(projects.components.bridge.connection.orchestrator.impl) + api(projects.components.bridge.connection.connectionbuilder.api) + api(projects.components.bridge.connection.connectionbuilder.impl) + api(projects.components.bridge.connection.config.api) + api(projects.components.bridge.connection.config.impl) + api(projects.components.bridge.connection.transportconfigbuilder.api) + api(projects.components.bridge.connection.transportconfigbuilder.impl) + api(projects.components.bridge.connection.device.common.api) + api(projects.components.bridge.connection.device.fzero.api) + api(projects.components.bridge.connection.device.fzero.impl) + api(projects.components.bridge.connection.feature.common.api) + api(projects.components.bridge.connection.feature.getinfo.api) + api(projects.components.bridge.connection.feature.getinfo.impl) + api(projects.components.bridge.connection.feature.lagsdetector.api) + api(projects.components.bridge.connection.feature.lagsdetector.impl) + api(projects.components.bridge.connection.feature.actionnotifier.api) + api(projects.components.bridge.connection.feature.protocolversion.api) + api(projects.components.bridge.connection.feature.protocolversion.impl) + api(projects.components.bridge.connection.feature.provider.api) + api(projects.components.bridge.connection.feature.provider.impl) + api(projects.components.bridge.connection.feature.restartrpc.api) + api(projects.components.bridge.connection.feature.restartrpc.impl) + api(projects.components.bridge.connection.feature.rpc.api) + api(projects.components.bridge.connection.feature.rpc.impl) + api(projects.components.bridge.connection.feature.rpcinfo.api) + api(projects.components.bridge.connection.feature.rpcinfo.impl) + api(projects.components.bridge.connection.feature.rpcstats.api) + api(projects.components.bridge.connection.feature.rpcstats.impl) + api(projects.components.bridge.connection.feature.serialspeed.api) + api(projects.components.bridge.connection.feature.serialspeed.impl) + api(projects.components.bridge.connection.feature.storage.api) + api(projects.components.bridge.connection.feature.storage.impl) + api(projects.components.bridge.connection.feature.storageinfo.api) + api(projects.components.bridge.connection.feature.storageinfo.impl) + + api(projects.components.filemngr.main.api) + api(projects.components.filemngr.main.impl) + api(projects.components.filemngr.listing.api) + api(projects.components.filemngr.listing.impl) + api(projects.components.filemngr.upload.api) + api(projects.components.filemngr.upload.impl) + api(projects.components.filemngr.search.api) + api(projects.components.filemngr.search.impl) + api(projects.components.filemngr.editor.api) + api(projects.components.filemngr.editor.impl) + api(projects.components.filemngr.download.api) + api(projects.components.filemngr.download.impl) + api(projects.components.filemngr.rename.api) + api(projects.components.filemngr.rename.impl) + api(projects.components.filemngr.create.api) + api(projects.components.filemngr.create.impl) + api(projects.components.filemngr.transfer.api) + api(projects.components.filemngr.transfer.impl) + + api(projects.components.analytics.shake2report.api) + api(projects.components.analytics.shake2report.noop) + api(projects.components.analytics.metric.api) + api(projects.components.analytics.metric.noop) + + api(libs.kotlin.immutable.collections) +} + +desktopDependencies { + api(projects.components.bridge.connection.transport.usb.api) + api(projects.components.bridge.connection.transport.usb.impl) + + api(libs.decompose.jetpack) +} + +androidDependencies { + api(projects.components.core.ui.res) + + api(projects.components.bridge.connection.transport.ble.api) + api(projects.components.bridge.connection.transport.ble.impl) + + api(projects.components.bridge.api) + + api(projects.components.keyparser.api) + api(projects.components.keyparser.impl) + + api(projects.components.deeplink.api) + api(projects.components.deeplink.impl) + + api(libs.appcompat) + + api(libs.timber) + + api(libs.ble.kotlin.scanner) + api(libs.ble.kotlin.client) + + api(libs.compose.activity) +} diff --git a/components/bridge/connection/sample/src/main/AndroidManifest.xml b/components/bridge/connection/sample/shared/src/androidMain/AndroidManifest.xml similarity index 78% rename from components/bridge/connection/sample/src/main/AndroidManifest.xml rename to components/bridge/connection/sample/shared/src/androidMain/AndroidManifest.xml index 2682cf4136..39a738da2b 100644 --- a/components/bridge/connection/sample/src/main/AndroidManifest.xml +++ b/components/bridge/connection/sample/shared/src/androidMain/AndroidManifest.xml @@ -2,12 +2,12 @@ xmlns:tools="http://schemas.android.com/tools"> diff --git a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/ConnectionTestActivity.kt b/components/bridge/connection/sample/shared/src/androidMain/kotlin/com/flipperdevices/bridge/connection/ConnectionTestActivity.kt similarity index 91% rename from components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/ConnectionTestActivity.kt rename to components/bridge/connection/sample/shared/src/androidMain/kotlin/com/flipperdevices/bridge/connection/ConnectionTestActivity.kt index 0e0f5df387..a199dc1315 100644 --- a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/ConnectionTestActivity.kt +++ b/components/bridge/connection/sample/shared/src/androidMain/kotlin/com/flipperdevices/bridge/connection/ConnectionTestActivity.kt @@ -2,10 +2,12 @@ package com.flipperdevices.bridge.connection import android.os.Bundle import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge import androidx.appcompat.app.AppCompatActivity import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.safeDrawingPadding import androidx.compose.ui.Modifier import com.arkivanov.decompose.defaultComponentContext import com.flipperdevices.bridge.connection.di.AppComponent @@ -29,6 +31,8 @@ class ConnectionTestActivity : AppCompatActivity() { super.onCreate(savedInstanceState) ComponentHolder.component().inject(this) + enableEdgeToEdge() + val root = rootComponentFactory( componentContext = defaultComponentContext(), ) @@ -40,6 +44,7 @@ class ConnectionTestActivity : AppCompatActivity() { modifier = Modifier .fillMaxSize() .background(LocalPallet.current.background) + .safeDrawingPadding() ) { root.Render() } diff --git a/components/bridge/connection/sample/shared/src/androidMain/kotlin/com/flipperdevices/bridge/connection/di/AppComponent.kt b/components/bridge/connection/sample/shared/src/androidMain/kotlin/com/flipperdevices/bridge/connection/di/AppComponent.kt new file mode 100644 index 0000000000..28c518e764 --- /dev/null +++ b/components/bridge/connection/sample/shared/src/androidMain/kotlin/com/flipperdevices/bridge/connection/di/AppComponent.kt @@ -0,0 +1,7 @@ +package com.flipperdevices.bridge.connection.di + +import com.flipperdevices.bridge.connection.ConnectionTestActivity + +interface AppComponent { + fun inject(activity: ConnectionTestActivity) +} diff --git a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchDecomposeComponent.kt b/components/bridge/connection/sample/shared/src/androidMain/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchDecomposeComponentImpl.kt similarity index 77% rename from components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchDecomposeComponent.kt rename to components/bridge/connection/sample/shared/src/androidMain/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchDecomposeComponentImpl.kt index 446684387d..d7aabe1ed1 100644 --- a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchDecomposeComponent.kt +++ b/components/bridge/connection/sample/shared/src/androidMain/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchDecomposeComponentImpl.kt @@ -1,5 +1,6 @@ package com.flipperdevices.bridge.connection.screens.search +import android.R import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding @@ -12,24 +13,26 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.arkivanov.decompose.ComponentContext -import com.flipperdevices.bridge.connection.R +import com.flipperdevices.core.di.AppGraph import com.flipperdevices.core.ui.ktx.clickableRipple import com.flipperdevices.core.ui.ktx.image.painterResourceByKey import com.flipperdevices.core.ui.lifecycle.viewModelWithFactory import com.flipperdevices.core.ui.theme.LocalTypography -import com.flipperdevices.ui.decompose.ScreenDecomposeComponent import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject +import flipperapp.components.bridge.connection.sample.shared.generated.resources.Res +import flipperapp.components.bridge.connection.sample.shared.generated.resources.connection_search_title +import me.gulya.anvil.assisted.ContributesAssistedFactory +import org.jetbrains.compose.resources.stringResource import javax.inject.Provider -class ConnectionSearchDecomposeComponent @AssistedInject constructor( +@ContributesAssistedFactory(AppGraph::class, ConnectionSearchDecomposeComponent.Factory::class) +class ConnectionSearchDecomposeComponentImpl @AssistedInject constructor( @Assisted componentContext: ComponentContext, private val searchViewModelProvider: Provider -) : ScreenDecomposeComponent(componentContext) { +) : ConnectionSearchDecomposeComponent(componentContext) { @Composable override fun Render() { @@ -41,7 +44,7 @@ class ConnectionSearchDecomposeComponent @AssistedInject constructor( Column { Text( modifier = Modifier.padding(16.dp), - text = stringResource(R.string.connection_search_title), + text = stringResource(Res.string.connection_search_title), style = LocalTypography.current.titleB24 ) LazyColumn { @@ -64,9 +67,9 @@ class ConnectionSearchDecomposeComponent @AssistedInject constructor( .size(24.dp), painter = painterResourceByKey( if (searchItem.savedDeviceModel == null) { - android.R.drawable.ic_menu_add + R.drawable.ic_menu_add } else { - android.R.drawable.ic_menu_delete + R.drawable.ic_menu_delete } ), contentDescription = null @@ -76,11 +79,4 @@ class ConnectionSearchDecomposeComponent @AssistedInject constructor( } } } - - @AssistedFactory - fun interface Factory { - operator fun invoke( - componentContext: ComponentContext - ): ConnectionSearchDecomposeComponent - } } diff --git a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchItem.kt b/components/bridge/connection/sample/shared/src/androidMain/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchItem.kt similarity index 100% rename from components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchItem.kt rename to components/bridge/connection/sample/shared/src/androidMain/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchItem.kt diff --git a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchViewModel.kt b/components/bridge/connection/sample/shared/src/androidMain/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchViewModel.kt similarity index 95% rename from components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchViewModel.kt rename to components/bridge/connection/sample/shared/src/androidMain/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchViewModel.kt index 894fa2a08e..60e503e3e4 100644 --- a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchViewModel.kt +++ b/components/bridge/connection/sample/shared/src/androidMain/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchViewModel.kt @@ -5,6 +5,7 @@ import android.content.Context import com.flipperdevices.bridge.api.utils.Constants import com.flipperdevices.bridge.connection.config.api.FDevicePersistedStorage import com.flipperdevices.bridge.connection.config.api.model.FDeviceFlipperZeroBleModel +import com.flipperdevices.core.preference.pb.FlipperZeroBle import com.flipperdevices.core.ui.lifecycle.DecomposeViewModel import kotlinx.collections.immutable.PersistentList import kotlinx.collections.immutable.persistentListOf @@ -73,5 +74,6 @@ class ConnectionSearchViewModel @Inject constructor( private fun ServerDevice.toFDeviceFlipperZeroBleModel() = FDeviceFlipperZeroBleModel( name = this.name?.replaceFirst(Constants.DEVICENAME_PREFIX, "") ?.trim() ?: this.address, - address = this.address + address = this.address, + hardwareColor = FlipperZeroBle.HardwareColor.WHITE ) diff --git a/components/bridge/connection/sample/shared/src/androidMain/kotlin/com/flipperdevices/bridge/connection/utils/PermissionCheckerImpl.kt b/components/bridge/connection/sample/shared/src/androidMain/kotlin/com/flipperdevices/bridge/connection/utils/PermissionCheckerImpl.kt new file mode 100644 index 0000000000..e239563bb3 --- /dev/null +++ b/components/bridge/connection/sample/shared/src/androidMain/kotlin/com/flipperdevices/bridge/connection/utils/PermissionCheckerImpl.kt @@ -0,0 +1,25 @@ +package com.flipperdevices.bridge.connection.utils + +import android.Manifest +import android.content.Context +import android.content.pm.PackageManager +import androidx.core.content.ContextCompat +import com.flipperdevices.bridge.connection.screens.utils.PermissionChecker +import com.flipperdevices.core.di.AppGraph +import com.squareup.anvil.annotations.ContributesBinding +import javax.inject.Inject + +@ContributesBinding(AppGraph::class, PermissionChecker::class) +class PermissionCheckerImpl @Inject constructor( + private val context: Context +) : PermissionChecker { + override fun isPermissionGranted(): Boolean { + return ContextCompat.checkSelfPermission( + context, + Manifest.permission.BLUETOOTH_SCAN + ) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission( + context, + Manifest.permission.BLUETOOTH_CONNECT + ) == PackageManager.PERMISSION_GRANTED + } +} diff --git a/components/newfilemanager/impl/src/androidMain/res/values/strings.xml b/components/bridge/connection/sample/shared/src/androidMain/res/values/strings.xml similarity index 50% rename from components/newfilemanager/impl/src/androidMain/res/values/strings.xml rename to components/bridge/connection/sample/shared/src/androidMain/res/values/strings.xml index 93811f5e10..2c0e015116 100644 --- a/components/newfilemanager/impl/src/androidMain/res/values/strings.xml +++ b/components/bridge/connection/sample/shared/src/androidMain/res/values/strings.xml @@ -1,4 +1,4 @@ - Share key %1$s + Flipper Connection Sample \ No newline at end of file diff --git a/components/bridge/connection/sample/shared/src/commonMain/composeResources/drawable/ic_more.xml b/components/bridge/connection/sample/shared/src/commonMain/composeResources/drawable/ic_more.xml new file mode 100644 index 0000000000..a34d2d0633 --- /dev/null +++ b/components/bridge/connection/sample/shared/src/commonMain/composeResources/drawable/ic_more.xml @@ -0,0 +1,10 @@ + + + diff --git a/components/bridge/connection/sample/src/main/res/values/strings.xml b/components/bridge/connection/sample/shared/src/commonMain/composeResources/values/strings.xml similarity index 100% rename from components/bridge/connection/sample/src/main/res/values/strings.xml rename to components/bridge/connection/sample/shared/src/commonMain/composeResources/values/strings.xml diff --git a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/ConnectionRootDecomposeComponent.kt b/components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/ConnectionRootDecomposeComponent.kt similarity index 74% rename from components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/ConnectionRootDecomposeComponent.kt rename to components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/ConnectionRootDecomposeComponent.kt index 5540dcd5b4..c347847128 100644 --- a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/ConnectionRootDecomposeComponent.kt +++ b/components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/ConnectionRootDecomposeComponent.kt @@ -1,9 +1,5 @@ package com.flipperdevices.bridge.connection.screens -import android.Manifest -import android.content.Context -import android.content.pm.PackageManager -import androidx.core.content.ContextCompat import com.arkivanov.decompose.ComponentContext import com.arkivanov.decompose.router.stack.ChildStack import com.arkivanov.decompose.router.stack.childStack @@ -13,6 +9,8 @@ import com.flipperdevices.bridge.connection.screens.device.ConnectionDeviceScree import com.flipperdevices.bridge.connection.screens.models.ConnectionRootConfig import com.flipperdevices.bridge.connection.screens.nopermission.ConnectionNoPermissionDecomposeComponent import com.flipperdevices.bridge.connection.screens.search.ConnectionSearchDecomposeComponent +import com.flipperdevices.bridge.connection.screens.utils.PermissionChecker +import com.flipperdevices.filemanager.main.api.FileManagerDecomposeComponent import com.flipperdevices.ui.decompose.CompositeDecomposeComponent import com.flipperdevices.ui.decompose.DecomposeComponent import dagger.assisted.Assisted @@ -21,16 +19,15 @@ import dagger.assisted.AssistedInject class ConnectionRootDecomposeComponent @AssistedInject constructor( @Assisted componentContext: ComponentContext, - private val context: Context, + private val permissionChecker: PermissionChecker, private val searchDecomposeFactory: ConnectionSearchDecomposeComponent.Factory, private val connectionDeviceScreenDecomposeComponentFactory: ConnectionDeviceScreenDecomposeComponent.Factory, - private val fileManagerComponentFactory: - com.flipperdevices.filemanager.main.api.FileManagerDecomposeComponent.Factory + private val fileManagerDecomposeComponent: FileManagerDecomposeComponent.Factory ) : CompositeDecomposeComponent(), ComponentContext by componentContext { override val stack: Value> = childStack( source = navigation, serializer = ConnectionRootConfig.serializer(), - initialConfiguration = if (isPermissionGranted()) { + initialConfiguration = if (permissionChecker.isPermissionGranted()) { ConnectionRootConfig.Device } else { ConnectionRootConfig.NoPermission @@ -56,22 +53,12 @@ class ConnectionRootDecomposeComponent @AssistedInject constructor( navigation = navigation ) - ConnectionRootConfig.FileManager -> fileManagerComponentFactory( + ConnectionRootConfig.FileManager -> fileManagerDecomposeComponent( componentContext = componentContext, - onBack = { navigation.pop() } + onBack = navigation::pop ) } - private fun isPermissionGranted(): Boolean { - return ContextCompat.checkSelfPermission( - context, - Manifest.permission.BLUETOOTH_SCAN - ) == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission( - context, - Manifest.permission.BLUETOOTH_CONNECT - ) == PackageManager.PERMISSION_GRANTED - } - @AssistedFactory fun interface Factory { operator fun invoke( diff --git a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/device/ConnectionDeviceScreenDecomposeComponent.kt b/components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/device/ConnectionDeviceScreenDecomposeComponent.kt similarity index 100% rename from components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/device/ConnectionDeviceScreenDecomposeComponent.kt rename to components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/device/ConnectionDeviceScreenDecomposeComponent.kt diff --git a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/device/composable/FCurrentDeviceComposable.kt b/components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/device/composable/FCurrentDeviceComposable.kt similarity index 100% rename from components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/device/composable/FCurrentDeviceComposable.kt rename to components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/device/composable/FCurrentDeviceComposable.kt diff --git a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/device/composable/FDeviceDropdownComposable.kt b/components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/device/composable/FDeviceDropdownComposable.kt similarity index 86% rename from components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/device/composable/FDeviceDropdownComposable.kt rename to components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/device/composable/FDeviceDropdownComposable.kt index 69edba7bae..9a1ccc1d4c 100644 --- a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/device/composable/FDeviceDropdownComposable.kt +++ b/components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/device/composable/FDeviceDropdownComposable.kt @@ -17,14 +17,15 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import com.flipperdevices.bridge.connection.R import com.flipperdevices.bridge.connection.config.api.model.FDeviceBaseModel import com.flipperdevices.bridge.connection.screens.device.viewmodel.DevicesDropdownState import com.flipperdevices.core.ui.ktx.clickableRipple -import com.flipperdevices.core.ui.res.R as DrawableRes +import flipperapp.components.bridge.connection.sample.shared.generated.resources.Res +import flipperapp.components.bridge.connection.sample.shared.generated.resources.connection_dropdown_unknown +import flipperapp.components.bridge.connection.sample.shared.generated.resources.ic_more +import org.jetbrains.compose.resources.painterResource +import org.jetbrains.compose.resources.stringResource @OptIn(ExperimentalMaterialApi::class) @Composable @@ -54,7 +55,7 @@ fun FDeviceDropdownComposable( ) { Text( text = devicesState.currentDevice?.humanReadableName - ?: stringResource(R.string.connection_dropdown_unknown) + ?: stringResource(Res.string.connection_dropdown_unknown) ) ExposedDropdownMenu( expanded = expanded, @@ -98,7 +99,7 @@ fun FDeviceDropdownComposable( Icon( modifier = Modifier.padding(end = 16.dp), - painter = painterResource(DrawableRes.drawable.ic_more), + painter = painterResource(Res.drawable.ic_more), contentDescription = null ) } diff --git a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/device/composable/FPingComposable.kt b/components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/device/composable/FPingComposable.kt similarity index 100% rename from components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/device/composable/FPingComposable.kt rename to components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/device/composable/FPingComposable.kt diff --git a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/device/viewmodel/FCurrentDeviceViewModel.kt b/components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/device/viewmodel/FCurrentDeviceViewModel.kt similarity index 100% rename from components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/device/viewmodel/FCurrentDeviceViewModel.kt rename to components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/device/viewmodel/FCurrentDeviceViewModel.kt diff --git a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/device/viewmodel/FDevicesViewModel.kt b/components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/device/viewmodel/FDevicesViewModel.kt similarity index 100% rename from components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/device/viewmodel/FDevicesViewModel.kt rename to components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/device/viewmodel/FDevicesViewModel.kt diff --git a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/device/viewmodel/PingViewModel.kt b/components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/device/viewmodel/PingViewModel.kt similarity index 100% rename from components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/device/viewmodel/PingViewModel.kt rename to components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/device/viewmodel/PingViewModel.kt diff --git a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/models/ConnectionRootConfig.kt b/components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/models/ConnectionRootConfig.kt similarity index 100% rename from components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/models/ConnectionRootConfig.kt rename to components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/models/ConnectionRootConfig.kt diff --git a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/nopermission/ConnectionNoPermissionDecomposeComponent.kt b/components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/nopermission/ConnectionNoPermissionDecomposeComponent.kt similarity index 72% rename from components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/nopermission/ConnectionNoPermissionDecomposeComponent.kt rename to components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/nopermission/ConnectionNoPermissionDecomposeComponent.kt index 041281af2d..4f51c68878 100644 --- a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/screens/nopermission/ConnectionNoPermissionDecomposeComponent.kt +++ b/components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/nopermission/ConnectionNoPermissionDecomposeComponent.kt @@ -7,11 +7,12 @@ import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.arkivanov.decompose.ComponentContext -import com.flipperdevices.bridge.connection.R import com.flipperdevices.ui.decompose.ScreenDecomposeComponent +import flipperapp.components.bridge.connection.sample.shared.generated.resources.Res +import flipperapp.components.bridge.connection.sample.shared.generated.resources.connection_test_require_permission +import org.jetbrains.compose.resources.stringResource class ConnectionNoPermissionDecomposeComponent( componentContext: ComponentContext @@ -24,7 +25,7 @@ class ConnectionNoPermissionDecomposeComponent( .padding(16.dp), contentAlignment = Alignment.Center ) { - Text(text = stringResource(R.string.connection_test_require_permission)) + Text(text = stringResource(Res.string.connection_test_require_permission)) } } } diff --git a/components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchDecomposeComponent.kt b/components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchDecomposeComponent.kt new file mode 100644 index 0000000000..55e39cd958 --- /dev/null +++ b/components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchDecomposeComponent.kt @@ -0,0 +1,14 @@ +package com.flipperdevices.bridge.connection.screens.search + +import com.arkivanov.decompose.ComponentContext +import com.flipperdevices.ui.decompose.ScreenDecomposeComponent + +abstract class ConnectionSearchDecomposeComponent( + componentContext: ComponentContext, +) : ScreenDecomposeComponent(componentContext) { + fun interface Factory { + operator fun invoke( + componentContext: ComponentContext + ): ConnectionSearchDecomposeComponent + } +} diff --git a/components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/utils/PermissionChecker.kt b/components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/utils/PermissionChecker.kt new file mode 100644 index 0000000000..cd5346b108 --- /dev/null +++ b/components/bridge/connection/sample/shared/src/commonMain/kotlin/com/flipperdevices/bridge/connection/screens/utils/PermissionChecker.kt @@ -0,0 +1,5 @@ +package com.flipperdevices.bridge.connection.screens.utils + +interface PermissionChecker { + fun isPermissionGranted(): Boolean +} diff --git a/components/bridge/connection/sample/shared/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/App.kt b/components/bridge/connection/sample/shared/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/App.kt new file mode 100644 index 0000000000..6b54e0f87f --- /dev/null +++ b/components/bridge/connection/sample/shared/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/App.kt @@ -0,0 +1,53 @@ +package com.flipperdevices.bridge.connection + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.safeDrawingPadding +import androidx.compose.ui.Modifier +import androidx.compose.ui.window.Window +import androidx.compose.ui.window.application +import androidx.compose.ui.window.rememberWindowState +import com.arkivanov.decompose.DefaultComponentContext +import com.arkivanov.decompose.extensions.compose.lifecycle.LifecycleController +import com.arkivanov.essenty.lifecycle.LifecycleRegistry +import com.flipperdevices.bridge.connection.di.AppComponent +import com.flipperdevices.bridge.connection.utils.runOnUiThread +import com.flipperdevices.core.ui.lifecycle.viewModelWithFactory +import com.flipperdevices.core.ui.theme.FlipperTheme +import com.flipperdevices.core.ui.theme.LocalPallet + +fun launch(appComponent: AppComponent) { + val lifecycle = LifecycleRegistry() + val root = runOnUiThread { + appComponent.rootComponentFactory( + DefaultComponentContext(lifecycle = lifecycle) + ) + } + application { + val windowState = rememberWindowState() + + LifecycleController(lifecycle, windowState) + Window( + onCloseRequest = ::exitApplication, + state = windowState, + title = "BusyStatusBar", + ) { + FlipperTheme( + content = { + Box( + modifier = Modifier + .fillMaxSize() + .background(LocalPallet.current.background) + .safeDrawingPadding() + ) { + root.Render() + } + }, + themeViewModel = root.viewModelWithFactory(key = null) { + appComponent.themeViewModelProvider.get() + } + ) + } + } +} diff --git a/components/bridge/connection/sample/shared/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/di/AppComponent.kt b/components/bridge/connection/sample/shared/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/di/AppComponent.kt new file mode 100644 index 0000000000..c8de2c39fe --- /dev/null +++ b/components/bridge/connection/sample/shared/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/di/AppComponent.kt @@ -0,0 +1,10 @@ +package com.flipperdevices.bridge.connection.di + +import com.flipperdevices.bridge.connection.screens.ConnectionRootDecomposeComponent +import com.flipperdevices.core.ui.theme.viewmodel.ThemeViewModel +import javax.inject.Provider + +interface AppComponent { + val themeViewModelProvider: Provider + val rootComponentFactory: ConnectionRootDecomposeComponent.Factory +} diff --git a/components/bridge/connection/sample/shared/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchDecomposeComponentNoop.kt b/components/bridge/connection/sample/shared/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchDecomposeComponentNoop.kt new file mode 100644 index 0000000000..dfc6a34380 --- /dev/null +++ b/components/bridge/connection/sample/shared/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/screens/search/ConnectionSearchDecomposeComponentNoop.kt @@ -0,0 +1,19 @@ +package com.flipperdevices.bridge.connection.screens.search + +import androidx.compose.runtime.Composable +import com.arkivanov.decompose.ComponentContext +import com.flipperdevices.core.di.AppGraph +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import me.gulya.anvil.assisted.ContributesAssistedFactory + +@ContributesAssistedFactory(AppGraph::class, ConnectionSearchDecomposeComponent.Factory::class) +class ConnectionSearchDecomposeComponentNoop @AssistedInject constructor( + @Assisted componentContext: ComponentContext, +) : ConnectionSearchDecomposeComponent(componentContext) { + + @Composable + override fun Render() { + // Empty + } +} diff --git a/components/bridge/connection/sample/shared/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/utils/PermissionCheckerNoop.kt b/components/bridge/connection/sample/shared/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/utils/PermissionCheckerNoop.kt new file mode 100644 index 0000000000..d29b59ba3a --- /dev/null +++ b/components/bridge/connection/sample/shared/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/utils/PermissionCheckerNoop.kt @@ -0,0 +1,11 @@ +package com.flipperdevices.bridge.connection.utils + +import com.flipperdevices.bridge.connection.screens.utils.PermissionChecker +import com.flipperdevices.core.di.AppGraph +import com.squareup.anvil.annotations.ContributesBinding +import javax.inject.Inject + +@ContributesBinding(AppGraph::class, PermissionChecker::class) +class PermissionCheckerNoop @Inject constructor() : PermissionChecker { + override fun isPermissionGranted() = true +} diff --git a/components/bridge/connection/sample/shared/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/utils/Utils.kt b/components/bridge/connection/sample/shared/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/utils/Utils.kt new file mode 100644 index 0000000000..881b510907 --- /dev/null +++ b/components/bridge/connection/sample/shared/src/desktopMain/kotlin/com/flipperdevices/bridge/connection/utils/Utils.kt @@ -0,0 +1,25 @@ +package com.flipperdevices.bridge.connection.utils + +import javax.swing.SwingUtilities + +internal fun runOnUiThread(block: () -> T): T { + if (SwingUtilities.isEventDispatchThread()) { + return block() + } + + var error: Throwable? = null + var result: T? = null + + SwingUtilities.invokeAndWait { + try { + result = block() + } catch (e: Throwable) { + error = e + } + } + + error?.also { throw it } + + @Suppress("UNCHECKED_CAST") + return result as T +} diff --git a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/di/AppComponent.kt b/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/di/AppComponent.kt deleted file mode 100644 index 8a672ddebd..0000000000 --- a/components/bridge/connection/sample/src/main/kotlin/com/flipperdevices/bridge/connection/di/AppComponent.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.flipperdevices.bridge.connection.di - -import android.app.Application -import android.content.Context -import com.flipperdevices.bridge.connection.ConnectionTestActivity -import com.flipperdevices.core.di.AppGraph -import com.flipperdevices.core.di.ApplicationParams -import com.squareup.anvil.annotations.MergeComponent -import dagger.BindsInstance -import javax.inject.Singleton - -@Singleton -@MergeComponent(AppGraph::class) -interface AppComponent { - fun inject(activity: ConnectionTestActivity) - - @MergeComponent.Factory - interface Factory { - fun create( - @BindsInstance context: Context, - @BindsInstance application: Application, - @BindsInstance applicationParams: ApplicationParams - ): AppComponent - } -} diff --git a/components/bridge/connection/sample/.gitignore b/components/bridge/connection/transport/usb/api/.gitignore similarity index 100% rename from components/bridge/connection/sample/.gitignore rename to components/bridge/connection/transport/usb/api/.gitignore diff --git a/components/bridge/connection/transport/usb/api/build.gradle.kts b/components/bridge/connection/transport/usb/api/build.gradle.kts new file mode 100644 index 0000000000..0540f983fe --- /dev/null +++ b/components/bridge/connection/transport/usb/api/build.gradle.kts @@ -0,0 +1,12 @@ +plugins { + id("flipper.multiplatform") + id("flipper.multiplatform-dependencies") +} + +android.namespace = "com.flipperdevices.bridge.connection.transport.usb.api" + +commonDependencies { + implementation(projects.components.bridge.connection.transport.common.api) + implementation(libs.kotlin.coroutines) + implementation(libs.kotlin.immutable.collections) +} diff --git a/components/bridge/connection/transport/usb/api/src/commonMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/api/FUSBApi.kt b/components/bridge/connection/transport/usb/api/src/commonMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/api/FUSBApi.kt new file mode 100644 index 0000000000..33322e13e2 --- /dev/null +++ b/components/bridge/connection/transport/usb/api/src/commonMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/api/FUSBApi.kt @@ -0,0 +1,5 @@ +package com.flipperdevices.bridge.connection.transport.usb.api + +import com.flipperdevices.bridge.connection.transport.common.api.FConnectedDeviceApi + +interface FUSBApi : FConnectedDeviceApi diff --git a/components/bridge/connection/transport/usb/api/src/commonMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/api/FUSBDeviceConnectionConfig.kt b/components/bridge/connection/transport/usb/api/src/commonMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/api/FUSBDeviceConnectionConfig.kt new file mode 100644 index 0000000000..88a57c15a9 --- /dev/null +++ b/components/bridge/connection/transport/usb/api/src/commonMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/api/FUSBDeviceConnectionConfig.kt @@ -0,0 +1,7 @@ +package com.flipperdevices.bridge.connection.transport.usb.api + +import com.flipperdevices.bridge.connection.transport.common.api.FDeviceConnectionConfig + +data class FUSBDeviceConnectionConfig( + val path: String, +) : FDeviceConnectionConfig() diff --git a/components/bridge/connection/transport/usb/api/src/commonMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/api/USBDeviceConnectionApi.kt b/components/bridge/connection/transport/usb/api/src/commonMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/api/USBDeviceConnectionApi.kt new file mode 100644 index 0000000000..b99ce2e8fb --- /dev/null +++ b/components/bridge/connection/transport/usb/api/src/commonMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/api/USBDeviceConnectionApi.kt @@ -0,0 +1,13 @@ +package com.flipperdevices.bridge.connection.transport.usb.api + +import com.flipperdevices.bridge.connection.transport.common.api.DeviceConnectionApi +import com.flipperdevices.bridge.connection.transport.common.api.FTransportConnectionStatusListener +import kotlinx.coroutines.CoroutineScope + +interface USBDeviceConnectionApi : DeviceConnectionApi { + override suspend fun connect( + scope: CoroutineScope, + config: FUSBDeviceConnectionConfig, + listener: FTransportConnectionStatusListener + ): Result +} diff --git a/components/bridge/connection/transport/usb/impl/.gitignore b/components/bridge/connection/transport/usb/impl/.gitignore new file mode 100644 index 0000000000..42afabfd2a --- /dev/null +++ b/components/bridge/connection/transport/usb/impl/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/components/bridge/connection/transport/usb/impl/build.gradle.kts b/components/bridge/connection/transport/usb/impl/build.gradle.kts new file mode 100644 index 0000000000..0968b876b9 --- /dev/null +++ b/components/bridge/connection/transport/usb/impl/build.gradle.kts @@ -0,0 +1,26 @@ +plugins { + id("flipper.multiplatform") + id("flipper.multiplatform-dependencies") + id("flipper.anvil-multiplatform") +} + +android.namespace = "com.flipperdevices.bridge.connection.transport.usb.impl" + +commonDependencies { + implementation(projects.components.bridge.connection.transport.usb.api) + + implementation(projects.components.core.log) + implementation(projects.components.core.di) + implementation(projects.components.core.ktx) + + implementation(projects.components.bridge.connection.transport.common.api) + implementation(projects.components.bridge.connection.feature.actionnotifier.api) + + implementation(libs.annotations) + implementation(libs.kotlin.immutable.collections) + implementation(libs.kotlin.coroutines) +} + +jvmSharedDependencies { + implementation(libs.jserial) +} diff --git a/components/bridge/connection/transport/usb/impl/src/jvmSharedMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/impl/USBDeviceConnectionApiImpl.kt b/components/bridge/connection/transport/usb/impl/src/jvmSharedMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/impl/USBDeviceConnectionApiImpl.kt new file mode 100644 index 0000000000..a397fe168d --- /dev/null +++ b/components/bridge/connection/transport/usb/impl/src/jvmSharedMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/impl/USBDeviceConnectionApiImpl.kt @@ -0,0 +1,101 @@ +package com.flipperdevices.bridge.connection.transport.usb.impl + +import com.fazecast.jSerialComm.SerialPort +import com.flipperdevices.bridge.connection.feature.actionnotifier.api.FlipperActionNotifier +import com.flipperdevices.bridge.connection.transport.common.api.FTransportConnectionStatusListener +import com.flipperdevices.bridge.connection.transport.usb.api.FUSBApi +import com.flipperdevices.bridge.connection.transport.usb.api.FUSBDeviceConnectionConfig +import com.flipperdevices.bridge.connection.transport.usb.api.USBDeviceConnectionApi +import com.flipperdevices.bridge.connection.transport.usb.impl.serial.FUSBSerialDeviceApi +import com.flipperdevices.core.log.LogTagProvider +import com.flipperdevices.core.log.info +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.NonCancellable +import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext + +private val FLOOD_END_STRING = "\r\n\r\n>: ".toByteArray() +private val COMMAND = "start_rpc_session\r".toByteArray() +private const val BAUD_RATE = 230400 +private const val DATA_BITS = 8 +private const val OPEN_PORT_TIME_MS = 1000 + +class USBDeviceConnectionApiImpl( + private val actionNotifierFactory: FlipperActionNotifier.Factory +) : USBDeviceConnectionApi, LogTagProvider { + override val TAG = "USBDeviceConnectionApi" + + override suspend fun connect( + scope: CoroutineScope, + config: FUSBDeviceConnectionConfig, + listener: FTransportConnectionStatusListener + ): Result = runCatching { + val serialPort = SerialPort.getCommPort(config.path) + serialPort.setComPortParameters( + BAUD_RATE, + DATA_BITS, + SerialPort.ONE_STOP_BIT, + SerialPort.NO_PARITY + ) + serialPort.openPort(OPEN_PORT_TIME_MS) + serialPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING, 0, 0) + val portOpened = serialPort.openPort() + + info { "Read port is: $portOpened" } + + if (!portOpened) { + error("Fail to open port") + } + + skipFlood(serialPort, FLOOD_END_STRING) + serialPort.writeBytes(COMMAND, COMMAND.size) + skipFlood(serialPort, "\n".toByteArray()) + + val deviceApi = FUSBSerialDeviceApi( + scope = scope, + serialPort = serialPort, + actionNotifier = actionNotifierFactory(scope) + ) + + scope.launch { + try { + awaitCancellation() + } finally { + withContext(NonCancellable) { + serialPort.closePort() + } + } + } + return@runCatching deviceApi + } + + @OptIn(ExperimentalStdlibApi::class) + private fun skipFlood(serialPort: SerialPort, floodBytes: ByteArray) { + info { "Start wait flood" } + var floodCurrentIndex = 0 + val buffer = ByteArray(size = 1) + while (!Thread.interrupted()) { + if (serialPort.readBytes(buffer, buffer.size) == 0) { + info { "Exit from skipFlood because buffer is empty" } + continue + } + + info { + "#skipFlood Read ${buffer.toHexString()} (${ + buffer.joinToString { + it.toInt().toChar().toString() + } + })" + } + if (floodBytes[floodCurrentIndex] == buffer.first()) { + floodCurrentIndex++ + } else { + floodCurrentIndex = 0 + } + if (floodCurrentIndex == floodBytes.size) { + return + } + } + } +} diff --git a/components/bridge/connection/transport/usb/impl/src/jvmSharedMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/impl/di/BleDeviceConnectionModule.kt b/components/bridge/connection/transport/usb/impl/src/jvmSharedMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/impl/di/BleDeviceConnectionModule.kt new file mode 100644 index 0000000000..049e6e18c9 --- /dev/null +++ b/components/bridge/connection/transport/usb/impl/src/jvmSharedMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/impl/di/BleDeviceConnectionModule.kt @@ -0,0 +1,25 @@ +package com.flipperdevices.bridge.connection.transport.usb.impl.di + +import com.flipperdevices.bridge.connection.feature.actionnotifier.api.FlipperActionNotifier +import com.flipperdevices.bridge.connection.transport.common.api.di.DeviceConnectionApiHolder +import com.flipperdevices.bridge.connection.transport.common.api.di.toHolder +import com.flipperdevices.bridge.connection.transport.usb.api.FUSBDeviceConnectionConfig +import com.flipperdevices.bridge.connection.transport.usb.impl.USBDeviceConnectionApiImpl +import com.flipperdevices.core.di.AppGraph +import com.squareup.anvil.annotations.ContributesTo +import dagger.Module +import dagger.Provides +import dagger.multibindings.ClassKey +import dagger.multibindings.IntoMap + +@Module +@ContributesTo(AppGraph::class) +class BleDeviceConnectionModule { + + @Provides + @IntoMap + @ClassKey(FUSBDeviceConnectionConfig::class) + fun provideBleDeviceConnectionApi( + actionNotifierFactory: FlipperActionNotifier.Factory + ): DeviceConnectionApiHolder = USBDeviceConnectionApiImpl(actionNotifierFactory).toHolder() +} diff --git a/components/bridge/connection/transport/usb/impl/src/jvmSharedMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/impl/serial/FUSBSerialDeviceApi.kt b/components/bridge/connection/transport/usb/impl/src/jvmSharedMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/impl/serial/FUSBSerialDeviceApi.kt new file mode 100644 index 0000000000..c39ef565c1 --- /dev/null +++ b/components/bridge/connection/transport/usb/impl/src/jvmSharedMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/impl/serial/FUSBSerialDeviceApi.kt @@ -0,0 +1,67 @@ +package com.flipperdevices.bridge.connection.transport.usb.impl.serial + +import com.fazecast.jSerialComm.SerialPort +import com.flipperdevices.bridge.connection.feature.actionnotifier.api.FlipperActionNotifier +import com.flipperdevices.bridge.connection.transport.common.api.serial.FSerialDeviceApi +import com.flipperdevices.bridge.connection.transport.common.api.serial.FlipperSerialSpeed +import com.flipperdevices.bridge.connection.transport.usb.api.FUSBApi +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.launch + +class FUSBSerialDeviceApi( + private val scope: CoroutineScope, + private val serialPort: SerialPort, + private val actionNotifier: FlipperActionNotifier +) : FUSBApi, FSerialDeviceApi { + private val receiverByteFlow = MutableSharedFlow() + private val txSpeed = SpeedMeter(scope) + private val rxSpeed = SpeedMeter(scope) + private val speedFlowState = MutableStateFlow(FlipperSerialSpeed()) + + init { + scope.launch { + val buffer = ByteArray(size = 1024) + var result = 1 + while (result > 0) { + result = serialPort.readBytes(buffer, buffer.size) + val readBytes = buffer.take(result).toByteArray() + receiverByteFlow.emit(readBytes) + } + error("End loop with result $result") + } + combine( + rxSpeed.getSpeed(), + txSpeed.getSpeed() + ) { rxBPS, txBPS -> + actionNotifier.notifyAboutAction() + speedFlowState.emit( + FlipperSerialSpeed(receiveBytesInSec = rxBPS, transmitBytesInSec = txBPS) + ) + }.launchIn(scope) + } + + override suspend fun getSpeed() = speedFlowState.asStateFlow() + override suspend fun getReceiveBytesFlow() = receiverByteFlow + override fun getActionNotifier() = actionNotifier + + override suspend fun sendBytes(data: ByteArray) { + var writtenBytesOffset = 0 + do { + val writtenBytes = + serialPort.writeBytes(data, writtenBytesOffset, data.size - writtenBytesOffset) + if (writtenBytes == -1) { + error("Failed to write bytes") + } + writtenBytesOffset += writtenBytes + } while (writtenBytesOffset < data.size) + } + + override suspend fun disconnect() { + serialPort.closePort() + } +} diff --git a/components/bridge/connection/transport/usb/impl/src/jvmSharedMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/impl/serial/SpeedMeter.kt b/components/bridge/connection/transport/usb/impl/src/jvmSharedMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/impl/serial/SpeedMeter.kt new file mode 100644 index 0000000000..df8d6ab382 --- /dev/null +++ b/components/bridge/connection/transport/usb/impl/src/jvmSharedMain/kotlin/com/flipperdevices/bridge/connection/transport/usb/impl/serial/SpeedMeter.kt @@ -0,0 +1,42 @@ +package com.flipperdevices.bridge.connection.transport.usb.impl.serial + +import com.flipperdevices.core.ktx.jre.FlipperDispatchers +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import java.util.concurrent.atomic.AtomicLong + +private const val DELAY_MS = 1000L + +class SpeedMeter(scope: CoroutineScope) { + private val bytesPerSecond = MutableStateFlow(0L) + private val bytesCollected = AtomicLong(0) + + init { + scope.launch(FlipperDispatchers.workStealingDispatcher) { + calculateSpeedEachSecond() + } + } + + fun getSpeed(): StateFlow = bytesPerSecond + + fun onReceiveBytes(bytesCount: Int) { + bytesCollected.addAndGet(bytesCount.toLong()) + } + + private suspend fun calculateSpeedEachSecond() = + withContext(FlipperDispatchers.workStealingDispatcher) { + while (isActive) { + delay(DELAY_MS) + val totalBytes = bytesCollected.getAndSet(0) + bytesPerSecond.update { + totalBytes + } + } + } +} diff --git a/components/bridge/pbutils/src/main/proto b/components/bridge/pbutils/src/main/proto index 1c84fa4891..ee5b6a22fd 160000 --- a/components/bridge/pbutils/src/main/proto +++ b/components/bridge/pbutils/src/main/proto @@ -1 +1 @@ -Subproject commit 1c84fa48919cbb71d1cc65236fc0ee36740e24c6 +Subproject commit ee5b6a22fd6aaf9075a2b7bd373309592e6627c5 diff --git a/components/bridge/service/impl/build.gradle.kts b/components/bridge/service/impl/build.gradle.kts index 4b8150f41c..75361ce401 100644 --- a/components/bridge/service/impl/build.gradle.kts +++ b/components/bridge/service/impl/build.gradle.kts @@ -34,7 +34,7 @@ dependencies { implementation(libs.kotlin.coroutines) implementation(libs.lifecycle.runtime.ktx) - implementation(libs.lifecycle.viewmodel.ktx) + implementation(libs.lifecycle.service) implementation(libs.essenty.lifecycle) diff --git a/components/connection/impl/build.gradle.kts b/components/connection/impl/build.gradle.kts index 6be84fb2fb..8231d0391a 100644 --- a/components/connection/impl/build.gradle.kts +++ b/components/connection/impl/build.gradle.kts @@ -33,6 +33,6 @@ dependencies { implementation(libs.decompose) implementation(libs.lifecycle.runtime.ktx) - implementation(libs.lifecycle.viewmodel.ktx) + implementation(libs.lifecycle.compose) } diff --git a/components/core/data/build.gradle.kts b/components/core/data/build.gradle.kts index aa3981b5a3..2411f31f33 100644 --- a/components/core/data/build.gradle.kts +++ b/components/core/data/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("flipper.multiplatform") + id("flipper.multiplatform-compose") id("flipper.multiplatform-dependencies") } @@ -7,7 +7,6 @@ android.namespace = "com.flipperdevices.core.data" commonDependencies { implementation(libs.kotlin.immutable.collections) - implementation(libs.compose.ui) } commonTestDependencies { diff --git a/components/core/preference/src/desktopMain/kotlin/com/flipperdevices/core/preference/FlipperSharedPreferenceModule.kt b/components/core/preference/src/desktopMain/kotlin/com/flipperdevices/core/preference/FlipperSharedPreferenceModule.kt index 21527feb8c..697ea28efd 100644 --- a/components/core/preference/src/desktopMain/kotlin/com/flipperdevices/core/preference/FlipperSharedPreferenceModule.kt +++ b/components/core/preference/src/desktopMain/kotlin/com/flipperdevices/core/preference/FlipperSharedPreferenceModule.kt @@ -52,7 +52,7 @@ class FlipperSharedPreferenceModule { scope = scope + Dispatchers.IO, produceFile = { storageProvider.rootPath - .resolve(SettingsFilePaths.DATASTORE_FILENAME_SETTINGS) + .resolve(SettingsFilePaths.DATASTORE_FILENAME_PAIR_SETTINGS) .toFile() } ) @@ -71,7 +71,7 @@ class FlipperSharedPreferenceModule { scope = scope + Dispatchers.IO, produceFile = { storageProvider.rootPath - .resolve(SettingsFilePaths.DATASTORE_FILENAME_SETTINGS) + .resolve(SettingsFilePaths.DATASTORE_FILENAME_PAIR_SETTINGS_V2) .toFile() } ) diff --git a/components/core/ui/decompose/build.gradle.kts b/components/core/ui/decompose/build.gradle.kts index c06366fa8f..9403d99ccd 100644 --- a/components/core/ui/decompose/build.gradle.kts +++ b/components/core/ui/decompose/build.gradle.kts @@ -10,9 +10,6 @@ commonDependencies { implementation(projects.components.core.preference) - implementation(libs.compose.ui) - implementation(libs.compose.foundation) - implementation(libs.bundles.decompose) implementation(libs.essenty.lifecycle.coroutines) implementation(libs.kotlin.serialization.json) @@ -22,5 +19,4 @@ androidDependencies { implementation(libs.compose.activity) implementation(libs.lifecycle.runtime.ktx) - implementation(libs.lifecycle.viewmodel.ktx) } diff --git a/components/core/ui/dialog/build.gradle.kts b/components/core/ui/dialog/build.gradle.kts index a637fcb7d2..33f87b8255 100644 --- a/components/core/ui/dialog/build.gradle.kts +++ b/components/core/ui/dialog/build.gradle.kts @@ -9,10 +9,4 @@ commonDependencies { implementation(projects.components.core.ui.res) implementation(projects.components.core.ui.ktx) implementation(projects.components.core.ui.theme) - - // Compose - implementation(libs.compose.ui) - implementation(libs.compose.tooling) - implementation(libs.compose.foundation) - implementation(libs.compose.material) } diff --git a/components/core/ui/flippermockup/build.gradle.kts b/components/core/ui/flippermockup/build.gradle.kts index 3849520c9f..5a54a15f68 100644 --- a/components/core/ui/flippermockup/build.gradle.kts +++ b/components/core/ui/flippermockup/build.gradle.kts @@ -8,11 +8,5 @@ android.namespace = "com.flipperdevices.core.ui.flippermockup" commonDependencies { implementation(projects.components.core.ui.theme) - // Compose - implementation(libs.compose.ui) - implementation(libs.compose.tooling) - implementation(libs.compose.foundation) - implementation(libs.compose.material) - implementation(projects.components.core.preference) } diff --git a/components/core/ui/ktx/build.gradle.kts b/components/core/ui/ktx/build.gradle.kts index 6c79d47298..e6c429414c 100644 --- a/components/core/ui/ktx/build.gradle.kts +++ b/components/core/ui/ktx/build.gradle.kts @@ -11,7 +11,6 @@ commonDependencies { implementation(projects.components.core.ui.res) // Compose - implementation(libs.lifecycle.viewmodel.ktx) implementation(libs.lifecycle.compose) implementation(libs.compose.placeholder) @@ -23,5 +22,6 @@ commonDependencies { } androidDependencies { + implementation(libs.image.lottie) } diff --git a/components/core/ui/lifecycle/build.gradle.kts b/components/core/ui/lifecycle/build.gradle.kts index a46022f613..d5fb4a0a63 100644 --- a/components/core/ui/lifecycle/build.gradle.kts +++ b/components/core/ui/lifecycle/build.gradle.kts @@ -9,10 +9,6 @@ commonDependencies { implementation(projects.components.core.ktx) implementation(projects.components.core.log) - // Compose - implementation(libs.compose.ui) - implementation(libs.compose.foundation) - implementation(projects.components.bridge.connection.feature.provider.api) implementation(projects.components.bridge.connection.orchestrator.api) @@ -20,9 +16,10 @@ commonDependencies { implementation(libs.kotlin.coroutines) api(libs.essenty.lifecycle) implementation(libs.essenty.lifecycle.coroutines) + + implementation(libs.annotations) } androidDependencies { implementation(projects.components.bridge.service.api) - implementation(libs.annotations) } diff --git a/components/core/ui/res/src/commonMain/composeResources/drawable/material_ic_close.xml b/components/core/ui/res/src/commonMain/composeResources/drawable/material_ic_close.xml new file mode 100644 index 0000000000..a8dcefdf4a --- /dev/null +++ b/components/core/ui/res/src/commonMain/composeResources/drawable/material_ic_close.xml @@ -0,0 +1,9 @@ + + + diff --git a/components/core/ui/res/src/commonMain/composeResources/drawable/material_ic_folder.xml b/components/core/ui/res/src/commonMain/composeResources/drawable/material_ic_folder.xml new file mode 100644 index 0000000000..147578267a --- /dev/null +++ b/components/core/ui/res/src/commonMain/composeResources/drawable/material_ic_folder.xml @@ -0,0 +1,9 @@ + + + diff --git a/components/core/ui/scrollbar/build.gradle.kts b/components/core/ui/scrollbar/build.gradle.kts index 39ac4cc667..44e5434e8f 100644 --- a/components/core/ui/scrollbar/build.gradle.kts +++ b/components/core/ui/scrollbar/build.gradle.kts @@ -7,10 +7,4 @@ android.namespace = "com.flipperdevices.core.ui.scrollbar" commonDependencies { implementation(projects.components.core.ui.theme) - - // Compose - implementation(libs.compose.ui) - implementation(libs.compose.tooling) - implementation(libs.compose.foundation) - implementation(libs.compose.material) } diff --git a/components/core/ui/searchbar/build.gradle.kts b/components/core/ui/searchbar/build.gradle.kts index 5871d7f033..651cc08df5 100644 --- a/components/core/ui/searchbar/build.gradle.kts +++ b/components/core/ui/searchbar/build.gradle.kts @@ -9,10 +9,4 @@ commonDependencies { implementation(projects.components.core.ui.res) implementation(projects.components.core.ui.theme) implementation(projects.components.core.ui.ktx) - - // Compose - implementation(libs.compose.ui) - implementation(libs.compose.tooling) - implementation(libs.compose.foundation) - implementation(libs.compose.material) } diff --git a/components/core/ui/tabswitch/build.gradle.kts b/components/core/ui/tabswitch/build.gradle.kts index 7c754254df..16526e50d2 100644 --- a/components/core/ui/tabswitch/build.gradle.kts +++ b/components/core/ui/tabswitch/build.gradle.kts @@ -8,10 +8,4 @@ android.namespace = "com.flipperdevices.tabswitch" commonDependencies { implementation(projects.components.core.ui.theme) implementation(projects.components.core.ui.ktx) - - // Compose - implementation(libs.compose.ui) - implementation(libs.compose.tooling) - implementation(libs.compose.foundation) - implementation(libs.compose.material) } diff --git a/components/core/ui/theme/build.gradle.kts b/components/core/ui/theme/build.gradle.kts index 6e0de5cca8..9cdd97e5df 100644 --- a/components/core/ui/theme/build.gradle.kts +++ b/components/core/ui/theme/build.gradle.kts @@ -11,7 +11,4 @@ commonDependencies { implementation(projects.components.core.ui.lifecycle) implementation(projects.components.core.ktx) implementation(projects.components.core.preference) - - implementation(libs.lifecycle.viewmodel.ktx) - implementation(libs.lifecycle.compose) } diff --git a/components/debug/stresstest/build.gradle.kts b/components/debug/stresstest/build.gradle.kts index f0fe44b85e..30353d6c59 100644 --- a/components/debug/stresstest/build.gradle.kts +++ b/components/debug/stresstest/build.gradle.kts @@ -30,7 +30,6 @@ dependencies { implementation(libs.kotlin.immutable.collections) - implementation(libs.lifecycle.viewmodel.ktx) implementation(libs.lifecycle.compose) implementation(libs.bundles.decompose) diff --git a/components/deeplink/api/build.gradle.kts b/components/deeplink/api/build.gradle.kts index 01ce51407c..e83908f52d 100644 --- a/components/deeplink/api/build.gradle.kts +++ b/components/deeplink/api/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("flipper.multiplatform") + id("flipper.multiplatform-compose") id("flipper.multiplatform-dependencies") id("kotlinx-serialization") } @@ -12,7 +12,6 @@ commonDependencies { implementation(projects.components.core.kmpparcelize) implementation(libs.kotlin.serialization.json) - implementation(libs.compose.ui) implementation(libs.annotations) implementation(libs.appcompat) diff --git a/components/faphub/catalogtab/impl/build.gradle.kts b/components/faphub/catalogtab/impl/build.gradle.kts index ed5e3cc2c0..ec61fd5d73 100644 --- a/components/faphub/catalogtab/impl/build.gradle.kts +++ b/components/faphub/catalogtab/impl/build.gradle.kts @@ -35,7 +35,5 @@ dependencies { implementation(libs.compose.paging) implementation(libs.decompose) - implementation(libs.lifecycle.viewmodel.ktx) - implementation(libs.kotlin.immutable.collections) } diff --git a/components/faphub/category/impl/build.gradle.kts b/components/faphub/category/impl/build.gradle.kts index 523bbea4fc..c34ba029e9 100644 --- a/components/faphub/category/impl/build.gradle.kts +++ b/components/faphub/category/impl/build.gradle.kts @@ -39,7 +39,5 @@ dependencies { implementation(libs.bundles.decompose) implementation(libs.compose.paging) - implementation(libs.lifecycle.viewmodel.ktx) - implementation(libs.kotlin.serialization.json) } diff --git a/components/faphub/fapscreen/impl/build.gradle.kts b/components/faphub/fapscreen/impl/build.gradle.kts index 7f056b04f5..97e230d06e 100644 --- a/components/faphub/fapscreen/impl/build.gradle.kts +++ b/components/faphub/fapscreen/impl/build.gradle.kts @@ -35,7 +35,7 @@ dependencies { implementation(libs.compose.tooling) implementation(libs.compose.foundation) implementation(libs.compose.material) - implementation(libs.lifecycle.viewmodel.ktx) + implementation(libs.lifecycle.compose) implementation(libs.bundles.decompose) diff --git a/components/faphub/installation/button/impl/build.gradle.kts b/components/faphub/installation/button/impl/build.gradle.kts index c02edefbe6..45ce83897c 100644 --- a/components/faphub/installation/button/impl/build.gradle.kts +++ b/components/faphub/installation/button/impl/build.gradle.kts @@ -46,6 +46,6 @@ dependencies { implementation(projects.components.faphub.dao.api) implementation(libs.kotlin.coroutines) - implementation(libs.lifecycle.viewmodel.ktx) + implementation(libs.okio) } diff --git a/components/faphub/installedtab/impl/build.gradle.kts b/components/faphub/installedtab/impl/build.gradle.kts index 57c06658f3..99e382198d 100644 --- a/components/faphub/installedtab/impl/build.gradle.kts +++ b/components/faphub/installedtab/impl/build.gradle.kts @@ -38,8 +38,6 @@ dependencies { implementation(libs.decompose) implementation(libs.coil.compose) - implementation(libs.lifecycle.viewmodel.ktx) - implementation(libs.kotlin.immutable.collections) testImplementation(libs.kotlin.coroutines.test) diff --git a/components/faphub/report/impl/build.gradle.kts b/components/faphub/report/impl/build.gradle.kts index a49ab5b104..6b3a3a349f 100644 --- a/components/faphub/report/impl/build.gradle.kts +++ b/components/faphub/report/impl/build.gradle.kts @@ -30,5 +30,4 @@ dependencies { // ViewModel implementation(libs.lifecycle.compose) - implementation(libs.lifecycle.viewmodel.ktx) } diff --git a/components/faphub/screenshotspreview/impl/build.gradle.kts b/components/faphub/screenshotspreview/impl/build.gradle.kts index f1fa379a73..2aa45921c7 100644 --- a/components/faphub/screenshotspreview/impl/build.gradle.kts +++ b/components/faphub/screenshotspreview/impl/build.gradle.kts @@ -25,7 +25,7 @@ dependencies { implementation(libs.compose.tooling) implementation(libs.compose.foundation) implementation(libs.compose.material) - implementation(libs.lifecycle.viewmodel.ktx) + implementation(libs.bundles.decompose) implementation(libs.zoomable) diff --git a/components/faphub/search/impl/build.gradle.kts b/components/faphub/search/impl/build.gradle.kts index b24f573b7a..180c946cf8 100644 --- a/components/faphub/search/impl/build.gradle.kts +++ b/components/faphub/search/impl/build.gradle.kts @@ -36,5 +36,4 @@ dependencies { implementation(libs.compose.material) implementation(libs.compose.paging) implementation(libs.bundles.decompose) - implementation(libs.lifecycle.viewmodel.ktx) } diff --git a/components/faphub/uninstallbutton/impl/build.gradle.kts b/components/faphub/uninstallbutton/impl/build.gradle.kts index f038ca0a21..5b241616e6 100644 --- a/components/faphub/uninstallbutton/impl/build.gradle.kts +++ b/components/faphub/uninstallbutton/impl/build.gradle.kts @@ -25,5 +25,4 @@ dependencies { // ViewModel implementation(libs.lifecycle.compose) - implementation(libs.lifecycle.viewmodel.ktx) } diff --git a/components/filemanager/impl/build.gradle.kts b/components/filemanager/impl/build.gradle.kts index a0df2bb725..1370118341 100644 --- a/components/filemanager/impl/build.gradle.kts +++ b/components/filemanager/impl/build.gradle.kts @@ -45,5 +45,4 @@ dependencies { implementation(libs.kotlin.coroutines) implementation(libs.kotlin.immutable.collections) implementation(libs.lifecycle.runtime.ktx) - implementation(libs.lifecycle.viewmodel.ktx) } diff --git a/components/filemngr/create/api/build.gradle.kts b/components/filemngr/create/api/build.gradle.kts index 4f3654c92c..3444cd2eb7 100644 --- a/components/filemngr/create/api/build.gradle.kts +++ b/components/filemngr/create/api/build.gradle.kts @@ -10,8 +10,9 @@ commonDependencies { implementation(projects.components.core.ui.decompose) - implementation(libs.compose.ui) implementation(libs.decompose) implementation(libs.okio) + + implementation(libs.kotlin.coroutines) } diff --git a/components/filemngr/create/impl/build.gradle.kts b/components/filemngr/create/impl/build.gradle.kts index 480e390edb..b54672e8e9 100644 --- a/components/filemngr/create/impl/build.gradle.kts +++ b/components/filemngr/create/impl/build.gradle.kts @@ -33,10 +33,6 @@ commonDependencies { implementation(projects.components.filemngr.create.api) // Compose - implementation(libs.compose.ui) - implementation(libs.compose.tooling) - implementation(libs.compose.foundation) - implementation(libs.compose.material) implementation(libs.kotlin.serialization.json) implementation(libs.ktor.client) diff --git a/components/filemngr/download/api/build.gradle.kts b/components/filemngr/download/api/build.gradle.kts index 65700f8b18..e4a771b724 100644 --- a/components/filemngr/download/api/build.gradle.kts +++ b/components/filemngr/download/api/build.gradle.kts @@ -8,8 +8,8 @@ android.namespace = "com.flipperdevices.filemanager.download.api" commonDependencies { implementation(projects.components.core.ui.decompose) - implementation(libs.compose.ui) implementation(libs.decompose) implementation(libs.okio) + implementation(libs.kotlin.coroutines) } diff --git a/components/filemngr/download/impl/build.gradle.kts b/components/filemngr/download/impl/build.gradle.kts index 489eafa83a..72ffbb32dc 100644 --- a/components/filemngr/download/impl/build.gradle.kts +++ b/components/filemngr/download/impl/build.gradle.kts @@ -33,10 +33,6 @@ commonDependencies { implementation(projects.components.filemngr.uiComponents) // Compose - implementation(libs.compose.ui) - implementation(libs.compose.tooling) - implementation(libs.compose.foundation) - implementation(libs.compose.material) implementation(libs.decompose) implementation(libs.kotlin.coroutines) diff --git a/components/filemngr/download/impl/src/commonMain/kotlin/com/flipperdevices/filemanager/download/impl/api/DownloadDecomposeComponentImpl.kt b/components/filemngr/download/impl/src/commonMain/kotlin/com/flipperdevices/filemanager/download/impl/api/DownloadDecomposeComponentImpl.kt index 2002ad7bc9..acc699e280 100644 --- a/components/filemngr/download/impl/src/commonMain/kotlin/com/flipperdevices/filemanager/download/impl/api/DownloadDecomposeComponentImpl.kt +++ b/components/filemngr/download/impl/src/commonMain/kotlin/com/flipperdevices/filemanager/download/impl/api/DownloadDecomposeComponentImpl.kt @@ -13,6 +13,7 @@ import com.arkivanov.decompose.ComponentContext import com.arkivanov.essenty.instancekeeper.getOrCreate import com.arkivanov.essenty.lifecycle.coroutines.coroutineScope import com.flipperdevices.core.di.AppGraph +import com.flipperdevices.core.ktx.jre.FlipperDispatchers import com.flipperdevices.core.ui.theme.LocalPalletV2 import com.flipperdevices.filemanager.download.api.DownloadDecomposeComponent import com.flipperdevices.filemanager.download.impl.composable.DownloadingComposable @@ -23,6 +24,7 @@ import dagger.assisted.AssistedInject import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.plus import me.gulya.anvil.assisted.ContributesAssistedFactory import javax.inject.Provider @@ -37,7 +39,11 @@ class DownloadDecomposeComponentImpl @AssistedInject constructor( override val isInProgress = downloadViewModel.state .map { state -> state is DownloadViewModel.State.Downloading } - .stateIn(coroutineScope(), SharingStarted.Eagerly, false) + .stateIn( + coroutineScope(FlipperDispatchers.workStealingDispatcher), + SharingStarted.Eagerly, + false + ) override fun onCancel() = downloadViewModel.onCancel() diff --git a/components/filemngr/editor/api/build.gradle.kts b/components/filemngr/editor/api/build.gradle.kts index 64ec4e8235..25bdbad5a5 100644 --- a/components/filemngr/editor/api/build.gradle.kts +++ b/components/filemngr/editor/api/build.gradle.kts @@ -9,7 +9,6 @@ commonDependencies { implementation(projects.components.core.ui.decompose) implementation(projects.components.bridge.connection.feature.storage.api) - implementation(libs.compose.ui) implementation(libs.decompose) implementation(libs.okio) } diff --git a/components/filemngr/editor/impl/build.gradle.kts b/components/filemngr/editor/impl/build.gradle.kts index 7e2b622bec..3184f26d53 100644 --- a/components/filemngr/editor/impl/build.gradle.kts +++ b/components/filemngr/editor/impl/build.gradle.kts @@ -37,15 +37,6 @@ commonDependencies { implementation(projects.components.filemngr.main.api) implementation(projects.components.filemngr.util) - // Compose - implementation(libs.compose.ui) - implementation(libs.compose.tooling) - implementation(libs.compose.foundation) - implementation(libs.compose.material) - implementation(libs.compose.material3) - implementation(libs.compose.material.icons.core) - implementation(libs.compose.material.icons.extended) - implementation(libs.kotlin.serialization.json) implementation(libs.ktor.client) diff --git a/components/filemngr/listing/api/build.gradle.kts b/components/filemngr/listing/api/build.gradle.kts index 0c6d3a8eef..7a25fcbb71 100644 --- a/components/filemngr/listing/api/build.gradle.kts +++ b/components/filemngr/listing/api/build.gradle.kts @@ -9,7 +9,6 @@ commonDependencies { implementation(projects.components.core.ui.decompose) implementation(projects.components.bridge.connection.feature.storage.api) - implementation(libs.compose.ui) implementation(libs.decompose) implementation(libs.okio) diff --git a/components/filemngr/listing/impl/build.gradle.kts b/components/filemngr/listing/impl/build.gradle.kts index 1cf261510d..b9e2b23c71 100644 --- a/components/filemngr/listing/impl/build.gradle.kts +++ b/components/filemngr/listing/impl/build.gradle.kts @@ -6,6 +6,14 @@ plugins { } android.namespace = "com.flipperdevices.filemanager.listing.impl" +kotlin { + sourceSets { + commonMain.dependencies { + implementation(compose.material3) + } + } +} + commonDependencies { implementation(projects.components.core.di) implementation(projects.components.core.ktx) @@ -37,15 +45,6 @@ commonDependencies { implementation(projects.components.filemngr.create.api) implementation(projects.components.filemngr.util) - // Compose - implementation(libs.compose.ui) - implementation(libs.compose.tooling) - implementation(libs.compose.foundation) - implementation(libs.compose.material) - implementation(libs.compose.material3) - implementation(libs.compose.material.icons.core) - implementation(libs.compose.material.icons.extended) - implementation(libs.kotlin.serialization.json) implementation(libs.ktor.client) diff --git a/components/filemngr/listing/impl/src/commonMain/kotlin/com/flipperdevices/filemanager/listing/impl/composable/appbar/CloseSelectionAppBar.kt b/components/filemngr/listing/impl/src/commonMain/kotlin/com/flipperdevices/filemanager/listing/impl/composable/appbar/CloseSelectionAppBar.kt index 2317286636..b1d36fab26 100644 --- a/components/filemngr/listing/impl/src/commonMain/kotlin/com/flipperdevices/filemanager/listing/impl/composable/appbar/CloseSelectionAppBar.kt +++ b/components/filemngr/listing/impl/src/commonMain/kotlin/com/flipperdevices/filemanager/listing/impl/composable/appbar/CloseSelectionAppBar.kt @@ -9,21 +9,21 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Icon import androidx.compose.material.Text -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Close import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.vector.rememberVectorPainter import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.flipperdevices.core.ui.ktx.OrangeAppBar import com.flipperdevices.core.ui.ktx.clickableRipple import com.flipperdevices.core.ui.theme.LocalPallet import com.flipperdevices.core.ui.theme.LocalTypography +import flipperapp.components.core.ui.res.generated.resources.Res +import flipperapp.components.core.ui.res.generated.resources.material_ic_close import flipperapp.components.filemngr.listing.impl.generated.resources.fml_selection_deselect_all import flipperapp.components.filemngr.listing.impl.generated.resources.fml_selection_select_all +import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource import flipperapp.components.filemngr.listing.impl.generated.resources.Res as FML @@ -42,7 +42,7 @@ fun CloseSelectionAppBar( .size(24.dp) .clip(CircleShape) .clickableRipple(onClick = onClose), - painter = rememberVectorPainter(Icons.Filled.Close), + painter = painterResource(Res.drawable.material_ic_close), contentDescription = null, tint = LocalPallet.current.onAppBar ) diff --git a/components/filemngr/main/api/build.gradle.kts b/components/filemngr/main/api/build.gradle.kts index fa4845e20d..080f7fe6c7 100644 --- a/components/filemngr/main/api/build.gradle.kts +++ b/components/filemngr/main/api/build.gradle.kts @@ -8,7 +8,6 @@ android.namespace = "com.flipperdevices.filemanager.main.api" commonDependencies { implementation(projects.components.core.ui.decompose) - implementation(libs.compose.ui) implementation(libs.decompose) implementation(libs.okio) } diff --git a/components/filemngr/main/impl/build.gradle.kts b/components/filemngr/main/impl/build.gradle.kts index dfcec26fd8..87775b6b44 100644 --- a/components/filemngr/main/impl/build.gradle.kts +++ b/components/filemngr/main/impl/build.gradle.kts @@ -29,14 +29,6 @@ commonDependencies { implementation(projects.components.filemngr.editor.api) implementation(projects.components.filemngr.util) - // Compose - implementation(libs.compose.ui) - implementation(libs.compose.tooling) - implementation(libs.compose.foundation) - implementation(libs.compose.material) - implementation(libs.compose.material.icons.core) - implementation(libs.compose.material.icons.extended) - implementation(libs.kotlin.serialization.json) implementation(libs.ktor.client) diff --git a/components/filemngr/rename/api/build.gradle.kts b/components/filemngr/rename/api/build.gradle.kts index 70ff8d0d93..8b722dff2b 100644 --- a/components/filemngr/rename/api/build.gradle.kts +++ b/components/filemngr/rename/api/build.gradle.kts @@ -10,7 +10,6 @@ commonDependencies { implementation(projects.components.core.ui.decompose) - implementation(libs.compose.ui) implementation(libs.decompose) implementation(libs.okio) diff --git a/components/filemngr/rename/impl/build.gradle.kts b/components/filemngr/rename/impl/build.gradle.kts index 1be48b0b3d..67920c0a20 100644 --- a/components/filemngr/rename/impl/build.gradle.kts +++ b/components/filemngr/rename/impl/build.gradle.kts @@ -33,10 +33,6 @@ commonDependencies { implementation(projects.components.filemngr.rename.api) // Compose - implementation(libs.compose.ui) - implementation(libs.compose.tooling) - implementation(libs.compose.foundation) - implementation(libs.compose.material) implementation(libs.kotlin.serialization.json) implementation(libs.ktor.client) diff --git a/components/filemngr/search/api/build.gradle.kts b/components/filemngr/search/api/build.gradle.kts index 23fa48f754..e894582c3a 100644 --- a/components/filemngr/search/api/build.gradle.kts +++ b/components/filemngr/search/api/build.gradle.kts @@ -8,7 +8,6 @@ android.namespace = "com.flipperdevices.filemanager.search.api" commonDependencies { implementation(projects.components.core.ui.decompose) - implementation(libs.compose.ui) implementation(libs.decompose) implementation(libs.okio) diff --git a/components/filemngr/search/impl/build.gradle.kts b/components/filemngr/search/impl/build.gradle.kts index 4c840e9b14..67b3d60960 100644 --- a/components/filemngr/search/impl/build.gradle.kts +++ b/components/filemngr/search/impl/build.gradle.kts @@ -33,15 +33,6 @@ commonDependencies { implementation(projects.components.filemngr.search.api) implementation(projects.components.filemngr.main.api) - // Compose - implementation(libs.compose.ui) - implementation(libs.compose.tooling) - implementation(libs.compose.foundation) - implementation(libs.compose.material) - implementation(libs.compose.material3) - implementation(libs.compose.material.icons.core) - implementation(libs.compose.material.icons.extended) - implementation(libs.kotlin.serialization.json) implementation(libs.ktor.client) diff --git a/components/filemngr/transfer/api/build.gradle.kts b/components/filemngr/transfer/api/build.gradle.kts index 1e9e8c64b4..73c51845c5 100644 --- a/components/filemngr/transfer/api/build.gradle.kts +++ b/components/filemngr/transfer/api/build.gradle.kts @@ -12,7 +12,6 @@ commonDependencies { implementation(projects.components.filemngr.listing.api) - implementation(libs.compose.ui) implementation(libs.decompose) implementation(libs.okio) diff --git a/components/filemngr/transfer/impl/build.gradle.kts b/components/filemngr/transfer/impl/build.gradle.kts index f5220ada90..e0bc14ba65 100644 --- a/components/filemngr/transfer/impl/build.gradle.kts +++ b/components/filemngr/transfer/impl/build.gradle.kts @@ -42,15 +42,6 @@ commonDependencies { implementation(projects.components.deeplink.api) - // Compose - implementation(libs.compose.ui) - implementation(libs.compose.tooling) - implementation(libs.compose.foundation) - implementation(libs.compose.material) - implementation(libs.compose.activity) - implementation(libs.compose.material.icons.core) - implementation(libs.compose.material.icons.extended) - implementation(libs.kotlin.serialization.json) implementation(libs.ktor.client) diff --git a/components/filemngr/ui-components/build.gradle.kts b/components/filemngr/ui-components/build.gradle.kts index 3d5567f5ab..270d282b8d 100644 --- a/components/filemngr/ui-components/build.gradle.kts +++ b/components/filemngr/ui-components/build.gradle.kts @@ -22,13 +22,6 @@ commonDependencies { implementation(libs.okio.fake) implementation(libs.kotlin.immutable.collections) - // Compose - implementation(libs.compose.ui) - implementation(libs.compose.foundation) - implementation(libs.compose.tooling) - implementation(libs.compose.material) - implementation(libs.compose.material.icons.core) - implementation(libs.compose.material.icons.extended) implementation(libs.compose.placeholder) implementation(libs.bundles.decompose) diff --git a/components/filemngr/ui-components/src/androidMain/kotlin/com/flipperdevices/filemanager/ui/components/itemcard/FolderCardListComposablePreview.kt b/components/filemngr/ui-components/src/androidMain/kotlin/com/flipperdevices/filemanager/ui/components/itemcard/FolderCardListComposablePreview.kt index 09ec1ba252..f294483285 100644 --- a/components/filemngr/ui-components/src/androidMain/kotlin/com/flipperdevices/filemanager/ui/components/itemcard/FolderCardListComposablePreview.kt +++ b/components/filemngr/ui-components/src/androidMain/kotlin/com/flipperdevices/filemanager/ui/components/itemcard/FolderCardListComposablePreview.kt @@ -2,14 +2,13 @@ package com.flipperdevices.filemanager.ui.components.itemcard import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Folder import androidx.compose.runtime.Composable -import androidx.compose.ui.graphics.vector.rememberVectorPainter import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.flipperdevices.core.ui.theme.FlipperThemeInternal import com.flipperdevices.filemanager.ui.components.itemcard.model.ItemUiSelectionState +import flipperapp.components.core.ui.res.generated.resources.Res +import flipperapp.components.core.ui.res.generated.resources.material_ic_folder import flipperapp.components.filemngr.ui_components.generated.resources.ic_folder_black import org.jetbrains.compose.resources.painterResource import flipperapp.components.filemngr.ui_components.generated.resources.Res as FR @@ -35,7 +34,7 @@ private fun FolderCardListComposablePreview() { } ItemUiSelectionState.entries.forEach { selectionState -> SwipeToDismissFolderCardListComposable( - painter = rememberVectorPainter(Icons.Filled.Folder), + painter = painterResource(Res.drawable.material_ic_folder), title = "A very very ultra mega super duper log title with some message at the end", subtitle = "A very very ultra mega super duper log title with some message at the end", selectionState = selectionState, @@ -49,7 +48,7 @@ private fun FolderCardListComposablePreview() { } ItemUiSelectionState.entries.forEach { selectionState -> SwipeToDismissFolderCardListComposable( - painter = rememberVectorPainter(Icons.Filled.Folder), + painter = painterResource(Res.drawable.material_ic_folder), title = "A very very ultra mega super duper log title with some message at the end", subtitle = "A very very ultra mega super duper log title with some message at the end", selectionState = selectionState, diff --git a/components/filemngr/ui-components/src/commonMain/kotlin/com/flipperdevices/filemanager/ui/components/name/NameDialog.kt b/components/filemngr/ui-components/src/commonMain/kotlin/com/flipperdevices/filemanager/ui/components/name/NameDialog.kt index 6aa7bb2dc9..1494d862cb 100644 --- a/components/filemngr/ui-components/src/commonMain/kotlin/com/flipperdevices/filemanager/ui/components/name/NameDialog.kt +++ b/components/filemngr/ui-components/src/commonMain/kotlin/com/flipperdevices/filemanager/ui/components/name/NameDialog.kt @@ -15,18 +15,18 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.selection.DisableSelection import androidx.compose.material.Icon -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Close import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.vector.rememberVectorPainter import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import com.flipperdevices.core.ui.ktx.elements.ComposableFlipperButton import com.flipperdevices.core.ui.theme.LocalPallet import com.flipperdevices.core.ui.theme.LocalPalletV2 +import flipperapp.components.core.ui.res.generated.resources.Res +import flipperapp.components.core.ui.res.generated.resources.material_ic_close import kotlinx.collections.immutable.ImmutableList +import org.jetbrains.compose.resources.painterResource @Composable fun NameDialog( @@ -57,7 +57,7 @@ fun NameDialog( horizontalArrangement = Arrangement.End ) { Icon( - painter = rememberVectorPainter(Icons.Filled.Close), + painter = painterResource(Res.drawable.material_ic_close), tint = LocalPalletV2.current.icon.blackAndWhite.default, contentDescription = null, modifier = Modifier diff --git a/components/filemngr/upload/api/build.gradle.kts b/components/filemngr/upload/api/build.gradle.kts index a84819b7d0..9e296d24e2 100644 --- a/components/filemngr/upload/api/build.gradle.kts +++ b/components/filemngr/upload/api/build.gradle.kts @@ -12,7 +12,6 @@ commonDependencies { implementation(projects.components.bridge.connection.feature.storage.api) - implementation(libs.compose.ui) implementation(libs.decompose) implementation(libs.okio) diff --git a/components/filemngr/upload/impl/build.gradle.kts b/components/filemngr/upload/impl/build.gradle.kts index b833584854..782e7e1c87 100644 --- a/components/filemngr/upload/impl/build.gradle.kts +++ b/components/filemngr/upload/impl/build.gradle.kts @@ -10,6 +10,8 @@ androidDependencies { implementation(projects.components.bridge.api) implementation(projects.components.bridge.pbutils) implementation(projects.components.bridge.service.api) + + implementation(libs.compose.activity) } commonDependencies { @@ -46,15 +48,6 @@ commonDependencies { implementation(projects.components.deeplink.api) - // Compose - implementation(libs.compose.ui) - implementation(libs.compose.tooling) - implementation(libs.compose.foundation) - implementation(libs.compose.material) - implementation(libs.compose.activity) - implementation(libs.compose.material.icons.core) - implementation(libs.compose.material.icons.extended) - implementation(libs.kotlin.serialization.json) implementation(libs.ktor.client) diff --git a/components/filemngr/upload/impl/src/desktopMain/kotlin/com/flipperdevices/filemanager/upload/impl/api/UploadDecomposeComponentNoop.kt b/components/filemngr/upload/impl/src/desktopMain/kotlin/com/flipperdevices/filemanager/upload/impl/api/UploadDecomposeComponentNoop.kt new file mode 100644 index 0000000000..28c818ab32 --- /dev/null +++ b/components/filemngr/upload/impl/src/desktopMain/kotlin/com/flipperdevices/filemanager/upload/impl/api/UploadDecomposeComponentNoop.kt @@ -0,0 +1,28 @@ +package com.flipperdevices.filemanager.upload.impl.api + +import androidx.compose.runtime.Composable +import com.arkivanov.decompose.ComponentContext +import com.flipperdevices.bridge.connection.feature.storage.api.model.ListingItem +import com.flipperdevices.core.di.AppGraph +import com.flipperdevices.filemanager.upload.api.MultipleFilesPicker +import com.flipperdevices.filemanager.upload.api.UploadDecomposeComponent +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import me.gulya.anvil.assisted.ContributesAssistedFactory +import okio.Path + +@ContributesAssistedFactory(AppGraph::class, UploadDecomposeComponent.Factory::class) +class UploadDecomposeComponentNoop @AssistedInject constructor( + @Suppress("UnusedPrivateProperty") @Assisted componentContext: ComponentContext, + @Suppress("UnusedPrivateProperty") @Assisted private val onFilesChanged: (List) -> Unit, +) : UploadDecomposeComponent { + @Composable + override fun rememberMultipleFilesPicker( + path: Path + ) = MultipleFilesPicker {} + + @Composable + override fun Render() { + // Empty + } +} diff --git a/components/info/impl/build.gradle.kts b/components/info/impl/build.gradle.kts index 758cd3f913..5c2f1b5bfa 100644 --- a/components/info/impl/build.gradle.kts +++ b/components/info/impl/build.gradle.kts @@ -69,7 +69,7 @@ dependencies { implementation(libs.kotlin.coroutines) implementation(libs.kotlin.immutable.collections) implementation(libs.lifecycle.runtime.ktx) - implementation(libs.lifecycle.viewmodel.ktx) + implementation(libs.lifecycle.compose) implementation(libs.ble) diff --git a/components/infrared/editor/build.gradle.kts b/components/infrared/editor/build.gradle.kts index e24e85506e..cccfd333c1 100644 --- a/components/infrared/editor/build.gradle.kts +++ b/components/infrared/editor/build.gradle.kts @@ -41,7 +41,6 @@ dependencies { // ViewModel implementation(libs.lifecycle.compose) - implementation(libs.lifecycle.viewmodel.ktx) implementation(libs.kotlin.serialization.json) implementation(libs.kotlin.immutable.collections) diff --git a/components/infrared/impl/build.gradle.kts b/components/infrared/impl/build.gradle.kts index 4aa21123b9..91093b29ff 100644 --- a/components/infrared/impl/build.gradle.kts +++ b/components/infrared/impl/build.gradle.kts @@ -44,7 +44,7 @@ dependencies { // ViewModel implementation(libs.lifecycle.compose) - implementation(libs.lifecycle.viewmodel.ktx) + implementation(libs.lifecycle.runtime.ktx) implementation(libs.kotlin.serialization.json) diff --git a/components/keyedit/impl/build.gradle.kts b/components/keyedit/impl/build.gradle.kts index 03228e78fc..8b439d4721 100644 --- a/components/keyedit/impl/build.gradle.kts +++ b/components/keyedit/impl/build.gradle.kts @@ -45,7 +45,6 @@ dependencies { implementation(libs.bundles.decompose) implementation(libs.lifecycle.compose) - implementation(libs.lifecycle.viewmodel.ktx) implementation(libs.lifecycle.runtime.ktx) implementation(libs.okio) diff --git a/components/keyemulate/impl/build.gradle.kts b/components/keyemulate/impl/build.gradle.kts index 9aca9536e7..a06b06bdd6 100644 --- a/components/keyemulate/impl/build.gradle.kts +++ b/components/keyemulate/impl/build.gradle.kts @@ -42,7 +42,7 @@ dependencies { implementation(libs.appcompat) implementation(libs.lifecycle.compose) - implementation(libs.lifecycle.viewmodel.ktx) + implementation(libs.lifecycle.runtime.ktx) // Testing diff --git a/components/keyscreen/impl/build.gradle.kts b/components/keyscreen/impl/build.gradle.kts index a68f562131..b93031dabb 100644 --- a/components/keyscreen/impl/build.gradle.kts +++ b/components/keyscreen/impl/build.gradle.kts @@ -51,7 +51,7 @@ dependencies { implementation(libs.appcompat) implementation(libs.lifecycle.compose) - implementation(libs.lifecycle.viewmodel.ktx) + implementation(libs.lifecycle.runtime.ktx) // Testing diff --git a/components/newfilemanager/api/.gitignore b/components/newfilemanager/api/.gitignore deleted file mode 100644 index c795b054e5..0000000000 --- a/components/newfilemanager/api/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build \ No newline at end of file diff --git a/components/newfilemanager/api/build.gradle.kts b/components/newfilemanager/api/build.gradle.kts deleted file mode 100644 index bd192d31dc..0000000000 --- a/components/newfilemanager/api/build.gradle.kts +++ /dev/null @@ -1,15 +0,0 @@ -plugins { - id("flipper.multiplatform") - id("flipper.multiplatform-dependencies") -} - -android.namespace = "com.flipperdevices.newfilemanager.api" - -commonDependencies { - implementation(projects.components.deeplink.api) - - implementation(projects.components.core.ui.decompose) - - implementation(libs.compose.ui) - implementation(libs.decompose) -} diff --git a/components/newfilemanager/api/src/commonMain/kotlin/com/flipperdevices/newfilemanager/api/navigation/FileManagerDecomposeComponent.kt b/components/newfilemanager/api/src/commonMain/kotlin/com/flipperdevices/newfilemanager/api/navigation/FileManagerDecomposeComponent.kt deleted file mode 100644 index 036a28b81b..0000000000 --- a/components/newfilemanager/api/src/commonMain/kotlin/com/flipperdevices/newfilemanager/api/navigation/FileManagerDecomposeComponent.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.flipperdevices.newfilemanager.api.navigation - -import com.arkivanov.decompose.ComponentContext -import com.flipperdevices.ui.decompose.CompositeDecomposeComponent -import com.flipperdevices.ui.decompose.DecomposeOnBackParameter - -abstract class FileManagerDecomposeComponent : CompositeDecomposeComponent() { - fun interface Factory { - operator fun invoke( - componentContext: ComponentContext, - onBack: DecomposeOnBackParameter - ): FileManagerDecomposeComponent<*> - } -} diff --git a/components/newfilemanager/impl/.gitignore b/components/newfilemanager/impl/.gitignore deleted file mode 100644 index c795b054e5..0000000000 --- a/components/newfilemanager/impl/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build \ No newline at end of file diff --git a/components/newfilemanager/impl/build.gradle.kts b/components/newfilemanager/impl/build.gradle.kts deleted file mode 100644 index 04ad0d6ffd..0000000000 --- a/components/newfilemanager/impl/build.gradle.kts +++ /dev/null @@ -1,53 +0,0 @@ -plugins { - id("flipper.multiplatform-compose") - id("flipper.multiplatform-dependencies") - id("flipper.anvil-multiplatform") - id("kotlinx-serialization") -} - -android.namespace = "com.flipperdevices.newfilemanager.impl" - -androidDependencies { - implementation(projects.components.core.di) - implementation(projects.components.core.log) - implementation(projects.components.core.ktx) - implementation(projects.components.core.progress) - implementation(projects.components.core.storage) - implementation(projects.components.core.preference) - implementation(projects.components.core.ui.theme) - implementation(projects.components.core.ui.lifecycle) - implementation(projects.components.core.ui.res) - implementation(projects.components.core.ui.ktx) - implementation(projects.components.core.ui.decompose) - implementation(projects.components.core.share) - - implementation(projects.components.bridge.connection.feature.common.api) - implementation(projects.components.bridge.connection.transport.common.api) - implementation(projects.components.bridge.connection.feature.provider.api) - implementation(projects.components.bridge.connection.feature.storage.api) - implementation(projects.components.bridge.connection.feature.serialspeed.api) - implementation(projects.components.bridge.dao.api) - - implementation(projects.components.newfilemanager.api) - - implementation(libs.kotlin.serialization.json) - - implementation(projects.components.deeplink.api) - - implementation(projects.components.bottombar.api) - - implementation(libs.annotations) - implementation(libs.appcompat) - - implementation(libs.compose.ui) - implementation(libs.compose.tooling) - implementation(libs.compose.foundation) - implementation(libs.compose.material) - implementation(libs.compose.activity) - implementation(libs.bundles.decompose) - - implementation(libs.kotlin.coroutines) - implementation(libs.kotlin.immutable.collections) - implementation(libs.lifecycle.runtime.ktx) - implementation(libs.lifecycle.viewmodel.ktx) -} diff --git a/components/newfilemanager/impl/src/androidMain/composeResources/values/strings.xml b/components/newfilemanager/impl/src/androidMain/composeResources/values/strings.xml deleted file mode 100644 index 3053617f36..0000000000 --- a/components/newfilemanager/impl/src/androidMain/composeResources/values/strings.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - Folder - File - Save file - Upload file - Create file or folder - Empty folder - Upload file %1$s - Download file %1$s - Share key %1$s - %1$s out of %2$s with speed: %3$s - %1$s with speed: %2$s - OK - Cancel - Uploading a file to your phone for editing (%1$s) - Uploading a file to the flipper (%1$s) - The file is larger than 1MB and therefore only part of the file is shown. The content will be overwritten when you save it! - Edit - Download & Share - Delete - Create file - Create folder - There should be a description of the error here, but we haven\'t added it yet - Error - Enter file name - Enter folder name - The file name cannot be empty - The file name too long - The file name can only contain numbers, characters of the Latin alphabet and the following characters: !#$%&\'()-@^_`{}~ - - \ No newline at end of file diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/api/FileManagerDecomposeComponentImpl.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/api/FileManagerDecomposeComponentImpl.kt deleted file mode 100644 index 3bc7573599..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/api/FileManagerDecomposeComponentImpl.kt +++ /dev/null @@ -1,65 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.api - -import com.arkivanov.decompose.ComponentContext -import com.arkivanov.decompose.router.stack.ChildStack -import com.arkivanov.decompose.router.stack.childStack -import com.arkivanov.decompose.value.Value -import com.flipperdevices.core.di.AppGraph -import com.flipperdevices.newfilemanager.api.navigation.FileManagerDecomposeComponent -import com.flipperdevices.newfilemanager.impl.model.FileManagerNavigationConfig -import com.flipperdevices.ui.decompose.DecomposeComponent -import com.flipperdevices.ui.decompose.DecomposeOnBackParameter -import com.flipperdevices.ui.decompose.popOr -import dagger.assisted.Assisted -import dagger.assisted.AssistedInject -import me.gulya.anvil.assisted.ContributesAssistedFactory - -@ContributesAssistedFactory(AppGraph::class, FileManagerDecomposeComponent.Factory::class) -class FileManagerDecomposeComponentImpl @AssistedInject constructor( - @Assisted componentContext: ComponentContext, - @Assisted private val onBack: DecomposeOnBackParameter, - private val fileManagerListingFactory: FileManagerListingComponent.Factory, - private val fileManagerUploadingFactory: FileManagerUploadingComponent.Factory, - private val fileManagerEditingFactory: FileManagerEditingComponent.Factory, - private val fileManagerDownloadFactory: FileManagerDownloadComponent.Factory -) : FileManagerDecomposeComponent(), - ComponentContext by componentContext { - - override val stack: Value> = - childStack( - source = navigation, - serializer = FileManagerNavigationConfig.serializer(), - initialConfiguration = FileManagerNavigationConfig.Screen("/"), - handleBackButton = true, - childFactory = ::child, - ) - - private fun child( - config: FileManagerNavigationConfig, - componentContext: ComponentContext - ): DecomposeComponent = when (config) { - is FileManagerNavigationConfig.Screen -> fileManagerListingFactory( - componentContext, - config, - navigation - ) - - is FileManagerNavigationConfig.Uploading -> fileManagerUploadingFactory( - componentContext, - config, - onBack = { navigation.popOr(onBack::invoke) } - ) - - is FileManagerNavigationConfig.Editing -> fileManagerEditingFactory( - componentContext, - config, - onBack = { navigation.popOr(onBack::invoke) } - ) - - is FileManagerNavigationConfig.Download -> fileManagerDownloadFactory( - componentContext, - config, - onBack = { navigation.popOr(onBack::invoke) } - ) - } -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/api/FileManagerDownloadComponent.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/api/FileManagerDownloadComponent.kt deleted file mode 100644 index 135492aed5..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/api/FileManagerDownloadComponent.kt +++ /dev/null @@ -1,64 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.api - -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import com.arkivanov.decompose.ComponentContext -import com.flipperdevices.core.ui.lifecycle.viewModelWithFactory -import com.flipperdevices.newfilemanager.impl.composable.ComposableFileManagerDownloadScreen -import com.flipperdevices.newfilemanager.impl.model.FileManagerNavigationConfig -import com.flipperdevices.newfilemanager.impl.model.ShareState -import com.flipperdevices.newfilemanager.impl.viewmodels.FileManagerViewModel -import com.flipperdevices.newfilemanager.impl.viewmodels.ShareViewModel -import com.flipperdevices.ui.decompose.DecomposeOnBackParameter -import com.flipperdevices.ui.decompose.ScreenDecomposeComponent -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject -import flipperapp.components.newfilemanager.impl.generated.resources.Res -import flipperapp.components.newfilemanager.impl.generated.resources.filemanager_error -import org.jetbrains.compose.resources.stringResource - -class FileManagerDownloadComponent @AssistedInject constructor( - private val fileManagerViewModelFactory: FileManagerViewModel.Factory, - private val shareModelFactory: ShareViewModel.Factory, - @Assisted componentContext: ComponentContext, - @Assisted private val config: FileManagerNavigationConfig.Download, - @Assisted private val onBack: DecomposeOnBackParameter -) : ScreenDecomposeComponent(componentContext) { - @Composable - @Suppress("NonSkippableComposable") - override fun Render() { - val fileManagerViewModel = viewModelWithFactory(key = config.path) { - fileManagerViewModelFactory(config.path) - } - val shareViewModel = viewModelWithFactory(key = config.shareFile.toString()) { - shareModelFactory(config.shareFile) - } - val fileManagerState by fileManagerViewModel.getFileManagerState().collectAsState() - val shareState by shareViewModel.getShareState().collectAsState() - val speedState by shareViewModel.getSpeedState().collectAsState() - - shareState.let { shareStateLocal -> - when (shareStateLocal) { - ShareState.Error -> Text(stringResource(Res.string.filemanager_error)) - is ShareState.Ready -> ComposableFileManagerDownloadScreen( - fileManagerState = fileManagerState, - shareState = shareStateLocal, - onBack = onBack::invoke, - speedState = speedState - ) - } - } - } - - @AssistedFactory - fun interface Factory { - operator fun invoke( - componentContext: ComponentContext, - config: FileManagerNavigationConfig.Download, - onBack: DecomposeOnBackParameter - ): FileManagerDownloadComponent - } -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/api/FileManagerEditingComponent.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/api/FileManagerEditingComponent.kt deleted file mode 100644 index 6eb72f4ba2..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/api/FileManagerEditingComponent.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.api - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import com.arkivanov.decompose.ComponentContext -import com.flipperdevices.core.ui.lifecycle.viewModelWithFactory -import com.flipperdevices.newfilemanager.impl.composable.ComposableFileManagerEditorScreen -import com.flipperdevices.newfilemanager.impl.model.FileManagerNavigationConfig -import com.flipperdevices.newfilemanager.impl.viewmodels.EditorViewModel -import com.flipperdevices.ui.decompose.DecomposeOnBackParameter -import com.flipperdevices.ui.decompose.ScreenDecomposeComponent -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject - -class FileManagerEditingComponent @AssistedInject constructor( - private val editorViewModelFactory: EditorViewModel.Factory, - @Assisted componentContext: ComponentContext, - @Assisted private val config: FileManagerNavigationConfig.Editing, - @Assisted private val onBack: DecomposeOnBackParameter -) : ScreenDecomposeComponent(componentContext) { - @Composable - @Suppress("NonSkippableComposable") - override fun Render() { - val editorViewModel = viewModelWithFactory(key = config.shareFile.toString()) { - editorViewModelFactory(config.shareFile) - } - val editorState by editorViewModel.getEditorState().collectAsState() - ComposableFileManagerEditorScreen( - editorState = editorState, - onClickSaveButton = editorViewModel::onSaveFile, - onBack = onBack::invoke - ) - } - - @AssistedFactory - fun interface Factory { - operator fun invoke( - componentContext: ComponentContext, - config: FileManagerNavigationConfig.Editing, - onBack: DecomposeOnBackParameter - ): FileManagerEditingComponent - } -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/api/FileManagerListingComponent.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/api/FileManagerListingComponent.kt deleted file mode 100644 index 5697623b88..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/api/FileManagerListingComponent.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.api - -import androidx.compose.runtime.Composable -import com.arkivanov.decompose.ComponentContext -import com.arkivanov.decompose.router.stack.StackNavigation -import com.arkivanov.decompose.router.stack.pushToFront -import com.flipperdevices.core.ui.lifecycle.viewModelWithFactory -import com.flipperdevices.deeplink.api.DeepLinkParser -import com.flipperdevices.newfilemanager.impl.composable.ComposableFileManagerScreen -import com.flipperdevices.newfilemanager.impl.model.FileManagerNavigationConfig -import com.flipperdevices.newfilemanager.impl.model.ShareFile -import com.flipperdevices.newfilemanager.impl.viewmodels.FileManagerViewModel -import com.flipperdevices.ui.decompose.ScreenDecomposeComponent -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject -import java.io.File - -class FileManagerListingComponent @AssistedInject constructor( - private val deepLinkParser: DeepLinkParser, - private val fileManagerViewModelFactory: FileManagerViewModel.Factory, - @Assisted componentContext: ComponentContext, - @Assisted val config: FileManagerNavigationConfig.Screen, - @Assisted val navigation: StackNavigation -) : ScreenDecomposeComponent(componentContext) { - @Composable - @Suppress("NonSkippableComposable") - override fun Render() { - ComposableFileManagerScreen( - fileManagerViewModel = viewModelWithFactory(config.path) { - fileManagerViewModelFactory(config.path) - }, - deepLinkParser = deepLinkParser, - onOpenFolder = { - navigation.pushToFront(FileManagerNavigationConfig.Screen(it.path)) - }, - onOpenEditor = { - navigation.pushToFront(FileManagerNavigationConfig.Editing(ShareFile(it))) - }, - onDownloadAndShareFile = { - val shareFile = ShareFile(it) - navigation.pushToFront( - FileManagerNavigationConfig.Download( - path = File(shareFile.flipperFilePath).absoluteFile.parent ?: "/", - shareFile = shareFile - ) - ) - }, - onUploadFile = { path, content -> - navigation.pushToFront( - FileManagerNavigationConfig.Uploading( - path = path, - deeplinkContent = content - ) - ) - } - ) - } - - @AssistedFactory - fun interface Factory { - operator fun invoke( - componentContext: ComponentContext, - config: FileManagerNavigationConfig.Screen, - navigation: StackNavigation - ): FileManagerListingComponent - } -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/api/FileManagerUploadingComponent.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/api/FileManagerUploadingComponent.kt deleted file mode 100644 index 9d9d7fc7ff..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/api/FileManagerUploadingComponent.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.api - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import com.arkivanov.decompose.ComponentContext -import com.flipperdevices.core.ui.lifecycle.viewModelWithFactory -import com.flipperdevices.newfilemanager.impl.composable.ComposableFileManagerUploadedScreen -import com.flipperdevices.newfilemanager.impl.model.FileManagerNavigationConfig -import com.flipperdevices.newfilemanager.impl.viewmodels.FileManagerViewModel -import com.flipperdevices.newfilemanager.impl.viewmodels.ReceiveViewModel -import com.flipperdevices.ui.decompose.DecomposeOnBackParameter -import com.flipperdevices.ui.decompose.ScreenDecomposeComponent -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject - -class FileManagerUploadingComponent @AssistedInject constructor( - private val fileManagerViewModelFactory: FileManagerViewModel.Factory, - private val receiveViewModelFactory: ReceiveViewModel.Factory, - @Assisted componentContext: ComponentContext, - @Assisted private val config: FileManagerNavigationConfig.Uploading, - @Assisted private val onBack: DecomposeOnBackParameter -) : ScreenDecomposeComponent(componentContext) { - @Composable - @Suppress("NonSkippableComposable") - override fun Render() { - val fileManagerViewModel = viewModelWithFactory(key = config.path) { - fileManagerViewModelFactory(config.path) - } - val uploaderViewModel = viewModelWithFactory(key = config.toString()) { - receiveViewModelFactory(config.deeplinkContent, config.path) - } - val fileManagerState by fileManagerViewModel.getFileManagerState().collectAsState() - val shareState by uploaderViewModel.getShareState().collectAsState() - val speedState by uploaderViewModel.getSpeedState().collectAsState() - - ComposableFileManagerUploadedScreen( - fileManagerState = fileManagerState, - shareState = shareState, - onBack = onBack::invoke, - speedState = speedState - ) - } - - @AssistedFactory - fun interface Factory { - operator fun invoke( - componentContext: ComponentContext, - config: FileManagerNavigationConfig.Uploading, - onBack: DecomposeOnBackParameter - ): FileManagerUploadingComponent - } -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/ComposableFileManagerDownloadScreen.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/ComposableFileManagerDownloadScreen.kt deleted file mode 100644 index 51e7f5adda..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/ComposableFileManagerDownloadScreen.kt +++ /dev/null @@ -1,47 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.composable - -import androidx.compose.foundation.layout.Box -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import com.flipperdevices.newfilemanager.impl.composable.dialog.ComposableProgressDialog -import com.flipperdevices.newfilemanager.impl.composable.list.ComposableFileManagerContent -import com.flipperdevices.newfilemanager.impl.model.FileManagerState -import com.flipperdevices.newfilemanager.impl.model.ShareState -import com.flipperdevices.newfilemanager.impl.model.SpeedState -@Composable -fun ComposableFileManagerDownloadScreen( - fileManagerState: FileManagerState, - shareState: ShareState, - speedState: SpeedState, - onBack: () -> Unit -) { - if (shareState is ShareState.Ready && shareState.processCompleted) { - LaunchedEffect(onBack) { - onBack() - } - } - - ComposableFileManagerDownloadScreenInternal( - fileManagerState, - shareState, - onCancel = onBack, - speedState = speedState - ) -} - -@Composable -private fun ComposableFileManagerDownloadScreenInternal( - fileManagerState: FileManagerState, - shareState: ShareState, - speedState: SpeedState, - onCancel: () -> Unit -) { - Box { - ComposableFileManagerContent(fileManagerState = fileManagerState, onFileClick = {}) - ComposableProgressDialog( - shareState = shareState, - onCancel = onCancel, - speedState = speedState - ) - } -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/ComposableFileManagerEditorScreen.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/ComposableFileManagerEditorScreen.kt deleted file mode 100644 index b1e89122d9..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/ComposableFileManagerEditorScreen.kt +++ /dev/null @@ -1,157 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.composable - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.material.CircularProgressIndicator -import androidx.compose.material.Text -import androidx.compose.material.TextField -import androidx.compose.material.TextFieldDefaults -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.flipperdevices.core.ktx.jre.roundPercentToString -import com.flipperdevices.core.ui.theme.FlipperThemeInternal -import com.flipperdevices.core.ui.theme.LocalPallet -import com.flipperdevices.newfilemanager.impl.composable.bar.ComposableEditorTopBar -import com.flipperdevices.newfilemanager.impl.model.DownloadProgress -import com.flipperdevices.newfilemanager.impl.model.EditorState -import flipperapp.components.newfilemanager.impl.generated.resources.Res -import flipperapp.components.newfilemanager.impl.generated.resources.filemanager_editor_loading_title -import flipperapp.components.newfilemanager.impl.generated.resources.filemanager_editor_saving_title -import flipperapp.components.newfilemanager.impl.generated.resources.filemanager_editor_warning -import flipperapp.components.newfilemanager.impl.generated.resources.filemanager_error -import org.jetbrains.compose.resources.StringResource -import org.jetbrains.compose.resources.stringResource - -@Composable -fun ComposableFileManagerEditorScreen( - editorState: EditorState, - onClickSaveButton: (String) -> Unit, - onBack: () -> Unit -) { - if (editorState is EditorState.Saved) { - LaunchedEffect(onBack) { - onBack() - } - } - - ComposableFileManagerEditorScreenInternal( - editorState = editorState, - onClickSaveButton = onClickSaveButton - ) -} - -@Composable -private fun ComposableFileManagerEditorScreenInternal( - editorState: EditorState, - onClickSaveButton: (String) -> Unit -) { - when (editorState) { - is EditorState.Loaded -> ComposableFileManagerEditorContent( - editorState, - onClickSaveButton - ) - - is EditorState.Loading -> ComposableFileManagerInProgress( - text = Res.string.filemanager_editor_loading_title, - progress = editorState.progress - ) - - is EditorState.Saving -> ComposableFileManagerInProgress( - text = Res.string.filemanager_editor_saving_title, - progress = editorState.progress - ) - - EditorState.Saved -> return - EditorState.Error -> Text(stringResource(Res.string.filemanager_error)) - } -} - -@Composable -private fun ComposableFileManagerEditorContent( - loadedState: EditorState.Loaded, - onClickSaveButton: (String) -> Unit -) { - Column { - var text by remember { mutableStateOf(loadedState.content) } - - ComposableEditorTopBar(loadedState.path, onClickSaveButton = { - onClickSaveButton(text) - }) - if (loadedState.tooLarge) { - Text( - modifier = Modifier - .fillMaxWidth() - .background(LocalPallet.current.warningColor), - text = stringResource(Res.string.filemanager_editor_warning), - color = LocalPallet.current.textOnWarningBackground - ) - } - TextField( - modifier = Modifier.fillMaxSize(), - value = text, - onValueChange = { - text = it - }, - colors = TextFieldDefaults.textFieldColors( - cursorColor = LocalPallet.current.text100 - ) - ) - } -} - -@Composable -private fun ComposableFileManagerInProgress( - text: StringResource, - progress: DownloadProgress -) { - Column( - Modifier.fillMaxSize(), - verticalArrangement = Arrangement.Center, - horizontalAlignment = Alignment.CenterHorizontally - ) { - CircularProgressIndicator() - Text( - modifier = Modifier.padding(16.dp), - text = stringResource( - text, - if (progress is DownloadProgress.Fixed) { - progress.toProgressFloat().roundPercentToString() - } else { - "~" - } - ), - textAlign = TextAlign.Center - ) - } -} - -@Preview( - showBackground = true, - showSystemUi = true -) -@Composable -private fun ComposableFileManagerEditorScreenPreview() { - FlipperThemeInternal { - ComposableFileManagerEditorScreenInternal( - EditorState.Loaded( - path = "/ext/test", - "Tmp", - tooLarge = true - ), - onClickSaveButton = {} - ) - } -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/ComposableFileManagerScreen.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/ComposableFileManagerScreen.kt deleted file mode 100644 index c8ffd3e3cd..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/ComposableFileManagerScreen.kt +++ /dev/null @@ -1,189 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.composable - -import androidx.activity.compose.rememberLauncherForActivityResult -import androidx.activity.result.contract.ActivityResultContracts -import androidx.compose.foundation.layout.padding -import androidx.compose.material.Scaffold -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import com.flipperdevices.deeplink.api.DeepLinkParser -import com.flipperdevices.deeplink.model.Deeplink -import com.flipperdevices.deeplink.model.DeeplinkContent -import com.flipperdevices.newfilemanager.impl.composable.bar.ComposableFileManagerTopBar -import com.flipperdevices.newfilemanager.impl.composable.dialog.ComposableInputDialog -import com.flipperdevices.newfilemanager.impl.composable.dialog.ComposableSelectDialog -import com.flipperdevices.newfilemanager.impl.composable.list.ComposableFileManagerContent -import com.flipperdevices.newfilemanager.impl.model.CreateFileManagerAction -import com.flipperdevices.newfilemanager.impl.model.FileItem -import com.flipperdevices.newfilemanager.impl.model.FileManagerState -import com.flipperdevices.newfilemanager.impl.viewmodels.FileManagerViewModel -import flipperapp.components.newfilemanager.impl.generated.resources.Res -import flipperapp.components.newfilemanager.impl.generated.resources.add_dialog_title_file -import flipperapp.components.newfilemanager.impl.generated.resources.add_dialog_title_folder -import flipperapp.components.newfilemanager.impl.generated.resources.filemanager_add_dialog_file -import flipperapp.components.newfilemanager.impl.generated.resources.filemanager_add_dialog_folder -import flipperapp.components.newfilemanager.impl.generated.resources.filemanager_open_dialog_delete -import flipperapp.components.newfilemanager.impl.generated.resources.filemanager_open_dialog_download -import flipperapp.components.newfilemanager.impl.generated.resources.filemanager_open_dialog_edit -import kotlinx.coroutines.runBlocking - -@Composable -fun ComposableFileManagerScreen( - fileManagerViewModel: FileManagerViewModel, - deepLinkParser: DeepLinkParser, - onOpenFolder: (FileItem) -> Unit, - onDownloadAndShareFile: (FileItem) -> Unit, - onOpenEditor: (FileItem) -> Unit, - onUploadFile: (path: String, DeeplinkContent) -> Unit -) { - val fileManagerState by fileManagerViewModel.getFileManagerState().collectAsState() - - var pendingDialogItem by remember { mutableStateOf(null) } - val localFileItem = pendingDialogItem - - if (localFileItem != null) { - val chooseOptions = if (isAbleToDelete(fileManagerState.currentPath)) { - arrayOf( - Res.string.filemanager_open_dialog_edit, - Res.string.filemanager_open_dialog_download, - Res.string.filemanager_open_dialog_delete - ) - } else { - arrayOf( - Res.string.filemanager_open_dialog_edit, - Res.string.filemanager_open_dialog_download - ) - } - ComposableSelectDialog(chooseOptions, onSelect = { - when (it) { - Res.string.filemanager_open_dialog_edit -> onOpenEditor(localFileItem) - Res.string.filemanager_open_dialog_download -> onDownloadAndShareFile(localFileItem) - Res.string.filemanager_open_dialog_delete -> { - fileManagerViewModel.onDeleteAction(localFileItem) - pendingDialogItem = null - } - else -> pendingDialogItem = null - } - }) - } - - var showAddDialog by remember { mutableStateOf(false) } - if (showAddDialog) { - ComposableCreateActionDialog( - onCreateAction = fileManagerViewModel::onCreateAction, - onDismiss = { showAddDialog = false } - ) - } - - ComposableFileManagerScreenInternal( - fileManagerState = fileManagerState, - deepLinkParser = deepLinkParser, - onOpenFolder = { - if (it.isDirectory) { - onOpenFolder(it) - } else { - pendingDialogItem = it - } - }, - onUploadFile = { - onUploadFile(fileManagerState.currentPath, it) - }, - onAddButton = { - showAddDialog = true - } - ) -} - -@Composable -private fun ComposableCreateActionDialog( - onCreateAction: (CreateFileManagerAction, String) -> Unit, - onDismiss: () -> Unit -) { - var createFileManagerAction by remember { mutableStateOf(null) } - val localCreateFileManagerAction = createFileManagerAction - - if (localCreateFileManagerAction != null) { - ComposableInputDialog( - when (localCreateFileManagerAction) { - CreateFileManagerAction.FILE -> Res.string.add_dialog_title_file - CreateFileManagerAction.FOLDER -> Res.string.add_dialog_title_folder - } - ) { - if (it != null) { - onCreateAction(localCreateFileManagerAction, it) - } - onDismiss() - createFileManagerAction = null - } - } - - ComposableSelectDialog( - arrayOf( - Res.string.filemanager_add_dialog_file, - Res.string.filemanager_add_dialog_folder - ), - onSelect = { - when (it) { - Res.string.filemanager_add_dialog_file -> - createFileManagerAction = CreateFileManagerAction.FILE - Res.string.filemanager_add_dialog_folder -> - createFileManagerAction = CreateFileManagerAction.FOLDER - else -> onDismiss() - } - } - ) -} - -@Composable -private fun ComposableFileManagerScreenInternal( - fileManagerState: FileManagerState, - onOpenFolder: (FileItem) -> Unit, - deepLinkParser: DeepLinkParser, - onUploadFile: (DeeplinkContent) -> Unit, - onAddButton: () -> Unit -) { - val context = LocalContext.current - - val pickFileLauncher = rememberLauncherForActivityResult( - ActivityResultContracts.GetContent() - ) { uri -> - if (uri != null) { - runBlocking { - val deeplink = deepLinkParser.fromUri(context, uri) - - if (deeplink != null && deeplink is Deeplink.RootLevel.SaveKey.ExternalContent) { - val deeplinkContent = deeplink.content - if (deeplinkContent != null) { - onUploadFile(deeplinkContent) - } - } - } - } - } - - Scaffold( - topBar = { - ComposableFileManagerTopBar( - fileManagerState.currentPath, - onClickUploadButton = { - pickFileLauncher.launch("*/*") - }, - onClickAddButton = onAddButton - ) - } - ) { scaffoldPaddings -> - ComposableFileManagerContent( - modifier = Modifier.padding(scaffoldPaddings), - fileManagerState = fileManagerState, - onFileClick = onOpenFolder - ) - } -} - -private fun isAbleToDelete(path: String) = path.startsWith("/ext") diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/ComposableFileManagerUploadedScreen.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/ComposableFileManagerUploadedScreen.kt deleted file mode 100644 index 4a5431f35c..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/ComposableFileManagerUploadedScreen.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.composable - -import androidx.compose.foundation.layout.Box -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import com.flipperdevices.newfilemanager.impl.composable.dialog.ComposableProgressDialog -import com.flipperdevices.newfilemanager.impl.composable.list.ComposableFileManagerContent -import com.flipperdevices.newfilemanager.impl.model.FileManagerState -import com.flipperdevices.newfilemanager.impl.model.ShareState -import com.flipperdevices.newfilemanager.impl.model.SpeedState - -@Composable -fun ComposableFileManagerUploadedScreen( - fileManagerState: FileManagerState, - shareState: ShareState, - speedState: SpeedState, - onBack: () -> Unit -) { - if (shareState is ShareState.Ready && shareState.processCompleted) { - LaunchedEffect(onBack) { - onBack() - } - } - - ComposableFileManagerUploadedScreenInternal( - fileManagerState, - shareState, - speedState, - onCancel = onBack - ) -} - -@Composable -private fun ComposableFileManagerUploadedScreenInternal( - fileManagerState: FileManagerState, - shareState: ShareState, - speedState: SpeedState, - onCancel: () -> Unit -) { - Box { - ComposableFileManagerContent(fileManagerState = fileManagerState, onFileClick = {}) - ComposableProgressDialog( - shareState = shareState, - speedState = speedState, - onCancel = onCancel - ) - } -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/bar/ComposableEditorTopBar.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/bar/ComposableEditorTopBar.kt deleted file mode 100644 index 45dab7f886..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/bar/ComposableEditorTopBar.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.composable.bar - -import androidx.compose.foundation.layout.statusBarsPadding -import androidx.compose.material.Icon -import androidx.compose.material.IconButton -import androidx.compose.material.TopAppBar -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import com.flipperdevices.newfilemanager.impl.R -import flipperapp.components.newfilemanager.impl.generated.resources.Res -import flipperapp.components.newfilemanager.impl.generated.resources.filemanager_save_action -import org.jetbrains.compose.resources.stringResource - -@Composable -fun ComposableEditorTopBar( - path: String, - onClickSaveButton: () -> Unit, - modifier: Modifier = Modifier -) { - TopAppBar( - modifier = modifier.statusBarsPadding(), - title = { - ComposableEllipsizeStartText( - text = path - ) - }, - actions = { - IconButton(onClick = onClickSaveButton) { - Icon( - painter = painterResource( - R.drawable.ic_ok - ), - contentDescription = stringResource( - Res.string.filemanager_save_action - ) - ) - } - } - ) -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/bar/ComposableEllipsizeStartText.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/bar/ComposableEllipsizeStartText.kt deleted file mode 100644 index d37909327a..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/bar/ComposableEllipsizeStartText.kt +++ /dev/null @@ -1,81 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.composable.bar - -import androidx.compose.foundation.layout.BoxWithConstraints -import androidx.compose.foundation.layout.BoxWithConstraintsScope -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.material.LocalTextStyle -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.platform.LocalFontFamilyResolver -import androidx.compose.ui.platform.LocalLayoutDirection -import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.rememberTextMeasurer -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.tooling.preview.Preview - -@Composable -fun ComposableEllipsizeStartText( - text: String, - modifier: Modifier = Modifier, - textStyle: TextStyle = LocalTextStyle.current -) { - BoxWithConstraints( - modifier = modifier.fillMaxWidth() - ) { - var fittableText = text - var alreadyReplacedCount = 2 - while (shouldShrink(text = fittableText, textStyle = textStyle)) { - alreadyReplacedCount++ - val remainingLength = text.length - alreadyReplacedCount - if (remainingLength <= 1) { - break - } - fittableText = "...${text.takeLast(remainingLength)}" - } - - Text( - text = fittableText, - style = textStyle, - maxLines = 1 - ) - } -} - -@Composable -private fun BoxWithConstraintsScope.shouldShrink( - text: String, - textStyle: TextStyle -): Boolean { - val textMeasurer = rememberTextMeasurer() - - // Represent line without index and paddings - val textLayoutResult = textMeasurer.measure( - AnnotatedString(text), - textStyle, - maxLines = 1, - softWrap = false, - overflow = TextOverflow.Visible, - density = LocalDensity.current, - fontFamilyResolver = LocalFontFamilyResolver.current, - constraints = constraints, - layoutDirection = LocalLayoutDirection.current - ) - - return textLayoutResult.hasVisualOverflow -} - -@Preview( - showSystemUi = true, - showBackground = true -) -@Composable -private fun ComposableEllipsizeStartTextPreview() { - Column { - ComposableEllipsizeStartText("Small text") - ComposableEllipsizeStartText("abc".repeat(n = 50)) - } -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/bar/ComposableFileManagerTopBar.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/bar/ComposableFileManagerTopBar.kt deleted file mode 100644 index 6488b13bf4..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/bar/ComposableFileManagerTopBar.kt +++ /dev/null @@ -1,66 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.composable.bar - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.statusBarsPadding -import androidx.compose.material.Icon -import androidx.compose.material.IconButton -import androidx.compose.material.TopAppBar -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import com.flipperdevices.core.ui.theme.LocalPallet -import com.flipperdevices.newfilemanager.impl.R -import flipperapp.components.newfilemanager.impl.generated.resources.Res -import flipperapp.components.newfilemanager.impl.generated.resources.filemanager_create_action -import flipperapp.components.newfilemanager.impl.generated.resources.filemanager_upload_action -import org.jetbrains.compose.resources.stringResource -import com.flipperdevices.core.ui.res.R as DesignSystem - -@Composable -fun ComposableFileManagerTopBar( - path: String, - onClickUploadButton: () -> Unit, - onClickAddButton: () -> Unit, - modifier: Modifier = Modifier -) { - TopAppBar( - modifier = modifier - .background(LocalPallet.current.background) - .statusBarsPadding(), - backgroundColor = LocalPallet.current.background, - title = { - ComposableEllipsizeStartText( - text = path - ) - }, - actions = { - if (isAbleToSave(path)) { - Row { - IconButton(onClick = onClickAddButton) { - Icon( - painter = painterResource( - R.drawable.ic_plus - ), - contentDescription = stringResource( - Res.string.filemanager_create_action - ) - ) - } - IconButton(onClick = onClickUploadButton) { - Icon( - painter = painterResource( - DesignSystem.drawable.ic_upload - ), - contentDescription = stringResource( - Res.string.filemanager_upload_action - ) - ) - } - } - } - } - ) -} - -private fun isAbleToSave(path: String) = path.startsWith("/ext") diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/dialog/ComposableInputDialog.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/dialog/ComposableInputDialog.kt deleted file mode 100644 index 0705b9c3a9..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/dialog/ComposableInputDialog.kt +++ /dev/null @@ -1,102 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.composable.dialog - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.material.AlertDialog -import androidx.compose.material.Button -import androidx.compose.material.Text -import androidx.compose.material.TextField -import androidx.compose.material.TextFieldDefaults -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.flipperdevices.bridge.connection.feature.storage.api.utils.FlipperSymbolFilter -import com.flipperdevices.core.ui.theme.LocalPallet -import com.flipperdevices.core.ui.theme.LocalTypography -import flipperapp.components.newfilemanager.impl.generated.resources.Res -import flipperapp.components.newfilemanager.impl.generated.resources.add_dialog_error_empty -import flipperapp.components.newfilemanager.impl.generated.resources.add_dialog_error_too_long -import flipperapp.components.newfilemanager.impl.generated.resources.add_dialog_error_wrong_character -import flipperapp.components.newfilemanager.impl.generated.resources.share_dialog_btn_close -import flipperapp.components.newfilemanager.impl.generated.resources.share_dialog_btn_ok -import org.jetbrains.compose.resources.StringResource -import org.jetbrains.compose.resources.stringResource - -private const val FILE_MAX_LENGTH = 128 - -@Composable -@Suppress("LongMethod") -fun ComposableInputDialog( - title: StringResource, - onFinishEdit: (String?) -> Unit -) { - var text by remember { mutableStateOf("") } - var errorText by remember { mutableStateOf(null) } - - AlertDialog( - title = { - Text( - text = stringResource(title), - style = LocalTypography.current.titleM18 - ) - }, - text = { - Column { - TextField( - modifier = Modifier.fillMaxWidth(), - value = text, - onValueChange = { - errorText = null - text = FlipperSymbolFilter.filterUnacceptableSymbolInFileName(it) - }, - colors = TextFieldDefaults.textFieldColors( - cursorColor = LocalPallet.current.text100 - ) - ) - errorText?.let { - Text( - text = stringResource(it), - color = LocalPallet.current.warningColor - ) - } - } - }, - onDismissRequest = { onFinishEdit(null) }, - buttons = { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.End - ) { - Button( - modifier = Modifier.padding(all = 16.dp), - onClick = { onFinishEdit(null) } - ) { - Text(text = stringResource(Res.string.share_dialog_btn_close)) - } - Button( - modifier = Modifier.padding(all = 16.dp), - onClick = { - if (text.isBlank()) { - errorText = Res.string.add_dialog_error_empty - } else if (!FlipperSymbolFilter.isAcceptableString(text.replace(".", ""))) { - errorText = Res.string.add_dialog_error_wrong_character - } else if (text.length > FILE_MAX_LENGTH) { - errorText = Res.string.add_dialog_error_too_long - } else { - onFinishEdit(text) - } - } - ) { - Text(text = stringResource(Res.string.share_dialog_btn_ok)) - } - } - } - ) -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/dialog/ComposableProgressDialog.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/dialog/ComposableProgressDialog.kt deleted file mode 100644 index 57f1c2412c..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/dialog/ComposableProgressDialog.kt +++ /dev/null @@ -1,164 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.composable.dialog - -import android.text.format.Formatter -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.material.AlertDialog -import androidx.compose.material.Button -import androidx.compose.material.LinearProgressIndicator -import androidx.compose.material.ProgressIndicatorDefaults -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.unit.dp -import com.flipperdevices.core.ui.theme.LocalPallet -import com.flipperdevices.newfilemanager.impl.model.DownloadProgress -import com.flipperdevices.newfilemanager.impl.model.ShareState -import com.flipperdevices.newfilemanager.impl.model.SpeedState -import flipperapp.components.newfilemanager.impl.generated.resources.Res -import flipperapp.components.newfilemanager.impl.generated.resources.filemanager_error -import flipperapp.components.newfilemanager.impl.generated.resources.filemanager_error_title -import flipperapp.components.newfilemanager.impl.generated.resources.share_dialog_btn_close -import flipperapp.components.newfilemanager.impl.generated.resources.share_dialog_progress_infinite_text -import flipperapp.components.newfilemanager.impl.generated.resources.share_dialog_progress_text -import flipperapp.components.newfilemanager.impl.generated.resources.share_dialog_title -import org.jetbrains.compose.resources.stringResource - -@Composable -fun ComposableProgressDialog( - shareState: ShareState, - speedState: SpeedState, - onCancel: () -> Unit -) { - AlertDialog( - onDismissRequest = { }, - title = { - when (shareState) { - ShareState.Error -> stringResource(Res.string.filemanager_error_title) - is ShareState.Ready -> Text( - text = stringResource( - Res.string.share_dialog_title, - shareState.name - ) - ) - } - }, - buttons = { - Box( - modifier = Modifier.fillMaxWidth(), - contentAlignment = Alignment.BottomEnd - ) { - Button( - modifier = Modifier.padding(all = 16.dp), - onClick = onCancel - ) { - Text(text = stringResource(Res.string.share_dialog_btn_close)) - } - } - }, - text = { - when (shareState) { - ShareState.Error -> Text(stringResource(Res.string.filemanager_error)) - is ShareState.Ready -> when (shareState.downloadProgress) { - is DownloadProgress.Fixed -> ComposableFixedProgress( - shareState.downloadProgress, - speedState - ) - - is DownloadProgress.Infinite -> ComposableInfiniteProgress( - shareState.downloadProgress, - speedState - ) - } - } - } - ) -} - -@Composable -fun ComposableFixedProgress( - fixedProgress: DownloadProgress.Fixed, - speedState: SpeedState, - modifier: Modifier = Modifier -) { - val animatedProgress by animateFloatAsState( - targetValue = fixedProgress.toProgressFloat(), - animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec - ) - val downloadedSize = Formatter.formatFileSize( - LocalContext.current, - fixedProgress.progress - ) - val totalSize = Formatter.formatFileSize( - LocalContext.current, - fixedProgress.totalSize - ) - - Column(modifier) { - Text( - modifier = Modifier.padding(bottom = 8.dp), - text = stringResource( - Res.string.share_dialog_progress_text, - downloadedSize, - totalSize, - getSpeedText(speedState) - ) - ) - LinearProgressIndicator( - modifier = Modifier.fillMaxWidth(), - progress = animatedProgress, - color = LocalPallet.current.accent - ) - } -} - -@Composable -private fun getSpeedText(speedState: SpeedState): String { - return when (speedState) { - is SpeedState.Ready -> - "${ - Formatter.formatFileSize( - LocalContext.current, - speedState.receiveBytesInSec - ) - }/s download/${ - Formatter.formatFileSize( - LocalContext.current, - speedState.transmitBytesInSec - ) - }/s upload" - - SpeedState.Unknown -> "Unknown" - } -} - -@Composable -fun ComposableInfiniteProgress( - infiniteProgress: DownloadProgress.Infinite, - speedState: SpeedState, - modifier: Modifier = Modifier, -) { - val downloadedSize = Formatter.formatFileSize( - LocalContext.current, - infiniteProgress.progress - ) - Column(modifier) { - Text( - modifier = Modifier.padding(bottom = 8.dp), - text = stringResource( - Res.string.share_dialog_progress_infinite_text, - downloadedSize, - getSpeedText(speedState) - ) - ) - LinearProgressIndicator( - modifier = Modifier.fillMaxWidth() - ) - } -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/dialog/ComposableSelectDialog.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/dialog/ComposableSelectDialog.kt deleted file mode 100644 index bcdf46f201..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/dialog/ComposableSelectDialog.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.composable.dialog - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.material.Divider -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.Dialog -import com.flipperdevices.core.ui.ktx.clickableRipple -import com.flipperdevices.core.ui.theme.LocalPallet -import com.flipperdevices.core.ui.theme.LocalTypography -import org.jetbrains.compose.resources.StringResource -import org.jetbrains.compose.resources.stringResource - -@Composable -fun ComposableSelectDialog( - options: Array, - onSelect: (StringResource?) -> Unit, - modifier: Modifier = Modifier -) { - Dialog(onDismissRequest = { onSelect(null) }) { - Column(modifier = modifier.background(LocalPallet.current.backgroundDialog)) { - options.forEachIndexed { index, elementText -> - ComposableDialogOption( - modifier = Modifier - .padding(16.dp) - .fillMaxWidth(), - text = elementText, - onClick = { - onSelect(elementText) - } - ) - if (index != options.lastIndex) { - Divider( - modifier = Modifier.fillMaxWidth(), - color = LocalPallet.current.divider12 - ) - } - } - } - } -} - -@Composable -private fun ComposableDialogOption( - text: StringResource, - onClick: () -> Unit, - modifier: Modifier = Modifier, -) { - Text( - modifier = modifier - .clickableRipple(onClick = onClick) - .then(modifier), - text = stringResource(text), - style = LocalTypography.current.titleM18 - ) -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/list/ComposableFileItem.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/list/ComposableFileItem.kt deleted file mode 100644 index d5161573a4..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/list/ComposableFileItem.kt +++ /dev/null @@ -1,103 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.composable.list - -import android.text.format.Formatter -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.unit.dp -import com.flipperdevices.bridge.dao.api.model.FlipperKeyType -import com.flipperdevices.bridge.dao.api.model.iconId -import com.flipperdevices.core.ui.ktx.clickableRipple -import com.flipperdevices.newfilemanager.impl.R -import com.flipperdevices.newfilemanager.impl.model.FileItem -import flipperapp.components.newfilemanager.impl.generated.resources.Res -import flipperapp.components.newfilemanager.impl.generated.resources.filemanager_file_pic_desc -import flipperapp.components.newfilemanager.impl.generated.resources.filemanager_folder_pic_desc -import org.jetbrains.compose.resources.stringResource - -@Composable -fun ComposableFileItem( - fileItem: FileItem, - onFileClick: (FileItem) -> Unit, - modifier: Modifier = Modifier -) { - Row( - modifier = modifier - .fillMaxWidth() - .clickableRipple { onFileClick(fileItem) }, - verticalAlignment = Alignment.CenterVertically - ) { - ComposableFileImage( - modifier = Modifier.padding(all = 8.dp), - fileItem = fileItem - ) - Column(modifier = Modifier.padding(vertical = 8.dp)) { - Text( - modifier = Modifier.padding(end = 8.dp), - style = MaterialTheme.typography.h5, - text = fileItem.fileName - ) - if (!fileItem.isDirectory) { - val fileSize = Formatter.formatFileSize(LocalContext.current, fileItem.size) - Text( - style = MaterialTheme.typography.h5, - text = fileSize - ) - } - } - } -} - -@Composable -fun ComposableFileImage( - fileItem: FileItem, - modifier: Modifier = Modifier -) { - if (fileItem.isDirectory) { - Image( - modifier = modifier, - painter = painterResource(R.drawable.ic_folder), - contentDescription = stringResource( - Res.string.filemanager_folder_pic_desc - ) - ) - } else { - Box( - modifier = modifier, - contentAlignment = Alignment.Center - ) { - Image( - modifier = Modifier.size(size = 48.dp), - painter = painterResource(R.drawable.ic_file), - contentDescription = stringResource( - Res.string.filemanager_file_pic_desc - ) - ) - val fileIcon = remember(fileItem) { - FlipperKeyType.getByExtension( - fileItem.fileName.substringAfterLast(".") - ) - } - - if (fileIcon != null) { - Image( - modifier = Modifier.size(size = 24.dp), - painter = painterResource(fileIcon.iconId), - contentDescription = fileIcon.humanReadableName - ) - } - } - } -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/list/ComposableFileManagerContent.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/list/ComposableFileManagerContent.kt deleted file mode 100644 index 61fcd1a94d..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/composable/list/ComposableFileManagerContent.kt +++ /dev/null @@ -1,71 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.composable.list - -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material.CircularProgressIndicator -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import com.flipperdevices.newfilemanager.impl.model.FileItem -import com.flipperdevices.newfilemanager.impl.model.FileManagerState -import flipperapp.components.newfilemanager.impl.generated.resources.Res -import flipperapp.components.newfilemanager.impl.generated.resources.filemanager_empty_folder -import flipperapp.components.newfilemanager.impl.generated.resources.filemanager_error -import kotlinx.collections.immutable.persistentListOf -import org.jetbrains.compose.resources.stringResource - -@Composable -fun ComposableFileManagerContent( - fileManagerState: FileManagerState, - onFileClick: (FileItem) -> Unit, - modifier: Modifier = Modifier, -) { - Box( - modifier = modifier.fillMaxSize(), - contentAlignment = Alignment.Center - ) { - when (fileManagerState) { - is FileManagerState.Error -> Text(stringResource(Res.string.filemanager_error)) - is FileManagerState.Ready -> when { - fileManagerState.filesInDirectory.isNotEmpty() -> - LazyColumn( - modifier = Modifier.fillMaxSize() - ) { - items(items = fileManagerState.filesInDirectory.toList()) { file -> - ComposableFileItem(file, onFileClick) - } - } - - fileManagerState.inProgress -> - CircularProgressIndicator(modifier = Modifier.size(size = 48.dp)) - - else -> Text(text = stringResource(Res.string.filemanager_empty_folder)) - } - } - } -} - -@Preview( - showBackground = true, - showSystemUi = true -) -@Composable -private fun ComposableFileManagerPreview() { - ComposableFileManagerContent( - fileManagerState = FileManagerState.Ready( - "/", - persistentListOf( - FileItem.DUMMY_FOLDER, - FileItem.DUMMY_FILE - ), - inProgress = true - ), - onFileClick = {} - ) -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/CreateFileManagerAction.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/CreateFileManagerAction.kt deleted file mode 100644 index 616e542c97..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/CreateFileManagerAction.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.model - -enum class CreateFileManagerAction { - FILE, - FOLDER -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/DownloadProgress.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/DownloadProgress.kt deleted file mode 100644 index 5ba9e93bb5..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/DownloadProgress.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.model - -sealed class DownloadProgress { - data class Fixed( - val progressInternal: Long = 0, - val totalSize: Long - ) : DownloadProgress() { - fun toProgressFloat() = if (totalSize != 0L) { - progress.toFloat() / totalSize.toFloat() - } else { - 0f - } - } - - data class Infinite( - val progressInternal: Long = 0 - ) : DownloadProgress() - - val progress: Long - get() = when (this) { - is Fixed -> progressInternal - is Infinite -> progressInternal - } -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/EditorState.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/EditorState.kt deleted file mode 100644 index 05f9d58614..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/EditorState.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.model - -sealed class EditorState { - data class Loading( - val progress: DownloadProgress - ) : EditorState() - - data class Loaded( - val path: String, - val content: String, - val tooLarge: Boolean - ) : EditorState() - - data class Saving( - val progress: DownloadProgress - ) : EditorState() - - data object Saved : EditorState() - - data object Error : EditorState() -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/FileItem.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/FileItem.kt deleted file mode 100644 index 05b1d5da21..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/FileItem.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.model - -import com.flipperdevices.bridge.connection.feature.storage.api.model.FileType -import com.flipperdevices.bridge.connection.feature.storage.api.model.ListingItem -import okio.Path.Companion.toPath - -data class FileItem( - val fileName: String, - val isDirectory: Boolean, - val path: String, - val size: Long -) { - constructor( - directory: String, - listingItem: ListingItem - ) : this( - fileName = listingItem.fileName, - isDirectory = listingItem.fileType == FileType.DIR, - path = directory.toPath().resolve(listingItem.fileName).toString(), - size = listingItem.size - ) - - companion object { - val DUMMY_FOLDER = FileItem("Test Directory", true, "/ext/Test Directory", 0) - val DUMMY_FILE = FileItem("testfile.ibtn", false, "/ext/Test Directory/testfile.ibtn", 1000) - } -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/FileManagerNavigationConfig.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/FileManagerNavigationConfig.kt deleted file mode 100644 index c4bef31860..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/FileManagerNavigationConfig.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.model - -import com.flipperdevices.deeplink.model.DeeplinkContent -import kotlinx.serialization.Serializable - -@Serializable -sealed class FileManagerNavigationConfig { - @Serializable - data class Screen(val path: String) : FileManagerNavigationConfig() - - @Serializable - data class Uploading( - val path: String, - val deeplinkContent: DeeplinkContent - ) : FileManagerNavigationConfig() - - @Serializable - data class Editing(val shareFile: ShareFile) : FileManagerNavigationConfig() - - @Serializable - data class Download( - val path: String, - val shareFile: ShareFile - ) : FileManagerNavigationConfig() -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/FileManagerState.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/FileManagerState.kt deleted file mode 100644 index e6f713c771..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/FileManagerState.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.model - -import kotlinx.collections.immutable.ImmutableList -import kotlinx.collections.immutable.persistentListOf - -sealed interface FileManagerState { - val currentPath: String - - data class Ready( - override val currentPath: String, - val filesInDirectory: ImmutableList = persistentListOf(), - val inProgress: Boolean - ) : FileManagerState - - data class Error( - override val currentPath: String - ) : FileManagerState -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/ShareFile.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/ShareFile.kt deleted file mode 100644 index 4cef50f836..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/ShareFile.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.model - -import kotlinx.serialization.Serializable - -@Serializable -data class ShareFile( - val name: String, - val flipperFilePath: String, - val size: Long -) { - constructor(fileItem: FileItem) : this(fileItem.fileName, fileItem.path, fileItem.size) -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/ShareState.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/ShareState.kt deleted file mode 100644 index b1d032aeb7..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/ShareState.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.model - -sealed interface ShareState { - data class Ready( - val name: String, - val downloadProgress: DownloadProgress = DownloadProgress.Infinite(), - val processCompleted: Boolean = false - ) : ShareState - - data object Error : ShareState -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/SpeedState.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/SpeedState.kt deleted file mode 100644 index 87eb39affd..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/model/SpeedState.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.model - -import com.flipperdevices.bridge.connection.transport.common.api.serial.FlipperSerialSpeed - -sealed interface SpeedState { - data class Ready( - val receiveBytesInSec: Long = 0L, - val transmitBytesInSec: Long = 0L - ) : SpeedState { - constructor(serialSpeed: FlipperSerialSpeed) : this( - serialSpeed.receiveBytesInSec, - serialSpeed.transmitBytesInSec - ) - } - - data object Unknown : SpeedState -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/viewmodels/CommonShareViewModel.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/viewmodels/CommonShareViewModel.kt deleted file mode 100644 index 1179c58dcf..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/viewmodels/CommonShareViewModel.kt +++ /dev/null @@ -1,73 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.viewmodels - -import com.flipperdevices.bridge.connection.feature.provider.api.FFeatureProvider -import com.flipperdevices.bridge.connection.feature.provider.api.FFeatureStatus -import com.flipperdevices.bridge.connection.feature.provider.api.get -import com.flipperdevices.bridge.connection.feature.serialspeed.api.FSpeedFeatureApi -import com.flipperdevices.bridge.connection.feature.storage.api.FStorageFeatureApi -import com.flipperdevices.core.ui.lifecycle.DecomposeViewModel -import com.flipperdevices.newfilemanager.impl.model.DownloadProgress -import com.flipperdevices.newfilemanager.impl.model.ShareState -import com.flipperdevices.newfilemanager.impl.model.SpeedState -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.launch - -abstract class CommonShareViewModel( - private val featureProvider: FFeatureProvider, - protected val fileName: String, - private val defaultProgress: DownloadProgress -) : DecomposeViewModel() { - private val speedState = MutableStateFlow(SpeedState.Unknown) - protected val shareStateFlow = MutableStateFlow( - ShareState.Ready( - fileName, - defaultProgress - ) - ) - - fun getSpeedState() = speedState.asStateFlow() - fun getShareState() = shareStateFlow.asStateFlow() - - init { - viewModelScope.launch { - featureProvider.get() - .collectLatest { storageFeatureStatus -> - when (storageFeatureStatus) { - FFeatureStatus.NotFound, - FFeatureStatus.Unsupported -> shareStateFlow.emit(ShareState.Error) - - FFeatureStatus.Retrieving -> shareStateFlow.emit( - ShareState.Ready( - fileName, - defaultProgress - ) - ) - - is FFeatureStatus.Supported -> start(storageFeatureStatus.featureApi) - } - } - } - viewModelScope.launch { - featureProvider.get() - .collectLatest { speedFeatureStatus -> - when (speedFeatureStatus) { - FFeatureStatus.NotFound, - FFeatureStatus.Retrieving, - FFeatureStatus.Unsupported -> speedState.emit(SpeedState.Unknown) - - is FFeatureStatus.Supported -> - speedFeatureStatus - .featureApi - .getSpeed() - .collectLatest { - speedState.emit(SpeedState.Ready(it)) - } - } - } - } - } - - protected abstract suspend fun start(storageFeatureApi: FStorageFeatureApi) -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/viewmodels/EditorViewModel.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/viewmodels/EditorViewModel.kt deleted file mode 100644 index e706c4e4cf..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/viewmodels/EditorViewModel.kt +++ /dev/null @@ -1,160 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.viewmodels - -import com.flipperdevices.bridge.connection.feature.provider.api.FFeatureProvider -import com.flipperdevices.bridge.connection.feature.provider.api.FFeatureStatus -import com.flipperdevices.bridge.connection.feature.provider.api.get -import com.flipperdevices.bridge.connection.feature.provider.api.getSync -import com.flipperdevices.bridge.connection.feature.storage.api.FStorageFeatureApi -import com.flipperdevices.bridge.connection.feature.storage.api.fm.FFileUploadApi -import com.flipperdevices.core.FlipperStorageProvider -import com.flipperdevices.core.ktx.jre.limit -import com.flipperdevices.core.ktx.jre.withLock -import com.flipperdevices.core.log.LogTagProvider -import com.flipperdevices.core.log.error -import com.flipperdevices.core.ui.lifecycle.DecomposeViewModel -import com.flipperdevices.newfilemanager.impl.model.DownloadProgress -import com.flipperdevices.newfilemanager.impl.model.EditorState -import com.flipperdevices.newfilemanager.impl.model.ShareFile -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch -import kotlinx.coroutines.sync.Mutex -import okio.buffer -import okio.use - -private const val LIMITED_SIZE_BYTES = 1024L * 1024L // 1MB - -class EditorViewModel @AssistedInject constructor( - @Assisted private val shareFile: ShareFile, - private val featureProvider: FFeatureProvider, - private val storageProvider: FlipperStorageProvider -) : DecomposeViewModel(), LogTagProvider { - override val TAG = "EditorViewModel" - - private val editorStateFlow = MutableStateFlow( - EditorState.Loading( - progress = DownloadProgress.Fixed( - totalSize = shareFile.size - ) - ) - ) - private val mutex = Mutex() - private val editorFile by lazy { - storageProvider.getTemporaryFile() - } - - init { - viewModelScope.launch { - featureProvider.get() - .collectLatest { - onFeatureStateChanged(it) - } - } - } - - fun getEditorState(): StateFlow = editorStateFlow - - private suspend fun onFeatureStateChanged( - featureStatus: FFeatureStatus - ) = withLock(mutex, "feature") { - when (featureStatus) { - FFeatureStatus.NotFound, - FFeatureStatus.Unsupported -> editorStateFlow.emit(EditorState.Error) - - FFeatureStatus.Retrieving -> editorStateFlow.emit(EditorState.Loading(DownloadProgress.Infinite())) - is FFeatureStatus.Supported -> loadFileSafe(featureStatus.featureApi) - } - } - - fun onSaveFile(text: String) { - val textBytes = text.toByteArray() - editorStateFlow.update { - EditorState.Saving( - DownloadProgress.Fixed( - totalSize = textBytes.size.toLong() - ) - ) - } - viewModelScope.launch { - val storageApi = featureProvider.getSync() - if (storageApi == null) { - editorStateFlow.emit(EditorState.Error) - return@launch - } - uploadFileSafe(storageApi.uploadApi(), textBytes) - } - } - - private suspend fun uploadFileSafe( - uploadApi: FFileUploadApi, - textBytes: ByteArray - ) = withLock(mutex, "save") { - storageProvider.fileSystem.write(editorFile) { - write(textBytes) - } - - uploadApi.upload( - shareFile.flipperFilePath, - editorFile - ) { current, max -> - editorStateFlow.emit(EditorState.Saving(DownloadProgress.Fixed(current, max))) - }.onFailure { exception -> - error(exception) { "Failed saved $shareFile" } - editorStateFlow.emit(EditorState.Error) - }.onSuccess { - editorStateFlow.emit(EditorState.Saved) - } - } - - private suspend fun loadFileSafe(storageFeatureApi: FStorageFeatureApi) { - editorStateFlow.emit(EditorState.Loading(DownloadProgress.Infinite())) - storageFeatureApi.downloadApi().download( - shareFile.flipperFilePath, - editorFile - ) { current, max -> - editorStateFlow.emit(EditorState.Loading(DownloadProgress.Fixed(current, max))) - }.onFailure { exception -> - error(exception) { "Failed download $shareFile" } - editorStateFlow.emit(EditorState.Error) - }.onSuccess { - val content = storageProvider - .fileSystem - .source(editorFile) - .limit(LIMITED_SIZE_BYTES) - .buffer() - .use { - it.readUtf8() - } - val metaSize = storageProvider.fileSystem.metadataOrNull(editorFile)?.size - val isTooLarge = if (metaSize != null) { - metaSize > LIMITED_SIZE_BYTES - } else { - false - } - editorStateFlow.emit( - EditorState.Loaded( - shareFile.flipperFilePath, - content = content, - tooLarge = isTooLarge - ) - ) - } - } - - override fun onDestroy() { - super.onDestroy() - storageProvider.fileSystem.delete(editorFile) - } - - @AssistedFactory - fun interface Factory { - operator fun invoke( - shareFile: ShareFile - ): EditorViewModel - } -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/viewmodels/FileManagerViewModel.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/viewmodels/FileManagerViewModel.kt deleted file mode 100644 index 69f7b19343..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/viewmodels/FileManagerViewModel.kt +++ /dev/null @@ -1,188 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.viewmodels - -import com.flipperdevices.bridge.connection.feature.provider.api.FFeatureProvider -import com.flipperdevices.bridge.connection.feature.provider.api.FFeatureStatus -import com.flipperdevices.bridge.connection.feature.provider.api.get -import com.flipperdevices.bridge.connection.feature.provider.api.getSync -import com.flipperdevices.bridge.connection.feature.storage.api.FStorageFeatureApi -import com.flipperdevices.bridge.connection.feature.storage.api.fm.FListingStorageApi -import com.flipperdevices.bridge.connection.feature.storage.api.model.StorageRequestPriority -import com.flipperdevices.core.ktx.jre.launchWithLock -import com.flipperdevices.core.ktx.jre.toThrowableFlow -import com.flipperdevices.core.ktx.jre.withLock -import com.flipperdevices.core.log.LogTagProvider -import com.flipperdevices.core.log.error -import com.flipperdevices.core.ui.lifecycle.DecomposeViewModel -import com.flipperdevices.newfilemanager.impl.model.CreateFileManagerAction -import com.flipperdevices.newfilemanager.impl.model.FileItem -import com.flipperdevices.newfilemanager.impl.model.FileManagerState -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject -import kotlinx.collections.immutable.toPersistentList -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.collectLatest -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch -import kotlinx.coroutines.sync.Mutex -import okio.ByteString -import okio.buffer -import kotlin.io.path.Path - -class FileManagerViewModel @AssistedInject constructor( - private val featureProvider: FFeatureProvider, - @Assisted private val directory: String -) : DecomposeViewModel(), LogTagProvider { - override val TAG = "FileManagerViewModel" - - private val mutex = Mutex() - private val fileManagerStateFlow = MutableStateFlow( - FileManagerState.Ready( - currentPath = directory, - inProgress = true - ) - ) - - init { - viewModelScope.launch { - featureProvider.get().collectLatest { - invalidate(it) - } - } - } - - fun getFileManagerState(): StateFlow = fileManagerStateFlow - - fun onCreateAction( - createFileManagerAction: CreateFileManagerAction, - name: String - ) { - fileManagerStateFlow.update { - FileManagerState.Ready( - currentPath = directory, - inProgress = true - ) - } - - launchWithLock(mutex, viewModelScope, "create") { - fileManagerStateFlow.emit( - FileManagerState.Ready( - currentPath = directory, - inProgress = true - ) - ) - val storageApi = featureProvider.getSync() - if (storageApi == null) { - fileManagerStateFlow.emit(FileManagerState.Error(directory)) - return@launchWithLock - } - val uploadApi = storageApi.uploadApi() - val pathOnFlipper = Path(directory).resolve(name).toString() - when (createFileManagerAction) { - CreateFileManagerAction.FILE -> runCatching { - uploadApi.sink( - pathOnFlipper = pathOnFlipper, - priority = StorageRequestPriority.FOREGROUND - ).buffer().use { - it.write(ByteString.of()) - } - } - - CreateFileManagerAction.FOLDER -> uploadApi.mkdir( - pathOnFlipper - ) - }.onFailure { - error(it) { "Fail create $name $createFileManagerAction" } - fileManagerStateFlow.emit(FileManagerState.Error(directory)) - }.onSuccess { - listFiles(storageApi.listingApi()) - } - } - } - - fun onDeleteAction(fileItem: FileItem) { - fileManagerStateFlow.value = FileManagerState.Ready( - currentPath = directory, inProgress = true - ) - - launchWithLock(mutex, viewModelScope, "delete") { - fileManagerStateFlow.emit( - FileManagerState.Ready( - currentPath = directory, - inProgress = true - ) - ) - val storageApi = featureProvider.getSync() - if (storageApi == null) { - fileManagerStateFlow.emit(FileManagerState.Error(directory)) - return@launchWithLock - } - storageApi.deleteApi().delete(fileItem.path, recursive = true) - .onSuccess { listFiles(storageApi.listingApi()) } - .onFailure { fileManagerStateFlow.emit(FileManagerState.Error(directory)) } - } - } - - private suspend fun invalidate( - featureStatus: FFeatureStatus - ) = withLock(mutex, "invalidate") { - when (featureStatus) { - FFeatureStatus.NotFound, FFeatureStatus.Unsupported -> fileManagerStateFlow.emit( - FileManagerState.Error(directory) - ) - - FFeatureStatus.Retrieving -> fileManagerStateFlow.emit( - FileManagerState.Ready( - currentPath = directory, - inProgress = true - ) - ) - - is FFeatureStatus.Supported -> listFiles(featureStatus.featureApi.listingApi()) - } - } - - private suspend fun listFiles( - listingApi: FListingStorageApi - ) { - listingApi.lsFlow(directory).toThrowableFlow().catch { - fileManagerStateFlow.emit(FileManagerState.Error(directory)) - }.collect { listingItems -> - fileManagerStateFlow.update { oldState -> - if (oldState is FileManagerState.Ready) { - oldState.copy( - filesInDirectory = oldState.filesInDirectory.plus( - listingItems.map { item -> - FileItem( - directory, - item - ) - } - ).toPersistentList() - ) - } else { - oldState - } - } - } - - fileManagerStateFlow.update { oldState -> - if (oldState is FileManagerState.Ready) { - oldState.copy( - inProgress = false - ) - } else { - oldState - } - } - } - - @AssistedFactory - fun interface Factory { - operator fun invoke( - directory: String - ): FileManagerViewModel - } -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/viewmodels/ReceiveViewModel.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/viewmodels/ReceiveViewModel.kt deleted file mode 100644 index 9a0ad4062d..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/viewmodels/ReceiveViewModel.kt +++ /dev/null @@ -1,92 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.viewmodels - -import android.content.Context -import com.flipperdevices.bridge.connection.feature.provider.api.FFeatureProvider -import com.flipperdevices.bridge.connection.feature.storage.api.FStorageFeatureApi -import com.flipperdevices.core.ktx.jre.FlipperDispatchers -import com.flipperdevices.core.log.LogTagProvider -import com.flipperdevices.core.log.error -import com.flipperdevices.core.log.info -import com.flipperdevices.core.progress.copyWithProgress -import com.flipperdevices.deeplink.model.DeeplinkContent -import com.flipperdevices.deeplink.model.cleanUp -import com.flipperdevices.deeplink.model.openStream -import com.flipperdevices.newfilemanager.impl.model.DownloadProgress -import com.flipperdevices.newfilemanager.impl.model.ShareState -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.withContext -import okio.source -import okio.use -import kotlin.io.path.Path - -class ReceiveViewModel @AssistedInject constructor( - @Assisted private val path: String, - @Assisted private val deeplinkContent: DeeplinkContent, - context: Context, - private val featureProvider: FFeatureProvider, -) : CommonShareViewModel( - featureProvider = featureProvider, - fileName = deeplinkContent.filename() ?: "Unknown", - defaultProgress = deeplinkContent.length()?.let { - DownloadProgress.Fixed(totalSize = it) - } ?: DownloadProgress.Infinite() -), - LogTagProvider { - override val TAG = "ReceiveViewModel" - - private val contentResolver = context.contentResolver - - override suspend fun start( - storageFeatureApi: FStorageFeatureApi - ): Unit = withContext(FlipperDispatchers.workStealingDispatcher) { - info { "Upload file $deeplinkContent in $path start" } - val fileStream = deeplinkContent.openStream(contentResolver) ?: return@withContext - runCatching { - fileStream.use { outputStream -> - storageFeatureApi - .uploadApi() - .sink(Path(path).resolve(fileName).toString()) - .use { sink -> - outputStream.source().copyWithProgress( - sink = sink, - sourceLength = { - deeplinkContent.length() - }, - progressListener = { current, max -> - shareStateFlow.emit( - ShareState.Ready( - name = fileName, - downloadProgress = DownloadProgress.Fixed(current, max) - ) - ) - } - ) - } - } - }.onSuccess { - shareStateFlow.update { - if (it is ShareState.Ready) { - it.copy(processCompleted = true) - } else { - it - } - } - }.onFailure { exception -> - error(exception) { "Fail upload file" } - shareStateFlow.emit(ShareState.Error) - } - - deeplinkContent.cleanUp(contentResolver) - } - - @AssistedFactory - fun interface Factory { - operator fun invoke( - deeplinkContent: DeeplinkContent, - path: String - ): ReceiveViewModel - } -} diff --git a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/viewmodels/ShareViewModel.kt b/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/viewmodels/ShareViewModel.kt deleted file mode 100644 index 130c465923..0000000000 --- a/components/newfilemanager/impl/src/androidMain/kotlin/com/flipperdevices/newfilemanager/impl/viewmodels/ShareViewModel.kt +++ /dev/null @@ -1,87 +0,0 @@ -package com.flipperdevices.newfilemanager.impl.viewmodels - -import android.app.Application -import com.flipperdevices.bridge.connection.feature.provider.api.FFeatureProvider -import com.flipperdevices.bridge.connection.feature.storage.api.FStorageFeatureApi -import com.flipperdevices.core.ktx.jre.FlipperDispatchers -import com.flipperdevices.core.ktx.jre.createClearNewFileWithMkDirs -import com.flipperdevices.core.log.LogTagProvider -import com.flipperdevices.core.log.error -import com.flipperdevices.core.log.info -import com.flipperdevices.core.share.SharableFile -import com.flipperdevices.core.share.ShareHelper -import com.flipperdevices.newfilemanager.impl.R -import com.flipperdevices.newfilemanager.impl.model.DownloadProgress -import com.flipperdevices.newfilemanager.impl.model.ShareFile -import com.flipperdevices.newfilemanager.impl.model.ShareState -import dagger.assisted.Assisted -import dagger.assisted.AssistedFactory -import dagger.assisted.AssistedInject -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.withContext -import okio.Path.Companion.toOkioPath - -class ShareViewModel @AssistedInject constructor( - private val featureProvider: FFeatureProvider, - @Assisted private val shareFile: ShareFile, - private val application: Application -) : CommonShareViewModel( - featureProvider = featureProvider, - fileName = shareFile.name, - defaultProgress = DownloadProgress.Fixed( - totalSize = shareFile.size - ) -), - LogTagProvider { - override val TAG = "ShareViewModel" - private val fileInSharedDir by lazy { - SharableFile(application, shareFile.name).apply { - createClearNewFileWithMkDirs() - } - } - - override suspend fun start( - storageFeatureApi: FStorageFeatureApi - ): Unit = withContext(FlipperDispatchers.workStealingDispatcher) { - info { "Start download file $shareFile" } - storageFeatureApi.downloadApi().download( - shareFile.flipperFilePath, - fileInSharedDir.toOkioPath() - ) { current, max -> - shareStateFlow.emit( - ShareState.Ready( - name = fileName, - downloadProgress = DownloadProgress.Fixed(current, max) - ) - ) - }.onFailure { exception -> - error(exception) { "Can't download $shareFile" } - shareStateFlow.emit(ShareState.Error) - }.onSuccess { - onCompleteDownload() - } - } - - private suspend fun onCompleteDownload() = withContext(Dispatchers.Main) { - ShareHelper.shareFile( - context = application, - file = fileInSharedDir, - resId = R.string.share_picker_title - ) - shareStateFlow.update { - if (it is ShareState.Ready) { - it.copy(processCompleted = true) - } else { - it - } - } - } - - @AssistedFactory - fun interface Factory { - operator fun invoke( - shareFile: ShareFile - ): ShareViewModel - } -} diff --git a/components/newfilemanager/impl/src/androidMain/res/drawable/ic_file.xml b/components/newfilemanager/impl/src/androidMain/res/drawable/ic_file.xml deleted file mode 100644 index cf197c58ab..0000000000 --- a/components/newfilemanager/impl/src/androidMain/res/drawable/ic_file.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/components/newfilemanager/impl/src/androidMain/res/drawable/ic_folder.xml b/components/newfilemanager/impl/src/androidMain/res/drawable/ic_folder.xml deleted file mode 100644 index 177741e3bb..0000000000 --- a/components/newfilemanager/impl/src/androidMain/res/drawable/ic_folder.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/components/newfilemanager/impl/src/androidMain/res/drawable/ic_ok.xml b/components/newfilemanager/impl/src/androidMain/res/drawable/ic_ok.xml deleted file mode 100644 index 6f91f7fd34..0000000000 --- a/components/newfilemanager/impl/src/androidMain/res/drawable/ic_ok.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/components/newfilemanager/impl/src/androidMain/res/drawable/ic_plus.xml b/components/newfilemanager/impl/src/androidMain/res/drawable/ic_plus.xml deleted file mode 100644 index 4a091abb19..0000000000 --- a/components/newfilemanager/impl/src/androidMain/res/drawable/ic_plus.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/components/nfc/mfkey32/screen/build.gradle.kts b/components/nfc/mfkey32/screen/build.gradle.kts index 2a6b5a4475..0675df58cb 100644 --- a/components/nfc/mfkey32/screen/build.gradle.kts +++ b/components/nfc/mfkey32/screen/build.gradle.kts @@ -42,6 +42,5 @@ dependencies { implementation(libs.kotlin.immutable.collections) - implementation(libs.lifecycle.viewmodel.ktx) implementation(libs.lifecycle.compose) } diff --git a/components/screenstreaming/impl/build.gradle.kts b/components/screenstreaming/impl/build.gradle.kts index 81e2457d4b..0cb7021135 100644 --- a/components/screenstreaming/impl/build.gradle.kts +++ b/components/screenstreaming/impl/build.gradle.kts @@ -44,6 +44,6 @@ dependencies { implementation(libs.kotlin.coroutines) implementation(libs.lifecycle.runtime.ktx) - implementation(libs.lifecycle.viewmodel.ktx) + implementation(libs.lifecycle.compose) } diff --git a/components/settings/impl/build.gradle.kts b/components/settings/impl/build.gradle.kts index 24bf7c5a19..fd69ae67ca 100644 --- a/components/settings/impl/build.gradle.kts +++ b/components/settings/impl/build.gradle.kts @@ -52,7 +52,6 @@ dependencies { implementation(libs.bundles.decompose) implementation(libs.lifecycle.compose) - implementation(libs.lifecycle.viewmodel.ktx) implementation(libs.kotlin.serialization.json) implementation(libs.kotlin.immutable.collections) diff --git a/components/share/receive/build.gradle.kts b/components/share/receive/build.gradle.kts index 2866dbf002..ac93e3c593 100644 --- a/components/share/receive/build.gradle.kts +++ b/components/share/receive/build.gradle.kts @@ -43,7 +43,7 @@ dependencies { implementation(libs.kotlin.immutable.collections) implementation(libs.kotlin.serialization.json) implementation(libs.lifecycle.runtime.ktx) - implementation(libs.lifecycle.viewmodel.ktx) + implementation(libs.lifecycle.compose) // Compose diff --git a/components/share/uploader/build.gradle.kts b/components/share/uploader/build.gradle.kts index fffedc749e..63e453f1ce 100644 --- a/components/share/uploader/build.gradle.kts +++ b/components/share/uploader/build.gradle.kts @@ -26,7 +26,7 @@ dependencies { implementation(libs.kotlin.coroutines) implementation(libs.lifecycle.runtime.ktx) - implementation(libs.lifecycle.viewmodel.ktx) + implementation(libs.lifecycle.compose) implementation(libs.kotlin.serialization.json) diff --git a/components/updater/card/build.gradle.kts b/components/updater/card/build.gradle.kts index 90ed45f416..b7e4f0421b 100644 --- a/components/updater/card/build.gradle.kts +++ b/components/updater/card/build.gradle.kts @@ -27,7 +27,6 @@ dependencies { implementation(projects.components.analytics.metric.api) - implementation(libs.lifecycle.viewmodel.ktx) implementation(libs.lifecycle.runtime.ktx) implementation(libs.lifecycle.compose) diff --git a/components/widget/screen/build.gradle.kts b/components/widget/screen/build.gradle.kts index bfcd1e1e17..ca6590de94 100644 --- a/components/widget/screen/build.gradle.kts +++ b/components/widget/screen/build.gradle.kts @@ -38,8 +38,6 @@ dependencies { implementation(libs.compose.swipetorefresh) implementation(libs.bundles.decompose) - implementation(libs.lifecycle.viewmodel.ktx) - implementation(libs.kotlin.immutable.collections) implementation(libs.kotlin.serialization.json) } diff --git a/config/geminio/modules_templates/Navigaton Feature Module/root/impl.build.gradle.kts.ftl b/config/geminio/modules_templates/Navigaton Feature Module/root/impl.build.gradle.kts.ftl index bece84dee8..e11ce797b0 100644 --- a/config/geminio/modules_templates/Navigaton Feature Module/root/impl.build.gradle.kts.ftl +++ b/config/geminio/modules_templates/Navigaton Feature Module/root/impl.build.gradle.kts.ftl @@ -20,7 +20,7 @@ dependencies { // ViewModel implementation(libs.lifecycle.compose) - implementation(libs.lifecycle.viewmodel.ktx) + <#if needSerialization> // Serialization diff --git a/config/geminio/modules_templates/Simple Api Impl Module/root/impl.build.gradle.kts.ftl b/config/geminio/modules_templates/Simple Api Impl Module/root/impl.build.gradle.kts.ftl index f83b40bc48..d0d5468345 100644 --- a/config/geminio/modules_templates/Simple Api Impl Module/root/impl.build.gradle.kts.ftl +++ b/config/geminio/modules_templates/Simple Api Impl Module/root/impl.build.gradle.kts.ftl @@ -28,7 +28,7 @@ dependencies { <#if needViewModel> // ViewModel implementation(libs.lifecycle.compose) - implementation(libs.lifecycle.viewmodel.ktx) + <#if needTest> diff --git a/config/geminio/modules_templates/Simple Module/root/build.gradle.kts.ftl b/config/geminio/modules_templates/Simple Module/root/build.gradle.kts.ftl index 8d2e876885..7f8fcfed41 100644 --- a/config/geminio/modules_templates/Simple Module/root/build.gradle.kts.ftl +++ b/config/geminio/modules_templates/Simple Module/root/build.gradle.kts.ftl @@ -30,7 +30,7 @@ dependencies { <#if needViewModel> // ViewModel implementation(libs.lifecycle.compose) - implementation(libs.lifecycle.viewmodel.ktx) + <#if needTest> diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index dc5220aad0..62470bf02e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ kotlin-general = "2.1.0" # https://kotlinlang.org/docs/releases.html#release-details kotlin-immutable-collections = "0.3.8" # https://github.com/Kotlin/kotlinx.collections.immutable/releases kotlin-datetime = "0.6.1" # https://github.com/Kotlin/kotlinx-datetime/releases -kotlinx = "1.9.0" # https://github.com/Kotlin/kotlinx.coroutines/releases +kotlinx = "1.10.1" # https://github.com/Kotlin/kotlinx.coroutines/releases ksp = "2.1.0-1.0.29" # https://github.com/google/ksp/releases anvil = "0.4.0" # https://github.com/ZacSweers/anvil/releases anvil-utils = "0.3.0-beta02" # https://github.com/IlyaGulya/anvil-utils/releases @@ -60,7 +60,7 @@ datastore = "1.1.1" # https://developer.android.com/topic/libraries/architecture # https://github.com/vsch/flexmark-java/issues/442 flexmark = "0.42.14" # https://github.com/vsch/flexmark-java/tags markdown = "0.27.0" # https://github.com/mikepenz/multiplatform-markdown-renderer/releases -ktor = "3.0.2" # https://ktor.io/ +ktor = "3.0.3" # https://ktor.io/ apache-compress = "1.27.1" # https://commons.apache.org/proper/commons-compress/ apache-codec = "1.17.1" # https://mvnrepository.com/artifact/commons-codec/commons-codec countly = "24.7.7" # https://github.com/Countly/countly-sdk-android/releases @@ -100,6 +100,8 @@ buildkonfig = "5.5.1" wire = "5.1.0" okio = "3.9.1" +jserial = "2.10.3" + [libraries] # Gradle - Core @@ -118,6 +120,7 @@ grgit-gradle = { module = "com.github.LionZXY:grgit", version.ref = "grgit-gradl kotlin-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx" } kotlin-coroutines-play-services = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-play-services", version.ref = "kotlinx" } kotlin-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx" } +kotlin-coroutines-swing = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-swing", version.ref = "kotlinx" } kotlin-serialization-gradle = { module = "org.jetbrains.kotlin:kotlin-serialization", version.ref = "kotlin-general" } kotlin-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization-json" } @@ -214,8 +217,7 @@ ktx-activity = { module = "androidx.activity:activity-ktx", version.ref = "ktx-a ktx-testing = { module = "androidx.test.ext:junit", version.ref = "ktx-testing" } # Lifecycle -lifecycle-viewmodel-ktx = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "lifecycle" } -lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime-ktx", version.ref = "lifecycle" } +lifecycle-runtime-ktx = { module = "androidx.lifecycle:lifecycle-runtime", version.ref = "lifecycle" } lifecycle-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "lifecycle" } lifecycle-service = { module = "androidx.lifecycle:lifecycle-service", version.ref = "lifecycle" } lifecycle-test = { module = "androidx.lifecycle:lifecycle-runtime-testing", version.ref = "lifecycle" } @@ -244,6 +246,9 @@ ble-scan = { module = "no.nordicsemi.android.support.v18:scanner", version.ref = ble-kotlin-scanner = { module = "no.nordicsemi.android.kotlin.ble:scanner", version.ref = "ble-kotlin" } ble-kotlin-client = { module = "no.nordicsemi.android.kotlin.ble:client", version.ref = "ble-kotlin" } +# USB +jserial = { module = "com.fazecast:jSerialComm", version.ref = "jserial" } + # Images image-lottie = { module = "com.airbnb.android:lottie-compose", version.ref = "lottie" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 959b2c5e7f..de0a425fbc 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -46,6 +46,8 @@ include( ":components:bridge:connection:pbutils", ":components:bridge:connection:transport:ble:api", ":components:bridge:connection:transport:ble:impl", + ":components:bridge:connection:transport:usb:api", + ":components:bridge:connection:transport:usb:impl", ":components:bridge:connection:transport:common:api", ":components:bridge:connection:transport:common:impl", ":components:bridge:connection:orchestrator:api", @@ -54,7 +56,9 @@ include( ":components:bridge:connection:service:impl", ":components:bridge:connection:connectionbuilder:api", ":components:bridge:connection:connectionbuilder:impl", - ":components:bridge:connection:sample", + ":components:bridge:connection:sample:shared", + ":components:bridge:connection:sample:android", + ":components:bridge:connection:sample:desktop", ":components:bridge:connection:config:api", ":components:bridge:connection:config:impl", ":components:bridge:connection:transportconfigbuilder:api", @@ -101,8 +105,6 @@ include( ":components:filemngr:util", ":components:filemanager:api", ":components:filemanager:impl", - ":components:newfilemanager:api", - ":components:newfilemanager:impl", ":components:filemngr:ui-components", ":components:filemngr:main:api", ":components:filemngr:main:impl",