From 092548e8bf8e469025f5a0755686e35ec76dccdf Mon Sep 17 00:00:00 2001 From: X1nto Date: Sun, 30 May 2021 20:21:05 +0400 Subject: [PATCH 001/118] initial compose commit --- .github/ISSUE_TEMPLATE/config.yml | 1 + .gitignore | 6 - README.md | 12 +- app/.gitignore | 2 + app/build.gradle.kts | 141 ++--- app/src/main/AndroidManifest.xml | 87 +-- app/src/main/ic_launcher-playstore.png | Bin 29627 -> 0 bytes .../java/com/vanced/manager/MainActivity.kt | 156 +++++ .../com/vanced/manager/ManagerApplication.kt | 28 + .../vanced/manager/SplashScreenActivity.kt | 17 + .../adapter/ExpandableAppListAdapter.kt | 199 ------ .../vanced/manager/adapter/GetNotifAdapter.kt | 79 --- .../com/vanced/manager/adapter/LinkAdapter.kt | 95 --- .../manager/adapter/SelectAppsAdapter.kt | 60 -- .../vanced/manager/adapter/SponsorAdapter.kt | 68 -- .../manager/adapter/WelcomePageAdapter.kt | 23 - .../main/java/com/vanced/manager/core/App.kt | 55 -- .../core/downloader/MicrogDownloader.kt | 29 - .../core/downloader/MusicDownloader.kt | 87 --- .../core/downloader/VancedDownloader.kt | 149 ----- .../manager/core/firebase/CloudMessaging.kt | 12 - .../core/installer/AppInstallerService.kt | 50 -- .../core/installer/AppUninstallerService.kt | 42 -- .../com/vanced/manager/di/DownloaderModule.kt | 29 + .../com/vanced/manager/di/MapperModule.kt | 28 + .../com/vanced/manager/di/NetworkModule.kt | 12 + .../vanced/manager/di/PackageManagerModule.kt | 30 + .../com/vanced/manager/di/RepositoryModule.kt | 21 + .../com/vanced/manager/di/ServiceModule.kt | 23 + .../com/vanced/manager/di/ViewModelModule.kt | 9 + .../PackageInformationDataSource.kt | 10 +- .../com/vanced/manager/domain/model/App.kt | 23 + .../vanced/manager/domain/model/AppStatus.kt | 9 + .../com/vanced/manager/domain/model/Json.kt | 9 + .../com/vanced/manager/domain/model/Link.kt | 5 + .../vanced/manager/domain}/pkg/PkgManager.kt | 3 +- .../manager/domain/util/EntityMapper.kt | 9 + .../manager/downloader/api/VancedAPI.kt | 20 + .../manager/downloader/base/BaseDownloader.kt | 106 ++++ .../downloader/impl/MicrogDownloader.kt | 15 + .../downloader/impl/MusicDownloader.kt | 15 + .../downloader/impl/VancedDownloader.kt | 112 ++++ .../com/vanced/manager/ext/RetrofitKotlin.kt | 24 + .../vanced/manager/installer/AppInstaller.kt | 31 + .../com/vanced/manager/model/AppListModel.kt | 12 - .../vanced/manager/model/AppVersionsModel.kt | 6 - .../com/vanced/manager/model/ButtonTag.kt | 5 - .../com/vanced/manager/model/DataModel.kt | 110 ---- .../com/vanced/manager/model/LinkModel.kt | 8 - .../com/vanced/manager/model/NotifModel.kt | 8 - .../com/vanced/manager/model/RootDataModel.kt | 37 -- .../vanced/manager/model/SelectAppModel.kt | 8 - .../com/vanced/manager/model/SponsorModel.kt | 9 - .../vanced/manager/model/VancedPrefModel.kt | 6 - .../com/vanced/manager/network/JsonService.kt | 11 + .../vanced/manager/network/model/AppDto.kt | 16 + .../manager/network/model/AppDtoMapper.kt | 81 +++ .../vanced/manager/network/model/JsonDto.kt | 11 + .../manager/network/model/JsonDtoMapper.kt | 32 + .../vanced/manager/network/util/Constants.kt | 8 + .../manager/preference/ManagerPreferences.kt | 16 + .../manager/repository/JsonRepository.kt | 9 + .../manager/repository/JsonRepositoryImpl.kt | 16 + .../com/vanced/manager/ui/MainActivity.kt | 237 ------- .../vanced/manager/ui/SplashScreenActivity.kt | 22 - .../com/vanced/manager/ui/WelcomeActivity.kt | 86 --- .../manager/ui/composables/AppComposables.kt | 226 +++++++ .../manager/ui/composables/ColorPicker.kt | 105 +++ .../ui/composables/DialogComposables.kt | 2 + .../ui/composables/DownloadComposables.kt | 111 ++++ .../ui/composables/GlobalComposables.kt | 140 ++++ .../manager/ui/composables/HomeComposables.kt | 80 +++ .../ui/composables/ManagerComponents.kt | 229 +++++++ .../manager/ui/composables/ManagerListItem.kt | 95 +++ .../ui/composables/PreferenceComposables.kt | 148 +++++ .../com/vanced/manager/ui/compose/Colors.kt | 2 - .../manager/ui/compose/PreferenceViews.kt | 107 ---- .../com/vanced/manager/ui/compose/Theme.kt | 52 -- .../vanced/manager/ui/core/EmptyPreference.kt | 61 -- .../manager/ui/core/PreferenceCategory.kt | 39 -- .../manager/ui/core/PreferenceSwitch.kt | 101 --- .../vanced/manager/ui/core/ThemedAppCard.kt | 19 - .../manager/ui/core/ThemedIconButton.kt | 24 - .../manager/ui/core/ThemedMaterialButton.kt | 34 - .../manager/ui/core/ThemedMaterialCheckbox.kt | 17 - .../ui/core/ThemedMaterialRadioButton.kt | 17 - .../manager/ui/core/ThemedMaterialSlider.kt | 23 - .../ui/core/ThemedOutlinedMaterialButton.kt | 31 - .../ui/core/ThemedSwipeRefreshlayout.kt | 31 - .../manager/ui/core/ThemedSwitchCompat.kt | 42 -- .../vanced/manager/ui/core/ThemedTextView.kt | 21 - .../manager/ui/dialogs/AppDownloadDialog.kt | 125 ---- .../manager/ui/dialogs/AppInfoDialog.kt | 54 -- .../manager/ui/dialogs/AppUninstallDialog.kt | 50 -- .../ui/dialogs/AppVersionSelectorDialog.kt | 94 --- .../manager/ui/dialogs/DialogContainer.kt | 132 ---- .../InstallationFilesDetectedDialog.kt | 76 --- .../ui/dialogs/ManagerAccentColorDialog.kt | 128 ---- .../ui/dialogs/ManagerLanguageDialog.kt | 66 -- .../manager/ui/dialogs/ManagerThemeDialog.kt | 50 -- .../manager/ui/dialogs/ManagerUpdateDialog.kt | 117 ---- .../ui/dialogs/ManagerVariantDialog.kt | 56 -- .../ui/dialogs/MusicPreferencesDialog.kt | 61 -- .../manager/ui/dialogs/SelectAppsDialog.kt | 63 -- .../manager/ui/dialogs/ServiceDTimerDialog.kt | 75 --- .../manager/ui/dialogs/URLChangeDialog.kt | 68 -- .../dialogs/VancedLanguageSelectionDialog.kt | 87 --- .../ui/dialogs/VancedPreferencesDialog.kt | 84 --- .../ui/dialogs/VancedThemeSelectorDialog.kt | 81 --- .../manager/ui/fragments/AboutFragment.kt | 84 --- .../ui/fragments/DevSettingsFragment.kt | 115 ---- .../manager/ui/fragments/GrantRootFragment.kt | 55 -- .../manager/ui/fragments/HomeFragment.kt | 118 ---- .../manager/ui/fragments/LogFragment.kt | 56 -- .../ui/fragments/SelectAppsFragment.kt | 58 -- .../manager/ui/fragments/SettingsFragment.kt | 154 ----- .../ui/fragments/SettingsFragmentCompose.kt | 56 -- .../manager/ui/fragments/WelcomeFragment.kt | 27 - .../vanced/manager/ui/layouts/AboutLayout.kt | 193 ++++++ .../vanced/manager/ui/layouts/HomeLayout.kt | 122 ++++ .../vanced/manager/ui/layouts/LogLayout.kt | 41 ++ .../manager/ui/layouts/SettingsLayout.kt | 117 ++++ .../ui/preferences/RadioButtonPreference.kt | 6 + .../com/vanced/manager/ui/screens/Screen.kt | 8 + .../java/com/vanced/manager/ui/theme/Color.kt | 11 + .../java/com/vanced/manager/ui/theme/Shape.kt | 11 + .../java/com/vanced/manager/ui/theme/Theme.kt | 53 ++ .../java/com/vanced/manager/ui/theme/Type.kt | 28 + .../manager/ui/viewmodel/HomeViewModel.kt | 69 ++ .../manager/ui/viewmodels/AboutViewModel.kt | 14 - .../manager/ui/viewmodels/HomeViewModel.kt | 229 ------- .../ui/viewmodels/HomeViewModelFactory.kt | 14 - .../main/java/com/vanced/manager/util/Log.kt | 35 + .../java/com/vanced/manager/util/Variant.kt | 7 + .../java/com/vanced/manager/utils/AppUtils.kt | 143 ----- .../com/vanced/manager/utils/DeviceUtils.kt | 9 - .../vanced/manager/utils/DownloadHelper.kt | 158 ----- .../com/vanced/manager/utils/Extensions.kt | 87 --- .../com/vanced/manager/utils/InstallPrefs.kt | 20 - .../com/vanced/manager/utils/InternetTools.kt | 147 ----- .../com/vanced/manager/utils/JsonHelper.kt | 34 - .../manager/utils/LanguageContextWrapper.kt | 40 -- .../vanced/manager/utils/LanguageHelper.kt | 81 --- .../com/vanced/manager/utils/MiuiHelper.kt | 12 - .../com/vanced/manager/utils/PackageHelper.kt | 596 ------------------ .../com/vanced/manager/utils/Preferences.kt | 49 -- .../vanced/manager/utils/ProgressHelper.kt | 22 - .../com/vanced/manager/utils/ThemeHelper.kt | 36 -- .../main/res/drawable/category_background.xml | 14 - .../res/drawable/ic_android_black_24dp.xml | 9 + app/src/main/res/drawable/ic_app_download.xml | 10 - ...holder.xml => ic_app_icon_placeholder.xml} | 12 +- app/src/main/res/drawable/ic_app_info.xml | 10 - .../main/res/drawable/ic_app_reinstall.xml | 10 - .../main/res/drawable/ic_app_uninstall.xml | 10 - app/src/main/res/drawable/ic_app_update.xml | 10 - .../res/drawable/ic_baseline_close_24.xml | 10 - .../res/drawable/ic_baseline_launch_24.xml | 10 - .../drawable/ic_baseline_navigate_next_36.xml | 10 - .../drawable/ic_baseline_navigate_next_48.xml | 10 - .../main/res/drawable/ic_baseline_save_24.xml | 5 - .../ic_keyboard_backspace_black_24dp.xml | 9 - app/src/main/res/drawable/ic_manager.xml | 81 +++ app/src/main/res/drawable/ic_reddit.xml | 0 .../res/drawable/ic_settings_black_24dp.xml | 10 - .../main/res/drawable/ic_shortcut_info.xml | 12 - .../res/drawable/ic_shortcut_settings.xml | 12 - app/src/main/res/drawable/ic_splash.xml | 11 + app/src/main/res/drawable/splash_logo.xml | 13 - app/src/main/res/drawable/vanced_gradient.xml | 13 - app/src/main/res/layout/activity_main.xml | 36 -- app/src/main/res/layout/activity_welcome.xml | 6 - .../main/res/layout/dialog_app_download.xml | 91 --- app/src/main/res/layout/dialog_app_info.xml | 56 -- .../main/res/layout/dialog_app_uninstall.xml | 50 -- .../res/layout/dialog_bottom_radio_button.xml | 31 - app/src/main/res/layout/dialog_custom_url.xml | 53 -- .../dialog_installation_files_detected.xml | 34 - .../layout/dialog_manager_accent_color.xml | 64 -- .../res/layout/dialog_manager_language.xml | 29 - .../main/res/layout/dialog_manager_theme.xml | 54 -- .../main/res/layout/dialog_manager_update.xml | 65 -- .../res/layout/dialog_manager_variant.xml | 46 -- .../res/layout/dialog_music_preferences.xml | 46 -- .../main/res/layout/dialog_select_apps.xml | 29 - .../main/res/layout/dialog_serviced_timer.xml | 50 -- .../dialog_vanced_language_selection.xml | 37 -- .../res/layout/dialog_vanced_preferences.xml | 98 --- app/src/main/res/layout/fragment_about.xml | 193 ------ .../main/res/layout/fragment_dev_settings.xml | 98 --- .../main/res/layout/fragment_grant_root.xml | 71 --- app/src/main/res/layout/fragment_home.xml | 69 -- app/src/main/res/layout/fragment_log.xml | 37 -- .../main/res/layout/fragment_select_apps.xml | 40 -- app/src/main/res/layout/fragment_settings.xml | 103 --- app/src/main/res/layout/fragment_welcome.xml | 32 - app/src/main/res/layout/view_app_checkbox.xml | 52 -- .../main/res/layout/view_app_expandable.xml | 182 ------ .../res/layout/view_notification_setting.xml | 5 - app/src/main/res/layout/view_preference.xml | 23 - .../res/layout/view_preference_category.xml | 9 - .../res/layout/view_preference_switch.xml | 41 -- app/src/main/res/layout/view_social_link.xml | 27 - app/src/main/res/layout/view_sponsor.xml | 46 -- app/src/main/res/menu/dev_settings_menu.xml | 13 - app/src/main/res/menu/toolbar_menu.xml | 24 - .../main/res/navigation/mobile_navigation.xml | 83 --- app/src/main/res/values-night/colors.xml | 2 +- app/src/main/res/values-v23/themes.xml | 9 - app/src/main/res/values/colors.xml | 5 +- app/src/main/res/values/strings.xml | 0 app/src/main/res/values/styles.xml | 202 ------ app/src/main/res/values/themes.xml | 83 +-- app/src/main/res/xml-v25/shortcuts.xml | 33 - build.gradle.kts | 18 +- buildSrc/.gitignore | 1 + buildSrc/src/main/java/Config.kt | 2 +- core-mvi/.gitignore | 1 - core-mvi/build.gradle.kts | 19 - .../com/vanced/manager/core/mvi/MviFlow.kt | 98 --- .../vanced/manager/core/mvi/MviFlowStore.kt | 6 - .../vanced/manager/core/mvi/MviRenderView.kt | 12 - .../com/vanced/manager/core/mvi/Typealias.kt | 16 - .../example/ExampleManyStoreFragment.kt | 95 --- .../kotlin/example/ExampleStoreFragment.kt | 75 --- .../main/kotlin/example/ExampleViewModel.kt | 43 -- .../example/ExampleWithViewModelFragment.kt | 49 -- core-mvi/src/main/kotlin/example/Mvi.kt | 25 - .../vanced/manager/core/mvi/MviFlowSpec.kt | 169 ----- .../manager/core/mvi/subject/MviSubject.kt | 33 - .../manager/core/mvi/subject/SubjectStore.kt | 54 -- .../manager/core/mvi/subject/SubjectView.kt | 43 -- core-presentation/.gitignore | 1 - core-presentation/build.gradle.kts | 42 -- .../src/main/AndroidManifest.xml | 1 - .../core/presentation/BaseViewModel.kt | 7 - core-ui/.gitignore | 1 - core-ui/build.gradle.kts | 53 -- core-ui/src/main/AndroidManifest.xml | 1 - .../base/BindingBottomSheetDialogFragment.kt | 54 -- .../core/ui/base/BindingDialogFragment.kt | 37 -- .../manager/core/ui/base/BindingFragment.kt | 37 -- .../vanced/manager/core/ui/ext/FragmentExt.kt | 16 - feature-home/.gitignore | 1 - feature-home/build.gradle.kts | 87 --- feature-home/src/main/AndroidManifest.xml | 1 - .../manager/feature/home/data/api/AppsApi.kt | 15 - .../home/data/datasource/AppIconDataSource.kt | 23 - .../data/datasource/AppsInfoDataSource.kt | 21 - .../feature/home/data/dto/AppInfoDto.kt | 17 - .../data/repository/AppsRepositoryImpl.kt | 54 -- .../feature/home/di/FeatureHomeModules.kt | 72 --- .../feature/home/domain/entity/AppInfo.kt | 18 - .../feature/home/domain/entity/AppState.kt | 7 - .../feature/home/domain/entity/example.json | 60 -- .../home/domain/repository/AppsRepository.kt | 8 - .../home/domain/usecase/GetAppsInfoUseCase.kt | 12 - .../home/presentation/HomeViewModel.kt | 30 - .../manager/feature/home/ui/HomeFragment.kt | 25 - .../home/ui/bind/HomeFragmentBinder.kt | 18 - .../feature/home/ui/uistate/UiState.kt | 3 - .../src/main/res/layout/fragment_home.xml | 59 -- feature-home/src/main/res/values/links.xml | 9 - .../AppInformationDataSourceImplTest.kt | 68 -- .../PkgInformationDataSourceImplTest.kt | 24 - gradle.properties | 4 +- gradle/wrapper/gradle-wrapper.jar | Bin 54329 -> 59203 bytes gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 53 +- gradlew.bat | 173 ++--- library-network/.gitignore | 1 - library-network/build.gradle.kts | 56 -- library-network/src/main/AndroidManifest.xml | 5 - .../library/network/di/NetworkModule.kt | 48 -- .../okhttp/interceptors/LoggingInterceptor.kt | 10 - .../interceptors/NoConnectionInterceptor.kt | 42 -- .../network/providers/MoshiProvider.kt | 11 - .../network/providers/OkHttpClientProvider.kt | 24 - .../network/providers/RetrofitProvider.kt | 25 - .../network/service/RetrofitService.kt | 6 - settings.gradle.kts | 6 - 281 files changed, 3082 insertions(+), 10708 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 app/.gitignore delete mode 100644 app/src/main/ic_launcher-playstore.png create mode 100644 app/src/main/java/com/vanced/manager/MainActivity.kt create mode 100644 app/src/main/java/com/vanced/manager/ManagerApplication.kt create mode 100644 app/src/main/java/com/vanced/manager/SplashScreenActivity.kt delete mode 100644 app/src/main/java/com/vanced/manager/adapter/ExpandableAppListAdapter.kt delete mode 100644 app/src/main/java/com/vanced/manager/adapter/GetNotifAdapter.kt delete mode 100644 app/src/main/java/com/vanced/manager/adapter/LinkAdapter.kt delete mode 100644 app/src/main/java/com/vanced/manager/adapter/SelectAppsAdapter.kt delete mode 100644 app/src/main/java/com/vanced/manager/adapter/SponsorAdapter.kt delete mode 100644 app/src/main/java/com/vanced/manager/adapter/WelcomePageAdapter.kt delete mode 100644 app/src/main/java/com/vanced/manager/core/App.kt delete mode 100644 app/src/main/java/com/vanced/manager/core/downloader/MicrogDownloader.kt delete mode 100644 app/src/main/java/com/vanced/manager/core/downloader/MusicDownloader.kt delete mode 100644 app/src/main/java/com/vanced/manager/core/downloader/VancedDownloader.kt delete mode 100644 app/src/main/java/com/vanced/manager/core/firebase/CloudMessaging.kt delete mode 100644 app/src/main/java/com/vanced/manager/core/installer/AppInstallerService.kt delete mode 100644 app/src/main/java/com/vanced/manager/core/installer/AppUninstallerService.kt create mode 100644 app/src/main/java/com/vanced/manager/di/DownloaderModule.kt create mode 100644 app/src/main/java/com/vanced/manager/di/MapperModule.kt create mode 100644 app/src/main/java/com/vanced/manager/di/NetworkModule.kt create mode 100644 app/src/main/java/com/vanced/manager/di/PackageManagerModule.kt create mode 100644 app/src/main/java/com/vanced/manager/di/RepositoryModule.kt create mode 100644 app/src/main/java/com/vanced/manager/di/ServiceModule.kt create mode 100644 app/src/main/java/com/vanced/manager/di/ViewModelModule.kt rename feature-home/src/main/java/com/vanced/manager/feature/home/data/datasource/PkgIngormationDataSource.kt => app/src/main/java/com/vanced/manager/domain/datasource/PackageInformationDataSource.kt (80%) create mode 100644 app/src/main/java/com/vanced/manager/domain/model/App.kt create mode 100644 app/src/main/java/com/vanced/manager/domain/model/AppStatus.kt create mode 100644 app/src/main/java/com/vanced/manager/domain/model/Json.kt create mode 100644 app/src/main/java/com/vanced/manager/domain/model/Link.kt rename {feature-home/src/main/java/com/vanced/manager/feature/home/data => app/src/main/java/com/vanced/manager/domain}/pkg/PkgManager.kt (96%) create mode 100644 app/src/main/java/com/vanced/manager/domain/util/EntityMapper.kt create mode 100644 app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt create mode 100644 app/src/main/java/com/vanced/manager/downloader/base/BaseDownloader.kt create mode 100644 app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt create mode 100644 app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt create mode 100644 app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt create mode 100644 app/src/main/java/com/vanced/manager/ext/RetrofitKotlin.kt create mode 100644 app/src/main/java/com/vanced/manager/installer/AppInstaller.kt delete mode 100644 app/src/main/java/com/vanced/manager/model/AppListModel.kt delete mode 100644 app/src/main/java/com/vanced/manager/model/AppVersionsModel.kt delete mode 100644 app/src/main/java/com/vanced/manager/model/ButtonTag.kt delete mode 100644 app/src/main/java/com/vanced/manager/model/DataModel.kt delete mode 100644 app/src/main/java/com/vanced/manager/model/LinkModel.kt delete mode 100644 app/src/main/java/com/vanced/manager/model/NotifModel.kt delete mode 100644 app/src/main/java/com/vanced/manager/model/RootDataModel.kt delete mode 100644 app/src/main/java/com/vanced/manager/model/SelectAppModel.kt delete mode 100644 app/src/main/java/com/vanced/manager/model/SponsorModel.kt delete mode 100644 app/src/main/java/com/vanced/manager/model/VancedPrefModel.kt create mode 100644 app/src/main/java/com/vanced/manager/network/JsonService.kt create mode 100644 app/src/main/java/com/vanced/manager/network/model/AppDto.kt create mode 100644 app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt create mode 100644 app/src/main/java/com/vanced/manager/network/model/JsonDto.kt create mode 100644 app/src/main/java/com/vanced/manager/network/model/JsonDtoMapper.kt create mode 100644 app/src/main/java/com/vanced/manager/network/util/Constants.kt create mode 100644 app/src/main/java/com/vanced/manager/preference/ManagerPreferences.kt create mode 100644 app/src/main/java/com/vanced/manager/repository/JsonRepository.kt create mode 100644 app/src/main/java/com/vanced/manager/repository/JsonRepositoryImpl.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/MainActivity.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/SplashScreenActivity.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/WelcomeActivity.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/composables/AppComposables.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/composables/ColorPicker.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/composables/DialogComposables.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/composables/DownloadComposables.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/composables/GlobalComposables.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/composables/HomeComposables.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/composables/ManagerComponents.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/composables/ManagerListItem.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/composables/PreferenceComposables.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/compose/Colors.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/compose/PreferenceViews.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/compose/Theme.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/core/EmptyPreference.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/core/PreferenceCategory.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/core/PreferenceSwitch.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/core/ThemedAppCard.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/core/ThemedIconButton.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/core/ThemedMaterialButton.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/core/ThemedMaterialCheckbox.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/core/ThemedMaterialRadioButton.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/core/ThemedMaterialSlider.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/core/ThemedOutlinedMaterialButton.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/core/ThemedSwipeRefreshlayout.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/core/ThemedSwitchCompat.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/core/ThemedTextView.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/dialogs/AppDownloadDialog.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/dialogs/AppInfoDialog.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/dialogs/AppUninstallDialog.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/dialogs/AppVersionSelectorDialog.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/dialogs/DialogContainer.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/dialogs/InstallationFilesDetectedDialog.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/dialogs/ManagerAccentColorDialog.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/dialogs/ManagerLanguageDialog.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/dialogs/ManagerThemeDialog.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/dialogs/ManagerUpdateDialog.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/dialogs/ManagerVariantDialog.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/dialogs/MusicPreferencesDialog.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/dialogs/SelectAppsDialog.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/dialogs/ServiceDTimerDialog.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/dialogs/URLChangeDialog.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/dialogs/VancedLanguageSelectionDialog.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/dialogs/VancedPreferencesDialog.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/dialogs/VancedThemeSelectorDialog.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/fragments/AboutFragment.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/fragments/DevSettingsFragment.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/fragments/GrantRootFragment.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/fragments/HomeFragment.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/fragments/LogFragment.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/fragments/SelectAppsFragment.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/fragments/SettingsFragment.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/fragments/SettingsFragmentCompose.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/fragments/WelcomeFragment.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/layouts/AboutLayout.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/preferences/RadioButtonPreference.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/screens/Screen.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/theme/Color.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/theme/Shape.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/theme/Theme.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/theme/Type.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/viewmodels/AboutViewModel.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/viewmodels/HomeViewModel.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/viewmodels/HomeViewModelFactory.kt create mode 100644 app/src/main/java/com/vanced/manager/util/Log.kt create mode 100644 app/src/main/java/com/vanced/manager/util/Variant.kt delete mode 100644 app/src/main/java/com/vanced/manager/utils/AppUtils.kt delete mode 100644 app/src/main/java/com/vanced/manager/utils/DeviceUtils.kt delete mode 100644 app/src/main/java/com/vanced/manager/utils/DownloadHelper.kt delete mode 100644 app/src/main/java/com/vanced/manager/utils/Extensions.kt delete mode 100644 app/src/main/java/com/vanced/manager/utils/InstallPrefs.kt delete mode 100644 app/src/main/java/com/vanced/manager/utils/InternetTools.kt delete mode 100644 app/src/main/java/com/vanced/manager/utils/JsonHelper.kt delete mode 100644 app/src/main/java/com/vanced/manager/utils/LanguageContextWrapper.kt delete mode 100644 app/src/main/java/com/vanced/manager/utils/LanguageHelper.kt delete mode 100644 app/src/main/java/com/vanced/manager/utils/MiuiHelper.kt delete mode 100644 app/src/main/java/com/vanced/manager/utils/PackageHelper.kt delete mode 100644 app/src/main/java/com/vanced/manager/utils/Preferences.kt delete mode 100644 app/src/main/java/com/vanced/manager/utils/ProgressHelper.kt delete mode 100644 app/src/main/java/com/vanced/manager/utils/ThemeHelper.kt delete mode 100644 app/src/main/res/drawable/category_background.xml create mode 100644 app/src/main/res/drawable/ic_android_black_24dp.xml delete mode 100644 app/src/main/res/drawable/ic_app_download.xml rename app/src/main/res/drawable/{app_image_placeholder.xml => ic_app_icon_placeholder.xml} (50%) delete mode 100644 app/src/main/res/drawable/ic_app_info.xml delete mode 100644 app/src/main/res/drawable/ic_app_reinstall.xml delete mode 100644 app/src/main/res/drawable/ic_app_uninstall.xml delete mode 100644 app/src/main/res/drawable/ic_app_update.xml delete mode 100644 app/src/main/res/drawable/ic_baseline_close_24.xml delete mode 100644 app/src/main/res/drawable/ic_baseline_launch_24.xml delete mode 100644 app/src/main/res/drawable/ic_baseline_navigate_next_36.xml delete mode 100644 app/src/main/res/drawable/ic_baseline_navigate_next_48.xml delete mode 100644 app/src/main/res/drawable/ic_baseline_save_24.xml delete mode 100644 app/src/main/res/drawable/ic_keyboard_backspace_black_24dp.xml create mode 100644 app/src/main/res/drawable/ic_manager.xml mode change 100755 => 100644 app/src/main/res/drawable/ic_reddit.xml delete mode 100644 app/src/main/res/drawable/ic_settings_black_24dp.xml delete mode 100644 app/src/main/res/drawable/ic_shortcut_info.xml delete mode 100644 app/src/main/res/drawable/ic_shortcut_settings.xml create mode 100644 app/src/main/res/drawable/ic_splash.xml delete mode 100644 app/src/main/res/drawable/splash_logo.xml delete mode 100644 app/src/main/res/drawable/vanced_gradient.xml delete mode 100644 app/src/main/res/layout/activity_main.xml delete mode 100644 app/src/main/res/layout/activity_welcome.xml delete mode 100644 app/src/main/res/layout/dialog_app_download.xml delete mode 100644 app/src/main/res/layout/dialog_app_info.xml delete mode 100644 app/src/main/res/layout/dialog_app_uninstall.xml delete mode 100644 app/src/main/res/layout/dialog_bottom_radio_button.xml delete mode 100644 app/src/main/res/layout/dialog_custom_url.xml delete mode 100644 app/src/main/res/layout/dialog_installation_files_detected.xml delete mode 100644 app/src/main/res/layout/dialog_manager_accent_color.xml delete mode 100644 app/src/main/res/layout/dialog_manager_language.xml delete mode 100644 app/src/main/res/layout/dialog_manager_theme.xml delete mode 100644 app/src/main/res/layout/dialog_manager_update.xml delete mode 100644 app/src/main/res/layout/dialog_manager_variant.xml delete mode 100644 app/src/main/res/layout/dialog_music_preferences.xml delete mode 100644 app/src/main/res/layout/dialog_select_apps.xml delete mode 100644 app/src/main/res/layout/dialog_serviced_timer.xml delete mode 100644 app/src/main/res/layout/dialog_vanced_language_selection.xml delete mode 100644 app/src/main/res/layout/dialog_vanced_preferences.xml delete mode 100644 app/src/main/res/layout/fragment_about.xml delete mode 100644 app/src/main/res/layout/fragment_dev_settings.xml delete mode 100644 app/src/main/res/layout/fragment_grant_root.xml delete mode 100644 app/src/main/res/layout/fragment_home.xml delete mode 100644 app/src/main/res/layout/fragment_log.xml delete mode 100644 app/src/main/res/layout/fragment_select_apps.xml delete mode 100644 app/src/main/res/layout/fragment_settings.xml delete mode 100644 app/src/main/res/layout/fragment_welcome.xml delete mode 100644 app/src/main/res/layout/view_app_checkbox.xml delete mode 100644 app/src/main/res/layout/view_app_expandable.xml delete mode 100644 app/src/main/res/layout/view_notification_setting.xml delete mode 100644 app/src/main/res/layout/view_preference.xml delete mode 100644 app/src/main/res/layout/view_preference_category.xml delete mode 100644 app/src/main/res/layout/view_preference_switch.xml delete mode 100644 app/src/main/res/layout/view_social_link.xml delete mode 100644 app/src/main/res/layout/view_sponsor.xml delete mode 100644 app/src/main/res/menu/dev_settings_menu.xml delete mode 100644 app/src/main/res/menu/toolbar_menu.xml delete mode 100644 app/src/main/res/navigation/mobile_navigation.xml delete mode 100644 app/src/main/res/values-v23/themes.xml mode change 100755 => 100644 app/src/main/res/values/strings.xml delete mode 100644 app/src/main/res/values/styles.xml delete mode 100644 app/src/main/res/xml-v25/shortcuts.xml create mode 100644 buildSrc/.gitignore delete mode 100644 core-mvi/.gitignore delete mode 100644 core-mvi/build.gradle.kts delete mode 100644 core-mvi/src/main/kotlin/com/vanced/manager/core/mvi/MviFlow.kt delete mode 100644 core-mvi/src/main/kotlin/com/vanced/manager/core/mvi/MviFlowStore.kt delete mode 100644 core-mvi/src/main/kotlin/com/vanced/manager/core/mvi/MviRenderView.kt delete mode 100644 core-mvi/src/main/kotlin/com/vanced/manager/core/mvi/Typealias.kt delete mode 100644 core-mvi/src/main/kotlin/example/ExampleManyStoreFragment.kt delete mode 100644 core-mvi/src/main/kotlin/example/ExampleStoreFragment.kt delete mode 100644 core-mvi/src/main/kotlin/example/ExampleViewModel.kt delete mode 100644 core-mvi/src/main/kotlin/example/ExampleWithViewModelFragment.kt delete mode 100644 core-mvi/src/main/kotlin/example/Mvi.kt delete mode 100644 core-mvi/src/test/kotlin/com/vanced/manager/core/mvi/MviFlowSpec.kt delete mode 100644 core-mvi/src/test/kotlin/com/vanced/manager/core/mvi/subject/MviSubject.kt delete mode 100644 core-mvi/src/test/kotlin/com/vanced/manager/core/mvi/subject/SubjectStore.kt delete mode 100644 core-mvi/src/test/kotlin/com/vanced/manager/core/mvi/subject/SubjectView.kt delete mode 100644 core-presentation/.gitignore delete mode 100644 core-presentation/build.gradle.kts delete mode 100644 core-presentation/src/main/AndroidManifest.xml delete mode 100644 core-presentation/src/main/java/com/vanced/manager/core/presentation/BaseViewModel.kt delete mode 100644 core-ui/.gitignore delete mode 100644 core-ui/build.gradle.kts delete mode 100644 core-ui/src/main/AndroidManifest.xml delete mode 100644 core-ui/src/main/java/com/vanced/manager/core/ui/base/BindingBottomSheetDialogFragment.kt delete mode 100644 core-ui/src/main/java/com/vanced/manager/core/ui/base/BindingDialogFragment.kt delete mode 100644 core-ui/src/main/java/com/vanced/manager/core/ui/base/BindingFragment.kt delete mode 100644 core-ui/src/main/java/com/vanced/manager/core/ui/ext/FragmentExt.kt delete mode 100644 feature-home/.gitignore delete mode 100644 feature-home/build.gradle.kts delete mode 100644 feature-home/src/main/AndroidManifest.xml delete mode 100644 feature-home/src/main/java/com/vanced/manager/feature/home/data/api/AppsApi.kt delete mode 100644 feature-home/src/main/java/com/vanced/manager/feature/home/data/datasource/AppIconDataSource.kt delete mode 100644 feature-home/src/main/java/com/vanced/manager/feature/home/data/datasource/AppsInfoDataSource.kt delete mode 100644 feature-home/src/main/java/com/vanced/manager/feature/home/data/dto/AppInfoDto.kt delete mode 100644 feature-home/src/main/java/com/vanced/manager/feature/home/data/repository/AppsRepositoryImpl.kt delete mode 100644 feature-home/src/main/java/com/vanced/manager/feature/home/di/FeatureHomeModules.kt delete mode 100644 feature-home/src/main/java/com/vanced/manager/feature/home/domain/entity/AppInfo.kt delete mode 100644 feature-home/src/main/java/com/vanced/manager/feature/home/domain/entity/AppState.kt delete mode 100644 feature-home/src/main/java/com/vanced/manager/feature/home/domain/entity/example.json delete mode 100644 feature-home/src/main/java/com/vanced/manager/feature/home/domain/repository/AppsRepository.kt delete mode 100644 feature-home/src/main/java/com/vanced/manager/feature/home/domain/usecase/GetAppsInfoUseCase.kt delete mode 100644 feature-home/src/main/java/com/vanced/manager/feature/home/presentation/HomeViewModel.kt delete mode 100644 feature-home/src/main/java/com/vanced/manager/feature/home/ui/HomeFragment.kt delete mode 100644 feature-home/src/main/java/com/vanced/manager/feature/home/ui/bind/HomeFragmentBinder.kt delete mode 100644 feature-home/src/main/java/com/vanced/manager/feature/home/ui/uistate/UiState.kt delete mode 100644 feature-home/src/main/res/layout/fragment_home.xml delete mode 100644 feature-home/src/main/res/values/links.xml delete mode 100644 feature-home/src/test/java/com/vanced/manager/feature/home/data/datasource/AppInformationDataSourceImplTest.kt delete mode 100644 feature-home/src/test/java/com/vanced/manager/feature/home/data/datasource/PkgInformationDataSourceImplTest.kt mode change 100755 => 100644 gradlew delete mode 100644 library-network/.gitignore delete mode 100644 library-network/build.gradle.kts delete mode 100644 library-network/src/main/AndroidManifest.xml delete mode 100644 library-network/src/main/java/com/vanced/manager/library/network/di/NetworkModule.kt delete mode 100644 library-network/src/main/java/com/vanced/manager/library/network/okhttp/interceptors/LoggingInterceptor.kt delete mode 100644 library-network/src/main/java/com/vanced/manager/library/network/okhttp/interceptors/NoConnectionInterceptor.kt delete mode 100644 library-network/src/main/java/com/vanced/manager/library/network/providers/MoshiProvider.kt delete mode 100644 library-network/src/main/java/com/vanced/manager/library/network/providers/OkHttpClientProvider.kt delete mode 100644 library-network/src/main/java/com/vanced/manager/library/network/providers/RetrofitProvider.kt delete mode 100644 library-network/src/main/java/com/vanced/manager/library/network/service/RetrofitService.kt diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..ec4bb386bc --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: false \ No newline at end of file diff --git a/.gitignore b/.gitignore index 6b24209962..d8e6fd459c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,4 @@ .gradle/ .idea/ build/ -out/ -app/src/main/java/com/vanced/manager/core/base/DummyJava.java -app/build/ -app/release local.properties -/.github/ -*.iml diff --git a/README.md b/README.md index 11e5ff0930..0c2f9fb947 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,6 @@ # Vanced Manager -
- [![Github All Releases](https://img.shields.io/github/downloads/YTVanced/VancedManager/total.svg?style=for-the-badge)](https://github.com/YTVanced/VancedManager/releases/latest) [![Github All Releases](https://img.shields.io/github/release/YTVanced/VancedManager.svg?style=for-the-badge)](https://github.com/YTVanced/VancedManager/releases/latest) -
- Hi, when we released Vanced 15.05.54, people were upset because it used the .apks format, which was way harder to install than a traditional .apk file. Even though we wrote clear instructions on how to install the new Vanced build, people still couldn't figure it out. Then we thought, "why don't we make a manager for vanced, which will download, update and uninstall Vanced and MicroG, have an easy and understandable UI and be less than 10mb?" and that's how Vanced Manager was born. @@ -17,10 +13,6 @@ Pull requests should be made to the Dev branch as that is the working branch, ma For anyone who wants to provide translations please submit them to https://crowdin.com/project/vanced-manager as we also use it for YouTube Vanced. Any issues with translations should be posted there too. -## TODO -- [ ] Clean up the ViewModel and DataModel code -- [ ] Migrate to Jetpack Compose when it's officially released - ## Building
@@ -43,7 +35,7 @@ chmod +x gradlew ./gradlew assembleDebug ``` -## Vanced FAQ -Vanced FAQ (from the faq branch) now available on the playstore! +## Vanced Guide +[Vanced Guide](https://github.com/YTVanced/VancedGuide/) now available on the playstore! Get it on Google Play diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000000..956c004dc0 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1,2 @@ +/build +/release \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4861b09b69..4acd73aa82 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,41 +1,29 @@ plugins { id("com.android.application") kotlin("android") - kotlin("kapt") - id("com.google.gms.google-services") - id("com.google.firebase.crashlytics") - id("com.google.firebase.firebase-perf") - id("androidx.navigation.safeargs.kotlin") - id("kotlin-android") } android { - compileSdkVersion(30) + compileSdk = 30 defaultConfig { + minSdk = 21 + targetSdk = 30 + applicationId = "com.vanced.manager" - minSdkVersion(21) - targetSdkVersion(30) - versionCode = 260 - versionName = "2.6.0 (Crimson)" + + versionCode = 3000 + versionName = "3.0.0 (Re@Composed)" vectorDrawables.useSupportLibrary = true buildConfigField("String[]", "MANAGER_LANGUAGES", "{$languages}") - buildConfigField("Boolean", "ENABLE_CROWDIN_AUTH", "false") - buildConfigField("String", "CROWDIN_HASH", "\"${System.getenv("CROWDIN_HASH")}\"") - buildConfigField("String", "CROWDIN_CLIENT_ID", "\"${System.getenv("CROWDIN_CLIENT_ID")}\"") - buildConfigField("String", "CROWDIN_CLIENT_SECRET", "\"${System.getenv("CROWDIN_CLIENT_SECRET")}\"") } - lintOptions { + lint { disable("MissingTranslation", "ExtraTranslation") } - applicationVariants.all { - resValue("string", "versionName", versionName) - } - buildTypes { getByName("release") { isMinifyEnabled = true @@ -44,30 +32,29 @@ android { } buildFeatures { - viewBinding = true - //compose = true + compose = true } packagingOptions { - exclude("META-INF/DEPENDENCIES") - exclude("META-INF/*.kotlin_module") + resources.excludes.add("META-INF/DEPENDENCIES") + resources.excludes.add("META-INF/*.kotlin_module") } -// To inline the bytecode built with JVM target 1.8 into -// bytecode that is being built with JVM target 1.6. (e.g. navArgs) - + // To inline the bytecode built with JVM target 1.8 into + // bytecode that is being built with JVM target 1.6. (e.g. navArgs) compileOptions { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } - tasks.withType { - kotlinOptions { - jvmTarget = "1.8" - //useIR = true - } - } +} +tasks.withType { + kotlinOptions { + jvmTarget = "1.8" + useIR = true + freeCompilerArgs = freeCompilerArgs + "-Xopt-in=kotlin.RequiresOptIn" + } } val languages: String get() { @@ -76,7 +63,7 @@ val languages: String get() { File("$projectDir/src/main/res").listFiles()?.filter { val name = it.name - name.startsWith("values-") && !name.contains("v23") + name.startsWith("values") && !name.contains("v23") && !name.contains("night") }?.forEach { dir -> val dirname = dir.name.substringAfter("-").substringBefore("-") if (!exceptions.contains(dirname)) { @@ -87,69 +74,49 @@ val languages: String get() { } dependencies { - - //val composeVersion = "1.0.0-alpha12" - implementation(project(":core-presentation")) - implementation(project(":core-ui")) - - implementation(project(":library-network")) - - // Kotlin - implementation(kotlin("stdlib-jdk8")) implementation(kotlin("reflect")) - // AndroidX - implementation("androidx.appcompat:appcompat:1.2.0") + implementation("androidx.core:core-ktx:1.5.0") + implementation("androidx.appcompat:appcompat:1.3.0") + implementation("com.google.android.material:material:1.3.0") implementation("androidx.browser:browser:1.3.0") - implementation("androidx.constraintlayout:constraintlayout:2.0.4") - implementation("androidx.core:core-ktx:1.3.2") - implementation("androidx.fragment:fragment-ktx:1.3.3") - implementation("androidx.lifecycle:lifecycle-livedata-core-ktx:2.3.1") - implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1") - implementation("androidx.localbroadcastmanager:localbroadcastmanager:1.0.0") - implementation("androidx.navigation:navigation-fragment-ktx:2.3.5") - implementation("androidx.navigation:navigation-ui-ktx:2.3.5") - implementation("androidx.preference:preference-ktx:1.1.1") - implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") + val composeVersion = "1.0.0-beta07" + implementation("androidx.compose.ui:ui:$composeVersion") + implementation("androidx.compose.material:material:$composeVersion") + implementation("androidx.compose.ui:ui-tooling:$composeVersion") + implementation("androidx.compose.ui:ui-util:$composeVersion") + implementation("androidx.compose.foundation:foundation:$composeVersion") + implementation("androidx.compose.material:material:$composeVersion") + implementation("androidx.compose.material:material-icons-core:$composeVersion") + implementation("androidx.compose.material:material-icons-extended:$composeVersion") + implementation("androidx.compose.runtime:runtime-livedata:$composeVersion") + + implementation("androidx.activity:activity-compose:1.3.0-alpha08") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.3.1") + implementation("androidx.navigation:navigation-compose:2.4.0-alpha01") + implementation("androidx.preference:preference-ktx:1.1.1") - // Compose -// implementation("androidx.compose.ui:ui:$composeVersion") -// implementation("androidx.compose.ui:ui-tooling:$composeVersion") -// implementation("androidx.compose.foundation:foundation:$composeVersion") -// implementation("androidx.constraintlayout:constraintlayout-compose:1.0.0-alpha02") -// implementation("androidx.compose.material:material:$composeVersion") -// implementation("androidx.compose.material:material-icons-core:$composeVersion") -// implementation("androidx.compose.material:material-icons-extended:$composeVersion") -// implementation("androidx.compose.runtime:runtime-livedata:$composeVersion") + val accompanistVersion = "0.10.0" + implementation("com.google.accompanist:accompanist-glide:$accompanistVersion") + implementation("com.google.accompanist:accompanist-swiperefresh:$accompanistVersion") + implementation("com.google.accompanist:accompanist-systemuicontroller:$accompanistVersion") - // Appearance implementation("com.github.madrapps:pikolo:2.0.1") - implementation("com.google.android.material:material:1.3.0") - - // JSON parser - implementation("com.beust:klaxon:5.5") - // Crowdin - implementation("com.github.crowdin.mobile-sdk-android:sdk:1.4.0") + val koinVersion = "3.0.1" + implementation("io.insert-koin:koin-android:$koinVersion") + implementation("io.insert-koin:koin-androidx-compose:$koinVersion") - // HTTP networking - implementation("com.github.kittinunf.fuel:fuel:2.3.1") - implementation("com.github.kittinunf.fuel:fuel-coroutines:2.3.1") - implementation("com.github.kittinunf.fuel:fuel-json:2.3.1") - implementation("com.squareup.okhttp3:logging-interceptor:4.9.1") - implementation("com.squareup.retrofit2:retrofit:2.9.0") + val retrofitVersion = "2.9.0" + implementation("com.squareup.retrofit2:retrofit:$retrofitVersion") + implementation("com.squareup.retrofit2:converter-gson:$retrofitVersion") - // Root permissions - implementation("com.github.topjohnwu.libsu:core:3.1.2") - implementation("com.github.topjohnwu.libsu:io:3.1.2") + implementation("dev.burnoo:compose-remember-preference:0.3.0") - // Layout - implementation("com.google.android:flexbox:2.0.1") + implementation("com.github.x1nto:apkhelper:1.1.0") - // Firebase - implementation("com.google.firebase:firebase-analytics-ktx:18.0.3") - implementation("com.google.firebase:firebase-crashlytics:17.4.1") - implementation("com.google.firebase:firebase-messaging:21.1.0") - implementation("com.google.firebase:firebase-perf:19.1.1") + testImplementation("junit:junit:4.13.2") + androidTestImplementation("androidx.test.ext:junit:1.1.2") + androidTestImplementation("androidx.test.espresso:espresso-core:3.3.0") } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 81440f187c..611e07b498 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,42 +1,20 @@ - - - - - - - - - - - - - - - - - + android:supportsRtl="true"> @@ -44,63 +22,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:name=".MainActivity" + android:theme="@style/Theme.MaterialComponents.NoActionBar" + android:label="@string/app_name"/> diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png deleted file mode 100644 index 7004eaa534ae4cff42e62225faf3a1147e078acb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29627 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 diff --git a/app/src/main/java/com/vanced/manager/MainActivity.kt b/app/src/main/java/com/vanced/manager/MainActivity.kt new file mode 100644 index 0000000000..738f91e244 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/MainActivity.kt @@ -0,0 +1,156 @@ +package com.vanced.manager + +import android.os.Bundle +import androidx.activity.compose.setContent +import androidx.appcompat.app.AppCompatActivity +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.foundation.background +import androidx.compose.material.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowBackIos +import androidx.compose.material.icons.filled.MoreVert +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.navigation.NavController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import com.google.accompanist.systemuicontroller.rememberSystemUiController +import com.vanced.manager.preference.defPrefs +import com.vanced.manager.preference.managerTheme +import com.vanced.manager.ui.composables.* +import com.vanced.manager.ui.layouts.* +import com.vanced.manager.ui.screens.Screen +import com.vanced.manager.ui.theme.ComposeTestTheme +import com.vanced.manager.ui.theme.isDark +import com.vanced.manager.ui.theme.managerTheme + +class MainActivity : AppCompatActivity() { + + @ExperimentalAnimationApi + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + managerTheme = defPrefs.managerTheme + + ComposeTestTheme { + //ButtonLayoutActivity() + MainActivityLayout() + } + } + } + + @ExperimentalAnimationApi + @Composable + fun MainActivityLayout() { + val isMenuExpanded = remember { mutableStateOf(false) } + val systemUiController = rememberSystemUiController() + val surfaceColor = managerSurfaceColor() + val isDark = isDark() + val navController = rememberNavController() + + val dropdownScreens = listOf( + Screen.Settings, + Screen.Logs, + Screen.About + ) + + SideEffect { + systemUiController.setSystemBarsColor(surfaceColor, !isDark) + } + + Scaffold( + topBar = { + MainToolbar( + navController, + dropdownScreens, + isMenuExpanded + ) + }, + backgroundColor = managerSurfaceColor() + ) { + NavHost( + navController = navController, + startDestination = Screen.Home.route + ) { + composable(Screen.Home.route) { + HomeLayout() + } + } + } + } + + @Composable + fun MainToolbar( + navController: NavController, + dropdownScreens: List, + isMenuExpanded: MutableState + ) { + TopAppBar( + title = { + navController.currentDestination + Text( + //This does not look good at all + text = Screen::class.sealedSubclasses.find { + it.objectInstance?.route == navController.currentDestination?.route + }?.objectInstance?.displayName ?: "", + color = managerAnimatedColor(color = MaterialTheme.colors.onSurface) + ) + }, + backgroundColor = managerAnimatedColor(color = MaterialTheme.colors.surface), + actions = { + if (navController.currentDestination?.route == Screen.Home.route) { + IconButton( + onClick = { isMenuExpanded.value = !isMenuExpanded.value } + ) { + Icon( + imageVector = Icons.Default.MoreVert, + contentDescription = null, + tint = managerTextColor() + ) + } + + DropdownMenu( + expanded = isMenuExpanded.value, + onDismissRequest = { + isMenuExpanded.value = false + }, + modifier = Modifier.background(managerCardColor()) + ) { + dropdownScreens.forEach { + ManagerDropdownMenuItem( + isMenuExpanded = isMenuExpanded, + title = it.displayName + ) { + navController.navigate(it.route) { + popUpTo(Screen.Home.route) + anim { + enter = R.animator.fragment_enter + exit = R.animator.fragment_exit + popEnter = R.animator.fragment_enter_pop + popEnter = R.animator.fragment_exit_pop + } + restoreState = true + } + } + } + } + } + }, + navigationIcon = if (navController.currentDestination?.route != Screen.Home.route) { { + IconButton(onClick = { + navController.popBackStack() + }) { + Icon( + imageVector = Icons.Default.ArrowBackIos, + contentDescription = null, + tint = managerTextColor() + ) + } + }} else null, + elevation = 0.dp + ) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ManagerApplication.kt b/app/src/main/java/com/vanced/manager/ManagerApplication.kt new file mode 100644 index 0000000000..4c374b7ddc --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ManagerApplication.kt @@ -0,0 +1,28 @@ +package com.vanced.manager + +import android.app.Application +import com.vanced.manager.di.* +import org.koin.android.ext.koin.androidContext +import org.koin.core.context.startKoin + +class ManagerApplication : Application() { + + override fun onCreate() { + super.onCreate() + + startKoin { + androidContext(this@ManagerApplication) + + modules( + mapperModule, + viewModelModule, + serviceModule, + repositoryModule, + packageManagerModule, + networkModule, + downloaderModule + ) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/SplashScreenActivity.kt b/app/src/main/java/com/vanced/manager/SplashScreenActivity.kt new file mode 100644 index 0000000000..d9e9868c1c --- /dev/null +++ b/app/src/main/java/com/vanced/manager/SplashScreenActivity.kt @@ -0,0 +1,17 @@ +package com.vanced.manager + +import android.content.Intent +import android.os.Bundle +import androidx.activity.ComponentActivity + +class SplashScreenActivity : ComponentActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + startActivity( + Intent(this, MainActivity::class.java) + ) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/adapter/ExpandableAppListAdapter.kt b/app/src/main/java/com/vanced/manager/adapter/ExpandableAppListAdapter.kt deleted file mode 100644 index 5ffb03fb49..0000000000 --- a/app/src/main/java/com/vanced/manager/adapter/ExpandableAppListAdapter.kt +++ /dev/null @@ -1,199 +0,0 @@ -package com.vanced.manager.adapter - -import android.animation.ValueAnimator -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.ImageView -import androidx.core.animation.addListener -import androidx.core.view.isGone -import androidx.core.view.isVisible -import androidx.core.view.updateLayoutParams -import androidx.fragment.app.FragmentActivity -import androidx.preference.PreferenceManager.getDefaultSharedPreferences -import androidx.recyclerview.widget.RecyclerView -import com.google.android.material.card.MaterialCardView -import com.vanced.manager.R -import com.vanced.manager.databinding.ViewAppExpandableBinding -import com.vanced.manager.model.ButtonTag -import com.vanced.manager.model.DataModel -import com.vanced.manager.ui.dialogs.AppInfoDialog -import com.vanced.manager.ui.dialogs.AppUninstallDialog -import com.vanced.manager.ui.viewmodels.HomeViewModel -import com.vanced.manager.utils.* - -class ExpandableAppListAdapter( - private val activity: FragmentActivity, - private val viewModel: HomeViewModel -) : RecyclerView.Adapter() { - - private val apps = mutableListOf() - private val dataModels = mutableListOf() - private val prefs = getDefaultSharedPreferences(activity) - - private val isRoot = prefs.managerVariant == "root" - - private var isAnimationRunning = false - - inner class ListViewHolder(private val binding: ViewAppExpandableBinding) : - RecyclerView.ViewHolder(binding.root) { - private var isExpanded = false - - fun bind(position: Int) { - val dataModel = dataModels[position] - with(binding) { - appTitle.text = dataModel?.appName - appDescription.text = dataModel?.appDescription - dataModel?.appIcon?.let { appIcon.setImageResource(it) } - appClickableLayout.setOnClickListener { - if (isAnimationRunning) return@setOnClickListener - val rootHeight = root.measuredHeight - val expandedViewHeight = appExpandedView.height - val expandedTranslation = appClickableLayout.height.toFloat() - - when (isExpanded.also { isExpanded = !isExpanded }) { - true -> { - appExpandedView.toggle(0f, 0.8f, -expandedTranslation) - root.toggleCard(rootHeight - expandedViewHeight) - appExpandArrow.rotateArrow(90f) - } - false -> { - root.toggleCard(rootHeight + expandedViewHeight) - appExpandedView.toggle(1f, 1f, expandedTranslation) - appExpandArrow.rotateArrow(-90f) - } - } - } - appUninstall.setOnClickListener { - AppUninstallDialog.newInstance(apps[position]).show(activity.supportFragmentManager, null) - } - appLaunch.setOnClickListener { - viewModel.launchApp(apps[position], isRoot) - } - appInfo.setOnClickListener { - AppInfoDialog.newInstance( - appName = apps[position], - appIcon = dataModel?.appIcon, - changelog = dataModel?.changelog?.value - ).show(activity.supportFragmentManager, "info") - } - dataModel?.buttonTag?.observe(activity) { buttonTag -> - appDownload.apply { - setOnClickListener { - viewModel.openInstallDialog( - buttonTag, - apps[position] - ) - } - contentDescription = activity.getString( - when (buttonTag) { - ButtonTag.UPDATE -> R.string.accessibility_update - ButtonTag.REINSTALL -> R.string.accessibility_reinstall - else -> R.string.accessibility_download - } - ) - } - } - dataModel?.isAppInstalled?.observe(activity) { - appUninstall.isVisible = it - appLaunch.isVisible = it - } - dataModel?.versionName?.observe(activity) { - appVersionLatest.text = it - appDownload.isGone = it == activity.getString(R.string.unavailable) - } - dataModel?.installedVersionName?.observe(activity) { - appVersionInstalled.text = it - } - dataModel?.buttonImage?.observe(activity) { - if (it != null) { - appDownload.icon = it - } - } - } - } - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListViewHolder { - val view = ViewAppExpandableBinding.inflate(LayoutInflater.from(activity), parent, false) - return ListViewHolder(view) - } - - override fun onBindViewHolder(holder: ListViewHolder, position: Int) { - holder.bind(position) - } - - override fun getItemCount(): Int = apps.size - - private fun ImageView.rotateArrow(degrees: Float) { - animate().apply { - duration = animationDuration - rotation(degrees) - } - } - - private fun View.toggle( - alpha: Float, - scale: Float, - translation: Float - ) { - animate().apply { - duration = animationDuration - scaleX(scale) - scaleY(scale) - alpha(alpha) - translationYBy(translation) - } - } - - private fun MaterialCardView.toggleCard(resultHeight: Int) { - ValueAnimator.ofInt(measuredHeight, resultHeight).apply { - duration = animationDuration - addUpdateListener { value -> - updateLayoutParams { - height = value.animatedValue as Int - } - } - addListener( - onStart = { - isAnimationRunning = true - }, - onEnd = { - isAnimationRunning = false - } - ) - }.start() - } - - init { - - if (prefs.enableVanced) { - if (isRoot) { - dataModels.add(viewModel.vancedRootModel.value) - } else { - dataModels.add(viewModel.vancedModel.value) - } - apps.add(activity.getString(R.string.vanced)) - } - - if (prefs.enableMusic) { - if (isRoot) { - dataModels.add(viewModel.musicRootModel.value) - } else { - dataModels.add(viewModel.musicModel.value) - } - apps.add(activity.getString(R.string.music)) - } - - if (!isRoot) { - dataModels.add(viewModel.microgModel.value) - apps.add(activity.getString(R.string.microg)) - } - - } - - companion object { - const val animationDuration = 250L - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/adapter/GetNotifAdapter.kt b/app/src/main/java/com/vanced/manager/adapter/GetNotifAdapter.kt deleted file mode 100644 index 7defd83418..0000000000 --- a/app/src/main/java/com/vanced/manager/adapter/GetNotifAdapter.kt +++ /dev/null @@ -1,79 +0,0 @@ -package com.vanced.manager.adapter - -import android.content.Context -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import com.google.firebase.messaging.FirebaseMessaging -import com.vanced.manager.R -import com.vanced.manager.databinding.ViewNotificationSettingBinding -import com.vanced.manager.model.NotifModel -import com.vanced.manager.utils.defPrefs - -class GetNotifAdapter(private val context: Context) : - RecyclerView.Adapter() { - - private val prefs = context.defPrefs - - private val vanced = NotifModel( - "Vanced-Update", - context.getString(R.string.push_notifications, context.getString(R.string.vanced)), - context.getString(R.string.push_notifications_summary, context.getString(R.string.vanced)), - "vanced_notifs" - ) - private val music = NotifModel( - "Music-Update", - context.getString(R.string.push_notifications, context.getString(R.string.music)), - context.getString(R.string.push_notifications_summary, context.getString(R.string.music)), - "music_notifs" - ) - private val microg = NotifModel( - "MicroG-Update", - context.getString(R.string.push_notifications, context.getString(R.string.microg)), - context.getString(R.string.push_notifications_summary, context.getString(R.string.microg)), - "microg_notifs" - ) - - private val apps = arrayOf(vanced, music, microg) - - inner class GetNotifViewHolder(val binding: ViewNotificationSettingBinding) : - RecyclerView.ViewHolder(binding.root) { - val switch = binding.notifSwitch - fun bind(position: Int) { - val app = apps[position] - with(binding.notifSwitch) { - setKey(app.key) - setSummary(app.switchSummary) - setTitle(app.switchTitle) - setDefaultValue(true) - with(prefs) { - setChecked( - getBoolean( - "enable_" + app.key.substringBefore("_"), - true - ) && getBoolean(app.key, true) - ) - } - } - } - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GetNotifViewHolder { - val view = - ViewNotificationSettingBinding.inflate(LayoutInflater.from(context), parent, false) - return GetNotifViewHolder(view) - } - - override fun onBindViewHolder(holder: GetNotifViewHolder, position: Int) { - holder.bind(position) - holder.switch.setOnCheckedListener { _, isChecked -> - when (isChecked) { - true -> FirebaseMessaging.getInstance().subscribeToTopic(apps[position].topic) - false -> FirebaseMessaging.getInstance().unsubscribeFromTopic(apps[position].topic) - } - } - } - - override fun getItemCount(): Int = 3 - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/adapter/LinkAdapter.kt b/app/src/main/java/com/vanced/manager/adapter/LinkAdapter.kt deleted file mode 100644 index a123965d85..0000000000 --- a/app/src/main/java/com/vanced/manager/adapter/LinkAdapter.kt +++ /dev/null @@ -1,95 +0,0 @@ -package com.vanced.manager.adapter - -import android.content.Context -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.appcompat.content.res.AppCompatResources -import androidx.recyclerview.widget.RecyclerView -import com.vanced.manager.R -import com.vanced.manager.databinding.ViewSocialLinkBinding -import com.vanced.manager.model.LinkModel -import com.vanced.manager.ui.viewmodels.HomeViewModel - -class LinkAdapter( - private val context: Context, - private val viewModel: HomeViewModel -) : RecyclerView.Adapter() { - - private val instagram = LinkModel( - AppCompatResources.getDrawable(context, R.drawable.ic_instagram), - INSTAGRAM - ) - - private val youtube = LinkModel( - AppCompatResources.getDrawable(context, R.drawable.ic_youtube), - YOUTUBE - ) - - private val github = LinkModel( - AppCompatResources.getDrawable(context, R.drawable.ic_github), - GITHUB - ) - - private val website = LinkModel( - AppCompatResources.getDrawable(context, R.drawable.ic_website), - WEBSITE - ) - - private val telegram = LinkModel( - AppCompatResources.getDrawable(context, R.drawable.ic_telegram), - TELEGRAM - ) - - private val twitter = LinkModel( - AppCompatResources.getDrawable(context, R.drawable.ic_twitter), - TWITTER - ) - - private val discord = LinkModel( - AppCompatResources.getDrawable(context, R.drawable.ic_discord), - DISCORD - ) - - private val reddit = LinkModel( - AppCompatResources.getDrawable(context, R.drawable.ic_reddit), - REDDIT - ) - - val links = arrayOf(instagram, youtube, github, website, telegram, twitter, discord, reddit) - - inner class LinkViewHolder(private val binding: ViewSocialLinkBinding) : - RecyclerView.ViewHolder(binding.root) { - - val logo = binding.linkImage - - fun bind(position: Int) { - binding.linkBg.setOnClickListener { - viewModel.openUrl(links[position].linkUrl) - } - } - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LinkViewHolder { - val view = ViewSocialLinkBinding.inflate(LayoutInflater.from(context), parent, false) - return LinkViewHolder(view) - } - - override fun onBindViewHolder(holder: LinkViewHolder, position: Int) { - holder.bind(position) - holder.logo.setImageDrawable(links[position].linkIcon) - } - - override fun getItemCount(): Int = links.size - - companion object { - const val INSTAGRAM = "https://instagram.com/vanced.youtube" - const val YOUTUBE = "https://youtube.com/c/YouTubeVanced" - const val GITHUB = "https://github.com/YTVanced/VancedManager" - const val WEBSITE = "https://vancedapp.com" - const val TELEGRAM = "https://t.me/joinchat/AAAAAEHf-pi4jH1SDlAL4w" - const val TWITTER = "https://twitter.com/YTVanced" - const val DISCORD = "https://discord.gg/WCGNdRruzb" - const val REDDIT = "https://www.reddit.com/r/Vanced/" - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/adapter/SelectAppsAdapter.kt b/app/src/main/java/com/vanced/manager/adapter/SelectAppsAdapter.kt deleted file mode 100644 index b4dbac9ef8..0000000000 --- a/app/src/main/java/com/vanced/manager/adapter/SelectAppsAdapter.kt +++ /dev/null @@ -1,60 +0,0 @@ -package com.vanced.manager.adapter - -import android.content.Context -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.preference.PreferenceManager.getDefaultSharedPreferences -import androidx.recyclerview.widget.RecyclerView -import com.vanced.manager.R -import com.vanced.manager.databinding.ViewAppCheckboxBinding -import com.vanced.manager.model.SelectAppModel -import com.vanced.manager.utils.enableMusic -import com.vanced.manager.utils.enableVanced - -class SelectAppsAdapter(private val context: Context) : - RecyclerView.Adapter() { - - private val prefs by lazy { getDefaultSharedPreferences(context) } - - private val vanced = SelectAppModel( - context.getString(R.string.vanced), - context.getString(R.string.description_vanced), - "vanced", - prefs.enableVanced - ) - - private val music = SelectAppModel( - context.getString(R.string.music), - context.getString(R.string.description_vanced_music), - "music", - prefs.enableMusic - ) - - val apps = arrayOf(vanced, music) - - inner class SelectAppsViewHolder(binding: ViewAppCheckboxBinding) : - RecyclerView.ViewHolder(binding.root) { - val appName = binding.appCheckboxText - val appDescription = binding.appCheckboxDescription - val appCard = binding.appCheckboxBg - val checkbox = binding.appCheckbox - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SelectAppsViewHolder { - val view = ViewAppCheckboxBinding.inflate(LayoutInflater.from(context), parent, false) - return SelectAppsViewHolder(view) - } - - override fun onBindViewHolder(holder: SelectAppsViewHolder, position: Int) { - holder.appName.text = apps[position].appName - holder.appDescription.text = apps[position].appDescription - holder.checkbox.isChecked = apps[position].isChecked - holder.appCard.setOnClickListener { - holder.checkbox.isChecked = !holder.checkbox.isChecked - apps[position].isChecked = !apps[position].isChecked - } - } - - override fun getItemCount(): Int = 2 - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/adapter/SponsorAdapter.kt b/app/src/main/java/com/vanced/manager/adapter/SponsorAdapter.kt deleted file mode 100644 index b93bc5f83b..0000000000 --- a/app/src/main/java/com/vanced/manager/adapter/SponsorAdapter.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.vanced.manager.adapter - -import android.content.Context -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.appcompat.content.res.AppCompatResources -import androidx.recyclerview.widget.RecyclerView -import com.vanced.manager.R -import com.vanced.manager.databinding.ViewSponsorBinding -import com.vanced.manager.model.SponsorModel -import com.vanced.manager.ui.viewmodels.HomeViewModel -import com.vanced.manager.utils.LIGHT -import com.vanced.manager.utils.currentTheme - -class SponsorAdapter( - private val context: Context, - private val viewModel: HomeViewModel -) : RecyclerView.Adapter() { - - private val brave = SponsorModel( - if (currentTheme == LIGHT) AppCompatResources.getDrawable( - context, - R.drawable.ic_brave_light - ) else AppCompatResources.getDrawable(context, R.drawable.ic_brave), - "Brave", - BRAVE - ) - - private val adguard = SponsorModel( - AppCompatResources.getDrawable(context, R.drawable.ic_adguard), - "AdGuard", - ADGUARD - ) - - val sponsors = arrayListOf(brave, adguard) - - inner class LinkViewHolder(private val binding: ViewSponsorBinding) : RecyclerView.ViewHolder( - binding.root - ) { - val logo = binding.sponsorLogo - fun bind(position: Int) { - with(binding) { - sponsorName.text = sponsors[position].name - cardSponsor.setOnClickListener { - viewModel.openUrl(sponsors[position].url) - } - } - } - } - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): LinkViewHolder { - val view = ViewSponsorBinding.inflate(LayoutInflater.from(context), parent, false) - return LinkViewHolder(view) - } - - override fun onBindViewHolder(holder: LinkViewHolder, position: Int) { - holder.bind(position) - holder.logo.setImageDrawable(sponsors[position].logo) - } - - override fun getItemCount(): Int = 2 - - companion object { - const val BRAVE = "https://vancedapp.com/brave" - const val ADGUARD = "https://adguard.com/?aid=31141&source=manager" - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/adapter/WelcomePageAdapter.kt b/app/src/main/java/com/vanced/manager/adapter/WelcomePageAdapter.kt deleted file mode 100644 index 40c1cab1f0..0000000000 --- a/app/src/main/java/com/vanced/manager/adapter/WelcomePageAdapter.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.vanced.manager.adapter - -import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentActivity -import androidx.viewpager2.adapter.FragmentStateAdapter -import com.vanced.manager.ui.fragments.GrantRootFragment -import com.vanced.manager.ui.fragments.SelectAppsFragment -import com.vanced.manager.ui.fragments.WelcomeFragment - -class WelcomePageAdapter(activity: FragmentActivity) : FragmentStateAdapter(activity) { - - override fun getItemCount(): Int = 3 - - override fun createFragment(position: Int): Fragment { - return when (position) { - 0 -> WelcomeFragment() - 1 -> SelectAppsFragment() - 2 -> GrantRootFragment() - else -> throw IllegalArgumentException("Unknown fragment") - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/App.kt b/app/src/main/java/com/vanced/manager/core/App.kt deleted file mode 100644 index 54cace32e3..0000000000 --- a/app/src/main/java/com/vanced/manager/core/App.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.vanced.manager.core - -import android.app.Application -import android.content.res.Configuration -import androidx.preference.PreferenceManager.getDefaultSharedPreferences -import com.crowdin.platform.Crowdin -import com.crowdin.platform.CrowdinConfig -import com.crowdin.platform.data.model.AuthConfig -import com.crowdin.platform.data.remote.NetworkType -import com.vanced.manager.BuildConfig.* -import com.vanced.manager.utils.AppUtils.log -import com.vanced.manager.utils.loadJson -import com.vanced.manager.utils.managerAccent -import com.vanced.manager.utils.mutableAccentColor -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.launch - -open class App : Application() { - - private val prefs by lazy { getDefaultSharedPreferences(this) } - private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO) - - override fun onCreate() { - scope.launch { loadJson(this@App) } - super.onCreate() - mutableAccentColor.value = prefs.managerAccent - Crowdin.init( - this, - CrowdinConfig.Builder().apply { - withDistributionHash(CROWDIN_HASH) - withNetworkType(NetworkType.WIFI) - if (ENABLE_CROWDIN_AUTH) { - if (prefs.getBoolean("crowdin_real_time", false)) - withRealTimeUpdates() - - withSourceLanguage("en") - withAuthConfig(AuthConfig(CROWDIN_CLIENT_ID, CROWDIN_CLIENT_SECRET, null)) - withScreenshotEnabled() - log("test", "crowdin credentials") - } - }.build() - ) - - if (prefs.getBoolean("crowdin_upload_screenshot", false)) - Crowdin.registerScreenShotContentObserver(this) - - } - - override fun onConfigurationChanged(newConfig: Configuration) { - super.onConfigurationChanged(newConfig) - Crowdin.onConfigurationChanged() - } -} diff --git a/app/src/main/java/com/vanced/manager/core/downloader/MicrogDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/MicrogDownloader.kt deleted file mode 100644 index 1095bfae73..0000000000 --- a/app/src/main/java/com/vanced/manager/core/downloader/MicrogDownloader.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.vanced.manager.core.downloader - -import android.content.Context -import com.vanced.manager.R -import com.vanced.manager.utils.* -import com.vanced.manager.utils.DownloadHelper.download -import com.vanced.manager.utils.PackageHelper.install - -object MicrogDownloader { - - private const val fileName = "microg.apk" - private const val folderName = "microg" - - fun downloadMicrog(context: Context) { - val url = microg.value?.string("url") ?: "" - download(url, "$baseInstallUrl/", folderName, fileName, context, onDownloadComplete = { - startMicrogInstall(context) - }, onError = { - downloadingFile.postValue(context.getString(R.string.error_downloading, fileName)) - }) - - } - - fun startMicrogInstall(context: Context) { - installing.postValue(true) - postReset() - install("${context.getExternalFilesDir(folderName)}/$fileName", context) - } -} diff --git a/app/src/main/java/com/vanced/manager/core/downloader/MusicDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/MusicDownloader.kt deleted file mode 100644 index 6b3eea09f3..0000000000 --- a/app/src/main/java/com/vanced/manager/core/downloader/MusicDownloader.kt +++ /dev/null @@ -1,87 +0,0 @@ -package com.vanced.manager.core.downloader - -import android.content.Context -import com.vanced.manager.R -import com.vanced.manager.utils.* -import com.vanced.manager.utils.AppUtils.musicRootPkg -import com.vanced.manager.utils.AppUtils.validateTheme -import com.vanced.manager.utils.DownloadHelper.download -import com.vanced.manager.utils.PackageHelper.downloadStockCheck -import com.vanced.manager.utils.PackageHelper.install -import com.vanced.manager.utils.PackageHelper.installMusicRoot - -object MusicDownloader { - - private var variant: String? = null - private var musicVersion: String? = null - private var versionCode: Int? = null - private var baseurl = "" - private var folderName: String? = null - private var downloadPath: String? = null - private var hashUrl: String? = null - - fun downloadMusic(context: Context, version: String? = null) { - val prefs = context.defPrefs - musicVersion = version ?: prefs.musicVersion?.getLatestAppVersion( - musicVersions.value?.value ?: listOf("") - ) - versionCode = music.value?.int("versionCode") - variant = prefs.managerVariant - baseurl = "$baseInstallUrl/music/v$musicVersion" - folderName = "music/$variant" - downloadPath = context.getExternalFilesDir(folderName)?.path - hashUrl = "$baseurl/hash.json" - - downloadApk(context) - } - - private fun downloadApk(context: Context, apk: String = "music") { - val url = if (apk == "stock") "$baseurl/stock/${getArch()}.apk" else "$baseurl/$variant.apk" - download( - url, - "$baseurl/", - folderName!!, - getFileNameFromUrl(url), - context, - onDownloadComplete = { - if (variant == "root" && apk != "stock") { - downloadApk(context, "stock") - return@download - } - - when (apk) { - "music" -> { - if (variant == "root") { - if (validateTheme(downloadPath!!, "root", hashUrl!!, context)) { - if (downloadStockCheck(musicRootPkg, versionCode!!, context)) - downloadApk(context, "stock") - else - startMusicInstall(context) - } else { - downloadApk(context, apk) - } - } else - startMusicInstall(context) - } - "stock" -> startMusicInstall(context) - } - }, - onError = { - downloadingFile.postValue( - context.getString( - R.string.error_downloading, - getFileNameFromUrl(url) - ) - ) - }) - } - - fun startMusicInstall(context: Context) { - installing.postValue(true) - postReset() - if (variant == "root") - installMusicRoot(context) - else - install("${context.getExternalFilesDir("music/nonroot")}/nonroot.apk", context) - } -} diff --git a/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloader.kt deleted file mode 100644 index 1114e39012..0000000000 --- a/app/src/main/java/com/vanced/manager/core/downloader/VancedDownloader.kt +++ /dev/null @@ -1,149 +0,0 @@ -package com.vanced.manager.core.downloader - -import android.content.Context -import android.content.SharedPreferences -import com.google.firebase.analytics.FirebaseAnalytics -import com.google.firebase.analytics.ktx.logEvent -import com.vanced.manager.R -import com.vanced.manager.utils.* -import com.vanced.manager.utils.AppUtils.log -import com.vanced.manager.utils.AppUtils.validateTheme -import com.vanced.manager.utils.AppUtils.vancedRootPkg -import com.vanced.manager.utils.DownloadHelper.download -import com.vanced.manager.utils.PackageHelper.downloadStockCheck -import com.vanced.manager.utils.PackageHelper.installSplitApkFiles -import com.vanced.manager.utils.PackageHelper.installVancedRoot -import java.io.File - -object VancedDownloader { - - private lateinit var prefs: SharedPreferences - private lateinit var defPrefs: SharedPreferences - private lateinit var arch: String - private var variant: String? = null - private var theme: String? = null - private var lang = mutableListOf() - - private lateinit var themePath: String - - private var count: Int = 0 - private var succesfulLangCount: Int = 0 - private var hashUrl = "" - - private var vancedVersionCode = 0 - private var vancedVersion: String? = null - - private var downloadPath: String? = null - private var folderName: String? = null - - fun downloadVanced(context: Context, version: String?) { - defPrefs = context.defPrefs - prefs = context.installPrefs - variant = defPrefs.managerVariant - folderName = "vanced/$variant" - downloadPath = context.getExternalFilesDir(folderName)?.path - File(downloadPath.toString()).deleteRecursively() - prefs.lang?.let { - lang = it.split(", ").toMutableList() - } - theme = prefs.theme - vancedVersion = version ?: defPrefs.vancedVersion?.getLatestAppVersion( - vancedVersions.value?.value ?: listOf("") - ) - themePath = "$baseInstallUrl/apks/v$vancedVersion/$variant/Theme" - hashUrl = "apks/v$vancedVersion/$variant/Theme/hash.json" - arch = getArch() - count = 0 - - vancedVersionCode = vanced.value?.int("versionCode") ?: 0 - try { - downloadSplits(context) - } catch (e: Exception) { - log("VMDownloader", e.stackTraceToString()) - downloadingFile.postValue(context.getString(R.string.error_downloading, "Vanced")) - } - - } - - private fun downloadSplits(context: Context, type: String = "theme") { - val url = when (type) { - "theme" -> "$themePath/$theme.apk" - "arch" -> "$baseInstallUrl/apks/v$vancedVersion/$variant/Arch/split_config.$arch.apk" - "stock" -> "$themePath/stock.apk" - "dpi" -> "$themePath/dpi.apk" - "lang" -> "$baseInstallUrl/apks/v$vancedVersion/$variant/Language/split_config.${lang[count]}.apk" - else -> throw NotImplementedError("This type of APK is NOT valid. What the hell did you even do?") - } - - download( - url, - "$baseInstallUrl/", - folderName!!, - getFileNameFromUrl(url), - context, - onDownloadComplete = { - when (type) { - "theme" -> - if (variant == "root") { - if (validateTheme(downloadPath!!, theme!!, hashUrl, context)) { - if (downloadStockCheck(vancedRootPkg, vancedVersionCode, context)) - downloadSplits(context, "arch") - else - startVancedInstall(context) - } else - downloadSplits(context, "theme") - } else - downloadSplits(context, "arch") - "arch" -> if (variant == "root") downloadSplits( - context, - "stock" - ) else downloadSplits(context, "lang") - "stock" -> downloadSplits(context, "dpi") - "dpi" -> downloadSplits(context, "lang") - "lang" -> { - count++ - succesfulLangCount++ - if (count < lang.size) - downloadSplits(context, "lang") - else - startVancedInstall(context) - } - - } - }, - onError = { - if (type == "lang") { - count++ - when { - count < lang.size -> downloadSplits(context, "lang") - succesfulLangCount == 0 -> { - lang.add("en") - downloadSplits(context, "lang") - } - else -> startVancedInstall(context) - } - - } else { - downloadingFile.postValue( - context.getString( - R.string.error_downloading, - getFileNameFromUrl(url) - ) - ) - } - }) - } - - fun startVancedInstall(context: Context, variant: String? = this.variant) { - installing.postValue(true) - postReset() - FirebaseAnalytics.getInstance(context).logEvent(FirebaseAnalytics.Event.SELECT_ITEM) { - variant?.let { param("vanced_variant", it) } - theme?.let { param("vanced_theme", it) } - } - if (variant == "root") - installVancedRoot(context) - else - installSplitApkFiles(context, "vanced") - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/firebase/CloudMessaging.kt b/app/src/main/java/com/vanced/manager/core/firebase/CloudMessaging.kt deleted file mode 100644 index 3870321cde..0000000000 --- a/app/src/main/java/com/vanced/manager/core/firebase/CloudMessaging.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.vanced.manager.core.firebase - -import com.google.firebase.messaging.FirebaseMessagingService -import com.vanced.manager.utils.AppUtils.log - -class CloudMessaging : FirebaseMessagingService() { - - override fun onNewToken(p0: String) { - log("VMC", "Generated new token: $p0") - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/installer/AppInstallerService.kt b/app/src/main/java/com/vanced/manager/core/installer/AppInstallerService.kt deleted file mode 100644 index df363d889a..0000000000 --- a/app/src/main/java/com/vanced/manager/core/installer/AppInstallerService.kt +++ /dev/null @@ -1,50 +0,0 @@ -package com.vanced.manager.core.installer - -import android.app.Service -import android.content.Intent -import android.content.pm.PackageInstaller -import android.os.IBinder -import com.vanced.manager.utils.AppUtils.log -import com.vanced.manager.utils.AppUtils.sendCloseDialog -import com.vanced.manager.utils.AppUtils.sendFailure -import com.vanced.manager.utils.AppUtils.sendRefresh - -class AppInstallerService : Service() { - - override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { - when (intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -999)) { - PackageInstaller.STATUS_PENDING_USER_ACTION -> { - log(TAG, "Requesting user confirmation for installation") - val confirmationIntent = intent.getParcelableExtra(Intent.EXTRA_INTENT) - confirmationIntent?.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - try { - startActivity(confirmationIntent) - } catch (e: Exception) { - log("VMInstall", "Unable to start installation") - } - } - PackageInstaller.STATUS_SUCCESS -> { - log(TAG, "Installation succeed") - sendCloseDialog(this) - sendRefresh(this) - } - else -> { - sendCloseDialog(this) - intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE)?.let { - sendFailure(it, this) - } - } - } - stopSelf() - return START_NOT_STICKY - } - - override fun onBind(intent: Intent?): IBinder? { - return null - } - - companion object { - const val TAG = "VMInstall" - } - -} diff --git a/app/src/main/java/com/vanced/manager/core/installer/AppUninstallerService.kt b/app/src/main/java/com/vanced/manager/core/installer/AppUninstallerService.kt deleted file mode 100644 index 54d2d282a5..0000000000 --- a/app/src/main/java/com/vanced/manager/core/installer/AppUninstallerService.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.vanced.manager.core.installer - -import android.app.Service -import android.content.Intent -import android.content.pm.PackageInstaller -import android.os.IBinder -import com.vanced.manager.utils.AppUtils.log -import com.vanced.manager.utils.AppUtils.sendRefresh - -class AppUninstallerService : Service() { - - override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { - val pkgName = intent?.getStringExtra("pkg") - when (intent?.getIntExtra(PackageInstaller.EXTRA_STATUS, -999)) { - PackageInstaller.STATUS_PENDING_USER_ACTION -> { - log(AppInstallerService.TAG, "Requesting user confirmation for uninstallation") - val confirmationIntent = intent.getParcelableExtra(Intent.EXTRA_INTENT) - confirmationIntent?.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - try { - startActivity(confirmationIntent) - } catch (e: Exception) { - } - } - //Delay broadcast until activity (and fragment) show up on the screen - PackageInstaller.STATUS_SUCCESS -> { - sendRefresh(this) - log("VMpm", "Successfully uninstalled $pkgName") - } - PackageInstaller.STATUS_FAILURE -> { - sendRefresh(this) - log("VMpm", "Failed to uninstall $pkgName") - } - } - stopSelf() - return START_NOT_STICKY - } - - override fun onBind(intent: Intent?): IBinder? { - return null - } - -} diff --git a/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt b/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt new file mode 100644 index 0000000000..e359bcbea0 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt @@ -0,0 +1,29 @@ +package com.vanced.manager.di + +import com.vanced.manager.downloader.impl.VancedDownloader +import com.vanced.manager.downloader.api.VancedAPI +import com.vanced.manager.network.util.baseUrl +import okhttp3.OkHttpClient +import org.koin.dsl.module +import retrofit2.Retrofit + +val downloaderModule = module { + + fun provideVancedAPI( + okHttpClient: OkHttpClient + ): VancedAPI = Retrofit.Builder() + .baseUrl(baseUrl) + .client(okHttpClient) + .build() + .create(VancedAPI::class.java) + + fun provideVancedDownloader( + vancedAPI: VancedAPI + ): VancedDownloader = VancedDownloader( + vancedAPI = vancedAPI + ) + + single { provideVancedAPI(get()) } + single { provideVancedDownloader(get()) } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/MapperModule.kt b/app/src/main/java/com/vanced/manager/di/MapperModule.kt new file mode 100644 index 0000000000..c1a97ea882 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/di/MapperModule.kt @@ -0,0 +1,28 @@ +package com.vanced.manager.di + +import com.vanced.manager.domain.datasource.PackageInformationDataSource +import com.vanced.manager.downloader.impl.VancedDownloader +import com.vanced.manager.network.model.AppDtoMapper +import com.vanced.manager.network.model.JsonDtoMapper +import org.koin.dsl.module + +val mapperModule = module { + + fun provideAppMapper( + packageInformationDataSource: PackageInformationDataSource, + vancedDownloader: VancedDownloader, + ): AppDtoMapper = AppDtoMapper( + packageInformationDataSource = packageInformationDataSource, + vancedDownloader = vancedDownloader + ) + + fun provideJsonMapper( + appDtoMapper: AppDtoMapper + ): JsonDtoMapper = JsonDtoMapper( + appDtoMapper = appDtoMapper + ) + + single { provideAppMapper(get(), get()) } + single { provideJsonMapper(get()) } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/NetworkModule.kt b/app/src/main/java/com/vanced/manager/di/NetworkModule.kt new file mode 100644 index 0000000000..83d42ce241 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/di/NetworkModule.kt @@ -0,0 +1,12 @@ +package com.vanced.manager.di + +import okhttp3.OkHttpClient +import org.koin.dsl.module + +val networkModule = module { + fun provideOkHttpClient(): OkHttpClient { + return OkHttpClient() + } + + single { provideOkHttpClient() } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/PackageManagerModule.kt b/app/src/main/java/com/vanced/manager/di/PackageManagerModule.kt new file mode 100644 index 0000000000..4ea917b6d7 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/di/PackageManagerModule.kt @@ -0,0 +1,30 @@ +package com.vanced.manager.di + +import android.content.Context +import com.vanced.manager.domain.datasource.PackageInformationDataSource +import com.vanced.manager.domain.datasource.PackageInformationDataSourceImpl +import com.vanced.manager.domain.pkg.PkgManager +import com.vanced.manager.domain.pkg.PkgManagerImpl +import org.koin.dsl.module + +val packageManagerModule = module { + + fun providePackageManager( + context: Context + ): PkgManager { + return PkgManagerImpl( + packageManager = context.packageManager + ) + } + + fun providePackageInformationDataSource( + pkgManager: PkgManager + ): PackageInformationDataSource { + return PackageInformationDataSourceImpl( + pkgManager = pkgManager + ) + } + + single { providePackageManager(get()) } + single { providePackageInformationDataSource(get()) } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt b/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt new file mode 100644 index 0000000000..0eb7b01c67 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt @@ -0,0 +1,21 @@ +package com.vanced.manager.di + +import com.vanced.manager.network.JsonService +import com.vanced.manager.network.model.JsonDtoMapper +import com.vanced.manager.repository.JsonRepository +import com.vanced.manager.repository.JsonRepositoryImpl +import org.koin.dsl.module + +val repositoryModule = module { + + fun provideJsonRepository( + jsonService: JsonService, + jsonDtoMapper: JsonDtoMapper + ): JsonRepository = JsonRepositoryImpl( + jsonService, + jsonDtoMapper + ) + + single { provideJsonRepository(get(), get()) } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/ServiceModule.kt b/app/src/main/java/com/vanced/manager/di/ServiceModule.kt new file mode 100644 index 0000000000..4440b8f9ba --- /dev/null +++ b/app/src/main/java/com/vanced/manager/di/ServiceModule.kt @@ -0,0 +1,23 @@ +package com.vanced.manager.di + +import com.google.gson.GsonBuilder +import com.vanced.manager.network.JsonService +import com.vanced.manager.network.util.baseGithubUrl +import okhttp3.OkHttpClient +import org.koin.dsl.module +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory + +val serviceModule = module { + + fun provideRetrofitService(okHttpClient: OkHttpClient): JsonService = + Retrofit.Builder() + .baseUrl(baseGithubUrl) + .addConverterFactory(GsonConverterFactory.create(GsonBuilder().create())) + .client(okHttpClient) + .build() + .create(JsonService::class.java) + + single { provideRetrofitService(get()) } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt new file mode 100644 index 0000000000..849857f789 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt @@ -0,0 +1,9 @@ +package com.vanced.manager.di + +import com.vanced.manager.ui.viewmodel.HomeViewModel +import org.koin.androidx.viewmodel.dsl.viewModel +import org.koin.dsl.module + +val viewModelModule = module { + viewModel { HomeViewModel(get(), get()) } +} \ No newline at end of file diff --git a/feature-home/src/main/java/com/vanced/manager/feature/home/data/datasource/PkgIngormationDataSource.kt b/app/src/main/java/com/vanced/manager/domain/datasource/PackageInformationDataSource.kt similarity index 80% rename from feature-home/src/main/java/com/vanced/manager/feature/home/data/datasource/PkgIngormationDataSource.kt rename to app/src/main/java/com/vanced/manager/domain/datasource/PackageInformationDataSource.kt index 6d42798a0c..f0d1ec1679 100644 --- a/feature-home/src/main/java/com/vanced/manager/feature/home/data/datasource/PkgIngormationDataSource.kt +++ b/app/src/main/java/com/vanced/manager/domain/datasource/PackageInformationDataSource.kt @@ -1,20 +1,20 @@ -package com.vanced.manager.feature.home.data.datasource +package com.vanced.manager.domain.datasource import android.content.pm.PackageManager -import com.vanced.manager.feature.home.data.pkg.PkgManager +import com.vanced.manager.domain.pkg.PkgManager import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -interface PkgInformationDataSource { +interface PackageInformationDataSource { suspend fun getVersionCode(packageName: String): Int? suspend fun getVersionName(packageName: String): String? } -class PkgInformationDataSourceImpl( +class PackageInformationDataSourceImpl( private val pkgManager: PkgManager -) : PkgInformationDataSource { +) : PackageInformationDataSource { override suspend fun getVersionCode(packageName: String): Int? = withContext(Dispatchers.IO) { diff --git a/app/src/main/java/com/vanced/manager/domain/model/App.kt b/app/src/main/java/com/vanced/manager/domain/model/App.kt new file mode 100644 index 0000000000..b1b8beccfb --- /dev/null +++ b/app/src/main/java/com/vanced/manager/domain/model/App.kt @@ -0,0 +1,23 @@ +package com.vanced.manager.domain.model + +import com.vanced.manager.downloader.base.BaseDownloader + +data class App( + val name: String? = null, + val remoteVersion: String? = null, + val remoteVersionCode: Int? = null, + val installedVersion: String? = null, + val installedVersionCode: Int? = null, + val installedVersionRoot: String? = null, + val installedVersionCodeRoot: Int? = null, + val iconUrl: String? = "", + val appStatus: AppStatus = AppStatus.Install, + val appStatusRoot: AppStatus = AppStatus.Install, + val packageName: String? = null, + val packageNameRoot: String? = null, + val changelog: String? = null, + val url: String? = null, + val themes: List? = null, + val languages: List? = null, + val downloader: BaseDownloader? = null +) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/domain/model/AppStatus.kt b/app/src/main/java/com/vanced/manager/domain/model/AppStatus.kt new file mode 100644 index 0000000000..e0ef6e978c --- /dev/null +++ b/app/src/main/java/com/vanced/manager/domain/model/AppStatus.kt @@ -0,0 +1,9 @@ +package com.vanced.manager.domain.model + +enum class AppStatus { + + Install, + Reinstall, + Update, + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/domain/model/Json.kt b/app/src/main/java/com/vanced/manager/domain/model/Json.kt new file mode 100644 index 0000000000..ad1d20e139 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/domain/model/Json.kt @@ -0,0 +1,9 @@ +package com.vanced.manager.domain.model + +data class Json( + val isMicrogBroken: Boolean, + val manager: App, + val vanced: App, + val music: App, + val microg: App +) diff --git a/app/src/main/java/com/vanced/manager/domain/model/Link.kt b/app/src/main/java/com/vanced/manager/domain/model/Link.kt new file mode 100644 index 0000000000..182e0d57dc --- /dev/null +++ b/app/src/main/java/com/vanced/manager/domain/model/Link.kt @@ -0,0 +1,5 @@ +package com.vanced.manager.domain.model + +data class Link( + val title: String +) diff --git a/feature-home/src/main/java/com/vanced/manager/feature/home/data/pkg/PkgManager.kt b/app/src/main/java/com/vanced/manager/domain/pkg/PkgManager.kt similarity index 96% rename from feature-home/src/main/java/com/vanced/manager/feature/home/data/pkg/PkgManager.kt rename to app/src/main/java/com/vanced/manager/domain/pkg/PkgManager.kt index 4b1da006a0..076a48c676 100644 --- a/feature-home/src/main/java/com/vanced/manager/feature/home/data/pkg/PkgManager.kt +++ b/app/src/main/java/com/vanced/manager/domain/pkg/PkgManager.kt @@ -1,9 +1,8 @@ -package com.vanced.manager.feature.home.data.pkg +package com.vanced.manager.domain.pkg import android.content.pm.PackageManager import android.os.Build - interface PkgManager { @Throws(PackageManager.NameNotFoundException::class) diff --git a/app/src/main/java/com/vanced/manager/domain/util/EntityMapper.kt b/app/src/main/java/com/vanced/manager/domain/util/EntityMapper.kt new file mode 100644 index 0000000000..bd8bf88c42 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/domain/util/EntityMapper.kt @@ -0,0 +1,9 @@ +package com.vanced.manager.domain.util + +interface EntityMapper { + + suspend fun mapToModel(entity: T): Model + + suspend fun mapFromModel(model: Model): T + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt b/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt new file mode 100644 index 0000000000..c6749f7cd1 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt @@ -0,0 +1,20 @@ +package com.vanced.manager.downloader.api + +import okhttp3.ResponseBody +import retrofit2.Call +import retrofit2.http.GET +import retrofit2.http.Path +import retrofit2.http.Streaming + +interface VancedAPI { + + @GET("apks/v{version}/{variant}/{type}/{apkName}.apk") + @Streaming + fun getApk( + @Path("version") version: String, + @Path("variant") variant: String, + @Path("type") type: String, + @Path("apkName") apkName: String, + ) : Call + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/base/BaseDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/base/BaseDownloader.kt new file mode 100644 index 0000000000..b431db7d46 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/downloader/base/BaseDownloader.kt @@ -0,0 +1,106 @@ +package com.vanced.manager.downloader.base + +import android.content.Context +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import com.vanced.manager.ui.composables.InstallationOption +import com.vanced.manager.util.log +import okhttp3.ResponseBody +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject +import retrofit2.Call +import retrofit2.awaitResponse +import java.io.* + +abstract class BaseDownloader( + private val appName: String +) : KoinComponent { + + var downloadProgress by mutableStateOf(0f) + private set + + var downloadFile by mutableStateOf("") + private set + + var installing by mutableStateOf(false) + + private lateinit var call: Call + + private val context: Context by inject() + + abstract suspend fun download() + + abstract val installationOptions: List + + private val tag = this::class.simpleName!! + + suspend fun downloadFile( + call: Call, + folderStructure: String, + fileName: String, + onError: (error: String) -> Unit = {}, + onComplete: suspend () -> Unit = {}, + ) { + fun error(errorBody: String) { + downloadFile = "Error downloading $fileName" + onError(errorBody) + log(tag, errorBody) + } + try { + this.call = call + val response = call.awaitResponse() + if (response.isSuccessful) { + val body = response.body() + if (body != null) { + if (writeFile(body, fileName, folderStructure)) { + onComplete() + } + } + } else { + val error = response.errorBody()?.toString() + if (error != null) { + error(error) + log(tag, error) + } + } + } catch (e: Exception) { + error(e.stackTraceToString()) + } + downloadProgress = 0f + } + + fun cancelDownload() { + call.cancel() + } + + private fun writeFile( + body: ResponseBody, + fileName: String, + folderStructure: String + ): Boolean { + val file = File("${context.getExternalFilesDir(appName)?.path}/$folderStructure/$fileName") + val inputStream = body.byteStream() + val outputStream = FileOutputStream(file) + return try { + val totalBytes = body.contentLength() + val fileReader = ByteArray(4096) + var downloadedBytes = 0L + var read: Int + while (inputStream.read(fileReader).also { read = it } != -1) { + outputStream.write(fileReader, 0, read) + downloadedBytes += read + downloadProgress = (downloadedBytes * 100 / totalBytes).toFloat() + } + true + } catch (e: IOException) { + false + } finally { + inputStream.close() + outputStream.close() + } + } + + + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt new file mode 100644 index 0000000000..84c9123f99 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt @@ -0,0 +1,15 @@ +package com.vanced.manager.downloader.impl + +import com.vanced.manager.downloader.base.BaseDownloader +import com.vanced.manager.ui.composables.InstallationOption + +object MicrogDownloader : BaseDownloader("") { + + override suspend fun download() { + + } + + override val installationOptions: List + get() = TODO("Not yet implemented") + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt new file mode 100644 index 0000000000..e7c9fc54be --- /dev/null +++ b/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt @@ -0,0 +1,15 @@ +package com.vanced.manager.downloader.impl + +import com.vanced.manager.downloader.base.BaseDownloader +import com.vanced.manager.ui.composables.InstallationOption + +object MusicDownloader : BaseDownloader("") { + + override suspend fun download() { + + } + + override val installationOptions: List + get() = TODO("Not yet implemented") + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt new file mode 100644 index 0000000000..873a1af2b7 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt @@ -0,0 +1,112 @@ +package com.vanced.manager.downloader.impl + +import com.vanced.manager.downloader.api.VancedAPI +import com.vanced.manager.downloader.base.BaseDownloader +import com.vanced.manager.ui.composables.InstallationOption +import com.vanced.manager.ui.composables.InstallationOptionKey + +class VancedDownloader( + private val vancedAPI: VancedAPI +) : BaseDownloader( + appName = "vanced" +) { + + private val themeInstallationOption = InstallationOption( + title = "Languages", + descriptionKey = InstallationOptionKey( + keyName = "vanced_languages", + keyDefaultValue = "en" + ) + ) { show, preference -> +// DialogRadioButtonPreference( +// preferenceTitle = "Language", +// preferenceKey = , +// defaultValue = , +// buttons = +// ) + } + + private val versionInstallationOption = InstallationOption( + title = "Languages", + descriptionKey = InstallationOptionKey( + keyName = "vanced_languages", + keyDefaultValue = "en" + ) + ) { show, preference -> +// DialogRadioButtonPreference( +// preferenceTitle = "Language", +// preferenceKey = , +// defaultValue = , +// buttons = +// ) + } + + private val languageInstallationOption = InstallationOption( + title = "Languages", + descriptionKey = InstallationOptionKey( + keyName = "vanced_languages", + keyDefaultValue = "en" + ) + ) { show, preference -> +// DialogRadioButtonPreference( +// preferenceTitle = "Language", +// preferenceKey = , +// defaultValue = , +// buttons = +// ) + } + + override val installationOptions: List get() = listOf( + languageInstallationOption + ) + + override suspend fun download() { + downloadTheme() + } + + private suspend fun downloadTheme() { + downloadFile( + vancedAPI.getApk( + version = "16.16.38", + variant = "nonroot", + type = "Theme", + apkName = "black.apk" + ), + folderStructure = "vanced/nonroot/v16.16.38", + fileName = "black.apk" + ) { + downloadArch() + } + } + + private suspend fun downloadArch() { + downloadFile( + vancedAPI.getApk( + version = "16.16.38", + variant = "nonroot", + type = "Arch", + apkName = "split_config.x86.apk" + ), + folderStructure = "vanced/nonroot/arch", + fileName = "black.apk" + ) { + downloadLanguage() + } + } + + private suspend fun downloadLanguage() { + downloadFile( + vancedAPI.getApk( + version = "16.16.38", + variant = "nonroot", + type = "Arch", + apkName = "split_config.x86.apk" + ), + folderStructure = "vanced/nonroot/lang", + fileName = "black.apk" + ) { + downloadLanguage() + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ext/RetrofitKotlin.kt b/app/src/main/java/com/vanced/manager/ext/RetrofitKotlin.kt new file mode 100644 index 0000000000..ff47605aa8 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ext/RetrofitKotlin.kt @@ -0,0 +1,24 @@ +package com.vanced.manager.ext + +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response + +fun Call.enqueue( + onResponse: (call: Call, response: Response) -> Unit, + onFailure: (call: Call, t: Throwable) -> Unit +) { + enqueue(object : Callback { + + override fun onResponse( + call: Call, + response: Response + ) = onResponse(call, response) + + override fun onFailure( + call: Call, + t: Throwable + ) = onFailure(call, t) + + }) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/installer/AppInstaller.kt b/app/src/main/java/com/vanced/manager/installer/AppInstaller.kt new file mode 100644 index 0000000000..b3ce353fd4 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/installer/AppInstaller.kt @@ -0,0 +1,31 @@ +package com.vanced.manager.installer + +import com.xinto.apkhelper.statusCallback +import com.xinto.apkhelper.statusCallbackBuilder +import com.vanced.manager.ui.viewmodel.HomeViewModel + +class AppInstaller( + private val viewModel: HomeViewModel +) { + + fun installVanced() { + + } + + fun installMusic() { + + } + + fun installMicrog() { + + } + + init { + statusCallback = statusCallbackBuilder( + onAction = { + viewModel.fetch() + } + ) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/model/AppListModel.kt b/app/src/main/java/com/vanced/manager/model/AppListModel.kt deleted file mode 100644 index b08928882c..0000000000 --- a/app/src/main/java/com/vanced/manager/model/AppListModel.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.vanced.manager.model - -import android.graphics.drawable.Drawable - -data class AppListModel( - val icon: Drawable?, - val appName: String?, - val remoteVersion: String?, - val installedVersion: String?, - val changelog: String?, - val pkg: String? -) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/model/AppVersionsModel.kt b/app/src/main/java/com/vanced/manager/model/AppVersionsModel.kt deleted file mode 100644 index 37e12d1fcd..0000000000 --- a/app/src/main/java/com/vanced/manager/model/AppVersionsModel.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.vanced.manager.model - -data class AppVersionsModel( - val version: String, - val value: String -) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/model/ButtonTag.kt b/app/src/main/java/com/vanced/manager/model/ButtonTag.kt deleted file mode 100644 index 602c50884f..0000000000 --- a/app/src/main/java/com/vanced/manager/model/ButtonTag.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.vanced.manager.model - -enum class ButtonTag { - INSTALL, UPDATE, REINSTALL -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/model/DataModel.kt b/app/src/main/java/com/vanced/manager/model/DataModel.kt deleted file mode 100644 index 64018dc75e..0000000000 --- a/app/src/main/java/com/vanced/manager/model/DataModel.kt +++ /dev/null @@ -1,110 +0,0 @@ -package com.vanced.manager.model - -import android.content.Context -import android.graphics.drawable.Drawable -import android.os.Build -import androidx.annotation.DrawableRes -import androidx.core.content.ContextCompat -import androidx.lifecycle.LifecycleOwner -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import com.beust.klaxon.JsonObject -import com.vanced.manager.R -import com.vanced.manager.utils.PackageHelper.isPackageInstalled - -open class DataModel( - private val jsonObject: LiveData, - private val context: Context, - lifecycleOwner: LifecycleOwner, - val appPkg: String, - val appName: String, - val appDescription: String, - @DrawableRes val appIcon: Int -) { - - private val versionCode = MutableLiveData() - private val installedVersionCode = MutableLiveData() - private val unavailable = context.getString(R.string.unavailable) - private val pm = context.packageManager - - val isAppInstalled = MutableLiveData() - val versionName = MutableLiveData() - val installedVersionName = MutableLiveData() - val buttonTag = MutableLiveData() - val buttonImage = MutableLiveData() - val changelog = MutableLiveData() - - private fun fetch() { - val jobj = jsonObject.value - isAppInstalled.value = isAppInstalled(appPkg) - versionCode.value = jobj?.int("versionCode") ?: 0 - versionName.value = jobj?.string("version") ?: unavailable - changelog.value = jobj?.string("changelog") ?: unavailable - } - - init { - fetch() - with(lifecycleOwner) { - jsonObject.observe(this) { - fetch() - } - isAppInstalled.observe(this) { - installedVersionCode.value = getPkgVersionCode(appPkg, it) - installedVersionName.value = getPkgVersionName(appPkg, it) - } - versionCode.observe(this) { versionCode -> - installedVersionCode.observe(this) { installedVersionCode -> - buttonTag.value = compareInt(installedVersionCode, versionCode) - buttonImage.value = compareIntDrawable(installedVersionCode, versionCode) - } - } - } - } - - open fun isAppInstalled(pkg: String): Boolean = isPackageInstalled(pkg, context.packageManager) - - private fun getPkgVersionName(pkg: String, isAppInstalled: Boolean): String { - return if (isAppInstalled) { - pm?.getPackageInfo(pkg, 0)?.versionName?.removeSuffix("-vanced") ?: unavailable - } else { - unavailable - } - } - - @Suppress("DEPRECATION") - private fun getPkgVersionCode(pkg: String, isAppInstalled: Boolean): Int { - return if (isAppInstalled) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) - pm?.getPackageInfo(pkg, 0)?.longVersionCode?.and(0xFFFFFFFF)?.toInt() ?: 0 - else - pm?.getPackageInfo(pkg, 0)?.versionCode ?: 0 - - } else { - 0 - } - } - - private fun compareInt(int1: Int?, int2: Int?): ButtonTag { - if (int2 != null && int1 != null) { - return when { - int1 == 0 -> ButtonTag.INSTALL - int2 > int1 -> ButtonTag.UPDATE - int1 >= int2 -> ButtonTag.REINSTALL - else -> ButtonTag.INSTALL - } - } - return ButtonTag.INSTALL - } - - private fun compareIntDrawable(int1: Int?, int2: Int?): Drawable { - if (int2 != null && int1 != null) { - return when { - int1 == 0 -> ContextCompat.getDrawable(context, R.drawable.ic_app_download)!! - int2 > int1 -> ContextCompat.getDrawable(context, R.drawable.ic_app_update)!! - int1 >= int2 -> ContextCompat.getDrawable(context, R.drawable.ic_app_reinstall)!! - else -> ContextCompat.getDrawable(context, R.drawable.ic_app_download)!! - } - } - return ContextCompat.getDrawable(context, R.drawable.ic_app_download)!! - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/model/LinkModel.kt b/app/src/main/java/com/vanced/manager/model/LinkModel.kt deleted file mode 100644 index 3c370ffa01..0000000000 --- a/app/src/main/java/com/vanced/manager/model/LinkModel.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.vanced.manager.model - -import android.graphics.drawable.Drawable - -data class LinkModel( - val linkIcon: Drawable?, - val linkUrl: String -) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/model/NotifModel.kt b/app/src/main/java/com/vanced/manager/model/NotifModel.kt deleted file mode 100644 index 1b302f4592..0000000000 --- a/app/src/main/java/com/vanced/manager/model/NotifModel.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.vanced.manager.model - -data class NotifModel( - val topic: String, - val switchTitle: String, - val switchSummary: String, - val key: String -) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/model/RootDataModel.kt b/app/src/main/java/com/vanced/manager/model/RootDataModel.kt deleted file mode 100644 index fc2cc4e898..0000000000 --- a/app/src/main/java/com/vanced/manager/model/RootDataModel.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.vanced.manager.model - -import android.content.Context -import androidx.annotation.DrawableRes -import androidx.lifecycle.LifecycleOwner -import androidx.lifecycle.LiveData -import com.beust.klaxon.JsonObject -import com.vanced.manager.utils.PackageHelper - -class RootDataModel( - jsonObject: LiveData, - context: Context, - lifecycleOwner: LifecycleOwner, - appPkg: String, - appName: String, - appDescription: String, - @DrawableRes appIcon: Int, - //BUG THIS! - //kotlin thinks that this value is null if we use - //private val scriptName: String - //Although it's impossible for it to be null. - //Ironic, isn't it? - private val scriptName: String? -) : DataModel( - jsonObject, context, lifecycleOwner, appPkg, appName, appDescription, appIcon -) { - - override fun isAppInstalled(pkg: String): Boolean { - //Adapt to nullable shit - return if (scriptName?.let { PackageHelper.scriptExists(it) } == true) { - super.isAppInstalled(appPkg) - } else { - false - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/model/SelectAppModel.kt b/app/src/main/java/com/vanced/manager/model/SelectAppModel.kt deleted file mode 100644 index 18117db126..0000000000 --- a/app/src/main/java/com/vanced/manager/model/SelectAppModel.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.vanced.manager.model - -data class SelectAppModel( - val appName: String, - val appDescription: String, - val tag: String, - var isChecked: Boolean -) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/model/SponsorModel.kt b/app/src/main/java/com/vanced/manager/model/SponsorModel.kt deleted file mode 100644 index 4468a3cdc8..0000000000 --- a/app/src/main/java/com/vanced/manager/model/SponsorModel.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.vanced.manager.model - -import android.graphics.drawable.Drawable - -data class SponsorModel( - val logo: Drawable?, - val name: String, - val url: String -) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/model/VancedPrefModel.kt b/app/src/main/java/com/vanced/manager/model/VancedPrefModel.kt deleted file mode 100644 index 4f155b433f..0000000000 --- a/app/src/main/java/com/vanced/manager/model/VancedPrefModel.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.vanced.manager.model - -data class VancedPrefModel( - val name: String, - val value: String -) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/JsonService.kt b/app/src/main/java/com/vanced/manager/network/JsonService.kt new file mode 100644 index 0000000000..48a8836376 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/network/JsonService.kt @@ -0,0 +1,11 @@ +package com.vanced.manager.network + +import com.vanced.manager.network.model.JsonDto +import retrofit2.http.GET + +interface JsonService { + + @GET("latest.json") + suspend fun get(): JsonDto + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDto.kt b/app/src/main/java/com/vanced/manager/network/model/AppDto.kt new file mode 100644 index 0000000000..eb39b3dbda --- /dev/null +++ b/app/src/main/java/com/vanced/manager/network/model/AppDto.kt @@ -0,0 +1,16 @@ +package com.vanced.manager.network.model + +import com.google.gson.annotations.SerializedName + +data class AppDto( + @SerializedName("name") val name: String? = null, + @SerializedName("version") val version: String? = null, + @SerializedName("versionCode") val versionCode: Int? = null, + @SerializedName("changelog") val changelog: String? = null, + @SerializedName("package_name") val packageName: String? = null, + @SerializedName("package_name_root") val packageNameRoot: String? = null, + @SerializedName("icon_url") val iconUrl: String? = null, + @SerializedName("url") val url: String? = null, + @SerializedName("themes") val themes: List? = null, + @SerializedName("languages") val languages: List? = null +) diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt new file mode 100644 index 0000000000..1d8d9ba40d --- /dev/null +++ b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt @@ -0,0 +1,81 @@ +package com.vanced.manager.network.model + +import com.vanced.manager.domain.datasource.PackageInformationDataSource +import com.vanced.manager.domain.model.App +import com.vanced.manager.domain.model.AppStatus +import com.vanced.manager.domain.util.EntityMapper +import com.vanced.manager.downloader.base.BaseDownloader +import com.vanced.manager.downloader.impl.MicrogDownloader +import com.vanced.manager.downloader.impl.MusicDownloader +import com.vanced.manager.downloader.impl.VancedDownloader +import com.vanced.manager.network.util.microgName +import com.vanced.manager.network.util.musicName +import com.vanced.manager.network.util.vancedName + +class AppDtoMapper( + private val packageInformationDataSource: PackageInformationDataSource, + private val vancedDownloader: VancedDownloader +) : EntityMapper { + + override suspend fun mapToModel(entity: AppDto): App = + with (entity) { + val localVersionCode = packageInformationDataSource.getVersionCode(packageName ?: "") + val localVersionCodeRoot = packageInformationDataSource.getVersionCode(packageNameRoot ?: "") + val localVersionName = packageInformationDataSource.getVersionName(packageName ?: "") + val localVersionNameRoot = packageInformationDataSource.getVersionName(packageNameRoot ?: "") + App( + name = name, + remoteVersion = version, + remoteVersionCode = versionCode, + installedVersion = localVersionName, + installedVersionCode = localVersionCode, + installedVersionRoot = localVersionNameRoot, + installedVersionCodeRoot = localVersionCodeRoot, + appStatus = compareVersionCodes(versionCode, localVersionCode), + appStatusRoot = compareVersionCodes(versionCode, localVersionCodeRoot), + packageName = packageName, + packageNameRoot = packageNameRoot, + iconUrl = iconUrl, + changelog = changelog, + url = url, + themes = themes, + languages = languages, + downloader = getDownloader(name) + ) + } + + override suspend fun mapFromModel(model: App): AppDto = + with (model) { + AppDto( + name = name, + version = remoteVersion, + versionCode = remoteVersionCode, + changelog = changelog, + url = url, + themes = themes, + languages = languages, + packageName = packageName, + packageNameRoot = packageNameRoot, + iconUrl = iconUrl + ) + } + + private fun compareVersionCodes(remote: Int?, local: Int?): AppStatus = + if (local != null && remote != null) { + when { + remote > local -> AppStatus.Update + remote <= local -> AppStatus.Reinstall + else -> AppStatus.Install + } + } else { + AppStatus.Install + } + + private fun getDownloader(app: String?): BaseDownloader? = + when (app) { + vancedName -> vancedDownloader + musicName -> MusicDownloader + microgName -> MicrogDownloader + else -> null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/model/JsonDto.kt b/app/src/main/java/com/vanced/manager/network/model/JsonDto.kt new file mode 100644 index 0000000000..b0b9f8d3fa --- /dev/null +++ b/app/src/main/java/com/vanced/manager/network/model/JsonDto.kt @@ -0,0 +1,11 @@ +package com.vanced.manager.network.model + +import com.google.gson.annotations.SerializedName + +data class JsonDto( + @SerializedName("is_microg_broken") var isMicrogBroken: Boolean, + @SerializedName("manager") var manager: AppDto, + @SerializedName("vanced") var vanced: AppDto, + @SerializedName("music") var music: AppDto, + @SerializedName("microg") var microg: AppDto +) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/model/JsonDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/JsonDtoMapper.kt new file mode 100644 index 0000000000..f04730ace2 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/network/model/JsonDtoMapper.kt @@ -0,0 +1,32 @@ +package com.vanced.manager.network.model + +import com.vanced.manager.domain.model.Json +import com.vanced.manager.domain.util.EntityMapper + +class JsonDtoMapper( + private val appDtoMapper: AppDtoMapper +) : EntityMapper { + + override suspend fun mapToModel(entity: JsonDto): Json = + with (entity) { + Json( + isMicrogBroken = isMicrogBroken, + manager = appDtoMapper.mapToModel(manager), + vanced = appDtoMapper.mapToModel(vanced), + music = appDtoMapper.mapToModel(music), + microg = appDtoMapper.mapToModel(microg) + ) + } + + override suspend fun mapFromModel(model: Json): JsonDto = + with (model) { + JsonDto( + isMicrogBroken = isMicrogBroken, + manager = appDtoMapper.mapFromModel(manager), + vanced = appDtoMapper.mapFromModel(vanced), + music = appDtoMapper.mapFromModel(music), + microg = appDtoMapper.mapFromModel(microg) + ) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/util/Constants.kt b/app/src/main/java/com/vanced/manager/network/util/Constants.kt new file mode 100644 index 0000000000..2887e395e5 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/network/util/Constants.kt @@ -0,0 +1,8 @@ +package com.vanced.manager.network.util + +const val baseUrl = "https://api.vancedapp.com/api/v1/" +const val baseGithubUrl = "https://x1nto.github.io/VancedFiles/" + +const val vancedName = "YouTube Vanced" +const val musicName = "YouTube Vanced Music" +const val microgName = "Vanced microG" \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/preference/ManagerPreferences.kt b/app/src/main/java/com/vanced/manager/preference/ManagerPreferences.kt new file mode 100644 index 0000000000..51569b40e2 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/preference/ManagerPreferences.kt @@ -0,0 +1,16 @@ +package com.vanced.manager.preference + +import android.content.Context +import android.content.SharedPreferences +import androidx.core.content.edit +import androidx.preference.PreferenceManager + +val Context.defPrefs: SharedPreferences get() = PreferenceManager.getDefaultSharedPreferences(this) + +var SharedPreferences.managerTheme + get() = getString("manager_theme", "Light") + set(value) { + edit { + putString("manager_theme", value) + } + } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/repository/JsonRepository.kt b/app/src/main/java/com/vanced/manager/repository/JsonRepository.kt new file mode 100644 index 0000000000..8ae38e35ef --- /dev/null +++ b/app/src/main/java/com/vanced/manager/repository/JsonRepository.kt @@ -0,0 +1,9 @@ +package com.vanced.manager.repository + +import com.vanced.manager.domain.model.Json + +interface JsonRepository { + + suspend fun fetch(): Json + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/repository/JsonRepositoryImpl.kt b/app/src/main/java/com/vanced/manager/repository/JsonRepositoryImpl.kt new file mode 100644 index 0000000000..7cbc27cbe5 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/repository/JsonRepositoryImpl.kt @@ -0,0 +1,16 @@ +package com.vanced.manager.repository + +import com.vanced.manager.domain.model.Json +import com.vanced.manager.network.JsonService +import com.vanced.manager.network.model.JsonDtoMapper + +class JsonRepositoryImpl( + private val service: JsonService, + private val mapper: JsonDtoMapper +) : JsonRepository { + + override suspend fun fetch(): Json { + return mapper.mapToModel(service.get()) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt deleted file mode 100644 index 22f60c5095..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ /dev/null @@ -1,237 +0,0 @@ -package com.vanced.manager.ui - -import android.content.ActivityNotFoundException -import android.content.ComponentName -import android.content.Context -import android.content.Intent -import android.content.res.Configuration -import android.net.Uri -import android.os.Bundle -import android.view.MenuItem -import androidx.appcompat.app.AppCompatActivity -import androidx.core.content.ContextCompat -import androidx.navigation.NavDestination -import androidx.navigation.findNavController -import androidx.navigation.ui.AppBarConfiguration -import androidx.navigation.ui.setupWithNavController -import androidx.preference.PreferenceManager.getDefaultSharedPreferences -import com.crowdin.platform.Crowdin -import com.crowdin.platform.LoadingStateListener -import com.google.firebase.messaging.FirebaseMessaging -import com.vanced.manager.BuildConfig.ENABLE_CROWDIN_AUTH -import com.vanced.manager.BuildConfig.VERSION_CODE -import com.vanced.manager.R -import com.vanced.manager.databinding.ActivityMainBinding -import com.vanced.manager.ui.dialogs.DialogContainer -import com.vanced.manager.ui.dialogs.ManagerUpdateDialog -import com.vanced.manager.ui.dialogs.URLChangeDialog -import com.vanced.manager.ui.fragments.HomeFragmentDirections -import com.vanced.manager.ui.fragments.SettingsFragmentDirections -import com.vanced.manager.utils.* -import com.vanced.manager.utils.AppUtils.currentLocale -import com.vanced.manager.utils.AppUtils.faqpkg -import com.vanced.manager.utils.AppUtils.log -import com.vanced.manager.utils.AppUtils.playStorePkg -import com.vanced.manager.utils.AppUtils.vancedRootPkg -import com.vanced.manager.utils.PackageHelper.isPackageInstalled - -class MainActivity : AppCompatActivity() { - - lateinit var binding: ActivityMainBinding - private val navHost by lazy { findNavController(R.id.nav_host) } - - private val loadingObserver = object : LoadingStateListener { - val tag = "VMLocalisation" - override fun onDataChanged() { - log(tag, "Loaded data") - } - - override fun onFailure(throwable: Throwable) { - log(tag, "Failed to load data: ${throwable.stackTraceToString()}") - } - - } - - override fun onCreate(savedInstanceState: Bundle?) { - setFinalTheme() - super.onCreate(savedInstanceState) - if (ENABLE_CROWDIN_AUTH) - authCrowdin() - - binding = ActivityMainBinding.inflate(layoutInflater) - setContentView(binding.root) - - with(binding) { - setSupportActionBar(toolbar) - toolbar.setupWithNavController( - this@MainActivity.navHost, - AppBarConfiguration(this@MainActivity.navHost.graph) - ) - } - navHost.addOnDestinationChangedListener { _, currFrag: NavDestination, _ -> - setDisplayHomeAsUpEnabled(currFrag.id != R.id.home_fragment) - } - - initDialogs(intent.getBooleanExtra("firstLaunch", false)) - manager.observe(this) { - if (manager.value?.int("versionCode") ?: 0 > VERSION_CODE) { - ManagerUpdateDialog.newInstance(true).show(this) - } - } - } - - override fun onBackPressed() { - if (!navHost.popBackStack()) - finish() - } - - private fun setDisplayHomeAsUpEnabled(isNeeded: Boolean) { - binding.toolbar.navigationIcon = if (isNeeded) ContextCompat.getDrawable( - this, - R.drawable.ic_keyboard_backspace_black_24dp - ) else null - } - - override fun onPause() { - super.onPause() - Crowdin.unregisterDataLoadingObserver(loadingObserver) - } - - override fun onResume() { - setFinalTheme() - super.onResume() - Crowdin.registerDataLoadingObserver(loadingObserver) - } - - override fun onOptionsItemSelected(item: MenuItem): Boolean { - return when (item.itemId) { - R.id.toolbar_about -> { - navHost.navigate(HomeFragmentDirections.toAboutFragment()) - true - } - R.id.toolbar_settings -> { - navHost.navigate(HomeFragmentDirections.toSettingsFragment()) - true - } - R.id.toolbar_log -> { - navHost.navigate(HomeFragmentDirections.toLogFragment()) - true - } - R.id.toolbar_guide -> { - try { - val intent = if (isPackageInstalled(faqpkg, packageManager)) { - Intent().apply { - component = ComponentName(faqpkg, "$faqpkg.ui.MainActivity") - } - } else { - Intent(Intent.ACTION_VIEW).apply { - val uriBuilder = Uri.parse("https://play.google.com/store/apps/details") - .buildUpon() - .appendQueryParameter("id", faqpkg) - .appendQueryParameter("launch", "true") - data = uriBuilder.build() - setPackage(playStorePkg) - } - } - startActivity(intent) - true - } catch (e: ActivityNotFoundException) { - false - } - } - R.id.toolbar_update_manager -> { - ManagerUpdateDialog.newInstance(false) - .show(supportFragmentManager, "manager_update") - true - } - R.id.dev_settings -> { - navHost.navigate(SettingsFragmentDirections.toDevSettingsFragment()) - return true - } - else -> super.onOptionsItemSelected(item) - } - } - - override fun attachBaseContext(newBase: Context) { - super.attachBaseContext(Crowdin.wrapContext(LanguageContextWrapper.wrap(newBase))) - } - - //I have no idea why the fuck is super method deprecated - @Suppress("DEPRECATION") - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - onActivityResult(requestCode) - } - - override fun onConfigurationChanged(newConfig: Configuration) { - super.onConfigurationChanged(newConfig) - - //update manager language when system language is changed - @Suppress("DEPRECATION") - if (newConfig.locale != currentLocale) { - recreate() //restarting activity in order to recreate viewmodels, otherwise some text won't update - return - } - - when (newConfig.orientation) { - Configuration.ORIENTATION_PORTRAIT -> log( - "VMUI", - "screen orientation changed to portrait" - ) - Configuration.ORIENTATION_LANDSCAPE -> log( - "VMUI", - "screen orientation changed to landscape" - ) - else -> log("VMUI", "screen orientation changed to [REDACTED]") - } - - } - - override fun recreate() { - //needed for setting language smh - startActivity(Intent(this, this::class.java)) - finish() - } - - private fun initDialogs(firstLaunch: Boolean) { - val prefs = getDefaultSharedPreferences(this) - val variant = prefs.managerVariant - prefs.getBoolean("show_root_dialog", true) - - if (intent?.data != null && intent.dataString?.startsWith("https") == true) { - val urldialog = URLChangeDialog() - val arg = Bundle() - arg.putString("url", intent.dataString) - urldialog.arguments = arg - urldialog.show(this) - } - - if (firstLaunch) { - DialogContainer.showSecurityDialog(this) - with(FirebaseMessaging.getInstance()) { - subscribeToTopic("Vanced-Update") - subscribeToTopic("Music-Update") - subscribeToTopic("MicroG-Update") - } - } else { - if (isMiuiOptimizationsEnabled) { - DialogContainer.miuiDialog(this) - } - } - - if (!prefs.getBoolean("statement", true)) { - DialogContainer.statementFalse(this) - } - - if (variant == "root") { - if (PackageHelper.getPackageVersionName(vancedRootPkg, packageManager) == "14.21.54") { - DialogContainer.basicDialog( - getString(R.string.hold_on), - getString(R.string.magisk_vanced), - this - ) - } - } - } - -} diff --git a/app/src/main/java/com/vanced/manager/ui/SplashScreenActivity.kt b/app/src/main/java/com/vanced/manager/ui/SplashScreenActivity.kt deleted file mode 100644 index 6778af4a94..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/SplashScreenActivity.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.vanced.manager.ui - -import android.content.Intent -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import androidx.preference.PreferenceManager.getDefaultSharedPreferences - -class SplashScreenActivity : AppCompatActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - if (getDefaultSharedPreferences(this).getBoolean("firstLaunch", true)) { - startActivity(Intent(this, WelcomeActivity::class.java)) - finish() - } else { - startActivity(Intent(this, MainActivity::class.java)) - finish() - } - - } -} diff --git a/app/src/main/java/com/vanced/manager/ui/WelcomeActivity.kt b/app/src/main/java/com/vanced/manager/ui/WelcomeActivity.kt deleted file mode 100644 index 2469462fae..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/WelcomeActivity.kt +++ /dev/null @@ -1,86 +0,0 @@ -package com.vanced.manager.ui - -import android.animation.ValueAnimator -import android.os.Bundle -import android.util.LayoutDirection -import androidx.appcompat.app.AppCompatActivity -import androidx.core.animation.addListener -import androidx.viewpager2.widget.ViewPager2 -import com.vanced.manager.adapter.WelcomePageAdapter -import com.vanced.manager.databinding.ActivityWelcomeBinding -import kotlin.math.abs - -class WelcomeActivity : AppCompatActivity() { - - private lateinit var binding: ActivityWelcomeBinding - private var isRtl = false - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - binding = ActivityWelcomeBinding.inflate(layoutInflater) - setContentView(binding.root) - - isRtl = resources.configuration.layoutDirection == LayoutDirection.RTL - - binding.welcomeViewpager.apply { - adapter = WelcomePageAdapter(this@WelcomeActivity) - isUserInputEnabled = false - setPageTransformer { page, position -> - page.apply { - val pageWidth = width.toFloat() - //Thank you, fragula dev! - when { - position > 0 && position < 1 -> { - alpha = 1f - translationX = 0f - } - position > -1 && position <= 0 -> { - alpha = 1.0f - abs(position * 0.7f) - translationX = pageWidth.rtlCompat * position / 1.3F - } - } - } - } - } - } - - override fun onBackPressed() { - with(binding) { - if (welcomeViewpager.currentItem == 0) { - super.onBackPressed() - } else { - navigateTo(welcomeViewpager.currentItem - 1) - } - } - } - - fun navigateTo(position: Int) { - binding.welcomeViewpager.currentPosition = position - } - - private val Float.rtlCompat get() = if (isRtl) this else -this - - //Shit way to implement animation duration, but at least it works - private var ViewPager2.currentPosition: Int - get() = currentItem - set(value) { - val pixelsToDrag: Int = width * (value - currentItem) - val animator = ValueAnimator.ofInt(0, pixelsToDrag) - var previousValue = 0 - animator.apply { - addUpdateListener { valueAnimator -> - val currentValue = valueAnimator.animatedValue as Int - val currentPxToDrag = (currentValue - previousValue).toFloat() - fakeDragBy(currentPxToDrag.rtlCompat) - previousValue = currentValue - } - addListener( - onStart = { beginFakeDrag() }, - onEnd = { endFakeDrag() } - ) - duration = 500 - start() - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/composables/AppComposables.kt b/app/src/main/java/com/vanced/manager/ui/composables/AppComposables.kt new file mode 100644 index 0000000000..0b84f5aa59 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/composables/AppComposables.kt @@ -0,0 +1,226 @@ +package com.vanced.manager.ui.composables + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.material.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.DeleteForever +import androidx.compose.material.icons.filled.Download +import androidx.compose.material.icons.filled.Launch +import androidx.compose.material.icons.outlined.Info +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.google.accompanist.glide.rememberGlidePainter +import com.vanced.manager.R +import com.vanced.manager.domain.model.App +import com.vanced.manager.downloader.base.BaseDownloader +import com.vanced.manager.ui.theme.managerAccentColor + +@OptIn(ExperimentalAnimationApi::class) +@Composable +fun AppCard( + app: App, + installationOptions: List? = null +) { + val showDownloadDialog = remember { mutableStateOf(false) } + val showAppInfo = remember { mutableStateOf(false) } + val showInstallationOptions = remember { mutableStateOf(false) } + val icon = rememberGlidePainter( + request = app.iconUrl ?: "", + requestBuilder = { + placeholder(R.drawable.ic_app_icon_placeholder) + }, + fadeIn = true + ) + ManagerCard { + Column { + AppInfoCard( + appName = app.name, + icon = icon + ) + AppActionCard( + appInstalledVersion = app.installedVersion, + appRemoteVersion = app.remoteVersion, + showDownloadDialog = showDownloadDialog, + showAppInfo = showAppInfo, + showInstallationOptions = showInstallationOptions + ) + if (installationOptions != null) { + AnimatedVisibility( + modifier = Modifier.fillMaxWidth(), + visible = showInstallationOptions.value + ) { + installationOptions.forEach { + it.Content() + } + } + } + } + } + + if (app.name != null && app.downloader != null) { + AppDownloadDialog( + app = app.name, + downloader = app.downloader, + showDialog = showDownloadDialog + ) + } + + if (app.name != null && app.changelog != null) { + ChangeLogDialog( + appName = app.name, + changelog = app.changelog, + icon = icon, + show = showAppInfo + ) + } +} + +@Composable +fun AppInfoCard( + appName: String?, + icon: Painter +) { + ManagerListItem( + title = appName ?: "", + icon = { + Image( + painter = icon, + contentDescription = "", + modifier = Modifier.size(48.dp, 48.dp), + ) + }, + topPadding = 8.dp, + bottomPadding = 8.dp + ) +} + +@Composable +fun AppActionCard( + appRemoteVersion: String?, + appInstalledVersion: String?, + showDownloadDialog: MutableState, + showAppInfo: MutableState, + showInstallationOptions: MutableState +) { + CompositionLocalProvider(LocalContentColor provides MaterialTheme.colors.managerAccentColor) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp, vertical = 4.dp) + .background(managerAccentColor().copy(alpha = 0.15f)), + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier + .weight(1f) + .wrapContentWidth(Alignment.Start) + ) { + Text( + text = "Latest: ${appRemoteVersion ?: "Unavailable"}", + fontSize = 12.sp + ) + Text( + text = "Installed: ${appInstalledVersion ?: "Unavailable"}", + fontSize = 12.sp + ) + } + Row( + modifier = Modifier + .weight(1f) + .padding(start = 4.dp) + .wrapContentWidth(Alignment.End) + ) { + IconButton(icon = Icons.Outlined.Info, contentDescription = "App Info") { + showAppInfo.value = true + } + IconButton(icon = Icons.Default.DeleteForever, contentDescription = "Uninstall") {} + IconButton(icon = Icons.Default.Launch, contentDescription = "Launch") {} + IconButton(icon = Icons.Default.Download, contentDescription = "Install") { + showInstallationOptions.value = true + } + } + } + } +} + +@Composable +fun AppDownloadDialog( + app: String, + downloader: BaseDownloader, + showDialog: MutableState +) { + val coroutineScope = rememberCoroutineScope() + + val rememberProgress = remember { downloader.downloadProgress } + val rememberFile = remember { downloader.downloadFile } + val rememberInstalling = remember { downloader.installing } + + val showProgress = remember { mutableStateOf(false) } + ManagerDialog(title = app, isShown = showDialog, buttons = { + AppDownloadDialogButtons( + showProgress = showProgress, + showDialog = showDialog, + downloader = downloader, + coroutineScope = coroutineScope + ) + }) { + AppDownloadDialogProgress( + progress = rememberProgress, + file = rememberFile, + showProgress = showProgress.value, + installing = rememberInstalling + ) + } +} + +@Composable +fun ChangeLogDialog( + appName: String, + changelog: String, + icon: Painter, + show: MutableState +) { + if (show.value) { + ManagerDialog( + title = "About $appName", + isShown = show, + buttons = { + ManagerThemedButton( + modifier = Modifier.fillMaxWidth(), + onClick = { show.value = false } + ) { + Text(text = "Close") + } + } + ) { + Image( + painter = icon, + contentDescription = null, + modifier = Modifier + .size(64.dp) + .align(Alignment.CenterHorizontally) + ) + HeaderView( + modifier = Modifier.padding(horizontal = 8.dp), + headerName = "Changelog", + headerPadding = 0.dp + ) { + Text( + modifier = Modifier.padding(top = 4.dp), + text = changelog, + fontSize = 14.sp + ) + } + } + } +} + + diff --git a/app/src/main/java/com/vanced/manager/ui/composables/ColorPicker.kt b/app/src/main/java/com/vanced/manager/ui/composables/ColorPicker.kt new file mode 100644 index 0000000000..70e66ba9a0 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/composables/ColorPicker.kt @@ -0,0 +1,105 @@ +package com.vanced.manager.ui.composables + +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.gestures.detectDragGestures +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.drawscope.DrawScope +import androidx.compose.ui.graphics.drawscope.Stroke +import androidx.compose.ui.graphics.drawscope.inset +import androidx.compose.ui.input.pointer.PointerInputChange +import androidx.compose.ui.input.pointer.pointerInput +import androidx.compose.ui.unit.dp +import androidx.core.graphics.ColorUtils + +//TODO +@Composable +fun HSLColorPicker( + modifier: Modifier = Modifier +) { + val hslColors = floatArrayOf(0f, 1f, 0.5f) + val hueColors = getColors(hslColors, length = 360, index = 0) { it } + val saturationColors = getColors(hslColors, length = 11, index = 1) { it / 10 } + val lightnessColors = getColors(hslColors, length = 11, index = 2) { it / 10 } + + val hueCircle by remember { mutableStateOf(Offset(0f, 0f)) } + val saturationCircle by remember { mutableStateOf(Offset(0f, 0f)) } + val lightnessCircle by remember { mutableStateOf(Offset(0f, 0f)) } + Canvas(modifier = modifier + .size(250.dp, 250.dp) + .pointerInput(Unit) { + detectDragGestures { change: PointerInputChange, dragAmount: Offset -> + val (changeX, changeY) = change.position + } + } + ) { + colorArc( + brush = Brush.sweepGradient(hueColors), + startAngle = 0f, + sweepAngle = 360f, + circleOffset = hueCircle + ) + inset( + inset = 60f + ) { + colorArc( + brush = Brush.linearGradient( + colors = saturationColors, + start = Offset.Infinite, + end = Offset.Zero + ), + startAngle = 100f, + sweepAngle = 155f, + circleOffset = saturationCircle + ) + colorArc( + brush = Brush.linearGradient(lightnessColors), + startAngle = 280f, + sweepAngle = 155f, + circleOffset = lightnessCircle + ) + } + } +} + +fun DrawScope.colorArc( + brush: Brush, + startAngle: Float, + sweepAngle: Float, + circleOffset: Offset +) { + drawArc( + brush = brush, + startAngle = startAngle, + sweepAngle = sweepAngle, + useCenter = false, + style = Stroke(width = 15f) + ) + + inset(circleOffset.x, circleOffset.y) { + drawCircle( + brush = brush, + radius = 50f + ) + } +} + +fun getColors( + hslColors: FloatArray, + length: Int, + index: Int, + calculate: (Float) -> Float +): List { + val colorsCopy = hslColors.copyOf() + return List(length) { + colorsCopy[index] = calculate(it.toFloat()) + Color(ColorUtils.HSLToColor(colorsCopy)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/composables/DialogComposables.kt b/app/src/main/java/com/vanced/manager/ui/composables/DialogComposables.kt new file mode 100644 index 0000000000..7f3dc152c9 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/composables/DialogComposables.kt @@ -0,0 +1,2 @@ +package com.vanced.manager.ui.composables + diff --git a/app/src/main/java/com/vanced/manager/ui/composables/DownloadComposables.kt b/app/src/main/java/com/vanced/manager/ui/composables/DownloadComposables.kt new file mode 100644 index 0000000000..ae47523512 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/composables/DownloadComposables.kt @@ -0,0 +1,111 @@ +package com.vanced.manager.ui.composables + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.material.Icon +import androidx.compose.material.LinearProgressIndicator +import androidx.compose.material.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowForwardIos +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import com.vanced.manager.downloader.base.BaseDownloader +import dev.burnoo.compose.rememberpreference.rememberStringPreference +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch + +data class InstallationOptionKey( + val keyName: String, + val keyDefaultValue: String = "", + val keyInitialValue: String = keyDefaultValue +) + +data class InstallationOption( + val title: String, + val descriptionKey: InstallationOptionKey, + val dialog: @Composable (show: MutableState, preference: MutableState) -> Unit +) { + + @Composable + fun Content() { + val showDialog = remember { mutableStateOf(false) } + val preference = rememberStringPreference( + keyName = descriptionKey.keyName, + defaultValue = descriptionKey.keyDefaultValue, + initialValue = descriptionKey.keyInitialValue + ) + ManagerListItem( + modifier = Modifier.clickable { + showDialog.value = true + }, + title = title, + description = preference.value, + trailing = { + Icon(imageVector = Icons.Default.ArrowForwardIos, contentDescription = null) + } + ) + if (showDialog.value) { + dialog(showDialog, preference) + } + } +} + +@Composable +fun AppDownloadDialogButtons( + showProgress: MutableState, + showDialog: MutableState, + downloader: BaseDownloader, + coroutineScope: CoroutineScope +) { + when(showProgress.value) { + true -> ManagerThemedButton(onClick = { + downloader.cancelDownload() + showDialog.value = false + showProgress.value = false + }) { + Text(text = "Cancel") + } + false -> ManagerThemedButton(onClick = { + coroutineScope.launch { + showProgress.value = true + downloader.download() + } + }) { + Text(text = "Download") + } + } +} + +@Composable +fun AppDownloadDialogProgress( + progress: Float, + file: String, + showProgress: Boolean, + installing: Boolean +) { + if (showProgress) { + when (installing) { + true -> LinearProgressIndicator(color = managerAccentColor()) + false -> LinearProgressIndicator( + progress = progress, + color = managerAccentColor() + ) + } + Row { + Text( + modifier = Modifier + .weight(1f) + .wrapContentWidth(Alignment.Start), + text = "Downloading $file" + ) + Text( + modifier = Modifier + .weight(1f) + .wrapContentWidth(Alignment.End), + text = "$progress" + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/composables/GlobalComposables.kt b/app/src/main/java/com/vanced/manager/ui/composables/GlobalComposables.kt new file mode 100644 index 0000000000..2b3da173d8 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/composables/GlobalComposables.kt @@ -0,0 +1,140 @@ +package com.vanced.manager.ui.composables + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.* +import androidx.compose.material.* +import androidx.compose.material.ripple.rememberRipple +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.em +import androidx.compose.ui.unit.sp +import com.vanced.manager.ui.theme.managerAccentColor + +@ExperimentalStdlibApi +@Composable +fun HeaderCard( + headerName: String, + headerPadding: Dp = 11.dp, + content: @Composable ColumnScope.() -> Unit +) { + ManagerCard( + modifier = Modifier + .fillMaxWidth() + ) { + Column { + Spacer(modifier = Modifier.size(height = 4.dp, width = 0.dp)) + HeaderView( + headerName = headerName, + content = content, + headerPadding = headerPadding + ) + } + } +} + +@Composable +fun HeaderView( + modifier: Modifier = Modifier, + headerName: String, + headerPadding: Dp = 11.dp, + content: @Composable ColumnScope.() -> Unit +) { + Column( + modifier = modifier + ) { + Header(headerName = headerName, headerPadding = headerPadding) + content() + } +} + +@OptIn(ExperimentalStdlibApi::class) +@Composable +fun Header( + headerName: String, + headerPadding: Dp = 11.dp, +) { + Text( + headerName.uppercase(), + letterSpacing = 0.15.em, + color = MaterialTheme.colors.managerAccentColor, + modifier = Modifier.padding(horizontal = headerPadding), + fontWeight = FontWeight.Bold, + fontSize = 13.sp + ) +} + +@Composable +fun IconButton( + icon: ImageVector, + contentDescription: String, + onClick: () -> Unit +) { + val interactionSource = remember { MutableInteractionSource() } + val buttonSize = 36.dp + val enabled = true + Box( + modifier = Modifier + .clickable( + onClick = onClick, + enabled = enabled, + role = Role.Button, + interactionSource = interactionSource, + indication = rememberRipple(bounded = false, radius = 18.dp) + ) + .size(buttonSize), + contentAlignment = Alignment.Center + ) { + val contentAlpha = if (enabled) LocalContentAlpha.current else ContentAlpha.disabled + CompositionLocalProvider(LocalContentAlpha provides contentAlpha) { + Icon( + imageVector = icon, + contentDescription = contentDescription + ) + } + } +} + +@Composable +fun RadiobuttonItem( + currentSelection: MutableState, + text: String, + preferenceValue: String, +) { + Row( + modifier = Modifier + .fillMaxWidth() + .clickable { + currentSelection.value = preferenceValue + } + .padding(horizontal = 8.dp, vertical = 6.dp), + verticalAlignment = Alignment.CenterVertically + ) { + RadioButton( + selected = preferenceValue == currentSelection.value, + onClick = { + currentSelection.value = preferenceValue + }, + colors = RadioButtonDefaults.colors( + MaterialTheme.colors.managerAccentColor, + Color.LightGray + ) + ) + Text( + modifier = Modifier.padding(start = 4.dp), + text = text, + color = managerTextColor(), + fontSize = 18.sp + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/composables/HomeComposables.kt b/app/src/main/java/com/vanced/manager/ui/composables/HomeComposables.kt new file mode 100644 index 0000000000..b30469da76 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/composables/HomeComposables.kt @@ -0,0 +1,80 @@ +package com.vanced.manager.ui.composables + +import android.net.Uri +import androidx.annotation.DrawableRes +import androidx.browser.customtabs.CustomTabsIntent +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.LocalContentColor +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp + +@Composable +fun LinkCard( + @DrawableRes icon: Int, + title: String, + link: String +) { + val context = LocalContext.current + val customTabs = remember { CustomTabsIntent.Builder().build() } + ManagerCard( + modifier = Modifier + .clip(RoundedCornerShape(12.dp)) + .clickable { + customTabs.launchUrl(context, Uri.parse(link)) + } + .size(width = 120.dp, height = 100.dp) + ) { + CompositionLocalProvider(LocalContentColor provides managerTextColor()) { + Column( + modifier = Modifier.padding(all = 16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Image( + modifier = Modifier.size(36.dp), + painter = painterResource(id = icon), + contentDescription = null, + ) + Spacer(modifier = Modifier.height(8.dp)) + Text( + text = title, + textAlign = TextAlign.Center + ) + } + } + } +} + +@Composable +fun ScrollableLinkRow( + items: List, + content: @Composable (T) -> Unit +) { + val state = rememberLazyListState() + LazyRow( + modifier = Modifier.fillMaxWidth(), + state = state + ) { + itemsIndexed(items) { index, item -> + content(item) + if (index < items.size - 1) { + Spacer(modifier = Modifier.width(8.dp)) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/composables/ManagerComponents.kt b/app/src/main/java/com/vanced/manager/ui/composables/ManagerComponents.kt new file mode 100644 index 0000000000..506b90b305 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/composables/ManagerComponents.kt @@ -0,0 +1,229 @@ +package com.vanced.manager.ui.composables + +import androidx.annotation.StringRes +import androidx.compose.animation.animateColorAsState +import androidx.compose.animation.core.tween +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListScope +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.graphics.luminance +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.window.Dialog +import com.vanced.manager.ui.theme.cardColor +import com.vanced.manager.ui.theme.managerAccentColor +import java.util.* + +@Composable +fun managerShape() = RoundedCornerShape(12.dp) + +@Composable +fun ManagerCard( + modifier: Modifier = Modifier, + shape: Shape = managerShape(), + content: @Composable () -> Unit, +) { + Card( + modifier = modifier, + shape = shape, + backgroundColor = managerCardColor(), + elevation = 0.dp, + content = content + ) +} + +@Composable +fun ManagerThemedButton( + modifier: Modifier = Modifier, + onClick: () -> Unit, + content: @Composable RowScope.() -> Unit +) { + val accentColor = managerAccentColor() + Button( + modifier = modifier, + onClick = onClick, + shape = managerShape(), + colors = ButtonDefaults.buttonColors( + backgroundColor = managerAccentColor() + ), + elevation = ButtonDefaults.elevation(0.dp) + ) { + CompositionLocalProvider(LocalContentColor provides if (accentColor.luminance() > 0.7) Color.Black else Color.White) { + content() + } + } +} + +@Composable +fun ManagerDialog( + title: String, + isShown: MutableState, + buttons: @Composable ColumnScope.() -> Unit, + content: @Composable ColumnScope.() -> Unit, +) { + Dialog( + onDismissRequest = { isShown.value = false }, + content = { + ManagerCard { + Column( + modifier = Modifier.padding(all = 8.dp) + ) { + Text( + modifier = Modifier.fillMaxWidth(), + text = title, + letterSpacing = 2.sp, + fontWeight = FontWeight.Bold, + color = managerTextColor().copy(alpha = 0.8f), + fontSize = 24.sp, + textAlign = TextAlign.Center + ) + Spacer(Modifier.height(8.dp)) + content() + Spacer(Modifier.height(8.dp)) + buttons() + } + } + } + ) +} + +@Composable +fun ManagerSurface( + content: @Composable () -> Unit +) { + Surface( + modifier = Modifier.fillMaxSize(), + color = managerSurfaceColor(), + content = content + ) +} + +@Composable +fun ManagerLazyColumn( + content: LazyListScope.() -> Unit +) { + LazyColumn( + contentPadding = PaddingValues(12.dp), + content = content + ) +} + +@Composable +fun ManagerScrollableColumn( + content: @Composable ColumnScope.() -> Unit +) { + val scrollState = rememberScrollState() + Column( + modifier = Modifier + .verticalScroll(scrollState) + .padding(12.dp), + horizontalAlignment = Alignment.CenterHorizontally, + content = content + ) +} + +@Composable +fun ManagerDropdownMenuItem( + isMenuExpanded: MutableState, + title: String, + onClick: () -> Unit +) { + DropdownMenuItem( + onClick = { + isMenuExpanded.value = false + onClick() + }, + ) { + Text(text = title) + } +} + +@Composable +fun animateManagerColor( + color: Color +): State { + return animateColorAsState( + targetValue = color, + animationSpec = tween(500) + ) +} + +@Composable +fun HomeHeaderView( + modifier: Modifier = Modifier, + headerName: String, + content: @Composable () -> Unit +) { + HeaderView( + modifier = modifier, + headerName = headerName, + headerPadding = 4.dp + ) { + ManagerHomeHeaderSeparator() + content() + } +} + +@Composable +fun managerAnimatedColor( + color: Color +): Color { + val animColor by animateColorAsState( + targetValue = color, + animationSpec = tween(500) + ) + return animColor +} + +@Composable +fun managerAnimatedText( + @StringRes stringId: Int +): String { + var text by remember { mutableStateOf("") } + CompositionLocalProvider( + LocalConfiguration provides LocalConfiguration.current.apply { + setLocale(Locale("ru")) + } + ) { + text = stringResource(id = stringId) + } + return text +} + +@Composable +fun ManagerCardSeparator() { + Spacer(modifier = Modifier.height(8.dp)) +} + +@Composable +fun ManagerHomeHeaderSeparator() { + Spacer(modifier = Modifier.height(4.dp)) +} + +@Composable +fun managerTextColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.onSurface) + +@Composable +fun managerSurfaceColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.surface) + +@Composable +fun managerCardColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.cardColor) + +@Composable +fun managerAccentColor(): Color = MaterialTheme.colors.managerAccentColor + +@Composable +fun animatedManagerAccentColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.managerAccentColor) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/composables/ManagerListItem.kt b/app/src/main/java/com/vanced/manager/ui/composables/ManagerListItem.kt new file mode 100644 index 0000000000..77a4582225 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/composables/ManagerListItem.kt @@ -0,0 +1,95 @@ +package com.vanced.manager.ui.composables + +import androidx.compose.foundation.layout.* +import androidx.compose.material.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp + +const val defaultPadding = 12 + +@Composable +fun ManagerListItem( + modifier: Modifier = Modifier, + title: String, + description: String? = null, + startPadding: Dp = defaultPadding.dp, + endPadding: Dp = defaultPadding.dp, + topPadding: Dp = defaultPadding.dp, + bottomPadding: Dp = defaultPadding.dp, + icon: @Composable (() -> Unit)? = null, + trailing: @Composable (() -> Unit)? = null +) { + val typography = MaterialTheme.typography + val textColor by animateManagerColor(color = MaterialTheme.colors.onBackground) + Box( + modifier = modifier + ) { + Row( + modifier = Modifier + .padding(top = topPadding, bottom = bottomPadding) + ) { + if (icon != null) { + Box( + modifier = Modifier + .padding(start = startPadding) + .align(Alignment.CenterVertically) + ) { + icon() + } + } + Column( + modifier = Modifier + .padding( + start = startPadding, + end = endPadding + ) + .weight(1f) + .align(Alignment.CenterVertically) + ) { + if (description == null) { + Spacer(modifier = Modifier.size(6.dp)) + } + Text( + text = title, + fontSize = 16.sp, + modifier = Modifier.fillMaxWidth(), + style = typography.subtitle1, + color = textColor + ) + if (description != null) { + CompositionLocalProvider( + LocalContentAlpha provides ContentAlpha.medium, + LocalContentColor provides textColor + ) { + Text( + text = description, + fontSize = 12.sp, + modifier = Modifier.fillMaxWidth() + ) + } + } + if (description == null) { + Spacer(modifier = Modifier.size(6.dp)) + } + + } + if (trailing != null) { + Box( + modifier = Modifier + .padding(end = endPadding) + .align(Alignment.CenterVertically) + ) { + CompositionLocalProvider(LocalContentColor provides textColor) { + trailing() + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/composables/PreferenceComposables.kt b/app/src/main/java/com/vanced/manager/ui/composables/PreferenceComposables.kt new file mode 100644 index 0000000000..8283b498d2 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/composables/PreferenceComposables.kt @@ -0,0 +1,148 @@ +package com.vanced.manager.ui.composables + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.* +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.unit.dp +import androidx.core.content.edit +import androidx.preference.PreferenceManager +import com.vanced.manager.ui.preferences.RadioButtonPreference + +@Composable +fun SwitchPreference( + preferenceTitle: String, + preferenceDescription: String?, + preferenceKey: String, + defaultValue: Boolean = true, + onCheckedChange: (isChecked: Boolean) -> Unit = {} +) { + val prefs = PreferenceManager.getDefaultSharedPreferences(LocalContext.current) + var isChecked by remember { mutableStateOf(prefs.getBoolean(preferenceKey, defaultValue)) } + + fun savePreference() { + isChecked = !isChecked + prefs.edit { + putBoolean(preferenceKey, isChecked) + } + onCheckedChange(isChecked) + } + + Preference( + preferenceTitle = preferenceTitle, + preferenceDescription = preferenceDescription, + onClick = { savePreference() }, + trailing = { + Switch( + checked = isChecked, + onCheckedChange = { savePreference() }, + colors = SwitchDefaults.colors( + checkedThumbColor = managerAccentColor(), + checkedTrackColor = managerAccentColor(), + uncheckedThumbColor = Color.Gray, + uncheckedTrackColor = Color.Gray + ) + ) + } + ) +} + +@Composable +fun Preference( + preferenceTitle: String, + preferenceDescription: String? = null, + trailing: @Composable (() -> Unit)? = null, + onClick: () -> Unit +) { + ManagerListItem( + modifier = Modifier.clickable(onClick = onClick), + title = preferenceTitle, + description = preferenceDescription, + trailing = trailing, + bottomPadding = 4.dp, + topPadding = 4.dp + ) +} + +@Composable +fun DialogPreference( + preferenceTitle: String, + preferenceDescription: String? = null, + trailing: @Composable (() -> Unit)? = null, + buttons: @Composable ColumnScope.(isShown: MutableState) -> Unit, + content: @Composable ColumnScope.() -> Unit +) { + val isShown = remember { mutableStateOf(false) } + Preference( + preferenceTitle = preferenceTitle, + preferenceDescription = preferenceDescription, + trailing = trailing + ) { + isShown.value = true + } + if (isShown.value) { + ManagerDialog( + title = preferenceTitle, + isShown = isShown, + buttons = { buttons(isShown) }, + content = content + ) + } +} + +@Composable +fun DialogRadioButtonPreference( + preferenceTitle: String, + preferenceKey: String, + defaultValue: String, + preferenceDescription: String? = null, + trailing: @Composable (() -> Unit)? = null, + buttons: List, + onSave: (newPref: String?) -> Unit = {} +) { + val prefs = PreferenceManager.getDefaultSharedPreferences(LocalContext.current) + val currentSelection = remember { mutableStateOf(prefs.getString(preferenceKey, defaultValue)) } + DialogPreference( + preferenceTitle = preferenceTitle, + preferenceDescription = preferenceDescription, + trailing = trailing, + buttons = { isShown -> + ManagerThemedButton( + modifier = Modifier.fillMaxWidth(), + onClick = { + prefs.edit { + putString(preferenceKey, currentSelection.value) + } + onSave(currentSelection.value) + isShown.value = false + } + ) { + Text(text = "Save") + } + } + ) { + LazyColumn( + modifier = Modifier + .weight( + weight = 1f, + fill = false + ) + + ) { + items(buttons) { button -> + val (title, key) = button + RadiobuttonItem( + currentSelection = currentSelection, + text = title, + preferenceValue = key + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/compose/Colors.kt b/app/src/main/java/com/vanced/manager/ui/compose/Colors.kt deleted file mode 100644 index a60c9bfea7..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/compose/Colors.kt +++ /dev/null @@ -1,2 +0,0 @@ -package com.vanced.manager.ui.compose - diff --git a/app/src/main/java/com/vanced/manager/ui/compose/PreferenceViews.kt b/app/src/main/java/com/vanced/manager/ui/compose/PreferenceViews.kt deleted file mode 100644 index c0eb5dbc2d..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/compose/PreferenceViews.kt +++ /dev/null @@ -1,107 +0,0 @@ -package com.vanced.manager.ui.compose - -//import androidx.compose.foundation.clickable -//import androidx.compose.foundation.layout.Column -//import androidx.compose.foundation.layout.ColumnScope -//import androidx.compose.foundation.layout.padding -//import androidx.compose.material.Switch -//import androidx.compose.material.Text -//import androidx.compose.runtime.* -//import androidx.compose.ui.Modifier -//import androidx.compose.ui.graphics.Color -//import androidx.compose.ui.platform.LocalContext -//import androidx.compose.ui.tooling.preview.Preview -//import androidx.compose.ui.unit.dp -//import androidx.compose.ui.unit.em -//import androidx.compose.ui.unit.sp -//import androidx.constraintlayout.compose.ConstraintLayout -//import androidx.core.content.edit -//import androidx.preference.PreferenceManager -// -//@Composable -//@Preview -//inline fun PreferenceCategory( -// categoryTitle: String, -// content: @Composable ColumnScope.() -> Unit -//) { -// Column { -// Text( -// categoryTitle, -// letterSpacing = 0.15.em, -// color = Color(LocalContext.current.accentColor) -// ) -// content() -// } -//} -// -// -//@Composable -//@Preview -//inline fun SwitchPreference( -// preferenceTitle: String, -// preferenceDescription: String? = null, -// preferenceKey: String, -// defValue: Boolean = true, -// crossinline onCheckedChange: (Boolean) -> Unit = {} -//) { -// val prefs = PreferenceManager.getDefaultSharedPreferences(LocalContext.current) -// val isChecked = remember { mutableStateOf(prefs.getBoolean(preferenceKey, defValue)) } -// ConstraintLayout(modifier = Modifier.padding(12.dp, 4.dp).clickable { -// isChecked.value = !isChecked.value -// }) { -// val (title, description, switch) = createRefs() -// Text(preferenceTitle, fontSize = 16.sp, modifier = Modifier.constrainAs(title) { -// top.linkTo(parent.top) -// start.linkTo(parent.start) -// end.linkTo(switch.start, 4.dp) -// if (preferenceDescription != null) { -// bottom.linkTo(description.top) -// } else { -// bottom.linkTo(parent.bottom) -// } -// }) -// if (preferenceDescription != null) { -// Text(preferenceDescription, fontSize = 13.sp, modifier = Modifier.constrainAs(description) { -// top.linkTo(title.bottom) -// start.linkTo(parent.start) -// end.linkTo(switch.start, 8.dp) -// }) -// } -// Switch( -// isChecked.value, -// onCheckedChange = { -// prefs.edit { putBoolean(preferenceKey, it) } -// onCheckedChange(it) -// }, -// modifier = Modifier.clickable(false) {} -// ) -// } -//} -// -//@Composable -//@Preview -//fun Preference( -// preferenceTitle: String, -// preferenceDescription: String? = null, -// onClick: () -> Unit -//) { -// ConstraintLayout(modifier = Modifier.padding(12.dp, 4.dp).clickable(onClick = onClick)) { -// val (title, description, switch) = createRefs() -// Text(preferenceTitle, fontSize = 16.sp, modifier = Modifier.constrainAs(title) { -// top.linkTo(parent.top) -// start.linkTo(parent.start) -// end.linkTo(switch.start, 4.dp) -// if (preferenceDescription != null) { -// bottom.linkTo(description.top) -// } else { -// bottom.linkTo(parent.bottom) -// } -// }) -// if (preferenceDescription != null) { -// Text(preferenceDescription, fontSize = 13.sp, modifier = Modifier.constrainAs(description) { -// top.linkTo(title.bottom) -// }) -// } -// } -// -//} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/compose/Theme.kt b/app/src/main/java/com/vanced/manager/ui/compose/Theme.kt deleted file mode 100644 index 6f873761b7..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/compose/Theme.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.vanced.manager.ui.compose - -//import android.content.Context -//import androidx.compose.foundation.isSystemInDarkTheme -//import androidx.compose.material.MaterialTheme -//import androidx.compose.material.darkColors -//import androidx.compose.material.lightColors -//import androidx.compose.runtime.Composable -//import androidx.compose.runtime.MutableState -//import androidx.compose.runtime.mutableStateOf -//import androidx.compose.runtime.remember -//import androidx.compose.ui.graphics.Color -//import androidx.compose.ui.platform.LocalContext -//import androidx.preference.PreferenceManager.getDefaultSharedPreferences -//import com.vanced.manager.utils.mutableAccentColor -// -//const val Dark = "Dark" -//const val SystemDefault = "System Default" -// -//const val defAccentColor: Int = -13732865 -// -//val Context.accentColor get() = mutableAccentColor.value ?: getDefaultSharedPreferences(this).getInt("manager_accent_color", defAccentColor) -// -//enum class Theme { -// DARK, LIGHT -//} -// -//val lightColors = lightColors( -// primary = Color(defAccentColor) -//) -// -//val darkColors = darkColors( -// primary = Color(defAccentColor) -//) -// -//fun Context.retrieveTheme(): Theme = when (getDefaultSharedPreferences(this).getString("manager_theme", SystemDefault)) { -// SystemDefault -> if (isSystemInDarkTheme()) Theme.DARK else Theme.LIGHT -// Dark -> Theme.DARK -// else -> Theme.LIGHT -//} -// -//val Context.isDarkTheme: Boolean -// get() = retrieveTheme() == Theme.DARK -// -//fun Context.ManagerTheme( -// content: @Composable () -> Unit -//) { -// MaterialTheme( -// colors = if (isDarkTheme) darkColors else lightColors, -// content = content -// ) -//} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/core/EmptyPreference.kt b/app/src/main/java/com/vanced/manager/ui/core/EmptyPreference.kt deleted file mode 100644 index 69522bb8ef..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/core/EmptyPreference.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.vanced.manager.ui.core - -import android.content.Context -import android.util.AttributeSet -import android.view.LayoutInflater -import android.widget.FrameLayout -import androidx.core.view.isGone -import androidx.core.view.isVisible -import com.vanced.manager.R -import com.vanced.manager.databinding.ViewPreferenceBinding - -class EmptyPreference @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null, - defStyle: Int = 0, - defStyleRes: Int = 0 -) : FrameLayout(context, attrs, defStyle, defStyleRes) { - - private var _binding: ViewPreferenceBinding? = null - - val binding: ViewPreferenceBinding - get() = requireNotNull(_binding) - - init { - _binding = ViewPreferenceBinding.inflate(LayoutInflater.from(context), this, true) - initAttrs(context, attrs) - } - - fun setTitle(newTitle: String) { - binding.preferenceTitle.text = newTitle - } - - fun setSummary(newSummary: String) { - with(binding) { - preferenceSummary.text = newSummary - preferenceSummary.isVisible = true - preferenceTitle.setPadding(0, 0, 0, 0) - } - } - - private fun initAttrs(context: Context, attrs: AttributeSet?) { - attrs?.let { mAttrs -> - val typedArray = - context.obtainStyledAttributes(mAttrs, R.styleable.EmptyPreference, 0, 0) - val title = typedArray.getText(R.styleable.EmptyPreference_preference_title) - val summary = typedArray.getText(R.styleable.EmptyPreference_preference_summary) - with(binding) { - if (summary != null) { - preferenceSummary.text = summary - } else { - preferenceSummary.isGone = true - preferenceTitle.setPadding(0, 12, 0, 12) - } - preferenceTitle.text = title - } - typedArray.recycle() - } - - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/core/PreferenceCategory.kt b/app/src/main/java/com/vanced/manager/ui/core/PreferenceCategory.kt deleted file mode 100644 index bb7f8591fd..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/core/PreferenceCategory.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.vanced.manager.ui.core - -import android.content.Context -import android.util.AttributeSet -import android.view.LayoutInflater -import android.widget.LinearLayout -import com.vanced.manager.R -import com.vanced.manager.databinding.ViewPreferenceCategoryBinding - -class PreferenceCategory @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null, - defStyle: Int = 0 -) : LinearLayout(context, attrs, defStyle) { - - private var _binding: ViewPreferenceCategoryBinding? = null - - val binding: ViewPreferenceCategoryBinding - get() = requireNotNull(_binding) - - init { - _binding = ViewPreferenceCategoryBinding.inflate(LayoutInflater.from(context), this, true) - initAttrs(context, attrs) - setPadding(0, 4, 0, 0) - orientation = VERTICAL - } - - private fun initAttrs(context: Context, attrs: AttributeSet?) { - attrs.let { mAttrs -> - val typedArray = - context.obtainStyledAttributes(mAttrs, R.styleable.PreferenceCategory, 0, 0) - val title = typedArray.getText(R.styleable.PreferenceCategory_category_title) - - binding.categoryTitle.text = title - typedArray.recycle() - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/core/PreferenceSwitch.kt b/app/src/main/java/com/vanced/manager/ui/core/PreferenceSwitch.kt deleted file mode 100644 index d80c588605..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/core/PreferenceSwitch.kt +++ /dev/null @@ -1,101 +0,0 @@ -package com.vanced.manager.ui.core - -import android.content.Context -import android.content.SharedPreferences -import android.util.AttributeSet -import android.view.LayoutInflater -import android.widget.CompoundButton -import android.widget.FrameLayout -import androidx.core.content.edit -import com.vanced.manager.R -import com.vanced.manager.databinding.ViewPreferenceSwitchBinding -import com.vanced.manager.utils.defPrefs - -class PreferenceSwitch @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null, - defStyle: Int = 0, - defStyleRes: Int = 0 -) : FrameLayout(context, attrs, defStyle, defStyleRes) { - - fun interface OnCheckedListener { - fun onChecked(buttonView: CompoundButton, isChecked: Boolean) - } - - private val prefs by lazy { context.defPrefs } - - var prefKey: String = "" - private set - - var defValue: Boolean = false - private set - - private var mListener: OnCheckedListener? = null - - private val prefListener = - SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, key -> - if (key == prefKey) { - binding.preferenceSwitch.isChecked = sharedPreferences.getBoolean(key, defValue) - } - } - - private var _binding: ViewPreferenceSwitchBinding? = null - - val binding: ViewPreferenceSwitchBinding - get() = requireNotNull(_binding) - - init { - _binding = ViewPreferenceSwitchBinding.inflate(LayoutInflater.from(context), this, true) - prefs.registerOnSharedPreferenceChangeListener(prefListener) - attrs?.let { mAttrs -> - with(context.obtainStyledAttributes(mAttrs, R.styleable.PreferenceSwitch, 0, 0)) { - val title = getText(R.styleable.PreferenceSwitch_switch_title) - val summary = getText(R.styleable.PreferenceSwitch_switch_summary) - val key = getText(R.styleable.PreferenceSwitch_switch_key) - val defValue = getBoolean(R.styleable.PreferenceSwitch_switch_def_value, false) - setKey(key) - setDefaultValue(defValue) - setTitle(title) - setSummary(summary) - recycle() - } - } - } - - override fun onFinishInflate() { - super.onFinishInflate() - setOnClickListener { - binding.preferenceSwitch.isChecked = !binding.preferenceSwitch.isChecked - } - binding.preferenceSwitch.setOnCheckedChangeListener { buttonView, isChecked -> - prefs.edit { putBoolean(prefKey, isChecked) } - mListener?.onChecked(buttonView, isChecked) - } - } - - fun setOnCheckedListener(listener: OnCheckedListener) { - mListener = listener - } - - fun setTitle(title: CharSequence?) { - binding.preferenceSwitchTitle.text = title - } - - fun setSummary(summary: CharSequence?) { - binding.preferenceSwitchSummary.text = summary - } - - fun setKey(key: CharSequence?) { - prefKey = key.toString() - binding.preferenceSwitch.isChecked = prefs.getBoolean(key.toString(), defValue) - } - - fun setDefaultValue(newVal: Boolean) { - defValue = newVal - binding.preferenceSwitch.isChecked = prefs.getBoolean(prefKey, newVal) - } - - fun setChecked(checked: Boolean) { - binding.preferenceSwitch.isChecked = checked - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/core/ThemedAppCard.kt b/app/src/main/java/com/vanced/manager/ui/core/ThemedAppCard.kt deleted file mode 100644 index cabfb2c6ed..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/core/ThemedAppCard.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.vanced.manager.ui.core - -import android.content.Context -import android.content.res.ColorStateList -import android.util.AttributeSet -import com.google.android.material.card.MaterialCardView -import com.vanced.manager.utils.accentColor - -class ThemedAppCard @JvmOverloads constructor( - context: Context, - attributeSet: AttributeSet? = null, - defStyleAttr: Int = 0 -) : MaterialCardView(context, attributeSet, defStyleAttr) { - - init { - setCardBackgroundColor(ColorStateList.valueOf(accentColor.value!!).withAlpha(35)) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/core/ThemedIconButton.kt b/app/src/main/java/com/vanced/manager/ui/core/ThemedIconButton.kt deleted file mode 100644 index 875ae6eb4e..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/core/ThemedIconButton.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.vanced.manager.ui.core - -import android.content.Context -import android.content.res.ColorStateList -import android.util.AttributeSet -import android.widget.Toast -import com.google.android.material.button.MaterialButton -import com.vanced.manager.utils.accentColor - -class ThemedIconButton @JvmOverloads constructor( - context: Context, - attributeSet: AttributeSet? = null, - defStyleAttr: Int = 0 -) : MaterialButton(context, attributeSet, defStyleAttr) { - - init { - iconTint = ColorStateList.valueOf(accentColor.value!!) - setOnLongClickListener { - Toast.makeText(context, contentDescription, Toast.LENGTH_SHORT).show() - true - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/core/ThemedMaterialButton.kt b/app/src/main/java/com/vanced/manager/ui/core/ThemedMaterialButton.kt deleted file mode 100644 index 0e830ca83d..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/core/ThemedMaterialButton.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.vanced.manager.ui.core - -import android.content.Context -import android.util.AttributeSet -import androidx.core.content.res.ResourcesCompat -import androidx.core.graphics.ColorUtils -import com.google.android.material.button.MaterialButton -import com.vanced.manager.R -import com.vanced.manager.utils.accentColor -import com.vanced.manager.utils.lifecycleOwner - -class ThemedMaterialButton @JvmOverloads constructor( - context: Context, - attributeSet: AttributeSet? = null, - defStyleAttr: Int = 0 -) : MaterialButton(context, attributeSet, defStyleAttr) { - - init { - context.lifecycleOwner?.let { owner -> - accentColor.observe(owner) { color -> - setBgColor(color.toInt()) - } - } - } - - private fun setBgColor(color: Int) { - setBackgroundColor(color) - if (ColorUtils.calculateLuminance(color) < 0.7) { - setTextColor(ResourcesCompat.getColor(resources, R.color.White, null)) - } else { - setTextColor(ResourcesCompat.getColor(resources, R.color.Black, null)) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/core/ThemedMaterialCheckbox.kt b/app/src/main/java/com/vanced/manager/ui/core/ThemedMaterialCheckbox.kt deleted file mode 100644 index 4b8001bf2b..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/core/ThemedMaterialCheckbox.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.vanced.manager.ui.core - -import android.content.Context -import android.content.res.ColorStateList -import android.util.AttributeSet -import com.google.android.material.checkbox.MaterialCheckBox -import com.vanced.manager.R -import com.vanced.manager.utils.accentColor - -class ThemedMaterialCheckbox @JvmOverloads constructor( - context: Context, - attributeSet: AttributeSet? = null, -) : MaterialCheckBox(context, attributeSet, R.attr.checkboxStyle) { - init { - buttonTintList = ColorStateList.valueOf(accentColor.value!!) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/core/ThemedMaterialRadioButton.kt b/app/src/main/java/com/vanced/manager/ui/core/ThemedMaterialRadioButton.kt deleted file mode 100644 index 895bcf51cc..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/core/ThemedMaterialRadioButton.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.vanced.manager.ui.core - -import android.content.Context -import android.content.res.ColorStateList -import android.util.AttributeSet -import com.google.android.material.radiobutton.MaterialRadioButton -import com.vanced.manager.R -import com.vanced.manager.utils.accentColor - -class ThemedMaterialRadioButton @JvmOverloads constructor( - context: Context, - attributeSet: AttributeSet? = null, -) : MaterialRadioButton(context, attributeSet, R.attr.radioButtonStyle) { - init { - buttonTintList = ColorStateList.valueOf(accentColor.value!!) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/core/ThemedMaterialSlider.kt b/app/src/main/java/com/vanced/manager/ui/core/ThemedMaterialSlider.kt deleted file mode 100644 index 8653121b73..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/core/ThemedMaterialSlider.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.vanced.manager.ui.core - -import android.content.Context -import android.content.res.ColorStateList -import android.util.AttributeSet -import com.google.android.material.slider.Slider -import com.vanced.manager.utils.accentColor - -class ThemedMaterialSlider @JvmOverloads constructor( - context: Context, - attributeSet: AttributeSet? = null, - defStyleAttr: Int = 0 -) : Slider(context, attributeSet, defStyleAttr) { - - init { - val accentValue = ColorStateList.valueOf(accentColor.value!!) - thumbTintList = accentValue - trackActiveTintList = accentValue - trackInactiveTintList = accentValue.withAlpha(70) - haloTintList = accentValue.withAlpha(60) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/core/ThemedOutlinedMaterialButton.kt b/app/src/main/java/com/vanced/manager/ui/core/ThemedOutlinedMaterialButton.kt deleted file mode 100644 index f8ac0e85db..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/core/ThemedOutlinedMaterialButton.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.vanced.manager.ui.core - -import android.content.Context -import android.content.res.ColorStateList -import android.util.AttributeSet -import androidx.core.graphics.ColorUtils -import com.google.android.material.button.MaterialButton -import com.vanced.manager.utils.accentColor -import com.vanced.manager.utils.lifecycleOwner - -class ThemedOutlinedMaterialButton @JvmOverloads constructor( - context: Context, - attributeSet: AttributeSet? = null, - defStyleAttr: Int = 0 -) : MaterialButton(context, attributeSet, defStyleAttr) { - init { - context.lifecycleOwner?.let { owner -> - accentColor.observe(owner) { color -> - applyAccent(color.toInt()) - } - } - } - - private fun applyAccent(color: Int) { - setTextColor(color) - rippleColor = ColorStateList( - arrayOf(intArrayOf()), - intArrayOf(ColorUtils.setAlphaComponent(color, 50)) - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/core/ThemedSwipeRefreshlayout.kt b/app/src/main/java/com/vanced/manager/ui/core/ThemedSwipeRefreshlayout.kt deleted file mode 100644 index 123da47b4d..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/core/ThemedSwipeRefreshlayout.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.vanced.manager.ui.core - -import android.content.Context -import android.util.AttributeSet -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout -import com.vanced.manager.R -import com.vanced.manager.utils.accentColor - -class ThemedSwipeRefreshlayout @JvmOverloads constructor( - context: Context, - attributeSet: AttributeSet? = null -) : SwipeRefreshLayout(context, attributeSet) { - init { - setColorSchemeColors(accentColor.value!!) - initAttrs(context, attributeSet) - } - - private fun initAttrs(context: Context, attributeSet: AttributeSet?) { - attributeSet.let { - val typedAttrs = - context.obtainStyledAttributes(it, R.styleable.ThemedSwipeRefreshlayout, 0, 0) - setProgressBackgroundColorSchemeColor( - typedAttrs.getColor( - R.styleable.ThemedSwipeRefreshlayout_progressBackgroundColor, - 0 - ) - ) - typedAttrs.recycle() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/core/ThemedSwitchCompat.kt b/app/src/main/java/com/vanced/manager/ui/core/ThemedSwitchCompat.kt deleted file mode 100644 index adcbd52b9e..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/core/ThemedSwitchCompat.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.vanced.manager.ui.core - -import android.content.Context -import android.content.res.ColorStateList -import android.graphics.Color -import android.util.AttributeSet -import androidx.appcompat.widget.SwitchCompat -import androidx.core.graphics.ColorUtils -import androidx.core.graphics.drawable.DrawableCompat -import com.vanced.manager.R -import com.vanced.manager.utils.accentColor -import com.vanced.manager.utils.lifecycleOwner - -class ThemedSwitchCompat @JvmOverloads constructor( - context: Context, - attributeSet: AttributeSet? = null, -) : SwitchCompat(context, attributeSet, R.attr.switchStyle) { - - private val states = - arrayOf(intArrayOf(-android.R.attr.state_checked), intArrayOf(android.R.attr.state_checked)) - - init { - context.lifecycleOwner?.let { owner -> - accentColor.observe(owner) { color -> - setSwitchColors(color.toInt()) - } - } - } - - private fun setSwitchColors(color: Int) { - val thumbColors = intArrayOf(Color.LTGRAY, color) - val trackColors = intArrayOf(Color.GRAY, ColorUtils.setAlphaComponent(color, 70)) - DrawableCompat.setTintList( - DrawableCompat.wrap(thumbDrawable), - ColorStateList(states, thumbColors) - ) - DrawableCompat.setTintList( - DrawableCompat.wrap(trackDrawable), - ColorStateList(states, trackColors) - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/core/ThemedTextView.kt b/app/src/main/java/com/vanced/manager/ui/core/ThemedTextView.kt deleted file mode 100644 index 86af8211d4..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/core/ThemedTextView.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.vanced.manager.ui.core - -import android.content.Context -import android.util.AttributeSet -import androidx.appcompat.widget.AppCompatTextView -import com.vanced.manager.utils.accentColor -import com.vanced.manager.utils.lifecycleOwner - -class ThemedTextView @JvmOverloads constructor( - context: Context, - attributeSet: AttributeSet? = null, - defStyleAttr: Int = 0 -) : AppCompatTextView(context, attributeSet, defStyleAttr) { - init { - context.lifecycleOwner?.let { owner -> - accentColor.observe(owner) { color -> - setTextColor(color.toInt()) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/AppDownloadDialog.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/AppDownloadDialog.kt deleted file mode 100644 index a1bf20892d..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/AppDownloadDialog.kt +++ /dev/null @@ -1,125 +0,0 @@ -package com.vanced.manager.ui.dialogs - -import android.annotation.SuppressLint -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import android.content.IntentFilter -import android.graphics.Color -import android.graphics.drawable.ColorDrawable -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.core.view.isVisible -import androidx.localbroadcastmanager.content.LocalBroadcastManager -import com.vanced.manager.R -import com.vanced.manager.core.downloader.MicrogDownloader.downloadMicrog -import com.vanced.manager.core.downloader.MusicDownloader.downloadMusic -import com.vanced.manager.core.downloader.VancedDownloader.downloadVanced -import com.vanced.manager.core.ui.base.BindingDialogFragment -import com.vanced.manager.databinding.DialogAppDownloadBinding -import com.vanced.manager.utils.* - -class AppDownloadDialog : BindingDialogFragment() { - - companion object { - - const val CLOSE_DIALOG = "close_dialog" - private const val TAG_APP = "TAG_APP" - private const val TAG_VERSION = "TAG_VERSION" - private const val TAG_INSTALLING = "TAG_INSTALLING" - - fun newInstance( - app: String, - version: String? = null, - installing: Boolean = false - ): AppDownloadDialog = AppDownloadDialog().apply { - arguments = Bundle().apply { - putString(TAG_APP, app) - putString(TAG_VERSION, version) - putBoolean(TAG_INSTALLING, installing) - } - } - } - - private val localBroadcastManager by lazy { LocalBroadcastManager.getInstance(requireActivity()) } - - private val broadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() { - override fun onReceive(context: Context, intent: Intent) { - if (intent.action == CLOSE_DIALOG) { - dismiss() - } - } - } - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogAppDownloadBinding.inflate(inflater, container, false) - - override fun otherSetups() { - dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) - bindData() - } - - private fun bindData() { - with(binding) { - isCancelable = false - binding.appDownloadProgressbar.applyAccent() - binding.appInstallProgressbar.applyAccent() - bindDownloadProgress() - val app = arguments?.getString(TAG_APP) - appDownloadHeader.text = app - if (arguments?.getBoolean(TAG_INSTALLING) == false) { - when (app) { - getString(R.string.vanced) -> downloadVanced( - requireContext(), - arguments?.getString(TAG_VERSION) - ) - getString(R.string.music) -> downloadMusic( - requireContext(), - arguments?.getString(TAG_VERSION) - ) - getString(R.string.microg) -> downloadMicrog(requireContext()) - } - } - } - } - - @SuppressLint("SetTextI18n") - private fun DialogAppDownloadBinding.bindDownloadProgress() { - downloadProgress.observe(viewLifecycleOwner) { - appDownloadProgressbar.progress = it - appDownloadProgress.text = "$it%" - } - installing.observe(viewLifecycleOwner) { installing -> - appDownloadProgressbarContainer.isVisible = !installing - appInstallProgressbar.isVisible = installing - appDownloadFile.isVisible = !installing - appDownloadCancel.isEnabled = !installing - appDownloadCancel.setOnClickListener { - if (installing) { - return@setOnClickListener - } - currentDownload?.cancel() - downloadProgress.value = 0 - dismiss() - } - } - downloadingFile.observe(viewLifecycleOwner) { - appDownloadFile.text = it - } - } - - override fun onResume() { - super.onResume() - registerReceiver() - } - - private fun registerReceiver() { - val intentFilter = IntentFilter() - intentFilter.addAction(CLOSE_DIALOG) - localBroadcastManager.registerReceiver(broadcastReceiver, intentFilter) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/AppInfoDialog.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/AppInfoDialog.kt deleted file mode 100644 index c3faeaafec..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/AppInfoDialog.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.vanced.manager.ui.dialogs - -import android.graphics.Color -import android.graphics.drawable.ColorDrawable -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.annotation.DrawableRes -import com.vanced.manager.R -import com.vanced.manager.core.ui.base.BindingDialogFragment -import com.vanced.manager.databinding.DialogAppInfoBinding - -class AppInfoDialog : BindingDialogFragment() { - - companion object { - - private const val TAG_APP_NAME = "TAG_APP_NAME" - private const val TAG_APP_ICON = "TAG_APP_ICON" - private const val TAG_CHANGELOG = "TAG_CHANGELOG" - - fun newInstance( - appName: String?, - @DrawableRes appIcon: Int?, - changelog: String? - ): AppInfoDialog = AppInfoDialog().apply { - arguments = Bundle().apply { - putString(TAG_APP_NAME, appName) - putString(TAG_CHANGELOG, changelog) - if (appIcon != null) { - putInt(TAG_APP_ICON, appIcon) - } - } - } - } - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogAppInfoBinding.inflate(inflater, container, false) - - override fun otherSetups() { - dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) - bindData() - } - - private fun bindData() { - with(binding) { - aboutAppName.text = getString(R.string.about_app, arguments?.getString(TAG_APP_NAME)) - aboutAppChangelog.text = arguments?.getString(TAG_CHANGELOG) - arguments?.getInt(TAG_APP_ICON)?.let { aboutAppImage.setImageResource(it) } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/AppUninstallDialog.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/AppUninstallDialog.kt deleted file mode 100644 index d6c1db6d7a..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/AppUninstallDialog.kt +++ /dev/null @@ -1,50 +0,0 @@ -package com.vanced.manager.ui.dialogs - -import android.app.Activity -import android.graphics.Color -import android.graphics.drawable.ColorDrawable -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import com.vanced.manager.R -import com.vanced.manager.core.ui.base.BindingDialogFragment -import com.vanced.manager.databinding.DialogAppUninstallBinding - -class AppUninstallDialog : BindingDialogFragment() { - - companion object { - - private var TAG_APP_NAME: String? = null - - fun newInstance(appName: String?) : AppUninstallDialog = AppUninstallDialog().apply { - arguments = Bundle().apply { - TAG_APP_NAME = appName - } - } - } - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogAppUninstallBinding.inflate(inflater, container, false) - - override fun otherSetups() { - dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) - bindData() - } - - private fun bindData() { - with(binding) { - appUninstallConfirm.setOnClickListener { - //uninstall instruction ?? - //dataModel?.appPkg?.let { it1 -> viewModel.uninstallPackage(it1) } (taken from original ExpandanbleAppListAdapter.kt) - //but uninstallPackage method is not static so I would be forced to spawn a new HomeViewModel instance - } - appUninstallCancel.setOnClickListener { - dismiss() - } - appUninstallMessage.text = getString(R.string.uninstall_app_text, TAG_APP_NAME) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/AppVersionSelectorDialog.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/AppVersionSelectorDialog.kt deleted file mode 100644 index a57983d3f9..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/AppVersionSelectorDialog.kt +++ /dev/null @@ -1,94 +0,0 @@ -package com.vanced.manager.ui.dialogs - -import android.content.DialogInterface -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.core.content.edit -import com.google.android.material.radiobutton.MaterialRadioButton -import com.vanced.manager.R -import com.vanced.manager.core.ui.base.BindingBottomSheetDialogFragment -import com.vanced.manager.core.ui.ext.showDialog -import com.vanced.manager.databinding.DialogBottomRadioButtonBinding -import com.vanced.manager.ui.core.ThemedMaterialRadioButton -import com.vanced.manager.utils.checkedButtonTag -import com.vanced.manager.utils.defPrefs -import com.vanced.manager.utils.formatVersion - -class AppVersionSelectorDialog : - BindingBottomSheetDialogFragment() { - - private val prefs by lazy { requireActivity().defPrefs } - - companion object { - - private const val TAG_VERSIONS = "TAG_VERSIONS" - private const val TAG_APP = "TAG_APP" - - fun newInstance( - versions: List?, - app: String - ): AppVersionSelectorDialog = AppVersionSelectorDialog().apply { - arguments = Bundle().apply { - val arrayList = arrayListOf() - versions?.let { arrayList.addAll(it) } - putStringArrayList(TAG_VERSIONS, arrayList) - putString(TAG_APP, app) - } - } - } - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogBottomRadioButtonBinding.inflate(inflater, container, false) - - override fun otherSetups() { - bindData() - } - - private fun bindData() { - with(binding) { - loadBoxes()?.forEach { mrb -> - dialogRadiogroup.addView( - mrb, - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ) - } - val tag = root.findViewWithTag( - prefs.getString("${arguments?.getString(TAG_APP)}_version", "latest") - ) - if (tag != null) { - tag.isChecked = true - } - dialogTitle.text = getString(R.string.version) - dialogSave.setOnClickListener { - val checkedTag = dialogRadiogroup.checkedButtonTag - if (checkedTag != null) { - prefs.edit { putString("${arguments?.getString(TAG_APP)}_version", checkedTag) } - } - dismiss() - } - } - } - - private fun loadBoxes() = - arguments?.getStringArrayList(TAG_VERSIONS)?.map { version -> - ThemedMaterialRadioButton(requireActivity()).apply { - text = version.formatVersion(requireActivity()) - tag = version - textSize = 18f - } - } - - override fun onDismiss(dialog: DialogInterface) { - super.onDismiss(dialog) - if (arguments?.getString(TAG_APP) == "vanced") { - showDialog(VancedPreferencesDialog()) - } else { - showDialog(MusicPreferencesDialog()) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/DialogContainer.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/DialogContainer.kt deleted file mode 100644 index ba34cd253b..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/DialogContainer.kt +++ /dev/null @@ -1,132 +0,0 @@ -package com.vanced.manager.ui.dialogs - -import android.content.Context -import androidx.core.content.edit -import androidx.preference.PreferenceManager -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.vanced.manager.R -import com.vanced.manager.utils.isMiuiOptimizationsEnabled -import com.vanced.manager.utils.openUrl -import com.vanced.manager.utils.showWithAccent - -object DialogContainer { - - fun showSecurityDialog(context: Context) { - MaterialAlertDialogBuilder(context).apply { - setTitle(context.resources.getString(R.string.welcome)) - setMessage(context.resources.getString(R.string.security_context)) - setPositiveButton(context.resources.getString(R.string.close)) { dialog, _ -> - dialog.cancel() - } - setOnCancelListener { - if (context.isMiuiOptimizationsEnabled) { - miuiDialog(context) - } - } - create() - showWithAccent() - } - val prefs = PreferenceManager.getDefaultSharedPreferences(context) - prefs.edit { putBoolean("firstLaunch", false) } - } - - fun miuiDialog(context: Context) { - MaterialAlertDialogBuilder(context).apply { - setTitle(context.getString(R.string.miui_one_title)) - setMessage(context.getString(R.string.miui_one)) - setNeutralButton(context.getString(R.string.close)) { dialog, _ -> dialog.dismiss() } - setPositiveButton(context.getString(R.string.guide)) { _, _ -> - openUrl( - "https://telegra.ph/How-to-install-v15-on-MIUI-02-11", - R.color.Telegram, - context - ) - } - setCancelable(false) - create() - showWithAccent() - } - } - - fun statementFalse(context: Context) { - MaterialAlertDialogBuilder(context).apply { - setTitle("Wait what?") - setMessage("So this statement is false huh? I'll go with True!") - setPositiveButton("wut?") { dialog, _ -> dialog.dismiss() } - create() - showWithAccent() - } - - val prefs = PreferenceManager.getDefaultSharedPreferences(context) - prefs.edit { putBoolean("statement", true) } - } - - fun installAlertBuilder(msg: String, fullMsg: String?, context: Context) { - MaterialAlertDialogBuilder(context).apply { - setTitle(context.getString(R.string.error)) - setMessage(msg) - when (msg) { - context.getString(R.string.installation_signature) -> { - setPositiveButton(context.getString(R.string.guide)) { _, _ -> - openUrl( - "https://lmgtfy.com/?q=andnixsh+apk+verification+disable", - R.color.Twitter, - context - ) - } - setNeutralButton(context.getString(R.string.close)) { dialog, _ -> dialog.dismiss() } - if (fullMsg != null) - setNegativeButton(context.getString(R.string.advanced)) { _, _ -> - basicDialog( - context.getString(R.string.advanced), - fullMsg, - context - ) - } - } - context.getString(R.string.installation_miui) -> { - setPositiveButton(context.getString(R.string.guide)) { _, _ -> - openUrl( - "https://telegra.ph/How-to-install-v15-on-MIUI-02-11", - R.color.Telegram, - context - ) - } - setNeutralButton(context.getString(R.string.close)) { dialog, _ -> dialog.dismiss() } - if (fullMsg != null) - setNegativeButton(context.getString(R.string.advanced)) { _, _ -> - basicDialog( - context.getString(R.string.advanced), - fullMsg, - context - ) - } - } - else -> { - setPositiveButton(context.getString(R.string.close)) { dialog, _ -> dialog.dismiss() } - if (fullMsg != null) - setNegativeButton(context.getString(R.string.advanced)) { _, _ -> - basicDialog( - context.getString(R.string.advanced), - fullMsg, - context - ) - } - } - } - create() - showWithAccent() - } - } - - fun basicDialog(title: String, msg: String, context: Context) { - MaterialAlertDialogBuilder(context).apply { - setTitle(title) - setMessage(msg) - setPositiveButton(context.getString(R.string.close)) { dialog, _ -> dialog.dismiss() } - create() - showWithAccent() - } - } - -} diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/InstallationFilesDetectedDialog.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/InstallationFilesDetectedDialog.kt deleted file mode 100644 index 35292e7e7e..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/InstallationFilesDetectedDialog.kt +++ /dev/null @@ -1,76 +0,0 @@ -package com.vanced.manager.ui.dialogs - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import com.vanced.manager.R -import com.vanced.manager.core.downloader.MicrogDownloader.startMicrogInstall -import com.vanced.manager.core.downloader.MusicDownloader.startMusicInstall -import com.vanced.manager.core.downloader.VancedDownloader.startVancedInstall -import com.vanced.manager.core.ui.base.BindingBottomSheetDialogFragment -import com.vanced.manager.core.ui.ext.showDialog -import com.vanced.manager.databinding.DialogInstallationFilesDetectedBinding -import com.vanced.manager.utils.defPrefs -import com.vanced.manager.utils.managerVariant - -class InstallationFilesDetectedDialog : - BindingBottomSheetDialogFragment() { - - companion object { - - private const val TAG_APP = "TAG_APP" - - fun newInstance( - app: String - ): InstallationFilesDetectedDialog = InstallationFilesDetectedDialog().apply { - arguments = Bundle().apply { - putString(TAG_APP, app) - } - } - } - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogInstallationFilesDetectedBinding.inflate(inflater, container, false) - - override fun otherSetups() { - bindData() - } - - private fun bindData() { - with(binding) { - val app = - arguments?.getString(TAG_APP) ?: throw IllegalArgumentException("app name is null") - installationDetectedTitle.text = getString(R.string.app_install_files_detected, app) - installationDetectedSummary.text = - getString(R.string.app_install_files_detected_summary, app) - installationDetectedRedownload.setOnClickListener { - dismiss() - when (app) { - getString(R.string.vanced) -> showDialog(VancedPreferencesDialog()) - getString(R.string.music) -> showDialog(MusicPreferencesDialog()) - else -> showDialog(AppDownloadDialog.newInstance(app)) - } - } - installationDetectedInstall.setOnClickListener { - dismiss() - when (app) { - getString(R.string.vanced) -> startVancedInstall( - requireContext(), - context?.defPrefs?.managerVariant - ) - getString(R.string.music) -> startMusicInstall(requireContext()) - getString(R.string.microg) -> startMicrogInstall(requireContext()) - } - showDialog( - AppDownloadDialog.newInstance( - app = app, - installing = true - ) - ) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/ManagerAccentColorDialog.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/ManagerAccentColorDialog.kt deleted file mode 100644 index 44219a52e3..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/ManagerAccentColorDialog.kt +++ /dev/null @@ -1,128 +0,0 @@ -package com.vanced.manager.ui.dialogs - -import android.content.DialogInterface -import android.graphics.Color -import android.graphics.drawable.ColorDrawable -import android.os.Bundle -import android.text.Editable -import android.text.TextWatcher -import android.view.LayoutInflater -import android.view.ViewGroup -import android.widget.TextView -import android.widget.Toast -import androidx.preference.PreferenceManager.getDefaultSharedPreferences -import com.madrapps.pikolo.listeners.OnColorSelectionListener -import com.vanced.manager.R -import com.vanced.manager.core.ui.base.BindingDialogFragment -import com.vanced.manager.databinding.DialogManagerAccentColorBinding -import com.vanced.manager.utils.* -import com.vanced.manager.utils.AppUtils.log - -class ManagerAccentColorDialog : BindingDialogFragment() { - - companion object { - fun newInstance(): ManagerAccentColorDialog = ManagerAccentColorDialog().apply { - arguments = Bundle() - } - } - - private val prefs by lazy { getDefaultSharedPreferences(requireActivity()) } - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogManagerAccentColorBinding.inflate(inflater, container, false) - - override fun otherSetups() { - dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) - bindData() - } - - override fun onCancel(dialog: DialogInterface) { - super.onCancel(dialog) - mutableAccentColor.value = prefs.getInt("manager_accent_color", defAccentColor) - } - - private fun bindData() { - with(binding) { - val accent = prefs.getInt("manager_accent_color", defAccentColor) - hexEdittext.apply { - setText(accent.toHex(), TextView.BufferType.EDITABLE) - addTextChangedListener(object : TextWatcher { - override fun beforeTextChanged( - s: CharSequence?, - start: Int, - count: Int, - after: Int - ) { - } - - override fun onTextChanged( - s: CharSequence?, - start: Int, - before: Int, - count: Int - ) { - if (length() == 0) { - setText("#") - setSelection(1) - } - - if (accentColor.value?.toHex() != text.toString() && length() == 7) { - try { - val colorFromEditText = Color.parseColor(text.toString()) - accentPicker.setColor(colorFromEditText) - mutableAccentColor.value = colorFromEditText - } catch (e: IllegalArgumentException) { - } - } - } - - override fun afterTextChanged(s: Editable?) {} - - }) - } - accentPicker.apply { - setColor(accent) - setColorSelectionListener(object : OnColorSelectionListener { - override fun onColorSelected(color: Int) { - mutableAccentColor.value = color - hexEdittext.setText(color.toHex(), TextView.BufferType.EDITABLE) - } - - override fun onColorSelectionEnd(color: Int) {} - - override fun onColorSelectionStart(color: Int) {} - - }) - } - accentCancel.setOnClickListener { - mutableAccentColor.value = accent - dismiss() - } - accentSave.setOnClickListener { - try { - val colorFromEditText = Color.parseColor(hexEdittext.text.toString()) - mutableAccentColor.value = colorFromEditText - prefs.managerAccent = colorFromEditText - } catch (e: IllegalArgumentException) { - log("VMTheme", getString(R.string.failed_accent)) - Toast.makeText( - requireActivity(), - getString(R.string.failed_accent), - Toast.LENGTH_SHORT - ).show() - return@setOnClickListener - } - - dismiss() - } - accentReset.setOnClickListener { - prefs.managerAccent = defAccentColor - mutableAccentColor.value = defAccentColor - dismiss() - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/ManagerLanguageDialog.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/ManagerLanguageDialog.kt deleted file mode 100644 index 73a8f108f3..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/ManagerLanguageDialog.kt +++ /dev/null @@ -1,66 +0,0 @@ -package com.vanced.manager.ui.dialogs - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import android.view.ViewGroup.LayoutParams.MATCH_PARENT -import android.view.ViewGroup.LayoutParams.WRAP_CONTENT -import androidx.preference.PreferenceManager.getDefaultSharedPreferences -import com.vanced.manager.BuildConfig.MANAGER_LANGUAGES -import com.vanced.manager.core.ui.base.BindingBottomSheetDialogFragment -import com.vanced.manager.databinding.DialogManagerLanguageBinding -import com.vanced.manager.ui.core.ThemedMaterialRadioButton -import com.vanced.manager.utils.checkedButtonTag -import com.vanced.manager.utils.getLanguageFormat -import com.vanced.manager.utils.managerLang - -class ManagerLanguageDialog : BindingBottomSheetDialogFragment() { - - companion object { - - fun newInstance(): ManagerLanguageDialog = ManagerLanguageDialog().apply { - arguments = Bundle() - } - } - - private val prefs by lazy { getDefaultSharedPreferences(requireActivity()) } - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogManagerLanguageBinding.inflate(inflater, container, false) - - override fun otherSetups() { - bindData() - } - - private fun bindData() { - with(binding) { - addRadioButtons().forEach { mrb -> - languageRadiogroup.addView(mrb, MATCH_PARENT, WRAP_CONTENT) - } - val language = prefs.managerLang - root.findViewWithTag(language)?.isChecked = true - languageSave.setOnClickListener { - val newPref = binding.languageRadiogroup.checkedButtonTag - if (language != newPref) { - prefs.managerLang = newPref - dismiss() - requireActivity().recreate() - } else { - dismiss() - } - } - } - } - - private fun addRadioButtons() = - (arrayOf("System Default") + MANAGER_LANGUAGES).map { lang -> - ThemedMaterialRadioButton(requireActivity()).apply { - text = getLanguageFormat(requireActivity(), lang) - textSize = 18f - tag = lang - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/ManagerThemeDialog.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/ManagerThemeDialog.kt deleted file mode 100644 index 8113a0edc5..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/ManagerThemeDialog.kt +++ /dev/null @@ -1,50 +0,0 @@ -package com.vanced.manager.ui.dialogs - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.preference.PreferenceManager.getDefaultSharedPreferences -import com.google.android.material.radiobutton.MaterialRadioButton -import com.vanced.manager.core.ui.base.BindingBottomSheetDialogFragment -import com.vanced.manager.databinding.DialogManagerThemeBinding -import com.vanced.manager.utils.checkedButtonTag -import com.vanced.manager.utils.managerTheme - -class ManagerThemeDialog : BindingBottomSheetDialogFragment() { - - companion object { - - fun newInstance(): ManagerThemeDialog = ManagerThemeDialog().apply { - arguments = Bundle() - } - } - - private val prefs by lazy { getDefaultSharedPreferences(requireActivity()) } - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogManagerThemeBinding.inflate(inflater, container, false) - - override fun otherSetups() { - bindData() - } - - private fun bindData() { - with(binding) { - val theme = prefs.managerTheme - root.findViewWithTag(theme).isChecked = true - themeSave.setOnClickListener { - val newPref = themeRadiogroup.checkedButtonTag - if (theme != newPref) { - prefs.managerTheme = newPref - dismiss() - requireActivity().recreate() - } else { - dismiss() - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/ManagerUpdateDialog.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/ManagerUpdateDialog.kt deleted file mode 100644 index e8636cfd53..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/ManagerUpdateDialog.kt +++ /dev/null @@ -1,117 +0,0 @@ -package com.vanced.manager.ui.dialogs - -import android.annotation.SuppressLint -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import android.content.IntentFilter -import android.graphics.Color -import android.graphics.drawable.ColorDrawable -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.core.view.isVisible -import androidx.localbroadcastmanager.content.LocalBroadcastManager -import com.vanced.manager.BuildConfig.VERSION_CODE -import com.vanced.manager.R -import com.vanced.manager.core.ui.base.BindingDialogFragment -import com.vanced.manager.databinding.DialogManagerUpdateBinding -import com.vanced.manager.utils.DownloadHelper.downloadManager -import com.vanced.manager.utils.applyAccent -import com.vanced.manager.utils.currentDownload -import com.vanced.manager.utils.downloadProgress -import com.vanced.manager.utils.manager - -class ManagerUpdateDialog : BindingDialogFragment() { - - companion object { - - const val CLOSE_DIALOG = "CLOSE_DIALOG" - private const val TAG_FORCE_UPDATE = "TAG_FORCE_UPDATE" - - fun newInstance( - forceUpdate: Boolean - ): ManagerUpdateDialog = ManagerUpdateDialog().apply { - arguments = Bundle().apply { - putBoolean(TAG_FORCE_UPDATE, forceUpdate) - } - } - } - - private val localBroadcastManager by lazy { LocalBroadcastManager.getInstance(requireActivity()) } - - private val broadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() { - override fun onReceive(context: Context, intent: Intent) { - when (intent.action) { - CLOSE_DIALOG -> dismiss() - } - } - } - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogManagerUpdateBinding.inflate(inflater, container, false) - - override fun otherSetups() { - dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) - bindData() - if (arguments?.getBoolean(TAG_FORCE_UPDATE) == true) { - binding.managerUpdatePatient.text = - requireActivity().getString(R.string.please_be_patient) - downloadManager(requireActivity()) - } else { - checkUpdates() - } - } - - private fun bindData() { - with(binding) { - isCancelable = false - managerUpdateProgressbar.applyAccent() - managerUpdateCancel.setOnClickListener { - downloadProgress.value = 0 - currentDownload?.cancel() - dismiss() - } - bindDownloadProgress() - } - } - - @SuppressLint("SetTextI18n") - private fun DialogManagerUpdateBinding.bindDownloadProgress() { - downloadProgress.observe(viewLifecycleOwner) { - managerUpdateProgressbar.progress = it - managerUpdateProgressbarContainer.isVisible = it != 0 - managerUpdateProgress.text = "$it%" - } - } - - override fun onResume() { - super.onResume() - registerReceiver() - } - - override fun onPause() { - super.onPause() - localBroadcastManager.unregisterReceiver(broadcastReceiver) - } - - private fun checkUpdates() { - if (manager.value?.int("versionCode") ?: 0 > VERSION_CODE) { - binding.managerUpdatePatient.text = - requireActivity().getString(R.string.please_be_patient) - downloadManager(requireActivity()) - } else { - binding.managerUpdatePatient.text = - requireActivity().getString(R.string.update_not_found) - } - } - - private fun registerReceiver() { - val intentFilter = IntentFilter() - intentFilter.addAction(CLOSE_DIALOG) - localBroadcastManager.registerReceiver(broadcastReceiver, intentFilter) - } -} diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/ManagerVariantDialog.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/ManagerVariantDialog.kt deleted file mode 100644 index e837a043f2..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/ManagerVariantDialog.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.vanced.manager.ui.dialogs - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.preference.PreferenceManager.getDefaultSharedPreferences -import com.google.android.material.radiobutton.MaterialRadioButton -import com.topjohnwu.superuser.Shell -import com.vanced.manager.core.ui.base.BindingBottomSheetDialogFragment -import com.vanced.manager.databinding.DialogManagerVariantBinding -import com.vanced.manager.utils.checkedButtonTag -import com.vanced.manager.utils.managerVariant - -class ManagerVariantDialog : BindingBottomSheetDialogFragment() { - - companion object { - - fun newInstance(): ManagerVariantDialog = ManagerVariantDialog().apply { - arguments = Bundle() - } - } - - private val prefs by lazy { getDefaultSharedPreferences(requireActivity()) } - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogManagerVariantBinding.inflate(inflater, container, false) - - override fun otherSetups() { - bindData() - } - - private fun bindData() { - with(binding) { - val variant = prefs.managerVariant - root.findViewWithTag(variant).isChecked = true - variantSave.setOnClickListener { - val newPref = variantRadiogroup.checkedButtonTag - if (variant != newPref) { - prefs.managerVariant = - if (newPref == "root" && Shell.rootAccess()) { - "root" - } else { - "nonroot" - } - dismiss() - requireActivity().recreate() - } else { - dismiss() - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/MusicPreferencesDialog.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/MusicPreferencesDialog.kt deleted file mode 100644 index ab39146c8a..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/MusicPreferencesDialog.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.vanced.manager.ui.dialogs - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import com.vanced.manager.R -import com.vanced.manager.core.ui.base.BindingBottomSheetDialogFragment -import com.vanced.manager.core.ui.ext.showDialog -import com.vanced.manager.databinding.DialogMusicPreferencesBinding -import com.vanced.manager.utils.* - -class MusicPreferencesDialog : BindingBottomSheetDialogFragment() { - - companion object { - - fun newInstance(): MusicPreferencesDialog = MusicPreferencesDialog().apply { - arguments = Bundle() - } - } - - private val prefs by lazy { requireActivity().defPrefs } - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogMusicPreferencesBinding.inflate(inflater, container, false) - - override fun otherSetups() { - bindData() - } - - private fun bindData() { - with(binding) { - val musicVersionsConv = musicVersions.value?.value?.convertToAppVersions() - musicInstallTitle.text = - getString(R.string.app_installation_preferences, getString(R.string.music)) - musicVersion.text = getString( - R.string.chosen_version, - prefs.musicVersion?.formatVersion(requireActivity()) - ) - openVersionSelectorLayout.setOnClickListener { - dismiss() - showDialog( - AppVersionSelectorDialog.newInstance( - versions = musicVersionsConv, - app = "music" - ) - ) - } - musicInstall.setOnClickListener { - dismiss() - showDialog( - AppDownloadDialog.newInstance( - app = getString(R.string.music) - ) - ) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/SelectAppsDialog.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/SelectAppsDialog.kt deleted file mode 100644 index f02b93d6c2..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/SelectAppsDialog.kt +++ /dev/null @@ -1,63 +0,0 @@ -package com.vanced.manager.ui.dialogs - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import android.widget.Toast -import androidx.core.content.edit -import androidx.preference.PreferenceManager.getDefaultSharedPreferences -import androidx.recyclerview.widget.LinearLayoutManager -import com.vanced.manager.R -import com.vanced.manager.adapter.SelectAppsAdapter -import com.vanced.manager.core.ui.base.BindingBottomSheetDialogFragment -import com.vanced.manager.databinding.DialogSelectAppsBinding - -class SelectAppsDialog : BindingBottomSheetDialogFragment() { - - companion object { - - fun newInstance(): SelectAppsDialog = SelectAppsDialog().apply { - arguments = Bundle() - } - } - - private val prefs by lazy { getDefaultSharedPreferences(requireActivity()) } - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogSelectAppsBinding.inflate(inflater, container, false) - - override fun otherSetups() { - bindData() - } - - private fun bindData() { - with(binding) { - val ad = SelectAppsAdapter(requireActivity()) - selectAppsRecycler.apply { - layoutManager = LinearLayoutManager(requireActivity()) - adapter = ad - setHasFixedSize(true) - } - selectAppsSave.setOnClickListener { - if (ad.apps.all { app -> !app.isChecked }) { - Toast.makeText( - requireActivity(), - R.string.select_at_least_one_app, - Toast.LENGTH_SHORT - ).show() - return@setOnClickListener - } - prefs.edit { - ad.apps.forEach { app -> - putBoolean("enable_${app.tag}", app.isChecked) - putBoolean("${app.tag}_notifs", app.isChecked) - } - } - dismiss() - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/ServiceDTimerDialog.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/ServiceDTimerDialog.kt deleted file mode 100644 index f78c08c9c7..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/ServiceDTimerDialog.kt +++ /dev/null @@ -1,75 +0,0 @@ -package com.vanced.manager.ui.dialogs - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import android.widget.Toast -import androidx.core.content.edit -import com.vanced.manager.R -import com.vanced.manager.core.ui.base.BindingDialogFragment -import com.vanced.manager.databinding.DialogServicedTimerBinding -import com.vanced.manager.utils.PackageHelper -import com.vanced.manager.utils.PackageHelper.getPackageDir -import com.vanced.manager.utils.PackageHelper.getPkgNameRoot -import com.vanced.manager.utils.PackageHelper.scriptExists -import com.vanced.manager.utils.defPrefs -import com.vanced.manager.utils.writeServiceDScript -import java.io.IOException -import java.util.* - -class ServiceDTimerDialog : BindingDialogFragment() { - - private val prefs by lazy { requireActivity().defPrefs } - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): DialogServicedTimerBinding = DialogServicedTimerBinding.inflate(inflater, container, false) - - override fun otherSetups() { - bindData() - } - - private fun bindData() { - with(binding) { - servicedSlider.value = prefs.getInt("serviced_sleep_timer", 1).toFloat() - servicedCancel.setOnClickListener { - dismiss() - } - servicedSave.setOnClickListener { - try { - arrayOf("vanced", "music").forEach { app -> - if (scriptExists(app)) { - val apkFPath = - "${PackageHelper.apkInstallPath}/${app.capitalize(Locale.ROOT)}/base.apk" - getPackageDir( - requireActivity(), - getPkgNameRoot(app) - )?.let { it1 -> - requireActivity().writeServiceDScript( - apkFPath, - it1, - app - ) - } - } - } - } catch (e: IOException) { - Toast.makeText( - requireActivity(), - R.string.script_save_failed, - Toast.LENGTH_SHORT - ).show() - return@setOnClickListener - } - - prefs.edit { - putInt("serviced_sleep_timer", servicedSlider.value.toInt()) - } - dismiss() - } - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/URLChangeDialog.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/URLChangeDialog.kt deleted file mode 100644 index 779adc6d94..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/URLChangeDialog.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.vanced.manager.ui.dialogs - -import android.graphics.Color -import android.graphics.drawable.ColorDrawable -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import android.widget.TextView -import androidx.lifecycle.lifecycleScope -import com.vanced.manager.core.ui.base.BindingDialogFragment -import com.vanced.manager.databinding.DialogCustomUrlBinding -import com.vanced.manager.utils.* -import kotlinx.coroutines.launch - -class URLChangeDialog : BindingDialogFragment() { - - private val prefs by lazy { requireActivity().defPrefs } - - companion object { - - fun newInstance(): URLChangeDialog = URLChangeDialog().apply { - arguments = Bundle() - } - } - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogCustomUrlBinding.inflate(inflater, container, false) - - override fun otherSetups() { - dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) - bindData() - } - - private fun bindData() { - with(binding) { - urlInput.setText( - if (arguments != null) { - arguments?.getString("url") - } else { - prefs.installUrl - }, - TextView.BufferType.EDITABLE - ) - urlSave.setOnClickListener { - val finalUrl = - if (urlInput.text?.startsWith("https://") == true || urlInput.text?.startsWith("http://") == true) { - urlInput.text?.removeSuffix("/").toString() - } else { - "https://${urlInput.text}".removeSuffix("/") - } - saveUrl(finalUrl) - } - urlReset.setOnClickListener { saveUrl(baseUrl) } - } - } - - private fun saveUrl(url: String) { - lifecycleScope.launch { - prefs.installUrl = url - baseInstallUrl = url - loadJson(requireActivity()) - dismiss() - } - } -} diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/VancedLanguageSelectionDialog.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/VancedLanguageSelectionDialog.kt deleted file mode 100644 index 412f1da756..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/VancedLanguageSelectionDialog.kt +++ /dev/null @@ -1,87 +0,0 @@ -package com.vanced.manager.ui.dialogs - -import android.content.DialogInterface -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import android.view.ViewGroup.LayoutParams.MATCH_PARENT -import android.view.ViewGroup.LayoutParams.WRAP_CONTENT -import android.widget.LinearLayout -import android.widget.Toast -import com.google.android.material.checkbox.MaterialCheckBox -import com.vanced.manager.R -import com.vanced.manager.core.ui.base.BindingBottomSheetDialogFragment -import com.vanced.manager.core.ui.ext.showDialog -import com.vanced.manager.databinding.DialogVancedLanguageSelectionBinding -import com.vanced.manager.ui.core.ThemedMaterialCheckbox -import com.vanced.manager.utils.installPrefs -import com.vanced.manager.utils.lang -import com.vanced.manager.utils.vanced -import java.util.* - -class VancedLanguageSelectionDialog : - BindingBottomSheetDialogFragment() { - - companion object { - - fun newInstance(): VancedLanguageSelectionDialog = VancedLanguageSelectionDialog().apply { - arguments = Bundle() - } - } - - private val langs = vanced.value?.array("langs")?.value - private val prefs by lazy { requireActivity().installPrefs } - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogVancedLanguageSelectionBinding.inflate(inflater, container, false) - - override fun otherSetups() { - bindData() - } - - private fun bindData() { - with(binding) { - langButtonLl.loadBoxes() - vancedInstallFinish.setOnClickListener { - val chosenLangs = mutableListOf() - langs?.forEach { lang -> - if (root.findViewWithTag(lang).isChecked) { - chosenLangs.add(lang) - } - } - if (chosenLangs.isEmpty()) { - Toast.makeText( - requireActivity(), - R.string.select_at_least_one_lang, - Toast.LENGTH_SHORT - ).show() - return@setOnClickListener - } - prefs.lang = chosenLangs.joinToString() - dismiss() - } - } - } - - private fun LinearLayout.loadBoxes() { - val langPrefs = prefs.lang - langs?.forEach { lang -> - val loc = Locale(lang) - val box = ThemedMaterialCheckbox(requireActivity()).apply { - tag = lang - isChecked = langPrefs?.contains(lang) ?: false - text = loc.getDisplayLanguage(loc).capitalize(Locale.ROOT) - textSize = 18F - } - addView(box, MATCH_PARENT, WRAP_CONTENT) - } - } - - override fun onDismiss(dialog: DialogInterface) { - super.onDismiss(dialog) - showDialog(VancedPreferencesDialog()) - } -} diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/VancedPreferencesDialog.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/VancedPreferencesDialog.kt deleted file mode 100644 index 73bd1a1678..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/VancedPreferencesDialog.kt +++ /dev/null @@ -1,84 +0,0 @@ -package com.vanced.manager.ui.dialogs - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import com.vanced.manager.R -import com.vanced.manager.core.ui.base.BindingBottomSheetDialogFragment -import com.vanced.manager.core.ui.ext.showDialog -import com.vanced.manager.databinding.DialogVancedPreferencesBinding -import com.vanced.manager.utils.* -import java.util.* - -class VancedPreferencesDialog : BindingBottomSheetDialogFragment() { - - companion object { - - fun newInstance(): VancedPreferencesDialog = VancedPreferencesDialog().apply { - arguments = Bundle() - } - } - - private val defPrefs by lazy { requireActivity().defPrefs } - private val installPrefs by lazy { requireActivity().installPrefs } - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogVancedPreferencesBinding.inflate(inflater, container, false) - - override fun otherSetups() { - bindData() - } - - private fun bindData() { - with(binding) { - val showLang = mutableListOf() - installPrefs.lang?.split(", ")?.forEach { lang -> - val loc = Locale(lang) - showLang.add(loc.getDisplayLanguage(loc).capitalize(Locale.ROOT)) - } - val vancedVersionsConv = vancedVersions.value?.value?.convertToAppVersions() - vancedInstallTitle.text = - getString(R.string.app_installation_preferences, getString(R.string.vanced)) - vancedTheme.text = getString( - R.string.chosen_theme, - installPrefs.theme?.convertToAppTheme(requireActivity()) - ) - vancedVersion.text = getString( - R.string.chosen_version, - defPrefs.vancedVersion?.formatVersion(requireActivity()) - ) - vancedLang.text = getString(R.string.chosen_lang, showLang) - openThemeSelectorLayout.setOnClickListener { - dismiss() - showDialog(VancedThemeSelectorDialog()) - } - openVersionSelectorLayout.setOnClickListener { - dismiss() - showDialog( - AppVersionSelectorDialog.newInstance( - versions = vancedVersionsConv, - app = "vanced" - ) - ) - } - openLanguageSelectorLayout.setOnClickListener { - dismiss() - showDialog(VancedLanguageSelectionDialog()) - } - vancedInstall.setOnClickListener { - if (showLang.isEmpty()) { - installPrefs.lang = "en" - } - dismiss() - showDialog( - AppDownloadDialog.newInstance( - app = getString(R.string.vanced) - ) - ) - } - } - } -} diff --git a/app/src/main/java/com/vanced/manager/ui/dialogs/VancedThemeSelectorDialog.kt b/app/src/main/java/com/vanced/manager/ui/dialogs/VancedThemeSelectorDialog.kt deleted file mode 100644 index 5b097b1dfe..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/dialogs/VancedThemeSelectorDialog.kt +++ /dev/null @@ -1,81 +0,0 @@ -package com.vanced.manager.ui.dialogs - -import android.content.Context -import android.content.DialogInterface -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import com.vanced.manager.R -import com.vanced.manager.core.ui.base.BindingBottomSheetDialogFragment -import com.vanced.manager.core.ui.ext.showDialog -import com.vanced.manager.databinding.DialogBottomRadioButtonBinding -import com.vanced.manager.ui.core.ThemedMaterialRadioButton -import com.vanced.manager.utils.checkedButtonTag -import com.vanced.manager.utils.convertToAppTheme -import com.vanced.manager.utils.theme -import com.vanced.manager.utils.vanced - -class VancedThemeSelectorDialog : - BindingBottomSheetDialogFragment() { - - companion object { - - fun newInstance(): VancedThemeSelectorDialog = VancedThemeSelectorDialog().apply { - arguments = Bundle() - } - } - - private val prefs by lazy { - requireActivity().getSharedPreferences( - "installPrefs", - Context.MODE_PRIVATE - ) - } - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = DialogBottomRadioButtonBinding.inflate(inflater, container, false) - - override fun otherSetups() { - bindData() - } - - private fun bindData() { - with(binding) { - loadButtons()?.forEach { mrb -> - dialogRadiogroup.addView( - mrb, - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT - ) - } - dialogTitle.text = requireActivity().getString(R.string.theme) - val tag = root.findViewWithTag(prefs.theme) - if (tag != null) { - tag.isChecked = true - } - dialogSave.setOnClickListener { - val checkedTag = binding.dialogRadiogroup.checkedButtonTag - if (checkedTag != null) { - prefs.theme = checkedTag - } - dismiss() - } - } - } - - private fun loadButtons() = vanced.value?.array("themes")?.value?.map { theme -> - ThemedMaterialRadioButton(requireActivity()).apply { - text = theme.convertToAppTheme(requireActivity()) - tag = theme - textSize = 18f - } - } - - override fun onDismiss(dialog: DialogInterface) { - super.onDismiss(dialog) - showDialog(VancedPreferencesDialog()) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/fragments/AboutFragment.kt b/app/src/main/java/com/vanced/manager/ui/fragments/AboutFragment.kt deleted file mode 100644 index 97e83e08c9..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/fragments/AboutFragment.kt +++ /dev/null @@ -1,84 +0,0 @@ -package com.vanced.manager.ui.fragments - -import android.annotation.SuppressLint -import android.os.Bundle -import android.view.LayoutInflater -import android.view.MotionEvent -import android.view.ViewGroup -import android.widget.Toast -import androidx.core.content.edit -import androidx.fragment.app.viewModels -import androidx.preference.PreferenceManager -import com.vanced.manager.R -import com.vanced.manager.core.ui.base.BindingFragment -import com.vanced.manager.core.ui.ext.showDialog -import com.vanced.manager.databinding.FragmentAboutBinding -import com.vanced.manager.ui.dialogs.AppInfoDialog -import com.vanced.manager.ui.viewmodels.AboutViewModel -import com.vanced.manager.utils.manager - -class AboutFragment : BindingFragment() { - - private val viewModel: AboutViewModel by viewModels() - private var count = 0 - private var startMillSec: Long = 0 - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = FragmentAboutBinding.inflate(inflater, container, false) - - override fun otherSetups() { - dataBind() - } - - @SuppressLint("ClickableViewAccessibility") - private fun dataBind() { - requireActivity().title = getString(R.string.title_about) - binding.aboutVersionCard.setOnClickListener { - showDialog( - AppInfoDialog.newInstance( - appName = getString(R.string.app_name), - appIcon = R.mipmap.ic_launcher, - changelog = manager.value?.string("changelog") - ) - ) - } - binding.root.setOnTouchListener { _, event: MotionEvent -> - val eventAction = event.action - if (eventAction == MotionEvent.ACTION_UP) { - val time = System.currentTimeMillis() - if (startMillSec == 0L || time - startMillSec > 3000) { - startMillSec = time - count = 1 - } else { - count++ - } - - if (count == 5) { - val prefs = PreferenceManager.getDefaultSharedPreferences(requireContext()) - val devSettings = prefs.getBoolean("devSettings", false) - if (!devSettings) { - Toast.makeText( - requireContext(), - "Dev options unlocked!", - Toast.LENGTH_SHORT - ).show() - prefs.edit { putBoolean("devSettings", true) } - } else - Toast.makeText( - requireContext(), - "Dev options already unlocked", - Toast.LENGTH_SHORT - ).show() - - } - return@setOnTouchListener true - } - false - } - binding.aboutGithubButton.setOnClickListener { viewModel.openUrl("https://github.com/YTVanced/VancedInstaller") } - binding.aboutLicenseButton.setOnClickListener { viewModel.openUrl("https://raw.githubusercontent.com/YTVanced/VancedInstaller/dev/LICENSE") } - } -} diff --git a/app/src/main/java/com/vanced/manager/ui/fragments/DevSettingsFragment.kt b/app/src/main/java/com/vanced/manager/ui/fragments/DevSettingsFragment.kt deleted file mode 100644 index ef271d6a83..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/fragments/DevSettingsFragment.kt +++ /dev/null @@ -1,115 +0,0 @@ -package com.vanced.manager.ui.fragments - -import android.content.Intent -import android.os.Build -import android.os.Bundle -import android.provider.Settings -import android.view.LayoutInflater -import android.view.ViewGroup -import androidx.annotation.RequiresApi -import androidx.core.content.edit -import androidx.core.net.toUri -import androidx.core.view.isVisible -import androidx.preference.PreferenceManager.getDefaultSharedPreferences -import com.crowdin.platform.Crowdin -import com.vanced.manager.BuildConfig -import com.vanced.manager.core.ui.base.BindingFragment -import com.vanced.manager.databinding.FragmentDevSettingsBinding -import com.vanced.manager.ui.WelcomeActivity -import com.vanced.manager.ui.dialogs.ManagerUpdateDialog -import com.vanced.manager.ui.dialogs.URLChangeDialog -import com.vanced.manager.utils.authCrowdin - -class DevSettingsFragment : BindingFragment() { - - private val prefs by lazy { getDefaultSharedPreferences(requireActivity()) } - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = FragmentDevSettingsBinding.inflate(inflater, container, false) - - override fun otherSetups() { - setHasOptionsMenu(true) - bindData() - } - - private fun bindData() { - with(binding) { - bindWelcomeLauncher() - bindForceUpdate() - bindChannelURL() - bindCrowdin() - bindKernelArch() - bindAndroidVersion() - } - } - - private fun FragmentDevSettingsBinding.bindWelcomeLauncher() { - welcomeScreenLauncher.setOnClickListener { - prefs.edit { - putBoolean("firstLaunch", true) - putBoolean("show_changelog_tooltip", true) - } - startActivity(Intent(requireContext(), WelcomeActivity::class.java)) - requireActivity().finish() - } - } - - private fun FragmentDevSettingsBinding.bindForceUpdate() { - forceManagerUpdate.setOnClickListener { - ManagerUpdateDialog.newInstance(true).show( - requireActivity().supportFragmentManager, - "update_manager" - ) - } - } - - private fun FragmentDevSettingsBinding.bindChannelURL() { - channelUrl.setOnClickListener { - URLChangeDialog().show(childFragmentManager.beginTransaction(), null) - } - } - - private fun FragmentDevSettingsBinding.bindCrowdin() { - if (BuildConfig.ENABLE_CROWDIN_AUTH) { - val isAuthorized = Crowdin.isAuthorized() - crowdinCategory.isVisible = true - - crowdinAuth.isVisible = !isAuthorized - screenshotUploading.isVisible = isAuthorized - realTimeUpdates.isVisible = isAuthorized - - crowdinAuth.setOnClickListener { - requireActivity().authCrowdin() - @RequiresApi(Build.VERSION_CODES.M) - if (!Settings.canDrawOverlays(requireActivity())) { - val intent = Intent( - Settings.ACTION_MANAGE_OVERLAY_PERMISSION, - ("package:" + requireActivity().packageName).toUri() - ) - startActivityForResult(intent, 69) - } - - Crowdin.authorize(requireActivity()) - } - } - } - - private fun FragmentDevSettingsBinding.bindKernelArch() { - val supportedAbis: Array = Build.SUPPORTED_ABIS - - kernelArch.setSummary( - if (supportedAbis.contains("arm64-v8a") || supportedAbis.contains("x86_64")) { - "64bit" - } else { - "32bit" - } - ) - } - - private fun FragmentDevSettingsBinding.bindAndroidVersion() { - androidVersion.setSummary("${Build.VERSION.RELEASE} (API ${Build.VERSION.SDK_INT})") - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/fragments/GrantRootFragment.kt b/app/src/main/java/com/vanced/manager/ui/fragments/GrantRootFragment.kt deleted file mode 100644 index ddf732af8f..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/fragments/GrantRootFragment.kt +++ /dev/null @@ -1,55 +0,0 @@ -package com.vanced.manager.ui.fragments - -import android.content.Intent -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import android.widget.Toast -import androidx.core.content.edit -import androidx.preference.PreferenceManager.getDefaultSharedPreferences -import com.topjohnwu.superuser.Shell -import com.vanced.manager.R -import com.vanced.manager.core.ui.base.BindingFragment -import com.vanced.manager.databinding.FragmentGrantRootBinding -import com.vanced.manager.ui.MainActivity - -class GrantRootFragment : BindingFragment() { - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = FragmentGrantRootBinding.inflate(inflater, container, false) - - override fun otherSetups() { - bindData() - } - - private fun bindData() { - with(binding) { - grantRootFinishFab.setOnClickListener { navigateToFirstLaunch() } - grantRootFab.setOnClickListener { grantRoot() } - } - } - - private fun navigateToFirstLaunch() { - val intent = Intent(requireActivity(), MainActivity::class.java) - intent.putExtra("firstLaunch", true) - startActivity(intent) - requireActivity().finish() - } - - private fun grantRoot() { - if (Shell.rootAccess()) { - getDefaultSharedPreferences(requireActivity()).edit { - putString( - "vanced_variant", - "root" - ) - } - navigateToFirstLaunch() - } else { - Toast.makeText(requireActivity(), R.string.root_not_granted, Toast.LENGTH_SHORT).show() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/fragments/HomeFragment.kt b/app/src/main/java/com/vanced/manager/ui/fragments/HomeFragment.kt deleted file mode 100644 index f342f237bc..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/fragments/HomeFragment.kt +++ /dev/null @@ -1,118 +0,0 @@ -package com.vanced.manager.ui.fragments - -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import android.content.IntentFilter -import android.os.Bundle -import android.view.LayoutInflater -import android.view.Menu -import android.view.MenuInflater -import android.view.ViewGroup -import androidx.fragment.app.viewModels -import androidx.localbroadcastmanager.content.LocalBroadcastManager -import androidx.recyclerview.widget.LinearLayoutManager -import com.crowdin.platform.util.inflateWithCrowdin -import com.google.android.flexbox.FlexboxLayoutManager -import com.google.android.flexbox.JustifyContent -import com.vanced.manager.R -import com.vanced.manager.adapter.ExpandableAppListAdapter -import com.vanced.manager.adapter.LinkAdapter -import com.vanced.manager.adapter.SponsorAdapter -import com.vanced.manager.core.ui.base.BindingFragment -import com.vanced.manager.databinding.FragmentHomeBinding -import com.vanced.manager.ui.dialogs.DialogContainer.installAlertBuilder -import com.vanced.manager.ui.viewmodels.HomeViewModel -import com.vanced.manager.ui.viewmodels.HomeViewModelFactory -import com.vanced.manager.utils.isFetching - -class HomeFragment : BindingFragment() { - - companion object { - const val INSTALL_FAILED = "INSTALL_FAILED" - const val REFRESH_HOME = "REFRESH_HOME" - } - - private val viewModel: HomeViewModel by viewModels { - HomeViewModelFactory(requireActivity()) - } - - private val localBroadcastManager by lazy { LocalBroadcastManager.getInstance(requireActivity()) } - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = FragmentHomeBinding.inflate(inflater, container, false) - - override fun otherSetups() { - bindData() - } - - private fun bindData() { - requireActivity().title = getString(R.string.title_home) - setHasOptionsMenu(true) - with(binding) { - homeRefresh.setOnRefreshListener { viewModel.fetchData() } - isFetching.observe(viewLifecycleOwner) { homeRefresh.isRefreshing = it } - - recyclerAppList.apply { - layoutManager = LinearLayoutManager(requireActivity()) - adapter = ExpandableAppListAdapter(requireActivity(), viewModel /*, tooltip*/) - setHasFixedSize(true) - } - - recyclerSponsors.apply { - val lm = FlexboxLayoutManager(requireActivity()) - lm.justifyContent = JustifyContent.SPACE_EVENLY - layoutManager = lm - setHasFixedSize(true) - adapter = SponsorAdapter(requireActivity(), viewModel) - } - - recyclerLinks.apply { - val lm = FlexboxLayoutManager(requireActivity()) - lm.justifyContent = JustifyContent.SPACE_EVENLY - layoutManager = lm - setHasFixedSize(true) - adapter = LinkAdapter(requireActivity(), viewModel) - } - } - } - - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - inflater.inflateWithCrowdin(R.menu.toolbar_menu, menu, resources) - super.onCreateOptionsMenu(menu, inflater) - } - - override fun onPause() { - super.onPause() - localBroadcastManager.unregisterReceiver(broadcastReceiver) - } - - override fun onResume() { - super.onResume() - registerReceivers() - } - - private val broadcastReceiver: BroadcastReceiver = object : BroadcastReceiver() { - override fun onReceive(context: Context, intent: Intent) { - when (intent.action) { - INSTALL_FAILED -> installAlertBuilder( - intent.getStringExtra("errorMsg").toString(), - intent.getStringExtra("fullErrorMsg"), - requireActivity() - ) - REFRESH_HOME -> viewModel.fetchData() - } - } - } - - private fun registerReceivers() { - val intentFilter = IntentFilter() - intentFilter.addAction(INSTALL_FAILED) - intentFilter.addAction(REFRESH_HOME) - localBroadcastManager.registerReceiver(broadcastReceiver, intentFilter) - } -} - diff --git a/app/src/main/java/com/vanced/manager/ui/fragments/LogFragment.kt b/app/src/main/java/com/vanced/manager/ui/fragments/LogFragment.kt deleted file mode 100644 index 94a1affaa3..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/fragments/LogFragment.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.vanced.manager.ui.fragments - -import android.os.Bundle -import android.text.TextUtils -import android.view.LayoutInflater -import android.view.ViewGroup -import android.widget.Toast -import com.vanced.manager.R -import com.vanced.manager.core.ui.base.BindingFragment -import com.vanced.manager.databinding.FragmentLogBinding -import com.vanced.manager.utils.AppUtils.logs -import java.io.File -import java.io.FileWriter -import java.io.IOException -import java.util.* - -class LogFragment : BindingFragment() { - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = FragmentLogBinding.inflate(inflater, container, false) - - override fun otherSetups() { - binding.bindData() - } - - private fun FragmentLogBinding.bindData() { - val logs = TextUtils.concat(*logs.toTypedArray()) - logText.text = logs - logSave.setOnClickListener { - try { - val calendar = Calendar.getInstance() - val year = calendar.get(Calendar.YEAR) - val month = calendar.get(Calendar.MONTH) - val day = calendar.get(Calendar.DAY_OF_MONTH) - val hour = calendar.get(Calendar.HOUR_OF_DAY) - val minute = calendar.get(Calendar.MINUTE) - val second = calendar.get(Calendar.SECOND) - val log = - File(requireActivity().getExternalFilesDir("logs")?.path + "/$year$month${day}_$hour$minute$second.log") - FileWriter(log).apply { - append(logs) - flush() - close() - } - Toast.makeText(requireActivity(), R.string.logs_saved, Toast.LENGTH_SHORT).show() - } catch (e: IOException) { - Toast.makeText(requireActivity(), R.string.logs_not_saved, Toast.LENGTH_SHORT) - .show() - } - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/fragments/SelectAppsFragment.kt b/app/src/main/java/com/vanced/manager/ui/fragments/SelectAppsFragment.kt deleted file mode 100644 index 809f8d5b39..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/fragments/SelectAppsFragment.kt +++ /dev/null @@ -1,58 +0,0 @@ -package com.vanced.manager.ui.fragments - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import android.widget.Toast -import androidx.core.content.edit -import androidx.preference.PreferenceManager.getDefaultSharedPreferences -import androidx.recyclerview.widget.LinearLayoutManager -import com.vanced.manager.R -import com.vanced.manager.adapter.SelectAppsAdapter -import com.vanced.manager.core.ui.base.BindingFragment -import com.vanced.manager.databinding.FragmentSelectAppsBinding -import com.vanced.manager.ui.WelcomeActivity - -class SelectAppsFragment : BindingFragment() { - - private lateinit var selectAdapter: SelectAppsAdapter - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = FragmentSelectAppsBinding.inflate(inflater, container, false) - - override fun otherSetups() { - bindData() - } - - private fun bindData() { - with(binding) { - initRecycler() - selectAppsFab.setOnClickListener { actionOnClickAppsFab() } - } - } - - private fun FragmentSelectAppsBinding.initRecycler() { - selectAdapter = SelectAppsAdapter(requireActivity()) - selectAppsRecycler.apply { - layoutManager = LinearLayoutManager(requireActivity()) - setHasFixedSize(true) - adapter = selectAdapter - } - } - - private fun actionOnClickAppsFab() { - if (selectAdapter.apps.all { app -> !app.isChecked }) { - Toast.makeText(requireActivity(), R.string.select_at_least_one_app, Toast.LENGTH_SHORT) - .show() - return - } - val prefs = getDefaultSharedPreferences(requireActivity()) - selectAdapter.apps.forEach { app -> - prefs.edit { putBoolean("enable_${app.tag}", app.isChecked) } - } - (requireActivity() as WelcomeActivity).navigateTo(2) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/fragments/SettingsFragment.kt b/app/src/main/java/com/vanced/manager/ui/fragments/SettingsFragment.kt deleted file mode 100644 index 28afa7c4c9..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/fragments/SettingsFragment.kt +++ /dev/null @@ -1,154 +0,0 @@ -package com.vanced.manager.ui.fragments - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.Menu -import android.view.MenuInflater -import android.view.ViewGroup -import android.widget.Toast -import androidx.core.view.isVisible -import androidx.fragment.app.FragmentActivity -import androidx.preference.PreferenceManager.getDefaultSharedPreferences -import androidx.recyclerview.widget.LinearLayoutManager -import com.google.firebase.analytics.FirebaseAnalytics -import com.google.firebase.crashlytics.FirebaseCrashlytics -import com.google.firebase.perf.FirebasePerformance -import com.vanced.manager.R -import com.vanced.manager.adapter.GetNotifAdapter -import com.vanced.manager.core.ui.base.BindingFragment -import com.vanced.manager.core.ui.ext.showDialog -import com.vanced.manager.databinding.FragmentSettingsBinding -import com.vanced.manager.ui.dialogs.* -import com.vanced.manager.utils.accentColor -import com.vanced.manager.utils.defAccentColor -import com.vanced.manager.utils.getLanguageFormat -import com.vanced.manager.utils.toHex -import java.io.File - -class SettingsFragment : BindingFragment() { - - private companion object { - const val LIGHT = "Light" - const val DARK = "Dark" - } - - private val prefs by lazy { getDefaultSharedPreferences(requireActivity()) } - - private lateinit var variant: String - private lateinit var parentActivity: FragmentActivity - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = FragmentSettingsBinding.inflate(inflater, container, false) - - override fun otherSetups() { - setHasOptionsMenu(true) - parentActivity = requireActivity() - bindData() - } - - private fun bindData() { - with(binding) { - variant = prefs.getString("vanced_variant", "nonroot").toString() - bindRecycler() - bindFirebase() - bindManagerVariant() - bindServiceDTimer() - bindClearFiles() - bindManagerTheme() - bindManagerAccentColor() - bindManagerLanguage() - selectApps.setOnClickListener { showDialog(SelectAppsDialog()) } - } - } - - private fun FragmentSettingsBinding.bindRecycler() { - notificationsRecycler.apply { - layoutManager = LinearLayoutManager(parentActivity) - adapter = GetNotifAdapter(parentActivity) - } - } - - private fun FragmentSettingsBinding.bindFirebase() { - firebase.setOnCheckedListener { _, isChecked -> - FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(isChecked) - FirebasePerformance.getInstance().isPerformanceCollectionEnabled = isChecked - FirebaseAnalytics.getInstance(parentActivity).setAnalyticsCollectionEnabled(isChecked) - } - } - - private fun FragmentSettingsBinding.bindManagerVariant() { - managerVariant.apply { - setSummary(variant) - setOnClickListener { showDialog(ManagerVariantDialog()) } - } - } - - private fun FragmentSettingsBinding.bindServiceDTimer() { - servicedTimer.apply { - if (variant == "root") this.isVisible = true - setOnClickListener { showDialog(ServiceDTimerDialog()) } - } - } - - private fun FragmentSettingsBinding.bindClearFiles() { - clearFiles.setOnClickListener { - with(requireActivity()) { - listOf( - "vanced/nonroot", - "vanced/root", - "music/nonroot", - "music/root", - "microg" - ).forEach { dir -> - File(getExternalFilesDir(dir)?.path.toString()).deleteRecursively() - } - Toast.makeText(this, getString(R.string.cleared_files), Toast.LENGTH_SHORT).show() - } - } - } - - private fun FragmentSettingsBinding.bindManagerTheme() { - val themePref = prefs.getString("manager_theme", "System Default") - managerTheme.apply { - setSummary( - when (themePref) { - LIGHT -> getString(R.string.theme_light) - DARK -> getString(R.string.theme_dark) - else -> getString(R.string.system_default) - } - ) - setOnClickListener { showDialog(ManagerThemeDialog()) } - } - } - - private fun FragmentSettingsBinding.bindManagerAccentColor() { - managerAccentColor.apply { - setSummary(prefs.getInt("manager_accent_color", defAccentColor).toHex()) - setOnClickListener { showDialog(ManagerAccentColorDialog()) } - accentColor.observe(viewLifecycleOwner) { - setSummary(it.toHex()) - } - } - } - - private fun FragmentSettingsBinding.bindManagerLanguage() { - val langPref = prefs.getString("manager_lang", "System Default") - managerLanguage.apply { - setSummary(getLanguageFormat(parentActivity, requireNotNull(langPref))) - setOnClickListener { showDialog(ManagerLanguageDialog()) } - } - - } - - override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { - val devSettings = - getDefaultSharedPreferences(requireActivity()).getBoolean("devSettings", false) - if (devSettings) { - inflater.inflate(R.menu.dev_settings_menu, menu) - } - super.onCreateOptionsMenu(menu, inflater) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/fragments/SettingsFragmentCompose.kt b/app/src/main/java/com/vanced/manager/ui/fragments/SettingsFragmentCompose.kt deleted file mode 100644 index 401a92a34c..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/fragments/SettingsFragmentCompose.kt +++ /dev/null @@ -1,56 +0,0 @@ -package com.vanced.manager.ui.fragments - -//import android.os.Bundle -//import android.view.LayoutInflater -//import android.view.View -//import android.view.ViewGroup -//import androidx.compose.foundation.lazy.LazyColumn -//import androidx.compose.ui.platform.ComposeView -//import androidx.fragment.app.Fragment -//import com.vanced.manager.R -//import com.vanced.manager.ui.compose.Preference -//import com.vanced.manager.ui.compose.PreferenceCategory -//import com.vanced.manager.ui.compose.SwitchPreference -// -//class SettingsFragmentCompose : Fragment() { -// -// override fun onCreateView( -// inflater: LayoutInflater, -// container: ViewGroup?, -// savedInstanceState: Bundle? -// ): View { -// return ComposeView(requireActivity()).apply { -// setContent { -// LazyColumn { -// // use `item` for separate elements like headers -// // and `items` for lists of identical elements -// item { -// PreferenceCategory( -// categoryTitle = getString(R.string.category_behaviour) -// ) { -// SwitchPreference( -// preferenceTitle = getString(R.string.use_custom_tabs), -// preferenceDescription = getString(R.string.link_custom_tabs), -// preferenceKey = "use_custom_tabs" -// ) -// } -// } -// item { -// PreferenceCategory( -// categoryTitle = getString(R.string.category_appearance) -// ) { -// Preference( -// preferenceTitle = "test", -// preferenceDescription = "test", -// ) {} -// Preference( -// preferenceTitle = "test" -// ) {} -// } -// } -// } -// } -// } -// } -// -//} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/fragments/WelcomeFragment.kt b/app/src/main/java/com/vanced/manager/ui/fragments/WelcomeFragment.kt deleted file mode 100644 index 3b6f309b17..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/fragments/WelcomeFragment.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.vanced.manager.ui.fragments - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import com.vanced.manager.core.ui.base.BindingFragment -import com.vanced.manager.databinding.FragmentWelcomeBinding -import com.vanced.manager.ui.WelcomeActivity - -class WelcomeFragment : BindingFragment() { - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = FragmentWelcomeBinding.inflate(inflater, container, false) - - override fun otherSetups() { - bindData() - } - - private fun bindData() { - binding.welcomeGetStarted.setOnClickListener { - (requireActivity() as WelcomeActivity).navigateTo(1) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/AboutLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/AboutLayout.kt new file mode 100644 index 0000000000..faacd8b4ad --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/layouts/AboutLayout.kt @@ -0,0 +1,193 @@ +package com.vanced.manager.ui.layouts + +import android.content.res.Configuration.UI_MODE_NIGHT_YES +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.items +import androidx.compose.material.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Circle +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Brush +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.withStyle +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.vanced.manager.ui.composables.HeaderCard +import com.vanced.manager.ui.composables.ManagerCard +import com.vanced.manager.ui.composables.ManagerLazyColumn +import com.vanced.manager.ui.composables.managerTextColor +import com.vanced.manager.ui.theme.ComposeTestTheme +import com.vanced.manager.ui.theme.vancedBlue +import com.vanced.manager.ui.theme.vancedRed + +data class Credit( + val creditName: String, + val persons: List +) + +data class Source( + val sourceLink: String +) + +private val credits = listOf( + Credit( + creditName = "Vanced Team", + persons = listOf( + "xfileFIN", + "ZaneZam", + "Laura Almeida", + "KevinX8" + ) + ), + Credit( + creditName = "Manager Team", + persons = listOf( + "Xinto", + "Koopah", + "Logan" + ) + ), + Credit( + creditName = "Other Contributors", + persons = listOf( + "bhatVikrant", + "bawm", + "AioiLight", + "HaliksaR" + ) + ) +) + +private val sources = listOf( + Source( + "" + ), + Source( + "" + ) +) + +@ExperimentalStdlibApi +@Composable +@Preview( + showSystemUi = true, + uiMode = UI_MODE_NIGHT_YES +) +fun AboutDarkMode() { + ComposeTestTheme { + AboutLayout() + } +} + +@ExperimentalStdlibApi +@Composable +@Preview( + showSystemUi = true +) +fun AboutLightMode() { + MaterialTheme { + AboutLayout() + } +} + +@ExperimentalStdlibApi +@Composable +fun AboutLayout() { + ManagerLazyColumn { + item { + ManagerCard { + Column( + modifier = Modifier + .background( + Brush.horizontalGradient( + colors = listOf( + vancedBlue, + vancedRed + ), + ) + ) + ) { + Spacer(modifier = Modifier.size(width = 0.dp, height = 8.dp)) + Text( + text = "Vanced Manager", + textAlign = TextAlign.Center, + modifier = Modifier.fillMaxWidth(), + fontSize = 30.sp, + color = Color.White + ) + Text( + text = buildAnnotatedString { + append("Re") + withStyle(style = SpanStyle(Color(0xFFBBB529))) { + append("@Compose") + } + append("d") + }, + textAlign = TextAlign.Center, + modifier = Modifier.fillMaxWidth(), + fontSize = 16.sp, + color = Color.White + ) + Spacer(modifier = Modifier.size(width = 0.dp, height = 8.dp)) + } + } + } + + items(credits) { credit -> + Spacer(modifier = Modifier.size(width = 0.dp, height = 12.dp)) + CreditsCard(creditName = credit.creditName, persons = credit.persons) + } + + item { + Spacer(modifier = Modifier.size(width = 0.dp, height = 12.dp)) + HeaderCard( + headerName = "Sources" + ) { + Row(modifier = Modifier.fillMaxWidth()) { + sources.forEach { _ -> + Box( + modifier = Modifier.weight(1f), + contentAlignment = Alignment.Center + ) { + Icon(imageVector = Icons.Default.Circle, contentDescription = null, modifier = Modifier.size(36.dp)) + } + } + } + Spacer(modifier = Modifier.size(8.dp)) + } + } + } +} + +@Composable +@ExperimentalStdlibApi +fun CreditsCard( + creditName: String, + persons: List +) { + HeaderCard( + headerName = creditName + ) { + CompositionLocalProvider( + LocalContentAlpha provides ContentAlpha.medium, + LocalContentColor provides managerTextColor() + ) { + Text( + text = persons.joinToString("\n"), + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 12.dp), + fontSize = 13.sp + ) + } + Spacer(modifier = Modifier.size(width = 0.dp, height = 2.dp)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt new file mode 100644 index 0000000000..85da6594c3 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt @@ -0,0 +1,122 @@ +package com.vanced.manager.ui.layouts + +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.util.fastForEachIndexed +import com.google.accompanist.swiperefresh.SwipeRefresh +import com.google.accompanist.swiperefresh.SwipeRefreshIndicator +import com.google.accompanist.swiperefresh.rememberSwipeRefreshState +import com.vanced.manager.R +import com.vanced.manager.domain.model.Link +import com.vanced.manager.ui.composables.* +import com.vanced.manager.ui.viewmodel.HomeViewModel +import org.koin.androidx.compose.getViewModel + +private val sponsors = listOf( + Link( + title = "Brave" + ), + Link( + title = "Adguard" + ) +) + +//Lol +private val socialMedia = listOf( + Link( + title = "Instagram" + ), + Link( + title = "Instagram" + ), + Link( + title = "Instagram" + ), + Link( + title = "Instagram" + ), + Link( + title = "Instagram" + ), + Link( + title = "Instagram" + ), + Link( + title = "Instagram" + ), + Link( + title = "Instagram" + ), + Link( + title = "Instagram" + ), + Link( + title = "Instagram" + ), +) + +@ExperimentalAnimationApi +@Composable +@Preview +fun HomeLayout() { + val viewModel: HomeViewModel = getViewModel() + val refreshState = rememberSwipeRefreshState(isRefreshing = viewModel.isFetching) + SwipeRefresh( + state = refreshState, + onRefresh = { viewModel.fetch() }, + indicator = { state, trigger -> + SwipeRefreshIndicator( + state = state, + refreshTriggerDistance = trigger, + scale = true, + contentColor = managerAccentColor() + ) + } + ) { + ManagerScrollableColumn { + HomeHeaderView(headerName = "Apps") { + viewModel.apps.fastForEachIndexed { index, app -> + val rememberedApp by remember { app } + AppCard(rememberedApp) + if (index != viewModel.apps.size - 1) { + Spacer(modifier = Modifier.size(height = 8.dp, width = 0.dp)) + } + } + } + ManagerCardSeparator() + HomeHeaderView( + modifier = Modifier.fillMaxWidth(), + headerName = "Support Us" + ) { + ScrollableLinkRow(items = sponsors) { sponsor -> + LinkCard( + icon = R.drawable.ic_android_black_24dp, + title = sponsor.title, + link = "https://m.youtube.com" + ) + } + } + ManagerCardSeparator() + HomeHeaderView( + modifier = Modifier.fillMaxWidth(), + headerName = "Social media" + ) { + ScrollableLinkRow(items = socialMedia) { socialMedia -> + LinkCard( + icon = R.drawable.ic_android_black_24dp, + title = socialMedia.title, + link = "https://m.youtube.com" + ) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt new file mode 100644 index 0000000000..5cd985b629 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt @@ -0,0 +1,41 @@ +package com.vanced.manager.ui.layouts + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.lazy.items +import androidx.compose.material.FloatingActionButton +import androidx.compose.material.Icon +import androidx.compose.material.Scaffold +import androidx.compose.material.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Share +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.vanced.manager.ui.composables.ManagerLazyColumn +import com.vanced.manager.ui.composables.managerAccentColor +import com.vanced.manager.ui.composables.managerSurfaceColor +import com.vanced.manager.util.logs + +@Composable +fun LogLayout() { + Scaffold( + modifier = Modifier.fillMaxSize(), + floatingActionButton = { + FloatingActionButton( + onClick = { /*TODO*/ }, + backgroundColor = managerAccentColor() + ) { + Icon( + imageVector = Icons.Default.Share, + contentDescription = "share" + ) + } + }, + backgroundColor = managerSurfaceColor() + ) { + ManagerLazyColumn { + items(logs) { log -> + Text(text = log.body) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt new file mode 100644 index 0000000000..ac6ad0d636 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt @@ -0,0 +1,117 @@ +package com.vanced.manager.ui.layouts + +import androidx.compose.foundation.layout.* +import androidx.compose.material.* +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.vanced.manager.ui.composables.* +import com.vanced.manager.ui.preferences.RadioButtonPreference +import com.vanced.manager.ui.theme.managerTheme + +data class NotificationPrefModel( + val app: String, + val prefKey: String +) + +private val notificationApps = arrayOf( + NotificationPrefModel( + app = "YouTube Vanced", + prefKey = "vanced" + ), + NotificationPrefModel( + app = "YouTube Music Vanced", + prefKey = "music" + ), + NotificationPrefModel( + app = "Vanced microG", + prefKey = "microg" + ) +) + +@ExperimentalStdlibApi +@ExperimentalMaterialApi +@Composable +fun SettingsLayout() { + var showDialog by remember { mutableStateOf(false) } + ManagerScrollableColumn { + HeaderCard(headerName = "Behaviour") { + SwitchPreference( + preferenceTitle = "Use Custom Tabs", + preferenceDescription = "Links will open in chrome custom tabs", + preferenceKey = "use_custom_tabs" + ) + notificationApps.forEach { + with (it) { + SwitchPreference( + preferenceTitle = "$app Push Notifications", + preferenceDescription = "Receive push notifications when an update for $app is released", + preferenceKey = "${prefKey}_notifications" + ) + } + } + Preference( + preferenceTitle = "Variant", + preferenceDescription = "nonroot", + onClick = {} + ) + Preference( + preferenceTitle = "Clear downloaded files", + onClick = {} + ) + } + Spacer(modifier = Modifier.size(12.dp)) + HeaderCard(headerName = "Appearance") { + Preference( + preferenceTitle = "Accent Color", + onClick = { + showDialog = true + } + ) + DialogRadioButtonPreference( + preferenceTitle = "Theme", + preferenceKey = "manager_theme", + defaultValue = "Light", + buttons = listOf( + RadioButtonPreference( + title = "Light Theme", + preferenceValue = "Light" + ), + RadioButtonPreference( + title = "Dark Theme", + preferenceValue = "Dark" + ), + RadioButtonPreference( + title = "System Default", + preferenceValue = "System Default" + ) + ) + ) { + managerTheme = it + } + } + } + if (showDialog) { + AlertDialog( + onDismissRequest = { showDialog = false }, + text = { + HSLColorPicker() +// AndroidView( +// factory = { +// HSLColorPicker(it) +// }, +// update = { view -> +// view.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 800) +// view.setColorSelectionListener(object : SimpleColorSelectionListener() { +// override fun onColorSelected(color: Int) { +// accentColorInt = color +// } +// }) +// } +// ) + }, + buttons = {} + ) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/RadioButtonPreference.kt b/app/src/main/java/com/vanced/manager/ui/preferences/RadioButtonPreference.kt new file mode 100644 index 0000000000..7ab5325d66 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/preferences/RadioButtonPreference.kt @@ -0,0 +1,6 @@ +package com.vanced.manager.ui.preferences + +data class RadioButtonPreference( + val title: String, + val preferenceValue: String +) diff --git a/app/src/main/java/com/vanced/manager/ui/screens/Screen.kt b/app/src/main/java/com/vanced/manager/ui/screens/Screen.kt new file mode 100644 index 0000000000..8bb151c9c8 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/screens/Screen.kt @@ -0,0 +1,8 @@ +package com.vanced.manager.ui.screens + +sealed class Screen(val route: String, val displayName: String) { + object Home : Screen("home", "Manager") + object Settings : Screen("settings", "Settings") + object About : Screen("about", "About") + object Logs : Screen("logs", "Logs") +} diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Color.kt b/app/src/main/java/com/vanced/manager/ui/theme/Color.kt new file mode 100644 index 0000000000..740269d383 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/theme/Color.kt @@ -0,0 +1,11 @@ +package com.vanced.manager.ui.theme + +import androidx.compose.ui.graphics.Color + +val purple200 = Color(0xFFBB86FC) +val purple500 = Color(0xFF6200EE) +val purple700 = Color(0xFF3700B3) +val teal200 = Color(0xFF03DAC5) + +val vancedBlue = Color(0xFF2E73FF) +val vancedRed = Color(0xFFFF0032) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Shape.kt b/app/src/main/java/com/vanced/manager/ui/theme/Shape.kt new file mode 100644 index 0000000000..2cfab954dd --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/theme/Shape.kt @@ -0,0 +1,11 @@ +package com.vanced.manager.ui.theme + +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Shapes +import androidx.compose.ui.unit.dp + +val shapes = Shapes( + small = RoundedCornerShape(4.dp), + medium = RoundedCornerShape(4.dp), + large = RoundedCornerShape(0.dp) +) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt new file mode 100644 index 0000000000..70b25b9c13 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt @@ -0,0 +1,53 @@ +package com.vanced.manager.ui.theme + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material.Colors +import androidx.compose.material.MaterialTheme +import androidx.compose.material.darkColors +import androidx.compose.material.lightColors +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.compose.ui.graphics.Color + +var managerTheme by mutableStateOf("") + +private val DarkColorPalette = darkColors( + primary = purple200, + primaryVariant = purple700, + secondary = teal200 +) + +private val LightColorPalette = lightColors( + primary = purple500, + primaryVariant = purple700, + secondary = teal200, + surface = Color(0xFFE9E9E9) +) + +val Colors.cardColor: Color get() = if (isLight) Color(0xFFF7F7F7) else Color(0xFF191919) + +val Colors.managerAccentColor: Color get() = Color(0xFF2E73FF) + +@Composable +fun isDark(): Boolean = when (managerTheme) { + "Dark" -> true + "Light" -> false + "System Default" -> isSystemInDarkTheme() + else -> throw IllegalArgumentException("Unknown theme") +} + +@Composable +fun ComposeTestTheme( + content: @Composable () -> Unit +) { + val colors = if (isDark()) DarkColorPalette else LightColorPalette + + MaterialTheme( + colors = colors, + typography = typography, + shapes = shapes, + content = content + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Type.kt b/app/src/main/java/com/vanced/manager/ui/theme/Type.kt new file mode 100644 index 0000000000..42a97096a0 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/theme/Type.kt @@ -0,0 +1,28 @@ +package com.vanced.manager.ui.theme + +import androidx.compose.material.Typography +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.sp + +// Set of Material typography styles to start with +val typography = Typography( + body1 = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 16.sp + ) + /* Other default text styles to override + button = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.W500, + fontSize = 14.sp + ), + caption = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Normal, + fontSize = 12.sp + ) + */ +) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt new file mode 100644 index 0000000000..bb7b9a25aa --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt @@ -0,0 +1,69 @@ +package com.vanced.manager.ui.viewmodel + +import android.content.Context +import android.util.Log +import androidx.compose.runtime.* +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import androidx.preference.PreferenceManager.getDefaultSharedPreferences +import com.vanced.manager.domain.model.App +import com.vanced.manager.repository.JsonRepository +import kotlinx.coroutines.launch + +class HomeViewModel( + context: Context, + private val repository: JsonRepository +) : ViewModel() { + + private val vanced = mutableStateOf(App()) + private val music = mutableStateOf(App()) + private val microg = mutableStateOf(App()) + private var manager = mutableStateOf(App()) + + var isFetching by mutableStateOf(false) + + val apps = mutableStateListOf>() + + fun fetch() { + viewModelScope.launch { + isFetching = true + try { + with(repository.fetch()) { + this@HomeViewModel.vanced.value = vanced + this@HomeViewModel.music.value = music + this@HomeViewModel.microg.value = microg + } + } catch (e: Exception) { + Log.d("HomeViewModel", "failed to fetch: $e") + } + + isFetching = false + } + } + + init { + + val prefs = getDefaultSharedPreferences(context) + val variant = prefs.getString("manager_variant", "nonroot") + val vancedEnabled = prefs.getBoolean("manager_vanced_enabled", true) + val musicEnabled = prefs.getBoolean("manager_music_enabled", true) + + apps.apply { + if (vancedEnabled) { + add(vanced) + } + + if (musicEnabled) { + add(music) + } + + if (variant == "nonroot") { + add(microg) + } + + } + + fetch() + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodels/AboutViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodels/AboutViewModel.kt deleted file mode 100644 index 2926b3d1a7..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/viewmodels/AboutViewModel.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.vanced.manager.ui.viewmodels - -import android.app.Application -import androidx.lifecycle.AndroidViewModel -import com.vanced.manager.R -import com.vanced.manager.utils.openUrl - -class AboutViewModel(application: Application) : AndroidViewModel(application) { - - fun openUrl(url: String) { - openUrl(url, R.color.GitHub, getApplication()) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodels/HomeViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodels/HomeViewModel.kt deleted file mode 100644 index c880f707ba..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/viewmodels/HomeViewModel.kt +++ /dev/null @@ -1,229 +0,0 @@ -package com.vanced.manager.ui.viewmodels - -import android.annotation.SuppressLint -import android.content.ActivityNotFoundException -import android.content.ComponentName -import android.content.Intent -import android.widget.Toast -import androidx.fragment.app.FragmentActivity -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import androidx.preference.PreferenceManager.getDefaultSharedPreferences -import com.crowdin.platform.Crowdin -import com.vanced.manager.R -import com.vanced.manager.adapter.LinkAdapter.Companion.DISCORD -import com.vanced.manager.adapter.LinkAdapter.Companion.REDDIT -import com.vanced.manager.adapter.LinkAdapter.Companion.TELEGRAM -import com.vanced.manager.adapter.LinkAdapter.Companion.TWITTER -import com.vanced.manager.adapter.SponsorAdapter.Companion.BRAVE -import com.vanced.manager.model.ButtonTag -import com.vanced.manager.model.DataModel -import com.vanced.manager.model.RootDataModel -import com.vanced.manager.ui.dialogs.AppDownloadDialog -import com.vanced.manager.ui.dialogs.InstallationFilesDetectedDialog -import com.vanced.manager.ui.dialogs.MusicPreferencesDialog -import com.vanced.manager.ui.dialogs.VancedPreferencesDialog -import com.vanced.manager.utils.* -import com.vanced.manager.utils.AppUtils.log -import com.vanced.manager.utils.AppUtils.managerPkg -import com.vanced.manager.utils.AppUtils.microgPkg -import com.vanced.manager.utils.AppUtils.musicPkg -import com.vanced.manager.utils.AppUtils.musicRootPkg -import com.vanced.manager.utils.AppUtils.vancedPkg -import com.vanced.manager.utils.AppUtils.vancedRootPkg -import com.vanced.manager.utils.PackageHelper.apkExist -import com.vanced.manager.utils.PackageHelper.musicApkExists -import com.vanced.manager.utils.PackageHelper.uninstallApk -import com.vanced.manager.utils.PackageHelper.uninstallRootApk -import com.vanced.manager.utils.PackageHelper.vancedInstallFilesExist -import kotlinx.coroutines.launch - -//TODO fix leak -@SuppressLint("StaticFieldLeak") -class HomeViewModel(private val activity: FragmentActivity) : ViewModel() { - - private val prefs = getDefaultSharedPreferences(activity) - private val variant get() = prefs.getString("vanced_variant", "nonroot") - - val vancedModel = MutableLiveData() - val vancedRootModel = MutableLiveData() - val microgModel = MutableLiveData() - val musicModel = MutableLiveData() - val musicRootModel = MutableLiveData() - val managerModel = MutableLiveData() - - fun fetchData() { - viewModelScope.launch { - loadJson(activity) - Crowdin.forceUpdate(activity) - } - } - - private val microgToast = Toast.makeText(activity, R.string.no_microg, Toast.LENGTH_LONG) - - fun openUrl(url: String) { - val color: Int = - when (url) { - DISCORD -> R.color.Discord - TELEGRAM -> R.color.Telegram - TWITTER -> R.color.Twitter - REDDIT -> R.color.Reddit - BRAVE -> R.color.Brave - else -> R.color.Vanced - } - - openUrl(url, color, activity) - } - - fun launchApp(app: String, isRoot: Boolean) { - val componentName = when (app) { - activity.getString(R.string.vanced) -> if (isRoot) ComponentName( - vancedRootPkg, - "$vancedRootPkg.HomeActivity" - ) else ComponentName(vancedPkg, "$vancedRootPkg.HomeActivity") - activity.getString(R.string.music) -> if (isRoot) ComponentName( - musicRootPkg, - "$musicRootPkg.activities.MusicActivity" - ) else ComponentName(musicPkg, "$musicRootPkg.activities.MusicActivity") - activity.getString(R.string.microg) -> ComponentName( - microgPkg, - "org.microg.gms.ui.SettingsActivity" - ) - else -> throw IllegalArgumentException("Can't open this app") - } - try { - activity.startActivity(Intent().setComponent(componentName)) - } catch (e: ActivityNotFoundException) { - log("VMHMV", e.toString()) - } - - } - - fun openInstallDialog(buttonTag: ButtonTag?, app: String) { - if (variant == "nonroot" && app != activity.getString(R.string.microg) && !microgModel.value?.isAppInstalled?.value!!) { - microgToast.show() - return - } - - if (buttonTag == ButtonTag.UPDATE) { - when (app) { - activity.getString(R.string.vanced) -> VancedPreferencesDialog().show(activity) - activity.getString(R.string.music) -> MusicPreferencesDialog().show(activity) - else -> AppDownloadDialog.newInstance(app).show(activity) - } - return - } - - when (app) { - activity.getString(R.string.vanced) -> { - when (variant) { - "nonroot" -> { - if (vancedInstallFilesExist(activity)) { - InstallationFilesDetectedDialog.newInstance(app).show(activity) - } else { - VancedPreferencesDialog().show(activity) - } - } - "root" -> { - VancedPreferencesDialog().show(activity) - } - } - } - activity.getString(R.string.music) -> { - when (variant) { - "nonroot" -> { - if (musicApkExists(activity)) { - InstallationFilesDetectedDialog.newInstance(app).show(activity) - } else { - MusicPreferencesDialog().show(activity) - } - } - "root" -> { - MusicPreferencesDialog().show(activity) - } - } - } - activity.getString(R.string.microg) -> { - if (apkExist(activity, "microg.apk")) { - InstallationFilesDetectedDialog.newInstance(app).show(activity) - } else { - AppDownloadDialog.newInstance(app).show(activity) - } - } - } - - } - - fun uninstallPackage(pkg: String) { - if (variant == "root" && uninstallRootApk(pkg)) { - viewModelScope.launch { loadJson(activity) } - } else { - uninstallApk(pkg, activity) - } - } - - init { - with(activity) { - if (variant == "root") { - vancedRootModel.value = RootDataModel( - vanced, - this, - this, - vancedRootPkg, - this.getString(R.string.vanced), - activity.getString(R.string.description_vanced), - R.drawable.ic_vanced, - "vanced" - ) - musicRootModel.value = RootDataModel( - music, - this, - this, - musicRootPkg, - this.getString(R.string.music), - activity.getString(R.string.description_vanced_music), - R.drawable.ic_music, - "music" - ) - } else { - vancedModel.value = DataModel( - vanced, - this, - this, - vancedPkg, - this.getString(R.string.vanced), - activity.getString(R.string.description_vanced), - R.drawable.ic_vanced - ) - musicModel.value = DataModel( - music, - this, - this, - musicPkg, - this.getString(R.string.music), - activity.getString(R.string.description_vanced_music), - R.drawable.ic_music - ) - microgModel.value = DataModel( - microg, - this, - this, - microgPkg, - this.getString(R.string.microg), - activity.getString(R.string.description_microg), - R.drawable.ic_microg - ) - } - managerModel.value = DataModel( - manager, - this, - this, - managerPkg, - this.getString(R.string.app_name), - "Just manager meh", - R.mipmap.ic_launcher - ) - } - } -} diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodels/HomeViewModelFactory.kt b/app/src/main/java/com/vanced/manager/ui/viewmodels/HomeViewModelFactory.kt deleted file mode 100644 index ef7e8d1668..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/viewmodels/HomeViewModelFactory.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.vanced.manager.ui.viewmodels - -import androidx.fragment.app.FragmentActivity -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider - -class HomeViewModelFactory(private val activity: FragmentActivity) : ViewModelProvider.Factory { - - @Suppress("UNCHECKED_CAST") - override fun create(modelClass: Class): T { - return HomeViewModel(activity) as T - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/util/Log.kt b/app/src/main/java/com/vanced/manager/util/Log.kt new file mode 100644 index 0000000000..33646a3663 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/util/Log.kt @@ -0,0 +1,35 @@ +package com.vanced.manager.util + +import android.util.Log +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.withStyle + +data class LogContent( + val body: AnnotatedString, +) + +val logs = mutableListOf() + +fun log(tag: String, message: String) { + Log.i(tag, message) + logs.add( + LogContent( + body = buildAnnotatedString { + withStyle(SpanStyle( + color = Color(0xFF2E73FF), + fontWeight = FontWeight.Bold + )) { + append("$tag:") + } + append("") + withStyle(SpanStyle(color = Color.Magenta)) { + append(message) + } + } + ) + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/util/Variant.kt b/app/src/main/java/com/vanced/manager/util/Variant.kt new file mode 100644 index 0000000000..326d183c53 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/util/Variant.kt @@ -0,0 +1,7 @@ +package com.vanced.manager.util + +enum class Variant { + + Root, Nonroot + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/utils/AppUtils.kt b/app/src/main/java/com/vanced/manager/utils/AppUtils.kt deleted file mode 100644 index 53ef76e85d..0000000000 --- a/app/src/main/java/com/vanced/manager/utils/AppUtils.kt +++ /dev/null @@ -1,143 +0,0 @@ -package com.vanced.manager.utils - -import android.content.Context -import android.content.Intent -import android.graphics.Color -import android.graphics.Typeface -import android.text.Spannable -import android.text.SpannableString -import android.text.style.ForegroundColorSpan -import android.text.style.StyleSpan -import android.util.Log -import androidx.localbroadcastmanager.content.LocalBroadcastManager -import com.vanced.manager.BuildConfig.APPLICATION_ID -import com.vanced.manager.R -import com.vanced.manager.ui.dialogs.AppDownloadDialog -import com.vanced.manager.ui.fragments.HomeFragment -import kotlinx.coroutines.* -import java.io.File -import java.io.IOException -import java.security.MessageDigest -import java.util.* - -object AppUtils : CoroutineScope by CoroutineScope(Dispatchers.IO) { - - const val vancedPkg = "com.vanced.android.youtube" - const val vancedRootPkg = "com.google.android.youtube" - const val musicPkg = "com.vanced.android.apps.youtube.music" - const val musicRootPkg = "com.google.android.apps.youtube.music" - const val microgPkg = "com.mgoogle.android.gms" - const val faqpkg = "com.vanced.faq" - const val managerPkg = APPLICATION_ID - const val playStorePkg = "com.android.vending" - - val logs = mutableListOf() - - var currentLocale: Locale? = null - - fun log(tag: String, message: String) { - logs.add( - SpannableString("$tag: $message\n").apply { - setSpan(ForegroundColorSpan(Color.parseColor("#2e73ff")), 0, tag.length + 1, 0) - setSpan(StyleSpan(Typeface.BOLD), 0, tag.length + 1, 0) - setSpan( - ForegroundColorSpan(Color.MAGENTA), - tag.length + 2, - tag.length + message.length + 2, - 0 - ) - } - ) - Log.d(tag, message) - } - - fun sendRefresh(context: Context): Job { - return launch { - delay(700) - LocalBroadcastManager.getInstance(context) - .sendBroadcast(Intent(HomeFragment.REFRESH_HOME)) - } - } - - fun sendCloseDialog(context: Context): Job { - return launch { - delay(700) - installing.postValue(false) - LocalBroadcastManager.getInstance(context) - .sendBroadcast(Intent(AppDownloadDialog.CLOSE_DIALOG)) - } - } - - fun sendFailure(error: MutableList, context: Context) { - sendFailure(error.joinToString(" "), context) - } - - fun sendFailure(error: String, context: Context): Job { - //Delay error broadcast until activity (and fragment) get back to the screen - return launch { - delay(700) - val intent = Intent(HomeFragment.INSTALL_FAILED) - intent.putExtra("errorMsg", getErrorMessage(error, context)) - intent.putExtra("fullErrorMsg", error) - LocalBroadcastManager.getInstance(context).sendBroadcast(intent) - } - } - - @Throws(IOException::class) - fun generateChecksum(data: ByteArray): String { - try { - val digest: MessageDigest = MessageDigest.getInstance("SHA-256") - val hash: ByteArray = digest.digest(data) - return printableHexString(hash) - } catch (e: Exception) { - e.printStackTrace() - } - - return "" - } - - private fun printableHexString(data: ByteArray): String { - // Create Hex String - val hexString: StringBuilder = StringBuilder() - for (aMessageDigest: Byte in data) { - var h: String = Integer.toHexString(0xFF and aMessageDigest.toInt()) - while (h.length < 2) - h = "0$h" - hexString.append(h) - } - return hexString.toString() - } - - fun validateTheme( - downloadPath: String, - apk: String, - hashUrl: String, - context: Context, - ): Boolean { - val themeF = File(downloadPath, "$apk.apk") - return runBlocking { checkSHA256(getSha256(hashUrl, apk, context), themeF) } - } - - private fun getErrorMessage(status: String, context: Context): String { - log("VMInstall", status) - return when { - status.contains("INSTALL_FAILED_ABORTED") -> context.getString(R.string.installation_aborted) - status.contains("INSTALL_FAILED_ALREADY_EXISTS") -> context.getString(R.string.installation_conflict) - status.contains("INSTALL_FAILED_CPU_ABI_INCOMPATIBLE") -> context.getString(R.string.installation_incompatible) - status.contains("INSTALL_FAILED_INSUFFICIENT_STORAGE") -> context.getString(R.string.installation_storage) - status.contains("INSTALL_FAILED_INVALID_APK") -> context.getString(R.string.installation_invalid) - status.contains("INSTALL_FAILED_VERSION_DOWNGRADE") -> context.getString(R.string.installation_downgrade) - status.contains("INSTALL_PARSE_FAILED_NO_CERTIFICATES") -> context.getString(R.string.installation_signature) - status.contains("Failed_Uninstall") -> context.getString(R.string.failed_uninstall) - status.contains("Chown_Fail") -> context.getString(R.string.chown_fail) - status.contains("IFile_Missing") -> context.getString(R.string.ifile_missing) - status.contains("ModApk_Missing") -> context.getString(R.string.modapk_missing) - status.contains("Files_Missing_VA") -> context.getString(R.string.files_missing_va) - status.contains("Path_Missing") -> context.getString(R.string.path_missing) - status.contains("INSTALL_FAILED_INTERNAL_ERROR: Permission Denied") -> context.getString( - R.string.installation_miui - ) - else -> context.getString(R.string.installation_failed) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/utils/DeviceUtils.kt b/app/src/main/java/com/vanced/manager/utils/DeviceUtils.kt deleted file mode 100644 index 114f29a77e..0000000000 --- a/app/src/main/java/com/vanced/manager/utils/DeviceUtils.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.vanced.manager.utils - -import android.os.Build - -fun getArch(): String = when { - Build.SUPPORTED_ABIS.contains("x86") -> "x86" - Build.SUPPORTED_ABIS.contains("arm64-v8a") -> "arm64_v8a" - else -> "armeabi_v7a" -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/utils/DownloadHelper.kt b/app/src/main/java/com/vanced/manager/utils/DownloadHelper.kt deleted file mode 100644 index 4cc8f1f4f8..0000000000 --- a/app/src/main/java/com/vanced/manager/utils/DownloadHelper.kt +++ /dev/null @@ -1,158 +0,0 @@ -package com.vanced.manager.utils - -import android.content.ActivityNotFoundException -import android.content.Context -import android.content.Intent -import android.net.Uri -import android.os.Build -import androidx.core.content.FileProvider -import com.vanced.manager.R -import com.vanced.manager.library.network.providers.createService -import com.vanced.manager.utils.AppUtils.log -import com.vanced.manager.utils.AppUtils.sendCloseDialog -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import okhttp3.ResponseBody -import retrofit2.Call -import retrofit2.Callback -import retrofit2.Response -import retrofit2.http.GET -import retrofit2.http.Streaming -import retrofit2.http.Url -import java.io.* - -object DownloadHelper : CoroutineScope by CoroutineScope(Dispatchers.IO) { - - interface DownloadHelper { - - @Streaming - @GET - fun download(@Url url: String): Call - - } - - fun download( - url: String, - baseUrl: String, - fileFolder: String, - fileName: String, - context: Context, - onDownloadComplete: () -> Unit = {}, - onError: (error: String) -> Unit = {} - ) { - downloadingFile.postValue(context.getString(R.string.downloading_file, fileName)) - val downloadInterface = createService(DownloadHelper::class, baseUrl) - val download = downloadInterface.download(url) - currentDownload = download - download.enqueue(object : Callback { - override fun onResponse(call: Call, response: Response) { - if (response.isSuccessful) { - launch { - if (response.body()?.let { - writeFile( - it, - context.getExternalFilesDir(fileFolder)?.path + "/" + fileName - ) - } == true) { - onDownloadComplete() - } else { - onError("Could not save file") - downloadProgress.postValue(0) - log( - "VMDownloader", - "Failed to save file: $url\n${response.errorBody()}" - ) - } - } - } else { - val errorBody = response.errorBody().toString() - onError(errorBody) - downloadProgress.postValue(0) - log("VMDownloader", "Failed to download file: $url\n$errorBody") - } - } - - override fun onFailure(call: Call, t: Throwable) { - if (call.isCanceled) { - log("VMDownloader", "Download canceled") - downloadProgress.postValue(0) - } else { - onError(t.stackTraceToString()) - downloadProgress.postValue(0) - log("VMDownloader", "Failed to download file: $url") - } - } - - }) - } - - fun writeFile(body: ResponseBody, filePath: String): Boolean { - return try { - val file = File(filePath) - val totalBytes = body.contentLength() - var inputStream: InputStream? = null - var outputStream: OutputStream? = null - try { - val fileReader = ByteArray(4096) - var downloadedBytes: Long = 0 - inputStream = body.byteStream() - outputStream = FileOutputStream(file) - var read: Int - while (inputStream.read(fileReader).also { read = it } != -1) { - outputStream.write(fileReader, 0, read) - downloadedBytes += read.toLong() - downloadProgress.postValue((downloadedBytes * 100 / totalBytes).toInt()) - } - outputStream.flush() - true - } catch (e: IOException) { - false - } finally { - inputStream?.close() - outputStream?.close() - } - } catch (e: IOException) { - false - } - } - - fun downloadManager(context: Context) { - val url = "https://github.com/YTVanced/VancedManager/releases/latest/download/manager.apk" - download( - url, - "https://github.com/YTVanced/VancedManager/", - "manager", - "manager.apk", - context, - onDownloadComplete = { - val apk = File("${context.getExternalFilesDir("manager")?.path}/manager.apk") - val uri = - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) - FileProvider.getUriForFile(context, "${context.packageName}.provider", apk) - else - Uri.fromFile(apk) - - val intent = Intent(Intent.ACTION_VIEW) - intent.setDataAndType(uri, "application/vnd.android.package-archive") - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - try { - context.startActivity(intent) - } catch (e: ActivityNotFoundException) { - log("VMDownloader", e.stackTraceToString()) - } finally { - sendCloseDialog(context) - } - }, - onError = { - downloadingFile.postValue( - context.getString( - R.string.error_downloading, - "manager.apk" - ) - ) - }) - } - -} diff --git a/app/src/main/java/com/vanced/manager/utils/Extensions.kt b/app/src/main/java/com/vanced/manager/utils/Extensions.kt deleted file mode 100644 index 4d46d33e21..0000000000 --- a/app/src/main/java/com/vanced/manager/utils/Extensions.kt +++ /dev/null @@ -1,87 +0,0 @@ -package com.vanced.manager.utils - -import android.content.Context -import android.content.ContextWrapper -import android.content.DialogInterface -import android.widget.RadioGroup -import androidx.core.graphics.ColorUtils -import androidx.fragment.app.DialogFragment -import androidx.fragment.app.FragmentActivity -import androidx.lifecycle.LifecycleOwner -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.google.android.material.progressindicator.LinearProgressIndicator -import com.google.android.material.radiobutton.MaterialRadioButton -import com.topjohnwu.superuser.io.SuFile -import com.topjohnwu.superuser.io.SuFileOutputStream -import com.vanced.manager.R -import com.vanced.manager.utils.AppUtils.log -import java.util.* - -val RadioGroup.checkedButtonTag: String? - get() = findViewById( - checkedRadioButtonId - )?.tag?.toString() - -fun DialogFragment.show(activity: FragmentActivity) { - try { - show(activity.supportFragmentManager, "") - } catch (e: Exception) { - log("VMUI", e.stackTraceToString()) - } -} - -fun List.convertToAppVersions(): List = listOf("latest") + reversed() - -fun String.formatVersion(context: Context): String = - if (this == "latest") context.getString(R.string.install_latest) else this - -fun String.convertToAppTheme(context: Context): String = with(context) { - getString( - R.string.light_plus_other, - if (this@convertToAppTheme == "dark") getString(R.string.vanced_dark) else getString(R.string.vanced_black) - ) -} - -fun String.getLatestAppVersion(versions: List): String = - if (this == "latest") versions.reversed()[0] else this - -val Context.lifecycleOwner: LifecycleOwner? - get() = when (this) { - is LifecycleOwner -> this - !is LifecycleOwner -> (this as ContextWrapper).baseContext as LifecycleOwner - else -> null - } - -fun Int.toHex(): String = java.lang.String.format("#%06X", 0xFFFFFF and this) - -//Material team decided to keep their LinearProgressIndicator final -//At least extension methods exist -fun LinearProgressIndicator.applyAccent() { - with(accentColor.value!!) { - setIndicatorColor(this) - trackColor = ColorUtils.setAlphaComponent(this, 70) - } -} - -fun MaterialAlertDialogBuilder.showWithAccent() { - with(accentColor.value!!) { - show().apply { - getButton(DialogInterface.BUTTON_POSITIVE).setTextColor(this@with) - getButton(DialogInterface.BUTTON_NEGATIVE).setTextColor(this@with) - getButton(DialogInterface.BUTTON_NEUTRAL).setTextColor(this@with) - } - } -} - -fun Context.writeServiceDScript(apkFPath: String, path: String, app: String) { - val shellFileZ = SuFile.open("/data/adb/service.d/$app.sh") - shellFileZ.createNewFile() - val script = """ - #!/system/bin/sh - while [ "$(getprop sys.boot_completed | tr -d '\r')" != "1" ]; do sleep 1; done - sleep ${defPrefs.serviceDSleepTimer} - chcon u:object_r:apk_data_file:s0 $apkFPath - mount -o bind $apkFPath $path - """.trimIndent() - SuFileOutputStream.open(shellFileZ).use { out -> out.write(script.toByteArray()) } -} diff --git a/app/src/main/java/com/vanced/manager/utils/InstallPrefs.kt b/app/src/main/java/com/vanced/manager/utils/InstallPrefs.kt deleted file mode 100644 index fbdb5b62ac..0000000000 --- a/app/src/main/java/com/vanced/manager/utils/InstallPrefs.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.vanced.manager.utils - -import android.content.Context -import android.content.SharedPreferences -import androidx.core.content.edit - -val Context.installPrefs: SharedPreferences - get() = getSharedPreferences( - "installPrefs", - Context.MODE_PRIVATE - ) - -var SharedPreferences.lang - get() = getString("lang", getDefaultVancedLanguages()) - set(value) = edit { putString("lang", value) } - - -var SharedPreferences.theme - get() = getString("theme", "dark") - set(value) = edit { putString("theme", value) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/utils/InternetTools.kt b/app/src/main/java/com/vanced/manager/utils/InternetTools.kt deleted file mode 100644 index a8601c4213..0000000000 --- a/app/src/main/java/com/vanced/manager/utils/InternetTools.kt +++ /dev/null @@ -1,147 +0,0 @@ -package com.vanced.manager.utils - -import android.content.ActivityNotFoundException -import android.content.Context -import android.content.Intent -import android.util.Log -import android.widget.Toast -import androidx.browser.customtabs.CustomTabColorSchemeParams -import androidx.browser.customtabs.CustomTabsIntent -import androidx.core.content.ContextCompat -import androidx.core.net.toUri -import androidx.lifecycle.MutableLiveData -import androidx.preference.PreferenceManager.getDefaultSharedPreferences -import com.beust.klaxon.JsonArray -import com.beust.klaxon.JsonObject -import com.vanced.manager.R -import com.vanced.manager.utils.AppUtils.generateChecksum -import com.vanced.manager.utils.AppUtils.log -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import java.io.File -import java.io.IOException -import java.net.HttpURLConnection -import java.net.SocketTimeoutException -import java.net.URL -import java.util.* - -private const val TAG = "VMNetTools" - -val vanced = MutableLiveData() -val music = MutableLiveData() -val microg = MutableLiveData() -val manager = MutableLiveData() - -val vancedVersions = MutableLiveData>() -val musicVersions = MutableLiveData>() - -val isFetching = MutableLiveData() - -var isMicrogBroken: Boolean = false - -var baseInstallUrl = "" - -fun openUrl(url: String, color: Int, context: Context) { - try { - val customTabPrefs = - getDefaultSharedPreferences(context).getBoolean("use_custom_tabs", true) - if (customTabPrefs) { - val builder = CustomTabsIntent.Builder() - val params = CustomTabColorSchemeParams.Builder() - .setToolbarColor(ContextCompat.getColor(context, color)) - builder.setDefaultColorSchemeParams(params.build()) - val customTabsIntent = builder.build() - customTabsIntent.intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK - customTabsIntent.launchUrl(context, url.toUri()) - } else - context.startActivity( - Intent( - Intent.ACTION_VIEW, - url.toUri() - ).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - ) - - } catch (e: ActivityNotFoundException) { - Toast.makeText(context, R.string.error, Toast.LENGTH_SHORT).show() - } catch (e: SecurityException) { - Toast.makeText(context, R.string.error, Toast.LENGTH_SHORT).show() - } -} - -fun getFileNameFromUrl(url: String) = url.substring(url.lastIndexOf('/') + 1, url.length) - -//TODO: Use a better connection method that doesn't cause inappropriate blocks -@Suppress("BlockingMethodInNonBlockingContext") -suspend fun loadJson(context: Context) = withContext(Dispatchers.IO) { - isFetching.postValue(true) - val installUrl = context.defPrefs.installUrl - if (baseInstallUrl == "" && installUrl != null) { - baseInstallUrl = installUrl - } - - try { - val latestbaseUrl = "$baseInstallUrl/latest.json" - val connection = URL(latestbaseUrl).openConnection() as HttpURLConnection - connection.apply { - connectTimeout = 5000 - readTimeout = 5000 - connect() - } - if (connection.responseCode != 200) { - log(TAG, latestbaseUrl + ": " + connection.responseCode.toString()) - baseInstallUrl = "https://mirror.codebucket.de/vanced/api/v1" - } - } catch (e: IOException) { - baseInstallUrl = "https://mirror.codebucket.de/vanced/api/v1" - } catch (e: SocketTimeoutException) { - log(TAG, "connection timed out") - baseInstallUrl = "https://mirror.codebucket.de/vanced/api/v1" - } - - log(TAG, "Fetching using URL: $baseInstallUrl") - - val calendar = Calendar.getInstance() - val hour = calendar.get(Calendar.HOUR_OF_DAY) - val minute = calendar.get(Calendar.MINUTE) - val second = calendar.get(Calendar.SECOND) - val fetchTime = "fetchTime=$hour$minute$second" - - val latest = getJson("$baseInstallUrl/latest.json?$fetchTime") - val versions = getJson("$baseInstallUrl/versions.json?$fetchTime") - isMicrogBroken = latest?.boolean("is_microg_broken") ?: false - vanced.postValue(latest?.obj("vanced")) - vancedVersions.postValue(versions?.array("vanced")) - music.postValue(latest?.obj("music")) - musicVersions.postValue(versions?.array("music")) - microg.postValue(latest?.obj("microg")) - manager.postValue(latest?.obj("manager")) - isFetching.postValue(false) -} - -private suspend fun getJsonString(file: String, obj: String, context: Context): String { - return try { - getJson("$baseInstallUrl/$file")?.string(obj) ?: context.getString(R.string.unavailable) - } catch (e: Exception) { - Log.e(TAG, "Error: ", e) - context.getString(R.string.unavailable) - } -} - -suspend fun getSha256(hashUrl: String, obj: String, context: Context): String { - return getJsonString(hashUrl, obj, context) -} - -fun checkSHA256(sha256: String, updateFile: File): Boolean { - return try { - val dataBuffer = updateFile.readBytes() - // Generate the checksum - val sum = generateChecksum(dataBuffer) - - sum.equals(sha256, ignoreCase = true) - } catch (e: Exception) { - e.printStackTrace() - false - } -} - -const val baseUrl = "https://api.vancedapp.com/api/v1" \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/utils/JsonHelper.kt b/app/src/main/java/com/vanced/manager/utils/JsonHelper.kt deleted file mode 100644 index d140f163b1..0000000000 --- a/app/src/main/java/com/vanced/manager/utils/JsonHelper.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.vanced.manager.utils - -import com.beust.klaxon.JsonArray -import com.beust.klaxon.JsonObject -import com.beust.klaxon.Klaxon -import com.beust.klaxon.Parser -import com.github.kittinunf.fuel.coroutines.awaitString -import com.github.kittinunf.fuel.httpGet - -private var dataMap: HashMap = HashMap() - -suspend fun getJson(url: String): JsonObject? { - return try { - if (dataMap.containsKey(url)) { - dataMap[url] - } else { - dataMap[url] = getSuspendJson(url) - dataMap[url] - } - } catch (e: Exception) { - //This null is NEEDED, do NOT try to "fix" NPE here!!! - null - } -} - -private suspend fun getSuspendJson(url: String): JsonObject = - Parser.default().parse( - StringBuilder(url.httpGet().awaitString()) - ) as JsonObject - -suspend fun getJsonArray(url: String): JsonArray = - Klaxon().parseArray( - url.httpGet().awaitString() - ) as JsonArray diff --git a/app/src/main/java/com/vanced/manager/utils/LanguageContextWrapper.kt b/app/src/main/java/com/vanced/manager/utils/LanguageContextWrapper.kt deleted file mode 100644 index e079d5e6f4..0000000000 --- a/app/src/main/java/com/vanced/manager/utils/LanguageContextWrapper.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.vanced.manager.utils - -import android.content.Context -import android.content.ContextWrapper -import android.content.res.Configuration -import android.content.res.Resources -import com.vanced.manager.utils.AppUtils.currentLocale -import java.util.* - -class LanguageContextWrapper(base: Context?) : ContextWrapper(base) { - - companion object { - - fun wrap(context: Context): ContextWrapper { - val config: Configuration = context.resources.configuration - context.createConfigurationContext(setLocale(config, context)) - return LanguageContextWrapper(context) - } - - @Suppress("DEPRECATION") - private fun setLocale(config: Configuration, context: Context): Configuration { - val pref = context.defPrefs.managerLang - val sysLocale = Resources.getSystem().configuration.locale - val locale = when { - pref == "System Default" -> Locale(sysLocale.language, sysLocale.country) - pref?.length!! > 2 -> Locale( - pref.substring(0, pref.length - 3), - pref.substring(pref.length - 2) - ) - else -> Locale(pref) - } - currentLocale = locale - Locale.setDefault(locale) - config.setLocale(locale) - return config - } - - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/utils/LanguageHelper.kt b/app/src/main/java/com/vanced/manager/utils/LanguageHelper.kt deleted file mode 100644 index 489f036af6..0000000000 --- a/app/src/main/java/com/vanced/manager/utils/LanguageHelper.kt +++ /dev/null @@ -1,81 +0,0 @@ -package com.vanced.manager.utils - -import android.app.Activity -import android.content.Context -import android.content.Intent -import android.content.res.Resources -import android.net.Uri -import android.os.Build -import android.os.LocaleList -import android.provider.Settings -import androidx.annotation.RequiresApi -import com.crowdin.platform.Crowdin -import com.vanced.manager.R -import java.util.* - -fun getLanguageFormat(context: Context, language: String): String { - return when { - language == "System Default" -> context.getString(R.string.system_default) - language.contains("_") -> { - val loc = Locale( - language.substringBefore("_"), - language.substringAfter("_") - ) - loc.getDisplayName(loc).capitalize(Locale.ENGLISH) - } - else -> { - val loc = Locale(language) - loc.getDisplayName(loc).capitalize(Locale.ENGLISH) - } - } - -} - -@Suppress("DEPRECATION") -fun getDefaultVancedLanguages(): String { - val serverLangs = vanced.value?.array("langs") ?: mutableListOf("") - val sysLocales = - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) Resources.getSystem().configuration.locales.toLangTags() else arrayOf( - Resources.getSystem().configuration.locale.language - ) - val finalLangs = mutableListOf() - sysLocales.forEach { sysLocale -> - when { - sysLocale == "en" -> finalLangs.add(sysLocale) - serverLangs.contains(sysLocale) -> finalLangs.add(sysLocale) - } - } - - return finalLangs.distinct().sorted().joinToString(", ") -} - -@RequiresApi(Build.VERSION_CODES.N) -fun LocaleList.toLangTags(): Array { - val langTags: Array = this.toLanguageTags().split(",").toTypedArray() - for (i in 0 until this.size()) { - langTags[i] = langTags[i].substring(0, 2) - } - return langTags -} - -fun Activity.authCrowdin() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (!Settings.canDrawOverlays(this)) { - val intent = Intent( - Settings.ACTION_MANAGE_OVERLAY_PERMISSION, - Uri.parse("package:$packageName") - ) - startActivityForResult(intent, 69) - return - } - Crowdin.authorize(this) - } -} - -fun Activity.onActivityResult(requestCode: Int) { - if (requestCode == 69 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (Settings.canDrawOverlays(this)) { - Crowdin.authorize(this) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/utils/MiuiHelper.kt b/app/src/main/java/com/vanced/manager/utils/MiuiHelper.kt deleted file mode 100644 index 3bf3ef1ab1..0000000000 --- a/app/src/main/java/com/vanced/manager/utils/MiuiHelper.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.vanced.manager.utils - -import android.content.Context -import android.provider.Settings - -private const val MIUI_OPTIMIZATION = "miui_optimization" - -val Context.isMiuiOptimizationsEnabled: Boolean - get() = Settings.Secure.getString( - contentResolver, - MIUI_OPTIMIZATION - ) == "1" \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/utils/PackageHelper.kt b/app/src/main/java/com/vanced/manager/utils/PackageHelper.kt deleted file mode 100644 index 9ae53c177c..0000000000 --- a/app/src/main/java/com/vanced/manager/utils/PackageHelper.kt +++ /dev/null @@ -1,596 +0,0 @@ -package com.vanced.manager.utils - -import android.app.PendingIntent -import android.content.Context -import android.content.Intent -import android.content.pm.PackageInfo -import android.content.pm.PackageInstaller -import android.content.pm.PackageManager -import android.os.Build -import com.topjohnwu.superuser.Shell -import com.topjohnwu.superuser.io.SuFile -import com.vanced.manager.BuildConfig -import com.vanced.manager.core.installer.AppInstallerService -import com.vanced.manager.core.installer.AppUninstallerService -import com.vanced.manager.utils.AppUtils.log -import com.vanced.manager.utils.AppUtils.musicRootPkg -import com.vanced.manager.utils.AppUtils.playStorePkg -import com.vanced.manager.utils.AppUtils.sendCloseDialog -import com.vanced.manager.utils.AppUtils.sendFailure -import com.vanced.manager.utils.AppUtils.sendRefresh -import com.vanced.manager.utils.AppUtils.vancedRootPkg -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import java.io.File -import java.io.FileInputStream -import java.io.IOException -import java.io.InputStream -import java.util.* - -object PackageHelper { - - const val apkInstallPath = "/data/adb" - private const val INSTALLER_TAG = "VMInstall" - private val vancedThemes = - vanced.value?.array("themes")?.value ?: listOf("black", "dark", "pink", "blue") - - init { - Shell.enableVerboseLogging = BuildConfig.DEBUG - Shell.setDefaultBuilder( - Shell.Builder.create() - .setFlags(Shell.FLAG_REDIRECT_STDERR) - .setTimeout(10) - ) - } - - private fun getAppNameRoot(pkg: String): String { - return when (pkg) { - vancedRootPkg -> "vanced" - musicRootPkg -> "music" - else -> "" - } - } - - fun scriptExists(scriptName: String): Boolean { - val serviceDScript = SuFile.open("$apkInstallPath/service.d/$scriptName.sh") - val postFsDataScript = SuFile.open("$apkInstallPath/post-fs-data.d/$scriptName.sh") - if (serviceDScript.exists() && postFsDataScript.exists()) { - return true - } - return false - } - - fun getPkgNameRoot(app: String): String { - return when (app) { - "vanced" -> vancedRootPkg - "music" -> musicRootPkg - else -> "" - } - } - - fun isPackageInstalled(packageName: String, packageManager: PackageManager): Boolean { - return try { - packageManager.getPackageInfo(packageName, 0) - true - } catch (e: PackageManager.NameNotFoundException) { - false - } - } - - fun getPackageVersionName(packageName: String, packageManager: PackageManager): String { - return if (isPackageInstalled(packageName, packageManager)) - packageManager.getPackageInfo(packageName, 0).versionName - else - "" - } - - @Suppress("DEPRECATION") - fun getPkgVerCode(pkg: String, pm: PackageManager): Int? { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) - pm.getPackageInfo(pkg, 0)?.longVersionCode?.and(0xFFFFFFFF)?.toInt() - else - pm.getPackageInfo(pkg, 0)?.versionCode - - } - - fun downloadStockCheck(pkg: String, versionCode: Int, context: Context): Boolean { - return try { - getPkgVerCode(pkg, context.packageManager) != versionCode - } catch (e: Exception) { - true - } - } - - fun apkExist(context: Context, apk: String): Boolean { - val apkPath = File(context.getExternalFilesDir(apk.substring(0, apk.length - 4))?.path, apk) - if (apkPath.exists()) - return true - - return false - } - - fun musicApkExists(context: Context): Boolean { - val apkPath = File(context.getExternalFilesDir("music/nonroot")?.path, "nonroot.apk") - if (apkPath.exists()) { - return true - } - - return false - } - - fun vancedInstallFilesExist(context: Context): Boolean { - val apksPath = File(context.getExternalFilesDir("vanced/nonroot")?.path.toString()) - val splitFiles = mutableListOf() - if (apksPath.exists()) { - val files = apksPath.listFiles() - if (files?.isNotEmpty() == true) { - for (file in files) { - when { - vancedThemes.any { file.name == "$it.apk" } && !splitFiles.contains("base") -> splitFiles.add( - "base" - ) - file.name.matches(Regex("split_config\\.(..)\\.apk")) && !splitFiles.contains( - "lang" - ) -> splitFiles.add("lang") - (file.name.startsWith("split_config.arm") || file.name.startsWith("split_config.x86")) && !splitFiles.contains( - "arch" - ) -> splitFiles.add("arch") - } - - if (splitFiles.size == 3) { - return true - } - } - } - return false - } - return false - } - - fun uninstallRootApk(pkg: String): Boolean { - val app = getAppNameRoot(pkg) - Shell.su("rm -rf $apkInstallPath/${app.capitalize(Locale.ROOT)}").exec() - Shell.su("rm $apkInstallPath/post-fs-data.d/$app.sh").exec() - Shell.su("rm $apkInstallPath/service.d/$app.sh").exec() - return Shell.su("pm uninstall $pkg").exec().isSuccess - } - - fun uninstallApk(pkg: String, context: Context) { - val callbackIntent = Intent(context, AppUninstallerService::class.java) - callbackIntent.putExtra("pkg", pkg) - val pendingIntent = PendingIntent.getService(context, 0, callbackIntent, 0) - try { - context.packageManager.packageInstaller.uninstall(pkg, pendingIntent.intentSender) - } catch (e: Exception) { - e.printStackTrace() - } - } - - fun install(path: String, context: Context) { - val callbackIntent = Intent(context, AppInstallerService::class.java) - val pendingIntent = PendingIntent.getService(context, 0, callbackIntent, 0) - val packageInstaller = context.packageManager.packageInstaller - val params = - PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL) - val sessionId: Int - var session: PackageInstaller.Session? = null - try { - sessionId = packageInstaller.createSession(params) - session = packageInstaller.openSession(sessionId) - val inputStream: InputStream = FileInputStream(path) - val outputStream = session.openWrite("install", 0, -1) - val buffer = ByteArray(65536) - var length: Int - while (inputStream.read(buffer).also { length = it } > 0) { - outputStream.write(buffer, 0, length) - } - session.fsync(outputStream) - inputStream.close() - outputStream.close() - session.commit(pendingIntent.intentSender) - } catch (e: Exception) { - log(INSTALLER_TAG, e.stackTraceToString()) - sendFailure(e.stackTraceToString(), context) - sendCloseDialog(context) - } finally { - session?.close() - } - } - - private fun installRootMusic(files: List, context: Context): Boolean { - files.forEach { apk -> - if (apk.name != "root.apk") { - val newPath = "/data/local/tmp/${apk.name}" - - //moving apk to tmp folder in order to avoid permission denials - Shell.su("mv ${apk.path} $newPath").exec() - val command = Shell.su("pm install -r $newPath").exec() - Shell.su("rm $newPath").exec() - if (command.isSuccess) { - return true - } else { - sendFailure(command.out, context) - sendCloseDialog(context) - } - - } - } - return false - } - - private fun installRootApp( - context: Context, - app: String, - appVerCode: Int?, - pkg: String, - modApkBool: (fileName: String) -> Boolean - ) = CoroutineScope(Dispatchers.IO).launch { - Shell.getShell { - val apkFilesPath = context.getExternalFilesDir("$app/root")?.path - val files = File(apkFilesPath.toString()).listFiles()?.toList() - if (files != null) { - val modApk: File? = files.lastOrNull { modApkBool(it.name) } - if (modApk != null) { - if (appVerCode != null) { - if (overwriteBase(modApk, files, appVerCode, pkg, app, context)) { - setInstallerPackage(context, pkg, playStorePkg) - log(INSTALLER_TAG, "Finished installation") - sendRefresh(context) - sendCloseDialog(context) - } - } else { - sendFailure(listOf("appVerCode is null").toMutableList(), context) - sendCloseDialog(context) - } - } else { - sendFailure(listOf("ModApk_Missing").toMutableList(), context) - sendCloseDialog(context) - } - } else { - sendFailure(listOf("Files_Missing_VA").toMutableList(), context) - sendCloseDialog(context) - } - - } - - } - - fun installMusicRoot(context: Context) { - installRootApp( - context, - "music", - music.value?.int("versionCode"), - musicRootPkg - ) { - it == "root.apk" - } - } - - fun installVancedRoot(context: Context) { - installRootApp( - context, - "vanced", - vanced.value?.int("versionCode"), - vancedRootPkg - ) { fileName -> - vancedThemes.any { fileName == "$it.apk" } - } - } - - fun installSplitApkFiles( - context: Context, - appName: String - ) { - val packageInstaller = context.packageManager.packageInstaller - val folder = File(context.getExternalFilesDir("$appName/nonroot")?.path.toString()) - var session: PackageInstaller.Session? = null - val sessionId: Int - val sessionParams = - PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL) - val callbackIntent = Intent(context, AppInstallerService::class.java) - val pendingIntent = PendingIntent.getService(context, 0, callbackIntent, 0) - try { - sessionId = packageInstaller.createSession(sessionParams) - session = packageInstaller.openSession(sessionId) - folder.listFiles()?.forEach { apk -> - val inputStream = FileInputStream(apk) - val outputStream = session.openWrite(apk.name, 0, apk.length()) - val buffer = ByteArray(65536) - var length: Int - while (inputStream.read(buffer).also { length = it } > 0) { - outputStream.write(buffer, 0, length) - } - session.fsync(outputStream) - inputStream.close() - outputStream.close() - } - session.commit(pendingIntent.intentSender) - } catch (e: Exception) { - log(INSTALLER_TAG, e.stackTraceToString()) - sendFailure(e.stackTraceToString(), context) - sendCloseDialog(context) - } finally { - session?.close() - } - } - - private fun installSplitApkFilesRoot(apkFiles: List?, context: Context): Boolean { - val filenames = arrayOf("black.apk", "dark.apk", "blue.apk", "pink.apk", "hash.json") - log(INSTALLER_TAG, "installing split apk files: ${apkFiles?.map { it.name }}") - val sessionId = - Shell.su("pm install-create -r").exec().out.joinToString(" ").filter { it.isDigit() } - .toIntOrNull() - - if (sessionId == null) { - sendFailure("Session ID is null", context) - sendCloseDialog(context) - return false - } - - apkFiles?.filter { !filenames.contains(it.name) }?.forEach { apkFile -> - val apkName = apkFile.name - log(INSTALLER_TAG, "installing APK: $apkName") - val newPath = "/data/local/tmp/$apkName" - // Moving apk to avoid permission denials - Shell.su("mv ${apkFile.path} $newPath").exec() - val command = Shell.su("pm install-write $sessionId $apkName $newPath").exec() - Shell.su("rm $newPath").exec() - if (!command.isSuccess) { - sendFailure(command.out, context) - sendCloseDialog(context) - return false - } - } - log(INSTALLER_TAG, "committing...") - val installResult = Shell.su("pm install-commit $sessionId").exec() - if (installResult.isSuccess) { - return true - } - sendFailure(installResult.out, context) - sendCloseDialog(context) - return false - } - - - //overwrite stock Vanced/Music - private fun overwriteBase( - apkFile: File, - baseApkFiles: List, - versionCode: Int, - pkg: String, - app: String, - context: Context - ): Boolean { - if (checkVersion(versionCode, baseApkFiles, pkg, context)) { - val path = getPackageDir(context, pkg) - val apath = apkFile.absolutePath - - setupFolder("$apkInstallPath/${app.capitalize(Locale.ROOT)}") - if (path != null) { - val apkFPath = "$apkInstallPath/${app.capitalize(Locale.ROOT)}/base.apk" - if (moveAPK(apath, apkFPath, pkg, context)) { - if (chConV(apkFPath, context)) { - if (setupScript(apkFPath, path, app, pkg, context)) { - return linkApp(apkFPath, pkg, path) - } - } - } - } - } - return false - } - - private fun setupScript( - apkFPath: String, - path: String, - app: String, - pkg: String, - context: Context - ): Boolean { - try { - log(INSTALLER_TAG, "Setting up script") - context.writeServiceDScript(apkFPath, path, app) - Shell.su("""echo "#!/system/bin/sh\nwhile read line; do echo \${"$"}{line} | grep $pkg | awk '{print \${'$'}2}' | xargs umount -l; done< /proc/mounts" > /data/adb/post-fs-data.d/$app.sh""") - .exec() - return Shell.su("chmod 744 /data/adb/service.d/$app.sh").exec().isSuccess - } catch (e: IOException) { - sendFailure(e.stackTraceToString(), context) - sendCloseDialog(context) - log(INSTALLER_TAG, e.stackTraceToString()) - } - return false - } - - private fun linkApp(apkFPath: String, pkg: String, path: String): Boolean { - log(INSTALLER_TAG, "Linking app") - Shell.su("am force-stop $pkg").exec() - Shell.su("""for i in ${'$'}(ls /data/app/ | grep $pkg | tr " "); do umount -l "/data/app/${"$"}i/base.apk"; done """) - .exec() - val response = Shell.su("""su -mm -c "mount -o bind $apkFPath $path"""").exec() - Thread.sleep(500) - Shell.su("am force-stop $pkg").exec() - return response.isSuccess - } - - private fun setupFolder(apkInstallPath: String): Boolean { - return Shell.su("mkdir -p $apkInstallPath").exec().isSuccess - } - - //check version and perform action based on result - private fun checkVersion( - versionCode: Int, - baseApkFiles: List, - pkg: String, - context: Context - ): Boolean { - log(INSTALLER_TAG, "Checking stock version") - val path = getPackageDir(context, pkg) - if (path != null) { - if (path.contains("/data/app/")) { - when (getVersionNumber(pkg, context)?.let { compareVersion(it, versionCode) }) { - 1 -> return fixHigherVer(baseApkFiles, pkg, context) - -1 -> return installStock(baseApkFiles, pkg, context) - } - return true - } - return installStock(baseApkFiles, pkg, context) - } - return installStock(baseApkFiles, pkg, context) - } - - private fun getPkgInfo(pkg: String, context: Context): PackageInfo? { - return try { - context.packageManager.getPackageInfo(pkg, 0) - } catch (e: Exception) { - log(INSTALLER_TAG, "Unable to get package info") - null - } - } - - private fun compareVersion(pkgVerCode: Int, versionCode: Int): Int { - return when { - pkgVerCode > versionCode -> 1 - pkgVerCode < versionCode -> -1 - else -> 0 - } - } - - //uninstall current update and install base that works with patch - private fun fixHigherVer(apkFiles: List, pkg: String, context: Context): Boolean { - log(INSTALLER_TAG, "Downgrading stock") - if (uninstallRootApk(pkg)) { - return if (pkg == vancedRootPkg) installSplitApkFilesRoot( - apkFiles, - context - ) else installRootMusic(apkFiles, context) - } - sendFailure(listOf("Failed_Uninstall").toMutableList(), context) - sendCloseDialog(context) - return false - } - - //install stock youtube matching vanced version - private fun installStock(baseApkFiles: List, pkg: String, context: Context): Boolean { - log(INSTALLER_TAG, "Installing stock") - return if (pkg == vancedRootPkg) installSplitApkFilesRoot( - baseApkFiles, - context - ) else installRootMusic(baseApkFiles, context) - } - - //set chcon to apk_data_file - private fun chConV(apkFPath: String, context: Context): Boolean { - log(INSTALLER_TAG, "Running chcon") - val response = Shell.su("chcon u:object_r:apk_data_file:s0 $apkFPath").exec() - //val response = Shell.su("chcon -R u:object_r:system_file:s0 $path").exec() - return if (response.isSuccess) { - true - } else { - sendFailure(response.out, context) - sendCloseDialog(context) - false - } - } - - //move patch to data/app - private fun moveAPK(apkFile: String, path: String, pkg: String, context: Context): Boolean { - log(INSTALLER_TAG, "Moving app") - val apkinF = SuFile.open(apkFile) - val apkoutF = SuFile.open(path) - - if (apkinF.exists()) { - try { - Shell.su("am force-stop $pkg").exec() - - //Shell.su("rm -r SuFile.open(path).parent") - - copy(apkinF, apkoutF) - Shell.su("chmod 644 $path").exec().isSuccess - return if (Shell.su("chown system:system $path").exec().isSuccess) { - true - } else { - sendFailure(listOf("Chown_Fail").toMutableList(), context) - sendCloseDialog(context) - false - } - - } catch (e: IOException) { - sendFailure(listOf("${e.message}").toMutableList(), context) - sendCloseDialog(context) - log(INSTALLER_TAG, e.stackTraceToString()) - return false - } - } - sendFailure(listOf("IFile_Missing").toMutableList(), context) - sendCloseDialog(context) - return false - } - - - @Throws(IOException::class) - fun copy(src: File, dst: File) { - val cmd = Shell.su("mv ${src.absolutePath} ${dst.absolutePath}").exec().isSuccess - log("ZLog", cmd.toString()) - } - - @Suppress("DEPRECATION") - private fun getVersionNumber(pkg: String, context: Context): Int? { - try { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) - context.packageManager.getPackageInfo(vancedRootPkg, 0).longVersionCode.and( - 0xFFFFFFFF - ).toInt() - else - context.packageManager.getPackageInfo(vancedRootPkg, 0).versionCode - } catch (e: Exception) { - val execRes = Shell.su("dumpsys package $pkg | grep versionCode").exec() - if (execRes.isSuccess) { - val result = execRes.out - var version = 0 - result - .asSequence() - .map { it.substringAfter("=") } - .map { it.substringBefore(" ") } - .filter { version < Integer.valueOf(it) } - .forEach { version = Integer.valueOf(it) } - return version - } - } - return null - } - - //get path of the installed youtube - fun getPackageDir(context: Context, pkg: String): String? { - val p = getPkgInfo(pkg, context) - return if (p != null) { - p.applicationInfo.sourceDir - } else { - val execRes = Shell.su("dumpsys package $pkg | grep codePath").exec() - if (execRes.isSuccess) { - val result = execRes.out - for (line in result) { - if (line.contains("data/app")) "${line.substringAfter("=")}/base.apk" - } - } - null - } - } - - private fun setInstallerPackage(context: Context, target: String, installer: String) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return - try { - log(INSTALLER_TAG, "Setting installer package to $installer for $target") - val installerUid = context.packageManager.getPackageUid(installer, 0) - val res = - Shell.su("""su $installerUid -c 'pm set-installer $target $installer'""").exec() - if (res.out.any { line -> line.contains("Success") }) { - log(INSTALLER_TAG, "Installer package successfully set") - return - } - log(INSTALLER_TAG, "Failed setting installer package") - } catch (e: PackageManager.NameNotFoundException) { - log(INSTALLER_TAG, "Installer package $installer not found. Skipping setting installer") - } - } -} diff --git a/app/src/main/java/com/vanced/manager/utils/Preferences.kt b/app/src/main/java/com/vanced/manager/utils/Preferences.kt deleted file mode 100644 index 3a688fb42a..0000000000 --- a/app/src/main/java/com/vanced/manager/utils/Preferences.kt +++ /dev/null @@ -1,49 +0,0 @@ -package com.vanced.manager.utils - -import android.content.Context -import android.content.SharedPreferences -import androidx.core.content.edit -import androidx.preference.PreferenceManager.getDefaultSharedPreferences - -val Context.defPrefs: SharedPreferences get() = getDefaultSharedPreferences(this) - -var SharedPreferences.managerTheme - get() = getString("manager_theme", "System Default") - set(value) = edit { putString("manager_theme", value) } - -var SharedPreferences.managerAccent - get() = getInt("manager_accent_color", defAccentColor) - set(value) = edit { putInt("manager_accent_color", value) } - -var SharedPreferences.managerVariant - get() = getString("vanced_variant", "nonroot") - set(value) = edit { putString("vanced_variant", value) } - -var SharedPreferences.managerLang - get() = getString("manager_lang", "System Default") - set(value) = edit { putString("manager_lang", value) } - -var SharedPreferences.installUrl - get() = getString("install_url", baseUrl) - set(value) = edit { putString("install_url", value) } - -var SharedPreferences.vancedVersion - get() = getString("vanced_version", "latest") - set(value) = edit { putString("vanced_version", value) } - -var SharedPreferences.musicVersion - get() = getString("music_version", "latest") - set(value) = edit { putString("music_version", value) } - -var SharedPreferences.serviceDSleepTimer - get() = getInt("serviced_sleep_timer", 1) - set(value) = edit { putInt("serviced_sleep_timer", value) } - -var SharedPreferences.enableVanced - get() = getBoolean("enable_vanced", true) - set(value) = edit { putBoolean("enable_vanced", value) } - -var SharedPreferences.enableMusic - get() = getBoolean("enable_music", true) - set(value) = edit { putBoolean("enable_music", value) } - diff --git a/app/src/main/java/com/vanced/manager/utils/ProgressHelper.kt b/app/src/main/java/com/vanced/manager/utils/ProgressHelper.kt deleted file mode 100644 index 341baf986f..0000000000 --- a/app/src/main/java/com/vanced/manager/utils/ProgressHelper.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.vanced.manager.utils - -import androidx.lifecycle.MutableLiveData -import okhttp3.ResponseBody -import retrofit2.Call - -val downloadProgress = MutableLiveData(0) -val downloadingFile = MutableLiveData("") -val installing = MutableLiveData(false) - -var currentDownload: Call? = null - -fun reset() { - downloadProgress.value = 0 - downloadingFile.value = "" -} - -fun postReset() { - downloadProgress.postValue(0) - downloadingFile.postValue("") -} - diff --git a/app/src/main/java/com/vanced/manager/utils/ThemeHelper.kt b/app/src/main/java/com/vanced/manager/utils/ThemeHelper.kt deleted file mode 100644 index 3713f6f9b6..0000000000 --- a/app/src/main/java/com/vanced/manager/utils/ThemeHelper.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.vanced.manager.utils - -import android.app.Activity -import android.content.res.Configuration -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import com.vanced.manager.R - -const val defAccentColor: Int = -13732865 -const val LIGHT = "Light" -const val DARK = "Dark" -const val SYSTEM_DEFAULT = "System Default" - -val mutableAccentColor = MutableLiveData(defAccentColor) -val accentColor: LiveData = mutableAccentColor - -var currentTheme = "" - -fun Activity.setFinalTheme() { - when (defPrefs.managerTheme) { - LIGHT -> setTheme(R.style.LightTheme, LIGHT) - DARK -> setTheme(R.style.DarkTheme, DARK) - SYSTEM_DEFAULT -> { - when (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) { - Configuration.UI_MODE_NIGHT_YES -> setTheme(R.style.DarkTheme, DARK) - Configuration.UI_MODE_NIGHT_NO -> setTheme(R.style.LightTheme, LIGHT) - } - } - else -> setTheme(R.style.LightTheme, LIGHT) - } -} - -fun Activity.setTheme(resId: Int, themeValue: String) { - setTheme(resId) - currentTheme = themeValue -} \ No newline at end of file diff --git a/app/src/main/res/drawable/category_background.xml b/app/src/main/res/drawable/category_background.xml deleted file mode 100644 index aec7c85466..0000000000 --- a/app/src/main/res/drawable/category_background.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_android_black_24dp.xml b/app/src/main/res/drawable/ic_android_black_24dp.xml new file mode 100644 index 0000000000..0df8cff0dd --- /dev/null +++ b/app/src/main/res/drawable/ic_android_black_24dp.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_app_download.xml b/app/src/main/res/drawable/ic_app_download.xml deleted file mode 100644 index 1f61509e84..0000000000 --- a/app/src/main/res/drawable/ic_app_download.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/app_image_placeholder.xml b/app/src/main/res/drawable/ic_app_icon_placeholder.xml similarity index 50% rename from app/src/main/res/drawable/app_image_placeholder.xml rename to app/src/main/res/drawable/ic_app_icon_placeholder.xml index fb39a14ea3..15515d0036 100644 --- a/app/src/main/res/drawable/app_image_placeholder.xml +++ b/app/src/main/res/drawable/ic_app_icon_placeholder.xml @@ -3,14 +3,12 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> - + - + - + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_app_info.xml b/app/src/main/res/drawable/ic_app_info.xml deleted file mode 100644 index 35f7f5f611..0000000000 --- a/app/src/main/res/drawable/ic_app_info.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_app_reinstall.xml b/app/src/main/res/drawable/ic_app_reinstall.xml deleted file mode 100644 index 3c6d07f471..0000000000 --- a/app/src/main/res/drawable/ic_app_reinstall.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_app_uninstall.xml b/app/src/main/res/drawable/ic_app_uninstall.xml deleted file mode 100644 index b0b1d8d065..0000000000 --- a/app/src/main/res/drawable/ic_app_uninstall.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_app_update.xml b/app/src/main/res/drawable/ic_app_update.xml deleted file mode 100644 index f92d6eff53..0000000000 --- a/app/src/main/res/drawable/ic_app_update.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_baseline_close_24.xml b/app/src/main/res/drawable/ic_baseline_close_24.xml deleted file mode 100644 index 16d6d37dd9..0000000000 --- a/app/src/main/res/drawable/ic_baseline_close_24.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_baseline_launch_24.xml b/app/src/main/res/drawable/ic_baseline_launch_24.xml deleted file mode 100644 index 455b503a1f..0000000000 --- a/app/src/main/res/drawable/ic_baseline_launch_24.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_baseline_navigate_next_36.xml b/app/src/main/res/drawable/ic_baseline_navigate_next_36.xml deleted file mode 100644 index 1aa6018d40..0000000000 --- a/app/src/main/res/drawable/ic_baseline_navigate_next_36.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_baseline_navigate_next_48.xml b/app/src/main/res/drawable/ic_baseline_navigate_next_48.xml deleted file mode 100644 index 8afa9b2bc6..0000000000 --- a/app/src/main/res/drawable/ic_baseline_navigate_next_48.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_baseline_save_24.xml b/app/src/main/res/drawable/ic_baseline_save_24.xml deleted file mode 100644 index 999020dcfc..0000000000 --- a/app/src/main/res/drawable/ic_baseline_save_24.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_keyboard_backspace_black_24dp.xml b/app/src/main/res/drawable/ic_keyboard_backspace_black_24dp.xml deleted file mode 100644 index a5d1965156..0000000000 --- a/app/src/main/res/drawable/ic_keyboard_backspace_black_24dp.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_manager.xml b/app/src/main/res/drawable/ic_manager.xml new file mode 100644 index 0000000000..04094e71f2 --- /dev/null +++ b/app/src/main/res/drawable/ic_manager.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_reddit.xml b/app/src/main/res/drawable/ic_reddit.xml old mode 100755 new mode 100644 diff --git a/app/src/main/res/drawable/ic_settings_black_24dp.xml b/app/src/main/res/drawable/ic_settings_black_24dp.xml deleted file mode 100644 index 661d05f8da..0000000000 --- a/app/src/main/res/drawable/ic_settings_black_24dp.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_shortcut_info.xml b/app/src/main/res/drawable/ic_shortcut_info.xml deleted file mode 100644 index 17d70fcf6e..0000000000 --- a/app/src/main/res/drawable/ic_shortcut_info.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/app/src/main/res/drawable/ic_shortcut_settings.xml b/app/src/main/res/drawable/ic_shortcut_settings.xml deleted file mode 100644 index 48beb04173..0000000000 --- a/app/src/main/res/drawable/ic_shortcut_settings.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - diff --git a/app/src/main/res/drawable/ic_splash.xml b/app/src/main/res/drawable/ic_splash.xml new file mode 100644 index 0000000000..476cb4e42a --- /dev/null +++ b/app/src/main/res/drawable/ic_splash.xml @@ -0,0 +1,11 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/splash_logo.xml b/app/src/main/res/drawable/splash_logo.xml deleted file mode 100644 index f68ed4cd7c..0000000000 --- a/app/src/main/res/drawable/splash_logo.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/drawable/vanced_gradient.xml b/app/src/main/res/drawable/vanced_gradient.xml deleted file mode 100644 index 49074b1798..0000000000 --- a/app/src/main/res/drawable/vanced_gradient.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml deleted file mode 100644 index 4612a1b1ac..0000000000 --- a/app/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_welcome.xml b/app/src/main/res/layout/activity_welcome.xml deleted file mode 100644 index c591147d1f..0000000000 --- a/app/src/main/res/layout/activity_welcome.xml +++ /dev/null @@ -1,6 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_app_download.xml b/app/src/main/res/layout/dialog_app_download.xml deleted file mode 100644 index 98ae464854..0000000000 --- a/app/src/main/res/layout/dialog_app_download.xml +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/dialog_app_info.xml b/app/src/main/res/layout/dialog_app_info.xml deleted file mode 100644 index b4ecca4afc..0000000000 --- a/app/src/main/res/layout/dialog_app_info.xml +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_app_uninstall.xml b/app/src/main/res/layout/dialog_app_uninstall.xml deleted file mode 100644 index 4f8e515755..0000000000 --- a/app/src/main/res/layout/dialog_app_uninstall.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_bottom_radio_button.xml b/app/src/main/res/layout/dialog_bottom_radio_button.xml deleted file mode 100644 index 9e6459d921..0000000000 --- a/app/src/main/res/layout/dialog_bottom_radio_button.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_custom_url.xml b/app/src/main/res/layout/dialog_custom_url.xml deleted file mode 100644 index 1bef148a54..0000000000 --- a/app/src/main/res/layout/dialog_custom_url.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_installation_files_detected.xml b/app/src/main/res/layout/dialog_installation_files_detected.xml deleted file mode 100644 index 0c13fd5007..0000000000 --- a/app/src/main/res/layout/dialog_installation_files_detected.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/dialog_manager_accent_color.xml b/app/src/main/res/layout/dialog_manager_accent_color.xml deleted file mode 100644 index 7b78e6e9f7..0000000000 --- a/app/src/main/res/layout/dialog_manager_accent_color.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/dialog_manager_language.xml b/app/src/main/res/layout/dialog_manager_language.xml deleted file mode 100644 index 7e2b515b6f..0000000000 --- a/app/src/main/res/layout/dialog_manager_language.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_manager_theme.xml b/app/src/main/res/layout/dialog_manager_theme.xml deleted file mode 100644 index 0fe43d6a9d..0000000000 --- a/app/src/main/res/layout/dialog_manager_theme.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_manager_update.xml b/app/src/main/res/layout/dialog_manager_update.xml deleted file mode 100644 index e26258b1fb..0000000000 --- a/app/src/main/res/layout/dialog_manager_update.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_manager_variant.xml b/app/src/main/res/layout/dialog_manager_variant.xml deleted file mode 100644 index 11eaf95c24..0000000000 --- a/app/src/main/res/layout/dialog_manager_variant.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/dialog_music_preferences.xml b/app/src/main/res/layout/dialog_music_preferences.xml deleted file mode 100644 index 153f88b709..0000000000 --- a/app/src/main/res/layout/dialog_music_preferences.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_select_apps.xml b/app/src/main/res/layout/dialog_select_apps.xml deleted file mode 100644 index 16d5179662..0000000000 --- a/app/src/main/res/layout/dialog_select_apps.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_serviced_timer.xml b/app/src/main/res/layout/dialog_serviced_timer.xml deleted file mode 100644 index f08de4b37e..0000000000 --- a/app/src/main/res/layout/dialog_serviced_timer.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/dialog_vanced_language_selection.xml b/app/src/main/res/layout/dialog_vanced_language_selection.xml deleted file mode 100644 index 05e6343edb..0000000000 --- a/app/src/main/res/layout/dialog_vanced_language_selection.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_vanced_preferences.xml b/app/src/main/res/layout/dialog_vanced_preferences.xml deleted file mode 100644 index 60dcabe726..0000000000 --- a/app/src/main/res/layout/dialog_vanced_preferences.xml +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_about.xml b/app/src/main/res/layout/fragment_about.xml deleted file mode 100644 index 8d68910b26..0000000000 --- a/app/src/main/res/layout/fragment_about.xml +++ /dev/null @@ -1,193 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_dev_settings.xml b/app/src/main/res/layout/fragment_dev_settings.xml deleted file mode 100644 index a4a4e3b4d8..0000000000 --- a/app/src/main/res/layout/fragment_dev_settings.xml +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_grant_root.xml b/app/src/main/res/layout/fragment_grant_root.xml deleted file mode 100644 index 88d201debd..0000000000 --- a/app/src/main/res/layout/fragment_grant_root.xml +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml deleted file mode 100644 index b5b57b63ea..0000000000 --- a/app/src/main/res/layout/fragment_home.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/fragment_log.xml b/app/src/main/res/layout/fragment_log.xml deleted file mode 100644 index 70c4f02cfe..0000000000 --- a/app/src/main/res/layout/fragment_log.xml +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - diff --git a/app/src/main/res/layout/fragment_select_apps.xml b/app/src/main/res/layout/fragment_select_apps.xml deleted file mode 100644 index 624835c1c0..0000000000 --- a/app/src/main/res/layout/fragment_select_apps.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml deleted file mode 100644 index ef49caa97e..0000000000 --- a/app/src/main/res/layout/fragment_settings.xml +++ /dev/null @@ -1,103 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_welcome.xml b/app/src/main/res/layout/fragment_welcome.xml deleted file mode 100644 index 1ee2b2fde2..0000000000 --- a/app/src/main/res/layout/fragment_welcome.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - diff --git a/app/src/main/res/layout/view_app_checkbox.xml b/app/src/main/res/layout/view_app_checkbox.xml deleted file mode 100644 index f12a94536d..0000000000 --- a/app/src/main/res/layout/view_app_checkbox.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/view_app_expandable.xml b/app/src/main/res/layout/view_app_expandable.xml deleted file mode 100644 index 50242d3466..0000000000 --- a/app/src/main/res/layout/view_app_expandable.xml +++ /dev/null @@ -1,182 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/view_notification_setting.xml b/app/src/main/res/layout/view_notification_setting.xml deleted file mode 100644 index 9830c9cd76..0000000000 --- a/app/src/main/res/layout/view_notification_setting.xml +++ /dev/null @@ -1,5 +0,0 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layout/view_preference.xml b/app/src/main/res/layout/view_preference.xml deleted file mode 100644 index 6c89a7e3e6..0000000000 --- a/app/src/main/res/layout/view_preference.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/view_preference_category.xml b/app/src/main/res/layout/view_preference_category.xml deleted file mode 100644 index 00f4ba52ee..0000000000 --- a/app/src/main/res/layout/view_preference_category.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/app/src/main/res/layout/view_preference_switch.xml b/app/src/main/res/layout/view_preference_switch.xml deleted file mode 100644 index 0592cd635c..0000000000 --- a/app/src/main/res/layout/view_preference_switch.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/view_social_link.xml b/app/src/main/res/layout/view_social_link.xml deleted file mode 100644 index 7bd2f2984a..0000000000 --- a/app/src/main/res/layout/view_social_link.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/view_sponsor.xml b/app/src/main/res/layout/view_sponsor.xml deleted file mode 100644 index 3f8acca6c7..0000000000 --- a/app/src/main/res/layout/view_sponsor.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/menu/dev_settings_menu.xml b/app/src/main/res/menu/dev_settings_menu.xml deleted file mode 100644 index 46fbeb5910..0000000000 --- a/app/src/main/res/menu/dev_settings_menu.xml +++ /dev/null @@ -1,13 +0,0 @@ - -

- - - - \ No newline at end of file diff --git a/app/src/main/res/menu/toolbar_menu.xml b/app/src/main/res/menu/toolbar_menu.xml deleted file mode 100644 index 2ac9edf1ce..0000000000 --- a/app/src/main/res/menu/toolbar_menu.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml deleted file mode 100644 index 1a3ee43e8e..0000000000 --- a/app/src/main/res/navigation/mobile_navigation.xml +++ /dev/null @@ -1,83 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml index 1e2dd8d6db..af05fc302e 100644 --- a/app/src/main/res/values-night/colors.xml +++ b/app/src/main/res/values-night/colors.xml @@ -2,7 +2,7 @@ - #131317 + #131317 diff --git a/app/src/main/res/values-v23/themes.xml b/app/src/main/res/values-v23/themes.xml deleted file mode 100644 index cd627ed4a2..0000000000 --- a/app/src/main/res/values-v23/themes.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 9a61311a23..90e84d1c38 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -9,10 +9,7 @@ #FF4500 #17191A - #5F5E5E - #ffffff - #000000 - #cfcfcf + #f7f7f7 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml old mode 100755 new mode 100644 diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml deleted file mode 100644 index f5128c197e..0000000000 --- a/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,202 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 40d802a17a..040404c7ff 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -1,85 +1,10 @@ - - - - - - \ No newline at end of file diff --git a/app/src/main/res/xml-v25/shortcuts.xml b/app/src/main/res/xml-v25/shortcuts.xml deleted file mode 100644 index 5315fd6ae4..0000000000 --- a/app/src/main/res/xml-v25/shortcuts.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 3b8338f39e..37390083aa 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,29 +1,19 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - buildscript { - val kotlinVersion by extra("1.4.32") repositories { google() - jcenter() + mavenCentral() } dependencies { - classpath("com.android.tools.build:gradle:4.1.3") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") - classpath("com.google.gms:google-services:4.3.5") - classpath("com.google.firebase:perf-plugin:1.3.5") - classpath("com.google.firebase:firebase-crashlytics-gradle:2.5.2") - classpath("androidx.navigation:navigation-safe-args-gradle-plugin:2.3.5") - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle.kts files + classpath("com.android.tools.build:gradle:7.0.0-beta03") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${Config.kotlinVersion}") } } allprojects { repositories { google() - jcenter() + mavenCentral() maven(url = "https://jitpack.io") } } diff --git a/buildSrc/.gitignore b/buildSrc/.gitignore new file mode 100644 index 0000000000..d16386367f --- /dev/null +++ b/buildSrc/.gitignore @@ -0,0 +1 @@ +build/ \ No newline at end of file diff --git a/buildSrc/src/main/java/Config.kt b/buildSrc/src/main/java/Config.kt index ce6e1f7ef5..dc5a7b8c9d 100644 --- a/buildSrc/src/main/java/Config.kt +++ b/buildSrc/src/main/java/Config.kt @@ -1,5 +1,5 @@ object Config { - const val kotlinVersion = "1.4.21" + const val kotlinVersion = "1.4.32" } \ No newline at end of file diff --git a/core-mvi/.gitignore b/core-mvi/.gitignore deleted file mode 100644 index 42afabfd2a..0000000000 --- a/core-mvi/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/core-mvi/build.gradle.kts b/core-mvi/build.gradle.kts deleted file mode 100644 index c359ea8f9d..0000000000 --- a/core-mvi/build.gradle.kts +++ /dev/null @@ -1,19 +0,0 @@ -plugins { - kotlin("jvm") -} - -java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 -} - -dependencies { - implementation(kotlin("stdlib")) - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1") - - testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.4.1") - testImplementation("io.kotest:kotest-runner-junit5:4.3.2") - testImplementation("io.kotest:kotest-assertions-core:4.3.2") - testImplementation("io.kotest:kotest-property:4.3.2") - testImplementation("io.mockk:mockk:1.10.4") -} \ No newline at end of file diff --git a/core-mvi/src/main/kotlin/com/vanced/manager/core/mvi/MviFlow.kt b/core-mvi/src/main/kotlin/com/vanced/manager/core/mvi/MviFlow.kt deleted file mode 100644 index 2d583ca08d..0000000000 --- a/core-mvi/src/main/kotlin/com/vanced/manager/core/mvi/MviFlow.kt +++ /dev/null @@ -1,98 +0,0 @@ -package com.vanced.manager.core.mvi - -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.* -import kotlinx.coroutines.launch -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock - -interface MviFlow { - - fun bindView( - view: MviRenderView, - scope: CoroutineScope, - actions: List = listOf() - ) - - fun bindSideEffects( - view: MviRenderView, - scope: CoroutineScope - ) -} - -private class MviFlowImpl( - initialState: State, - private val reducer: Reducer, - private val handler: Handler, - scope: CoroutineScope, -) : MviFlow, - CoroutineScope by scope, - Mutex by Mutex() { - - private val state = MutableStateFlow(initialState) - private val sideEffect = MutableSharedFlow() - - override fun bindSideEffects( - view: MviRenderView, - scope: CoroutineScope - ): Unit = with(scope) { - launch { - sideEffect.collect { view.sideEffects(it) } - } - } - - override fun bindView( - view: MviRenderView, - scope: CoroutineScope, - actions: List - ): Unit = with(scope) { - emitStateForRender(view) - handleActions(view, actions) - } - - private fun CoroutineScope.emitStateForRender( - view: MviRenderView - ) = launch { - state.collect { - view.render(it) - } - } - - private fun CoroutineScope.handleActions( - view: MviRenderView, - actions: List - ) = launch { - view.actionsFlow() - .onStart { emitAll(actions.asFlow()) } - .proceed() - } - - private suspend fun Flow.proceed() = - collect { action -> - handler.invoke( - MutableSharedFlow().subscribeState(), - state.value, action, sideEffect - ) - } - - private fun MutableSharedFlow.subscribeState(): MutableSharedFlow = - also { - onEach { modification -> - withLock { - reducer.invoke(state, state.value, modification) - } - }.launchIn(this@MviFlowImpl) - } -} - -fun MviFlow( - initialState: State, - reducer: Reducer, - handler: Handler, - scope: CoroutineScope -): MviFlow = MviFlowImpl( - initialState = initialState, - reducer = reducer, - handler = handler, - scope = scope -) \ No newline at end of file diff --git a/core-mvi/src/main/kotlin/com/vanced/manager/core/mvi/MviFlowStore.kt b/core-mvi/src/main/kotlin/com/vanced/manager/core/mvi/MviFlowStore.kt deleted file mode 100644 index 0eaa3fd74c..0000000000 --- a/core-mvi/src/main/kotlin/com/vanced/manager/core/mvi/MviFlowStore.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.vanced.manager.core.mvi - -interface MviFlowStore { - - val store: MviFlow -} \ No newline at end of file diff --git a/core-mvi/src/main/kotlin/com/vanced/manager/core/mvi/MviRenderView.kt b/core-mvi/src/main/kotlin/com/vanced/manager/core/mvi/MviRenderView.kt deleted file mode 100644 index 31a9fb9c22..0000000000 --- a/core-mvi/src/main/kotlin/com/vanced/manager/core/mvi/MviRenderView.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.vanced.manager.core.mvi - -import kotlinx.coroutines.flow.Flow - -interface MviRenderView { - - fun render(state: State) - - fun actionsFlow(): Flow - - fun sideEffects(sideEffect: SideEffect) -} \ No newline at end of file diff --git a/core-mvi/src/main/kotlin/com/vanced/manager/core/mvi/Typealias.kt b/core-mvi/src/main/kotlin/com/vanced/manager/core/mvi/Typealias.kt deleted file mode 100644 index b108ef2a17..0000000000 --- a/core-mvi/src/main/kotlin/com/vanced/manager/core/mvi/Typealias.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.vanced.manager.core.mvi - -import kotlinx.coroutines.flow.MutableSharedFlow - -typealias Handler = - suspend MutableSharedFlow.( - state: State, - action: Action, - sideEffectsFlow: MutableSharedFlow, - ) -> Unit - -typealias Reducer = - suspend MutableSharedFlow.( - state: State, - modification: Modification - ) -> Unit \ No newline at end of file diff --git a/core-mvi/src/main/kotlin/example/ExampleManyStoreFragment.kt b/core-mvi/src/main/kotlin/example/ExampleManyStoreFragment.kt deleted file mode 100644 index 18ae925a1b..0000000000 --- a/core-mvi/src/main/kotlin/example/ExampleManyStoreFragment.kt +++ /dev/null @@ -1,95 +0,0 @@ -package example - -import com.vanced.manager.core.mvi.* -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job -import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.callbackFlow -import kotlinx.coroutines.launch - -class ExampleManyStoreFragment { - - val lifecycleScope = CoroutineScope(Job()) - - private val view1 = getView() - private val container1 = getStore() - - private val view2 = getView() - private val container2 = getStore() - - private fun onCreate() { - lifecycleScope.launch { // bind view for call render - container1.store.bindView(view = view1, scope = this) - } - lifecycleScope.launch { // bind side effects (single events) for catch on view - container1.store.bindSideEffects(view = view1, scope = this) - } - - lifecycleScope.launch { // bind view for call render - container2.store.bindView(view = view2, scope = this) - } - lifecycleScope.launch { // bind side effects (single events) for catch on view - container2.store.bindSideEffects(view = view2, scope = this) - } - } -} - -// handle actions, generate side effects (single events) and send changes (may be viewModel ane change) -private fun createHandler(): Handler = - { _: State, action: Action, sideEffect: MutableSharedFlow -> - when (action) { - Action.Click -> { - sideEffect.emit(SideEffect.ShowToast("")) - delay(10) - emit(Modification.ChangeText("")) - } - } - } - -// handle modifications and current state and generate new state for view\ -private fun createReducer(): Reducer = { _: State, modification: Modification -> - when (modification) { - is Modification.ChangeText -> { - State.Default - } - } -} - -private fun ExampleManyStoreFragment.getStore() = object : MviFlowStore { - - override val store: MviFlow - get() = MviFlow( - initialState = State.Default, - reducer = createReducer(), - handler = createHandler(), - scope = lifecycleScope - )// create "store" -} - -private fun getView() = - object : MviRenderView { - override fun render(state: State) { - when (state) { - State.Default -> { - // render view - } - } - } - - override fun actionsFlow(): Flow = callbackFlow { - //generate actions click and other - awaitClose() - } - - override fun sideEffects(sideEffect: SideEffect) { - when (sideEffect) { - is SideEffect.ShowToast -> { - // Toast.show - } - } - } - - } \ No newline at end of file diff --git a/core-mvi/src/main/kotlin/example/ExampleStoreFragment.kt b/core-mvi/src/main/kotlin/example/ExampleStoreFragment.kt deleted file mode 100644 index 2f2b24eebb..0000000000 --- a/core-mvi/src/main/kotlin/example/ExampleStoreFragment.kt +++ /dev/null @@ -1,75 +0,0 @@ -package example - -import com.vanced.manager.core.mvi.* -import kotlinx.coroutines.* -import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.callbackFlow - -class ExampleStoreFragment : - MviRenderView, - MviFlowStore { - - private val lifecycleScope = CoroutineScope(Job()) - - // handle actions, generate side effects (single events) and send changes (may be viewModel ane change) - private val handler: Handler = - { _: State, action: Action, sideEffectsFlow: MutableSharedFlow -> - when (action) { - Action.Click -> { - sideEffectsFlow.emit(SideEffect.ShowToast("")) - delay(10) - emit(Modification.ChangeText("")) - } - } - } - - // handle modifications and current state and generate new state for view - private val reducer: Reducer = { _: State, modification: Modification -> - when (modification) { - is Modification.ChangeText -> { - State.Default - } - } - } - - override val store: MviFlow = - MviFlow( - initialState = State.Default, - reducer = reducer, - handler = handler, - scope = lifecycleScope - )// create "store" - - private fun onCreate() { - lifecycleScope.launch { // bind view for call render - store.bindView(view = this@ExampleStoreFragment, scope = this) - } - lifecycleScope.launch { // bind side effects (single events) for catch on view - store.bindSideEffects(view = this@ExampleStoreFragment, scope = this) - } - } - - override fun render(state: State) { - when (state) { - State.Default -> { - // render view - } - } - } - - @ExperimentalCoroutinesApi - override fun actionsFlow(): Flow = callbackFlow { - //generate actions click and other - awaitClose() - } - - override fun sideEffects(sideEffect: SideEffect) { // single events - when (sideEffect) { - is SideEffect.ShowToast -> { - // Toast.show - } - } - } -} \ No newline at end of file diff --git a/core-mvi/src/main/kotlin/example/ExampleViewModel.kt b/core-mvi/src/main/kotlin/example/ExampleViewModel.kt deleted file mode 100644 index 8666ba0d1d..0000000000 --- a/core-mvi/src/main/kotlin/example/ExampleViewModel.kt +++ /dev/null @@ -1,43 +0,0 @@ -package example - -import com.vanced.manager.core.mvi.Handler -import com.vanced.manager.core.mvi.MviFlow -import com.vanced.manager.core.mvi.MviFlowStore -import com.vanced.manager.core.mvi.Reducer -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.MutableSharedFlow - -class ExampleViewModel : MviFlowStore { - - private val viewModelScope = CoroutineScope(Job()) - - // handle actions, generate side effects (single events) and send changes (may be viewModel ane change) - private val handler: Handler = - { _: State, action: Action, sideEffectsFlow: MutableSharedFlow -> - when (action) { - Action.Click -> { - sideEffectsFlow.emit(SideEffect.ShowToast("")) - delay(10) - emit(Modification.ChangeText("")) - } - } - } - - // handle modifications and current state and generate new state for view - private val reducer: Reducer = { _: State, modification: Modification -> - when (modification) { - is Modification.ChangeText -> { - State.Default - } - } - } - - override val store: MviFlow = MviFlow( - initialState = State.Default, - reducer = reducer, - handler = handler, - scope = viewModelScope - ) // create "store" -} \ No newline at end of file diff --git a/core-mvi/src/main/kotlin/example/ExampleWithViewModelFragment.kt b/core-mvi/src/main/kotlin/example/ExampleWithViewModelFragment.kt deleted file mode 100644 index 30a70d9848..0000000000 --- a/core-mvi/src/main/kotlin/example/ExampleWithViewModelFragment.kt +++ /dev/null @@ -1,49 +0,0 @@ -package example - -import com.vanced.manager.core.mvi.MviRenderView -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.Job -import kotlinx.coroutines.channels.awaitClose -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.callbackFlow -import kotlinx.coroutines.launch - - -class ExampleWithViewModelFragment : MviRenderView { - - private val lifecycleScope = CoroutineScope(Job()) - - private val viewModel = ExampleViewModel() - - private fun onCreate() { - lifecycleScope.launch { - viewModel.store.bindView(view = this@ExampleWithViewModelFragment, scope = this) - } - lifecycleScope.launch { - viewModel.store.bindSideEffects(view = this@ExampleWithViewModelFragment, scope = this) - } - } - - override fun render(state: State) { - when (state) { - State.Default -> { - // render view - } - } - } - - @ExperimentalCoroutinesApi - override fun actionsFlow(): Flow = callbackFlow { - //generate actions click and other - awaitClose() - } - - override fun sideEffects(sideEffect: SideEffect) { // single events - when (sideEffect) { - is SideEffect.ShowToast -> { - // Toast.show - } - } - } -} \ No newline at end of file diff --git a/core-mvi/src/main/kotlin/example/Mvi.kt b/core-mvi/src/main/kotlin/example/Mvi.kt deleted file mode 100644 index 81f236928f..0000000000 --- a/core-mvi/src/main/kotlin/example/Mvi.kt +++ /dev/null @@ -1,25 +0,0 @@ -package example - -// "single events" -sealed class SideEffect { - - data class ShowToast(val message: String) : SideEffect() -} - -// view state -sealed class State { - - object Default : State() -} - -// view actions -sealed class Action { - - object Click : Action() -} - -// Modification for view -sealed class Modification { - - data class ChangeText(val text: String) : Modification() -} \ No newline at end of file diff --git a/core-mvi/src/test/kotlin/com/vanced/manager/core/mvi/MviFlowSpec.kt b/core-mvi/src/test/kotlin/com/vanced/manager/core/mvi/MviFlowSpec.kt deleted file mode 100644 index 854888c2b3..0000000000 --- a/core-mvi/src/test/kotlin/com/vanced/manager/core/mvi/MviFlowSpec.kt +++ /dev/null @@ -1,169 +0,0 @@ -package com.vanced.manager.core.mvi - -import com.vanced.manager.core.mvi.subject.* -import io.kotest.core.spec.style.ShouldSpec -import io.kotest.matchers.shouldBe -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.flow -import kotlinx.coroutines.test.TestCoroutineScope - -@ExperimentalCoroutinesApi -class MviFlowSpec : ShouldSpec() { - - data class Test(val msg: String) - - init { - context("Various events") { - should("return Modifications") { - val testData = "testText" - val store = SubjectStore( - scope = TestCoroutineScope(), - defaultState = State.Default, - testData = testData - ) - SubjectView( - scope = TestCoroutineScope(), - store = store, - actions = flow { - emit(Action.Click) - emit(Action.Tap) - emit(Action.Click) - } - ) - delay(600) - store.modifications shouldBe listOf( - Modification.ChangeDescription(testData), - Modification.ChangeTitle(testData), - Modification.ChangeDescription(testData), - ) - } - should("return States") { - val testData = 4545454545 - val store = SubjectStore( - scope = TestCoroutineScope(), - defaultState = State.Default, - testData = testData - ) - val view = SubjectView( - scope = TestCoroutineScope(), - store = store, - actions = flow { - emit(Action.Click) - emit(Action.Tap) - emit(Action.Click) - } - ) - delay(600) - view.states shouldBe listOf( - State.Default, - State.SetDescription(testData), - State.Default, - State.SetTitle(testData), - State.Default, - State.SetDescription(testData), - State.Default, - ) - } - should("return SideEffects") { - val testData = Test("test") - val store = SubjectStore( - scope = TestCoroutineScope(), - defaultState = State.Default, - testData = testData - ) - val view = SubjectView( - scope = TestCoroutineScope(), - store = store, - actions = flow { - emit(Action.Click) - emit(Action.Tap) - emit(Action.Click) - } - ) - delay(600) - view.sideEffects shouldBe listOf( - SideEffect.ShowToast(testData), - SideEffect.ShowToast(testData), - SideEffect.ShowToast(testData), - ) - } - } - - context("The same event") { - should("return Modifications") { - val testData = Test("test") - val store = SubjectStore( - scope = TestCoroutineScope(), - defaultState = State.Default, - testData = testData - ) - SubjectView( - scope = TestCoroutineScope(), - store = store, - actions = flow { - emit(Action.Click) - emit(Action.Click) - emit(Action.Click) - } - ) - delay(600) - store.modifications shouldBe listOf( - Modification.ChangeDescription(testData), - Modification.ChangeDescription(testData), - Modification.ChangeDescription(testData), - ) - } - should("return States") { - val testData = Test("test") - val store = SubjectStore( - scope = TestCoroutineScope(), - defaultState = State.Default, - testData = testData - ) - val view = SubjectView( - scope = TestCoroutineScope(), - store = store, - actions = flow { - emit(Action.Click) - emit(Action.Click) - emit(Action.Click) - } - ) - delay(600) - view.states shouldBe listOf( - State.Default, - State.SetDescription(testData), - State.Default, - State.SetDescription(testData), - State.Default, - State.SetDescription(testData), - State.Default - ) - } - should("return SideEffects") { - val testData = Test("test") - val store = SubjectStore( - scope = TestCoroutineScope(), - defaultState = State.Default, - testData = testData - ) - val view = SubjectView( - scope = TestCoroutineScope(), - store = store, - actions = flow { - emit(Action.Click) - emit(Action.Click) - emit(Action.Click) - } - ) - delay(600) - view.sideEffects shouldBe listOf( - SideEffect.ShowToast(testData), - SideEffect.ShowToast(testData), - SideEffect.ShowToast(testData), - ) - } - } - } -} \ No newline at end of file diff --git a/core-mvi/src/test/kotlin/com/vanced/manager/core/mvi/subject/MviSubject.kt b/core-mvi/src/test/kotlin/com/vanced/manager/core/mvi/subject/MviSubject.kt deleted file mode 100644 index aafab30cdd..0000000000 --- a/core-mvi/src/test/kotlin/com/vanced/manager/core/mvi/subject/MviSubject.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.vanced.manager.core.mvi.subject - -// "single events" -sealed class SideEffect { - - data class ShowToast(val message: testData) : SideEffect() -} - -// view state -sealed class State { - - object Default : State() - - data class SetTitle(val text: testData) : State() - - data class SetDescription(val text: testData) : State() -} - -// view actions -sealed class Action { - - object Click : Action() - - object Tap : Action() -} - -// Modification for view -sealed class Modification { - - data class ChangeTitle(val text: testData) : Modification() - - data class ChangeDescription(val text: testData) : Modification() -} \ No newline at end of file diff --git a/core-mvi/src/test/kotlin/com/vanced/manager/core/mvi/subject/SubjectStore.kt b/core-mvi/src/test/kotlin/com/vanced/manager/core/mvi/subject/SubjectStore.kt deleted file mode 100644 index 7c0596f69e..0000000000 --- a/core-mvi/src/test/kotlin/com/vanced/manager/core/mvi/subject/SubjectStore.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.vanced.manager.core.mvi.subject - -import com.vanced.manager.core.mvi.Handler -import com.vanced.manager.core.mvi.MviFlow -import com.vanced.manager.core.mvi.MviFlowStore -import com.vanced.manager.core.mvi.Reducer -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.MutableSharedFlow - -class SubjectStore( - scope: CoroutineScope, - defaultState: State, - private val testData: TD -) : MviFlowStore { - - val modifications = mutableListOf() - - private val handler: Handler = - { state: State, action: Action, sideEffectsFlow: MutableSharedFlow -> - when (action) { - Action.Click -> { - emit(Modification.ChangeDescription(testData)) - sideEffectsFlow.emit(SideEffect.ShowToast(testData)) - } - Action.Tap -> { - emit(Modification.ChangeTitle(testData)) - sideEffectsFlow.emit(SideEffect.ShowToast(testData)) - } - } - } - - private val reducer: Reducer = - { state: State, modification: Modification -> - modifications.add(modification) - when (modification) { - is Modification.ChangeDescription<*> -> { - emit(State.SetDescription(modification.text)) - emit(State.Default) - } - is Modification.ChangeTitle<*> -> { - emit(State.SetTitle(modification.text)) - emit(State.Default) - } - } - } - - override val store: MviFlow = - MviFlow( - scope = scope, - initialState = defaultState, - handler = handler, - reducer = reducer - ) -} \ No newline at end of file diff --git a/core-mvi/src/test/kotlin/com/vanced/manager/core/mvi/subject/SubjectView.kt b/core-mvi/src/test/kotlin/com/vanced/manager/core/mvi/subject/SubjectView.kt deleted file mode 100644 index 7a0dc1d750..0000000000 --- a/core-mvi/src/test/kotlin/com/vanced/manager/core/mvi/subject/SubjectView.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.vanced.manager.core.mvi.subject - -import com.vanced.manager.core.mvi.MviRenderView -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.launch - -class SubjectView( - scope: CoroutineScope, - private val actions: Flow, - store: SubjectStore -) : MviRenderView { - - val states = mutableListOf() - val sideEffects = mutableListOf() - - init { - scope.launch { - store.store.bindSideEffects( - view = this@SubjectView, - scope = this - ) - } - scope.launch { - store.store.bindView( - view = this@SubjectView, - scope = this - ) - } - } - - override fun render(state: State) { - states.add(state) - } - - @ExperimentalCoroutinesApi - override fun actionsFlow(): Flow = actions - - override fun sideEffects(sideEffect: SideEffect) { - sideEffects.add(sideEffect) - } -} \ No newline at end of file diff --git a/core-presentation/.gitignore b/core-presentation/.gitignore deleted file mode 100644 index 42afabfd2a..0000000000 --- a/core-presentation/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/core-presentation/build.gradle.kts b/core-presentation/build.gradle.kts deleted file mode 100644 index 85d1b3ca34..0000000000 --- a/core-presentation/build.gradle.kts +++ /dev/null @@ -1,42 +0,0 @@ -plugins { - id("com.android.library") - kotlin("android") -} - -android { - compileSdkVersion(30) - - defaultConfig { - minSdkVersion(16) - targetSdkVersion(30) - versionCode = 1 - versionName = "1.0" - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles("consumer-rules.pro") - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") - } - } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - - tasks.withType { - kotlinOptions { - jvmTarget = "1.8" - } - } - -} - -dependencies { - implementation(kotlin("stdlib")) - implementation("androidx.core:core-ktx:1.3.2") - implementation("androidx.appcompat:appcompat:1.2.0") -} \ No newline at end of file diff --git a/core-presentation/src/main/AndroidManifest.xml b/core-presentation/src/main/AndroidManifest.xml deleted file mode 100644 index f9c138f6c6..0000000000 --- a/core-presentation/src/main/AndroidManifest.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/core-presentation/src/main/java/com/vanced/manager/core/presentation/BaseViewModel.kt b/core-presentation/src/main/java/com/vanced/manager/core/presentation/BaseViewModel.kt deleted file mode 100644 index 4236db913c..0000000000 --- a/core-presentation/src/main/java/com/vanced/manager/core/presentation/BaseViewModel.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.vanced.manager.core.presentation - -import androidx.lifecycle.ViewModel - -class BaseViewModel : ViewModel() { - //TODO -} \ No newline at end of file diff --git a/core-ui/.gitignore b/core-ui/.gitignore deleted file mode 100644 index 42afabfd2a..0000000000 --- a/core-ui/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/core-ui/build.gradle.kts b/core-ui/build.gradle.kts deleted file mode 100644 index 641084e1cd..0000000000 --- a/core-ui/build.gradle.kts +++ /dev/null @@ -1,53 +0,0 @@ -plugins { - id("com.android.library") - kotlin("android") -} - -android { - compileSdkVersion(30) - - defaultConfig { - minSdkVersion(16) - targetSdkVersion(30) - versionCode = 1 - versionName = "1.0" - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles("consumer-rules.pro") - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - viewBinding = true - } - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - - tasks.withType { - kotlinOptions { - jvmTarget = "1.8" - } - } -} - -dependencies { - implementation(kotlin("stdlib")) - implementation(kotlin("reflect")) - implementation("androidx.core:core-ktx:1.3.2") - implementation("androidx.appcompat:appcompat:1.2.0") - implementation("androidx.activity:activity-ktx:1.2.2") - implementation("com.google.android.material:material:1.3.0") - - //https://developer.android.com/jetpack/androidx/releases/lifecycle - implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.3.1") - implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1") -} \ No newline at end of file diff --git a/core-ui/src/main/AndroidManifest.xml b/core-ui/src/main/AndroidManifest.xml deleted file mode 100644 index 55b93fbfb4..0000000000 --- a/core-ui/src/main/AndroidManifest.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/core-ui/src/main/java/com/vanced/manager/core/ui/base/BindingBottomSheetDialogFragment.kt b/core-ui/src/main/java/com/vanced/manager/core/ui/base/BindingBottomSheetDialogFragment.kt deleted file mode 100644 index b3ea8d512e..0000000000 --- a/core-ui/src/main/java/com/vanced/manager/core/ui/base/BindingBottomSheetDialogFragment.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.vanced.manager.core.ui.base - -import android.app.Dialog -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.FrameLayout -import androidx.viewbinding.ViewBinding -import com.google.android.material.bottomsheet.BottomSheetBehavior -import com.google.android.material.bottomsheet.BottomSheetDialog -import com.google.android.material.bottomsheet.BottomSheetDialogFragment - -abstract class BindingBottomSheetDialogFragment : BottomSheetDialogFragment() { - - private var _binding: VB? = null - protected val binding: VB get() = requireNotNull(_binding) - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - _binding = binding(inflater, container, savedInstanceState) - otherSetups() - return binding.root - } - - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - val dialog = super.onCreateDialog(savedInstanceState) - dialog.setOnShowListener { - val bottomSheetDialogFragment = (it as BottomSheetDialog).findViewById(com.google.android.material.R.id.design_bottom_sheet) - if (bottomSheetDialogFragment != null) { - BottomSheetBehavior.from(bottomSheetDialogFragment).apply { - state = BottomSheetBehavior.STATE_EXPANDED - } - } - } - return dialog - } - - protected abstract fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): VB - - protected open fun otherSetups() = Unit - - override fun onDestroyView() { - super.onDestroyView() - _binding = null - } -} \ No newline at end of file diff --git a/core-ui/src/main/java/com/vanced/manager/core/ui/base/BindingDialogFragment.kt b/core-ui/src/main/java/com/vanced/manager/core/ui/base/BindingDialogFragment.kt deleted file mode 100644 index bc3ffa9b97..0000000000 --- a/core-ui/src/main/java/com/vanced/manager/core/ui/base/BindingDialogFragment.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.vanced.manager.core.ui.base - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.appcompat.app.AppCompatDialogFragment -import androidx.viewbinding.ViewBinding - -abstract class BindingDialogFragment : AppCompatDialogFragment() { - - private var _binding: VB? = null - protected val binding: VB get() = requireNotNull(_binding) - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - _binding = binding(inflater, container, savedInstanceState) - otherSetups() - return binding.root - } - - protected abstract fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): VB - - protected open fun otherSetups() = Unit - - override fun onDestroyView() { - super.onDestroyView() - _binding = null - } -} \ No newline at end of file diff --git a/core-ui/src/main/java/com/vanced/manager/core/ui/base/BindingFragment.kt b/core-ui/src/main/java/com/vanced/manager/core/ui/base/BindingFragment.kt deleted file mode 100644 index 3462c79e67..0000000000 --- a/core-ui/src/main/java/com/vanced/manager/core/ui/base/BindingFragment.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.vanced.manager.core.ui.base - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.Fragment -import androidx.viewbinding.ViewBinding - -abstract class BindingFragment : Fragment() { - - private var _binding: VB? = null - protected val binding: VB get() = requireNotNull(_binding) - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - _binding = binding(inflater, container, savedInstanceState) - otherSetups() - return binding.root - } - - protected abstract fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): VB - - protected open fun otherSetups() = Unit - - override fun onDestroyView() { - super.onDestroyView() - _binding = null - } -} \ No newline at end of file diff --git a/core-ui/src/main/java/com/vanced/manager/core/ui/ext/FragmentExt.kt b/core-ui/src/main/java/com/vanced/manager/core/ui/ext/FragmentExt.kt deleted file mode 100644 index 6dc5d24dd6..0000000000 --- a/core-ui/src/main/java/com/vanced/manager/core/ui/ext/FragmentExt.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.vanced.manager.core.ui.ext - -import android.util.Log -import androidx.fragment.app.DialogFragment -import androidx.fragment.app.Fragment - -fun Fragment.requireSupportFM() = requireActivity().supportFragmentManager - -fun Fragment.showDialog(dialog: D) { - try { - dialog.show(requireSupportFM(), dialog::class.simpleName) - } catch (e: IllegalStateException) { - Log.d("VMUI", "Can not perform this action after onSaveInstanceState") - } - -} \ No newline at end of file diff --git a/feature-home/.gitignore b/feature-home/.gitignore deleted file mode 100644 index 42afabfd2a..0000000000 --- a/feature-home/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/feature-home/build.gradle.kts b/feature-home/build.gradle.kts deleted file mode 100644 index af97f019a2..0000000000 --- a/feature-home/build.gradle.kts +++ /dev/null @@ -1,87 +0,0 @@ -plugins { - id("com.android.library") - kotlin("android") -} - -android { - compileSdkVersion(30) - - defaultConfig { - minSdkVersion(16) - targetSdkVersion(30) - versionCode = 1 - versionName = "1.0" - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles("consumer-rules.pro") - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - viewBinding = true - } - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - - tasks.withType { - kotlinOptions { - jvmTarget = "1.8" - } - } - -} - -android.testOptions { - unitTests.all { - it.useJUnitPlatform() - } -} - - -dependencies { - implementation(project(":core-ui")) - implementation(project(":core-presentation")) - implementation(project(":library-network")) - - implementation(kotlin("stdlib")) - implementation("androidx.appcompat:appcompat:1.2.0") - implementation("androidx.core:core-ktx:1.3.2") - implementation("androidx.fragment:fragment-ktx:1.3.3") - implementation("androidx.lifecycle:lifecycle-livedata-core-ktx:2.3.1") - implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1") - implementation("com.google.android.material:material:1.3.0") - implementation("androidx.swiperefreshlayout:swiperefreshlayout:1.1.0") - - implementation("com.squareup.retrofit2:retrofit:2.9.0") - - implementation("com.squareup.moshi:moshi-kotlin:1.11.0") - implementation("com.squareup.moshi:moshi-kotlin-codegen:1.11.0") - implementation("com.squareup.moshi:moshi-adapters:1.11.0") - - implementation("com.squareup.okhttp3:logging-interceptor:4.9.1") - - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2") - - implementation("org.koin:koin-android:2.2.1") - implementation("org.koin:koin-android-viewmodel:2.2.1") - implementation("org.koin:koin-android-ext:2.2.1") - - testImplementation("io.kotest:kotest-runner-junit5:4.4.3") - testImplementation("io.kotest:kotest-assertions-core:4.4.3") - testImplementation("io.kotest:kotest-property:4.4.3") - testImplementation("io.mockk:mockk:1.10.6") - - androidTestImplementation("io.mockk:mockk-android:1.10.6") - androidTestImplementation("androidx.test:core:1.3.0") - androidTestImplementation("androidx.test:runner:1.3.0") - androidTestImplementation("androidx.test:rules:1.3.0") -} \ No newline at end of file diff --git a/feature-home/src/main/AndroidManifest.xml b/feature-home/src/main/AndroidManifest.xml deleted file mode 100644 index 714a235e5a..0000000000 --- a/feature-home/src/main/AndroidManifest.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/feature-home/src/main/java/com/vanced/manager/feature/home/data/api/AppsApi.kt b/feature-home/src/main/java/com/vanced/manager/feature/home/data/api/AppsApi.kt deleted file mode 100644 index e483138cf9..0000000000 --- a/feature-home/src/main/java/com/vanced/manager/feature/home/data/api/AppsApi.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.vanced.manager.feature.home.data.api - -import com.vanced.manager.feature.home.data.dto.AppInfoDto -import okhttp3.ResponseBody -import retrofit2.http.GET -import retrofit2.http.Url - -interface AppsApi { - - @GET - suspend fun getAppsInfo(@Url url: String): List - - @GET - suspend fun getIcon(@Url url: String): ResponseBody -} \ No newline at end of file diff --git a/feature-home/src/main/java/com/vanced/manager/feature/home/data/datasource/AppIconDataSource.kt b/feature-home/src/main/java/com/vanced/manager/feature/home/data/datasource/AppIconDataSource.kt deleted file mode 100644 index 4b3645de64..0000000000 --- a/feature-home/src/main/java/com/vanced/manager/feature/home/data/datasource/AppIconDataSource.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.vanced.manager.feature.home.data.datasource - -import android.graphics.Bitmap -import android.graphics.BitmapFactory -import com.vanced.manager.feature.home.data.api.AppsApi -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext - -interface AppIconDataSource { - - suspend fun getIcon(url: String): Bitmap -} - -class AppIconDataSourceImpl( - private val api: AppsApi -) : AppIconDataSource { - - override suspend fun getIcon(url: String): Bitmap = - withContext(Dispatchers.IO) { - val inputStream = api.getIcon(url).byteStream() - BitmapFactory.decodeStream(inputStream) - } -} \ No newline at end of file diff --git a/feature-home/src/main/java/com/vanced/manager/feature/home/data/datasource/AppsInfoDataSource.kt b/feature-home/src/main/java/com/vanced/manager/feature/home/data/datasource/AppsInfoDataSource.kt deleted file mode 100644 index 3db690cbc7..0000000000 --- a/feature-home/src/main/java/com/vanced/manager/feature/home/data/datasource/AppsInfoDataSource.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.vanced.manager.feature.home.data.datasource - -import com.vanced.manager.feature.home.data.api.AppsApi -import com.vanced.manager.feature.home.data.dto.AppInfoDto -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext - -interface AppsInfoDataSource { - - suspend fun getAppsInfo(channel: String): List -} - -class AppsInfoDataSourceImpl( - private val api: AppsApi -) : AppsInfoDataSource { - - override suspend fun getAppsInfo(channel: String): List = - withContext(Dispatchers.IO) { - api.getAppsInfo(channel) - } -} \ No newline at end of file diff --git a/feature-home/src/main/java/com/vanced/manager/feature/home/data/dto/AppInfoDto.kt b/feature-home/src/main/java/com/vanced/manager/feature/home/data/dto/AppInfoDto.kt deleted file mode 100644 index 31721415c4..0000000000 --- a/feature-home/src/main/java/com/vanced/manager/feature/home/data/dto/AppInfoDto.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.vanced.manager.feature.home.data.dto - -import com.squareup.moshi.Json -import com.squareup.moshi.JsonClass - -@JsonClass(generateAdapter = true) -data class AppInfoDto( - @Json(name = "name") val name: String, - @Json(name = "iconUrl") val iconUrl: String, - @Json(name = "versionName") val versionName: String, - @Json(name = "versionCode") val versionCode: Int, - @Json(name = "pkgName") val pkgName: String, - @Json(name = "downloadUrl") val downloadUrl: String, - @Json(name = "changelog") val changelog: String, - @Json(name = "languages") val languages: List?, - @Json(name = "themes") val themes: List?, -) diff --git a/feature-home/src/main/java/com/vanced/manager/feature/home/data/repository/AppsRepositoryImpl.kt b/feature-home/src/main/java/com/vanced/manager/feature/home/data/repository/AppsRepositoryImpl.kt deleted file mode 100644 index a074982cb2..0000000000 --- a/feature-home/src/main/java/com/vanced/manager/feature/home/data/repository/AppsRepositoryImpl.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.vanced.manager.feature.home.data.repository - -import com.vanced.manager.feature.home.data.datasource.AppIconDataSource -import com.vanced.manager.feature.home.data.datasource.AppsInfoDataSource -import com.vanced.manager.feature.home.data.datasource.PkgInformationDataSource -import com.vanced.manager.feature.home.data.dto.AppInfoDto -import com.vanced.manager.feature.home.domain.entity.AppInfo -import com.vanced.manager.feature.home.domain.entity.AppState -import com.vanced.manager.feature.home.domain.repository.AppsRepository - - -class AppsRepositoryImpl( - private val appsInfoDataSource: AppsInfoDataSource, - private val appIconDataSource: AppIconDataSource, - private val pkgInformationDataSource: PkgInformationDataSource, - private val channel: String //TODO experiment -) : AppsRepository { - - // TODO switch content OR send toggles to build retrofit and change channel get json - override suspend fun getAppsInfo(): List = - appsInfoDataSource.getAppsInfo(channel) - .map { it.toEntity() } - - private suspend fun AppInfoDto.toEntity(): AppInfo { - val localVersionName = pkgInformationDataSource.getVersionName(pkgName) - val localVersionCode = pkgInformationDataSource.getVersionCode(pkgName) - return AppInfo( - name = name, - icon = appIconDataSource.getIcon(iconUrl), - versionName = versionName, - versionCode = versionCode, - pkgName = pkgName, - downloadUrl = downloadUrl, - changelog = changelog, - languages = languages, - themes = themes, - localVersionName = localVersionName, - localVersionCode = localVersionCode, - state = compareCode(versionCode, localVersionCode) - ) - } - - private fun compareCode(remote: Int, local: Int?): AppState = - if (local != null) { - when { - remote > local -> AppState.UPDATE - remote == local -> AppState.REINSTALL - remote < local -> AppState.REINSTALL - else -> throw IllegalArgumentException("Unknown versions") - } - } else { - AppState.INSTALL - } -} \ No newline at end of file diff --git a/feature-home/src/main/java/com/vanced/manager/feature/home/di/FeatureHomeModules.kt b/feature-home/src/main/java/com/vanced/manager/feature/home/di/FeatureHomeModules.kt deleted file mode 100644 index bda6df442d..0000000000 --- a/feature-home/src/main/java/com/vanced/manager/feature/home/di/FeatureHomeModules.kt +++ /dev/null @@ -1,72 +0,0 @@ -package com.vanced.manager.feature.home.di - -import com.vanced.manager.feature.home.data.api.AppsApi -import com.vanced.manager.feature.home.data.datasource.AppsInfoDataSource -import com.vanced.manager.feature.home.data.datasource.AppsInfoDataSourceImpl -import com.vanced.manager.feature.home.data.datasource.PkgInformationDataSource -import com.vanced.manager.feature.home.data.datasource.PkgInformationDataSourceImpl -import com.vanced.manager.feature.home.data.pkg.PkgManager -import com.vanced.manager.feature.home.data.pkg.PkgManagerImpl -import com.vanced.manager.feature.home.data.repository.AppsRepositoryImpl -import com.vanced.manager.feature.home.domain.repository.AppsRepository -import com.vanced.manager.feature.home.domain.usecase.GetAppsInfoUseCase -import com.vanced.manager.feature.home.presentation.HomeViewModel -import com.vanced.manager.library.network.service.createRetrofitService -import org.koin.android.ext.koin.androidContext -import org.koin.android.viewmodel.dsl.viewModel -import org.koin.core.qualifier.named -import org.koin.dsl.module - -internal val retrofitModule = module { - single { createRetrofitService(get()) } -} - -internal val pkgManagerModule = module { - single { PkgManagerImpl(androidContext().packageManager) } -} - -internal val dataSourceModule = module { - single { AppsInfoDataSourceImpl(api = get()) } - - single { PkgInformationDataSourceImpl(pkgManager = get()) } -} - -internal val channelModule = module { - factory(named("channel")) { - listOf( - "https://vancedapp.com/api/v1/latest.json", - "https://vancedapp.com/api/v1/latest_root.json", - "https://vancedapp.custom.com/api/v1/latest.json", - "https://vancedapp.custom.com/api/v1/latest_root.json" - ).random() - } -} - -internal val repositoryModule = module { - factory { - AppsRepositoryImpl( - appsInfoDataSource = get(), - appIconDataSource = get(), - pkgInformationDataSource = get(), - channel = get(named("channel")) //TODO experiment - ) - } -} - -internal val useCaseModule = module { - single { GetAppsInfoUseCase(repository = get()) } -} - -internal val viewModelModule = module { - viewModel { HomeViewModel(getAppsInfoUseCase = get()) } -} - -val FeatureHomeModules = listOf( - channelModule, //TODO experiment - retrofitModule, - pkgManagerModule, - dataSourceModule, - repositoryModule, - useCaseModule, - viewModelModule -) \ No newline at end of file diff --git a/feature-home/src/main/java/com/vanced/manager/feature/home/domain/entity/AppInfo.kt b/feature-home/src/main/java/com/vanced/manager/feature/home/domain/entity/AppInfo.kt deleted file mode 100644 index 89d6fb1f18..0000000000 --- a/feature-home/src/main/java/com/vanced/manager/feature/home/domain/entity/AppInfo.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.vanced.manager.feature.home.domain.entity - -import android.graphics.Bitmap - -data class AppInfo( - val name: String, - val icon: Bitmap, - val versionName: String, - val versionCode: Int, - val pkgName: String, - val downloadUrl: String, - val changelog: String, - val languages: List?, - val themes: List?, - val localVersionName: String?, - val localVersionCode: Int?, - val state: AppState, -) \ No newline at end of file diff --git a/feature-home/src/main/java/com/vanced/manager/feature/home/domain/entity/AppState.kt b/feature-home/src/main/java/com/vanced/manager/feature/home/domain/entity/AppState.kt deleted file mode 100644 index 9fd2e5c89e..0000000000 --- a/feature-home/src/main/java/com/vanced/manager/feature/home/domain/entity/AppState.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.vanced.manager.feature.home.domain.entity - -enum class AppState { - INSTALL, - UPDATE, - REINSTALL -} \ No newline at end of file diff --git a/feature-home/src/main/java/com/vanced/manager/feature/home/domain/entity/example.json b/feature-home/src/main/java/com/vanced/manager/feature/home/domain/entity/example.json deleted file mode 100644 index 0ebfe5aafb..0000000000 --- a/feature-home/src/main/java/com/vanced/manager/feature/home/domain/entity/example.json +++ /dev/null @@ -1,60 +0,0 @@ -[ - { - "name": "manager", - "iconUrl": "https://github.com/YTVanced/VancedManager/icon.png", - "versionName": "2.0.1", - "versionCode": 201, - "pkgName": "com.vanced.manager", - "downloadUrl": "https://github.com/YTVanced/VancedManager/releases/latest/download", - "changelog": "- Fixed issues with Android 5 and 6\n- Fixed various crashes\n- Improved performance" - }, - { - "name": "vanced", - "iconUrl": "https://github.com/YTVanced/icon.png", - "versionName": "15.43.32", - "versionCode": 1515701696, - "pkgName": "com.vanced.android.youtube", - "downloadUrl": "https://github.com/YTVanced/releases/latest/download", - "changelog": "- Added toggle to revert to ExoPlayer V1\\r\\n- Added toggle to hide the new big Create button\\r\\n- A lot of fixes to old features", - "languages": [ - "af", - "am", - "ar", - "az", - "be", - "bg", - "bn", - "bs", - "ca", - "cs", - "da", - "de", - "el", - "en" - ], - // may be null, - "themes": [ - "dark", - "black" - ] - // may be null - }, - { - "name": "music", - "iconUrl": "https://github.com/YTMVanced/icon.png", - "versionName": "4.04.52", - "versionCode": 40452240, - "pkgName": "com.vanced.android.apps.youtube.music", - "downloadUrl": "https://github.com/YTMVanced/releases/latest/download", - "changelog": "- Added a toggle switch for outline icons\\n- Toolbar premium button has been removed" - }, - { - "name": "microg", - "iconUrl": "https://github.com/microg/icon.png", - "versionName": "0.2.14.204215", - "versionCode": 204215001, - "pkgName": "com.vanced.android.apps.youtube.music", - "downloadUrl": "https://github.com/microg/releases/latest/download", - "changelog": "- Updated to upstream sources\\n- Fixed video uploading" - } -] \ No newline at end of file diff --git a/feature-home/src/main/java/com/vanced/manager/feature/home/domain/repository/AppsRepository.kt b/feature-home/src/main/java/com/vanced/manager/feature/home/domain/repository/AppsRepository.kt deleted file mode 100644 index eead2233b4..0000000000 --- a/feature-home/src/main/java/com/vanced/manager/feature/home/domain/repository/AppsRepository.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.vanced.manager.feature.home.domain.repository - -import com.vanced.manager.feature.home.domain.entity.AppInfo - -interface AppsRepository { - - suspend fun getAppsInfo(): List -} \ No newline at end of file diff --git a/feature-home/src/main/java/com/vanced/manager/feature/home/domain/usecase/GetAppsInfoUseCase.kt b/feature-home/src/main/java/com/vanced/manager/feature/home/domain/usecase/GetAppsInfoUseCase.kt deleted file mode 100644 index 451ad3e848..0000000000 --- a/feature-home/src/main/java/com/vanced/manager/feature/home/domain/usecase/GetAppsInfoUseCase.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.vanced.manager.feature.home.domain.usecase - -import com.vanced.manager.feature.home.domain.entity.AppInfo -import com.vanced.manager.feature.home.domain.repository.AppsRepository - -class GetAppsInfoUseCase( - private val repository: AppsRepository -) { - - suspend operator fun invoke(): List = - repository.getAppsInfo() -} \ No newline at end of file diff --git a/feature-home/src/main/java/com/vanced/manager/feature/home/presentation/HomeViewModel.kt b/feature-home/src/main/java/com/vanced/manager/feature/home/presentation/HomeViewModel.kt deleted file mode 100644 index c5140bbaef..0000000000 --- a/feature-home/src/main/java/com/vanced/manager/feature/home/presentation/HomeViewModel.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.vanced.manager.feature.home.presentation - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.vanced.manager.feature.home.domain.entity.AppInfo -import com.vanced.manager.feature.home.domain.usecase.GetAppsInfoUseCase -import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.SharedFlow -import kotlinx.coroutines.flow.asSharedFlow -import kotlinx.coroutines.launch -import retrofit2.HttpException - -class HomeViewModel( - private val getAppsInfoUseCase: GetAppsInfoUseCase -) : ViewModel() { - - private val _appsList = MutableSharedFlow>() - val appsList: SharedFlow> = - _appsList.asSharedFlow() - - fun fetchAppsInfo() { - viewModelScope.launch { - try { - _appsList.emit(getAppsInfoUseCase()) - } catch (exception: HttpException) { - //TODO state - } - } - } -} \ No newline at end of file diff --git a/feature-home/src/main/java/com/vanced/manager/feature/home/ui/HomeFragment.kt b/feature-home/src/main/java/com/vanced/manager/feature/home/ui/HomeFragment.kt deleted file mode 100644 index f6a56720d0..0000000000 --- a/feature-home/src/main/java/com/vanced/manager/feature/home/ui/HomeFragment.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.vanced.manager.feature.home.ui - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.ViewGroup -import com.vanced.manager.core.ui.base.BindingFragment -import com.vanced.manager.feature.home.databinding.FragmentHomeBinding -import com.vanced.manager.feature.home.presentation.HomeViewModel -import com.vanced.manager.feature.home.ui.bind.bindData -import org.koin.android.viewmodel.ext.android.viewModel - -class HomeFragment : BindingFragment() { - - private val viewModel: HomeViewModel by viewModel() - - override fun binding( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ) = FragmentHomeBinding.inflate(inflater, container, false) - - override fun otherSetups() { - bindData(binding, viewModel) - } -} \ No newline at end of file diff --git a/feature-home/src/main/java/com/vanced/manager/feature/home/ui/bind/HomeFragmentBinder.kt b/feature-home/src/main/java/com/vanced/manager/feature/home/ui/bind/HomeFragmentBinder.kt deleted file mode 100644 index e8460c2e1f..0000000000 --- a/feature-home/src/main/java/com/vanced/manager/feature/home/ui/bind/HomeFragmentBinder.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.vanced.manager.feature.home.ui.bind - -import android.util.Log -import androidx.lifecycle.coroutineScope -import com.vanced.manager.feature.home.databinding.FragmentHomeBinding -import com.vanced.manager.feature.home.presentation.HomeViewModel -import com.vanced.manager.feature.home.ui.HomeFragment -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach - -internal fun HomeFragment.bindData( - binding: FragmentHomeBinding, - viewModel: HomeViewModel -) { - viewModel.appsList.onEach { - Log.d("apps", it.toString()) - }.launchIn(viewLifecycleOwner.lifecycle.coroutineScope) -} \ No newline at end of file diff --git a/feature-home/src/main/java/com/vanced/manager/feature/home/ui/uistate/UiState.kt b/feature-home/src/main/java/com/vanced/manager/feature/home/ui/uistate/UiState.kt deleted file mode 100644 index 0b494068ca..0000000000 --- a/feature-home/src/main/java/com/vanced/manager/feature/home/ui/uistate/UiState.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.vanced.manager.feature.home.ui.uistate - -sealed class UiState \ No newline at end of file diff --git a/feature-home/src/main/res/layout/fragment_home.xml b/feature-home/src/main/res/layout/fragment_home.xml deleted file mode 100644 index fb847de6fc..0000000000 --- a/feature-home/src/main/res/layout/fragment_home.xml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/feature-home/src/main/res/values/links.xml b/feature-home/src/main/res/values/links.xml deleted file mode 100644 index 0e85d4bcfa..0000000000 --- a/feature-home/src/main/res/values/links.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - https://discord.gg/TUVd7rd - https://t.me/joinchat/AAAAAEHf-pi4jH1SDlAL4w - https://twitter.com/YTVanced - https://reddit.com/r/vanced - https://vanced.activity - https://brave.com/van874 - \ No newline at end of file diff --git a/feature-home/src/test/java/com/vanced/manager/feature/home/data/datasource/AppInformationDataSourceImplTest.kt b/feature-home/src/test/java/com/vanced/manager/feature/home/data/datasource/AppInformationDataSourceImplTest.kt deleted file mode 100644 index ed7290f2f7..0000000000 --- a/feature-home/src/test/java/com/vanced/manager/feature/home/data/datasource/AppInformationDataSourceImplTest.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.vanced.manager.feature.home.data.datasource - -/* - -internal class AppInformationDataSourceImplTest : ShouldSpec() { - - private val api: GetAppInformationApi = mockk() - - private val dataSource = AppInformationDataSourceImpl(api) - - private val verifiable = VancedAppsDto( - VancedManagerDto("", 1, "", ""), - YouTubeVancedDto("", 1, "", "", listOf(), listOf()), - YouTubeMusicVancedDto("", 1, "", ""), - MicroGDto("", 1, "", "") - ) - - init { // https://kotest.io/styles/ - context("return information") { - should("VancedManagerInfo") { - coEvery { api.getAppInformation() } returns verifiable - dataSource - .getVancedManagerInformation() shouldBe - VancedManagerInfo( - version = "", - versionCode = 1, - baseUrl = "", - changeLog = "" - ) - } - should("YouTubeVancedInfo") { - coEvery { api.getAppInformation() } returns verifiable - dataSource - .getYouTubeVancedInformation() shouldBe - YouTubeVancedInfo( - version = "", - versionCode = 1, - baseUrl = "", - changeLog = "", - themes = listOf(), - langs = listOf() - ) - } - should("YouTubeMusicVancedInfo") { - coEvery { api.getAppInformation() } returns verifiable - dataSource - .getYouTubeMusicVancedInformation() shouldBe - YouTubeMusicVancedInfo( - version = "", - versionCode = 1, - baseUrl = "", - changeLog = "" - ) - } - should("MicroGInfo") { - coEvery { api.getAppInformation() } returns verifiable - dataSource - .getMicroGInformation() shouldBe - MicroGInfo( - version = "", - versionCode = 1, - baseUrl = "", - changeLog = "" - ) - } - } - } -}*/ diff --git a/feature-home/src/test/java/com/vanced/manager/feature/home/data/datasource/PkgInformationDataSourceImplTest.kt b/feature-home/src/test/java/com/vanced/manager/feature/home/data/datasource/PkgInformationDataSourceImplTest.kt deleted file mode 100644 index 7aa955827a..0000000000 --- a/feature-home/src/test/java/com/vanced/manager/feature/home/data/datasource/PkgInformationDataSourceImplTest.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.vanced.manager.feature.home.data.datasource - -/* -internal class PkgInformationDataSourceImplTest : ShouldSpec() { - - private val pkgManager: PkgManager = mockk() - - private val dataSource = PkgInformationDataSourceImpl(pkgManager) - - init { // https://kotest.io/styles/ - should("return version code") { - val testPackageName = "VancedManager" - val expectation = 4545 - coEvery { pkgManager.getVersionCode(testPackageName) } returns expectation - dataSource.getVersionCode(testPackageName) shouldBe expectation - } - should("return version name") { - val testPackageName = "VancedManager" - val expectation = "VancedManagerName" - coEvery { pkgManager.getVersionName(testPackageName) } returns expectation - dataSource.getVersionName(testPackageName) shouldBe expectation - } - } -}*/ \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 2cf4a482b2..fa797e8c60 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. # Default value: -Xmx1024m -XX:MaxPermSize=256m -# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 # # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit @@ -14,5 +14,3 @@ android.enableJetifier=true android.useAndroidX=true kotlin.code.style=official -org.gradle.jvmargs=-Xmx1536M -Dkotlin.daemon.jvm.options\="-Xmx1536M" -org.gradle.parallel=false diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index f6b961fd5a86aa5fbfe90f707c3138408be7c718..e708b1c023ec8b20f512888fe07c5bd3ff77bb8f 100644 GIT binary patch literal 59203 zcma&O1CT9Y(k9%tZQHhO+qUh#ZQHhO+qmuS+qP|E@9xZO?0h@l{(r>DQ>P;GjjD{w zH}lENr;dU&FbEU?00aa80D$0M0RRB{U*7-#kbjS|qAG&4l5%47zyJ#WrfA#1$1Ctx zf&Z_d{GW=lf^w2#qRJ|CvSJUi(^E3iv~=^Z(zH}F)3Z%V3`@+rNB7gTVU{Bb~90p|f+0(v;nz01EG7yDMX9@S~__vVgv%rS$+?IH+oZ03D5zYrv|^ zC1J)SruYHmCki$jLBlTaE5&dFG9-kq3!^i>^UQL`%gn6)jz54$WDmeYdsBE9;PqZ_ zoGd=P4+|(-u4U1dbAVQrFWoNgNd;0nrghPFbQrJctO>nwDdI`Q^i0XJDUYm|T|RWc zZ3^Qgo_Qk$%Fvjj-G}1NB#ZJqIkh;kX%V{THPqOyiq)d)0+(r9o(qKlSp*hmK#iIY zA^)Vr$-Hz<#SF=0@tL@;dCQsm`V9s1vYNq}K1B)!XSK?=I1)tX+bUV52$YQu*0%fnWEukW>mxkz+%3-S!oguE8u#MGzST8_Dy^#U?fA@S#K$S@9msUiX!gd_ow>08w5)nX{-KxqMOo7d?k2&?Vf z&diGDtZr(0cwPe9z9FAUSD9KC)7(n^lMWuayCfxzy8EZsns%OEblHFSzP=cL6}?J| z0U$H!4S_TVjj<`6dy^2j`V`)mC;cB%* z8{>_%E1^FH!*{>4a7*C1v>~1*@TMcLK{7nEQ!_igZC}ikJ$*<$yHy>7)oy79A~#xE zWavoJOIOC$5b6*q*F_qN1>2#MY)AXVyr$6x4b=$x^*aqF*L?vmj>Mgv+|ITnw_BoW zO?jwHvNy^prH{9$rrik1#fhyU^MpFqF2fYEt(;4`Q&XWOGDH8k6M=%@fics4ajI;st# zCU^r1CK&|jzUhRMv;+W~6N;u<;#DI6cCw-otsc@IsN3MoSD^O`eNflIoR~l4*&-%RBYk@gb^|-JXs&~KuSEmMxB}xSb z@K76cXD=Y|=I&SNC2E+>Zg?R6E%DGCH5J1nU!A|@eX9oS(WPaMm==k2s_ueCqdZw| z&hqHp)47`c{BgwgvY2{xz%OIkY1xDwkw!<0veB#yF4ZKJyabhyyVS`gZepcFIk%e2 zTcrmt2@-8`7i-@5Nz>oQWFuMC_KlroCl(PLSodswHqJ3fn<;gxg9=}~3x_L3P`9Sn zChIf}8vCHvTriz~T2~FamRi?rh?>3bX1j}%bLH+uFX+p&+^aXbOK7clZxdU~6Uxgy z8R=obwO4dL%pmVo*Ktf=lH6hnlz_5k3cG;m8lgaPp~?eD!Yn2kf)tU6PF{kLyn|oI@eQ`F z3IF7~Blqg8-uwUuWZScRKn%c2_}dXB6Dx_&xR*n9M9LXasJhtZdr$vBY!rP{c@=)& z#!?L$2UrkvClwQO>U*fSMs67oSj2mxiJ$t;E|>q%Kh_GzzWWO&3;ufU%2z%ucBU8H z3WIwr$n)cfCXR&>tyB7BcSInK>=ByZA%;cVEJhcg<#6N{aZC4>K41XF>ZgjG`z_u& zGY?;Ad?-sgiOnI`oppF1o1Gurqbi*;#x2>+SSV6|1^G@ooVy@fg?wyf@0Y!UZ4!}nGuLeC^l)6pwkh|oRY`s1Pm$>zZ3u-83T|9 zGaKJIV3_x+u1>cRibsaJpJqhcm%?0-L;2 zitBrdRxNmb0OO2J%Y&Ym(6*`_P3&&5Bw157{o7LFguvxC$4&zTy#U=W*l&(Q2MNO} zfaUwYm{XtILD$3864IA_nn34oVa_g^FRuHL5wdUd)+W-p-iWCKe8m_cMHk+=? zeKX)M?Dt(|{r5t7IenkAXo%&EXIb-i^w+0CX0D=xApC=|Xy(`xy+QG^UyFe z+#J6h_&T5i#sV)hj3D4WN%z;2+jJcZxcI3*CHXGmOF3^)JD5j&wfX)e?-|V0GPuA+ zQFot%aEqGNJJHn$!_}#PaAvQ^{3-Ye7b}rWwrUmX53(|~i0v{}G_sI9uDch_brX&6 zWl5Ndj-AYg(W9CGfQf<6!YmY>Ey)+uYd_JNXH=>|`OH-CDCmcH(0%iD_aLlNHKH z7bcW-^5+QV$jK?R*)wZ>r9t}loM@XN&M-Pw=F#xn(;u3!(3SXXY^@=aoj70;_=QE9 zGghsG3ekq#N||u{4We_25U=y#T*S{4I{++Ku)> zQ!DZW;pVcn>b;&g2;YE#+V`v*Bl&Y-i@X6D*OpNA{G@JAXho&aOk(_j^weW{#3X5Y z%$q_wpb07EYPdmyH(1^09i$ca{O<}7) zRWncXdSPgBE%BM#by!E>tdnc$8RwUJg1*x($6$}ae$e9Knj8gvVZe#bLi!<+&BkFj zg@nOpDneyc+hU9P-;jmOSMN|*H#>^Ez#?;%C3hg_65leSUm;iz)UkW)jX#p)e&S&M z1|a?wDzV5NVnlhRBCd_;F87wp>6c<&nkgvC+!@KGiIqWY4l}=&1w7|r6{oBN8xyzh zG$b#2=RJp_iq6)#t5%yLkKx(0@D=C3w+oiXtSuaQ%I1WIb-eiE$d~!)b@|4XLy!CZ z9p=t=%3ad@Ep+<9003D2KZ5VyP~_n$=;~r&YUg5UZ0KVD&tR1DHy9x)qWtKJp#Kq# zP*8p#W(8JJ_*h_3W}FlvRam?<4Z+-H77^$Lvi+#vmhL9J zJ<1SV45xi;SrO2f=-OB(7#iNA5)x1uNC-yNxUw|!00vcW2PufRm>e~toH;M0Q85MQLWd?3O{i8H+5VkR@l9Dg-ma ze2fZ%>G(u5(k9EHj2L6!;(KZ8%8|*-1V|B#EagbF(rc+5iL_5;Eu)L4Z-V;0HfK4d z*{utLse_rvHZeQ>V5H=f78M3Ntg1BPxFCVD{HbNA6?9*^YIq;B-DJd{Ca2L#)qWP? zvX^NhFmX?CTWw&Ns}lgs;r3i+Bq@y}Ul+U%pzOS0Fcv9~aB(0!>GT0)NO?p=25LjN z2bh>6RhgqD7bQj#k-KOm@JLgMa6>%-ok1WpOe)FS^XOU{c?d5shG(lIn3GiVBxmg`u%-j=)^v&pX1JecJics3&jvPI)mDut52? z3jEA)DM%}BYbxxKrizVYwq?(P&19EXlwD9^-6J+4!}9{ywR9Gk42jjAURAF&EO|~N z)?s>$Da@ikI4|^z0e{r`J8zIs>SpM~Vn^{3fArRu;?+43>lD+^XtUcY1HidJwnR6+ z!;oG2=B6Z_=M%*{z-RaHc(n|1RTKQdNjjV!Pn9lFt^4w|AeN06*j}ZyhqZ^!-=cyGP_ShV1rGxkx8t zB;8`h!S{LD%ot``700d0@Grql(DTt4Awgmi+Yr0@#jbe=2#UkK%rv=OLqF)9D7D1j z!~McAwMYkeaL$~kI~90)5vBhBzWYc3Cj1WI0RS`z000R8-@ET0dA~*r(gSiCJmQMN&4%1D zyVNf0?}sBH8zNbBLn>~(W{d3%@kL_eQ6jEcR{l>C|JK z(R-fA!z|TTRG40|zv}7E@PqCAXP3n`;%|SCQ|ZS%ym$I{`}t3KPL&^l5`3>yah4*6 zifO#{VNz3)?ZL$be;NEaAk9b#{tV?V7 zP|wf5YA*1;s<)9A4~l3BHzG&HH`1xNr#%){4xZ!jq%o=7nN*wMuXlFV{HaiQLJ`5G zBhDi#D(m`Q1pLh@Tq+L;OwuC52RdW7b8}~60WCOK5iYMUad9}7aWBuILb({5=z~YF zt?*Jr5NG+WadM{mDL>GyiByCuR)hd zA=HM?J6l1Xv0Dl+LW@w$OTcEoOda^nFCw*Sy^I@$sSuneMl{4ys)|RY#9&NxW4S)9 zq|%83IpslTLoz~&vTo!Ga@?rj_kw{|k{nv+w&Ku?fyk4Ki4I?);M|5Axm)t+BaE)D zm(`AQ#k^DWrjbuXoJf2{Aj^KT zFb1zMSqxq|vceV+Mf-)$oPflsO$@*A0n0Z!R{&(xh8s}=;t(lIy zv$S8x>m;vQNHuRzoaOo?eiWFe{0;$s`Bc+Osz~}Van${u;g(su`3lJ^TEfo~nERfP z)?aFzpDgnLYiERsKPu|0tq4l2wT)Atr6Qb%m-AUn6HnCue*yWICp7TjW$@sO zm5rm4aTcPQ(rfi7a`xP7cKCFrJD}*&_~xgLyr^-bmsL}y;A5P|al8J3WUoBSjqu%v zxC;mK!g(7r6RRJ852Z~feoC&sD3(6}^5-uLK8o)9{8L_%%rItZK9C){UxB|;G>JbP zsRRtS4-3B*5c+K2kvmgZK8472%l>3cntWUOVHxB|{Ay~aOg5RN;{PJgeVD*H%ac+y!h#wi%o2bF2Ca8IyMyH{>4#{E_8u^@+l-+n=V}Sq?$O z{091@v%Bd*3pk0^2UtiF9Z+(a@wy6 zUdw8J*ze$K#=$48IBi1U%;hmhO>lu!uU;+RS}p&6@rQila7WftH->*A4=5W|Fmtze z)7E}jh@cbmr9iup^i%*(uF%LG&!+Fyl@LFA-}Ca#bxRfDJAiR2dt6644TaYw1Ma79 zt8&DYj31j^5WPNf5P&{)J?WlCe@<3u^78wnd(Ja4^a>{^Tw}W>|Cjt^If|7l^l)^Q zbz|7~CF(k_9~n|h;ysZ+jHzkXf(*O*@5m zLzUmbHp=x!Q|!9NVXyipZ3)^GuIG$k;D)EK!a5=8MFLI_lpf`HPKl=-Ww%z8H_0$j ztJ||IfFG1lE9nmQ0+jPQy zCBdKkjArH@K7jVcMNz);Q(Q^R{d5G?-kk;Uu_IXSyWB)~KGIizZL(^&qF;|1PI7!E zTP`%l)gpX|OFn&)M%txpQ2F!hdA~hX1Cm5)IrdljqzRg!f{mN%G~H1&oqe`5eJCIF zHdD7O;AX-{XEV(a`gBFJ9ews#CVS2y!&>Cm_dm3C8*n3MA*e67(WC?uP@8TXuMroq z{#w$%z@CBIkRM7?}Xib+>hRjy?%G!fiw8! z8(gB+8J~KOU}yO7UGm&1g_MDJ$IXS!`+*b*QW2x)9>K~Y*E&bYMnjl6h!{17_8d!%&9D`a7r&LKZjC<&XOvTRaKJ1 zUY@hl5^R&kZl3lU3njk`3dPzxj$2foOL26r(9zsVF3n_F#v)s5vv3@dgs|lP#eylq62{<-vczqP!RpVBTgI>@O6&sU>W|do17+#OzQ7o5A$ICH z?GqwqnK^n2%LR;$^oZM;)+>$X3s2n}2jZ7CdWIW0lnGK-b#EG01)P@aU`pg}th&J-TrU`tIpb5t((0eu|!u zQz+3ZiOQ^?RxxK4;zs=l8q!-n7X{@jSwK(iqNFiRColuEOg}!7cyZi`iBX4g1pNBj zAPzL?P^Ljhn;1$r8?bc=#n|Ed7wB&oHcw()&*k#SS#h}jO?ZB246EGItsz*;^&tzp zu^YJ0=lwsi`eP_pU8}6JA7MS;9pfD;DsSsLo~ogzMNP70@@;Fm8f0^;>$Z>~}GWRw!W5J3tNX*^2+1f3hz{~rIzJo z6W%J(H!g-eI_J1>0juX$X4Cl6i+3wbc~k146UIX&G22}WE>0ga#WLsn9tY(&29zBvH1$`iWtTe zG2jYl@P!P)eb<5DsR72BdI7-zP&cZNI{7q3e@?N8IKc4DE#UVr->|-ryuJXk^u^>4 z$3wE~=q390;XuOQP~TNoDR?#|NSPJ%sTMInA6*rJ%go|=YjGe!B>z6u$IhgQSwoV* zjy3F2#I>uK{42{&IqP59)Y(1*Z>>#W8rCf4_eVsH)`v!P#^;BgzKDR`ARGEZzkNX+ zJUQu=*-ol=Xqqt5=`=pA@BIn@6a9G8C{c&`i^(i+BxQO9?YZ3iu%$$da&Kb?2kCCo zo7t$UpSFWqmydXf@l3bVJ=%K?SSw)|?srhJ-1ZdFu*5QhL$~-IQS!K1s@XzAtv6*Y zl8@(5BlWYLt1yAWy?rMD&bwze8bC3-GfNH=p zynNFCdxyX?K&G(ZZ)afguQ2|r;XoV^=^(;Cku#qYn4Lus`UeKt6rAlFo_rU`|Rq z&G?~iWMBio<78of-2X(ZYHx~=U0Vz4btyXkctMKdc9UM!vYr~B-(>)(Hc|D zMzkN4!PBg%tZoh+=Gba!0++d193gbMk2&krfDgcbx0jI92cq?FFESVg0D$>F+bil} zY~$)|>1HZsX=5sAZ2WgPB5P=8X#TI+NQ(M~GqyVB53c6IdX=k>Wu@A0Svf5#?uHaF zsYn|koIi3$(%GZ2+G+7Fv^lHTb#5b8sAHSTnL^qWZLM<(1|9|QFw9pnRU{svj}_Al zL)b9>fN{QiA($8peNEJyy`(a{&uh-T4_kdZFIVsKKVM(?05}76EEz?#W za^fiZOAd14IJ4zLX-n7Lq0qlQ^lW8Cvz4UKkV9~P}>sq0?xD3vg+$4vLm~C(+ zM{-3Z#qnZ09bJ>}j?6ry^h+@PfaD7*jZxBEY4)UG&daWb??6)TP+|3#Z&?GL?1i+280CFsE|vIXQbm| zM}Pk!U`U5NsNbyKzkrul-DzwB{X?n3E6?TUHr{M&+R*2%yOiXdW-_2Yd6?38M9Vy^ z*lE%gA{wwoSR~vN0=no}tP2Ul5Gk5M(Xq`$nw#ndFk`tcpd5A=Idue`XZ!FS>Q zG^0w#>P4pPG+*NC9gLP4x2m=cKP}YuS!l^?sHSFftZy{4CoQrb_ z^20(NnG`wAhMI=eq)SsIE~&Gp9Ne0nD4%Xiu|0Fj1UFk?6avDqjdXz{O1nKao*46y zT8~iA%Exu=G#{x=KD;_C&M+Zx4+n`sHT>^>=-1YM;H<72k>$py1?F3#T1*ef9mLZw z5naLQr?n7K;2l+{_uIw*_1nsTn~I|kkCgrn;|G~##hM;9l7Jy$yJfmk+&}W@JeKcF zx@@Woiz8qdi|D%aH3XTx5*wDlbs?dC1_nrFpm^QbG@wM=i2?Zg;$VK!c^Dp8<}BTI zyRhAq@#%2pGV49*Y5_mV4+OICP|%I(dQ7x=6Ob}>EjnB_-_18*xrY?b%-yEDT(wrO z9RY2QT0`_OpGfMObKHV;QLVnrK%mc?$WAdIT`kJQT^n%GuzE7|9@k3ci5fYOh(287 zuIbg!GB3xLg$YN=n)^pHGB0jH+_iIiC=nUcD;G6LuJsjn2VI1cyZx=a?ShCsF==QK z;q~*m&}L<-cb+mDDXzvvrRsybcgQ;Vg21P(uLv5I+eGc7o7tc6`;OA9{soHFOz zT~2?>Ts}gprIX$wRBb4yE>ot<8+*Bv`qbSDv*VtRi|cyWS>)Fjs>fkNOH-+PX&4(~ z&)T8Zam2L6puQl?;5zg9h<}k4#|yH9czHw;1jw-pwBM*O2hUR6yvHATrI%^mvs9q_ z&ccT0>f#eDG<^WG^q@oVqlJrhxH)dcq2cty@l3~|5#UDdExyXUmLQ}f4#;6fI{f^t zDCsgIJ~0`af%YR%Ma5VQq-p21k`vaBu6WE?66+5=XUd%Ay%D$irN>5LhluRWt7 zov-=f>QbMk*G##&DTQyou$s7UqjjW@k6=!I@!k+S{pP8R(2=e@io;N8E`EOB;OGoI zw6Q+{X1_I{OO0HPpBz!X!@`5YQ2)t{+!?M_iH25X(d~-Zx~cXnS9z>u?+If|iNJbx zyFU2d1!ITX64D|lE0Z{dLRqL1Ajj=CCMfC4lD3&mYR_R_VZ>_7_~|<^o*%_&jevU+ zQ4|qzci=0}Jydw|LXLCrOl1_P6Xf@c0$ieK2^7@A9UbF{@V_0p%lqW|L?5k>bVM8|p5v&2g;~r>B8uo<4N+`B zH{J)h;SYiIVx@#jI&p-v3dwL5QNV1oxPr8J%ooezTnLW>i*3Isb49%5i!&ac_dEXv zvXmVUck^QHmyrF8>CGXijC_R-y(Qr{3Zt~EmW)-nC!tiH`wlw5D*W7Pip;T?&j%kX z6DkZX4&}iw>hE(boLyjOoupf6JpvBG8}jIh!!VhnD0>}KSMMo{1#uU6kiFcA04~|7 zVO8eI&x1`g4CZ<2cYUI(n#wz2MtVFHx47yE5eL~8bot~>EHbevSt}LLMQX?odD{Ux zJMnam{d)W4da{l7&y-JrgiU~qY3$~}_F#G7|MxT)e;G{U`In&?`j<5D->}cb{}{T(4DF0BOk-=1195KB-E*o@c?`>y#4=dMtYtSY=&L{!TAjFVcq0y@AH`vH! z$41+u!Ld&}F^COPgL(EE{0X7LY&%D7-(?!kjFF7=qw<;`V{nwWBq<)1QiGJgUc^Vz ztMUlq1bZqKn17|6x6iAHbWc~l1HcmAxr%$Puv!znW)!JiukwIrqQ00|H$Z)OmGG@= zv%A8*4cq}(?qn4rN6o`$Y))(MyXr8R<2S^J+v(wmFmtac!%VOfN?&(8Nr!T@kV`N; z*Q33V3t`^rN&aBiHet)18wy{*wi1=W!B%B-Q6}SCrUl$~Hl{@!95ydml@FK8P=u4s z4e*7gV2s=YxEvskw2Ju!2%{8h01rx-3`NCPc(O zH&J0VH5etNB2KY6k4R@2Wvl^Ck$MoR3=)|SEclT2ccJ!RI9Nuter7u9@;sWf-%um;GfI!=eEIQ2l2p_YWUd{|6EG ze{yO6;lMc>;2tPrsNdi@&1K6(1;|$xe8vLgiouj%QD%gYk`4p{Ktv9|j+!OF-P?@p z;}SV|oIK)iwlBs+`ROXkhd&NK zzo__r!B>tOXpBJMDcv!Mq54P+n4(@dijL^EpO1wdg~q+!DT3lB<>9AANSe!T1XgC=J^)IP0XEZ()_vpu!!3HQyJhwh?r`Ae%Yr~b% zO*NY9t9#qWa@GCPYOF9aron7thfWT`eujS4`t2uG6)~JRTI;f(ZuoRQwjZjp5Pg34 z)rp$)Kr?R+KdJ;IO;pM{$6|2y=k_siqvp%)2||cHTe|b5Ht8&A{wazGNca zX$Ol?H)E_R@SDi~4{d-|8nGFhZPW;Cts1;08TwUvLLv&_2$O6Vt=M)X;g%HUr$&06 zISZb(6)Q3%?;3r~*3~USIg=HcJhFtHhIV(siOwV&QkQe#J%H9&E21!C*d@ln3E@J* zVqRO^<)V^ky-R|%{(9`l-(JXq9J)1r$`uQ8a}$vr9E^nNiI*thK8=&UZ0dsFN_eSl z(q~lnD?EymWLsNa3|1{CRPW60>DSkY9YQ;$4o3W7Ms&@&lv9eH!tk~N&dhqX&>K@} zi1g~GqglxkZ5pEFkllJ)Ta1I^c&Bt6#r(QLQ02yHTaJB~- zCcE=5tmi`UA>@P=1LBfBiqk)HB4t8D?02;9eXj~kVPwv?m{5&!&TFYhu>3=_ zsGmYZ^mo*-j69-42y&Jj0cBLLEulNRZ9vXE)8~mt9C#;tZs;=#M=1*hebkS;7(aGf zcs7zH(I8Eui9UU4L--))yy`&d&$In&VA2?DAEss4LAPCLd>-$i?lpXvn!gu^JJ$(DoUlc6wE98VLZ*z`QGQov5l4Fm_h?V-;mHLYDVOwKz7>e4+%AzeO>P6v}ndPW| zM>m#6Tnp7K?0mbK=>gV}=@k*0Mr_PVAgGMu$j+pWxzq4MAa&jpCDU&-5eH27Iz>m^ zax1?*HhG%pJ((tkR(V(O(L%7v7L%!_X->IjS3H5kuXQT2!ow(;%FDE>16&3r){!ex zhf==oJ!}YU89C9@mfDq!P3S4yx$aGB?rbtVH?sHpg?J5C->!_FHM%Hl3#D4eplxzQ zRA+<@LD%LKSkTk2NyWCg7u=$%F#;SIL44~S_OGR}JqX}X+=bc@swpiClB`Zbz|f!4 z7Ysah7OkR8liXfI`}IIwtEoL}(URrGe;IM8%{>b1SsqXh)~w}P>yiFRaE>}rEnNkT z!HXZUtxUp1NmFm)Dm@-{FI^aRQqpSkz}ZSyKR%Y}YHNzBk)ZIp} zMtS=aMvkgWKm9&oTcU0?S|L~CDqA+sHpOxwnswF-fEG)cXCzUR?ps@tZa$=O)=L+5 zf%m58cq8g_o}3?Bhh+c!w4(7AjxwQ3>WnVi<{{38g7yFboo>q|+7qs<$8CPXUFAN< zG&}BHbbyQ5n|qqSr?U~GY{@GJ{(Jny{bMaOG{|IkUj7tj^9pa9|FB_<+KHLxSxR;@ zHpS$4V)PP+tx}22fWx(Ku9y+}Ap;VZqD0AZW4gCDTPCG=zgJmF{|x;(rvdM|2|9a}cex6xrMkERnkE;}jvU-kmzd%_J50$M`lIPCKf+^*zL=@LW`1SaEc%=m zQ+lT06Gw+wVwvQ9fZ~#qd430v2HndFsBa9WjD0P}K(rZYdAt^5WQIvb%D^Q|pkVE^ zte$&#~zmULFACGfS#g=2OLOnIf2Of-k!(BIHjs77nr!5Q1*I9 z1%?=~#Oss!rV~?-6Gm~BWJiA4mJ5TY&iPm_$)H1_rTltuU1F3I(qTQ^U$S>%$l z)Wx1}R?ij0idp@8w-p!Oz{&*W;v*IA;JFHA9%nUvVDy7Q8woheC#|8QuDZb-L_5@R zOqHwrh|mVL9b=+$nJxM`3eE{O$sCt$UK^2@L$R(r^-_+z?lOo+me-VW=Zw z-Bn>$4ovfWd%SPY`ab-u9{INc*k2h+yH%toDHIyqQ zO68=u`N}RIIs7lsn1D){)~%>ByF<>i@qFb<-axvu(Z+6t7v<^z&gm9McRB~BIaDn$ z#xSGT!rzgad8o>~kyj#h1?7g96tOcCJniQ+*#=b7wPio>|6a1Z?_(TS{)KrPe}(8j z!#&A=k(&Pj^F;r)CI=Z{LVu>uj!_W1q4b`N1}E(i%;BWjbEcnD=mv$FL$l?zS6bW!{$7j1GR5ocn94P2u{ z70tAAcpqtQo<@cXw~@i-@6B23;317|l~S>CB?hR5qJ%J3EFgyBdJd^fHZu7AzHF(BQ!tyAz^L0`X z23S4Fe{2X$W0$zu9gm%rg~A>ijaE#GlYlrF9$ds^QtaszE#4M(OLVP2O-;XdT(XIC zatwzF*)1c+t~c{L=fMG8Z=k5lv>U0;C{caN1NItnuSMp)6G3mbahu>E#sj&oy94KC zpH}8oEw{G@N3pvHhp{^-YaZeH;K+T_1AUv;IKD<=mv^&Ueegrb!yf`4VlRl$M?wsl zZyFol(2|_QM`e_2lYSABpKR{{NlxlDSYQNkS;J66aT#MSiTx~;tUmvs-b*CrR4w=f z8+0;*th6kfZ3|5!Icx3RV11sp=?`0Jy3Fs0N4GZQMN=8HmT6%x9@{Dza)k}UwL6JT zHRDh;%!XwXr6yuuy`4;Xsn0zlR$k%r%9abS1;_v?`HX_hI|+EibVnlyE@3aL5vhQq zlIG?tN^w@0(v9M*&L+{_+RQZw=o|&BRPGB>e5=ys7H`nc8nx)|-g;s7mRc7hg{GJC zAe^vCIJhajmm7C6g! zL&!WAQ~5d_5)00?w_*|*H>3$loHrvFbitw#WvLB!JASO?#5Ig5$Ys10n>e4|3d;tS zELJ0|R4n3Az(Fl3-r^QiV_C;)lQ1_CW{5bKS15U|E9?ZgLec@%kXr84>5jV2a5v=w z?pB1GPdxD$IQL4)G||B_lI+A=08MUFFR4MxfGOu07vfIm+j=z9tp~5i_6jb`tR>qV z$#`=BQ*jpCjm$F0+F)L%xRlnS%#&gro6PiRfu^l!EVan|r3y}AHJQOORGx4~ z&<)3=K-tx518DZyp%|!EqpU!+X3Et7n2AaC5(AtrkW>_57i}$eqs$rupubg0a1+WO zGHZKLN2L0D;ab%{_S1Plm|hx8R?O14*w*f&2&bB050n!R2by zw!@XOQx$SqZ5I<(Qu$V6g>o#A!JVwErWv#(Pjx=KeS0@hxr4?13zj#oWwPS(7Ro|v z>Mp@Kmxo79q|}!5qtX2-O@U&&@6s~!I&)1WQIl?lTnh6UdKT_1R640S4~f=_xoN3- zI+O)$R@RjV$F=>Ti7BlnG1-cFKCC(t|Qjm{SalS~V-tX#+2ekRhwmN zZr`8{QF6y~Z!D|{=1*2D-JUa<(1Z=;!Ei!KiRNH?o{p5o3crFF=_pX9O-YyJchr$~ zRC`+G+8kx~fD2k*ZIiiIGR<8r&M@3H?%JVOfE>)})7ScOd&?OjgAGT@WVNSCZ8N(p zuQG~76GE3%(%h1*vUXg$vH{ua0b`sQ4f0*y=u~lgyb^!#CcPJa2mkSEHGLsnO^kb$ zru5_l#nu=Y{rSMWiYx?nO{8I!gH+?wEj~UM?IrG}E|bRIBUM>UlY<`T1EHpRr36vv zBi&dG8oxS|J$!zoaq{+JpJy+O^W(nt*|#g32bd&K^w-t>!Vu9N!k9eA8r!Xc{utY> zg9aZ(D2E0gL#W0MdjwES-7~Wa8iubPrd?8-$C4BP?*wok&O8+ykOx{P=Izx+G~hM8 z*9?BYz!T8~dzcZr#ux8kS7u7r@A#DogBH8km8Ry4slyie^n|GrTbO|cLhpqgMdsjX zJ_LdmM#I&4LqqsOUIXK8gW;V0B(7^$y#h3h>J0k^WJfAMeYek%Y-Dcb_+0zPJez!GM zAmJ1u;*rK=FNM0Nf}Y!!P9c4)HIkMnq^b;JFd!S3?_Qi2G#LIQ)TF|iHl~WKK6JmK zbv7rPE6VkYr_%_BT}CK8h=?%pk@3cz(UrZ{@h40%XgThP*-Oeo`T0eq9 zA8BnWZKzCy5e&&_GEsU4*;_k}(8l_&al5K-V*BFM=O~;MgRkYsOs%9eOY6s6AtE*<7GQAR2ulC3RAJrG_P1iQK5Z~&B z&f8X<>yJV6)oDGIlS$Y*D^Rj(cszTy5c81a5IwBr`BtnC6_e`ArI8CaTX_%rx7;cn zR-0?J_LFg*?(#n~G8cXut(1nVF0Oka$A$1FGcERU<^ggx;p@CZc?3UB41RY+wLS`LWFNSs~YP zuw1@DNN3lTd|jDL7gjBsd9}wIw}4xT2+8dBQzI00m<@?c2L%>}QLfK5%r!a-iII`p zX@`VEUH)uj^$;7jVUYdADQ2k*!1O3WdfgF?OMtUXNpQ1}QINamBTKDuv19^{$`8A1 zeq%q*O0mi@(%sZU>Xdb0Ru96CFqk9-L3pzLVsMQ`Xpa~N6CR{9Rm2)A|CI21L(%GW zh&)Y$BNHa=FD+=mBw3{qTgw)j0b!Eahs!rZnpu)z!!E$*eXE~##yaXz`KE5(nQM`s zD!$vW9XH)iMxu9R>r$VlLk9oIR%HxpUiW=BK@4U)|1WNQ=mz9a z^!KkO=>GaJ!GBXm{KJj^;kh-MkUlEQ%lza`-G&}C5y1>La1sR6hT=d*NeCnuK%_LV zOXt$}iP6(YJKc9j-Fxq~*ItVUqljQ8?oaysB-EYtFQp9oxZ|5m0^Hq(qV!S+hq#g( z?|i*H2MIr^Kxgz+3vIljQ*Feejy6S4v~jKEPTF~Qhq!(ms5>NGtRgO5vfPPc4Z^AM zTj!`5xEreIN)vaNxa|q6qWdg>+T`Ol0Uz)ckXBXEGvPNEL3R8hB3=C5`@=SYgAju1 z!)UBr{2~=~xa{b8>x2@C7weRAEuatC)3pkRhT#pMPTpSbA|tan%U7NGMvzmF?c!V8 z=pEWxbdXbTAGtWTyI?Fml%lEr-^AE}w#l(<7OIw;ctw}imYax&vR4UYNJZK6P7ZOd zP87XfhnUHxCUHhM@b*NbTi#(-8|wcv%3BGNs#zRCVV(W?1Qj6^PPQa<{yaBwZ`+<`w|;rqUY_C z&AeyKwwf*q#OW-F()lir=T^<^wjK65Lif$puuU5+tk$;e_EJ;Lu+pH>=-8=PDhkBg z8cWt%@$Sc#C6F$Vd+0507;{OOyT7Hs%nKS88q-W!$f~9*WGBpHGgNp}=C*7!RiZ5s zn1L_DbKF@B8kwhDiLKRB@lsXVVLK|ph=w%_`#owlf@s@V(pa`GY$8h%;-#h@TsO|Y8V=n@*!Rog7<7Cid%apR|x zOjhHCyfbIt%+*PCveTEcuiDi%Wx;O;+K=W?OFUV%)%~6;gl?<0%)?snDDqIvkHF{ zyI02)+lI9ov42^hL>ZRrh*HhjF9B$A@=H94iaBESBF=eC_KT$8A@uB^6$~o?3Wm5t1OIaqF^~><2?4e3c&)@wKn9bD? zoeCs;H>b8DL^F&>Xw-xjZEUFFTv>JD^O#1E#)CMBaG4DX9bD(Wtc8Rzq}9soQ8`jf zeSnHOL}<+WVSKp4kkq&?SbETjq6yr@4%SAqOG=9E(3YeLG9dtV+8vmzq+6PFPk{L; z(&d++iu=^F%b+ea$i2UeTC{R*0Isk;vFK!no<;L+(`y`3&H-~VTdKROkdyowo1iqR zbVW(3`+(PQ2>TKY>N!jGmGo7oeoB8O|P_!Ic@ zZ^;3dnuXo;WJ?S+)%P>{Hcg!Jz#2SI(s&dY4QAy_vRlmOh)QHvs_7c&zkJCmJGVvV zX;Mtb>QE+xp`KyciG$Cn*0?AK%-a|=o!+7x&&yzHQOS>8=B*R=niSnta^Pxp1`=md z#;$pS$4WCT?mbiCYU?FcHGZ#)kHVJTTBt^%XE(Q};aaO=Zik0UgLcc0I(tUpt(>|& zcxB_|fxCF7>&~5eJ=Dpn&5Aj{A^cV^^}(7w#p;HG&Q)EaN~~EqrE1qKrMAc&WXIE;>@<&)5;gD2?={Xf@Mvn@OJKw=8Mgn z!JUFMwD+s==JpjhroT&d{$kQAy%+d`a*XxDEVxy3`NHzmITrE`o!;5ClXNPb4t*8P zzAivdr{j_v!=9!^?T3y?gzmqDWX6mkzhIzJ-3S{T5bcCFMr&RPDryMcdwbBuZbsgN zGrp@^i?rcfN7v0NKGzDPGE#4yszxu=I_`MI%Z|10nFjU-UjQXXA?k8Pk|OE<(?ae) zE%vG#eZAlj*E7_3dx#Zz4kMLj>H^;}33UAankJiDy5ZvEhrjr`!9eMD8COp}U*hP+ zF}KIYx@pkccIgyxFm#LNw~G&`;o&5)2`5aogs`1~7cMZQ7zj!%L4E`2yzlQN6REX20&O<9 zKV6fyr)TScJPPzNTC2gL+0x#=u>(({{D7j)c-%tvqls3#Y?Z1m zV5WUE)zdJ{$p>yX;^P!UcXP?UD~YM;IRa#Rs5~l+*$&nO(;Ers`G=0D!twR(0GF@c zHl9E5DQI}Oz74n zfKP>&$q0($T4y$6w(p=ERAFh+>n%iaeRA%!T%<^+pg?M)@ucY<&59$x9M#n+V&>}=nO9wCV{O~lg&v#+jcUj(tQ z`0u1YH)-`U$15a{pBkGyPL0THv1P|4e@pf@3IBZS4dVJPo#H>pWq%Lr0YS-SeWash z8R7=jb28KPMI|_lo#GEO|5B?N_e``H*23{~a!AmUJ+fb4HX-%QI@lSEUxKlGV7z7Q zSKw@-TR>@1RL%w{x}dW#k1NgW+q4yt2Xf1J62Bx*O^WG8OJ|FqI4&@d3_o8Id@*)4 zYrk=>@!wv~mh7YWv*bZhxqSmFh2Xq)o=m;%n$I?GSz49l1$xRpPu_^N(vZ>*>Z<04 z2+rP70oM=NDysd!@fQdM2OcyT?3T^Eb@lIC-UG=Bw{BjQ&P`KCv$AcJ;?`vdZ4){d z&gkoUK{$!$$K`3*O-jyM1~p-7T*qb)Ys>Myt^;#1&a%O@x8A+E>! zY8=eD`ZG)LVagDLBeHg>=atOG?Kr%h4B%E6m@J^C+U|y)XX@f z8oyJDW|9g=<#f<{JRr{y#~euMnv)`7j=%cHWLc}ngjq~7k**6%4u>Px&W%4D94(r* z+akunK}O0DC2A%Xo9jyF;DobX?!1I(7%}@7F>i%&nk*LMO)bMGg2N+1iqtg+r(70q zF5{Msgsm5GS7DT`kBsjMvOrkx&|EU!{{~gL4d2MWrAT=KBQ-^zQCUq{5PD1orxlIL zq;CvlWx#f1NWvh`hg011I%?T_s!e38l*lWVt|~z-PO4~~1g)SrJ|>*tXh=QfXT)%( z+ex+inPvD&O4Ur;JGz>$sUOnWdpSLcm1X%aQDw4{dB!cnj`^muI$CJ2%p&-kULVCE z>$eMR36kN$wCPR+OFDM3-U(VOrp9k3)lI&YVFqd;Kpz~K)@Fa&FRw}L(SoD z9B4a+hQzZT-BnVltst&=kq6Y(f^S4hIGNKYBgMxGJ^;2yrO}P3;r)(-I-CZ)26Y6? z&rzHI_1GCvGkgy-t1E;r^3Le30|%$ebDRu2+gdLG)r=A~Qz`}~&L@aGJ{}vVs_GE* zVUjFnzHiXfKQbpv&bR&}l2bzIjAooB)=-XNcYmrGmBh(&iu@o!^hn0^#}m2yZZUK8 zufVm7Gq0y`Mj;9b>`c?&PZkU0j4>IL=UL&-Lp3j&47B5pAW4JceG{!XCA)kT<%2nqCxj<)uy6XR_uws~>_MEKPOpAQ!H zkn>FKh)<9DwwS*|Y(q?$^N!6(51O0 z^JM~Ax{AI1Oj$fs-S5d4T7Z_i1?{%0SsIuQ&r8#(JA=2iLcTN+?>wOL532%&dMYkT z*T5xepC+V6zxhS@vNbMoi|i)=rpli@R9~P!39tWbSSb904ekv7D#quKbgFEMTb48P zuq(VJ+&L8aWU(_FCD$3^uD!YM%O^K(dvy~Wm2hUuh6bD|#(I39Xt>N1Y{ZqXL`Fg6 zKQ?T2htHN!(Bx;tV2bfTtIj7e)liN-29s1kew>v(D^@)#v;}C4-G=7x#;-dM4yRWm zyY`cS21ulzMK{PoaQ6xChEZ}o_#}X-o}<&0)$1#3we?+QeLt;aVCjeA)hn!}UaKt< zat1fHEx13y-rXNMvpUUmCVzocPmN~-Y4(YJvQ#db)4|%B!rBsgAe+*yor~}FrNH08 z3V!97S}D7d$zbSD{$z;@IYMxM6aHdypIuS*pr_U6;#Y!_?0i|&yU*@16l z*dcMqDQgfNBf}?quiu4e>H)yTVfsp#f+Du0@=Kc41QockXkCkvu>FBd6Q+@FL!(Yx z2`YuX#eMEiLEDhp+9uFqME_E^faV&~9qjBHJkIp~%$x^bN=N)K@kvSVEMdDuzA0sn z88CBG?`RX1@#hQNd`o^V{37)!w|nA)QfiYBE^m=yQKv-fQF+UCMcuEe1d4BH7$?>b zJl-r9@0^Ie=)guO1vOd=i$_4sz>y3x^R7n4ED!5oXL3@5**h(xr%Hv)_gILarO46q+MaDOF%ChaymKoI6JU5Pg;7#2n9-18|S1;AK+ zgsn6;k6-%!QD>D?cFy}8F;r@z8H9xN1jsOBw2vQONVqBVEbkiNUqgw~*!^##ht>w0 zUOykwH=$LwX2j&nLy=@{hr)2O&-wm-NyjW7n~Zs9UlH;P7iP3 zI}S(r0YFVYacnKH(+{*)Tbw)@;6>%=&Th=+Z6NHo_tR|JCI8TJiXv2N7ei7M^Q+RM z?9o`meH$5Yi;@9XaNR#jIK^&{N|DYNNbtdb)XW1Lv2k{E>;?F`#Pq|&_;gm~&~Zc9 zf+6ZE%{x4|{YdtE?a^gKyzr}dA>OxQv+pq|@IXL%WS0CiX!V zm$fCePA%lU{%pTKD7|5NJHeXg=I0jL@$tOF@K*MI$)f?om)D63K*M|r`gb9edD1~Y zc|w7N)Y%do7=0{RC|AziW7#am$)9jciRJ?IWl9PE{G3U+$%FcyKs_0Cgq`=K3@ttV z9g;M!3z~f_?P%y3-ph%vBMeS@p7P&Ea8M@97+%XEj*(1E6vHj==d zjsoviB>j^$_^OI_DEPvFkVo(BGRo%cJeD){6Uckei=~1}>sp299|IRjhXe)%?uP0I zF5+>?0#Ye}T^Y$u_rc4=lPcq4K^D(TZG-w30-YiEM=dcK+4#o*>lJ8&JLi+3UcpZk z!^?95S^C0ja^jwP`|{<+3cBVog$(mRdQmadS+Vh~z zS@|P}=|z3P6uS+&@QsMp0no9Od&27O&14zHXGAOEy zh~OKpymK5C%;LLb467@KgIiVwYbYd6wFxI{0-~MOGfTq$nBTB!{SrWmL9Hs}C&l&l#m?s*{tA?BHS4mVKHAVMqm63H<|c5n0~k)-kbg zXidai&9ZUy0~WFYYKT;oe~rytRk?)r8bptITsWj(@HLI;@=v5|XUnSls7$uaxFRL+ zRVMGuL3w}NbV1`^=Pw*0?>bm8+xfeY(1PikW*PB>>Tq(FR`91N0c2&>lL2sZo5=VD zQY{>7dh_TX98L2)n{2OV=T10~*YzX27i2Q7W86M4$?gZIXZaBq#sA*{PH8){|GUi;oM>e?ua7eF4WFuFYZSG| zze?srg|5Ti8Og{O zeFxuw9!U+zhyk?@w zjsA6(oKD=Ka;A>Ca)oPORxK+kxH#O@zhC!!XS4@=swnuMk>t+JmLmFiE^1aX3f<)D@`%K0FGK^gg1a1j>zi z2KhV>sjU7AX3F$SEqrXSC}fRx64GDoc%!u2Yag68Lw@w9v;xOONf@o)Lc|Uh3<21ctTYu-mFZuHk*+R{GjXHIGq3p)tFtQp%TYqD=j1&y)>@zxoxUJ!G@ zgI0XKmP6MNzw>nRxK$-Gbzs}dyfFzt>#5;f6oR27ql!%+{tr+(`(>%51|k`ML} zY4eE)Lxq|JMas(;JibNQds1bUB&r}ydMQXBY4x(^&fY_&LlQC)3hylc$~8&~|06-D z#T+%66rYbHX%^KuqJED_wuGB+=h`nWA!>1n0)3wZrBG3%`b^Ozv6__dNa@%V14|!D zQ?o$z5u0^8`giv%qE!BzZ!3j;BlDlJDk)h@9{nSQeEk!z9RGW) z${RSF3phEM*ce*>Xdp}585vj$|40=&S{S-GTiE?Op*vY&Lvr9}BO$XWy80IF+6@%n z5*2ueT_g@ofP#u5pxb7n*fv^Xtt7&?SRc{*2Ka-*!BuOpf}neHGCiHy$@Ka1^Dint z;DkmIL$-e)rj4o2WQV%Gy;Xg(_Bh#qeOsTM2f@KEe~4kJ8kNLQ+;(!j^bgJMcNhvklP5Z6I+9Fq@c&D~8Fb-4rmDT!MB5QC{Dsb;BharP*O;SF4& zc$wj-7Oep7#$WZN!1nznc@Vb<_Dn%ga-O#J(l=OGB`dy=Sy&$(5-n3zzu%d7E#^8`T@}V+5B;PP8J14#4cCPw-SQTdGa2gWL0*zKM z#DfSXs_iWOMt)0*+Y>Lkd=LlyoHjublNLefhKBv@JoC>P7N1_#> zv=mLWe96%EY;!ZGSQDbZWb#;tzqAGgx~uk+-$+2_8U`!ypbwXl z^2E-FkM1?lY@yt8=J3%QK+xaZ6ok=-y%=KXCD^0r!5vUneW>95PzCkOPO*t}p$;-> ze5j-BLT_;)cZQzR2CEsm@rU7GZfFtdp*a|g4wDr%8?2QkIGasRfDWT-Dvy*U{?IHT z*}wGnzdlSptl#ZF^sf)KT|BJs&kLG91^A6ls{CzFprZ6-Y!V0Xysh%9p%iMd7HLsS zN+^Un$tDV)T@i!v?3o0Fsx2qI(AX_$dDkBzQ@fRM%n zRXk6hb9Py#JXUs+7)w@eo;g%QQ95Yq!K_d=z{0dGS+pToEI6=Bo8+{k$7&Z zo4>PH(`ce8E-Ps&uv`NQ;U$%t;w~|@E3WVOCi~R4oj5wP?%<*1C%}Jq%a^q~T7u>K zML5AKfQDv6>PuT`{SrKHRAF+^&edg6+5R_#H?Lz3iGoWo#PCEd0DS;)2U({{X#zU^ zw_xv{4x7|t!S)>44J;KfA|DC?;uQ($l+5Vp7oeqf7{GBF9356nx|&B~gs+@N^gSdd zvb*>&W)|u#F{Z_b`f#GVtQ`pYv3#||N{xj1NgB<#=Odt6{eB%#9RLt5v zIi|0u70`#ai}9fJjKv7dE!9ZrOIX!3{$z_K5FBd-Kp-&e4(J$LD-)NMTp^_pB`RT; zftVVlK2g@+1Ahv2$D){@Y#cL#dUj9*&%#6 zd2m9{1NYp>)6=oAvqdCn5#cx{AJ%S8skUgMglu2*IAtd+z1>B&`MuEAS(D(<6X#Lj z?f4CFx$)M&$=7*>9v1ER4b6!SIz-m0e{o0BfkySREchp?WdVPpQCh!q$t>?rL!&Jg zd#heM;&~A}VEm8Dvy&P|J*eAV&w!&Nx6HFV&B8jJFVTmgLaswn!cx$&%JbTsloz!3 zMEz1d`k==`Ueub_JAy_&`!ogbwx27^ZXgFNAbx=g_I~5nO^r)}&myw~+yY*cJl4$I znNJ32M&K=0(2Dj_>@39`3=FX!v3nZHno_@q^!y}%(yw0PqOo=);6Y@&ylVe>nMOZ~ zd>j#QQSBn3oaWd;qy$&5(5H$Ayi)0haAYO6TH>FR?rhqHmNOO+(})NB zLI@B@v0)eq!ug`>G<@htRlp3n!EpU|n+G+AvXFrWSUsLMBfL*ZB`CRsIVHNTR&b?K zxBgsN0BjfB>UVcJ|x%=-zb%OV7lmZc& zxiupadZVF7)6QuhoY;;FK2b*qL0J-Rn-8!X4ZY$-ZSUXV5DFd7`T41c(#lAeLMoeT z4%g655v@7AqT!i@)Edt5JMbN(=Q-6{=L4iG8RA%}w;&pKmtWvI4?G9pVRp|RTw`g0 zD5c12B&A2&P6Ng~8WM2eIW=wxd?r7A*N+&!Be7PX3s|7~z=APxm=A?5 zt>xB4WG|*Td@VX{Rs)PV0|yK`oI3^xn(4c_j&vgxk_Y3o(-`_5o`V zRTghg6%l@(qodXN;dB#+OKJEEvhfcnc#BeO2|E(5df-!fKDZ!%9!^BJ_4)9P+9Dq5 zK1=(v?KmIp34r?z{NEWnLB3Px{XYwy-akun4F7xTRr2^zeYW{gcK9)>aJDdU5;w5@ zak=<+-PLH-|04pelTb%ULpuuuJC7DgyT@D|p{!V!0v3KpDnRjANN12q6SUR3mb9<- z>2r~IApQGhstZ!3*?5V z8#)hJ0TdZg0M-BK#nGFP>$i=qk82DO z7h;Ft!D5E15OgW)&%lej*?^1~2=*Z5$2VX>V{x8SC+{i10BbtUk9@I#Vi&hX)q
Q!LwySI{Bnv%Sm)yh{^sSVJ8&h_D-BJ_YZe5eCaAWU9b$O2c z$T|{vWVRtOL!xC0DTc(Qbe`ItNtt5hr<)VijD0{U;T#bUEp381_y`%ZIav?kuYG{iyYdEBPW=*xNSc;Rlt6~F4M`5G+VtOjc z*0qGzCb@gME5udTjJA-9O<&TWd~}ysBd(eVT1-H82-doyH9RST)|+Pb{o*;$j9Tjs zhU!IlsPsj8=(x3bAKJTopW3^6AKROHR^7wZ185wJGVhA~hEc|LP;k7NEz-@4p5o}F z`AD6naG3(n=NF9HTH81=F+Q|JOz$7wm9I<+#BSmB@o_cLt2GkW9|?7mM;r!JZp89l zbo!Hp8=n!XH1{GwaDU+k)pGp`C|cXkCU5%vcH)+v@0eK>%7gWxmuMu9YLlChA|_D@ zi#5zovN_!a-0?~pUV-Rj*1P)KwdU-LguR>YM&*Nen+ln8Q$?WFCJg%DY%K}2!!1FE zDv-A%Cbwo^p(lzac&_TZ-l#9kq`mhLcY3h9ZTUVCM(Ad&=EriQY5{jJv<5K&g|*Lk zgV%ILnf1%8V2B0E&;Sp4sYbYOvvMebLwYwzkRQ#F8GpTQq#uv=J`uaSJ34OWITeSGo6+-8Xw znCk*n{kdDEi)Hi&u^)~cs@iyCkFWB2SWZU|Uc%^43ZIZQ-vWNExCCtDWjqHs;;tWf$v{}0{p0Rvxkq``)*>+Akq%|Na zA`@~-Vfe|+(AIlqru+7Ceh4nsVmO9p9jc8}HX^W&ViBDXT+uXbT#R#idPn&L>+#b6 zflC-4C5-X;kUnR~L>PSLh*gvL68}RBsu#2l`s_9KjUWRhiqF`j)`y`2`YU(>3bdBj z?>iyjEhe-~$^I5!nn%B6Wh+I`FvLNvauve~eX<+Ipl&04 zT}};W&1a3%W?dJ2=N#0t?e+aK+%t}5q%jSLvp3jZ%?&F}nOOWr>+{GFIa%wO_2`et z=JzoRR~}iKuuR+azPI8;Gf9)z3kyA4EIOSl!sRR$DlW}0>&?GbgPojmjmnln;cTqCt=ADbE zZ8GAnoM+S1(5$i8^O4t`ue;vO4i}z0wz-QEIVe5_u03;}-!G1NyY8;h^}y;tzY}i5 zqQr#Ur3Fy8sSa$Q0ys+f`!`+>9WbvU_I`Sj;$4{S>O3?#inLHCrtLy~!s#WXV=oVP zeE93*Nc`PBi4q@%Ao$x4lw9vLHM!6mn3-b_cebF|n-2vt-zYVF_&sDE--J-P;2WHo z+@n2areE0o$LjvjlV2X7ZU@j+`{*8zq`JR3gKF#EW|#+{nMyo-a>nFFTg&vhyT=b} zDa8+v0(Dgx0yRL@ZXOYIlVSZ0|MFizy0VPW8;AfA5|pe!#j zX}Py^8fl5SyS4g1WSKKtnyP+_PoOwMMwu`(i@Z)diJp~U54*-miOchy7Z35eL>^M z4p<-aIxH4VUZgS783@H%M7P9hX>t{|RU7$n4T(brCG#h9e9p! z+o`i;EGGq3&pF;~5V~eBD}lC)>if$w%Vf}AFxGqO88|ApfHf&Bvu+xdG)@vuF}Yvk z)o;~k-%+0K0g+L`Wala!$=ZV|z$e%>f0%XoLib%)!R^RoS+{!#X?h-6uu zF&&KxORdZU&EwQFITIRLo(7TA3W}y6X{?Y%y2j0It!ekU#<)$qghZtpcS>L3uh`Uj z7GY;6f$9qKynP#oS3$$a{p^{D+0oJQ71`1?OAn_m8)UGZmj3l*ZI)`V-a>MKGGFG< z&^jg#Ok%(hhm>hSrZ5;Qga4u(?^i>GiW_j9%_7M>j(^|Om$#{k+^*ULnEgzW_1gCICtAD^WpC`A z{9&DXkG#01Xo)U$OC(L5Y$DQ|Q4C6CjUKk1UkPj$nXH##J{c8e#K|&{mA*;b$r0E4 zUNo0jthwA(c&N1l=PEe8Rw_8cEl|-eya9z&H3#n`B$t#+aJ03RFMzrV@gowbe8v(c zIFM60^0&lCFO10NU4w@|61xiZ4CVXeaKjd;d?sv52XM*lS8XiVjgWpRB;&U_C0g+`6B5V&w|O6B*_q zsATxL!M}+$He)1eOWECce#eS@2n^xhlB4<_Nn?yCVEQWDs(r`|@2GqLe<#(|&P0U? z$7V5IgpWf09uIf_RazRwC?qEqRaHyL?iiS05UiGesJy%^>-C{{ypTBI&B0-iUYhk> zIk<5xpsuV@g|z(AZD+C-;A!fTG=df1=<%nxy(a(IS+U{ME4ZbDEBtcD_3V=icT6*_ z)>|J?>&6%nvHhZERBtjK+s4xnut*@>GAmA5m*OTp$!^CHTr}vM4n(X1Q*;{e-Rd2BCF-u@1ZGm z!S8hJ6L=Gl4T_SDa7Xx|-{4mxveJg=ctf`BJ*fy!yF6Dz&?w(Q_6B}WQVtNI!BVBC zKfX<>7vd6C96}XAQmF-Jd?1Q4eTfRB3q7hCh0f!(JkdWT5<{iAE#dKy*Jxq&3a1@~ z8C||Dn2mFNyrUV|<-)C^_y7@8c2Fz+2jrae9deBDu;U}tJ{^xAdxCD248(k;dCJ%o z`y3sADe>U%suxwwv~8A1+R$VB=Q?%U?4joI$um;aH+eCrBqpn- z%79D_7rb;R-;-9RTrwi9dPlg8&@tfWhhZ(Vx&1PQ+6(huX`;M9x~LrW~~#3{j0Bh2kDU$}@!fFQej4VGkJv?M4rU^x!RU zEwhu$!CA_iDjFjrJa`aocySDX16?~;+wgav;}Zut6Mg%C4>}8FL?8)Kgwc(Qlj{@#2Pt0?G`$h7P#M+qoXtlV@d}%c&OzO+QYKK`kyXaK{U(O^2DyIXCZlNQjt0^8~8JzNGrIxhj}}M z&~QZlbx%t;MJ(Vux;2tgNKGlAqphLq%pd}JG9uoVHUo?|hN{pLQ6Em%r*+7t^<);X zm~6=qChlNAVXNN*Sow->*4;}T;l;D1I-5T{Bif@4_}=>l`tK;qqDdt5zvisCKhMAH z#r}`)7VW?LZqfdmXQ%zo5bJ00{Xb9^YKrk0Nf|oIW*K@(=`o2Vndz}ZDyk{!u}PVx zzd--+_WC*U{~DH3{?GI64IB+@On&@9X>EUAo&L+G{L^dozaI4C3G#2wr~hseW@K&g zKWs{uHu-9Je!3;4pE>eBltKUXb^*hG8I&413)$J&{D4N%7PcloU6bn%jPxJyQL?g* z9g+YFFEDiE`8rW^laCNzQmi7CTnPfwyg3VDHRAl>h=In6jeaVOP@!-CP60j3+#vpL zEYmh_oP0{-gTe7Or`L6x)6w?77QVi~jD8lWN@3RHcm80iV%M1A!+Y6iHM)05iC64tb$X2lV_%Txk@0l^hZqi^%Z?#- zE;LE0uFx)R08_S-#(wC=dS&}vj6P4>5ZWjhthP=*Hht&TdLtKDR;rXEX4*z0h74FA zMCINqrh3Vq;s%3MC1YL`{WjIAPkVL#3rj^9Pj9Ss7>7duy!9H0vYF%>1jh)EPqvlr6h%R%CxDsk| z!BACz7E%j?bm=pH6Eaw{+suniuY7C9Ut~1cWfOX9KW9=H><&kQlinPV3h9R>3nJvK z4L9(DRM=x;R&d#a@oFY7mB|m8h4692U5eYfcw|QKwqRsshN(q^v$4$)HgPpAJDJ`I zkqjq(8Cd!K!+wCd=d@w%~e$=gdUgD&wj$LQ1r>-E=O@c ze+Z$x{>6(JA-fNVr)X;*)40Eym1TtUZI1Pwwx1hUi+G1Jlk~vCYeXMNYtr)1?qwyg zsX_e*$h?380O00ou?0R@7-Fc59o$UvyVs4cUbujHUA>sH!}L54>`e` zHUx#Q+Hn&Og#YVOuo*niy*GU3rH;%f``nk#NN5-xrZ34NeH$l`4@t);4(+0|Z#I>Y z)~Kzs#exIAaf--65L0UHT_SvV8O2WYeD>Mq^Y6L!Xu8%vnpofG@w!}R7M28?i1*T&zp3X4^OMCY6(Dg<-! zXmcGQrRgHXGYre7GfTJ)rhl|rs%abKT_Nt24_Q``XH{88NVPW+`x4ZdrMuO0iZ0g` z%p}y};~T5gbb9SeL8BSc`SO#ixC$@QhXxZ=B}L`tP}&k?1oSPS=4%{UOHe0<_XWln zwbl5cn(j-qK`)vGHY5B5C|QZd5)W7c@{bNVXqJ!!n$^ufc?N9C-BF2QK1(kv++h!>$QbAjq)_b$$PcJdV+F7hz0Hu@ zqj+}m0qn{t^tD3DfBb~0B36|Q`bs*xs|$i^G4uNUEBl4g;op-;Wl~iThgga?+dL7s zUP(8lMO?g{GcYpDS{NM!UA8Hco?#}eNEioRBHy4`mq!Pd-9@-97|k$hpEX>xoX+dY zDr$wfm^P&}Wu{!%?)U_(%Mn79$(ywvu*kJ9r4u|MyYLI_67U7%6Gd_vb##Nerf@>& z8W11z$$~xEZt$dPG}+*IZky+os5Ju2eRi;1=rUEeIn>t-AzC_IGM-IXWK3^6QNU+2pe=MBn4I*R@A%-iLDCOHTE-O^wo$sL_h{dcPl=^muAQb`_BRm};=cy{qSkui;`WSsj9%c^+bIDQ z0`_?KX0<-=o!t{u(Ln)v>%VGL z0pC=GB7*AQ?N7N{ut*a%MH-tdtNmNC+Yf$|KS)BW(gQJ*z$d{+{j?(e&hgTy^2|AR9vx1Xre2fagGv0YXWqtNkg*v%40v?BJBt|f9wX5 z{QTlCM}b-0{mV?IG>TW_BdviUKhtosrBqdfq&Frdz>cF~yK{P@(w{Vr7z2qKFwLhc zQuogKO@~YwyS9%+d-zD7mJG~@?EFJLSn!a&mhE5$_4xBl&6QHMzL?CdzEnC~C3$X@ zvY!{_GR06ep5;<#cKCSJ%srxX=+pn?ywDwtJ2{TV;0DKBO2t++B(tIO4)Wh`rD13P z4fE$#%zkd=UzOB74gi=-*CuID&Z3zI^-`4U^S?dHxK8fP*;fE|a(KYMgMUo`THIS1f!*6dOI2 zFjC3O=-AL`6=9pp;`CYPTdVX z8(*?V&%QoipuH0>WKlL8A*zTKckD!paN@~hh zmXzm~qZhMGVdQGd=AG8&20HW0RGV8X{$9LldFZYm zE?}`Q3i?xJRz43S?VFMmqRyvWaS#(~Lempg9nTM$EFDP(Gzx#$r)W&lpFKqcAoJh-AxEw$-bjW>`_+gEi z2w`99#UbFZGiQjS8kj~@PGqpsPX`T{YOj`CaEqTFag;$jY z8_{Wzz>HXx&G*Dx<5skhpETxIdhKH?DtY@b9l8$l?UkM#J-Snmts7bd7xayKTFJ(u zyAT&@6cAYcs{PBfpqZa%sxhJ5nSZBPji?Zlf&}#L?t)vC4X5VLp%~fz2Sx<*oN<7` z?ge=k<=X7r<~F7Tvp9#HB{!mA!QWBOf%EiSJ6KIF8QZNjg&x~-%e*tflL(ji_S^sO ztmib1rp09uon}RcsFi#k)oLs@$?vs(i>5k3YN%$T(5Or(TZ5JW9mA6mIMD08=749$ z!d+l*iu{Il7^Yu}H;lgw=En1sJpCKPSqTCHy4(f&NPelr31^*l%KHq^QE>z>Ks_bH zjbD?({~8Din7IvZeJ>8Ey=e;I?thpzD=zE5UHeO|neioJwG;IyLk?xOz(yO&0DTU~ z^#)xcs|s>Flgmp;SmYJ4g(|HMu3v7#;c*Aa8iF#UZo7CvDq4>8#qLJ|YdZ!AsH%^_7N1IQjCro

K7UpUK$>l@ zw`1S}(D?mUXu_C{wupRS-jiX~w=Uqqhf|Vb3Cm9L=T+w91Cu^ z*&Ty%sN?x*h~mJc4g~k{xD4ZmF%FXZNC;oVDwLZ_WvrnzY|{v8hc1nmx4^}Z;yriXsAf+Lp+OFLbR!&Ox?xABwl zu8w&|5pCxmu#$?Cv2_-Vghl2LZ6m7}VLEfR5o2Ou$x02uA-%QB2$c(c1rH3R9hesc zfpn#oqpbKuVsdfV#cv@5pV4^f_!WS+F>SV6N0JQ9E!T90EX((_{bSSFv9ld%I0&}9 zH&Jd4MEX1e0iqDtq~h?DBrxQX1iI0lIs<|kB$Yrh&cpeK0-^K%=FBsCBT46@h#yi!AyDq1V(#V}^;{{V*@T4WJ&U-NTq43w=|K>z8%pr_nC>%C(Wa_l78Ufib$r8Od)IIN=u>417 z`Hl{9A$mI5A(;+-Q&$F&h-@;NR>Z<2U;Y21>>Z;s@0V@SbkMQQj%_;~+qTuQ?c|AV zcWm3XZQHhP&R%QWarS%mJ!9R^&!_)*s(v+VR@I#QrAT}`17Y+l<`b-nvmDNW`De%y zrwTZ9EJrj1AFA>B`1jYDow}~*dfPs}IZMO3=a{Fy#IOILc8F0;JS4x(k-NSpbN@qM z`@aE_e}5{!$v3+qVs7u?sOV(y@1Os*Fgu`fCW9=G@F_#VQ%xf$hj0~wnnP0$hFI+@ zkQj~v#V>xn)u??YutKsX>pxKCl^p!C-o?+9;!Nug^ z{rP!|+KsP5%uF;ZCa5F;O^9TGac=M|=V z_H(PfkV1rz4jl?gJ(ArXMyWT4y(86d3`$iI4^l9`vLdZkzpznSd5Ikfrs8qcSy&>z zTIZgWZGXw0n9ibQxYWE@gI0(3#KA-dAdPcsL_|hg2@~C!VZDM}5;v_Nykfq!*@*Zf zE_wVgx82GMDryKO{U{D>vSzSc%B~|cjDQrt5BN=Ugpsf8H8f1lR4SGo#hCuXPL;QQ z#~b?C4MoepT3X`qdW2dNn& zo8)K}%Lpu>0tQei+{>*VGErz|qjbK#9 zvtd8rcHplw%YyQCKR{kyo6fgg!)6tHUYT(L>B7er5)41iG`j$qe*kSh$fY!PehLcD zWeKZHn<492B34*JUQh=CY1R~jT9Jt=k=jCU2=SL&&y5QI2uAG2?L8qd2U(^AW#{(x zThSy=C#>k+QMo^7caQcpU?Qn}j-`s?1vXuzG#j8(A+RUAY})F@=r&F(8nI&HspAy4 z4>(M>hI9c7?DCW8rw6|23?qQMSq?*Vx?v30U%luBo)B-k2mkL)Ljk5xUha3pK>EEj z@(;tH|M@xkuN?gsz;*bygizwYR!6=(Xgcg^>WlGtRYCozY<rFX2E>kaZo)O<^J7a`MX8Pf`gBd4vrtD|qKn&B)C&wp0O-x*@-|m*0egT=-t@%dD zgP2D+#WPptnc;_ugD6%zN}Z+X4=c61XNLb7L1gWd8;NHrBXwJ7s0ce#lWnnFUMTR& z1_R9Fin4!d17d4jpKcfh?MKRxxQk$@)*hradH2$3)nyXep5Z;B z?yX+-Bd=TqO2!11?MDtG0n(*T^!CIiF@ZQymqq1wPM_X$Iu9-P=^}v7npvvPBu!d$ z7K?@CsA8H38+zjA@{;{kG)#AHME>Ix<711_iQ@WWMObXyVO)a&^qE1GqpP47Q|_AG zP`(AD&r!V^MXQ^e+*n5~Lp9!B+#y3#f8J^5!iC@3Y@P`;FoUH{G*pj*q7MVV)29+j z>BC`a|1@U_v%%o9VH_HsSnM`jZ-&CDvbiqDg)tQEnV>b%Ptm)T|1?TrpIl)Y$LnG_ zzKi5j2Fx^K^PG1=*?GhK;$(UCF-tM~^=Z*+Wp{FSuy7iHt9#4n(sUuHK??@v+6*|10Csdnyg9hAsC5_OrSL;jVkLlf zHXIPukLqbhs~-*oa^gqgvtpgTk_7GypwH><53riYYL*M=Q@F-yEPLqQ&1Sc zZB%w}T~RO|#jFjMWcKMZccxm-SL)s_ig?OC?y_~gLFj{n8D$J_Kw%{r0oB8?@dWzn zB528d-wUBQzrrSSLq?fR!K%59Zv9J4yCQhhDGwhptpA5O5U?Hjqt>8nOD zi{)0CI|&Gu%zunGI*XFZh(ix)q${jT8wnnzbBMPYVJc4HX*9d^mz|21$=R$J$(y7V zo0dxdbX3N#=F$zjstTf*t8vL)2*{XH!+<2IJ1VVFa67|{?LP&P41h$2i2;?N~RA30LV`BsUcj zfO9#Pg1$t}7zpv#&)8`mis3~o+P(DxOMgz-V*(?wWaxi?R=NhtW}<#^Z?(BhSwyar zG|A#Q7wh4OfK<|DAcl9THc-W4*>J4nTevsD%dkj`U~wSUCh15?_N@uMdF^Kw+{agk zJ`im^wDqj`Ev)W3k3stasP`88-M0ZBs7;B6{-tSm3>I@_e-QfT?7|n0D~0RRqDb^G zyHb=is;IwuQ&ITzL4KsP@Z`b$d%B0Wuhioo1CWttW8yhsER1ZUZzA{F*K=wmi-sb#Ju+j z-l@In^IKnb{bQG}Ps>+Vu_W#grNKNGto+yjA)?>0?~X`4I3T@5G1)RqGUZuP^NJCq&^HykuYtMDD8qq+l8RcZNJsvN(10{ zQ1$XcGt}QH-U^WU!-wRR1d--{B$%vY{JLWIV%P4-KQuxxDeJaF#{eu&&r!3Qu{w}0f--8^H|KwE>)ORrcR+2Qf zb})DRcH>k0zWK8@{RX}NYvTF;E~phK{+F;MkIP$)T$93Ba2R2TvKc>`D??#mv9wg$ zd~|-`Qx5LwwsZ2hb*Rt4S9dsF%Cny5<1fscy~)d;0m2r$f=83<->c~!GNyb!U)PA; zq^!`@@)UaG)Ew(9V?5ZBq#c%dCWZrplmuM`o~TyHjAIMh0*#1{B>K4po-dx$Tk-Cq z=WZDkP5x2W&Os`N8KiYHRH#UY*n|nvd(U>yO=MFI-2BEp?x@=N<~CbLJBf6P)}vLS?xJXYJ2^<3KJUdrwKnJnTp{ zjIi|R=L7rn9b*D#Xxr4*R<3T5AuOS+#U8hNlfo&^9JO{VbH!v9^JbK=TCGR-5EWR@ zN8T-_I|&@A}(hKeL4_*eb!1G8p~&_Im8|wc>Cdir+gg90n1dw?QaXcx6Op_W1r=axRw>4;rM*UOpT#Eb9xU1IiWo@h?|5uP zka>-XW0Ikp@dIe;MN8B01a7+5V@h3WN{J=HJ*pe0uwQ3S&MyWFni47X32Q7SyCTNQ z+sR!_9IZa5!>f&V$`q!%H8ci!a|RMx5}5MA_kr+bhtQy{-^)(hCVa@I!^TV4RBi zAFa!Nsi3y37I5EK;0cqu|9MRj<^r&h1lF}u0KpKQD^5Y+LvFEwM zLU@@v4_Na#Axy6tn3P%sD^5P#<7F;sd$f4a7LBMk zGU^RZHBcxSA%kCx*eH&wgA?Qwazm8>9SCSz_!;MqY-QX<1@p$*T8lc?@`ikEqJ>#w zcG``^CoFMAhdEXT9qt47g0IZkaU)4R7wkGs^Ax}usqJ5HfDYAV$!=6?>J6+Ha1I<5 z|6=9soU4>E))tW$<#>F ziZ$6>KJf0bPfbx_)7-}tMINlc=}|H+$uX)mhC6-Hz+XZxsKd^b?RFB6et}O#+>Wmw9Ec9) z{q}XFWp{3@qmyK*Jvzpyqv57LIR;hPXKsrh{G?&dRjF%Zt5&m20Ll?OyfUYC3WRn{cgQ?^V~UAv+5 z&_m#&nIwffgX1*Z2#5^Kl4DbE#NrD&Hi4|7SPqZ}(>_+JMz=s|k77aEL}<=0Zfb)a z%F(*L3zCA<=xO)2U3B|pcTqDbBoFp>QyAEU(jMu8(jLA61-H!ucI804+B!$E^cQQa z)_ERrW3g!B9iLb3nn3dlkvD7KsY?sRvls3QC0qPi>o<)GHx%4Xb$5a3GBTJ(k@`e@ z$RUa^%S15^1oLEmA=sayrP5;9qtf!Z1*?e$ORVPsXpL{jL<6E)0sj&swP3}NPmR%FM?O>SQgN5XfHE< zo(4#Cv11(%Nnw_{_Ro}r6=gKd{k?NebJ~<~Kv0r(r0qe4n3LFx$5%x(BKvrz$m?LG zjLIc;hbj0FMdb9aH9Lpsof#yG$(0sG2%RL;d(n>;#jb!R_+dad+K;Ccw!|RY?uS(a zj~?=&M!4C(5LnlH6k%aYvz@7?xRa^2gml%vn&eKl$R_lJ+e|xsNfXzr#xuh(>`}9g zLHSyiFwK^-p!;p$yt7$F|3*IfO3Mlu9e>Dpx8O`37?fA`cj`C0B-m9uRhJjs^mRp# zWB;Aj6|G^1V6`jg7#7V9UFvnB4((nIwG?k%c7h`?0tS8J3Bn0t#pb#SA}N-|45$-j z$R>%7cc2ebAClXc(&0UtHX<>pd)akR3Kx_cK+n<}FhzmTx!8e9^u2e4%x{>T6pQ`6 zO182bh$-W5A3^wos0SV_TgPmF4WUP-+D25KjbC{y_6W_9I2_vNKwU(^qSdn&>^=*t z&uvp*@c8#2*paD!ZMCi3;K{Na;I4Q35zw$YrW5U@Kk~)&rw;G?d7Q&c9|x<Hg|CNMsxovmfth*|E*GHezPTWa^Hd^F4!B3sF;)? z(NaPyAhocu1jUe(!5Cy|dh|W2=!@fNmuNOzxi^tE_jAtzNJ0JR-avc_H|ve#KO}#S z#a(8secu|^Tx553d4r@3#6^MHbH)vmiBpn0X^29xEv!Vuh1n(Sr5I0V&`jA2;WS|Y zbf0e}X|)wA-Pf5gBZ>r4YX3Mav1kKY(ulAJ0Q*jB)YhviHK)w!TJsi3^dMa$L@^{` z_De`fF4;M87vM3Ph9SzCoCi$#Fsd38u!^0#*sPful^p5oI(xGU?yeYjn;Hq1!wzFk zG&2w}W3`AX4bxoVm03y>ts{KaDf!}b&7$(P4KAMP=vK5?1In^-YYNtx1f#}+2QK@h zeSeAI@E6Z8a?)>sZ`fbq9_snl6LCu6g>o)rO;ijp3|$vig+4t} zylEo7$SEW<_U+qgVcaVhk+4k+C9THI5V10qV*dOV6pPtAI$)QN{!JRBKh-D zk2^{j@bZ}yqW?<#VVuI_27*cI-V~sJiqQv&m07+10XF+#ZnIJdr8t`9s_EE;T2V;B z4UnQUH9EdX%zwh-5&wflY#ve!IWt0UE-My3?L#^Bh%kcgP1q{&26eXLn zTkjJ*w+(|_>Pq0v8{%nX$QZbf)tbJaLY$03;MO=Ic-uqYUmUCuXD>J>o6BCRF=xa% z3R4SK9#t1!K4I_d>tZgE>&+kZ?Q}1qo4&h%U$GfY058s%*=!kac{0Z+4Hwm!)pFLR zJ+5*OpgWUrm0FPI2ib4NPJ+Sk07j(`diti^i#kh&f}i>P4~|d?RFb#!JN)~D@)beox}bw?4VCf^y*`2{4`-@%SFTry2h z>9VBc9#JxEs1+0i2^LR@B1J`B9Ac=#FW=(?2;5;#U$0E0UNag_!jY$&2diQk_n)bT zl5Me_SUvqUjwCqmVcyb`igygB_4YUB*m$h5oeKv3uIF0sk}~es!{D>4r%PC*F~FN3owq5e0|YeUTSG#Vq%&Gk7uwW z0lDo#_wvflqHeRm*}l?}o;EILszBt|EW*zNPmq#?4A+&i0xx^?9obLyY4xx=Y9&^G;xYXYPxG)DOpPg!i_Ccl#3L}6xAAZzNhPK1XaC_~ z!A|mlo?Be*8Nn=a+FhgpOj@G7yYs(Qk(8&|h@_>w8Y^r&5nCqe0V60rRz?b5%J;GYeBqSAjo|K692GxD4` zRZyM2FdI+-jK2}WAZTZ()w_)V{n5tEb@>+JYluDozCb$fA4H)$bzg(Ux{*hXurjO^ zwAxc+UXu=&JV*E59}h3kzQPG4M)X8E*}#_&}w*KEgtX)cU{vm9b$atHa;s>| z+L6&cn8xUL*OSjx4YGjf6{Eq+Q3{!ZyhrL&^6Vz@jGbI%cAM9GkmFlamTbcQGvOlL zmJ?(FI)c86=JEs|*;?h~o)88>12nXlpMR4@yh%qdwFNpct;vMlc=;{FSo*apJ;p}! zAX~t;3tb~VuP|ZW;z$=IHf->F@Ml)&-&Bnb{iQyE#;GZ@C$PzEf6~q}4D>9jic@mTO5x76ulDz@+XAcm35!VSu zT*Gs>;f0b2TNpjU_BjHZ&S6Sqk6V1370+!eppV2H+FY!q*n=GHQ!9Rn6MjY!Jc77A zG7Y!lFp8?TIHN!LXO?gCnsYM-gQxsm=Ek**VmZu7vnuufD7K~GIxfxbsQ@qv2T zPa`tvHB$fFCyZl>3oYg?_wW)C>^_iDOc^B7klnTOoytQH18WkOk)L2BSD0r%xgRSW zQS9elF^?O=_@|58zKLK;(f77l-Zzu}4{fXed2saq!5k#UZAoDBqYQS{sn@j@Vtp|$ zG%gnZ$U|9@u#w1@11Sjl8ze^Co=)7yS(}=;68a3~g;NDe_X^}yJj;~s8xq9ahQ5_r zxAlTMnep*)w1e(TG%tWsjo3RR;yVGPEO4V{Zp?=a_0R#=V^ioQu4YL=BO4r0$$XTX zZfnw#_$V}sDAIDrezGQ+h?q24St0QNug_?{s-pI(^jg`#JRxM1YBV;a@@JQvH8*>> zIJvku74E0NlXkYe_624>znU0J@L<-c=G#F3k4A_)*;ky!C(^uZfj%WB3-*{*B$?9+ zDm$WFp=0(xnt6`vDQV3Jl5f&R(Mp};;q8d3I%Kn>Kx=^;uSVCw0L=gw53%Bp==8Sw zxtx=cs!^-_+i{2OK`Q;913+AXc_&Z5$@z3<)So0CU3;JAv=H?@Zpi~riQ{z-zLtVL z!oF<}@IgJp)Iyz1zVJ42!SPHSkjYNS4%ulVVIXdRuiZ@5Mx8LJS}J#qD^Zi_xQ@>DKDr-_e#>5h3dtje*NcwH_h;i{Sx7}dkdpuW z(yUCjckQsagv*QGMSi9u1`Z|V^}Wjf7B@q%j2DQXyd0nOyqg%m{CK_lAoKlJ7#8M} z%IvR?Vh$6aDWK2W!=i?*<77q&B8O&3?zP(Cs@kapc)&p7En?J;t-TX9abGT#H?TW? ztO5(lPKRuC7fs}zwcUKbRh=7E8wzTsa#Z{a`WR}?UZ%!HohN}d&xJ=JQhpO1PI#>X zHkb>pW04pU%Bj_mf~U}1F1=wxdBZu1790>3Dm44bQ#F=T4V3&HlOLsGH)+AK$cHk6 zia$=$kog?)07HCL*PI6}DRhpM^*%I*kHM<#1Se+AQ!!xyhcy6j7`iDX7Z-2i73_n# zas*?7LkxS-XSqv;YBa zW_n*32D(HTYQ0$feV_Fru1ZxW0g&iwqixPX3=9t4o)o|kOo79V$?$uh?#8Q8e>4e)V6;_(x&ViUVxma+i25qea;d-oK7ouuDsB^ab{ zu1qjQ%`n56VtxBE#0qAzb7lph`Eb-}TYpXB!H-}3Ykqyp`otprp7{VEuW*^IR2n$Fb99*nAtqT&oOFIf z@w*6>YvOGw@Ja?Pp1=whZqydzx@9X4n^2!n83C5{C?G@|E?&$?p*g68)kNvUTJ)I6 z1Q|(#UuP6pj78GUxq11m-GSszc+)X{C2eo-?8ud9sB=3(D47v?`JAa{V(IF zPZQ_0AY*9M97>Jf<o%#O_%Wq}8>YM=q0|tGY+hlXcpE=Z4Od z`NT7Hu2hnvRoqOw@g1f=bv`+nba{GwA$Ak0INlqI1k<9!x_!sL()h?hEWoWrdU3w` zZ%%)VR+Bc@_v!C#koM1p-3v_^L6)_Ktj4HE>aUh%2XZE@JFMOn)J~c`_7VWNb9c-N z2b|SZMR4Z@E7j&q&9(6H3yjEu6HV7{2!1t0lgizD;mZ9$r(r7W5G$ky@w(T_dFnOD z*p#+z$@pKE+>o@%eT(2-p_C}wbQ5s(%Sn_{$HDN@MB+Ev?t@3dPy`%TZ!z}AThZSu zN<1i$siJhXFdjV zP*y|V<`V8t=h#XTRUR~5`c`Z9^-`*BZf?WAehGdg)E2Je)hqFa!k{V(u+(hTf^Yq& zoruUh2(^3pe)2{bvt4&4Y9CY3js)PUHtd4rVG57}uFJL)D(JfSIo^{P=7liFXG zq5yqgof0V8paQcP!gy+;^pp-DA5pj=gbMN0eW=-eY+N8~y+G>t+x}oa!5r>tW$xhI zPQSv=pi;~653Gvf6~*JcQ%t1xOrH2l3Zy@8AoJ+wz@daW@m7?%LXkr!bw9GY@ns3e zSfuWF_gkWnesv?s3I`@}NgE2xwgs&rj?kH-FEy82=O8`+szN ziHch`vvS`zNfap14!&#i9H@wF7}yIPm=UB%(o(}F{wsZ(wA0nJ2aD^@B41>>o-_U6 zUqD~vdo48S8~FTb^+%#zcbQiiYoDKYcj&$#^;Smmb+Ljp(L=1Kt_J!;0s%1|JK}Wi z;={~oL!foo5n8=}rs6MmUW~R&;SIJO3TL4Ky?kh+b2rT9B1Jl4>#Uh-Bec z`Hsp<==#UEW6pGPhNk8H!!DUQR~#F9jEMI6T*OWfN^Ze&X(4nV$wa8QUJ>oTkruH# zm~O<`J7Wxseo@FqaZMl#Y(mrFW9AHM9Kb|XBMqaZ2a)DvJgYipkDD_VUF_PKd~dT7 z#02}bBfPn9a!X!O#83=lbJSK#E}K&yx-HI#T6ua)6o0{|={*HFusCkHzs|Fn&|C3H zBck1cmfcWVUN&i>X$YU^Sn6k2H;r3zuXbJFz)r5~3$d$tUj(l1?o={MM){kjgqXRO zc5R*#{;V7AQh|G|)jLM@wGAK&rm2~@{Pewv#06pHbKn#wL0P6F1!^qw9g&cW3Z=9} zj)POhOlwsh@eF=>z?#sIs*C-Nl(yU!#DaiaxhEs#iJqQ8w%(?+6lU02MYSeDkr!B- zPjMv+on6OLXgGnAtl(ao>|X2Y8*Hb}GRW5}-IzXnoo-d0!m4Vy$GS!XOLy>3_+UGs z2D|YcQx@M#M|}TDOetGi{9lGo9m-=0-^+nKE^*?$^uHkxZh}I{#UTQd;X!L+W@jm( zDg@N4+lUqI92o_rNk{3P>1gxAL=&O;x)ZT=q1mk0kLlE$WeWuY_$0`0jY-Kkt zP*|m3AF}Ubd=`<>(Xg0har*_@x2YH}bn0Wk*OZz3*e5;Zc;2uBdnl8?&XjupbkOeNZsNh6pvsq_ydmJI+*z**{I{0K)-;p1~k8cpJXL$^t!-`E}=*4G^-E8>H!LjTPxSx zcF+cS`ommfKMhNSbas^@YbTpH1*RFrBuATUR zt{oFWSk^$xU&kbFQ;MCX22RAN5F6eq9UfR$ut`Jw--p2YX)A*J69m^!oYfj2y7NYcH6&r+0~_sH^c^nzeN1AU4Ga7=FlR{S|Mm~MpzY0$Z+p2W(a={b-pR9EO1Rs zB%KY|@wLcAA@)KXi!d2_BxrkhDn`DT1=Dec}V!okd{$+wK z4E{n8R*xKyci1(CnNdhf$Dp2(Jpof0-0%-38X=Dd9PQgT+w%Lshx9+loPS~MOm%ZT zt%2B2iL_KU_ita%N>xjB!#71_3=3c}o zgeW~^U_ZTJQ2!PqXulQd=3b=XOQhwATK$y(9$#1jOQ4}4?~l#&nek)H(04f(Sr=s| zWv7Lu1=%WGk4FSw^;;!8&YPM)pQDCY9DhU`hMty1@sq1=Tj7bFsOOBZOFlpR`W>-J$-(kezWJj;`?x-v>ev{*8V z8p|KXJPV$HyQr1A(9LVrM47u-XpcrIyO`yWvx1pVYc&?154aneRpLqgx)EMvRaa#|9?Wwqs2+W8n5~79G z(}iCiLk;?enn}ew`HzhG+tu+Ru@T+K5juvZN)wY;x6HjvqD!&!)$$;1VAh~7fg0K| zEha#aN=Yv|3^~YFH}cc38ovVb%L|g@9W6fo(JtT6$fa?zf@Ct88e}m?i)b*Jgc{fl zExfdvw-BYDmH6>(4QMt#p0;FUIQqkhD}aH?a7)_%JtA~soqj{ppP_82yi9kaxuK>~ ze_)Zt>1?q=ZH*kF{1iq9sr*tVuy=u>Zev}!gEZx@O6-fjyu9X00gpIl-fS_pzjpqJ z1yqBmf9NF!jaF<+YxgH6oXBdK)sH(>VZ)1siyA$P<#KDt;8NT*l_0{xit~5j1P)FN zI8hhYKhQ)i z37^aP13B~u65?sg+_@2Kr^iWHN=U;EDSZ@2W2!5ALhGNWXnFBY%7W?1 z=HI9JzQ-pLKZDYTv<0-lt|6c-RwhxZ)mU2Os{bsX_i^@*fKUj8*aDO5pks=qn3Dv6 zwggpKLuyRCTVPwmw1r}B#AS}?X7b837UlXwp~E2|PJw2SGVueL7){Y&z!jL!XN=0i zU^Eig`S2`{+gU$68aRdWx?BZ{sU_f=8sn~>s~M?GU~`fH5kCc; z8ICp+INM3(3{#k32RZdv6b9MQYdZXNuk7ed8;G?S2nT+NZBG=Tar^KFl2SvhW$bGW#kdWL-I)s_IqVnCDDM9fm8g;P;8 z7t4yZn3^*NQfx7SwmkzP$=fwdC}bafQSEF@pd&P8@H#`swGy_rz;Z?Ty5mkS%>m#% zp_!m9e<()sfKiY(nF<1zBz&&`ZlJf6QLvLhl`_``%RW&{+O>Xhp;lwSsyRqGf=RWd zpftiR`={2(siiPAS|p}@q=NhVc0ELprt%=fMXO3B)4ryC2LT(o=sLM7hJC!}T1@)E zA3^J$3&1*M6Xq>03FX`R&w*NkrZE?FwU+Muut;>qNhj@bX17ZJxnOlPSZ=Zeiz~T_ zOu#yc3t6ONHB;?|r4w+pI)~KGN;HOGC)txxiUN8#mexj+W(cz%9a4sx|IRG=}ia zuEBuba3AHsV2feqw-3MvuL`I+2|`Ud4~7ZkN=JZ;L20|Oxna5vx1qbIh#k2O4$RQF zo`tL()zxaqibg^GbB+BS5#U{@K;WWQj~GcB1zb}zJkPwH|5hZ9iH2308!>_;%msji zJHSL~s)YHBR=Koa1mLEOHos*`gp=s8KA-C zu0aE+W!#iJ*0xqKm3A`fUGy#O+X+5W36myS>Uh2!R*s$aCU^`K&KKLCCDkejX2p=5 z%o7-fl03x`gaSNyr?3_JLv?2RLS3F*8ub>Jd@^Cc17)v8vYEK4aqo?OS@W9mt%ITJ z9=S2%R8M){CugT@k~~0x`}Vl!svYqX=E)c_oU6o}#Hb^%G1l3BudxA{F*tbjG;W_>=xV73pKY53v%>I)@D36I_@&p$h|Aw zonQS`07z_F#@T-%@-Tb|)7;;anoD_WH>9ewFy(ZcEOM$#Y)8>qi7rCnsH9GO-_7zF zu*C87{Df1P4TEOsnzZ@H%&lvV(3V@;Q!%+OYRp`g05PjY^gL$^$-t0Y>H*CDDs?FZly*oZ&dxvsxaUWF!{em4{A>n@vpXg$dwvt@_rgmHF z-MER`ABa8R-t_H*kv>}CzOpz;!>p^^9ztHMsHL|SRnS<-y5Z*r(_}c4=fXF`l^-i}>e7v!qs_jv zqvWhX^F=2sDNWA9c@P0?lUlr6ecrTKM%pNQ^?*Lq?p-0~?_j50xV%^(+H>sMul#Tw zeciF*1=?a7cI(}352%>LO96pD+?9!fNyl^9v3^v&Y4L)mNGK0FN43&Xf8jUlxW1Bw zyiu2;qW-aGNhs=zbuoxnxiwZ3{PFZM#Kw)9H@(hgX23h(`Wm~m4&TvoZoYp{plb^> z_#?vXcxd>r7K+1HKJvhed>gtK`TAbJUazUWQY6T~t2af%#<+Veyr%7-#*A#@&*;@g58{i|E%6yC_InGXCOd{L0;$)z#?n7M`re zh!kO{6=>7I?*}czyF7_frt#)s1CFJ_XE&VrDA?Dp3XbvF{qsEJgb&OLSNz_5g?HpK z9)8rsr4JN!Af3G9!#Qn(6zaUDqLN(g2g8*M)Djap?WMK9NKlkC)E2|-g|#-rp%!Gz zAHd%`iq|81efi93m3yTBw3g0j#;Yb2X{mhRAI?&KDmbGqou(2xiRNb^sV}%%Wu0?< z?($L>(#BO*)^)rSgyNRni$i`R4v;GhlCZ8$@e^ROX(p=2_v6Y!%^As zu022)fHdv_-~Yu_H6WVPLpHQx!W%^6j)cBhS`O3QBW#x(eX54d&I22op(N59b*&$v zFiSRY6rOc^(dgSV1>a7-5C;(5S5MvKcM2Jm-LD9TGqDpP097%52V+0>Xqq!! zq4e3vj53SE6i8J`XcQB|MZPP8j;PAOnpGnllH6#Ku~vS42xP*Nz@~y%db7Xi8s09P z1)e%8ys6&M8D=Dt6&t`iKG_4X=!kgRQoh%Z`dc&mlOUqXk-k`jKv9@(a^2-Upw>?< zt5*^DV~6Zedbec4NVl($2T{&b)zA@b#dUyd>`2JC0=xa_fIm8{5um zr-!ApXZhC8@=vC2WyxO|!@0Km)h8ep*`^he92$@YwP>VcdoS5OC^s38e#7RPsg4j+ zbVGG}WRSET&ZfrcR(x~k8n1rTP%CnfUNKUonD$P?FtNFF#cn!wEIab-;jU=B1dHK@ z(;(yAQJ`O$sMn>h;pf^8{JISW%d+@v6@CnXh9n5TXGC}?FI9i-D0OMaIg&mAg=0Kn zNJ7oz5*ReJukD55fUsMuaP+H4tDN&V9zfqF@ zr=#ecUk9wu{0;!+gl;3Bw=Vn^)z$ahVhhw)io!na&9}LmWurLb0zubxK=UEnU*{5P z+SP}&*(iBKSO4{alBHaY^)5Q=mZ+2OwIooJ7*Q5XJ+2|q`9#f?6myq!&oz?klihLq z4C)$XP!BNS0G_Z1&TM>?Jk{S~{F3n83ioli=IO6f%wkvCl(RFFw~j0tb{GvXTx>*sB0McY0s&SNvj4+^h`9nJ_wM>F!Uc>X}9PifQekn0sKI2SAJP!a4h z5cyGTuCj3ZBM^&{dRelIlT^9zcfaAuL5Y~bl!ppSf`wZbK$z#6U~rdclk``e+!qhe z6Qspo*%<)eu6?C;Bp<^VuW6JI|Ncvyn+LlSl;Mp22Bl7ARQ0Xc24%29(ZrdsIPw&-=yHQ7_Vle|5h>AST0 zUGX2Zk34vp?U~IHT|;$U86T+UUHl_NE4m|}>E~6q``7hccCaT^#y+?wD##Q%HwPd8 zV3x4L4|qqu`B$4(LXqDJngNy-{&@aFBvVsywt@X^}iH7P%>bR?ciC$I^U-4Foa`YKI^qDyGK7k%E%c_P=yzAi`YnxGA%DeNd++j3*h^ z=rn>oBd0|~lZ<6YvmkKY*ZJlJ;Im0tqgWu&E92eqt;+NYdxx`eS(4Hw_Jb5|yVvBg z*tbdY^!AN;luEyN4VRhS@-_DC{({ziH{&Z}iGElSV~qvT>L-8G%+yEL zX#MFOhj{InyKG=mvW-<1B@c-}x$vA(nU?>S>0*eN#!SLzQ)Ex7fvQ)S4D<8|I#N$3 zT5Ei`Z?cxBODHX8(Xp73v`IsAYC@9b;t}z0wxVuQSY1J^GRwDPN@qbM-ZF48T$GZ< z8WU+;Pqo?{ghI-KZ-i*ydXu`Ep0Xw^McH_KE9J0S7G;x8Fe`DVG?j3Pv=0YzJ}yZR z%2=oqHiUjvuk0~Ca>Kol4CFi0_xQT~;_F?=u+!kIDl-9g`#ZNZ9HCy17Ga1v^Jv9# z{T4Kb1-AzUxq*MutfOWWZgD*HnFfyYg0&e9f(5tZ>krPF6{VikNeHoc{linPPt#Si z&*g>(c54V8rT_AX!J&bNm-!umPvOR}vDai#`CX___J#=zeB*{4<&2WpaDncZsOkp* zsg<%@@rbrMkR_ux9?LsQxzoBa1s%$BBn6vk#{&&zUwcfzeCBJUwFYSF$08qDsB;gWQN*g!p8pxjofWbqNSZOEKOaTx@+* zwdt5*Q47@EOZ~EZL9s?1o?A%9TJT=Ob_13yyugvPg*e&ZU(r6^k4=2+D-@n=Hv5vu zSXG|hM(>h9^zn=eQ=$6`JO&70&2|%V5Lsx>)(%#;pcOfu>*nk_3HB_BNaH$`jM<^S zcSftDU1?nL;jy)+sfonQN}(}gUW?d_ikr*3=^{G)=tjBtEPe>TO|0ddVB zTklrSHiW+!#26frPXQQ(YN8DG$PZo?(po(QUCCf_OJC`pw*uey00%gmH!`WJkrKXj2!#6?`T25mTu9OJp2L8z3! z=arrL$ZqxuE{%yV)14Kd>k}j7pxZ6#$Dz8$@WV5p8kTqN<-7W)Q7Gt2{KoOPK_tZ| zf2WG~O5@{qPI+W<4f_;reuFVdO^5`ADC1!JQE|N`s3cq@(0WB!n0uh@*c{=LAd;~} zyGK@hbF-Oo+!nN)@i*O(`@FA#u?o=~e{`4O#5}z&=UkU*50fOrzi11D^&FOqe>wii z?*k+2|EcUs;Gx{!@KBT~>PAwLrIDT7Th=Utu?~?np@t^gFs?zgX=D${RwOY^WGh-+ z+#4$066ISh8eYW#FXWp~S`<*%O^ZuItL1Tyqt8#tZ zY120E;^VG`!lZn&3sPd$RkdHpU#|w+bYV)pJC|SH9g%|5IkxVTQcBA4CL0}$&}ef@ zW^Vtj%M;;_1xxP9x#ex17&4N*{ksO*_4O}xYu(p*JkL#yr}@7b)t5X?%CY<+s5_MJ zuiqt+N_;A(_)%lumoyRFixWa-M7qK_9s6<1X?JDa9fP!+_6u~~M$5L=ipB=7(j#f< zZ34J%=bs549%~_mA(|={uZNs_0?o7;-LBP(ZRnkd{-^|2|=4vUTmtByHL8 zEph`(LSEzQj68a+`d$V<45J7cyv^#|^|%fD#si1Nx!4NW*`l*{->HEWNh6-|g>-=r zXmQ|-i}Ku$ndUeHQ^&ieT!Lf}vf6GaqW9$DJ2NWrqwPY%%4nip$@vK$nRp*_C-v<| zuKz~ZyN&<%!NS26&x?jhy+@awJipMQ-8(X4#Ae5??U<1QMt1l9R=w9fAnEF}NYu$2 z>6}Vkc zIb*A?G*z8^IvibmBKn_u^5&T_1oey0gZS2~obf(#xk=erZGTEdQnt3DMGM+0oPwss zj5zXD;(oWhB_T@~Ig#9@v)AKtXu3>Inmgf@A|-lD-1U>cNyl3h?ADD9)GG4}zUGPk zZzaXe!~Kf?<~@$G?Uql3t8jy9{2!doq4=J}j9ktTxss{p6!9UdjyDERlA*xZ!=Q)KDs5O)phz>Vq3BNGoM(H|=1*Q4$^2fTZw z(%nq1P|5Rt81}SYJpEEzMPl5VJsV5&4e)ZWKDyoZ>1EwpkHx-AQVQc8%JMz;{H~p{=FXV>jIxvm4X*qv52e?Y-f%DJ zxEA165GikEASQ^fH6K#d!Tpu2HP{sFs%E=e$gYd$aj$+xue6N+Wc(rAz~wUsk2`(b z8Kvmyz%bKQxpP}~baG-rwYcYCvkHOi zlkR<=>ZBTU*8RF_d#Bl@zZsRIhx<%~Z@Z=ik z>adw3!DK(8R|q$vy{FTxw%#xliD~6qXmY^7_9kthVPTF~Xy1CfBqbU~?1QmxmU=+k z(ggxvEuA;0e&+ci-zQR{-f7aO{O(Pz_OsEjLh_K>MbvoZ4nxtk5u{g@nPv)cgW_R} z9}EA4K4@z0?7ue}Z(o~R(X&FjejUI2g~08PH1E4w>9o{)S(?1>Z0XMvTb|;&EuyOE zGvWNpYX)Nv<8|a^;1>bh#&znEcl-r!T#pn= z4$?Yudha6F%4b>*8@=BdtXXY4N+`U4Dmx$}>HeVJk-QdTG@t!tVT#0(LeV0gvqyyw z2sEp^9eY0N`u10Tm4n8No&A=)IeEC|gnmEXoNSzu!1<4R<%-9kY_8~5Ej?zRegMn78wuMs#;i&eUA0Zk_RXQ3b&TT} z;SCI=7-FUB@*&;8|n>(_g^HGf3@QODE3LpmX~ELnymQm{Sx9xrKS zK29p~?v@R$0=v6Dr5aW>-!{+h@?Q58|Kz8{{W`%J+lDAdb&M5VHrX_mDY;1-JLnf)ezmPau$)1;=`-FU=-r-83tX=C`S#}GZufju zQ>sXNT0Ny=k@nc%cFnvA_i4SC)?_ORXHq8B4D%el1uPX`c~uG#S1M7C+*MMqLw78E zhY2dI8@+N^qrMI1+;TUda(vGqGSRyU{Fnm`aqrr7bz42c5xsOO-~oZpkzorD1g}Y<6rk&3>PsSGy}W?MtqFky@A(X# zIuNZK0cK?^=;PUAu>j0#HtjbHCV*6?jzA&OoE$*Jlga*}LF`SF?WLhv1O|zqC<>*> zYB;#lsYKx0&kH@BFpW8n*yDcc6?;_zaJs<-jPSkCsSX-!aV=P5kUgF@Nu<{a%#K*F z134Q{9|YX7X(v$62_cY3^G%t~rD>Q0z@)1|zs)vjJ6Jq9;7#Ki`w+eS**En?7;n&7 zu==V3T&eFboN3ZiMx3D8qYc;VjFUk_H-WWCau(VFXSQf~viH0L$gwD$UfFHqNcgN`x}M+YQ6RnN<+@t>JUp#)9YOkqst-Ga?{FsDpEeX0(5v{0J~SEbWiL zXC2}M4?UH@u&|;%0y`eb33ldo4~z-x8zY!oVmV=c+f$m?RfDC35mdQ2E>Pze7KWP- z>!Bh<&57I+O_^s}9Tg^k)h7{xx@0a0IA~GAOt2yy!X%Q$1rt~LbTB6@Du!_0%HV>N zlf)QI1&gvERKwso23mJ!Ou6ZS#zCS5W`gxE5T>C#E|{i<1D35C222I33?Njaz`On7 zi<+VWFP6D{e-{yiN#M|Jgk<44u1TiMI78S5W`Sdb5f+{zu34s{CfWN7a3Cf^@L%!& zN$?|!!9j2c)j$~+R6n#891w-z8(!oBpL2K=+%a$r2|~8-(vQj5_XT`<0Ksf;oP+tz z9CObS!0m)Tgg`K#xBM8B(|Z)Wb&DYL{WTYv`;A=q6~Nnx2+!lTIXtj8J7dZE!P_{z z#f8w6F}^!?^KE#+ZDv+xd5O&3EmomZzsv?>E-~ygGum45fk!SBN&|eo1rKw^?aZJ4 E2O(~oYXATM literal 54329 zcmagFV|ZrKvM!pAZQHhO+qP}9lTNj?q^^Y^VFp)SH8qbSJ)2BQ2giqr}t zFG7D6)c?v~^Z#E_K}1nTQbJ9gQ9<%vVRAxVj)8FwL5_iTdUB>&m3fhE=kRWl;g`&m z!W5kh{WsV%fO*%je&j+Lv4xxK~zsEYQls$Q-p&dwID|A)!7uWtJF-=Tm1{V@#x*+kUI$=%KUuf2ka zjiZ{oiL1MXE2EjciJM!jrjFNwCh`~hL>iemrqwqnX?T*MX;U>>8yRcZb{Oy+VKZos zLiFKYPw=LcaaQt8tj=eoo3-@bG_342HQ%?jpgAE?KCLEHC+DmjxAfJ%Og^$dpC8Xw zAcp-)tfJm}BPNq_+6m4gBgBm3+CvmL>4|$2N$^Bz7W(}fz1?U-u;nE`+9`KCLuqg} zwNstNM!J4Uw|78&Y9~9>MLf56to!@qGkJw5Thx%zkzj%Ek9Nn1QA@8NBXbwyWC>9H z#EPwjMNYPigE>*Ofz)HfTF&%PFj$U6mCe-AFw$U%-L?~-+nSXHHKkdgC5KJRTF}`G zE_HNdrE}S0zf4j{r_f-V2imSqW?}3w-4=f@o@-q+cZgaAbZ((hn))@|eWWhcT2pLpTpL!;_5*vM=sRL8 zqU##{U#lJKuyqW^X$ETU5ETeEVzhU|1m1750#f}38_5N9)B_2|v@1hUu=Kt7-@dhA zq_`OMgW01n`%1dB*}C)qxC8q;?zPeF_r;>}%JYmlER_1CUbKa07+=TV45~symC*g8 zW-8(gag#cAOuM0B1xG8eTp5HGVLE}+gYTmK=`XVVV*U!>H`~j4+ROIQ+NkN$LY>h4 zqpwdeE_@AX@PL};e5vTn`Ro(EjHVf$;^oiA%@IBQq>R7_D>m2D4OwwEepkg}R_k*M zM-o;+P27087eb+%*+6vWFCo9UEGw>t&WI17Pe7QVuoAoGHdJ(TEQNlJOqnjZ8adCb zI`}op16D@v7UOEo%8E-~m?c8FL1utPYlg@m$q@q7%mQ4?OK1h%ODjTjFvqd!C z-PI?8qX8{a@6d&Lb_X+hKxCImb*3GFemm?W_du5_&EqRq!+H?5#xiX#w$eLti-?E$;Dhu`{R(o>LzM4CjO>ICf z&DMfES#FW7npnbcuqREgjPQM#gs6h>`av_oEWwOJZ2i2|D|0~pYd#WazE2Bbsa}X@ zu;(9fi~%!VcjK6)?_wMAW-YXJAR{QHxrD5g(ou9mR6LPSA4BRG1QSZT6A?kelP_g- zH(JQjLc!`H4N=oLw=f3{+WmPA*s8QEeEUf6Vg}@!xwnsnR0bl~^2GSa5vb!Yl&4!> zWb|KQUsC$lT=3A|7vM9+d;mq=@L%uWKwXiO9}a~gP4s_4Yohc!fKEgV7WbVo>2ITbE*i`a|V!^p@~^<={#?Gz57 zyPWeM2@p>D*FW#W5Q`1`#5NW62XduP1XNO(bhg&cX`-LYZa|m-**bu|>}S;3)eP8_ zpNTnTfm8 ze+7wDH3KJ95p)5tlwk`S7mbD`SqHnYD*6`;gpp8VdHDz%RR_~I_Ar>5)vE-Pgu7^Y z|9Px+>pi3!DV%E%4N;ii0U3VBd2ZJNUY1YC^-e+{DYq+l@cGtmu(H#Oh%ibUBOd?C z{y5jW3v=0eV0r@qMLgv1JjZC|cZ9l9Q)k1lLgm))UR@#FrJd>w^`+iy$c9F@ic-|q zVHe@S2UAnc5VY_U4253QJxm&Ip!XKP8WNcnx9^cQ;KH6PlW8%pSihSH2(@{2m_o+m zr((MvBja2ctg0d0&U5XTD;5?d?h%JcRJp{_1BQW1xu&BrA3(a4Fh9hon-ly$pyeHq zG&;6q?m%NJ36K1Sq_=fdP(4f{Hop;_G_(i?sPzvB zDM}>*(uOsY0I1j^{$yn3#U(;B*g4cy$-1DTOkh3P!LQ;lJlP%jY8}Nya=h8$XD~%Y zbV&HJ%eCD9nui-0cw!+n`V~p6VCRqh5fRX z8`GbdZ@73r7~myQLBW%db;+BI?c-a>Y)m-FW~M=1^|<21_Sh9RT3iGbO{o-hpN%d6 z7%++#WekoBOP^d0$$|5npPe>u3PLvX_gjH2x(?{&z{jJ2tAOWTznPxv-pAv<*V7r$ z6&glt>7CAClWz6FEi3bToz-soY^{ScrjwVPV51=>n->c(NJngMj6TyHty`bfkF1hc zkJS%A@cL~QV0-aK4>Id!9dh7>0IV;1J9(myDO+gv76L3NLMUm9XyPauvNu$S<)-|F zZS}(kK_WnB)Cl`U?jsdYfAV4nrgzIF@+%1U8$poW&h^c6>kCx3;||fS1_7JvQT~CV zQ8Js+!p)3oW>Df(-}uqC`Tcd%E7GdJ0p}kYj5j8NKMp(KUs9u7?jQ94C)}0rba($~ zqyBx$(1ae^HEDG`Zc@-rXk1cqc7v0wibOR4qpgRDt#>-*8N3P;uKV0CgJE2SP>#8h z=+;i_CGlv+B^+$5a}SicVaSeaNn29K`C&=}`=#Nj&WJP9Xhz4mVa<+yP6hkrq1vo= z1rX4qg8dc4pmEvq%NAkpMK>mf2g?tg_1k2%v}<3`$6~Wlq@ItJ*PhHPoEh1Yi>v57 z4k0JMO)*=S`tKvR5gb-(VTEo>5Y>DZJZzgR+j6{Y`kd|jCVrg!>2hVjz({kZR z`dLlKhoqT!aI8=S+fVp(5*Dn6RrbpyO~0+?fy;bm$0jmTN|t5i6rxqr4=O}dY+ROd zo9Et|x}!u*xi~>-y>!M^+f&jc;IAsGiM_^}+4|pHRn{LThFFpD{bZ|TA*wcGm}XV^ zr*C6~@^5X-*R%FrHIgo-hJTBcyQ|3QEj+cSqp#>&t`ZzB?cXM6S(lRQw$I2?m5=wd z78ki`R?%;o%VUhXH?Z#(uwAn9$m`npJ=cA+lHGk@T7qq_M6Zoy1Lm9E0UUysN)I_x zW__OAqvku^>`J&CB=ie@yNWsaFmem}#L3T(x?a`oZ+$;3O-icj2(5z72Hnj=9Z0w% z<2#q-R=>hig*(t0^v)eGq2DHC%GymE-_j1WwBVGoU=GORGjtaqr0BNigOCqyt;O(S zKG+DoBsZU~okF<7ahjS}bzwXxbAxFfQAk&O@>LsZMsZ`?N?|CDWM(vOm%B3CBPC3o z%2t@%H$fwur}SSnckUm0-k)mOtht`?nwsDz=2#v=RBPGg39i#%odKq{K^;bTD!6A9 zskz$}t)sU^=a#jLZP@I=bPo?f-L}wpMs{Tc!m7-bi!Ldqj3EA~V;4(dltJmTXqH0r z%HAWKGutEc9vOo3P6Q;JdC^YTnby->VZ6&X8f{obffZ??1(cm&L2h7q)*w**+sE6dG*;(H|_Q!WxU{g)CeoT z(KY&bv!Usc|m+Fqfmk;h&RNF|LWuNZ!+DdX*L=s-=_iH=@i` z?Z+Okq^cFO4}_n|G*!)Wl_i%qiMBaH8(WuXtgI7EO=M>=i_+;MDjf3aY~6S9w0K zUuDO7O5Ta6+k40~xh~)D{=L&?Y0?c$s9cw*Ufe18)zzk%#ZY>Tr^|e%8KPb0ht`b( zuP@8#Ox@nQIqz9}AbW0RzE`Cf>39bOWz5N3qzS}ocxI=o$W|(nD~@EhW13Rj5nAp; zu2obEJa=kGC*#3=MkdkWy_%RKcN=?g$7!AZ8vBYKr$ePY(8aIQ&yRPlQ=mudv#q$q z4%WzAx=B{i)UdLFx4os?rZp6poShD7Vc&mSD@RdBJ=_m^&OlkEE1DFU@csgKcBifJ zz4N7+XEJhYzzO=86 z#%eBQZ$Nsf2+X0XPHUNmg#(sNt^NW1Y0|M(${e<0kW6f2q5M!2YE|hSEQ*X-%qo(V zHaFwyGZ0on=I{=fhe<=zo{=Og-_(to3?cvL4m6PymtNsdDINsBh8m>a%!5o3s(en) z=1I z6O+YNertC|OFNqd6P=$gMyvmfa`w~p9*gKDESFqNBy(~Zw3TFDYh}$iudn)9HxPBi zdokK@o~nu?%imcURr5Y~?6oo_JBe}t|pU5qjai|#JDyG=i^V~7+a{dEnO<(y>ahND#_X_fcEBNiZ)uc&%1HVtx8Ts z*H_Btvx^IhkfOB#{szN*n6;y05A>3eARDXslaE>tnLa>+`V&cgho?ED+&vv5KJszf zG4@G;7i;4_bVvZ>!mli3j7~tPgybF5|J6=Lt`u$D%X0l}#iY9nOXH@(%FFJLtzb%p zzHfABnSs;v-9(&nzbZytLiqqDIWzn>JQDk#JULcE5CyPq_m#4QV!}3421haQ+LcfO*>r;rg6K|r#5Sh|y@h1ao%Cl)t*u`4 zMTP!deC?aL7uTxm5^nUv#q2vS-5QbBKP|drbDXS%erB>fYM84Kpk^au99-BQBZR z7CDynflrIAi&ahza+kUryju5LR_}-Z27g)jqOc(!Lx9y)e z{cYc&_r947s9pteaa4}dc|!$$N9+M38sUr7h(%@Ehq`4HJtTpA>B8CLNO__@%(F5d z`SmX5jbux6i#qc}xOhumzbAELh*Mfr2SW99=WNOZRZgoCU4A2|4i|ZVFQt6qEhH#B zK_9G;&h*LO6tB`5dXRSBF0hq0tk{2q__aCKXYkP#9n^)@cq}`&Lo)1KM{W+>5mSed zKp~=}$p7>~nK@va`vN{mYzWN1(tE=u2BZhga5(VtPKk(*TvE&zmn5vSbjo zZLVobTl%;t@6;4SsZ>5+U-XEGUZGG;+~|V(pE&qqrp_f~{_1h@5ZrNETqe{bt9ioZ z#Qn~gWCH!t#Ha^n&fT2?{`}D@s4?9kXj;E;lWV9Zw8_4yM0Qg-6YSsKgvQ*fF{#Pq z{=(nyV>#*`RloBVCs;Lp*R1PBIQOY=EK4CQa*BD0MsYcg=opP?8;xYQDSAJBeJpw5 zPBc_Ft9?;<0?pBhCmOtWU*pN*;CkjJ_}qVic`}V@$TwFi15!mF1*m2wVX+>5p%(+R zQ~JUW*zWkalde{90@2v+oVlkxOZFihE&ZJ){c?hX3L2@R7jk*xjYtHi=}qb+4B(XJ z$gYcNudR~4Kz_WRq8eS((>ALWCO)&R-MXE+YxDn9V#X{_H@j616<|P(8h(7z?q*r+ zmpqR#7+g$cT@e&(%_|ipI&A%9+47%30TLY(yuf&*knx1wNx|%*H^;YB%ftt%5>QM= z^i;*6_KTSRzQm%qz*>cK&EISvF^ovbS4|R%)zKhTH_2K>jP3mBGn5{95&G9^a#4|K zv+!>fIsR8z{^x4)FIr*cYT@Q4Z{y}};rLHL+atCgHbfX*;+k&37DIgENn&=k(*lKD zG;uL-KAdLn*JQ?@r6Q!0V$xXP=J2i~;_+i3|F;_En;oAMG|I-RX#FwnmU&G}w`7R{ z788CrR-g1DW4h_`&$Z`ctN~{A)Hv_-Bl!%+pfif8wN32rMD zJDs$eVWBYQx1&2sCdB0!vU5~uf)=vy*{}t{2VBpcz<+~h0wb7F3?V^44*&83Z2#F` z32!rd4>uc63rQP$3lTH3zb-47IGR}f)8kZ4JvX#toIpXH`L%NnPDE~$QI1)0)|HS4 zVcITo$$oWWwCN@E-5h>N?Hua!N9CYb6f8vTFd>h3q5Jg-lCI6y%vu{Z_Uf z$MU{{^o~;nD_@m2|E{J)q;|BK7rx%`m``+OqZAqAVj-Dy+pD4-S3xK?($>wn5bi90CFAQ+ACd;&m6DQB8_o zjAq^=eUYc1o{#+p+ zn;K<)Pn*4u742P!;H^E3^Qu%2dM{2slouc$AN_3V^M7H_KY3H)#n7qd5_p~Za7zAj|s9{l)RdbV9e||_67`#Tu*c<8!I=zb@ z(MSvQ9;Wrkq6d)!9afh+G`!f$Ip!F<4ADdc*OY-y7BZMsau%y?EN6*hW4mOF%Q~bw z2==Z3^~?q<1GTeS>xGN-?CHZ7a#M4kDL zQxQr~1ZMzCSKFK5+32C%+C1kE#(2L=15AR!er7GKbp?Xd1qkkGipx5Q~FI-6zt< z*PTpeVI)Ngnnyaz5noIIgNZtb4bQdKG{Bs~&tf)?nM$a;7>r36djllw%hQxeCXeW^ z(i6@TEIuxD<2ulwLTt|&gZP%Ei+l!(%p5Yij6U(H#HMkqM8U$@OKB|5@vUiuY^d6X zW}fP3;Kps6051OEO(|JzmVU6SX(8q>*yf*x5QoxDK={PH^F?!VCzES_Qs>()_y|jg6LJlJWp;L zKM*g5DK7>W_*uv}{0WUB0>MHZ#oJZmO!b3MjEc}VhsLD~;E-qNNd?x7Q6~v zR=0$u>Zc2Xr}>x_5$-s#l!oz6I>W?lw;m9Ae{Tf9eMX;TI-Wf_mZ6sVrMnY#F}cDd z%CV*}fDsXUF7Vbw>PuDaGhu631+3|{xp<@Kl|%WxU+vuLlcrklMC!Aq+7n~I3cmQ! z`e3cA!XUEGdEPSu``&lZEKD1IKO(-VGvcnSc153m(i!8ohi`)N2n>U_BemYJ`uY>8B*Epj!oXRLV}XK}>D*^DHQ7?NY*&LJ9VSo`Ogi9J zGa;clWI8vIQqkngv2>xKd91K>?0`Sw;E&TMg&6dcd20|FcTsnUT7Yn{oI5V4@Ow~m zz#k~8TM!A9L7T!|colrC0P2WKZW7PNj_X4MfESbt<-soq*0LzShZ}fyUx!(xIIDwx zRHt^_GAWe0-Vm~bDZ(}XG%E+`XhKpPlMBo*5q_z$BGxYef8O!ToS8aT8pmjbPq)nV z%x*PF5ZuSHRJqJ!`5<4xC*xb2vC?7u1iljB_*iUGl6+yPyjn?F?GOF2_KW&gOkJ?w z3e^qc-te;zez`H$rsUCE0<@7PKGW?7sT1SPYWId|FJ8H`uEdNu4YJjre`8F*D}6Wh z|FQ`xf7yiphHIAkU&OYCn}w^ilY@o4larl?^M7&8YI;hzBIsX|i3UrLsx{QDKwCX< zy;a>yjfJ6!sz`NcVi+a!Fqk^VE^{6G53L?@Tif|j!3QZ0fk9QeUq8CWI;OmO-Hs+F zuZ4sHLA3{}LR2Qlyo+{d@?;`tpp6YB^BMoJt?&MHFY!JQwoa0nTSD+#Ku^4b{5SZVFwU9<~APYbaLO zu~Z)nS#dxI-5lmS-Bnw!(u15by(80LlC@|ynj{TzW)XcspC*}z0~8VRZq>#Z49G`I zgl|C#H&=}n-ajxfo{=pxPV(L*7g}gHET9b*s=cGV7VFa<;Htgjk>KyW@S!|z`lR1( zGSYkEl&@-bZ*d2WQ~hw3NpP=YNHF^XC{TMG$Gn+{b6pZn+5=<()>C!N^jncl0w6BJ zdHdnmSEGK5BlMeZD!v4t5m7ct7{k~$1Ie3GLFoHjAH*b?++s<|=yTF+^I&jT#zuMx z)MLhU+;LFk8bse|_{j+d*a=&cm2}M?*arjBPnfPgLwv)86D$6L zLJ0wPul7IenMvVAK$z^q5<^!)7aI|<&GGEbOr=E;UmGOIa}yO~EIr5xWU_(ol$&fa zR5E(2vB?S3EvJglTXdU#@qfDbCYs#82Yo^aZN6`{Ex#M)easBTe_J8utXu(fY1j|R z9o(sQbj$bKU{IjyhosYahY{63>}$9_+hWxB3j}VQkJ@2$D@vpeRSldU?&7I;qd2MF zSYmJ>zA(@N_iK}m*AMPIJG#Y&1KR)6`LJ83qg~`Do3v^B0>fU&wUx(qefuTgzFED{sJ65!iw{F2}1fQ3= ziFIP{kezQxmlx-!yo+sC4PEtG#K=5VM9YIN0z9~c4XTX?*4e@m;hFM!zVo>A`#566 z>f&3g94lJ{r)QJ5m7Xe3SLau_lOpL;A($wsjHR`;xTXgIiZ#o&vt~ zGR6KdU$FFbLfZCC3AEu$b`tj!9XgOGLSV=QPIYW zjI!hSP#?8pn0@ezuenOzoka8!8~jXTbiJ6+ZuItsWW03uzASFyn*zV2kIgPFR$Yzm zE<$cZlF>R8?Nr2_i?KiripBc+TGgJvG@vRTY2o?(_Di}D30!k&CT`>+7ry2!!iC*X z<@=U0_C#16=PN7bB39w+zPwDOHX}h20Ap);dx}kjXX0-QkRk=cr};GYsjSvyLZa-t zzHONWddi*)RDUH@RTAsGB_#&O+QJaaL+H<<9LLSE+nB@eGF1fALwjVOl8X_sdOYme z0lk!X=S(@25=TZHR7LlPp}fY~yNeThMIjD}pd9+q=j<_inh0$>mIzWVY+Z9p<{D^#0Xk+b_@eNSiR8;KzSZ#7lUsk~NGMcB8C2c=m2l5paHPq`q{S(kdA7Z1a zyfk2Y;w?^t`?@yC5Pz9&pzo}Hc#}mLgDmhKV|PJ3lKOY(Km@Fi2AV~CuET*YfUi}u zfInZnqDX(<#vaS<^fszuR=l)AbqG{}9{rnyx?PbZz3Pyu!eSJK`uwkJU!ORQXy4x83r!PNgOyD33}}L=>xX_93l6njNTuqL8J{l%*3FVn3MG4&Fv*`lBXZ z?=;kn6HTT^#SrPX-N)4EZiIZI!0ByXTWy;;J-Tht{jq1mjh`DSy7yGjHxIaY%*sTx zuy9#9CqE#qi>1misx=KRWm=qx4rk|}vd+LMY3M`ow8)}m$3Ggv&)Ri*ON+}<^P%T5 z_7JPVPfdM=Pv-oH<tecoE}(0O7|YZc*d8`Uv_M*3Rzv7$yZnJE6N_W=AQ3_BgU_TjA_T?a)U1csCmJ&YqMp-lJe`y6>N zt++Bi;ZMOD%%1c&-Q;bKsYg!SmS^#J@8UFY|G3!rtyaTFb!5@e(@l?1t(87ln8rG? z--$1)YC~vWnXiW3GXm`FNSyzu!m$qT=Eldf$sMl#PEfGmzQs^oUd=GIQfj(X=}dw+ zT*oa0*oS%@cLgvB&PKIQ=Ok?>x#c#dC#sQifgMwtAG^l3D9nIg(Zqi;D%807TtUUCL3_;kjyte#cAg?S%e4S2W>9^A(uy8Ss0Tc++ZTjJw1 z&Em2g!3lo@LlDyri(P^I8BPpn$RE7n*q9Q-c^>rfOMM6Pd5671I=ZBjAvpj8oIi$! zl0exNl(>NIiQpX~FRS9UgK|0l#s@#)p4?^?XAz}Gjb1?4Qe4?j&cL$C8u}n)?A@YC zfmbSM`Hl5pQFwv$CQBF=_$Sq zxsV?BHI5bGZTk?B6B&KLdIN-40S426X3j_|ceLla*M3}3gx3(_7MVY1++4mzhH#7# zD>2gTHy*%i$~}mqc#gK83288SKp@y3wz1L_e8fF$Rb}ex+`(h)j}%~Ld^3DUZkgez zOUNy^%>>HHE|-y$V@B}-M|_{h!vXpk01xaD%{l{oQ|~+^>rR*rv9iQen5t?{BHg|% zR`;S|KtUb!X<22RTBA4AAUM6#M?=w5VY-hEV)b`!y1^mPNEoy2K)a>OyA?Q~Q*&(O zRzQI~y_W=IPi?-OJX*&&8dvY0zWM2%yXdFI!D-n@6FsG)pEYdJbuA`g4yy;qrgR?G z8Mj7gv1oiWq)+_$GqqQ$(ZM@#|0j7})=#$S&hZwdoijFI4aCFLVI3tMH5fLreZ;KD zqA`)0l~D2tuIBYOy+LGw&hJ5OyE+@cnZ0L5+;yo2pIMdt@4$r^5Y!x7nHs{@>|W(MzJjATyWGNwZ^4j+EPU0RpAl-oTM@u{lx*i0^yyWPfHt6QwPvYpk9xFMWfBFt!+Gu6TlAmr zeQ#PX71vzN*_-xh&__N`IXv6`>CgV#eA_%e@7wjgkj8jlKzO~Ic6g$cT`^W{R{606 zCDP~+NVZ6DMO$jhL~#+!g*$T!XW63#(ngDn#Qwy71yj^gazS{e;3jGRM0HedGD@pt z?(ln3pCUA(ekqAvvnKy0G@?-|-dh=eS%4Civ&c}s%wF@0K5Bltaq^2Os1n6Z3%?-Q zAlC4goQ&vK6TpgtzkHVt*1!tBYt-`|5HLV1V7*#45Vb+GACuU+QB&hZ=N_flPy0TY zR^HIrdskB#<$aU;HY(K{a3(OQa$0<9qH(oa)lg@Uf>M5g2W0U5 zk!JSlhrw8quBx9A>RJ6}=;W&wt@2E$7J=9SVHsdC?K(L(KACb#z)@C$xXD8^!7|uv zZh$6fkq)aoD}^79VqdJ!Nz-8$IrU(_-&^cHBI;4 z^$B+1aPe|LG)C55LjP;jab{dTf$0~xbXS9!!QdcmDYLbL^jvxu2y*qnx2%jbL%rB z{aP85qBJe#(&O~Prk%IJARcdEypZ)vah%ZZ%;Zk{eW(U)Bx7VlzgOi8)x z`rh4l`@l_Ada7z&yUK>ZF;i6YLGwI*Sg#Fk#Qr0Jg&VLax(nNN$u-XJ5=MsP3|(lEdIOJ7|(x3iY;ea)5#BW*mDV%^=8qOeYO&gIdJVuLLN3cFaN=xZtFB=b zH{l)PZl_j^u+qx@89}gAQW7ofb+k)QwX=aegihossZq*+@PlCpb$rpp>Cbk9UJO<~ zDjlXQ_Ig#W0zdD3&*ei(FwlN#3b%FSR%&M^ywF@Fr>d~do@-kIS$e%wkIVfJ|Ohh=zc zF&Rnic^|>@R%v?@jO}a9;nY3Qrg_!xC=ZWUcYiA5R+|2nsM*$+c$TOs6pm!}Z}dfM zGeBhMGWw3$6KZXav^>YNA=r6Es>p<6HRYcZY)z{>yasbC81A*G-le8~QoV;rtKnkx z;+os8BvEe?0A6W*a#dOudsv3aWs?d% z0oNngyVMjavLjtjiG`!007#?62ClTqqU$@kIY`=x^$2e>iqIy1>o|@Tw@)P)B8_1$r#6>DB_5 zmaOaoE~^9TolgDgooKFuEFB#klSF%9-~d2~_|kQ0Y{Ek=HH5yq9s zDq#1S551c`kSiWPZbweN^A4kWiP#Qg6er1}HcKv{fxb1*BULboD0fwfaNM_<55>qM zETZ8TJDO4V)=aPp_eQjX%||Ud<>wkIzvDlpNjqW>I}W!-j7M^TNe5JIFh#-}zAV!$ICOju8Kx)N z0vLtzDdy*rQN!7r>Xz7rLw8J-(GzQlYYVH$WK#F`i_i^qVlzTNAh>gBWKV@XC$T-` z3|kj#iCquDhiO7NKum07i|<-NuVsX}Q}mIP$jBJDMfUiaWR3c|F_kWBMw0_Sr|6h4 zk`_r5=0&rCR^*tOy$A8K;@|NqwncjZ>Y-75vlpxq%Cl3EgH`}^^~=u zoll6xxY@a>0f%Ddpi;=cY}fyG!K2N-dEyXXmUP5u){4VnyS^T4?pjN@Ot4zjL(Puw z_U#wMH2Z#8Pts{olG5Dy0tZj;N@;fHheu>YKYQU=4Bk|wcD9MbA`3O4bj$hNRHwzb zSLcG0SLV%zywdbuwl(^E_!@&)TdXge4O{MRWk2RKOt@!8E{$BU-AH(@4{gxs=YAz9LIob|Hzto0}9cWoz6Tp2x0&xi#$ zHh$dwO&UCR1Ob2w00-2eG7d4=cN(Y>0R#$q8?||q@iTi+7-w-xR%uMr&StFIthC<# zvK(aPduwuNB}oJUV8+Zl)%cnfsHI%4`;x6XW^UF^e4s3Z@S<&EV8?56Wya;HNs0E> z`$0dgRdiUz9RO9Au3RmYq>K#G=X%*_dUbSJHP`lSfBaN8t-~@F>)BL1RT*9I851A3 z<-+Gb#_QRX>~av#Ni<#zLswtu-c6{jGHR>wflhKLzC4P@b%8&~u)fosoNjk4r#GvC zlU#UU9&0Hv;d%g72Wq?Ym<&&vtA3AB##L}=ZjiTR4hh7J)e>ei} zt*u+>h%MwN`%3}b4wYpV=QwbY!jwfIj#{me)TDOG`?tI!%l=AwL2G@9I~}?_dA5g6 zCKgK(;6Q0&P&K21Tx~k=o6jwV{dI_G+Ba*Zts|Tl6q1zeC?iYJTb{hel*x>^wb|2RkHkU$!+S4OU4ZOKPZjV>9OVsqNnv5jK8TRAE$A&^yRwK zj-MJ3Pl?)KA~fq#*K~W0l4$0=8GRx^9+?w z!QT8*-)w|S^B0)ZeY5gZPI2G(QtQf?DjuK(s^$rMA!C%P22vynZY4SuOE=wX2f8$R z)A}mzJi4WJnZ`!bHG1=$lwaxm!GOnRbR15F$nRC-M*H<*VfF|pQw(;tbSfp({>9^5 zw_M1-SJ9eGF~m(0dvp*P8uaA0Yw+EkP-SWqu zqal$hK8SmM7#Mrs0@OD+%_J%H*bMyZiWAZdsIBj#lkZ!l2c&IpLu(5^T0Ge5PHzR} zn;TXs$+IQ_&;O~u=Jz+XE0wbOy`=6>m9JVG} zJ~Kp1e5m?K3x@@>!D)piw^eMIHjD4RebtR`|IlckplP1;r21wTi8v((KqNqn%2CB< zifaQc&T}*M&0i|LW^LgdjIaX|o~I$`owHolRqeH_CFrqCUCleN130&vH}dK|^kC>) z-r2P~mApHotL4dRX$25lIcRh_*kJaxi^%ZN5-GAAMOxfB!6flLPY-p&QzL9TE%ho( zRwftE3sy5<*^)qYzKkL|rE>n@hyr;xPqncY6QJ8125!MWr`UCWuC~A#G1AqF1@V$kv>@NBvN&2ygy*{QvxolkRRb%Ui zsmKROR%{*g*WjUUod@@cS^4eF^}yQ1>;WlGwOli z+Y$(8I`0(^d|w>{eaf!_BBM;NpCoeem2>J}82*!em=}}ymoXk>QEfJ>G(3LNA2-46 z5PGvjr)Xh9>aSe>vEzM*>xp{tJyZox1ZRl}QjcvX2TEgNc^(_-hir@Es>NySoa1g^ zFow_twnHdx(j?Q_3q51t3XI7YlJ4_q&(0#)&a+RUy{IcBq?)eaWo*=H2UUVIqtp&lW9JTJiP&u zw8+4vo~_IJXZIJb_U^&=GI1nSD%e;P!c{kZALNCm5c%%oF+I3DrA63_@4)(v4(t~JiddILp7jmoy+>cD~ivwoctFfEL zP*#2Rx?_&bCpX26MBgp^4G>@h`Hxc(lnqyj!*t>9sOBcXN(hTwEDpn^X{x!!gPX?1 z*uM$}cYRwHXuf+gYTB}gDTcw{TXSOUU$S?8BeP&sc!Lc{{pEv}x#ELX>6*ipI1#>8 zKes$bHjiJ1OygZge_ak^Hz#k;=od1wZ=o71ba7oClBMq>Uk6hVq|ePPt)@FM5bW$I z;d2Or@wBjbTyZj|;+iHp%Bo!Vy(X3YM-}lasMItEV_QrP-Kk_J4C>)L&I3Xxj=E?| zsAF(IfVQ4w+dRRnJ>)}o^3_012YYgFWE)5TT=l2657*L8_u1KC>Y-R{7w^S&A^X^U}h20jpS zQsdeaA#WIE*<8KG*oXc~$izYilTc#z{5xhpXmdT-YUnGh9v4c#lrHG6X82F2-t35} zB`jo$HjKe~E*W$=g|j&P>70_cI`GnOQ;Jp*JK#CT zuEGCn{8A@bC)~0%wsEv?O^hSZF*iqjO~_h|>xv>PO+?525Nw2472(yqS>(#R)D7O( zg)Zrj9n9$}=~b00=Wjf?E418qP-@8%MQ%PBiCTX=$B)e5cHFDu$LnOeJ~NC;xmOk# z>z&TbsK>Qzk)!88lNI8fOE2$Uxso^j*1fz>6Ot49y@=po)j4hbTIcVR`ePHpuJSfp zxaD^Dn3X}Na3@<_Pc>a;-|^Pon(>|ytG_+U^8j_JxP=_d>L$Hj?|0lz>_qQ#a|$+( z(x=Lipuc8p4^}1EQhI|TubffZvB~lu$zz9ao%T?%ZLyV5S9}cLeT?c} z>yCN9<04NRi~1oR)CiBakoNhY9BPnv)kw%*iv8vdr&&VgLGIs(-FbJ?d_gfbL2={- zBk4lkdPk~7+jIxd4{M(-W1AC_WcN&Oza@jZoj zaE*9Y;g83#m(OhA!w~LNfUJNUuRz*H-=$s*z+q+;snKPRm9EptejugC-@7-a-}Tz0 z@KHra#Y@OXK+KsaSN9WiGf?&jlZ!V7L||%KHP;SLksMFfjkeIMf<1e~t?!G3{n)H8 zQAlFY#QwfKuj;l@<$YDATAk;%PtD%B(0<|8>rXU< zJ66rkAVW_~Dj!7JGdGGi4NFuE?7ZafdMxIh65Sz7yQoA7fBZCE@WwysB=+`kT^LFX zz8#FlSA5)6FG9(qL3~A24mpzL@@2D#>0J7mMS1T*9UJ zvOq!!a(%IYY69+h45CE?(&v9H4FCr>gK0>mK~F}5RdOuH2{4|}k@5XpsX7+LZo^Qa4sH5`eUj>iffoBVm+ zz4Mtf`h?NW$*q1yr|}E&eNl)J``SZvTf6Qr*&S%tVv_OBpbjnA0&Vz#(;QmGiq-k! zgS0br4I&+^2mgA15*~Cd00cXLYOLA#Ep}_)eED>m+K@JTPr_|lSN}(OzFXQSBc6fM z@f-%2;1@BzhZa*LFV z-LrLmkmB%<<&jEURBEW>soaZ*rSIJNwaV%-RSaCZi4X)qYy^PxZ=oL?6N-5OGOMD2 z;q_JK?zkwQ@b3~ln&sDtT5SpW9a0q+5Gm|fpVY2|zqlNYBR}E5+ahgdj!CvK$Tlk0 z9g$5N;aar=CqMsudQV>yb4l@hN(9Jcc=1(|OHsqH6|g=K-WBd8GxZ`AkT?OO z-z_Ued-??Z*R4~L7jwJ%-`s~FK|qNAJ;EmIVDVpk{Lr7T4l{}vL)|GuUuswe9c5F| zv*5%u01hlv08?00Vpwyk*Q&&fY8k6MjOfpZfKa@F-^6d=Zv|0@&4_544RP5(s|4VPVP-f>%u(J@23BHqo2=zJ#v9g=F!cP((h zpt0|(s++ej?|$;2PE%+kc6JMmJjDW)3BXvBK!h!E`8Y&*7hS{c_Z?4SFP&Y<3evqf z9-ke+bSj$%Pk{CJlJbWwlBg^mEC^@%Ou?o>*|O)rl&`KIbHrjcpqsc$Zqt0^^F-gU2O=BusO+(Op}!jNzLMc zT;0YT%$@ClS%V+6lMTfhuzzxomoat=1H?1$5Ei7&M|gxo`~{UiV5w64Np6xV zVK^nL$)#^tjhCpTQMspXI({TW^U5h&Wi1Jl8g?P1YCV4=%ZYyjSo#5$SX&`r&1PyC zzc;uzCd)VTIih|8eNqFNeBMe#j_FS6rq81b>5?aXg+E#&$m++Gz9<+2)h=K(xtn}F ziV{rmu+Y>A)qvF}ms}4X^Isy!M&1%$E!rTO~5(p+8{U6#hWu>(Ll1}eD64Xa>~73A*538wry?v$vW z>^O#FRdbj(k0Nr&)U`Tl(4PI*%IV~;ZcI2z&rmq=(k^}zGOYZF3b2~Klpzd2eZJl> zB=MOLwI1{$RxQ7Y4e30&yOx?BvAvDkTBvWPpl4V8B7o>4SJn*+h1Ms&fHso%XLN5j z-zEwT%dTefp~)J_C8;Q6i$t!dnlh-!%haR1X_NuYUuP-)`IGWjwzAvp!9@h`kPZhf zwLwFk{m3arCdx8rD~K2`42mIN4}m%OQ|f)4kf%pL?Af5Ul<3M2fv>;nlhEPR8b)u} zIV*2-wyyD%%) zl$G@KrC#cUwoL?YdQyf9WH)@gWB{jd5w4evI& zOFF)p_D8>;3-N1z6mES!OPe>B^<;9xsh)){Cw$Vs-ez5nXS95NOr3s$IU;>VZSzKn zBvub8_J~I%(DozZW@{)Vp37-zevxMRZ8$8iRfwHmYvyjOxIOAF2FUngKj289!(uxY zaClWm!%x&teKmr^ABrvZ(ikx{{I-lEzw5&4t3P0eX%M~>$wG0ZjA4Mb&op+0$#SO_ z--R`>X!aqFu^F|a!{Up-iF(K+alKB{MNMs>e(i@Tpy+7Z-dK%IEjQFO(G+2mOb@BO zP>WHlS#fSQm0et)bG8^ZDScGnh-qRKIFz zfUdnk=m){ej0i(VBd@RLtRq3Ep=>&2zZ2%&vvf?Iex01hx1X!8U+?>ER;yJlR-2q4 z;Y@hzhEC=d+Le%=esE>OQ!Q|E%6yG3V_2*uh&_nguPcZ{q?DNq8h_2ahaP6=pP-+x zK!(ve(yfoYC+n(_+chiJ6N(ZaN+XSZ{|H{TR1J_s8x4jpis-Z-rlRvRK#U%SMJ(`C z?T2 zF(NNfO_&W%2roEC2j#v*(nRgl1X)V-USp-H|CwFNs?n@&vpRcj@W@xCJwR6@T!jt377?XjZ06=`d*MFyTdyvW!`mQm~t3luzYzvh^F zM|V}rO>IlBjZc}9Z zd$&!tthvr>5)m;5;96LWiAV0?t)7suqdh0cZis`^Pyg@?t>Ms~7{nCU;z`Xl+raSr zXpp=W1oHB*98s!Tpw=R5C)O{{Inl>9l7M*kq%#w9a$6N~v?BY2GKOVRkXYCgg*d

<5G2M1WZP5 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 F{|7XC?P&l2 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 6667917bd1..0f80bbf516 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Tue Apr 13 14:40:59 GET 2021 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip diff --git a/gradlew b/gradlew old mode 100755 new mode 100644 index cccdd3d517..4f906e0c81 --- a/gradlew +++ b/gradlew @@ -1,5 +1,21 @@ #!/usr/bin/env sh +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + ############################################################################## ## ## Gradle start up script for UN*X @@ -28,7 +44,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -66,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -109,10 +126,11 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath @@ -138,19 +156,19 @@ if $cygwin ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi @@ -159,14 +177,9 @@ save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } -APP_ARGS=$(save "$@") +APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index e95643d6a2..107acd32c4 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,84 +1,89 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/library-network/.gitignore b/library-network/.gitignore deleted file mode 100644 index 42afabfd2a..0000000000 --- a/library-network/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/library-network/build.gradle.kts b/library-network/build.gradle.kts deleted file mode 100644 index 1c4c3b147a..0000000000 --- a/library-network/build.gradle.kts +++ /dev/null @@ -1,56 +0,0 @@ -plugins { - id("com.android.library") - kotlin("android") -} - -android { - compileSdkVersion(30) - - defaultConfig { - minSdkVersion(16) - targetSdkVersion(30) - versionCode = 1 - versionName = "1.0" - - testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles("consumer-rules.pro") - } - - buildTypes { - getByName("release") { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") - } - } - compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 - } - - tasks.withType { - kotlinOptions { - jvmTarget = "1.8" - } - } - -} - -dependencies { - implementation(kotlin("stdlib")) - implementation("androidx.core:core-ktx:1.3.2") - - implementation("com.squareup.retrofit2:retrofit:2.9.0") - implementation("com.squareup.retrofit2:converter-moshi:2.9.0") - - implementation("com.squareup.moshi:moshi-kotlin:1.11.0") - implementation("com.squareup.moshi:moshi-kotlin-codegen:1.11.0") - implementation("com.squareup.moshi:moshi-adapters:1.11.0") - - implementation("com.squareup.okhttp3:logging-interceptor:4.9.1") - - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2") - - implementation("org.koin:koin-android:2.2.1") - implementation("org.koin:koin-android-viewmodel:2.2.1") - implementation("org.koin:koin-android-ext:2.2.1") -} \ No newline at end of file diff --git a/library-network/src/main/AndroidManifest.xml b/library-network/src/main/AndroidManifest.xml deleted file mode 100644 index 53d91c7c6c..0000000000 --- a/library-network/src/main/AndroidManifest.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/library-network/src/main/java/com/vanced/manager/library/network/di/NetworkModule.kt b/library-network/src/main/java/com/vanced/manager/library/network/di/NetworkModule.kt deleted file mode 100644 index c3d177c98d..0000000000 --- a/library-network/src/main/java/com/vanced/manager/library/network/di/NetworkModule.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.vanced.manager.library.network.di - -import com.vanced.manager.library.network.okhttp.interceptors.LOG_INTERCEPTOR -import com.vanced.manager.library.network.okhttp.interceptors.NO_CONNECT_INTERCEPTOR -import com.vanced.manager.library.network.okhttp.interceptors.loggingInterceptor -import com.vanced.manager.library.network.okhttp.interceptors.noConnectionInterceptor -import com.vanced.manager.library.network.providers.provideMoshi -import com.vanced.manager.library.network.providers.provideOkHttpClient -import com.vanced.manager.library.network.providers.provideRetrofit -import org.koin.android.BuildConfig -import org.koin.android.ext.koin.androidContext -import org.koin.core.qualifier.named -import org.koin.dsl.module - - -const val ORIGINAL = "ORIGINAL" - -val NetworkModule = module { - factory(named(LOG_INTERCEPTOR)) { loggingInterceptor() } - factory(named(NO_CONNECT_INTERCEPTOR)) { noConnectionInterceptor(androidContext()) } - - factory(named(ORIGINAL)) { - if (BuildConfig.DEBUG) { - provideOkHttpClient( - interceptors = listOf( - get(named(LOG_INTERCEPTOR)), - get(named(NO_CONNECT_INTERCEPTOR)) - ) - ) - } else { - provideOkHttpClient( - interceptors = listOf( - get(named(NO_CONNECT_INTERCEPTOR)) - ) - ) - } - } - - factory { provideMoshi() } - - factory(named(ORIGINAL)) { - provideRetrofit( - moshi = get(), - okHttpClient = get(named(ORIGINAL)), - url = "https://www.haliksar.fun" - ) - } -} \ No newline at end of file diff --git a/library-network/src/main/java/com/vanced/manager/library/network/okhttp/interceptors/LoggingInterceptor.kt b/library-network/src/main/java/com/vanced/manager/library/network/okhttp/interceptors/LoggingInterceptor.kt deleted file mode 100644 index adb21f390d..0000000000 --- a/library-network/src/main/java/com/vanced/manager/library/network/okhttp/interceptors/LoggingInterceptor.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.vanced.manager.library.network.okhttp.interceptors - -import okhttp3.Interceptor -import okhttp3.logging.HttpLoggingInterceptor -import okhttp3.logging.HttpLoggingInterceptor.Level - -const val LOG_INTERCEPTOR = "LOG_INTERCEPTOR" - -internal fun loggingInterceptor(): Interceptor = - HttpLoggingInterceptor().setLevel(Level.BODY) \ No newline at end of file diff --git a/library-network/src/main/java/com/vanced/manager/library/network/okhttp/interceptors/NoConnectionInterceptor.kt b/library-network/src/main/java/com/vanced/manager/library/network/okhttp/interceptors/NoConnectionInterceptor.kt deleted file mode 100644 index 125a445794..0000000000 --- a/library-network/src/main/java/com/vanced/manager/library/network/okhttp/interceptors/NoConnectionInterceptor.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.vanced.manager.library.network.okhttp.interceptors - -import android.content.Context -import android.net.ConnectivityManager -import android.net.NetworkCapabilities -import android.os.Build -import okhttp3.Interceptor - -class NoConnectException : Exception() - -const val NO_CONNECT_INTERCEPTOR = "NO_CONNECT_INTERCEPTOR" - -internal fun noConnectionInterceptor(context: Context) = Interceptor { chain -> - if (!isInternetAvailable(context)) { - throw NoConnectException() - } else { - chain.proceed(chain.request()) - } -} - -@Suppress("DEPRECATION") -private fun isInternetAvailable(context: Context): Boolean { - with(context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager) { - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - val networkCapabilities = activeNetwork ?: return false - val actNw = getNetworkCapabilities(networkCapabilities) ?: return false - when { - actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true - actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true - actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true - else -> false - } - } else { - when (activeNetworkInfo?.type) { - ConnectivityManager.TYPE_WIFI -> true - ConnectivityManager.TYPE_MOBILE -> true - ConnectivityManager.TYPE_ETHERNET -> true - else -> false - } - } - } -} \ No newline at end of file diff --git a/library-network/src/main/java/com/vanced/manager/library/network/providers/MoshiProvider.kt b/library-network/src/main/java/com/vanced/manager/library/network/providers/MoshiProvider.kt deleted file mode 100644 index 291b2d2597..0000000000 --- a/library-network/src/main/java/com/vanced/manager/library/network/providers/MoshiProvider.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.vanced.manager.library.network.providers - -import com.squareup.moshi.Moshi -import com.squareup.moshi.adapters.Rfc3339DateJsonAdapter -import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory -import java.util.* - -internal fun provideMoshi(): Moshi = Moshi.Builder() - .add(KotlinJsonAdapterFactory()) - .add(Date::class.java, Rfc3339DateJsonAdapter().nullSafe()) - .build() \ No newline at end of file diff --git a/library-network/src/main/java/com/vanced/manager/library/network/providers/OkHttpClientProvider.kt b/library-network/src/main/java/com/vanced/manager/library/network/providers/OkHttpClientProvider.kt deleted file mode 100644 index 80e0b7ce1c..0000000000 --- a/library-network/src/main/java/com/vanced/manager/library/network/providers/OkHttpClientProvider.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.vanced.manager.library.network.providers - -import okhttp3.Authenticator -import okhttp3.Interceptor -import okhttp3.OkHttpClient -import java.util.concurrent.TimeUnit - -private const val WaitTime = 0L -private const val ConnTime = 0L - -fun provideOkHttpClient( - interceptors: List = emptyList(), - authenticators: List = emptyList() -): OkHttpClient = - OkHttpClient.Builder() - .callTimeout(WaitTime, TimeUnit.SECONDS) - .readTimeout(WaitTime, TimeUnit.MILLISECONDS) - .connectTimeout(ConnTime, TimeUnit.MILLISECONDS) - .writeTimeout(WaitTime, TimeUnit.MILLISECONDS) - .apply { - interceptors.forEach { addInterceptor(it) } - authenticators.forEach { authenticator(it) } - } - .build() \ No newline at end of file diff --git a/library-network/src/main/java/com/vanced/manager/library/network/providers/RetrofitProvider.kt b/library-network/src/main/java/com/vanced/manager/library/network/providers/RetrofitProvider.kt deleted file mode 100644 index edafe26b2d..0000000000 --- a/library-network/src/main/java/com/vanced/manager/library/network/providers/RetrofitProvider.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.vanced.manager.library.network.providers - -import com.squareup.moshi.Moshi -import okhttp3.OkHttpClient -import retrofit2.Retrofit -import retrofit2.converter.moshi.MoshiConverterFactory -import kotlin.reflect.KClass - -fun provideRetrofit( - okHttpClient: OkHttpClient, - moshi: Moshi, - url: String -): Retrofit = Retrofit.Builder() - .addConverterFactory(MoshiConverterFactory.create(moshi)) - .client(okHttpClient) - .baseUrl(url) - .build() - -fun createService(service: KClass, baseurl: String): S { - return provideRetrofit( - provideOkHttpClient(), - provideMoshi(), - baseurl - ).create(service.java) -} \ No newline at end of file diff --git a/library-network/src/main/java/com/vanced/manager/library/network/service/RetrofitService.kt b/library-network/src/main/java/com/vanced/manager/library/network/service/RetrofitService.kt deleted file mode 100644 index 1dcb43ba98..0000000000 --- a/library-network/src/main/java/com/vanced/manager/library/network/service/RetrofitService.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.vanced.manager.library.network.service - -import retrofit2.Retrofit - -inline fun createRetrofitService(retrofit: Retrofit): T = - retrofit.create(T::class.java) \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index e7d18a0a03..7d945f68af 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,9 +1,3 @@ rootProject.name = "Vanced Manager" include(":app") - -include(":core-presentation", ":core-ui" , ":core-mvi") - -include(":feature-home") - -include(":library-network") From 6f86200a3a15650c5ff6e32faee85cdeaab7f6ce Mon Sep 17 00:00:00 2001 From: X1nto Date: Mon, 31 May 2021 15:40:24 +0400 Subject: [PATCH 002/118] switched to LiveData for viewmodel --- .../vanced/manager/ui/layouts/HomeLayout.kt | 8 +++++--- .../manager/ui/viewmodel/HomeViewModel.kt | 20 +++++++++++-------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt index 85da6594c3..7866509dac 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt @@ -6,7 +6,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember +import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -15,6 +15,7 @@ import com.google.accompanist.swiperefresh.SwipeRefresh import com.google.accompanist.swiperefresh.SwipeRefreshIndicator import com.google.accompanist.swiperefresh.rememberSwipeRefreshState import com.vanced.manager.R +import com.vanced.manager.domain.model.App import com.vanced.manager.domain.model.Link import com.vanced.manager.ui.composables.* import com.vanced.manager.ui.viewmodel.HomeViewModel @@ -68,7 +69,8 @@ private val socialMedia = listOf( @Preview fun HomeLayout() { val viewModel: HomeViewModel = getViewModel() - val refreshState = rememberSwipeRefreshState(isRefreshing = viewModel.isFetching) + val isFetching by viewModel.isFetching.observeAsState(false) + val refreshState = rememberSwipeRefreshState(isRefreshing = isFetching) SwipeRefresh( state = refreshState, onRefresh = { viewModel.fetch() }, @@ -84,7 +86,7 @@ fun HomeLayout() { ManagerScrollableColumn { HomeHeaderView(headerName = "Apps") { viewModel.apps.fastForEachIndexed { index, app -> - val rememberedApp by remember { app } + val rememberedApp by app.observeAsState(initial = App()) AppCard(rememberedApp) if (index != viewModel.apps.size - 1) { Spacer(modifier = Modifier.size(height = 8.dp, width = 0.dp)) diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt index bb7b9a25aa..c1a6c1c4be 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt @@ -3,6 +3,8 @@ package com.vanced.manager.ui.viewmodel import android.content.Context import android.util.Log import androidx.compose.runtime.* +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import androidx.preference.PreferenceManager.getDefaultSharedPreferences @@ -15,18 +17,19 @@ class HomeViewModel( private val repository: JsonRepository ) : ViewModel() { - private val vanced = mutableStateOf(App()) - private val music = mutableStateOf(App()) - private val microg = mutableStateOf(App()) - private var manager = mutableStateOf(App()) + private val vanced = MutableLiveData() + private val music = MutableLiveData() + private val microg = MutableLiveData() + private var manager = MutableLiveData() - var isFetching by mutableStateOf(false) + private val _isFetching = MutableLiveData() + val isFetching: LiveData = _isFetching - val apps = mutableStateListOf>() + val apps = mutableListOf>() fun fetch() { viewModelScope.launch { - isFetching = true + _isFetching.value = true try { with(repository.fetch()) { this@HomeViewModel.vanced.value = vanced @@ -37,12 +40,13 @@ class HomeViewModel( Log.d("HomeViewModel", "failed to fetch: $e") } - isFetching = false + _isFetching.value = false } } init { + val prefs = getDefaultSharedPreferences(context) val variant = prefs.getString("manager_variant", "nonroot") val vancedEnabled = prefs.getBoolean("manager_vanced_enabled", true) From d9ed25304f5c48296839d594287d55d838ed74d7 Mon Sep 17 00:00:00 2001 From: X1nto Date: Mon, 31 May 2021 17:36:26 +0400 Subject: [PATCH 003/118] updated links --- .../com/vanced/manager/di/DownloaderModule.kt | 4 +- .../com/vanced/manager/di/ServiceModule.kt | 4 +- .../com/vanced/manager/domain/model/Link.kt | 6 +- .../manager/network/model/AppDtoMapper.kt | 12 ++-- .../vanced/manager/network/util/Constants.kt | 22 +++++-- .../vanced/manager/ui/layouts/HomeLayout.kt | 46 +------------- .../com/vanced/manager/util/SocialLinks.kt | 61 +++++++++++++++++++ 7 files changed, 95 insertions(+), 60 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/util/SocialLinks.kt diff --git a/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt b/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt index e359bcbea0..e35a0a40b3 100644 --- a/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt +++ b/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt @@ -2,7 +2,7 @@ package com.vanced.manager.di import com.vanced.manager.downloader.impl.VancedDownloader import com.vanced.manager.downloader.api.VancedAPI -import com.vanced.manager.network.util.baseUrl +import com.vanced.manager.network.util.BASE import okhttp3.OkHttpClient import org.koin.dsl.module import retrofit2.Retrofit @@ -12,7 +12,7 @@ val downloaderModule = module { fun provideVancedAPI( okHttpClient: OkHttpClient ): VancedAPI = Retrofit.Builder() - .baseUrl(baseUrl) + .baseUrl(BASE) .client(okHttpClient) .build() .create(VancedAPI::class.java) diff --git a/app/src/main/java/com/vanced/manager/di/ServiceModule.kt b/app/src/main/java/com/vanced/manager/di/ServiceModule.kt index 4440b8f9ba..44c12581eb 100644 --- a/app/src/main/java/com/vanced/manager/di/ServiceModule.kt +++ b/app/src/main/java/com/vanced/manager/di/ServiceModule.kt @@ -2,7 +2,7 @@ package com.vanced.manager.di import com.google.gson.GsonBuilder import com.vanced.manager.network.JsonService -import com.vanced.manager.network.util.baseGithubUrl +import com.vanced.manager.network.util.BASE_GITHUB import okhttp3.OkHttpClient import org.koin.dsl.module import retrofit2.Retrofit @@ -12,7 +12,7 @@ val serviceModule = module { fun provideRetrofitService(okHttpClient: OkHttpClient): JsonService = Retrofit.Builder() - .baseUrl(baseGithubUrl) + .baseUrl(BASE_GITHUB) .addConverterFactory(GsonConverterFactory.create(GsonBuilder().create())) .client(okHttpClient) .build() diff --git a/app/src/main/java/com/vanced/manager/domain/model/Link.kt b/app/src/main/java/com/vanced/manager/domain/model/Link.kt index 182e0d57dc..080ba76d18 100644 --- a/app/src/main/java/com/vanced/manager/domain/model/Link.kt +++ b/app/src/main/java/com/vanced/manager/domain/model/Link.kt @@ -1,5 +1,9 @@ package com.vanced.manager.domain.model +import androidx.annotation.DrawableRes + data class Link( - val title: String + val title: String, + val link: String, + @DrawableRes val icon: Int ) diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt index 1d8d9ba40d..16e6657346 100644 --- a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt +++ b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt @@ -8,9 +8,9 @@ import com.vanced.manager.downloader.base.BaseDownloader import com.vanced.manager.downloader.impl.MicrogDownloader import com.vanced.manager.downloader.impl.MusicDownloader import com.vanced.manager.downloader.impl.VancedDownloader -import com.vanced.manager.network.util.microgName -import com.vanced.manager.network.util.musicName -import com.vanced.manager.network.util.vancedName +import com.vanced.manager.network.util.MICROG_NAME +import com.vanced.manager.network.util.MUSIC_NAME +import com.vanced.manager.network.util.VANCED_NAME class AppDtoMapper( private val packageInformationDataSource: PackageInformationDataSource, @@ -73,9 +73,9 @@ class AppDtoMapper( private fun getDownloader(app: String?): BaseDownloader? = when (app) { - vancedName -> vancedDownloader - musicName -> MusicDownloader - microgName -> MicrogDownloader + VANCED_NAME -> vancedDownloader + MUSIC_NAME -> MusicDownloader + MICROG_NAME -> MicrogDownloader else -> null } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/util/Constants.kt b/app/src/main/java/com/vanced/manager/network/util/Constants.kt index 2887e395e5..8837825e0d 100644 --- a/app/src/main/java/com/vanced/manager/network/util/Constants.kt +++ b/app/src/main/java/com/vanced/manager/network/util/Constants.kt @@ -1,8 +1,20 @@ package com.vanced.manager.network.util -const val baseUrl = "https://api.vancedapp.com/api/v1/" -const val baseGithubUrl = "https://x1nto.github.io/VancedFiles/" +const val BASE = "https://api.vancedapp.com/api/v1/" +const val BASE_GITHUB = "https://x1nto.github.io/VancedFiles/" -const val vancedName = "YouTube Vanced" -const val musicName = "YouTube Vanced Music" -const val microgName = "Vanced microG" \ No newline at end of file +const val VANCED_NAME = "YouTube Vanced" +const val MUSIC_NAME = "YouTube Vanced Music" +const val MICROG_NAME = "Vanced microG" + +const val BRAVE = "" +const val ADGUARD = "" + +const val INSTAGRAM = "https://instagram.com/vanced.youtube" +const val YOUTUBE = "https://youtube.com/c/YouTubeVanced" +const val GITHUB = "https://github.com/YTVanced/VancedManager" +const val WEBSITE = "https://vancedapp.com" +const val TELEGRAM = "https://t.me/joinchat/AAAAAEHf-pi4jH1SDlAL4w" +const val TWITTER = "https://twitter.com/YTVanced" +const val DISCORD = "https://discord.gg/WCGNdRruzb" +const val REDDIT = "https://www.reddit.com/r/Vanced/" \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt index 7866509dac..90f2c8b5c1 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt @@ -16,54 +16,12 @@ import com.google.accompanist.swiperefresh.SwipeRefreshIndicator import com.google.accompanist.swiperefresh.rememberSwipeRefreshState import com.vanced.manager.R import com.vanced.manager.domain.model.App -import com.vanced.manager.domain.model.Link import com.vanced.manager.ui.composables.* import com.vanced.manager.ui.viewmodel.HomeViewModel +import com.vanced.manager.util.socialMedia +import com.vanced.manager.util.sponsors import org.koin.androidx.compose.getViewModel -private val sponsors = listOf( - Link( - title = "Brave" - ), - Link( - title = "Adguard" - ) -) - -//Lol -private val socialMedia = listOf( - Link( - title = "Instagram" - ), - Link( - title = "Instagram" - ), - Link( - title = "Instagram" - ), - Link( - title = "Instagram" - ), - Link( - title = "Instagram" - ), - Link( - title = "Instagram" - ), - Link( - title = "Instagram" - ), - Link( - title = "Instagram" - ), - Link( - title = "Instagram" - ), - Link( - title = "Instagram" - ), -) - @ExperimentalAnimationApi @Composable @Preview diff --git a/app/src/main/java/com/vanced/manager/util/SocialLinks.kt b/app/src/main/java/com/vanced/manager/util/SocialLinks.kt new file mode 100644 index 0000000000..bea816310c --- /dev/null +++ b/app/src/main/java/com/vanced/manager/util/SocialLinks.kt @@ -0,0 +1,61 @@ +package com.vanced.manager.util + +import com.vanced.manager.R +import com.vanced.manager.domain.model.Link +import com.vanced.manager.network.util.* + +val sponsors = listOf( + Link( + title = "Brave", + link = BRAVE, + icon = R.drawable.ic_brave + ), + Link( + title = "Adguard", + link = ADGUARD, + icon = R.drawable.ic_adguard + ) +) + +val socialMedia = listOf( + Link( + title = "Instagram", + link = INSTAGRAM, + icon = R.drawable.ic_instagram + ), + Link( + title = "YouTube", + link = YOUTUBE, + icon = R.drawable.ic_youtube + ), + Link( + title = "GitHub", + link = GITHUB, + icon = R.drawable.ic_github + ), + Link( + title = "Website", + link = WEBSITE, + icon = R.drawable.ic_website + ), + Link( + title = "Telegram", + link = TELEGRAM, + icon = R.drawable.ic_telegram + ), + Link( + title = "Twitter", + link = TWITTER, + icon = R.drawable.ic_twitter + ), + Link( + title = "Discord", + link = DISCORD, + icon = R.drawable.ic_discord + ), + Link( + title = "Reddit", + link = REDDIT, + icon = R.drawable.ic_reddit + ), +) \ No newline at end of file From c6017fe248a699b6e86bec9c4a64d6b6a6b3b76d Mon Sep 17 00:00:00 2001 From: X1nto Date: Tue, 1 Jun 2021 13:48:17 +0400 Subject: [PATCH 004/118] organized strings --- app/src/main/res/values-af-rZA/strings.xml | 188 +++++++------- app/src/main/res/values-ar-rSA/strings.xml | 188 +++++++------- app/src/main/res/values-az-rAZ/strings.xml | 188 +++++++------- app/src/main/res/values-bg-rBG/strings.xml | 188 +++++++------- app/src/main/res/values-bn-rBD/strings.xml | 188 +++++++------- app/src/main/res/values-bn-rIN/strings.xml | 188 +++++++------- app/src/main/res/values-ca-rES/strings.xml | 188 +++++++------- app/src/main/res/values-ckb-rIR/strings.xml | 188 +++++++------- app/src/main/res/values-cs-rCZ/strings.xml | 188 +++++++------- app/src/main/res/values-da-rDK/strings.xml | 188 +++++++------- app/src/main/res/values-de-rDE/strings.xml | 188 +++++++------- app/src/main/res/values-el-rGR/strings.xml | 188 +++++++------- app/src/main/res/values-es-rES/strings.xml | 188 +++++++------- app/src/main/res/values-et-rEE/strings.xml | 188 +++++++------- app/src/main/res/values-fi-rFI/strings.xml | 188 +++++++------- app/src/main/res/values-fil-rPH/strings.xml | 188 +++++++------- app/src/main/res/values-fr-rFR/strings.xml | 188 +++++++------- app/src/main/res/values-hi-rIN/strings.xml | 188 +++++++------- app/src/main/res/values-hr-rHR/strings.xml | 188 +++++++------- app/src/main/res/values-hu-rHU/strings.xml | 188 +++++++------- app/src/main/res/values-in-rID/strings.xml | 188 +++++++------- app/src/main/res/values-it-rIT/strings.xml | 188 +++++++------- app/src/main/res/values-iw-rIL/strings.xml | 188 +++++++------- app/src/main/res/values-ja-rJP/strings.xml | 188 +++++++------- app/src/main/res/values-ka-rGE/strings.xml | 188 +++++++------- app/src/main/res/values-kmr-rTR/strings.xml | 188 +++++++------- app/src/main/res/values-ko-rKR/strings.xml | 188 +++++++------- app/src/main/res/values-ku-rTR/strings.xml | 188 +++++++------- app/src/main/res/values-lt-rLT/strings.xml | 188 +++++++------- app/src/main/res/values-ml-rIN/strings.xml | 188 +++++++------- app/src/main/res/values-mr-rIN/strings.xml | 188 +++++++------- app/src/main/res/values-nl-rNL/strings.xml | 188 +++++++------- app/src/main/res/values-no-rNO/strings.xml | 188 +++++++------- app/src/main/res/values-pa-rIN/strings.xml | 188 +++++++------- app/src/main/res/values-pa-rPK/strings.xml | 188 +++++++------- app/src/main/res/values-pl-rPL/strings.xml | 188 +++++++------- app/src/main/res/values-ps-rAF/strings.xml | 188 +++++++------- app/src/main/res/values-pt-rBR/strings.xml | 188 +++++++------- app/src/main/res/values-pt-rPT/strings.xml | 188 +++++++------- app/src/main/res/values-ro-rRO/strings.xml | 188 +++++++------- app/src/main/res/values-ru-rRU/strings.xml | 188 +++++++------- app/src/main/res/values-si-rLK/strings.xml | 188 +++++++------- app/src/main/res/values-sk-rSK/strings.xml | 188 +++++++------- app/src/main/res/values-so-rSO/strings.xml | 188 +++++++------- app/src/main/res/values-sr-rSP/strings.xml | 188 +++++++------- app/src/main/res/values-sv-rSE/strings.xml | 188 +++++++------- app/src/main/res/values-ta-rIN/strings.xml | 188 +++++++------- app/src/main/res/values-th-rTH/strings.xml | 188 +++++++------- app/src/main/res/values-tr-rTR/strings.xml | 188 +++++++------- app/src/main/res/values-uk-rUA/strings.xml | 188 +++++++------- app/src/main/res/values-vi-rVN/strings.xml | 188 +++++++------- app/src/main/res/values-zh-rCN/strings.xml | 188 +++++++------- app/src/main/res/values-zh-rTW/strings.xml | 188 +++++++------- app/src/main/res/values/resources.xml | 13 - app/src/main/res/values/strings.xml | 270 +++++++++++--------- 55 files changed, 5129 insertions(+), 5118 deletions(-) diff --git a/app/src/main/res/values-af-rZA/strings.xml b/app/src/main/res/values-af-rZA/strings.xml index 7aa9303bfc..a5ae4f4797 100644 --- a/app/src/main/res/values-af-rZA/strings.xml +++ b/app/src/main/res/values-af-rZA/strings.xml @@ -1,120 +1,120 @@ - What is your favourite song - Maak toe - A custom GMS Implementation for Vanced based on the microG Project. - A modified YouTube client with many useful features! - Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. - Herstel - Stoor - Select Your Apps + What is your favourite song + Maak toe + A custom GMS Implementation for Vanced based on the microG Project. + A modified YouTube client with many useful features! + Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. + Herstel + Stoor + Select Your Apps - Oor - Guide - Manager - Logs - Settings - Update Manager + Oor + Guide + Manager + Logs + Settings + Update Manager - Is Your Device Rooted? - Grant Root Permission - Let\'s get started - Select at least one app! - Don\'t know what this is or don\'t want to use the root version? just click the blue arrow below! + Is Your Device Rooted? + Grant Root Permission + Let\'s get started + Select at least one app! + Don\'t know what this is or don\'t want to use the root version? just click the blue arrow below! - About %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - Apps - Changelog - Downloading %1$s - Install + About %1$s + Download + Info + Launch + Reinstall + Uninstall + Update + Apps + Changelog + Downloading %1$s + Install Latest: - Install Vanced microG first + Install Vanced microG first Root access not granted - Social Media - Support us - Unavailable + Social Media + Support us + Unavailable Installed: - Accent Color - Appearance - Behavior - Clear downloaded files - Successfully cleared files - This lets us collect information about app performance and crash logs - Firebase Analytics - Language - Links will open in Chrome Custom Tabs - Use Chrome Custom Tabs - %1$s Push Notifications - Receive push notifications when an update for %1$s is released - Failed to save new time value - Root Script Sleep Time - Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues - System Default - Theme - Dark Theme - Light Theme - Manager Update Center - No new updates - Variant + Accent Color + Appearance + Behavior + Clear downloaded files + Successfully cleared files + This lets us collect information about app performance and crash logs + Firebase Analytics + Language + Links will open in Chrome Custom Tabs + Use Chrome Custom Tabs + %1$s Push Notifications + Receive push notifications when an update for %1$s is released + Failed to save new time value + Root Script Sleep Time + Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues + System Default + Theme + Dark Theme + Light Theme + Manager Update Center + No new updates + Variant - Could not save logs - Successfully saved logs + Could not save logs + Successfully saved logs Details - %1$s installation files detected! - Manager detected that all necessary files for %1$s installation were found. Do you want to install it? + %1$s installation files detected! + Manager detected that all necessary files for %1$s installation were found. Do you want to install it? %1$s Installation Preferences - Checking for updates… + Checking for updates… Language(s): %1$s Theme: %1$s Version: %1$s - Error - Guide - Stop! + Error + Guide + Stop! You are using the Magisk/TWRP version of Vanced, which is discontinued and cannot be updated using this app. Please remove it by removing the Magisk module/using TWRP Vanced uninstaller. - To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) - MIUI Optimizations are enabled! - Please do NOT exit the app during this process! - Redownload - Make sure that you downloaded the app from vancedapp.com, the Vanced Discord server, or the Vanced GitHub + To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) + MIUI Optimizations are enabled! + Please do NOT exit the app during this process! + Redownload + Make sure that you downloaded the app from vancedapp.com, the Vanced Discord server, or the Vanced GitHub Version - Welcome + Welcome - Choose your preferred language(s) for Vanced - Latest + Choose your preferred language(s) for Vanced + Latest Light + %1$s Select at least one language! - Black - Dark + Black + Dark - Manager Devs - Other Contributors - Sources - Vanced Team + Manager Devs + Other Contributors + Sources + Vanced Team - Failed to `chown` APK to system owner, please try again. - Error Downloading %1$s + Failed to `chown` APK to system owner, please try again. + Error Downloading %1$s Failed to apply new accent color - Failed to uninstall package %1$s - Failed to locate the required files for installation. Re-download the installation files, then try again. - Failed to locate apk file for black/dark theme from storage, please try again. - Installation failed because the user aborted the installation. - Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. - Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. - Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu - Installation failed because the installation file is incompatible with your device. Clear downloaded files in the Settings, then try again. - Installation failed because the apk files are corrupted, please try again. - Installation failed because MIUI Optimization is enabled. Disable MIUI Optimization, then try again. - Installation failed because apk signature verification is enabled. Disable apk signature verification, then try again. - Installation failed because the device doesn\'t have enough free space. - Failed to find apk file for black/dark theme from the installer. Clear app data of Manager, then try again. - Failed to locate the stock YouTube installation path after split installation. + Failed to uninstall package %1$s + Failed to locate the required files for installation. Re-download the installation files, then try again. + Failed to locate apk file for black/dark theme from storage, please try again. + Installation failed because the user aborted the installation. + Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. + Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. + Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu + Installation failed because the installation file is incompatible with your device. Clear downloaded files in the Settings, then try again. + Installation failed because the apk files are corrupted, please try again. + Installation failed because MIUI Optimization is enabled. Disable MIUI Optimization, then try again. + Installation failed because apk signature verification is enabled. Disable apk signature verification, then try again. + Installation failed because the device doesn\'t have enough free space. + Failed to find apk file for black/dark theme from the installer. Clear app data of Manager, then try again. + Failed to locate the stock YouTube installation path after split installation. diff --git a/app/src/main/res/values-ar-rSA/strings.xml b/app/src/main/res/values-ar-rSA/strings.xml index b7ebc2ab20..47bb521c4f 100644 --- a/app/src/main/res/values-ar-rSA/strings.xml +++ b/app/src/main/res/values-ar-rSA/strings.xml @@ -1,120 +1,120 @@ - إلغاء - إغلاق - نسخة خاصة من خدمات جوجل للجوال معدة خصيصا لتطبيق ڤانسد بناءً على مشروع microG. - تطبيق يوتيوب معدل مع العديد من الميزات المفيدة! - ڤانسد لموسيقى يوتيوب! يلبي احتياجاتك حتى وان كان يضم ميزات اقل من ڤانسد. - إعادة تعيين - حفظ - اختر تطبيقاتك + إلغاء + إغلاق + نسخة خاصة من خدمات جوجل للجوال معدة خصيصا لتطبيق ڤانسد بناءً على مشروع microG. + تطبيق يوتيوب معدل مع العديد من الميزات المفيدة! + ڤانسد لموسيقى يوتيوب! يلبي احتياجاتك حتى وان كان يضم ميزات اقل من ڤانسد. + إعادة تعيين + حفظ + اختر تطبيقاتك - حول - دليل الاستخدام - المدير - السجلات - الإعدادات - تحديث المدير + حول + دليل الاستخدام + المدير + السجلات + الإعدادات + تحديث المدير - هل جهازك مروت؟ - امنح صلاحيات الروت - فلنبدأ - اختر تطبيقاً واحداً على الأقل! - لا تعرف ما هذا أو لا تود استخدام نسخة الروت؟ اضغط على السهم الأزرق في الأسفل! + هل جهازك مروت؟ + امنح صلاحيات الروت + فلنبدأ + اختر تطبيقاً واحداً على الأقل! + لا تعرف ما هذا أو لا تود استخدام نسخة الروت؟ اضغط على السهم الأزرق في الأسفل! - حول %1$s - تنزيل - المعلومات - تشغيل - أعد التثبيت - إلغاء التثبيت - تحديث - التطبيقات - سجل التغييرات - جارٍ تنزيل %1$s - تثبيت + حول %1$s + تنزيل + المعلومات + تشغيل + أعد التثبيت + إلغاء التثبيت + تحديث + التطبيقات + سجل التغييرات + جارٍ تنزيل %1$s + تثبيت الأحدث: - قم بتثبيت Vanced microG أولاً + قم بتثبيت Vanced microG أولاً لم يتم منح صلاحيات الروت - وسائل التواصل الإجتماعي - ادعمنا - غير متاح + وسائل التواصل الإجتماعي + ادعمنا + غير متاح مثبت: - الألوان - المظهر - السلوك - مسح الملفات التي تم تنزيلها - تم مسح الملفات بنجاح - هذا يتيح لنا جمع المعلومات عن أداء التطبيق وسجلات الأعطال - تحليلات Firebase - اللغة - سيتم فتح الروابط في علامات تبويب مخصصة لمتصفح كروم - استخدم علامات تبويب مخصصة لمتصفح كروم - إشعارات %1$s - تلقي الإشعارات عند إصدار تحديث لـ %1$s - فشل في حفظ القيمة الزمنية الجديدة - Script sleep time للروت - ضبط القيمة الزمنية للنوم المستخدمة في /data/adb/service.d/app.sh script، مفيد لإصلاح مشاكل التركيب - الوضع الافتراضي - السمة - السمة الداكنة - السمة الفاتحة - مركز التحديث - لا توجد تحديثات جديدة - النوع + الألوان + المظهر + السلوك + مسح الملفات التي تم تنزيلها + تم مسح الملفات بنجاح + هذا يتيح لنا جمع المعلومات عن أداء التطبيق وسجلات الأعطال + تحليلات Firebase + اللغة + سيتم فتح الروابط في علامات تبويب مخصصة لمتصفح كروم + استخدم علامات تبويب مخصصة لمتصفح كروم + إشعارات %1$s + تلقي الإشعارات عند إصدار تحديث لـ %1$s + فشل في حفظ القيمة الزمنية الجديدة + Script sleep time للروت + ضبط القيمة الزمنية للنوم المستخدمة في /data/adb/service.d/app.sh script، مفيد لإصلاح مشاكل التركيب + الوضع الافتراضي + السمة + السمة الداكنة + السمة الفاتحة + مركز التحديث + لا توجد تحديثات جديدة + النوع - تعذر حفظ السجل - تم حفظ السجل بنجاح + تعذر حفظ السجل + تم حفظ السجل بنجاح التفاصيل - تم اكتشاف ملفات تثبيت %1$s! - اكتشف المدير أن جميع الملفات اللازمة لتثبيت %1$s موجودة. هل تريد التثبيت؟ + تم اكتشاف ملفات تثبيت %1$s! + اكتشف المدير أن جميع الملفات اللازمة لتثبيت %1$s موجودة. هل تريد التثبيت؟ تفضيلات تثبيت %1$s - جارٍ التحقق من وجود تحديثات… + جارٍ التحقق من وجود تحديثات… اللغة/اللغات: %1$s السمة: %1$s الإصدار: %1$s - خطأ - الدليل - إيقاف! + خطأ + الدليل + إيقاف! يبدو أنك تستخدم إصدار ماجيسك/TWRP من ڤانسد، الذي قد تم إيقافه ولا يمكن تحديثه بإستخدام هذا التطبيق. الرجاء إزالته أولاً من قائمة إضافات ماجيسك أو بإستخدام أداة إلغاء تثبيت ڤانسد من TWRP. - من أجل تثبيت ڤانسد، عليك تعطيل تحسينات MIUI في إعدادات المطور. (يمكنك تجاهل هذه الرسالة إذا كنت تستخدم نسخة رقم 20.2.20 أو أجدد تستند إلى نسخة نظام شاومي أوروبا) - تحسينات MIUI مفعلة! - الرجاء عدم الخروج من التطبيق أثناء هذه العملية! - إعادة التنزيل - تأكد من أنك قمت بتنزيل التطبيق من موقع vancedapp.com، أو خادم الديسكورد لڤانسد أو Vanced GitHub + من أجل تثبيت ڤانسد، عليك تعطيل تحسينات MIUI في إعدادات المطور. (يمكنك تجاهل هذه الرسالة إذا كنت تستخدم نسخة رقم 20.2.20 أو أجدد تستند إلى نسخة نظام شاومي أوروبا) + تحسينات MIUI مفعلة! + الرجاء عدم الخروج من التطبيق أثناء هذه العملية! + إعادة التنزيل + تأكد من أنك قمت بتنزيل التطبيق من موقع vancedapp.com، أو خادم الديسكورد لڤانسد أو Vanced GitHub الإصدار - مرحباً بك + مرحباً بك - اختر لغتك(لغاتك) المفضلة لڤانسد - الأحدث + اختر لغتك(لغاتك) المفضلة لڤانسد + الأحدث فاتح + %1$s اختر لغة واحدة على الأقل! - أسود - داكن + أسود + داكن - مطوري المدير - مساهمين آخرين - المصادر - فريق ڤانسد + مطوري المدير + مساهمين آخرين + المصادر + فريق ڤانسد - فشل تغيير ملكية حزمة التثبيت الى مالك النظام، الرجاء المحاولة مرة أخرى. - خطأ في تنزيل %1$s + فشل تغيير ملكية حزمة التثبيت الى مالك النظام، الرجاء المحاولة مرة أخرى. + خطأ في تنزيل %1$s فشل تطبيق لون النسق الجديد - فشل في الغاء تثبيت حزمة %1$s - فشل العثور على الملفات المطلوبة للتثبيت. أعد تحميل ملفات التثبيت، ثم حاول مرة أخرى. - فشل العثور على حزمة تثبيت السمة السوداء/المظلمة من وحدة التخزين، الرجاء المحاولة مرة أخرى. - فشل التثبيت لأن المستخدم ألغى التثبيت. - فشل التثبيت، لأن هذا التطبيق يتعارض مع تطبيق مثبت بالفعل. قم بإلغاء تثبيت الإصدار الحالي من Vanced، ثم حاول مرة أخرى. - فشل التثبيت لأن المستخدم حاول تثبيت إصدار قديم. قم بألغاء تثبيت التحديثات الخاصة باليوتيوب الأصلي، ثم حاول مرة أخرى. - فشل التثبيت لأسباب غير معروفة، انضم إلى تيليجرام أو ديسكورد لمزيد من الدعم. يرجى أيضاً إرفاق لقطة الشاشة من القائمة المتقدمة - فشل التثبيت لأن ملف التثبيت غير متوافق مع جهازك. امسح الملفات التي تم تنزيلها في الإعدادات، ثم حاول مرة أخرى. - فشل التثبيت لأن حزم التثبيت تالفة، الرجاء المحاولة مرة أخرى. - فشل التثبيت لأن تحسينات MIUI مفعلة. قم بتعطيل تحسينات MIUI ، ثم حاول مرة أخرى. - فشل التثبيت لأن التحقق من توقيع حزم التثبيت مفعل. الرجاء تعطيل التحقق من توقيع حزم التثبيت, ثم المحاولة مرة أخرى. - فشل التثبيت، مساحة جهازك الخالية لا تكفي. - فشل العثور على حزمة التثبيت للسمة السوداء/المظلمة من المثبت. امسح بيانات التطبيق لمدير ڤانسد، ثم حاول مرة أخرى. - فشل تحديد مسار تثبيت اليوتيوب الأصلي بعد تثبيت الحزم المنفصلة. + فشل في الغاء تثبيت حزمة %1$s + فشل العثور على الملفات المطلوبة للتثبيت. أعد تحميل ملفات التثبيت، ثم حاول مرة أخرى. + فشل العثور على حزمة تثبيت السمة السوداء/المظلمة من وحدة التخزين، الرجاء المحاولة مرة أخرى. + فشل التثبيت لأن المستخدم ألغى التثبيت. + فشل التثبيت، لأن هذا التطبيق يتعارض مع تطبيق مثبت بالفعل. قم بإلغاء تثبيت الإصدار الحالي من Vanced، ثم حاول مرة أخرى. + فشل التثبيت لأن المستخدم حاول تثبيت إصدار قديم. قم بألغاء تثبيت التحديثات الخاصة باليوتيوب الأصلي، ثم حاول مرة أخرى. + فشل التثبيت لأسباب غير معروفة، انضم إلى تيليجرام أو ديسكورد لمزيد من الدعم. يرجى أيضاً إرفاق لقطة الشاشة من القائمة المتقدمة + فشل التثبيت لأن ملف التثبيت غير متوافق مع جهازك. امسح الملفات التي تم تنزيلها في الإعدادات، ثم حاول مرة أخرى. + فشل التثبيت لأن حزم التثبيت تالفة، الرجاء المحاولة مرة أخرى. + فشل التثبيت لأن تحسينات MIUI مفعلة. قم بتعطيل تحسينات MIUI ، ثم حاول مرة أخرى. + فشل التثبيت لأن التحقق من توقيع حزم التثبيت مفعل. الرجاء تعطيل التحقق من توقيع حزم التثبيت, ثم المحاولة مرة أخرى. + فشل التثبيت، مساحة جهازك الخالية لا تكفي. + فشل العثور على حزمة التثبيت للسمة السوداء/المظلمة من المثبت. امسح بيانات التطبيق لمدير ڤانسد، ثم حاول مرة أخرى. + فشل تحديد مسار تثبيت اليوتيوب الأصلي بعد تثبيت الحزم المنفصلة. diff --git a/app/src/main/res/values-az-rAZ/strings.xml b/app/src/main/res/values-az-rAZ/strings.xml index 58abdd25cc..7e100b2e17 100644 --- a/app/src/main/res/values-az-rAZ/strings.xml +++ b/app/src/main/res/values-az-rAZ/strings.xml @@ -1,120 +1,120 @@ - İmtina - Bağla - microG Layihəsi əsasında Vanced üçün təkmilləşdirilmiş özəl bir GMS tətbiqi. - Çoxlu faydalı özəllikləri ilə modifikasiya edilmiş YouTube versiyası! - Yenə Vanced, ancaq YouTube Msuic üçün! Nisbətən daha az özəlliyi olsa da, ehtiyaclarınızı qarşılayacaq. - Sıfırla - Saxla - Tətbiqlərinizi Seçin + İmtina + Bağla + microG Layihəsi əsasında Vanced üçün təkmilləşdirilmiş özəl bir GMS tətbiqi. + Çoxlu faydalı özəllikləri ilə modifikasiya edilmiş YouTube versiyası! + Yenə Vanced, ancaq YouTube Msuic üçün! Nisbətən daha az özəlliyi olsa da, ehtiyaclarınızı qarşılayacaq. + Sıfırla + Saxla + Tətbiqlərinizi Seçin - Haqqında - Bələdçi - Menecer - Qeydlər - Tənzimləmələr - Yeniləmə Meneceri + Haqqında + Bələdçi + Menecer + Qeydlər + Tənzimləmələr + Yeniləmə Meneceri - Cihazınızda root varmı? - Root İcazəsi Ver - Gəlin başlayaq - Ən azı bir tətbiq seçin! - Root versiyasının nə olduğunu bilmirsiz ya da sadəcə istifadə etmək istəmirsiz? onda aşağıdakı göy oxa toxunun! + Cihazınızda root varmı? + Root İcazəsi Ver + Gəlin başlayaq + Ən azı bir tətbiq seçin! + Root versiyasının nə olduğunu bilmirsiz ya da sadəcə istifadə etmək istəmirsiz? onda aşağıdakı göy oxa toxunun! - %1$s Haqqında - Download - Info - Launch - Reinstall - Uninstall - Update - Tətbiqlər - Dəyişikliklər - %1$s endirilir - Quraşdır + %1$s Haqqında + Download + Info + Launch + Reinstall + Uninstall + Update + Tətbiqlər + Dəyişikliklər + %1$s endirilir + Quraşdır Ən son: - Əvvəlcə Vanced microG-ni quraşdırın + Əvvəlcə Vanced microG-ni quraşdırın Root icazəsi verilməyib - Sosial Media - Bizi dəstəklə - Əlçatmazdır + Sosial Media + Bizi dəstəklə + Əlçatmazdır Qurulan: - Tema rəngi - Görünüş - Davranış - Endirilmiş faylları təmizlə - Fayllar uğurla təmizləndi - Bu bizə tətbiq performansı və çökmə jurnalı haqqında məlumat yığmağa imkan verir - Firebase Analitikləri - Dil - Bağlantılar Chrome Özəl Vərəqlərində açılacaq - Chrome Özəl Vərəqlərini istifadə et - %1$s Ani Bildirişlər - %1$s üçün yeni buraxılış olanda ani bildirişlər alın - Yeni vaxt qiymətini saxlamaq olmadı - Root Qoşma Gözləmə Müddəti - /data/adb/service.d/app.sh kodundakı yuxu vaxtı qiymətini nizamlayın, bu qoşma xətalarını aradan qaldırmağa kömək edəcək - İlkin Sistem - Mövzu - Tünd mövzu - Açıq mövzu - Menecer Yeniləmə Mərkəzi - Yeniləmə yoxdur - Variant + Tema rəngi + Görünüş + Davranış + Endirilmiş faylları təmizlə + Fayllar uğurla təmizləndi + Bu bizə tətbiq performansı və çökmə jurnalı haqqında məlumat yığmağa imkan verir + Firebase Analitikləri + Dil + Bağlantılar Chrome Özəl Vərəqlərində açılacaq + Chrome Özəl Vərəqlərini istifadə et + %1$s Ani Bildirişlər + %1$s üçün yeni buraxılış olanda ani bildirişlər alın + Yeni vaxt qiymətini saxlamaq olmadı + Root Qoşma Gözləmə Müddəti + /data/adb/service.d/app.sh kodundakı yuxu vaxtı qiymətini nizamlayın, bu qoşma xətalarını aradan qaldırmağa kömək edəcək + İlkin Sistem + Mövzu + Tünd mövzu + Açıq mövzu + Menecer Yeniləmə Mərkəzi + Yeniləmə yoxdur + Variant - Qeydləri saxlamaq olmadı - Qeydlər uğurla saxlandı + Qeydləri saxlamaq olmadı + Qeydlər uğurla saxlandı Təfsilatlar - %1$s quraşdırma faylı aşkarlandı! - Menecer %1$s quraşdırması üçün lazımi bütün faylların tapıldığını aşkarladı. Quraşdırmaq istəyirsiniz? + %1$s quraşdırma faylı aşkarlandı! + Menecer %1$s quraşdırması üçün lazımi bütün faylların tapıldığını aşkarladı. Quraşdırmaq istəyirsiniz? %1$s Qurma Seçimləri - Yeniləmələr yoxlanılır… + Yeniləmələr yoxlanılır… Dil(lər): %1$s Mövzu: %1$s Versiya: %1$s - Xəta - Bələdçi - Dayandır! + Xəta + Bələdçi + Dayandır! Buraxılışı dayandırılan və bu tətbiq istifadə edərək yenilənə bilməyən Vanced-in Magisk/TWRP versiyasını istifadə edirsiniz. Zəhmət olmasa magisk modulunu/TWRP Vanced silici istifadə edərək silin. - Vanced-i quraşdırmaq üçün tərtibatçı tənzimləmələrindən MIUI Optimallaşdırmasını sıradan çıxartmaq LAZIMDIR. (20.2.20 və ya yuxarı xiaomi.eu əsaslı ROM istifadə edirsinizsə bu xəbərdarlığı nəzərə almaya bilərsiniz) - MIUI Optimizasiyaları açıqdır! - Xahiş olunur iş gedərkən tətbiqi TƏRK ETMƏYİN! - Yenidən endir - Tətbiqi vancedapp.com, Vanced Discord server və ya Vanced GitHub\'dan endirdiyinizə əmin olun + Vanced-i quraşdırmaq üçün tərtibatçı tənzimləmələrindən MIUI Optimallaşdırmasını sıradan çıxartmaq LAZIMDIR. (20.2.20 və ya yuxarı xiaomi.eu əsaslı ROM istifadə edirsinizsə bu xəbərdarlığı nəzərə almaya bilərsiniz) + MIUI Optimizasiyaları açıqdır! + Xahiş olunur iş gedərkən tətbiqi TƏRK ETMƏYİN! + Yenidən endir + Tətbiqi vancedapp.com, Vanced Discord server və ya Vanced GitHub\'dan endirdiyinizə əmin olun Versiya - Xoş gəlmisiniz + Xoş gəlmisiniz - Vanced üçün istədiyiniz dili seçin - Ən son + Vanced üçün istədiyiniz dili seçin + Ən son İşıqlı + %1$s Ən azı bir dil seçin! - Qara - Qaranlıq + Qara + Qaranlıq - Menecer Tərtibatçıları - Digər Dəstəkçilər - Mənbələr - Vanced Birliyi + Menecer Tərtibatçıları + Digər Dəstəkçilər + Mənbələr + Vanced Birliyi - Apk, sistem sahibinə dəyişdirilmədi, yenidən sınayın. - %1$s Yüklənərkən xəta + Apk, sistem sahibinə dəyişdirilmədi, yenidən sınayın. + %1$s Yüklənərkən xəta Yeni ikinci rəngi təyin etmək alınmadı - %1$s paketini silmək olmur - Quraşdırmaq üçün lazımi fayllar tapılmadı. Quraşdırma fayllarını yenidən endirib təkrar sınayın. - Anbarda qara/tünd mövzu üçün apk faylı tapılmadı, yenidən sınayın. - İstifadəçi quraşdırmanı ləğv etdiyi üçün quraşdırılma uğursuz oldu. - Tətbiq əvvəlcədən quraşdırılmış bir tətbiqlə toqquşduğu üçün quraşdırılma uğursuz oldu. Vanced-in cari versiyasını silib yenidən sınayın. - İstifadəçi paketi alt versiyaya keçirməyə çalışdığı üçün quraşdırılma uğursuz oldu. Stok YouTube tətbiqindən yeniləmələri silib yenidən sınayın. - Bilinməyən səbəblərdən qurma alınmadı, əlavə yardım üçün Telegram və ya Discordumuza qoşulun. Xahiş olunur Qabaqcıl bölməsindən ekran görüntüsü də əlavə edin - Quraşdırma faylı cihazınıza uyğun gəlmədiyi üçün quraşdırılma uğursuz oldu. Tənzimləmələrdən endirilmiş faylları təmizləyib yenidən sınayın. - Apk faylları zədəli olduğu üçün quraşdırılma uğursuz oldu, yenidən sınayın. - MIUI Optimallaşdırma fəal olduğu üçün quraşdırılma uğursuz oldu. MIUI Optimallaşdırmanı sıradan çıxarıb yenidən sınayın. - Apk imza təsdiqləmə fəal olduğu üçün quraşdırılma uğursuz oldu. Apk imza təsdiqləməsini sıradan çıxarıb yenidən sınayın. - Cihazda yaddaş az olduğundan qurma alınmadı. - Quraşdırıcıda qara/tünd tema üçün apk faylı tapılmadı. Menecer-in tətbiq verilənlərini təmizləyib yenidən sınayın. - Ayrılmış quraşdırmadan sonra stok YouTube quraşdırma yolu tapılmadı. + %1$s paketini silmək olmur + Quraşdırmaq üçün lazımi fayllar tapılmadı. Quraşdırma fayllarını yenidən endirib təkrar sınayın. + Anbarda qara/tünd mövzu üçün apk faylı tapılmadı, yenidən sınayın. + İstifadəçi quraşdırmanı ləğv etdiyi üçün quraşdırılma uğursuz oldu. + Tətbiq əvvəlcədən quraşdırılmış bir tətbiqlə toqquşduğu üçün quraşdırılma uğursuz oldu. Vanced-in cari versiyasını silib yenidən sınayın. + İstifadəçi paketi alt versiyaya keçirməyə çalışdığı üçün quraşdırılma uğursuz oldu. Stok YouTube tətbiqindən yeniləmələri silib yenidən sınayın. + Bilinməyən səbəblərdən qurma alınmadı, əlavə yardım üçün Telegram və ya Discordumuza qoşulun. Xahiş olunur Qabaqcıl bölməsindən ekran görüntüsü də əlavə edin + Quraşdırma faylı cihazınıza uyğun gəlmədiyi üçün quraşdırılma uğursuz oldu. Tənzimləmələrdən endirilmiş faylları təmizləyib yenidən sınayın. + Apk faylları zədəli olduğu üçün quraşdırılma uğursuz oldu, yenidən sınayın. + MIUI Optimallaşdırma fəal olduğu üçün quraşdırılma uğursuz oldu. MIUI Optimallaşdırmanı sıradan çıxarıb yenidən sınayın. + Apk imza təsdiqləmə fəal olduğu üçün quraşdırılma uğursuz oldu. Apk imza təsdiqləməsini sıradan çıxarıb yenidən sınayın. + Cihazda yaddaş az olduğundan qurma alınmadı. + Quraşdırıcıda qara/tünd tema üçün apk faylı tapılmadı. Menecer-in tətbiq verilənlərini təmizləyib yenidən sınayın. + Ayrılmış quraşdırmadan sonra stok YouTube quraşdırma yolu tapılmadı. diff --git a/app/src/main/res/values-bg-rBG/strings.xml b/app/src/main/res/values-bg-rBG/strings.xml index ce80bb6bf0..533b2a9acf 100644 --- a/app/src/main/res/values-bg-rBG/strings.xml +++ b/app/src/main/res/values-bg-rBG/strings.xml @@ -1,120 +1,120 @@ - Отказ - Затвори - Персонализирано внедряване на GMS за Vanced въз основа на проекта microG. - Модифициран клиент за YouTube с много полезни функции! - Vanced, но за YouTube Music! Относително по-малко богат на функции, но ще отговори на вашите нужди. - Изчисти - Запази - Изберете приложения + Отказ + Затвори + Персонализирано внедряване на GMS за Vanced въз основа на проекта microG. + Модифициран клиент за YouTube с много полезни функции! + Vanced, но за YouTube Music! Относително по-малко богат на функции, но ще отговори на вашите нужди. + Изчисти + Запази + Изберете приложения - Относно - Ръководство - Мениджър - Логове - Настройки - Обнови Vanced Manager + Относно + Ръководство + Мениджър + Логове + Настройки + Обнови Vanced Manager - Имате ли Root достъп на устройството си? - Разрешете Root достъп - Да започваме - Изберете поне едно приложение! - Не знаете какво е това или не искате да ползвате Root версията? Просто натиснете синята стрелка по-долу! + Имате ли Root достъп на устройството си? + Разрешете Root достъп + Да започваме + Изберете поне едно приложение! + Не знаете какво е това или не искате да ползвате Root версията? Просто натиснете синята стрелка по-долу! - Относно %1$s - Изтегляне - Информация - Стартиране - Reinstall - Деинсталиране - Актуализиране - Приложения - Списък с промени - Изтегляне на %1$s - Инсталиране + Относно %1$s + Изтегляне + Информация + Стартиране + Reinstall + Деинсталиране + Актуализиране + Приложения + Списък с промени + Изтегляне на %1$s + Инсталиране Най-нова: - Инсталирайте първо Vanced microG + Инсталирайте първо Vanced microG Root достъп не е разрешен - Социални медии - Подкрепете ни - Недостъпно + Социални медии + Подкрепете ни + Недостъпно Инсталиранa: - Акцентиращ цвят - Външен вид - Поведение - Изчисти изтеглените файлове - Файловете са изчистени успешно - Позволява ни да събираме информация за поведението на приложението и доклади за сривове - Firebase анализ - Език - Връзките ще се отварят в персонализирани раздели на Chrome - Ползвай персонализирани раздели на Chrome - %1$s насочени известия - Получаване на насочени известия, когато има нова версия на %1$s - Неуспешно запазване на новата стойност за времето - Време за заспиване на Root скрипта - Настройване на времето на заспиване в /data/adb/service.d/app.sh скрипта, полезно при поправка на проблеми при монтиране - По подразбиране за системата - Тема - Тъмна тема - Светла тема - Център за актуализации - Няма актуализации - Вариант + Акцентиращ цвят + Външен вид + Поведение + Изчисти изтеглените файлове + Файловете са изчистени успешно + Позволява ни да събираме информация за поведението на приложението и доклади за сривове + Firebase анализ + Език + Връзките ще се отварят в персонализирани раздели на Chrome + Ползвай персонализирани раздели на Chrome + %1$s насочени известия + Получаване на насочени известия, когато има нова версия на %1$s + Неуспешно запазване на новата стойност за времето + Време за заспиване на Root скрипта + Настройване на времето на заспиване в /data/adb/service.d/app.sh скрипта, полезно при поправка на проблеми при монтиране + По подразбиране за системата + Тема + Тъмна тема + Светла тема + Център за актуализации + Няма актуализации + Вариант - Не могат да се запазят логовете - Успешно запазени логове + Не могат да се запазят логовете + Успешно запазени логове Подробности - %1$s инсталационни файлове са открити! - Мениджърът откри всички необходими файлове за инсталацията на %1$s. Желаете ли да го инсталирате? + %1$s инсталационни файлове са открити! + Мениджърът откри всички необходими файлове за инсталацията на %1$s. Желаете ли да го инсталирате? Предпочитания за инсталация на %1$s - Проверка за актуализации… + Проверка за актуализации… Език(ци): %1$s Тема: %1$s Версия: %1$s - Грешка - Ръководство - Стоп! + Грешка + Ръководство + Стоп! Използвате Magisk/TWRP версията на Vanced, която е прекратена и не може да се актуализира с това приложение. Премахнете я като премахнете Magisk модула или чрез TWRP Vanced uninstaller. - За да инсталирате Vanced, ТРЯБВА да изключите MIUI оптимизациите в настройките за разработчици. (Това не е валидно ако ползвате 20.2.20 или по-нов ROM, базиран на xiaomi.eu) - MIUI оптимизациите са включени! - Моля, НЕ излизайте от приложението по време на този процес! - Изтегли отново - Уверете се, че сте изтеглили приложението от vancedapp.com, Vanced Discord сървъра или от Vanced GitHub + За да инсталирате Vanced, ТРЯБВА да изключите MIUI оптимизациите в настройките за разработчици. (Това не е валидно ако ползвате 20.2.20 или по-нов ROM, базиран на xiaomi.eu) + MIUI оптимизациите са включени! + Моля, НЕ излизайте от приложението по време на този процес! + Изтегли отново + Уверете се, че сте изтеглили приложението от vancedapp.com, Vanced Discord сървъра или от Vanced GitHub Версия - Добре дошли + Добре дошли - Изберете предпочитан(и) език(ци) за Vanced - Най-нова + Изберете предпочитан(и) език(ци) за Vanced + Най-нова Светла + %1$s Изберете поне един език! - Черна - Тъмна + Черна + Тъмна - Разработчици - Други сътрудници - Източници - Екип на Vanced + Разработчици + Други сътрудници + Източници + Екип на Vanced - Неуспешно`chown` APK към собственика на системата, моля опитайте отново. - Грешка при изтегляне на %1$s + Неуспешно`chown` APK към собственика на системата, моля опитайте отново. + Грешка при изтегляне на %1$s Неуспешно задаване на акцентиращ цвят - Неуспешно деинсталиране на %1$s - Необходимите файлове за инсталация не са открити. Изтеглете ги отново и опитайте пак. - Не може да бъде открит apk файла за черна/тъмна тема, моля опитайте отново. - Инсталацията е неуспешна, защото е прекратена от потребителя. - Инсталацията е неуспешна, поради конфликт с вече инсталирано приложение. Деинсталирайте го и опитайте отново. - Инсталацията е неуспешна, защото потребителя се опитва да инсталира по-стара версия на пакета. Деинсталирайте актуализациите на оригиналното приложение и опитайте отново. - Инсталацията не бе успешна по неизвестни причини, присъединете се към нашия Telegram или Discord за допълнителна поддръжка. Моля, прикачете и екранна снимка от меню Разширени - Инсталацията е неуспешна, защото инсталационният файл не е съвместим с устройството ви. Изчистете изтеглените файлове от настройките и опитайте отново. - Инсталацията е неуспешна, защото apk файловете за повредени, моля опитайте отново. - Инсталацията е неуспешна, поради включени MIUI оптимизации. Изключете ги и опитайте отново. - Инсталацията е неуспешна, поради включена проверка на подписите на apk файловете. Изключете я и опитайте отново. - Инсталацията не бе успешна, тъй като устройството няма достатъчно свободно място. - Не е открит apk файл за черна/тъмна тема от инсталатора. Изчистете данните на мениджъра и опитайте отново. - Не е открит пътя на инсталацията на оригиналното YouTube приложение след разделното инсталиране. + Неуспешно деинсталиране на %1$s + Необходимите файлове за инсталация не са открити. Изтеглете ги отново и опитайте пак. + Не може да бъде открит apk файла за черна/тъмна тема, моля опитайте отново. + Инсталацията е неуспешна, защото е прекратена от потребителя. + Инсталацията е неуспешна, поради конфликт с вече инсталирано приложение. Деинсталирайте го и опитайте отново. + Инсталацията е неуспешна, защото потребителя се опитва да инсталира по-стара версия на пакета. Деинсталирайте актуализациите на оригиналното приложение и опитайте отново. + Инсталацията не бе успешна по неизвестни причини, присъединете се към нашия Telegram или Discord за допълнителна поддръжка. Моля, прикачете и екранна снимка от меню Разширени + Инсталацията е неуспешна, защото инсталационният файл не е съвместим с устройството ви. Изчистете изтеглените файлове от настройките и опитайте отново. + Инсталацията е неуспешна, защото apk файловете за повредени, моля опитайте отново. + Инсталацията е неуспешна, поради включени MIUI оптимизации. Изключете ги и опитайте отново. + Инсталацията е неуспешна, поради включена проверка на подписите на apk файловете. Изключете я и опитайте отново. + Инсталацията не бе успешна, тъй като устройството няма достатъчно свободно място. + Не е открит apk файл за черна/тъмна тема от инсталатора. Изчистете данните на мениджъра и опитайте отново. + Не е открит пътя на инсталацията на оригиналното YouTube приложение след разделното инсталиране. diff --git a/app/src/main/res/values-bn-rBD/strings.xml b/app/src/main/res/values-bn-rBD/strings.xml index c09b444297..c2f1986f38 100644 --- a/app/src/main/res/values-bn-rBD/strings.xml +++ b/app/src/main/res/values-bn-rBD/strings.xml @@ -1,120 +1,120 @@ - বাতিল করুন - বন্ধ করুন - A custom GMS Implementation for Vanced based on the microG Project. - A modified YouTube client with many useful features! - Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. - পুনরায় স্থির করুন - সংরক্ষণ করুন - আপনার পছন্দসই অ্যাপগুলি নির্বাচন করুন + বাতিল করুন + বন্ধ করুন + A custom GMS Implementation for Vanced based on the microG Project. + A modified YouTube client with many useful features! + Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. + পুনরায় স্থির করুন + সংরক্ষণ করুন + আপনার পছন্দসই অ্যাপগুলি নির্বাচন করুন - সম্বন্ধে - Guide - ম্যানেজার - Logs - সেটিংস - ম্যানেজার আপডেট করুন + সম্বন্ধে + Guide + ম্যানেজার + Logs + সেটিংস + ম্যানেজার আপডেট করুন - আপনার ডিভাইস কি রুটেড? - রুটের অনুমতি দিন - চলুন শুরু করি - অন্তত একটি অ্যাপ নির্বাচন করুন! - এটা কী জানেন না অথবা রুট ভার্সন ব্যবহার করতে চাচ্ছেন না? শুধু নিচের নীল তীর চিহ্নটিতে ক্লিক করুন! + আপনার ডিভাইস কি রুটেড? + রুটের অনুমতি দিন + চলুন শুরু করি + অন্তত একটি অ্যাপ নির্বাচন করুন! + এটা কী জানেন না অথবা রুট ভার্সন ব্যবহার করতে চাচ্ছেন না? শুধু নিচের নীল তীর চিহ্নটিতে ক্লিক করুন! - সম্পর্কিত তথ্য %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - Apps - পরিবর্তন তালিকা - %1$s ডাউনলোড করা হচ্ছে - ইনস্টল করুন + সম্পর্কিত তথ্য %1$s + Download + Info + Launch + Reinstall + Uninstall + Update + Apps + পরিবর্তন তালিকা + %1$s ডাউনলোড করা হচ্ছে + ইনস্টল করুন সর্বশেষ: - Install Vanced microG first + Install Vanced microG first রুট অনুমতি দেয়া হয়নি - Social Media - Support us - অনুপলব্ধ + Social Media + Support us + অনুপলব্ধ ইনস্টল করা আছে: - অ্যাকসেন্ট রঙ - চেহারা - আচরণ - ডাউনলোড করা ফাইলগুলি সাফ করুন - সাফল্যের সাথে ফাইলগুলি সাফ করা হয়েছে - এটি অ্যাপ্লিকেশন কর্মক্ষমতা এবং ক্র্যাশ লগ সম্পর্কিত তথ্য আমাদের দিবে। - ফায়ারবেস বিশ্লেষণ - ভাষা - লিঙ্কগুলি ক্রোম কাস্টম ট্যাবসে খোলা হবে - ক্রোম কাস্টম ট্যাবস ব্যবহার করুন - %1$s পুশ বিজ্ঞপ্তি - %1$s এর আপডেট প্রকাশিত হলে পুশ বিজ্ঞপ্তি পান - Failed to save new time value - Root Script Sleep Time - Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues - সিস্টেম দ্বারা নির্ধারিত - থিম - গাঢ় থিম - হালকা থিম - ম্যানেজার আপডেট কেন্দ্র - কোনো নতুন আপডেট নেই - রকমফের + অ্যাকসেন্ট রঙ + চেহারা + আচরণ + ডাউনলোড করা ফাইলগুলি সাফ করুন + সাফল্যের সাথে ফাইলগুলি সাফ করা হয়েছে + এটি অ্যাপ্লিকেশন কর্মক্ষমতা এবং ক্র্যাশ লগ সম্পর্কিত তথ্য আমাদের দিবে। + ফায়ারবেস বিশ্লেষণ + ভাষা + লিঙ্কগুলি ক্রোম কাস্টম ট্যাবসে খোলা হবে + ক্রোম কাস্টম ট্যাবস ব্যবহার করুন + %1$s পুশ বিজ্ঞপ্তি + %1$s এর আপডেট প্রকাশিত হলে পুশ বিজ্ঞপ্তি পান + Failed to save new time value + Root Script Sleep Time + Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues + সিস্টেম দ্বারা নির্ধারিত + থিম + গাঢ় থিম + হালকা থিম + ম্যানেজার আপডেট কেন্দ্র + কোনো নতুন আপডেট নেই + রকমফের - Could not save logs - Successfully saved logs + Could not save logs + Successfully saved logs Details - %1$s ইন্সটল করার জন্য ফাইল পাওয়া গেছে! - ম্যানেজার সনাক্ত করেছে যে %1$s এর ইনস্টলেসনের জন্য সকল ফাইল পাওয়া গেছে। আপনি কি এটি ইনস্টল করতে চান? + %1$s ইন্সটল করার জন্য ফাইল পাওয়া গেছে! + ম্যানেজার সনাক্ত করেছে যে %1$s এর ইনস্টলেসনের জন্য সকল ফাইল পাওয়া গেছে। আপনি কি এটি ইনস্টল করতে চান? %1$s Installation Preferences - আপডেট আছে কিনা দেখা হচ্ছে… + আপডেট আছে কিনা দেখা হচ্ছে… ভাষা (গুলি):%1$s থিম: %1$s ভার্সন: %1$s - ত্রুটি - সহায়িকা - থামো! + ত্রুটি + সহায়িকা + থামো! You are using the Magisk/TWRP version of Vanced, which is discontinued and cannot be updated using this app. Please remove it by removing the Magisk module/using TWRP Vanced uninstaller. - To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) - MIUI Optimizations are enabled! - Please do NOT exit the app during this process! - Redownload - Make sure that you downloaded the app from vancedapp.com, the Vanced Discord server, or the Vanced GitHub + To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) + MIUI Optimizations are enabled! + Please do NOT exit the app during this process! + Redownload + Make sure that you downloaded the app from vancedapp.com, the Vanced Discord server, or the Vanced GitHub Version - স্বাগতম + স্বাগতম - ভ্যানসডের জন্য আপনার পছন্দসই ভাষা (গুলি) চয়ন করুন - Latest + ভ্যানসডের জন্য আপনার পছন্দসই ভাষা (গুলি) চয়ন করুন + Latest Light + %1$s Select at least one language! - Black - Dark + Black + Dark - পরিচালক বিকাশকারী - Other Contributors - সূত্রসমূহ - ভান্সড দল + পরিচালক বিকাশকারী + Other Contributors + সূত্রসমূহ + ভান্সড দল - Failed to `chown` APK to system owner, please try again. - %1$s ডাউনলোড করার সময় ত্রুটি + Failed to `chown` APK to system owner, please try again. + %1$s ডাউনলোড করার সময় ত্রুটি Failed to apply new accent color - প্যাকেজ %1$s আনইনস্টল করতে ব্যর্থ - সফটওয়্যার টি ইনস্টল এর জন্য প্রয়োজনী ফাইল সংগ্রহতে ব্যর্থ হয়েছে। পুনরায় ডাওনলোড এবং ইনস্টল করে চেষ্টা করুন. - স্টোরেজ থেকে কালো / অন্ধকান থিমের জন্য apk ফাইল সনাক্ত করতে ব্যর্থ হয়েছে, দয়া করে আবার চেষ্টা করুন।. - Installation failed because the user aborted the installation. - Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. - Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. - Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu - ইনস্টলেশন ব্যর্থ হয়েছে কারণ ইনস্টলেশন ফাইলটি আপনার ডিভাইসের সাথে বেমানান। সেটিংসে ডাউনলোড করা ফাইল সাফ করুন, তারপরে আবার চেষ্টা করুন।. - অ্যাপ্লিকেশন ব্যর্থ হয়েছে কারণ এপিপি ফাইলগুলি দূষিত হয়েছে, দয়া করে আবার চেষ্টা করুন।. - ইনস্টলেশন ব্যর্থ হয়েছে কারণ এমআইইউআই অপটিমাইজেশন সক্ষম রয়েছে। MIUI অপ্টিমাইজেশন অক্ষম করুন, তারপরে আবার চেষ্টা করুন।. - Installation failed because apk signature verification is enabled. Disable apk signature verification, then try again. - Installation failed because the device doesn\'t have enough free space. - ইনস্টলার থেকে কালো / অন্ধকার থিমের জন্য সফটওয়্যারের ফাইল খুঁজতে ব্যর্থ। আপনার অ্যাপ্লিকেশনের ডেটা সাফ করুন, তারপরে আবার চেষ্টা করুন।. - ভিন্ন ভিন্ন ইনস্টলেশন পরে স্টক ইউটিউব ইনস্টলেশন পথ সনাক্ত করতে ব্যর্থ. + প্যাকেজ %1$s আনইনস্টল করতে ব্যর্থ + সফটওয়্যার টি ইনস্টল এর জন্য প্রয়োজনী ফাইল সংগ্রহতে ব্যর্থ হয়েছে। পুনরায় ডাওনলোড এবং ইনস্টল করে চেষ্টা করুন. + স্টোরেজ থেকে কালো / অন্ধকান থিমের জন্য apk ফাইল সনাক্ত করতে ব্যর্থ হয়েছে, দয়া করে আবার চেষ্টা করুন।. + Installation failed because the user aborted the installation. + Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. + Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. + Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu + ইনস্টলেশন ব্যর্থ হয়েছে কারণ ইনস্টলেশন ফাইলটি আপনার ডিভাইসের সাথে বেমানান। সেটিংসে ডাউনলোড করা ফাইল সাফ করুন, তারপরে আবার চেষ্টা করুন।. + অ্যাপ্লিকেশন ব্যর্থ হয়েছে কারণ এপিপি ফাইলগুলি দূষিত হয়েছে, দয়া করে আবার চেষ্টা করুন।. + ইনস্টলেশন ব্যর্থ হয়েছে কারণ এমআইইউআই অপটিমাইজেশন সক্ষম রয়েছে। MIUI অপ্টিমাইজেশন অক্ষম করুন, তারপরে আবার চেষ্টা করুন।. + Installation failed because apk signature verification is enabled. Disable apk signature verification, then try again. + Installation failed because the device doesn\'t have enough free space. + ইনস্টলার থেকে কালো / অন্ধকার থিমের জন্য সফটওয়্যারের ফাইল খুঁজতে ব্যর্থ। আপনার অ্যাপ্লিকেশনের ডেটা সাফ করুন, তারপরে আবার চেষ্টা করুন।. + ভিন্ন ভিন্ন ইনস্টলেশন পরে স্টক ইউটিউব ইনস্টলেশন পথ সনাক্ত করতে ব্যর্থ. diff --git a/app/src/main/res/values-bn-rIN/strings.xml b/app/src/main/res/values-bn-rIN/strings.xml index 29bc5fda82..4c9f76c73a 100644 --- a/app/src/main/res/values-bn-rIN/strings.xml +++ b/app/src/main/res/values-bn-rIN/strings.xml @@ -1,120 +1,120 @@ - বাতিল করুন - বন্ধ করুন - মাইক্রোজি প্রকল্পের ভিত্তিতে ভ্যান্সডের জন্য একটি কাস্টম জিএমএস বাস্তবায়ন।. - অনেক দরকারী বৈশিষ্ট্য সহ একটি পরিবর্তিত ইউটিউব ক্লায়েন্ট! - ভ্যান্সড, তবে ইউটিউব মিউজিকের জন্য! তুলনামূলকভাবে কম বৈশিষ্ট্য সমৃদ্ধ তবে আপনার চাহিদা পূরণ করবে।. - পুনরায় স্থির করুন - সংরক্ষণ করুন - আপনার পছন্দসই অ্যাপগুলি নির্বাচন করুন + বাতিল করুন + বন্ধ করুন + মাইক্রোজি প্রকল্পের ভিত্তিতে ভ্যান্সডের জন্য একটি কাস্টম জিএমএস বাস্তবায়ন।. + অনেক দরকারী বৈশিষ্ট্য সহ একটি পরিবর্তিত ইউটিউব ক্লায়েন্ট! + ভ্যান্সড, তবে ইউটিউব মিউজিকের জন্য! তুলনামূলকভাবে কম বৈশিষ্ট্য সমৃদ্ধ তবে আপনার চাহিদা পূরণ করবে।. + পুনরায় স্থির করুন + সংরক্ষণ করুন + আপনার পছন্দসই অ্যাপগুলি নির্বাচন করুন - সম্বন্ধে - গাইড - ম্যানেজার - লগস - সেটিংস - ম্যানেজার আপডেট করুন + সম্বন্ধে + গাইড + ম্যানেজার + লগস + সেটিংস + ম্যানেজার আপডেট করুন - আপনার ডিভাইসটিতে আপনার রুট অ্যাক্সেস আছে? - রুট অনুমতি মঞ্জুর করুন - শুরু করা যাক - অন্তত একটি অ্যাপ নির্বাচন করুন! - এটি কি তা জানেন না বা রুট ভার্সনটি ব্যবহার করতে চান না? কেবল নীচের নীল তীর চিহ্নটি ক্লিক করুন! + আপনার ডিভাইসটিতে আপনার রুট অ্যাক্সেস আছে? + রুট অনুমতি মঞ্জুর করুন + শুরু করা যাক + অন্তত একটি অ্যাপ নির্বাচন করুন! + এটি কি তা জানেন না বা রুট ভার্সনটি ব্যবহার করতে চান না? কেবল নীচের নীল তীর চিহ্নটি ক্লিক করুন! - %1$s এর সম্বন্ধে - ডাউনলোড - তথ্য - লঞ্চ করুন - Reinstall - আনইনস্টল - আপডেট - অ্যাপস - পরিবর্তন নথি - %1$s ডাউনলোড করা হচ্ছে - ইনস্টল করুন + %1$s এর সম্বন্ধে + ডাউনলোড + তথ্য + লঞ্চ করুন + Reinstall + আনইনস্টল + আপডেট + অ্যাপস + পরিবর্তন নথি + %1$s ডাউনলোড করা হচ্ছে + ইনস্টল করুন সর্বশেষ: - প্রথমে ভ্যান্সড মাইক্রোজি ইনস্টল করুন + প্রথমে ভ্যান্সড মাইক্রোজি ইনস্টল করুন রুট অনুমতি দেয়া হয়নি - সোশ্যাল মিডিয়া - আমাদের সমর্থন করুন - অনুপলব্ধ + সোশ্যাল মিডিয়া + আমাদের সমর্থন করুন + অনুপলব্ধ ইনস্টল করা আছে: - অ্যাকসেন্ট রঙ - রূপ - আচরণ - ডাউনলোড করা ফাইলগুলি মুছে ফেলুন - সফলভাবে ফাইলগুলি মুছে ফেলা হয়েছে - এটি আমাদের অ্যাপ্লিকেশন কর্মক্ষমতা এবং ক্র্যাশ লগ সম্পর্কিত তথ্য সংগ্রহ করতে দেয় - ফায়ারবেস তথ্য বিশ্লেষণ - ভাষা - লিঙ্কগুলি ক্রোম কাস্টম ট্যাবসে খুলবে - ক্রোম কাস্টম ট্যাবস ব্যবহার করুন - %1$s পুশ বিজ্ঞপ্তিগুলি - %1$s এর আপডেট প্রকাশিত হলে পুশ বিজ্ঞপ্তি পান - নতুন সময়ের মান সংরক্ষণ করতে ব্যর্থ হয়েছে - রুট স্ক্রিপ্ট স্লিপ টাইম - মাউন্টিং ইস্যু ফিক্স করার জন্য দরকারী /data/adb/service.d/app.sh স্ক্রিপ্টে ব্যবহৃত স্লিপ টাইম মানটি অ্যাডজাস্ট করুন - সিস্টেম দ্বারা র্নির্ধারিত - থিম - গাঢ় থিম - হালকা থিম - ম্যানেজার আপডেট কেন্দ্র - কোনো নতুন আপডেট নেই - বিকল্প + অ্যাকসেন্ট রঙ + রূপ + আচরণ + ডাউনলোড করা ফাইলগুলি মুছে ফেলুন + সফলভাবে ফাইলগুলি মুছে ফেলা হয়েছে + এটি আমাদের অ্যাপ্লিকেশন কর্মক্ষমতা এবং ক্র্যাশ লগ সম্পর্কিত তথ্য সংগ্রহ করতে দেয় + ফায়ারবেস তথ্য বিশ্লেষণ + ভাষা + লিঙ্কগুলি ক্রোম কাস্টম ট্যাবসে খুলবে + ক্রোম কাস্টম ট্যাবস ব্যবহার করুন + %1$s পুশ বিজ্ঞপ্তিগুলি + %1$s এর আপডেট প্রকাশিত হলে পুশ বিজ্ঞপ্তি পান + নতুন সময়ের মান সংরক্ষণ করতে ব্যর্থ হয়েছে + রুট স্ক্রিপ্ট স্লিপ টাইম + মাউন্টিং ইস্যু ফিক্স করার জন্য দরকারী /data/adb/service.d/app.sh স্ক্রিপ্টে ব্যবহৃত স্লিপ টাইম মানটি অ্যাডজাস্ট করুন + সিস্টেম দ্বারা র্নির্ধারিত + থিম + গাঢ় থিম + হালকা থিম + ম্যানেজার আপডেট কেন্দ্র + কোনো নতুন আপডেট নেই + বিকল্প - লগগুলি সংরক্ষণ করা যায়নি - সফলভাবে লগ সংরক্ষণ করা হয়েছে + লগগুলি সংরক্ষণ করা যায়নি + সফলভাবে লগ সংরক্ষণ করা হয়েছে বিশদ - ইনস্টল করার জন্য %1$s ফাইল খুঁজে পাওয়া গেছে! - %1$s ইনস্টল করার জন্য প্রয়োজনীয় সমস্ত ফাইলগুলি ম্যানেজার খুঁজে পেয়েছে। আপনি কি ইনস্টল করতে চান? + ইনস্টল করার জন্য %1$s ফাইল খুঁজে পাওয়া গেছে! + %1$s ইনস্টল করার জন্য প্রয়োজনীয় সমস্ত ফাইলগুলি ম্যানেজার খুঁজে পেয়েছে। আপনি কি ইনস্টল করতে চান? %1$s ইনস্টল করার পছন্দগুলি - আপডেটের জন্য চেক করা হচ্ছে… + আপডেটের জন্য চেক করা হচ্ছে… ভাষা(গুলি): %1$s থিম: %1$s সংস্করণ: %1$s - ত্রুটি - সহায়িকা - থামুন! + ত্রুটি + সহায়িকা + থামুন! আপনি ভ্যান্সড ম্যাজিস্ক/TWRP সংস্করণ ব্যবহার করছেন যা বন্ধ হয়ে গেছে এবং আপনি এটিকে আপডেট করতে পারবেন না। দয়া করে ম্যাজিস্ক মডিউলটি সরিয়ে/TWRP ভ্যান্সড আনইনস্টলার ব্যবহার করে এটি মুছে ফেলুন। - ভ্যান্সড ইনস্টল করতে হলে, আপনাকে ডেভেলপার সেটিংসে MIUI অপটিমাইজেশন বন্ধ করতে হবে। (আপনি যদি ২০.২.২০ বা তার পরবর্তী xiaomi.eu ভিত্তিক রম ব্যবহার করেন তবে আপনি এই সতর্কবার্তাটি এড়িয়ে যেতে পারেন) - MIUI অপটিমাইজেশন সক্ষম করা আছে! - এই প্রক্রিয়া চলাকালীন দয়া করে অ্যাপ্লিকেশন থেকে কোনোমতেই প্রস্থান করবেন না! - পুনরায় ডাউনলোড করুন - নিশ্চিত করুন যে আপনি অ্যাপটি vancedapp.com, ভ্যান্সড ডিসকার্ড সার্ভার বা ভ্যান্সড গিটহাব থেকে ডাউনলোড করেছেন + ভ্যান্সড ইনস্টল করতে হলে, আপনাকে ডেভেলপার সেটিংসে MIUI অপটিমাইজেশন বন্ধ করতে হবে। (আপনি যদি ২০.২.২০ বা তার পরবর্তী xiaomi.eu ভিত্তিক রম ব্যবহার করেন তবে আপনি এই সতর্কবার্তাটি এড়িয়ে যেতে পারেন) + MIUI অপটিমাইজেশন সক্ষম করা আছে! + এই প্রক্রিয়া চলাকালীন দয়া করে অ্যাপ্লিকেশন থেকে কোনোমতেই প্রস্থান করবেন না! + পুনরায় ডাউনলোড করুন + নিশ্চিত করুন যে আপনি অ্যাপটি vancedapp.com, ভ্যান্সড ডিসকার্ড সার্ভার বা ভ্যান্সড গিটহাব থেকে ডাউনলোড করেছেন সংস্করণ - স্বাগত + স্বাগত - ভ্যান্সডের জন্য আপনার পছন্দসই ভাষা(গুলি) চয়ন করুন - সর্বশেষ + ভ্যান্সডের জন্য আপনার পছন্দসই ভাষা(গুলি) চয়ন করুন + সর্বশেষ হাল্কা + %1$s অন্তত একটি ভাষা নির্বাচন করুন! - কালো - অন্ধকার + কালো + অন্ধকার - ম্যানেজার বিকাশকারীরা - অন্যান্য অবদানকারী - উৎসগুলি - ভ্যান্সড টীম + ম্যানেজার বিকাশকারীরা + অন্যান্য অবদানকারী + উৎসগুলি + ভ্যান্সড টীম - System owner কে APK `chown` করতে ব্যর্থ, দয়া করে আবার চেষ্টা করুন। - %1$s ডাউনলোড করার সময় ত্রুটি + System owner কে APK `chown` করতে ব্যর্থ, দয়া করে আবার চেষ্টা করুন। + %1$s ডাউনলোড করার সময় ত্রুটি নতুন অ্যাকসেন্ট রঙ প্রয়োগ করতে ব্যর্থ হয়েছে - %1$s পেকেজ আন‌ইনস্টল করা যাইনি - ইনস্টলেশনের জন্য প্রয়োজনীয় ফাইলগুলি খুঁজে পাওয়া যায় নি। ইনস্টল করার জন্য ফাইলগুলি পুনরায় ডাউনলোড করুন, তারপরে আবার চেষ্টা করুন। - স্টোরেজ থেকে কালো/গাঢ় থিমের জন্য এপিকে ফাইল সনাক্ত করতে ব্যর্থ, দয়া করে আবার চেষ্টা করুন। - ইনস্টল করা যায়নি কারণ ব্যবহারকারী ইনস্টল করা বাতিল করে দিয়েছেন। - ইনস্টলেশন ব্যর্থ হয়েছে কারণ অ্যাপ্লিকেশনটি ইতিমধ্যে ইনস্টল হওয়া আরেকটি অ্যাপ্লিকেশানের সাথে দ্বন্দ্ব করেছে। অ্যাপটির বর্তমান সংস্করণটি আনইনস্টল করুন, তারপরে আবার চেষ্টা করুন। - ইনস্টলেশন ব্যর্থ হয়েছে কারণ ব্যবহারকারী প্যাকেজটি ডাউনগ্রেড করার চেষ্টা করেছিল। স্টক অ্যাপ্লিকেশন থেকে আপডেটগুলি আনইনস্টল করুন, তারপরে আবার চেষ্টা করুন। - অজানা কারণে ইনস্টলেশন ব্যর্থ হয়েছে, আরও সহায়তার জন্য আমাদের টেলিগ্রাম বা ডিসকর্ডে যোগ দিন। অ্যাডভান্সড মেনু থেকে স্ক্রিনশটটিও সংযুক্ত করুন - ইনস্টলেশন ব্যর্থ হয়েছে কারণ ইনস্টলেশন ফাইলটি আপনার ডিভাইসের উপযুক্ত নয়। সেটিংসে ডাউনলোড করা ফাইল মুছে ফেলুন, তারপরে আবার চেষ্টা করুন। - ইনস্টলেশন ব্যর্থ হয়েছে কারণ এপিকে ফাইলগুলি দূষিত, দয়া করে আবার চেষ্টা করুন। - ইনস্টলেশন ব্যর্থ হয়েছে কারণ এমআইইউআই অপটিমাইজেশন সক্ষম আছে। এমআইইউআই অপ্টিমাইজেশন অক্ষম করুন, তারপরে আবার চেষ্টা করুন। - ইনস্টলেশন ব্যর্থ হয়েছে কারণ এপিকে স্বাক্ষর যাচাইকরণ সক্ষম করা আছে। এপিকে স্বাক্ষর যাচাইকরণ অক্ষম করুন, তারপরে আবার চেষ্টা করুন। - ইনস্টলেশন ব্যর্থ হয়েছে কারণ ডিভাইসে পর্যাপ্ত ফাঁকা জায়গা নেই। - ইনস্টলার থেকে কালো/গাঢ় থিমের জন্য সফটওয়্যারের ফাইল খুঁজতে ব্যর্থ। ম্যানেজারের ডেটা সাফ করুন, তারপরে আবার চেষ্টা করুন। - স্পিল্ট ফাইলগুলি ইনস্টল করার পরে স্টক ইউটিউবের ইনস্টলেশন পাথ সনাক্ত করতে ব্যর্থ। + %1$s পেকেজ আন‌ইনস্টল করা যাইনি + ইনস্টলেশনের জন্য প্রয়োজনীয় ফাইলগুলি খুঁজে পাওয়া যায় নি। ইনস্টল করার জন্য ফাইলগুলি পুনরায় ডাউনলোড করুন, তারপরে আবার চেষ্টা করুন। + স্টোরেজ থেকে কালো/গাঢ় থিমের জন্য এপিকে ফাইল সনাক্ত করতে ব্যর্থ, দয়া করে আবার চেষ্টা করুন। + ইনস্টল করা যায়নি কারণ ব্যবহারকারী ইনস্টল করা বাতিল করে দিয়েছেন। + ইনস্টলেশন ব্যর্থ হয়েছে কারণ অ্যাপ্লিকেশনটি ইতিমধ্যে ইনস্টল হওয়া আরেকটি অ্যাপ্লিকেশানের সাথে দ্বন্দ্ব করেছে। অ্যাপটির বর্তমান সংস্করণটি আনইনস্টল করুন, তারপরে আবার চেষ্টা করুন। + ইনস্টলেশন ব্যর্থ হয়েছে কারণ ব্যবহারকারী প্যাকেজটি ডাউনগ্রেড করার চেষ্টা করেছিল। স্টক অ্যাপ্লিকেশন থেকে আপডেটগুলি আনইনস্টল করুন, তারপরে আবার চেষ্টা করুন। + অজানা কারণে ইনস্টলেশন ব্যর্থ হয়েছে, আরও সহায়তার জন্য আমাদের টেলিগ্রাম বা ডিসকর্ডে যোগ দিন। অ্যাডভান্সড মেনু থেকে স্ক্রিনশটটিও সংযুক্ত করুন + ইনস্টলেশন ব্যর্থ হয়েছে কারণ ইনস্টলেশন ফাইলটি আপনার ডিভাইসের উপযুক্ত নয়। সেটিংসে ডাউনলোড করা ফাইল মুছে ফেলুন, তারপরে আবার চেষ্টা করুন। + ইনস্টলেশন ব্যর্থ হয়েছে কারণ এপিকে ফাইলগুলি দূষিত, দয়া করে আবার চেষ্টা করুন। + ইনস্টলেশন ব্যর্থ হয়েছে কারণ এমআইইউআই অপটিমাইজেশন সক্ষম আছে। এমআইইউআই অপ্টিমাইজেশন অক্ষম করুন, তারপরে আবার চেষ্টা করুন। + ইনস্টলেশন ব্যর্থ হয়েছে কারণ এপিকে স্বাক্ষর যাচাইকরণ সক্ষম করা আছে। এপিকে স্বাক্ষর যাচাইকরণ অক্ষম করুন, তারপরে আবার চেষ্টা করুন। + ইনস্টলেশন ব্যর্থ হয়েছে কারণ ডিভাইসে পর্যাপ্ত ফাঁকা জায়গা নেই। + ইনস্টলার থেকে কালো/গাঢ় থিমের জন্য সফটওয়্যারের ফাইল খুঁজতে ব্যর্থ। ম্যানেজারের ডেটা সাফ করুন, তারপরে আবার চেষ্টা করুন। + স্পিল্ট ফাইলগুলি ইনস্টল করার পরে স্টক ইউটিউবের ইনস্টলেশন পাথ সনাক্ত করতে ব্যর্থ। diff --git a/app/src/main/res/values-ca-rES/strings.xml b/app/src/main/res/values-ca-rES/strings.xml index cff8c74674..6b0086dcd4 100644 --- a/app/src/main/res/values-ca-rES/strings.xml +++ b/app/src/main/res/values-ca-rES/strings.xml @@ -1,120 +1,120 @@ - Cancel·lar - Tanca - Implementació modificada de GMS per a Cancer basada en el Projecte microG. - Una aplicació modificada de YouTube amb moltes característiques útils! - Vanced, però per a YouTube Music! Amb relativament menys característiques, però que assoleix les vostres necessitats. - Restableix - Desa - Seleccioneu les aplicacions + Cancel·lar + Tanca + Implementació modificada de GMS per a Cancer basada en el Projecte microG. + Una aplicació modificada de YouTube amb moltes característiques útils! + Vanced, però per a YouTube Music! Amb relativament menys característiques, però que assoleix les vostres necessitats. + Restableix + Desa + Seleccioneu les aplicacions - Quant a - Guia - Gestor - Registre - Configuració - Gestionador d\'actualitzacions + Quant a + Guia + Gestor + Registre + Configuració + Gestionador d\'actualitzacions - Té el vostre dispositiu accés de Superusuari (\'Root\')? - Concedir permís de Superusuari (\'Root\') - Comencem-hi - Selecciona com a mínim una aplicació! - No saps què és o no vols utilitzar la versió de Superusuari (\'Root\')? Simplement clica la fletxa blava de sota! + Té el vostre dispositiu accés de Superusuari (\'Root\')? + Concedir permís de Superusuari (\'Root\') + Comencem-hi + Selecciona com a mínim una aplicació! + No saps què és o no vols utilitzar la versió de Superusuari (\'Root\')? Simplement clica la fletxa blava de sota! - Sobre %1$s - Descarrega - Informació - Llança - Reinstall - Desinstal·la - Actualitza - Aplicacions - Registre de canvis - Descarregant %1$s - Instal·lar + Sobre %1$s + Descarrega + Informació + Llança + Reinstall + Desinstal·la + Actualitza + Aplicacions + Registre de canvis + Descarregant %1$s + Instal·lar Darrera: - Instal·la primer Vanced microG + Instal·la primer Vanced microG L\'accés arrel no s\'ha concedit - Xarxes socials - Dóna\'ns suport - No disponible + Xarxes socials + Dóna\'ns suport + No disponible Instal·lat: - Color d\'èmfasi - Aparença - Comportament - Esborrar fitxers descarregats - Fitxers netejats correctament - Permet-te\'ns recollir informació sobre el rendiment de l\'aplicació i els registres d\'error - Estadístiques de Firebase - Llengua - Els enllaços s\'obriran en pestanyes personalitzades del Chrome - Utilitza pestanyes personalitzades del Chrome - %1$s notificacions automàtiques - Rebeu notificacions automàtiques quan es publiqui una actualització de%1$s - Error a l\'hora de guardar un nou valor de temps - Temps de repòs de la seqüència de comandes de Superusuari (\'Root\') - Ajusta el temps de repòs emprat a l\'script /data/adb/service.d/app.sh, útil per solventar problemes de muntatge - Per defecte del sistema - Tema - Tema fosc - Tema clar - Gestor d\'actualitzacions - Cap actualització - Variant + Color d\'èmfasi + Aparença + Comportament + Esborrar fitxers descarregats + Fitxers netejats correctament + Permet-te\'ns recollir informació sobre el rendiment de l\'aplicació i els registres d\'error + Estadístiques de Firebase + Llengua + Els enllaços s\'obriran en pestanyes personalitzades del Chrome + Utilitza pestanyes personalitzades del Chrome + %1$s notificacions automàtiques + Rebeu notificacions automàtiques quan es publiqui una actualització de%1$s + Error a l\'hora de guardar un nou valor de temps + Temps de repòs de la seqüència de comandes de Superusuari (\'Root\') + Ajusta el temps de repòs emprat a l\'script /data/adb/service.d/app.sh, útil per solventar problemes de muntatge + Per defecte del sistema + Tema + Tema fosc + Tema clar + Gestor d\'actualitzacions + Cap actualització + Variant - No s\'han pogut desar els registres - Registres desats satisfactòriament + No s\'han pogut desar els registres + Registres desats satisfactòriament Detalls - Arxius d\'instal·lació de %1$s detectats! - El gestionador ha trobat tots els arxius necessaris per a l\'instal·lació de %1$s. Voleu instalar-ho? + Arxius d\'instal·lació de %1$s detectats! + El gestionador ha trobat tots els arxius necessaris per a l\'instal·lació de %1$s. Voleu instalar-ho? Preferències d\'instal·lació de %1$s - Cercant actualitzacions… + Cercant actualitzacions… Llengua(es): %1$s Tema: %1$s Versió: %1$s - Error - Guia - Atura\'t! + Error + Guia + Atura\'t! You are using the Magisk/TWRP version of Vanced, which is discontinued and cannot be updated using this app. Please remove it by removing the Magisk module/using TWRP Vanced uninstaller. - To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) - MIUI Optimizations are enabled! - Please do NOT exit the app during this process! - Redownload - Make sure that you downloaded the app from vancedapp.com, the Vanced Discord server, or the Vanced GitHub + To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) + MIUI Optimizations are enabled! + Please do NOT exit the app during this process! + Redownload + Make sure that you downloaded the app from vancedapp.com, the Vanced Discord server, or the Vanced GitHub Version - Benvingut + Benvingut - Trieu els vostres idiomes preferits per a Vanced - Latest + Trieu els vostres idiomes preferits per a Vanced + Latest Light + %1$s Select at least one language! - Black - Dark + Black + Dark - Gestor de desenvolupadors - Other Contributors - Fonts - Equip avançat + Gestor de desenvolupadors + Other Contributors + Fonts + Equip avançat - Failed to `chown` APK to system owner, please try again. - Error en descarregar %1$s + Failed to `chown` APK to system owner, please try again. + Error en descarregar %1$s Failed to apply new accent color - Error en instal·lar el paquet %1$s - Failed to locate the required files for installation. Re-download the installation files, then try again. - Failed to locate apk file for black/dark theme from storage, please try again. - Installation failed because the user aborted the installation. - Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. - Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. - Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu - La instal·lació ha fallat perquè el fitxer d\'instal·lació és incompatible amb el dispositiu. Esborreu els fitxers descarregats a Configuració i torneu-ho a provar. - La instal·lació ha fallat perquè els fitxers apk estan danyats. Torneu-ho a provar. - La instal·lació ha fallat perquè l\'optimització MIUI està activada. Desactiveu l\'optimització MIUI i torneu-ho a provar. - La instal·lació ha fallat perquè la verificació de la signatura apk està activada. Desactiveu la verificació de la signatura apk i torneu-ho a provar. - Installation failed because the device doesn\'t have enough free space. - Failed to find apk file for black/dark theme from the installer. Clear app data of Manager, then try again. - Failed to locate the stock YouTube installation path after split installation. + Error en instal·lar el paquet %1$s + Failed to locate the required files for installation. Re-download the installation files, then try again. + Failed to locate apk file for black/dark theme from storage, please try again. + Installation failed because the user aborted the installation. + Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. + Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. + Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu + La instal·lació ha fallat perquè el fitxer d\'instal·lació és incompatible amb el dispositiu. Esborreu els fitxers descarregats a Configuració i torneu-ho a provar. + La instal·lació ha fallat perquè els fitxers apk estan danyats. Torneu-ho a provar. + La instal·lació ha fallat perquè l\'optimització MIUI està activada. Desactiveu l\'optimització MIUI i torneu-ho a provar. + La instal·lació ha fallat perquè la verificació de la signatura apk està activada. Desactiveu la verificació de la signatura apk i torneu-ho a provar. + Installation failed because the device doesn\'t have enough free space. + Failed to find apk file for black/dark theme from the installer. Clear app data of Manager, then try again. + Failed to locate the stock YouTube installation path after split installation. diff --git a/app/src/main/res/values-ckb-rIR/strings.xml b/app/src/main/res/values-ckb-rIR/strings.xml index 6dae3363f4..3d4a2a43b0 100644 --- a/app/src/main/res/values-ckb-rIR/strings.xml +++ b/app/src/main/res/values-ckb-rIR/strings.xml @@ -1,120 +1,120 @@ - هەڵوەشاندنەوە - داخستن - A custom GMS Implementation for Vanced based on the microG Project. - A modified YouTube client with many useful features! - Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. - ڕێکخستنەوە - پاراستن - بەرنامەکانت دیاریبکە + هەڵوەشاندنەوە + داخستن + A custom GMS Implementation for Vanced based on the microG Project. + A modified YouTube client with many useful features! + Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. + ڕێکخستنەوە + پاراستن + بەرنامەکانت دیاریبکە - دەربارە - زانیاری - بەرێوەبردن - تۆماری نوێکاری - ڕێکخستنەکان - نوێکردنەوەی بەرنامە + دەربارە + زانیاری + بەرێوەبردن + تۆماری نوێکاری + ڕێکخستنەکان + نوێکردنەوەی بەرنامە - مۆبایلەکەت ڕۆت کراوە؟ - ڕێگەپێدانی ڕۆت Root - دەست پێکردن - لانیکەم دانەیەک دیاریبکە! - ئەگەر نازانیت ئەمە چییە یان ناتەوێ بەشێوەی ڕۆت بەکاری بهێنیت، پەنجە بنێ بە دوگمە شینەکەدا! + مۆبایلەکەت ڕۆت کراوە؟ + ڕێگەپێدانی ڕۆت Root + دەست پێکردن + لانیکەم دانەیەک دیاریبکە! + ئەگەر نازانیت ئەمە چییە یان ناتەوێ بەشێوەی ڕۆت بەکاری بهێنیت، پەنجە بنێ بە دوگمە شینەکەدا! - دەربارەی %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - بەرنامەکان - گۆڕانکارییەکان - داگرتنی %1$s - دامەزراندن + دەربارەی %1$s + Download + Info + Launch + Reinstall + Uninstall + Update + بەرنامەکان + گۆڕانکارییەکان + داگرتنی %1$s + دامەزراندن دوایین: - Install Vanced microG first + Install Vanced microG first ڕێگەپێدانی Root نەدراوە - تۆڕە کۆمەڵایەتییەکان - پشتگیریکردن - بەردەست نیە + تۆڕە کۆمەڵایەتییەکان + پشتگیریکردن + بەردەست نیە دامەزرێنراو: - ڕەنگی سەرەکی - ڕووکار - ڕێکخستن - سڕینەوەی فایلە داگیراوەکان - فایلەکان بەسەرکەتوویی سڕانەوە - کۆکردنەوەی زانیاری لەکاتی بوونی کێشەو تۆماری هەڵە لە بەرنامەکەدا - Firebase شیکردنەوەی - زمان - بەستەرەکان لە پەنجەرەی تایبەتی گۆگڵ کرۆمدا دەکرێنەوە - بەکارهێنانی پەنجەرەی تایبەتی گۆگڵ کرۆم - %1$s وەرگرتنی ئاگادارکردنەوەکان - وەرگرتنی ئاگادارکردنەوە کاتێ نوێکردنەوەی %1$s بەردەست کرا - پاشکەوتکردنی بیرخەرەوە سەرکەوتو نەبوو - ماوەی وەستاندنی سکریپتی Root - Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues - سیستەم - ڕووکار - تاریک - ڕووناک - ناوەندی نوێکردنەوە - هیچ نوێکردنەوەیەک نیە - جۆر + ڕەنگی سەرەکی + ڕووکار + ڕێکخستن + سڕینەوەی فایلە داگیراوەکان + فایلەکان بەسەرکەتوویی سڕانەوە + کۆکردنەوەی زانیاری لەکاتی بوونی کێشەو تۆماری هەڵە لە بەرنامەکەدا + Firebase شیکردنەوەی + زمان + بەستەرەکان لە پەنجەرەی تایبەتی گۆگڵ کرۆمدا دەکرێنەوە + بەکارهێنانی پەنجەرەی تایبەتی گۆگڵ کرۆم + %1$s وەرگرتنی ئاگادارکردنەوەکان + وەرگرتنی ئاگادارکردنەوە کاتێ نوێکردنەوەی %1$s بەردەست کرا + پاشکەوتکردنی بیرخەرەوە سەرکەوتو نەبوو + ماوەی وەستاندنی سکریپتی Root + Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues + سیستەم + ڕووکار + تاریک + ڕووناک + ناوەندی نوێکردنەوە + هیچ نوێکردنەوەیەک نیە + جۆر - نەتوانرا تۆمارەکە بپارێزرێت - تۆمارەکە بەسەرکەوتوویی پارێزرا + نەتوانرا تۆمارەکە بپارێزرێت + تۆمارەکە بەسەرکەوتوویی پارێزرا Details - %1$s فایل دۆزرایەوە بۆ دابەزاندن! - بەرنامەکە هەموو ئەو فایلانەی دۆزیەوە %1$s کە پێویستن بۆ دابەزاندن، ئەتەوێ دایان مەزرێنیت؟ + %1$s فایل دۆزرایەوە بۆ دابەزاندن! + بەرنامەکە هەموو ئەو فایلانەی دۆزیەوە %1$s کە پێویستن بۆ دابەزاندن، ئەتەوێ دایان مەزرێنیت؟ %1$s ڕێکخستنەکانی دامەزراندن - پشکنین بۆ نوێکردنەوە… + پشکنین بۆ نوێکردنەوە… زمان: %1$s ڕووکار: %1$s وەشان: %1$s - هەڵەیەک ڕوویدا - زانیاری - وەستاندن! + هەڵەیەک ڕوویدا + زانیاری + وەستاندن! تۆ وەشانی Magisk/TWRP ـی Vanced بەکاردێنیت، کە ناتوانرێت بە بەکارهێنانی ئەم بەرنامەیە نوێبکرێتەوە، تکایە لایبدە بە سڕینەوەی مۆدیولی ماگیسک/لەڕێی TWRP Vanced. - To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) - باشترکردنی MIUI چالاککراوە! - Please do NOT exit the app during this process! - داگرتنەوە - دڵنیابە کە بەرنامەکەت لە سایتی vancedapp.com، سێرڤەری دیسکۆرد یان Vanced GitHub داگرتووە + To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) + باشترکردنی MIUI چالاککراوە! + Please do NOT exit the app during this process! + داگرتنەوە + دڵنیابە کە بەرنامەکەت لە سایتی vancedapp.com، سێرڤەری دیسکۆرد یان Vanced GitHub داگرتووە وەشان - بەخێربێیت + بەخێربێیت - زمانێک هەڵبژێرە بۆ بەکارهێنانی بەرنامەکە - دوایین + زمانێک هەڵبژێرە بۆ بەکارهێنانی بەرنامەکە + دوایین ڕووناک + %1$s لانیکەم زمانێک دیاریبکە! - ڕەش - تاریک + ڕەش + تاریک - کراوە بە کوردی لەلایەن: گۆران غەریب(کوردرۆید) - وەرگێڕانی کوردی - گۆران غەریب - سەرچاوەکان - Vanced تیمی + کراوە بە کوردی لەلایەن: گۆران غەریب(کوردرۆید) + وەرگێڕانی کوردی - گۆران غەریب + سەرچاوەکان + Vanced تیمی - سەرکەوتو نەبوو `chown` بۆ دانان وەک بەرنامەی سیستەم, تکایە دووبارە هەوڵبدەرەوە. - کێشە ڕوویدا لە داگرتنی %1$s + سەرکەوتو نەبوو `chown` بۆ دانان وەک بەرنامەی سیستەم, تکایە دووبارە هەوڵبدەرەوە. + کێشە ڕوویدا لە داگرتنی %1$s گۆڕینی ڕەنگ سەرکەوتو نەبوو - سڕینەوەی %1$s سەرکەوتو نەبوو - سەرکەوتو نەبوو لە دۆزینەوەی فایلە پێویستەکان بۆ دامەزراندن، فایلە پێویستیەکان دووبارە دابگرەوە بۆ جێگیرکردن، پاشان دووبارە هەوڵبدەرەوە. - سەرکەوتوو نەبوو لەدۆزینەوەی شوێنی فایلی Apk بۆ ڕووکاری ڕەش/تاریک لە بیرگەدا، تکایە دووبارە هەوڵبدەرەوە. - دامەزراندن سەرکەوتو نەبوو، لەبەر ئەوەی بەکارهێنەر کۆتاییهێنا بە دابەزاندنەکە. - دامەزراندن سەرکەوتو نەبوو لەبەرئەوەی وەشانێکی تری بەرنامەکە پێشتر دامەزرێنراوە، وەشانی ئێستای Vanced بسڕەوە و پاشان دووبارە هەوڵبدەرەوە. - دامەزراندن سەرکەوتو نەبوو، لەبەر ئەوەی بەکارهێنەر هەوڵیدا بۆ نزمکردنەوەی وەشان، نوێکارییەکانی بەرنامەی بنەڕەتی YouTube بسڕەوە و دووبارە هەوڵبدەرەوە. - Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu - دامەزراندن سەرکەوتو نەبوو لەبەرئەوەی فایلی دابەزاندن گونجاو نییە لەگەڵ ئامێرەکەت، فایلە داگیراوەکان بسڕەوە و پاشان دووبارە هەوڵبدەرەوە. - دامەزراندن سەرکەوتوو نەبوو لەبەرئەوەی فایلی apk تێکچووە، تکایە دووبارە هەوڵبدرەوە. - دامەزراندن سەرکەوتو نەبوو لەبەرئەوەی باشکردنی ڕووکاری MIUI چالاککراوە، باشکردنی ڕووکاری MIUI ناچالاک بکە ودووبارە هەوڵبدەرەوە. - دامەزراندن سەرکەوتو نەبوو لەبەرئەوەی سەلماندنەکانی apk چالاککراوە، سەلماندنی دووپاتکردنەوەی ئیمزای apk ناچالاک بکە و پاشان دووبارە هەوڵبدەرەوە. - Installation failed because the device doesn\'t have enough free space. - سەرکەوتو نەبوو لە دۆزینەوەی فایلی Apk بۆ ڕووکاری ڕەش/تاریک لە دامەزرێنەرەکەدا. داتای بەرنامەکە بسڕەوە لە ڕێکبەندیەکاندا و دووبارە هەوڵبدەرەوە. - سەرکەوتو نەبوو لە دۆزینەوەی بەرنامەی بنەڕەتی YouTube لەشوێنی دابەزاندن لەپاش دامەزراندنی پێکهاتەکان. + سڕینەوەی %1$s سەرکەوتو نەبوو + سەرکەوتو نەبوو لە دۆزینەوەی فایلە پێویستەکان بۆ دامەزراندن، فایلە پێویستیەکان دووبارە دابگرەوە بۆ جێگیرکردن، پاشان دووبارە هەوڵبدەرەوە. + سەرکەوتوو نەبوو لەدۆزینەوەی شوێنی فایلی Apk بۆ ڕووکاری ڕەش/تاریک لە بیرگەدا، تکایە دووبارە هەوڵبدەرەوە. + دامەزراندن سەرکەوتو نەبوو، لەبەر ئەوەی بەکارهێنەر کۆتاییهێنا بە دابەزاندنەکە. + دامەزراندن سەرکەوتو نەبوو لەبەرئەوەی وەشانێکی تری بەرنامەکە پێشتر دامەزرێنراوە، وەشانی ئێستای Vanced بسڕەوە و پاشان دووبارە هەوڵبدەرەوە. + دامەزراندن سەرکەوتو نەبوو، لەبەر ئەوەی بەکارهێنەر هەوڵیدا بۆ نزمکردنەوەی وەشان، نوێکارییەکانی بەرنامەی بنەڕەتی YouTube بسڕەوە و دووبارە هەوڵبدەرەوە. + Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu + دامەزراندن سەرکەوتو نەبوو لەبەرئەوەی فایلی دابەزاندن گونجاو نییە لەگەڵ ئامێرەکەت، فایلە داگیراوەکان بسڕەوە و پاشان دووبارە هەوڵبدەرەوە. + دامەزراندن سەرکەوتوو نەبوو لەبەرئەوەی فایلی apk تێکچووە، تکایە دووبارە هەوڵبدرەوە. + دامەزراندن سەرکەوتو نەبوو لەبەرئەوەی باشکردنی ڕووکاری MIUI چالاککراوە، باشکردنی ڕووکاری MIUI ناچالاک بکە ودووبارە هەوڵبدەرەوە. + دامەزراندن سەرکەوتو نەبوو لەبەرئەوەی سەلماندنەکانی apk چالاککراوە، سەلماندنی دووپاتکردنەوەی ئیمزای apk ناچالاک بکە و پاشان دووبارە هەوڵبدەرەوە. + Installation failed because the device doesn\'t have enough free space. + سەرکەوتو نەبوو لە دۆزینەوەی فایلی Apk بۆ ڕووکاری ڕەش/تاریک لە دامەزرێنەرەکەدا. داتای بەرنامەکە بسڕەوە لە ڕێکبەندیەکاندا و دووبارە هەوڵبدەرەوە. + سەرکەوتو نەبوو لە دۆزینەوەی بەرنامەی بنەڕەتی YouTube لەشوێنی دابەزاندن لەپاش دامەزراندنی پێکهاتەکان. diff --git a/app/src/main/res/values-cs-rCZ/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml index 3107819f08..7cda59faaa 100644 --- a/app/src/main/res/values-cs-rCZ/strings.xml +++ b/app/src/main/res/values-cs-rCZ/strings.xml @@ -1,120 +1,120 @@ - Zrušit - Zavřít - Vlastní implementace GMS pro Vanced založená na projektu microG. - Upravený klient YouTube se spoustou užitečných funkcí! - Vanced, ale YouTube Music! Obsahuje o trochu méně funkcí, ale splní vaše potřeby. - Resetovat - Uložit - Vyberte své aplikace + Zrušit + Zavřít + Vlastní implementace GMS pro Vanced založená na projektu microG. + Upravený klient YouTube se spoustou užitečných funkcí! + Vanced, ale YouTube Music! Obsahuje o trochu méně funkcí, ale splní vaše potřeby. + Resetovat + Uložit + Vyberte své aplikace - O aplikaci - Průvodce - Manager - Záznamy - Nastavení - Aktualizovat Manager + O aplikaci + Průvodce + Manager + Záznamy + Nastavení + Aktualizovat Manager - Má vaše zařízení oprávnění root? - Udělit oprávnění root - Začínáme - Vyberte alespoň jednu aplikaci! - Nevíte, co to je, nebo nechcete používat verzi s přístupem root? V tom případě klikněte na modrou šipku níže! + Má vaše zařízení oprávnění root? + Udělit oprávnění root + Začínáme + Vyberte alespoň jednu aplikaci! + Nevíte, co to je, nebo nechcete používat verzi s přístupem root? V tom případě klikněte na modrou šipku níže! - O aplikaci %1$s - Stáhnout - Informace - Spustit - Přeinstalovat - Odinstalovat - Aktualizovat - Aplikace - Seznam změn - Stahování %1$s - Nainstalovat + O aplikaci %1$s + Stáhnout + Informace + Spustit + Přeinstalovat + Odinstalovat + Aktualizovat + Aplikace + Seznam změn + Stahování %1$s + Nainstalovat Nejnovější: - Nejprve nainstalujte Vanced microG + Nejprve nainstalujte Vanced microG Root přístup nebyl udělen - Sociální média - Podpořte nás - Není k dispozici + Sociální média + Podpořte nás + Není k dispozici Nainstalováno: - Doplňková barva - Vzhled - Chování - Vymazat stažené soubory - Vymazání souborů proběhlo úspěšně - Toto nám umožňuje shromažďovat informace o výkonu aplikace a záznamy o selhání - Firebase analytika - Jazyk - Odkazy se budou otevírat na vlastních kartách prohlížeče Chrome - Používat vlastní karty prohlížeče Chrome - %1$s vyskakovací oznámení - Po vydání aktualizace pro %1$s obdržíte vyskakovací oznámení - Nepodařilo se uložit novou hodnotu času - Doba nečinnosti kořenového skriptu - Upravte hodnotu doby nečinnosti použitou ve skriptu /data/adb/service.d/app.sh, která je užitečná pro opravu problémů s připojením - Výchozí systémové nastavení - Motiv - Tmavý motiv - Světlý motiv - Centrum aktualizací aplikace Manager - Žádné nové aktualizace - Varianta + Doplňková barva + Vzhled + Chování + Vymazat stažené soubory + Vymazání souborů proběhlo úspěšně + Toto nám umožňuje shromažďovat informace o výkonu aplikace a záznamy o selhání + Firebase analytika + Jazyk + Odkazy se budou otevírat na vlastních kartách prohlížeče Chrome + Používat vlastní karty prohlížeče Chrome + %1$s vyskakovací oznámení + Po vydání aktualizace pro %1$s obdržíte vyskakovací oznámení + Nepodařilo se uložit novou hodnotu času + Doba nečinnosti kořenového skriptu + Upravte hodnotu doby nečinnosti použitou ve skriptu /data/adb/service.d/app.sh, která je užitečná pro opravu problémů s připojením + Výchozí systémové nastavení + Motiv + Tmavý motiv + Světlý motiv + Centrum aktualizací aplikace Manager + Žádné nové aktualizace + Varianta - Záznamy nelze uložit - Záznamy byly úspěšně uloženy + Záznamy nelze uložit + Záznamy byly úspěšně uloženy Podrobnosti - Počet zjištěných instalačních souborů: %1$s - Manager nalezl všechny soubory potřebné pro instalaci aplikace %1$s. Chcete ji nyní nainstalovat? + Počet zjištěných instalačních souborů: %1$s + Manager nalezl všechny soubory potřebné pro instalaci aplikace %1$s. Chcete ji nyní nainstalovat? Předvolby instalace: %1$s - Kontrola aktualizací… + Kontrola aktualizací… Jazyk(y): %1$s Motiv: %1$s Verze: %1$s - Chyba - Průvodce - Zadržte! + Chyba + Průvodce + Zadržte! Používáte verzi Vanced pro Magisk/TWRP, jejíž vývoj byl ukončen a kterou nelze pomocí této aplikace aktualizovat. Odstraňte ji prosím odebráním modulu Magisk použitím Vanced odinstalátoru v TWRP. - Chcete‑li nainstalovat Vanced, MUSÍTE vypnout optimalizace MIUI v nastavení pro vývojáře. (Toto varování můžete ignorovat, pokud používáte ROM ze 20. 2. 2020 nebo novější založenou na xiaomi.eu) - Optimalizace MIUI jsou zapnuty! - Během tohoto procesu NEUKONČUJTE aplikaci! - Stáhnout znovu - Ujistěte se, že jste si aplikaci stáhli z našeho webu vancedapp.com, z našeho Vanced Discord serveru nebo z našeho GitHubu + Chcete‑li nainstalovat Vanced, MUSÍTE vypnout optimalizace MIUI v nastavení pro vývojáře. (Toto varování můžete ignorovat, pokud používáte ROM ze 20. 2. 2020 nebo novější založenou na xiaomi.eu) + Optimalizace MIUI jsou zapnuty! + Během tohoto procesu NEUKONČUJTE aplikaci! + Stáhnout znovu + Ujistěte se, že jste si aplikaci stáhli z našeho webu vancedapp.com, z našeho Vanced Discord serveru nebo z našeho GitHubu Verze - Vítejte + Vítejte - Vyberte si jeden nebo více preferovaných jazyků pro Vanced - Nejnovější + Vyberte si jeden nebo více preferovaných jazyků pro Vanced + Nejnovější Světlý + %1$s Vyberte alespoň jeden jazyk! - Černý - Tmavý + Černý + Tmavý - Vývojáři aplikace Manager - Další přispěvatelé - Zdrojové kódy - Tým Vanced + Vývojáři aplikace Manager + Další přispěvatelé + Zdrojové kódy + Tým Vanced - Nepodařilo se změnit vlastníka souboru APK na vlastníka systému, zkuste to prosím znovu. - Chyba při stahování %1$s + Nepodařilo se změnit vlastníka souboru APK na vlastníka systému, zkuste to prosím znovu. + Chyba při stahování %1$s Nepodařilo se nastavit novou doplňkovou barvu - Nepodařilo se odinstalovat balíček %1$s - Nepodařilo se najít požadované soubory pro instalaci. Stáhněte znovu instalační soubory a poté to zkuste znovu. - Ve vnitřním úložišti se nepodařilo najít soubor APK pro černý/tmavý motiv. Zkuste to prosím znovu. - Instalace se nezdařila, protože uživatel přerušil instalaci. - Instalace se nezdařila, protože aplikace je v konfliktu s již nainstalovanou aplikací. Odinstalujte aktuální verzi aplikace a poté to zkuste znovu. - Instalace se nezdařila, protože se uživatel pokusil balíček downgradovat. Odinstalujte aktualizace z výchozí aplikace a poté to zkuste znovu. - Instalace se z neznámých důvodů nezdařila. Pro další podporu se připojte k našemu Telegramu nebo Discordu. Připojte také snímek obrazovky z nabídky Pokročilé - Instalace se nezdařila, protože instalační soubor není kompatibilní s vaším zařízením. Vymažte v Nastavení stažené soubory a poté to zkuste znovu. - Instalace se nezdařila, protože soubory APK jsou poškozeny. Zkuste to prosím znovu. - Instalace se nezdařila, protože je zapnuta optimalizace MIUI. Vypněte optimalizaci MIUI a poté to zkuste znovu. - Instalace se nezdařila, protože je povoleno ověření podpisu APK. Zakažte ověření podpisu APK a poté to zkuste znovu. - Instalace se nezdařila, protože v zařízení není dostatek volného místa. - Nepodařilo se najít soubor APK pro černý/tmavý motiv z instalátoru. Vymažte data aplikace Manager a zkuste to znovu. - Nepodařilo se najít výchozí cestu instalace YouTube po rozdělené instalaci. + Nepodařilo se odinstalovat balíček %1$s + Nepodařilo se najít požadované soubory pro instalaci. Stáhněte znovu instalační soubory a poté to zkuste znovu. + Ve vnitřním úložišti se nepodařilo najít soubor APK pro černý/tmavý motiv. Zkuste to prosím znovu. + Instalace se nezdařila, protože uživatel přerušil instalaci. + Instalace se nezdařila, protože aplikace je v konfliktu s již nainstalovanou aplikací. Odinstalujte aktuální verzi aplikace a poté to zkuste znovu. + Instalace se nezdařila, protože se uživatel pokusil balíček downgradovat. Odinstalujte aktualizace z výchozí aplikace a poté to zkuste znovu. + Instalace se z neznámých důvodů nezdařila. Pro další podporu se připojte k našemu Telegramu nebo Discordu. Připojte také snímek obrazovky z nabídky Pokročilé + Instalace se nezdařila, protože instalační soubor není kompatibilní s vaším zařízením. Vymažte v Nastavení stažené soubory a poté to zkuste znovu. + Instalace se nezdařila, protože soubory APK jsou poškozeny. Zkuste to prosím znovu. + Instalace se nezdařila, protože je zapnuta optimalizace MIUI. Vypněte optimalizaci MIUI a poté to zkuste znovu. + Instalace se nezdařila, protože je povoleno ověření podpisu APK. Zakažte ověření podpisu APK a poté to zkuste znovu. + Instalace se nezdařila, protože v zařízení není dostatek volného místa. + Nepodařilo se najít soubor APK pro černý/tmavý motiv z instalátoru. Vymažte data aplikace Manager a zkuste to znovu. + Nepodařilo se najít výchozí cestu instalace YouTube po rozdělené instalaci. diff --git a/app/src/main/res/values-da-rDK/strings.xml b/app/src/main/res/values-da-rDK/strings.xml index 9ad00f2a38..3d98057837 100644 --- a/app/src/main/res/values-da-rDK/strings.xml +++ b/app/src/main/res/values-da-rDK/strings.xml @@ -1,120 +1,120 @@ - Annuller - Luk - En brugerdefineret GMS implementering for Vanced baseret på microG Project. - En modificeret YouTube klient med mange nyttige funktioner! - Vanced, men for YouTube Music! Relativt mindre funktionsrig men opfylder dine behov. - Nulstil - Gem - Vælg Dine Apps + Annuller + Luk + En brugerdefineret GMS implementering for Vanced baseret på microG Project. + En modificeret YouTube klient med mange nyttige funktioner! + Vanced, men for YouTube Music! Relativt mindre funktionsrig men opfylder dine behov. + Nulstil + Gem + Vælg Dine Apps - Om - Guide - Manager - Logfiler - Indstillinger - Opdaterings Manager + Om + Guide + Manager + Logfiler + Indstillinger + Opdaterings Manager - Er Din Enhed Rooted? - Tildel Root Tilladelse - Lad os komme igang - Vælg mindst én app! - Ved du ikke hvad dette er, eller ønsker du ikke at bruge root versionen? Bare klik på den blå pil nedenfor! + Er Din Enhed Rooted? + Tildel Root Tilladelse + Lad os komme igang + Vælg mindst én app! + Ved du ikke hvad dette er, eller ønsker du ikke at bruge root versionen? Bare klik på den blå pil nedenfor! - Om %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - Apps - Ændringslog - Downloader %1$s - Installer + Om %1$s + Download + Info + Launch + Reinstall + Uninstall + Update + Apps + Ændringslog + Downloader %1$s + Installer Seneste: - Installer først Vanced microG + Installer først Vanced microG Root adgang ikke tildelt - Sociale medier - Støt os - Utilgængelig + Sociale medier + Støt os + Utilgængelig Installeret: - Sekundær farve - Udseende - Adfærd - Ryd hentede filer - Filer ryddet succesfuldt - Dette giver os mulighed for at indsamle oplysninger om appens ydeevne og nedbruds logs - Firebase analyse - Sprog - Links vil åbne i Chrome Custom Faner - Brug Chrome Custom Faner - %1$s Push Notifikationer - Modtag push meddelelser når der er en ny opdatering til %1$s - Kunne ikke gemme ny tidsværdi - Root script dvale tid - Justér dvale tid brugt i /data/adb/service.d/app.sh script, bruges til at rette monteringsproblemer - System Standard - Tema - Mørkt tema - Lyst tema - Manager opdaterings center - Ingen nye opdateringer - Variant + Sekundær farve + Udseende + Adfærd + Ryd hentede filer + Filer ryddet succesfuldt + Dette giver os mulighed for at indsamle oplysninger om appens ydeevne og nedbruds logs + Firebase analyse + Sprog + Links vil åbne i Chrome Custom Faner + Brug Chrome Custom Faner + %1$s Push Notifikationer + Modtag push meddelelser når der er en ny opdatering til %1$s + Kunne ikke gemme ny tidsværdi + Root script dvale tid + Justér dvale tid brugt i /data/adb/service.d/app.sh script, bruges til at rette monteringsproblemer + System Standard + Tema + Mørkt tema + Lyst tema + Manager opdaterings center + Ingen nye opdateringer + Variant - Kunne ikke gemme logfil - Logfiler gemt succesfuldt + Kunne ikke gemme logfil + Logfiler gemt succesfuldt Detaljer - %1$s installationsfiler fundet! - Manageren opdagede, at alle nødvendige filer til %1$s installationen blev fundet. Vil du installere den? + %1$s installationsfiler fundet! + Manageren opdagede, at alle nødvendige filer til %1$s installationen blev fundet. Vil du installere den? %1$s Installationsindstillinger - Søger efter opdateringer… + Søger efter opdateringer… Sprog:%1$s Tema: %1$s Version: %1$s - Fejl - Vejledning - Stop! + Fejl + Vejledning + Stop! Det ser ud som om du bruger Magisk/TWRP versionen af Vanced. Den er ikke længere understøttet og kan derfor ikke opdateres igennem denne app. Vær venlig at fjerne magisk modulet/brug TWRP Vanced uninstaller. - For at installere Vanced er du NØDT til at slå MIUI optimering fra i udvikler indstillingerne. (Du kan ignorere denne advarsel hvis du bruger en 20.2.20 eller nyere xiaomi.eu baseret ROM) - MIUI Optimering er aktiveret! - Afslut venligst IKKE appen under denne proces! - Hent igen - Venligst sørg for kun at have downloaded appen fra vancedapp.com, Vanced Discord serveren eller Vanced GitHub siden + For at installere Vanced er du NØDT til at slå MIUI optimering fra i udvikler indstillingerne. (Du kan ignorere denne advarsel hvis du bruger en 20.2.20 eller nyere xiaomi.eu baseret ROM) + MIUI Optimering er aktiveret! + Afslut venligst IKKE appen under denne proces! + Hent igen + Venligst sørg for kun at have downloaded appen fra vancedapp.com, Vanced Discord serveren eller Vanced GitHub siden Version - Velkommen + Velkommen - Vælg dit fortrukne sprog til Vanced - Seneste + Vælg dit fortrukne sprog til Vanced + Seneste Lys + %1$s Vælg mindst ét sprog! - Sort - Mørk + Sort + Mørk - Manager udviklere - Øvrige Bidragsydere - Kilder - Vanced holdet + Manager udviklere + Øvrige Bidragsydere + Kilder + Vanced holdet - Kunne ikke vælge Apk til systemejer, Prøv igen. - Fejl i download af %1$s + Kunne ikke vælge Apk til systemejer, Prøv igen. + Fejl i download af %1$s Kunne ikke anvende ny accentfarve - Fejlede i at fjerne pakke %1$s - Kunne ikke finde de påkrævede filer til installation. Download installationsfilerne igen, og prøv igen. - Kunne ikke finde apk-fil til sort/mørkt tema fra lager. Prøv venligst igen. - Installationen fejlede fordi brugeren lukkede installationen. - Installationen fejlede fordi appen konflikter med en allerede installeret app. Fjern den nuværende version af appen og prøv igen. - Installationen fejlede fordi brugeren prøvede at nedgradere pakken. Fjern opdateringer fra Youtube appen og prøv igen. - Installation mislykkedes af ukendte årsager, kom på vores Telegram eller Discord for yderligere hjælp. Vedhæft venligst også et skærmbillede fra menuen Avanceret - Installationen fejlede fordi installationsfilen er inkompatibel med din enhed. Ryd de downloadede filer i indstillingerne og prøv igen. - Installationen fejlede fordi apk filerne er beskadiget, prøv igen. - Installationen fejlede fordi MIUI optimering er slået til. Slå MIUI optimering fra og prøv igen. - Installationen fejlede fordi apk signatur verifikation er slået til. Slå apk signatur verifikation fra og prøv igen. - Installationen mislykkedes, fordi enheden ikke har nok ledig plads. - Kunne ikke finde apk fil til sort/mørkt tema fra installationsprogrammet. Ryd app data fra Manager, og prøv derefter igen. - Kunne ikke finde lageret YouTube-installationsstien efter split installation. + Fejlede i at fjerne pakke %1$s + Kunne ikke finde de påkrævede filer til installation. Download installationsfilerne igen, og prøv igen. + Kunne ikke finde apk-fil til sort/mørkt tema fra lager. Prøv venligst igen. + Installationen fejlede fordi brugeren lukkede installationen. + Installationen fejlede fordi appen konflikter med en allerede installeret app. Fjern den nuværende version af appen og prøv igen. + Installationen fejlede fordi brugeren prøvede at nedgradere pakken. Fjern opdateringer fra Youtube appen og prøv igen. + Installation mislykkedes af ukendte årsager, kom på vores Telegram eller Discord for yderligere hjælp. Vedhæft venligst også et skærmbillede fra menuen Avanceret + Installationen fejlede fordi installationsfilen er inkompatibel med din enhed. Ryd de downloadede filer i indstillingerne og prøv igen. + Installationen fejlede fordi apk filerne er beskadiget, prøv igen. + Installationen fejlede fordi MIUI optimering er slået til. Slå MIUI optimering fra og prøv igen. + Installationen fejlede fordi apk signatur verifikation er slået til. Slå apk signatur verifikation fra og prøv igen. + Installationen mislykkedes, fordi enheden ikke har nok ledig plads. + Kunne ikke finde apk fil til sort/mørkt tema fra installationsprogrammet. Ryd app data fra Manager, og prøv derefter igen. + Kunne ikke finde lageret YouTube-installationsstien efter split installation. diff --git a/app/src/main/res/values-de-rDE/strings.xml b/app/src/main/res/values-de-rDE/strings.xml index 94e23c7c33..8185681786 100644 --- a/app/src/main/res/values-de-rDE/strings.xml +++ b/app/src/main/res/values-de-rDE/strings.xml @@ -1,120 +1,120 @@ - Abbrechen - Schließen - Eine eigene GMD-Implementation für Vanced, basierend auf dem MicroG-Projekt. - Ein modifizierter YouTube-Client mit vielen nützlichen Funktionen! - Vanced, aber für YouTube Music! Weniger Funktionen, stillt aber deine Bedürfnisse. - Zurücksetzen - Speichern - Wähle deine Apps + Abbrechen + Schließen + Eine eigene GMD-Implementation für Vanced, basierend auf dem MicroG-Projekt. + Ein modifizierter YouTube-Client mit vielen nützlichen Funktionen! + Vanced, aber für YouTube Music! Weniger Funktionen, stillt aber deine Bedürfnisse. + Zurücksetzen + Speichern + Wähle deine Apps - Über - Anleitung - Manager - Protokolle - Einstellungen - Update Manager + Über + Anleitung + Manager + Protokolle + Einstellungen + Update Manager - Ist dein Gerät gerootet? - Root-Berechtigung erteilen - Los geht\'s - Wähle mindestens eine App! - Du weißt nicht was das ist, oder willst die Root-Version nicht benutzen? klicke einfach den blauen Pfeil unten an! + Ist dein Gerät gerootet? + Root-Berechtigung erteilen + Los geht\'s + Wähle mindestens eine App! + Du weißt nicht was das ist, oder willst die Root-Version nicht benutzen? klicke einfach den blauen Pfeil unten an! - Über %1$s - Download - Info - Starten - Neu installieren - Deinstallieren - Aktualisieren - Anwendungen - Änderungen - %1$s wird heruntergeladen - Installieren + Über %1$s + Download + Info + Starten + Neu installieren + Deinstallieren + Aktualisieren + Anwendungen + Änderungen + %1$s wird heruntergeladen + Installieren Neueste: - Installiere zuerst Vanced MicroG + Installiere zuerst Vanced MicroG Root-Zugriff nicht erteilt - Soziale Medien - Unterstütze uns - Nicht verfügbar + Soziale Medien + Unterstütze uns + Nicht verfügbar Installiert: - Akzentfarbe - Darstellung - Verhalten - Heruntergeladene Dateien löschen - Daten erfolgreich gelöscht - Dadurch können wir Informationen über die Performance der App und Absturzprotokolle sammeln - Firebase-Analyse - Sprache - Links werden in Chrome Custom Tabs geöffnet - Verwende Chrome Custom Tabs - %1$s Push-Benachrichtigungen - Push-Benachrichtigungen erhalten, wenn ein Update für %1$s veröffentlicht wird - Speichern des neuen Zeitwertes fehlgeschlagen - Wartezeit des Root-Skriptes - Anpassen des Wertes für die Ruhezeit, der im Skript /data/adb/service.d/app.sh verwendet wird, nützlich zur Behebung von Problemen beim Einbinden - Systemstandard - Theme - Dunkles Theme - Helles Theme - Update Center - Keine neuen Updates - Variante + Akzentfarbe + Darstellung + Verhalten + Heruntergeladene Dateien löschen + Daten erfolgreich gelöscht + Dadurch können wir Informationen über die Performance der App und Absturzprotokolle sammeln + Firebase-Analyse + Sprache + Links werden in Chrome Custom Tabs geöffnet + Verwende Chrome Custom Tabs + %1$s Push-Benachrichtigungen + Push-Benachrichtigungen erhalten, wenn ein Update für %1$s veröffentlicht wird + Speichern des neuen Zeitwertes fehlgeschlagen + Wartezeit des Root-Skriptes + Anpassen des Wertes für die Ruhezeit, der im Skript /data/adb/service.d/app.sh verwendet wird, nützlich zur Behebung von Problemen beim Einbinden + Systemstandard + Theme + Dunkles Theme + Helles Theme + Update Center + Keine neuen Updates + Variante - Protokolle konnten nicht gespeichert werden - Protokolle erfolgreich gespeichert + Protokolle konnten nicht gespeichert werden + Protokolle erfolgreich gespeichert Details - %1$s Installationsdateien erkannt! - Manager hat festgestellt, dass alle notwendigen Dateien für die Installation von %1$s gefunden wurden. Möchtest Du sie installieren? + %1$s Installationsdateien erkannt! + Manager hat festgestellt, dass alle notwendigen Dateien für die Installation von %1$s gefunden wurden. Möchtest Du sie installieren? %1$s Installationsoptionen - Suche nach Updates… + Suche nach Updates… Sprache(n): %1$s Theme: %1$s Version: %1$s - Fehler - Erklärung - Stopp! + Fehler + Erklärung + Stopp! Du benutzt die Magisk/TWRP-Version von Vanced, die nicht mehr unterstützt wird und mit dieser App nicht aktualisiert werden kann. Bitte entferne siie indem du das Magisk-Modul mit dem TWRP Vanced Uninstaller entfernst. - Um Vanced installieren zu können, MÜSSEN Sie MIUI Optimierungen in den Entwickleroptionen deaktivieren. (Bitte ignorieren Sie diese Warnung, wenn Sie xiaomi.eu Roms mit der Version 20.2.20 oder höher verwenden.) - MIUI Optimierungen sind aktiviert! - Bitte schließen Sie die App NICHT während dieses Prozesses! - Erneut herunterladen - Stelle sicher, dass du die App von vancedapp.com, dem Vanced Discord Server oder dem Vanced GitHub heruntergeladen hast + Um Vanced installieren zu können, MÜSSEN Sie MIUI Optimierungen in den Entwickleroptionen deaktivieren. (Bitte ignorieren Sie diese Warnung, wenn Sie xiaomi.eu Roms mit der Version 20.2.20 oder höher verwenden.) + MIUI Optimierungen sind aktiviert! + Bitte schließen Sie die App NICHT während dieses Prozesses! + Erneut herunterladen + Stelle sicher, dass du die App von vancedapp.com, dem Vanced Discord Server oder dem Vanced GitHub heruntergeladen hast Version - Willkommen + Willkommen - Wählen Sie ihre bevorzugte Sprache(n) für Vanced - Neueste + Wählen Sie ihre bevorzugte Sprache(n) für Vanced + Neueste Hell + %1$s Wähle mindestens eine Sprache aus! - Schwarz - Dunkel + Schwarz + Dunkel - Manager-Entwickler - Weitere Mitwirkende - Quellen - Vanced Team + Manager-Entwickler + Weitere Mitwirkende + Quellen + Vanced Team - Fehler beim `chown` der APK zum Systembesitzer, bitte versuche es erneut. - Download von %1$s fehlgeschlagen + Fehler beim `chown` der APK zum Systembesitzer, bitte versuche es erneut. + Download von %1$s fehlgeschlagen Neue Akzentfarbe konnte nicht angewendet werden - Entfernen von %1$s fehlgeschlagen - Die benötigten Dateien für die Installation konnten nicht gefunden werden. Laden Sie die Installationsdateien erneut herunter und versuchen Sie es erneut. - Apk-Datei für schwarzes/dunkles Theme konnte nicht gefunden werden, bitte versuchen Sie es erneut. - Installation fehlgeschlagen, da der Benutzer die Installation abgebrochen hat. - Die Installation ist fehlgeschlagen, weil die App in Konflikt mit einer bereits installierten App steht. Deinstalliere die aktuell installierte Version der App und versuchen es dann erneut. - Installation fehlgeschlagen, da der Benutzer versucht hat, eine ältere Version des Paketes zu installieren. Deinstallieren Sie Updates von der YouTube App und versuchen Sie es erneut. - Die Installation ist aus unbekannten Gründen fehlgeschlagen. Betrete unser Telegram Chat oder Discord Server für weitere Unterstützung und halte bitte einen Screenshot aus dem erweiterten Menü bereit - Installation fehlgeschlagen, da die Installationsdatei nicht mit Ihrem Gerät kompatibel ist. Löschen Sie heruntergeladene Dateien in den Einstellungen, dann versuchen Sie es erneut. - Installation fehlgeschlagen, da die apk-Dateien beschädigt sind, bitte versuchen Sie es erneut. - Installation fehlgeschlagen, da die MIUI-Optimierung aktiviert ist. Deaktivieren Sie die MIUI-Optimierung, und versuchen Sie es erneut. - Installation fehlgeschlagen, da die apk Signaturüberprüfung aktiviert ist. Deaktivieren Sie die apk Signaturüberprüfung, dann versuchen Sie es erneut. - Installation fehlgeschlagen, da das Gerät nicht genügend freien Speicherplatz hat. - Apk-Datei für schwarzes/dunkles Theme konnte nicht gefunden werden. Löschen Sie die App-Daten des Managers und versuchen Sie es erneut. - Fehler beim Auffinden des YouTube-Installationspfades nach der geteilten Installation. + Entfernen von %1$s fehlgeschlagen + Die benötigten Dateien für die Installation konnten nicht gefunden werden. Laden Sie die Installationsdateien erneut herunter und versuchen Sie es erneut. + Apk-Datei für schwarzes/dunkles Theme konnte nicht gefunden werden, bitte versuchen Sie es erneut. + Installation fehlgeschlagen, da der Benutzer die Installation abgebrochen hat. + Die Installation ist fehlgeschlagen, weil die App in Konflikt mit einer bereits installierten App steht. Deinstalliere die aktuell installierte Version der App und versuchen es dann erneut. + Installation fehlgeschlagen, da der Benutzer versucht hat, eine ältere Version des Paketes zu installieren. Deinstallieren Sie Updates von der YouTube App und versuchen Sie es erneut. + Die Installation ist aus unbekannten Gründen fehlgeschlagen. Betrete unser Telegram Chat oder Discord Server für weitere Unterstützung und halte bitte einen Screenshot aus dem erweiterten Menü bereit + Installation fehlgeschlagen, da die Installationsdatei nicht mit Ihrem Gerät kompatibel ist. Löschen Sie heruntergeladene Dateien in den Einstellungen, dann versuchen Sie es erneut. + Installation fehlgeschlagen, da die apk-Dateien beschädigt sind, bitte versuchen Sie es erneut. + Installation fehlgeschlagen, da die MIUI-Optimierung aktiviert ist. Deaktivieren Sie die MIUI-Optimierung, und versuchen Sie es erneut. + Installation fehlgeschlagen, da die apk Signaturüberprüfung aktiviert ist. Deaktivieren Sie die apk Signaturüberprüfung, dann versuchen Sie es erneut. + Installation fehlgeschlagen, da das Gerät nicht genügend freien Speicherplatz hat. + Apk-Datei für schwarzes/dunkles Theme konnte nicht gefunden werden. Löschen Sie die App-Daten des Managers und versuchen Sie es erneut. + Fehler beim Auffinden des YouTube-Installationspfades nach der geteilten Installation. diff --git a/app/src/main/res/values-el-rGR/strings.xml b/app/src/main/res/values-el-rGR/strings.xml index c01473c611..38b920645f 100644 --- a/app/src/main/res/values-el-rGR/strings.xml +++ b/app/src/main/res/values-el-rGR/strings.xml @@ -1,120 +1,120 @@ - Ακύρωση - Κλείσιμο - Μια πειραγμένη εκδοχή των GMS (υπηρεσιών κινητής της Google) για το Vanced βασισμένη στο έργο του microG. - Μια πειραγμένη εφαρμογή του YouTube με πολλά χρήσιμα χαρακτηριστικά! - Vanced, αλλά για το YouTube Music! Λιγότερο πλούσιο σε χαρακτηριστικά αλλά καλύπτει τις ανάγκες σας. - Επαναφορά - Αποθήκευση - Επιλέξτε τις εφαρμογές σας + Ακύρωση + Κλείσιμο + Μια πειραγμένη εκδοχή των GMS (υπηρεσιών κινητής της Google) για το Vanced βασισμένη στο έργο του microG. + Μια πειραγμένη εφαρμογή του YouTube με πολλά χρήσιμα χαρακτηριστικά! + Vanced, αλλά για το YouTube Music! Λιγότερο πλούσιο σε χαρακτηριστικά αλλά καλύπτει τις ανάγκες σας. + Επαναφορά + Αποθήκευση + Επιλέξτε τις εφαρμογές σας - Πληροφορίες - Οδηγός για το Vanced - Διαχειριστής Vanced - Αρχείο καταγραφής σφαλμάτων - Ρυθμίσεις - Ενημέρωση Διαχειριστή Vanced + Πληροφορίες + Οδηγός για το Vanced + Διαχειριστής Vanced + Αρχείο καταγραφής σφαλμάτων + Ρυθμίσεις + Ενημέρωση Διαχειριστή Vanced - Έχετε πρόσβαση Root στη συσκευή σας; - Χορήγηση Άδειας Root - Ας ξεκινήσουμε - Επιλέξτε τουλάχιστον μια εφαρμογή! - Δεν ξέρετε τι είναι αυτό ή δεν θέλετε να χρησιμοποιήσετε την έκδοση root; Τότε απλώς πατήστε το μπλε βέλος παρακάτω! + Έχετε πρόσβαση Root στη συσκευή σας; + Χορήγηση Άδειας Root + Ας ξεκινήσουμε + Επιλέξτε τουλάχιστον μια εφαρμογή! + Δεν ξέρετε τι είναι αυτό ή δεν θέλετε να χρησιμοποιήσετε την έκδοση root; Τότε απλώς πατήστε το μπλε βέλος παρακάτω! - Σχετικά με το %1$s - Λήψη - Πληροφορίες - Εκκίνηση - Επανεγκατάσταση - Απεγκατάσταση - Ενημέρωση - Εφαρμογές - Αρχείο καταγραφής αλλαγών - Λήψη %1$s - Εγκατάσταση + Σχετικά με το %1$s + Λήψη + Πληροφορίες + Εκκίνηση + Επανεγκατάσταση + Απεγκατάσταση + Ενημέρωση + Εφαρμογές + Αρχείο καταγραφής αλλαγών + Λήψη %1$s + Εγκατάσταση Τελευταία έκδοση: - Εγκαταστήστε πρώτα το Vanced microG + Εγκαταστήστε πρώτα το Vanced microG Δεν επιτράπηκε η πρόσβαση Root - Μέσα Κοινωνικής Δικτύωσης - Υποστηρίξτε μας - Μη διαθέσιμο + Μέσα Κοινωνικής Δικτύωσης + Υποστηρίξτε μας + Μη διαθέσιμο Εγκατεστημένη έκδοση: - Χρώμα Διεπαφής - Εμφάνιση - Συμπεριφορά - Εκκαθάριση ληφθέντων αρχείων - Επιτυχής εκκαθάριση αρχείων - Αυτό μας επιτρέπει να συλλέγουμε πληροφορίες σχετικά με την επίδοση της εφαρμογής και σχετικά με καταγραφές σφαλμάτων λογισμικού - Firebase Analytics - Γλώσσα - Οι σύνδεσμοι θα ανοίγουν σε προσαρμοσμένες καρτέλες chrome - Χρήση προσαρμοσμένων καρτέλων Chrome - Ειδοποιήσεις Push για το %1$s - Λάβεται ειδοποιήσεις push όταν υπάρχουν διαθέσιμες ενημερώσεις για το %1$s - Αποτυχία αποθήκευσης νέας τιμής χρόνου - Σενάριο Χρόνου Αδράνειας Root - Ρυθμίστε στην τιμη του χρόνου αδράνειας που βρίσκετε στο αρχείο σενάριο /data/adb/service.d/app.sh, χρήσιμο για επιδιόρθωση προβλημάτων προσάρτησης - Προεπιλογή Συστήματος - Θέμα - Σκουρόχρωμο Θέμα - Ανοιχτόχρωμο Θέμα - Κέντρο ενημερώσεων - Δεν υπάρχουν νέες ενημερώσεις - Παραλλαγή + Χρώμα Διεπαφής + Εμφάνιση + Συμπεριφορά + Εκκαθάριση ληφθέντων αρχείων + Επιτυχής εκκαθάριση αρχείων + Αυτό μας επιτρέπει να συλλέγουμε πληροφορίες σχετικά με την επίδοση της εφαρμογής και σχετικά με καταγραφές σφαλμάτων λογισμικού + Firebase Analytics + Γλώσσα + Οι σύνδεσμοι θα ανοίγουν σε προσαρμοσμένες καρτέλες chrome + Χρήση προσαρμοσμένων καρτέλων Chrome + Ειδοποιήσεις Push για το %1$s + Λάβεται ειδοποιήσεις push όταν υπάρχουν διαθέσιμες ενημερώσεις για το %1$s + Αποτυχία αποθήκευσης νέας τιμής χρόνου + Σενάριο Χρόνου Αδράνειας Root + Ρυθμίστε στην τιμη του χρόνου αδράνειας που βρίσκετε στο αρχείο σενάριο /data/adb/service.d/app.sh, χρήσιμο για επιδιόρθωση προβλημάτων προσάρτησης + Προεπιλογή Συστήματος + Θέμα + Σκουρόχρωμο Θέμα + Ανοιχτόχρωμο Θέμα + Κέντρο ενημερώσεων + Δεν υπάρχουν νέες ενημερώσεις + Παραλλαγή - Αδυναμία αποθήκευσης αρχείου καταγραφής σφαλμάτων - Επιτυχής αποθήκευση αρχείου καταγραφής σφαλμάτων + Αδυναμία αποθήκευσης αρχείου καταγραφής σφαλμάτων + Επιτυχής αποθήκευση αρχείου καταγραφής σφαλμάτων Πληροφορίες - Ανιχνεύτηκαν τα αρχεία εγκατάστασης του %1$s! - Ο Διαχειριστής του Vanced ανίχνευσε ότι βρέθηκαν όλα τα απαραίτητα αρχεία για την εγκατάσταση του %1$s. Θέλετε να εγκατασταθεί; + Ανιχνεύτηκαν τα αρχεία εγκατάστασης του %1$s! + Ο Διαχειριστής του Vanced ανίχνευσε ότι βρέθηκαν όλα τα απαραίτητα αρχεία για την εγκατάσταση του %1$s. Θέλετε να εγκατασταθεί; Προτιμήσεις Εγκατάστασης του %1$s - Έλεγχος για ενημερώσεις… + Έλεγχος για ενημερώσεις… Γλώσσα(/ες): %1$s Θέμα: %1$s Έκδοση: %1$s - Σφάλμα - Οδηγίες - Σταματήστε! + Σφάλμα + Οδηγίες + Σταματήστε! Χρησιμοποιείτε την έκδοση Magisk/TWRP του Vanced, η οποία δεν υποστηρίζεται πλέον και δεν μπορεί να ενημερωθεί μέσω αυτής της εφαρμογής. Παρακαλούμε αφαιρέστε αυτή την έκδοση αφαιρώντας το Magisk Module/χρησιμοποιόντας το πρόγραμμα κατάργησης TWRP Vanced. - Για να εγκαταστήσετε το Vanced, ΠΡΕΠΕΙ να απενεργοποιήσετε τις Βελτιστοποιήσεις MIUI στις ρυθμίσεις για προγραμματιστές. (Μπορείτε να αγνοήσετε αυτή την προειδοποίηση αν χρησιμοποιείτε την έκδοση ROM 20.2.20 ή μεταγενέστερη, βάσει του xiaomi.eu) - Η βελτιστοποίηση MIUI είναι ενεργή! - Παρακαλώ ΜΗΝ βγείτε από την εφαρμογή κατά τη διάρκεια αυτής της διαδικασίας! - Επανάληψη λήψης - Βεβαιωθείτε ότι κάνατε λήψη της εφαρμογής από το vancedapp.com, τον διακομιστή Discord του Vanced ή το GitHub του Vanced + Για να εγκαταστήσετε το Vanced, ΠΡΕΠΕΙ να απενεργοποιήσετε τις Βελτιστοποιήσεις MIUI στις ρυθμίσεις για προγραμματιστές. (Μπορείτε να αγνοήσετε αυτή την προειδοποίηση αν χρησιμοποιείτε την έκδοση ROM 20.2.20 ή μεταγενέστερη, βάσει του xiaomi.eu) + Η βελτιστοποίηση MIUI είναι ενεργή! + Παρακαλώ ΜΗΝ βγείτε από την εφαρμογή κατά τη διάρκεια αυτής της διαδικασίας! + Επανάληψη λήψης + Βεβαιωθείτε ότι κάνατε λήψη της εφαρμογής από το vancedapp.com, τον διακομιστή Discord του Vanced ή το GitHub του Vanced Έκδοση - Καλώς ορίσατε + Καλώς ορίσατε - Επιλέξτε την(/ις) γλώσσα(/ες) που επιθυμείτε για το Vanced - Τελευταία + Επιλέξτε την(/ις) γλώσσα(/ες) που επιθυμείτε για το Vanced + Τελευταία Ανοιχτόχρωμο + %1$s Επιλέξτε τουλάχιστον μια γλώσσα! - Μαύρο - Σκουρόχρωμο + Μαύρο + Σκουρόχρωμο - Προγραμματιστές Διαχειριστή Vanced - Άλλοι Συνεισφέροντες - Πηγές - Η ομάδα του Vanced + Προγραμματιστές Διαχειριστή Vanced + Άλλοι Συνεισφέροντες + Πηγές + Η ομάδα του Vanced - Αποτυχία παραχώρησης ιδιοκτησίας του APK στον κάτοχο συστήματος, παρακαλούμε προσπαθείστε ξανά. - Σφάλμα λήψης του %1$s + Αποτυχία παραχώρησης ιδιοκτησίας του APK στον κάτοχο συστήματος, παρακαλούμε προσπαθείστε ξανά. + Σφάλμα λήψης του %1$s Αδυναμία εφαρμογής χρώματος διεπαφής - Αποτυχία απεγκατάστασης πακέτου %1$s - Αδυναμία εντοπισμού των απαιτούμενων αρχείων για την εγκατάσταση. Κατεβάστε τα αρχεία εγκατάστασης, και προσπαθήστε ξανά. - Αδυναμία εντοπισμού του αρχείου apk σκουρόχρωμου/απολύτου μαύρου θέματος στον αποθηκευτικό χώρο, παρακαλώ προσπαθήστε ξανά. - Η εγκατάσταση απέτυχε διότι ο χρήστης ακύρωσε την εγκατάσταση. - Η εγκατάσταση απέτυχε διότι η εφαρμογή αντικρούεται με μια ήδη εγκατεστημένη εφαρμογή. Κάντε απεγκατάσταση την τρέχουσα έκδοση της εφαρμογής, και μετά προσπαθήστε ξανά. - Η εγκατάσταση απέτυχε διότι ο χρήστης προσπάθησε να υποβαθμίσει το πακέτο. Απεγκαταστήστε τις ενημερώσεις της αρχικής εφαρμογής YouTube, στη συνέχεια προσπαθήστε ξανά. - Η εγκατάσταση απέτυχε για άγνωστους λόγους, μπείτε στο Telegram ή στο Discord μας για περαιτέρω υποστήριξη. Παρακαλώ επισυνάψτε ένα στιγμιότυπο οθόνης από τις επιλογές για προχωρημένους - Η εγκατάσταση απέτυχε διότι το αρχείο εγκατάστασης είναι μη συμβατό με την συσκευή σας. Κάντε εκκαθάριση των ληφθέντων αρχείων στις ρυθμίσεις, στην συνέχεια προσπαθήστε ξανά. - Η εγκατάσταση απέτυχε διότι τα αρχεία apk έχουν διαφθαρεί, παρακαλώ προσπαθήστε ξανά. - Η εγκατάσταση απέτυχε διότι η βελτιστοποίηση MIUI είναι ενεργή. Απενεργοποιήστε την βελτιστοποίηση MIUI, και προσπαθήστε ξανά. - Η εγκατάσταση απέτυχε διότι η επαλήθευση υπογραφής των apk είναι ενεργή. Απενεργοποιήστε την επαλήθευση υπογραφής apk, στην συνέχεια προσπαθήστε ξανά. - Η εγκατάσταση απέτυχε διότι δεν υπάρχει αρκετός ελεύθερος χώρος στη συσκευή σας. - Αδυναμία εύρεσης του αρχείου apk σκουρόχρωμου/απολύτου μαύρου θέματος από το πρόγραμμα εγκατάστασης. Κάνετε εκκαθάριση των δεδομένων του διαχειριστή Vanced, στην συνέχεια προσπαθήστε ξανά. - Αδυναμία εύρεσης της διαδρομής εγκατάστασης της αρχικής εφαρμογής YouTube μετά από εγκατάσταση σε τεμάχια. + Αποτυχία απεγκατάστασης πακέτου %1$s + Αδυναμία εντοπισμού των απαιτούμενων αρχείων για την εγκατάσταση. Κατεβάστε τα αρχεία εγκατάστασης, και προσπαθήστε ξανά. + Αδυναμία εντοπισμού του αρχείου apk σκουρόχρωμου/απολύτου μαύρου θέματος στον αποθηκευτικό χώρο, παρακαλώ προσπαθήστε ξανά. + Η εγκατάσταση απέτυχε διότι ο χρήστης ακύρωσε την εγκατάσταση. + Η εγκατάσταση απέτυχε διότι η εφαρμογή αντικρούεται με μια ήδη εγκατεστημένη εφαρμογή. Κάντε απεγκατάσταση την τρέχουσα έκδοση της εφαρμογής, και μετά προσπαθήστε ξανά. + Η εγκατάσταση απέτυχε διότι ο χρήστης προσπάθησε να υποβαθμίσει το πακέτο. Απεγκαταστήστε τις ενημερώσεις της αρχικής εφαρμογής YouTube, στη συνέχεια προσπαθήστε ξανά. + Η εγκατάσταση απέτυχε για άγνωστους λόγους, μπείτε στο Telegram ή στο Discord μας για περαιτέρω υποστήριξη. Παρακαλώ επισυνάψτε ένα στιγμιότυπο οθόνης από τις επιλογές για προχωρημένους + Η εγκατάσταση απέτυχε διότι το αρχείο εγκατάστασης είναι μη συμβατό με την συσκευή σας. Κάντε εκκαθάριση των ληφθέντων αρχείων στις ρυθμίσεις, στην συνέχεια προσπαθήστε ξανά. + Η εγκατάσταση απέτυχε διότι τα αρχεία apk έχουν διαφθαρεί, παρακαλώ προσπαθήστε ξανά. + Η εγκατάσταση απέτυχε διότι η βελτιστοποίηση MIUI είναι ενεργή. Απενεργοποιήστε την βελτιστοποίηση MIUI, και προσπαθήστε ξανά. + Η εγκατάσταση απέτυχε διότι η επαλήθευση υπογραφής των apk είναι ενεργή. Απενεργοποιήστε την επαλήθευση υπογραφής apk, στην συνέχεια προσπαθήστε ξανά. + Η εγκατάσταση απέτυχε διότι δεν υπάρχει αρκετός ελεύθερος χώρος στη συσκευή σας. + Αδυναμία εύρεσης του αρχείου apk σκουρόχρωμου/απολύτου μαύρου θέματος από το πρόγραμμα εγκατάστασης. Κάνετε εκκαθάριση των δεδομένων του διαχειριστή Vanced, στην συνέχεια προσπαθήστε ξανά. + Αδυναμία εύρεσης της διαδρομής εγκατάστασης της αρχικής εφαρμογής YouTube μετά από εγκατάσταση σε τεμάχια. diff --git a/app/src/main/res/values-es-rES/strings.xml b/app/src/main/res/values-es-rES/strings.xml index fccb8f5892..b4998cc7b7 100644 --- a/app/src/main/res/values-es-rES/strings.xml +++ b/app/src/main/res/values-es-rES/strings.xml @@ -1,120 +1,120 @@ - Cancelar - Cerrar - Una implementación de GMS personalizada para Vanced basada en el proyecto microG. - ¡Un cliente de YouTube modificado con muchas características útiles! - Vanced, pero para YouTube Music! Tiene relativamente menos características, pero satisface tus necesidades. - Restablecer - Guardar - Selecciona tus aplicaciones + Cancelar + Cerrar + Una implementación de GMS personalizada para Vanced basada en el proyecto microG. + ¡Un cliente de YouTube modificado con muchas características útiles! + Vanced, pero para YouTube Music! Tiene relativamente menos características, pero satisface tus necesidades. + Restablecer + Guardar + Selecciona tus aplicaciones - Información - Guía - Manager - Registros - Ajustes - Actualizar Manager + Información + Guía + Manager + Registros + Ajustes + Actualizar Manager - ¿Su dispositivo está rooteado? - Otorgar permiso root - Comencemos - ¡Seleccione al menos una aplicación! - ¿No sabes que es esto o no quieres usar la versión root? ¡Haz clic en la flecha azul de abajo! + ¿Su dispositivo está rooteado? + Otorgar permiso root + Comencemos + ¡Seleccione al menos una aplicación! + ¿No sabes que es esto o no quieres usar la versión root? ¡Haz clic en la flecha azul de abajo! - Acerca de %1$s - Descargar - Info - Iniciar - Reinstalar - Desinstalar - Actualizar - Apps - Historial de actualizaciones - Descargando %1$s - Instalar + Acerca de %1$s + Descargar + Info + Iniciar + Reinstalar + Desinstalar + Actualizar + Apps + Historial de actualizaciones + Descargando %1$s + Instalar Más reciente: - Primero, instala Vanced microG + Primero, instala Vanced microG Acceso root no concedido - Redes Sociales - Apóyanos - No Disponible + Redes Sociales + Apóyanos + No Disponible Instalado: - Color de Acento - Apariencia - Comportamiento - Limpiar archivos descargados - Archivos limpiados exitosamente - Esto nos permite recopilar información sobre el rendimiento de la aplicación y los registros de errores - Analíticas de Firebase - Idioma - Links serán abiertos en Chrome Custom Tabs - Usar Chrome Custom Tabs - Notificaciones push de %1$s - Recibir notificaciones push cuando una actualización para %1$s sea lanzada - Error al guardar el nuevo valor de tiempo - Tiempo de reposo de la secuencia de comandos de la raíz - Ajustar el valor de tiempo de reposo en el script /data/adb/service.d/app.sh, útil para arreglar problemas de montaje - Predeterminado del sistema - Tema - Tema Oscuro - Tema Claro - Centro de Actualizaciones - Sin actualizaciónes nuevas - Variante + Color de Acento + Apariencia + Comportamiento + Limpiar archivos descargados + Archivos limpiados exitosamente + Esto nos permite recopilar información sobre el rendimiento de la aplicación y los registros de errores + Analíticas de Firebase + Idioma + Links serán abiertos en Chrome Custom Tabs + Usar Chrome Custom Tabs + Notificaciones push de %1$s + Recibir notificaciones push cuando una actualización para %1$s sea lanzada + Error al guardar el nuevo valor de tiempo + Tiempo de reposo de la secuencia de comandos de la raíz + Ajustar el valor de tiempo de reposo en el script /data/adb/service.d/app.sh, útil para arreglar problemas de montaje + Predeterminado del sistema + Tema + Tema Oscuro + Tema Claro + Centro de Actualizaciones + Sin actualizaciónes nuevas + Variante - No se pudieron guardar los registros - Registros guardados con éxito + No se pudieron guardar los registros + Registros guardados con éxito Detalles - ¡%1$s archivos de instalación detectados! - El Manager detectó que todos los archivos necesarios para la instalación de %1$s se encontraron. ¿Quieres instalarlo? + ¡%1$s archivos de instalación detectados! + El Manager detectó que todos los archivos necesarios para la instalación de %1$s se encontraron. ¿Quieres instalarlo? %1$s Preferencias de instalación - Buscando actualizaciones… + Buscando actualizaciones… Idioma(s): %1$s Tema: %1$s Versión: %1$s - Error - Guía - ¡Detente! + Error + Guía + ¡Detente! Estás usando la versión Magisk/TWRP de Vanced, la cual está descontinuada y no puede ser actualizada usando esta aplicación. Por favor, remuevala eliminando el módulo Magisk o usando el desinstalador TWRP Vanced. - Para instalar Vanced, DEBES desabilitar las optimizaciones MIUI en las opciones de desarrollador. (Puedes ignorar esta advertencia si estás usando un ROM basado en xiaomi.eu 20.2.20 o posterior) - ¡Optimizaciones MIUI habilitadas! - ¡Por favor, NO salga de la aplicación durante este proceso! - Volver a descargar - Asegúrate de haber descargado la app desde vancedapp.com, el grupo de Discord de Vanced, o el GitHub de Vanced + Para instalar Vanced, DEBES desabilitar las optimizaciones MIUI en las opciones de desarrollador. (Puedes ignorar esta advertencia si estás usando un ROM basado en xiaomi.eu 20.2.20 o posterior) + ¡Optimizaciones MIUI habilitadas! + ¡Por favor, NO salga de la aplicación durante este proceso! + Volver a descargar + Asegúrate de haber descargado la app desde vancedapp.com, el grupo de Discord de Vanced, o el GitHub de Vanced Versión - Bienvenido + Bienvenido - Elige tu(s) idioma(s) preferido(s) para Vanced - Más reciente + Elige tu(s) idioma(s) preferido(s) para Vanced + Más reciente Claro + %1$s ¡Seleccione al menos un idioma! - Negro - Oscuro + Negro + Oscuro - Desarrolladores del Manager - Otros colaboradores - Fuentes - Equipo Vanced + Desarrolladores del Manager + Otros colaboradores + Fuentes + Equipo Vanced - Fallo al ejecutar `chown` al propietario del sistema, por favor inténtalo de nuevo. - Error al descargar %1$s + Fallo al ejecutar `chown` al propietario del sistema, por favor inténtalo de nuevo. + Error al descargar %1$s Falla al aplicar el nuevo color de acento - Falla al desinstalar paquete %1$s - Falla al localizar los archivos necesarios para la instalación. Vuelva a descargar los archivos de instalación y vuelva a intentarlo. - Falla al localizar en el almacenamiento el archivo apk para el tema negro/oscuro, por favor intente otra vez. - La instalación ha fallado debido a que el usuario ha abortado la instalación. - La instalación ha fallado porque la aplicación entra en conflicto con una aplicación ya instalada. Desinstala la versión actual de la aplicación y vuelve a intentarlo. - La instalación falló porque el usuario trató de degradar el paquete. Desinstala las actualizaciones de la aplicación original e intenta de nuevo. - La instalación ha fallado por razones desconocidas, únete a nuestro Telegram o Discord para más soporte. Por favor, también adjunta una captura de pantalla desde el menú Avanzado - La instalación ha fallado porque el archivo de instalación es incompatible con tu dispositivo. Limpia los archivos descargados en la ajustes y vuelve a intentarlo. - La instalación falló porque los archivos apk están corruptos, por favor inténtalo de nuevo. - La instalación ha fallado porque la Optimización MIUI está activada. Desactiva la optimización MIUI y vuelva a intentarlo. - La instalación ha fallado porque la verificación de firmas de apk está habilitada. Desactiva la verificación de la firmas de apk, y vuelve a intentarlo. - La instalación falló porque el dispositivo no tiene suficiente espacio libre. - Falla al encontrar en el instalador el archivo apk para el tema negro/oscuro. Limpia los datos del Manager y vuelva a intentarlo. - Falla al localizar la ruta de instalación de YouTube después de la instalación split. + Falla al desinstalar paquete %1$s + Falla al localizar los archivos necesarios para la instalación. Vuelva a descargar los archivos de instalación y vuelva a intentarlo. + Falla al localizar en el almacenamiento el archivo apk para el tema negro/oscuro, por favor intente otra vez. + La instalación ha fallado debido a que el usuario ha abortado la instalación. + La instalación ha fallado porque la aplicación entra en conflicto con una aplicación ya instalada. Desinstala la versión actual de la aplicación y vuelve a intentarlo. + La instalación falló porque el usuario trató de degradar el paquete. Desinstala las actualizaciones de la aplicación original e intenta de nuevo. + La instalación ha fallado por razones desconocidas, únete a nuestro Telegram o Discord para más soporte. Por favor, también adjunta una captura de pantalla desde el menú Avanzado + La instalación ha fallado porque el archivo de instalación es incompatible con tu dispositivo. Limpia los archivos descargados en la ajustes y vuelve a intentarlo. + La instalación falló porque los archivos apk están corruptos, por favor inténtalo de nuevo. + La instalación ha fallado porque la Optimización MIUI está activada. Desactiva la optimización MIUI y vuelva a intentarlo. + La instalación ha fallado porque la verificación de firmas de apk está habilitada. Desactiva la verificación de la firmas de apk, y vuelve a intentarlo. + La instalación falló porque el dispositivo no tiene suficiente espacio libre. + Falla al encontrar en el instalador el archivo apk para el tema negro/oscuro. Limpia los datos del Manager y vuelva a intentarlo. + Falla al localizar la ruta de instalación de YouTube después de la instalación split. diff --git a/app/src/main/res/values-et-rEE/strings.xml b/app/src/main/res/values-et-rEE/strings.xml index afb565464f..249569f428 100644 --- a/app/src/main/res/values-et-rEE/strings.xml +++ b/app/src/main/res/values-et-rEE/strings.xml @@ -1,120 +1,120 @@ - Katkesta - Sulge - A custom GMS Implementation for Vanced based on the microG Project. - A modified YouTube client with many useful features! - Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. - Lähtesta - Salvesta - Valige Oma Rakendused + Katkesta + Sulge + A custom GMS Implementation for Vanced based on the microG Project. + A modified YouTube client with many useful features! + Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. + Lähtesta + Salvesta + Valige Oma Rakendused - Teave - Juhend - Haldur - Logid - Seaded - Uuenduste Haldur + Teave + Juhend + Haldur + Logid + Seaded + Uuenduste Haldur - Kas teie seade on juuritud? - Anna juurluba - Alustame - Vali vähemalt üks rakendus! - Kas te ei tea mis see on, või ei soovi kasutada rooditud versiooni? vajutage allpool sinist noolt! + Kas teie seade on juuritud? + Anna juurluba + Alustame + Vali vähemalt üks rakendus! + Kas te ei tea mis see on, või ei soovi kasutada rooditud versiooni? vajutage allpool sinist noolt! - Umbes %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - Rakendused - Muudatuste logi - Allalaadimine %1$s - Installi + Umbes %1$s + Download + Info + Launch + Reinstall + Uninstall + Update + Rakendused + Muudatuste logi + Allalaadimine %1$s + Installi Uusim: - Installi Vanced MicroG esimesena + Installi Vanced MicroG esimesena Administraatoriõigusi ei tagatud - Sotsiaalmeedia - Toetage meid - Pole saadaval + Sotsiaalmeedia + Toetage meid + Pole saadaval Installitud: - Rõhuvärv - Välimus - Käitumine - Tühjenda allalaaditud failid - Failid on edukalt puhastatud - See lubab meil koguda informatsiooni äpi jõudluse ja rikkelogi kohta - Firebase Analytics - Keel - Lingid avatakse Chrome kohandatud vahekaartides - Kasuta Chrome kohandatud vahekaarte - %1$s Hüpikteated - Saa hüpikteateid kui %1$s uuendus on saadaval - Aja uue väärtuse salvestamine ebaõnnestus - Uneaja skript - Reguleerige uneaja väärtust, mis on kasutatav /data/adb/service.d/app.sh skriptis, see on kasulik paigaldusprobleemide parandamiseks - Süsteemi vaikimisi - Kujundus - Tume Kujundus - Hele Kujundus - Halduri värskenduskeskus - Uusi uuendusi ei ole - Variant + Rõhuvärv + Välimus + Käitumine + Tühjenda allalaaditud failid + Failid on edukalt puhastatud + See lubab meil koguda informatsiooni äpi jõudluse ja rikkelogi kohta + Firebase Analytics + Keel + Lingid avatakse Chrome kohandatud vahekaartides + Kasuta Chrome kohandatud vahekaarte + %1$s Hüpikteated + Saa hüpikteateid kui %1$s uuendus on saadaval + Aja uue väärtuse salvestamine ebaõnnestus + Uneaja skript + Reguleerige uneaja väärtust, mis on kasutatav /data/adb/service.d/app.sh skriptis, see on kasulik paigaldusprobleemide parandamiseks + Süsteemi vaikimisi + Kujundus + Tume Kujundus + Hele Kujundus + Halduri värskenduskeskus + Uusi uuendusi ei ole + Variant - Ei suutnud salvestada logi - Edukalt salvestatud logid + Ei suutnud salvestada logi + Edukalt salvestatud logid Üksikasjad - %1$s paigaldusfailid on leitud! - Haldur tuvastas, et kõik failid paigaldamaks %1$s on leitud. Kas soovite seda paigaldada? + %1$s paigaldusfailid on leitud! + Haldur tuvastas, et kõik failid paigaldamaks %1$s on leitud. Kas soovite seda paigaldada? %1$s Paigalduseelistused - Uuenduste otsimine… + Uuenduste otsimine… Keel(ed): %1$s Kujundus: %1$s Versioon: %1$s - Viga - Juhend - Peata! + Viga + Juhend + Peata! Te kasutate Vanced Magisk/TWRP versiooni, mis on katkestatud, ning seda ei saa uuendada kasutades seda äppi. Palun eemaldage Magisk moodul kasutades TWRP Vanced eemaldajat. - Et paigaldada Vanced, PEAB keelama MIUI optimiseerimise arendaja valikute alt. (Võite seda igroneerida kui kasutate 20.2.20 või uuemat xiaomi.eu põhist ROMi) - MIUI optimiseerimine on lubatud! - Palun ärge väljuge rakendusest protsessi ajal! - Lae uuesti alla - Veenduge, et laadisite rakenduse alla vancedapp.com, Vanced Discordi serverist või Vanced GitHubist + Et paigaldada Vanced, PEAB keelama MIUI optimiseerimise arendaja valikute alt. (Võite seda igroneerida kui kasutate 20.2.20 või uuemat xiaomi.eu põhist ROMi) + MIUI optimiseerimine on lubatud! + Palun ärge väljuge rakendusest protsessi ajal! + Lae uuesti alla + Veenduge, et laadisite rakenduse alla vancedapp.com, Vanced Discordi serverist või Vanced GitHubist Versioon - Tere tulemast + Tere tulemast - Valige eelistatud keel(ed) Vanced jaoks - Uusim + Valige eelistatud keel(ed) Vanced jaoks + Uusim Hele + %1$s Vali vähemalt üks keel! - Must - Tume + Must + Tume - Halduri arendajad - Teised kaastöötajad - Allikad - Vanced Meeskond + Halduri arendajad + Teised kaastöötajad + Allikad + Vanced Meeskond - APK edastamine süsteemi omanikule ebaõnnestus, proovige uuesti. - Viga allalaadimisel %1$s + APK edastamine süsteemi omanikule ebaõnnestus, proovige uuesti. + Viga allalaadimisel %1$s Uue rõhuvärvi rakendamine ebaõnnestus - Paketi %1$s eemaldamine ebaõnnestus - Paigalduseks vajalike failide leidmine ebaõnnestus. Laadige paigaldusfailid uuesti alla ja proovige uuesti. - Apk faili musta/tumeda teema jaoks leidmine ebaõnnestus, proovige palun uuesti. - Paigaldamine ebaõnnestus kuna kasutaja katkestas selle. - Paigaldamine ebaõnnestus, kuna tekkis konflikt olemasoleva versiooniga. Eemaldage praegune rakenduse versioon, ning proovige uuesti. - Paigaldamine ebaõnnestus kuna kasutaja proovis paketti madalamale versioonile üle viia. Eemaldage värskendused originaalrakendusest ja proovige uuesti. - Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu - Paigaldamine ebaõnnestus, kuna paigaldusfail ei sobitu teie seadmega. Puhastage allalaaditud failid seadete alt, ning proovige uuesti. - Paigaldamine ebaõnnestus kuna apk failid on vigased, palun proovige uuesti. - Paigaldamine ebaõnnestus, kuna MIUI optimiseerimine on lubatud. Keelake MIUI optimiseerimine ja proovige uuesti. - Paigaldamine ebaõnnestus kuna apk-allkirja kontrollimine on lubatud. Keelake apk allkirja kinnitamine ja proovige uuesti. - Installimist ei saadud viia lõpule kuna seadmes pole piisvalt vaba ruumi. - Apk faili musta/tumeda teema jaoks leidmine paigaldajast ebaõnnestus. Puhastage halduri rakenduse andmed ja proovige uuesti. - Pärast jagatud paigaldamist ei õnnestunud leida originaal YouTube\'i paigaldus asukohta. + Paketi %1$s eemaldamine ebaõnnestus + Paigalduseks vajalike failide leidmine ebaõnnestus. Laadige paigaldusfailid uuesti alla ja proovige uuesti. + Apk faili musta/tumeda teema jaoks leidmine ebaõnnestus, proovige palun uuesti. + Paigaldamine ebaõnnestus kuna kasutaja katkestas selle. + Paigaldamine ebaõnnestus, kuna tekkis konflikt olemasoleva versiooniga. Eemaldage praegune rakenduse versioon, ning proovige uuesti. + Paigaldamine ebaõnnestus kuna kasutaja proovis paketti madalamale versioonile üle viia. Eemaldage värskendused originaalrakendusest ja proovige uuesti. + Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu + Paigaldamine ebaõnnestus, kuna paigaldusfail ei sobitu teie seadmega. Puhastage allalaaditud failid seadete alt, ning proovige uuesti. + Paigaldamine ebaõnnestus kuna apk failid on vigased, palun proovige uuesti. + Paigaldamine ebaõnnestus, kuna MIUI optimiseerimine on lubatud. Keelake MIUI optimiseerimine ja proovige uuesti. + Paigaldamine ebaõnnestus kuna apk-allkirja kontrollimine on lubatud. Keelake apk allkirja kinnitamine ja proovige uuesti. + Installimist ei saadud viia lõpule kuna seadmes pole piisvalt vaba ruumi. + Apk faili musta/tumeda teema jaoks leidmine paigaldajast ebaõnnestus. Puhastage halduri rakenduse andmed ja proovige uuesti. + Pärast jagatud paigaldamist ei õnnestunud leida originaal YouTube\'i paigaldus asukohta. diff --git a/app/src/main/res/values-fi-rFI/strings.xml b/app/src/main/res/values-fi-rFI/strings.xml index 1a6fe81e30..c52dcdd681 100644 --- a/app/src/main/res/values-fi-rFI/strings.xml +++ b/app/src/main/res/values-fi-rFI/strings.xml @@ -1,120 +1,120 @@ - Peruuta - Sulje - Mukautettu GMS-Toteutus Vancedille perustuen microG projektiin. - Muokattu YouTube-sovellus, jossa on monia hyödyllisiä ominaisuuksia! - Vanced, mutta YouTube Musicille! Suhteellisen vähemmän ominaisuuksia, mutta täyttää tarpeesi. - Palauta - Tallenna - Valitse Sovelluksesi + Peruuta + Sulje + Mukautettu GMS-Toteutus Vancedille perustuen microG projektiin. + Muokattu YouTube-sovellus, jossa on monia hyödyllisiä ominaisuuksia! + Vanced, mutta YouTube Musicille! Suhteellisen vähemmän ominaisuuksia, mutta täyttää tarpeesi. + Palauta + Tallenna + Valitse Sovelluksesi - Tietoja - Opas - Manager - Lokit - Asetukset - Päivitä hallintasovellus + Tietoja + Opas + Manager + Lokit + Asetukset + Päivitä hallintasovellus - Onko laitteesi rootattu? - Anna root-oikeudet - Aloitetaan - Valitse ainakin yksi sovellus! - Etkö tiedä mikä tämä on tai etkö halua käyttää rootattua versiota? Klikkaa alla olevaa sinistä nuolta! + Onko laitteesi rootattu? + Anna root-oikeudet + Aloitetaan + Valitse ainakin yksi sovellus! + Etkö tiedä mikä tämä on tai etkö halua käyttää rootattua versiota? Klikkaa alla olevaa sinistä nuolta! - %1$s-tietoja - Download - Info - Launch - Reinstall - Uninstall - Update - Sovellukset - Muutoshistoria - Ladataan %1$s - Asenna + %1$s-tietoja + Download + Info + Launch + Reinstall + Uninstall + Update + Sovellukset + Muutoshistoria + Ladataan %1$s + Asenna Uusin: - Asenna Vanced microG ensin + Asenna Vanced microG ensin Pääkäyttäjän oikeuksia ei ole annettu - Sosiaalinen media - Tue meitä - Ei saatavilla + Sosiaalinen media + Tue meitä + Ei saatavilla Asennettu: - Aksenttiväri - Ulkoasu - Käyttäytyminen - Tyhjennä ladatut tiedostot - Tiedostot tyhjennettiin onnistuneesti - Tämän avulla voimme kerätä tietoa sovelluksen suorituskyvystä ja kaatumislokeista - Firebase-analytiikka - Kieli - Linkit aukeavat Chromen mukautetuissa välilehdissä - Käytä Chromen mukautettuja välilehtiä - %1$s Push-ilmoitusta - Vastaanota push-ilmoituksia, kun %1$s:lle on julkaistu päivitys - Uuden ajan tallennus epäonnistui - Juuren Skriptin Nukkumisaika - Säädä lepoajan arvoa jota käytetään /data/adb/service.d/app.sh skriptissä, joka on hyödyllinen asennusongelmien korjaamisessa - Järjestelmän oletus - Teema - Tumma teema - Vaalea teema - Managerin päivityskeskus - Ei uusia päivityksiä - Variaatio + Aksenttiväri + Ulkoasu + Käyttäytyminen + Tyhjennä ladatut tiedostot + Tiedostot tyhjennettiin onnistuneesti + Tämän avulla voimme kerätä tietoa sovelluksen suorituskyvystä ja kaatumislokeista + Firebase-analytiikka + Kieli + Linkit aukeavat Chromen mukautetuissa välilehdissä + Käytä Chromen mukautettuja välilehtiä + %1$s Push-ilmoitusta + Vastaanota push-ilmoituksia, kun %1$s:lle on julkaistu päivitys + Uuden ajan tallennus epäonnistui + Juuren Skriptin Nukkumisaika + Säädä lepoajan arvoa jota käytetään /data/adb/service.d/app.sh skriptissä, joka on hyödyllinen asennusongelmien korjaamisessa + Järjestelmän oletus + Teema + Tumma teema + Vaalea teema + Managerin päivityskeskus + Ei uusia päivityksiä + Variaatio - Lokeja ei voitu tallentaa - Lokit tallennettiin onnistuneesti + Lokeja ei voitu tallentaa + Lokit tallennettiin onnistuneesti Lisätiedot - %1$s asennustiedostoa havaittu! - Hallitsija havaitsi, että kaikki tarvittavat tiedostot %1$s asennusta varten. Haluatko asentaa sen? + %1$s asennustiedostoa havaittu! + Hallitsija havaitsi, että kaikki tarvittavat tiedostot %1$s asennusta varten. Haluatko asentaa sen? %1$s asennusasetukset - Tarkistetaan päivityksiä… + Tarkistetaan päivityksiä… Kieli: %1$s Teema: %1$s Versio: %1$s - Virhe - Opas - Pysähdy! + Virhe + Opas + Pysähdy! Käytät Magisk / TWRP versio Vanced, joka on lopetettu ja ei voi päivittää käyttämällä tätä sovellusta. Poista se poistamalla Magisk moduuli / käyttämällä TWRP Vanced asennuksen. - Asentaaksesi Vancedin, sinun täytyy poistaa MIUI-optimisaatiot käytöstä kehittäjäasetuksista. (Voit ohittaa tämän varoituksen, jos käytät versiota 20.2.20 tai uudempaa xiaomi.eu-pohjaista ROM:ia) - MIUI-optimoinnit ovat käytössä! - ÄLÄ poistu sovelluksesta tämän prosessin aikana! - Uudelleenlataa - Varmista, että latasit sovelluksen osoitteesta vancedapp.com, Vanced Discord-palvelin tai Vanced GitHub + Asentaaksesi Vancedin, sinun täytyy poistaa MIUI-optimisaatiot käytöstä kehittäjäasetuksista. (Voit ohittaa tämän varoituksen, jos käytät versiota 20.2.20 tai uudempaa xiaomi.eu-pohjaista ROM:ia) + MIUI-optimoinnit ovat käytössä! + ÄLÄ poistu sovelluksesta tämän prosessin aikana! + Uudelleenlataa + Varmista, että latasit sovelluksen osoitteesta vancedapp.com, Vanced Discord-palvelin tai Vanced GitHub Versio - Tervetuloa + Tervetuloa - Valitse Vancedille haluamasi kieli tai kielet - Uusin + Valitse Vancedille haluamasi kieli tai kielet + Uusin Vaalea + %1$s Valitse ainakin yksi kieli! - Musta - Tumma + Musta + Tumma - Managerin kehittäjät - Muut avustajat - Lähdekoodi - Vanced kehitystiimi + Managerin kehittäjät + Muut avustajat + Lähdekoodi + Vanced kehitystiimi - Ei voitu `chown` APK järjestelmän omistajalle, yritä uudelleen. - %1$s lataus epäonnistui + Ei voitu `chown` APK järjestelmän omistajalle, yritä uudelleen. + %1$s lataus epäonnistui Uuden aksenttivärin käyttöönotto epäonnistui - Paketin %1$s asennus epäonnistui - Asennukseen vaadittavien tiedostojen paikannus epäonnistui. Yritä ladata asennustiedostot uudelleen. - APK-tiedostoa mustalle/tummalle teemalle ei voitu paikantaa tallennustilasta, yritä uudelleen. - Asennus epäonnistui, koska käyttäjä keskeytti asennuksen. - Asennus epäonnistui, koska sovellus on ristiriidassa jo asennetun sovelluksen kanssa. Poista sovelluksen nykyinen versio ja yritä uudelleen. - Asennus epäonnistui, koska käyttäjä yritti asentaa paketin vanhempaa versiota. Poista YouTube-sovelluksen päivitykset ja yritä sitten uudelleen. - Asennus epäonnistui tuntemattomasta syystä, liity Vancedin Telegramiin tai Discordiin saadaksesi tukea. Liitä myös kuvankaappaus Lisäasetukset valikosta - Asennus epäonnistui, koska asennustiedosto ei ole yhteensopiva laitteesi kanssa. Tyhjennä ladatut tiedostot asetuksista ja yritä uudelleen. - Asennus epäonnistui, koska APK-tiedostot ovat vioittuneet, yritä uudelleen. - Asennus epäonnistui, koska MIUI-optimointi on käytössä. Poista MIUI-optimointi käytöstä ja yritä uudelleen. - Asennus epäonnistui, koska APK-allekirjoituksen vahvistus on käytössä. Poista APK-allekirjoituksen vahvistus käytöstä, ja yritä uudelleen. - Asennus epäonnistui, koska laitteella ei ole tarpeeksi vapaata tilaa. - APK-tiedostoa mustalle/tummalle teemalle ei löytynyt asentajalta. Tyhjennä Managerin sovellustiedot ja yritä uudelleen. - Youtube-sovelluksen asennuspolkua ei voitu paikantaa jaetun asennuksen jälkeen. + Paketin %1$s asennus epäonnistui + Asennukseen vaadittavien tiedostojen paikannus epäonnistui. Yritä ladata asennustiedostot uudelleen. + APK-tiedostoa mustalle/tummalle teemalle ei voitu paikantaa tallennustilasta, yritä uudelleen. + Asennus epäonnistui, koska käyttäjä keskeytti asennuksen. + Asennus epäonnistui, koska sovellus on ristiriidassa jo asennetun sovelluksen kanssa. Poista sovelluksen nykyinen versio ja yritä uudelleen. + Asennus epäonnistui, koska käyttäjä yritti asentaa paketin vanhempaa versiota. Poista YouTube-sovelluksen päivitykset ja yritä sitten uudelleen. + Asennus epäonnistui tuntemattomasta syystä, liity Vancedin Telegramiin tai Discordiin saadaksesi tukea. Liitä myös kuvankaappaus Lisäasetukset valikosta + Asennus epäonnistui, koska asennustiedosto ei ole yhteensopiva laitteesi kanssa. Tyhjennä ladatut tiedostot asetuksista ja yritä uudelleen. + Asennus epäonnistui, koska APK-tiedostot ovat vioittuneet, yritä uudelleen. + Asennus epäonnistui, koska MIUI-optimointi on käytössä. Poista MIUI-optimointi käytöstä ja yritä uudelleen. + Asennus epäonnistui, koska APK-allekirjoituksen vahvistus on käytössä. Poista APK-allekirjoituksen vahvistus käytöstä, ja yritä uudelleen. + Asennus epäonnistui, koska laitteella ei ole tarpeeksi vapaata tilaa. + APK-tiedostoa mustalle/tummalle teemalle ei löytynyt asentajalta. Tyhjennä Managerin sovellustiedot ja yritä uudelleen. + Youtube-sovelluksen asennuspolkua ei voitu paikantaa jaetun asennuksen jälkeen. diff --git a/app/src/main/res/values-fil-rPH/strings.xml b/app/src/main/res/values-fil-rPH/strings.xml index 628d052cc4..2a27ba3472 100644 --- a/app/src/main/res/values-fil-rPH/strings.xml +++ b/app/src/main/res/values-fil-rPH/strings.xml @@ -1,120 +1,120 @@ - Kanselahin - Isara - Custom na Implementasyon sa GMS para sa Vanced nakabatay sa proyekto ng microG. - Binagong client ng Youtube na maraming nakatutulong na features! - Vanced, pero para sa Youtube Music! Hindi kasing dami ang mga features, pero natutupad ang iyong pangangailangan. - I-reset - I-save - Piliin ang mga app + Kanselahin + Isara + Custom na Implementasyon sa GMS para sa Vanced nakabatay sa proyekto ng microG. + Binagong client ng Youtube na maraming nakatutulong na features! + Vanced, pero para sa Youtube Music! Hindi kasing dami ang mga features, pero natutupad ang iyong pangangailangan. + I-reset + I-save + Piliin ang mga app - Tungkol sa app - Gabay - Manager - Mga Log - Settings - I-update ang Manager + Tungkol sa app + Gabay + Manager + Mga Log + Settings + I-update ang Manager - Naka-root ba ang device mo? - Pahintulutin ang Root - Magsimula na tayo - Mag-marka ka kahit isa lang na app! - Hindi mo alam ito o huwag gamitin ang root bersyon? I-click ang asul na arrow sa baba! + Naka-root ba ang device mo? + Pahintulutin ang Root + Magsimula na tayo + Mag-marka ka kahit isa lang na app! + Hindi mo alam ito o huwag gamitin ang root bersyon? I-click ang asul na arrow sa baba! - Tungkol sa %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - Mga Apps - Changelog - Downloading %1$s - I-install + Tungkol sa %1$s + Download + Info + Launch + Reinstall + Uninstall + Update + Mga Apps + Changelog + Downloading %1$s + I-install Bago: - I-install muna ang Vanced microG + I-install muna ang Vanced microG Walang binigay na root access - Social Media - Suportahin kami - Di-makukuha + Social Media + Suportahin kami + Di-makukuha Naka-install: - Kulay ng font - Hitsura - Kilos - Tanggalin ang naka-download na files - Natagumpayan na tanggalin ang mga files - Ginagamit ito para sa pag-kolekta ng impormasyon tungkol sa pagganap at crash logs ng app - Firebase Analitiko - Wika - Mabubuksan ang mga links sa Chrome Custom Tabs - Gamitin ang Chrome Custom Tabs - %1$s Push Notifications - Tumanggap ng push notifications kapag ang update sa %1$s ay nailabas - Nabigo na i-save ang bagong time value - Root Script Sleep Time - Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues - Sistemang Default - Tema - Itim na tema - Puti na tema - Manager Update Center - Walang bagong update - Klase + Kulay ng font + Hitsura + Kilos + Tanggalin ang naka-download na files + Natagumpayan na tanggalin ang mga files + Ginagamit ito para sa pag-kolekta ng impormasyon tungkol sa pagganap at crash logs ng app + Firebase Analitiko + Wika + Mabubuksan ang mga links sa Chrome Custom Tabs + Gamitin ang Chrome Custom Tabs + %1$s Push Notifications + Tumanggap ng push notifications kapag ang update sa %1$s ay nailabas + Nabigo na i-save ang bagong time value + Root Script Sleep Time + Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues + Sistemang Default + Tema + Itim na tema + Puti na tema + Manager Update Center + Walang bagong update + Klase - Hindi ma-save ang logs - Natagumpay na i-save ang logs + Hindi ma-save ang logs + Natagumpay na i-save ang logs Mga Detalye - %1$s Nandito ang installation files! - Nakita ng Manager na lahat na kailangan para sa %1$s installation ay nahanap. Gusto mo bang i-install? + %1$s Nandito ang installation files! + Nakita ng Manager na lahat na kailangan para sa %1$s installation ay nahanap. Gusto mo bang i-install? %1$s Kagustuhan sa Pag-install - Naghahanap ng mga updates… + Naghahanap ng mga updates… (Mga) Wika: %1$s Tema: %1$s Bersyon: %1$s - May pagkamali - Gabay - Itigil! + May pagkamali + Gabay + Itigil! Gumagamit ka ng Magisk/TWRP na bersyon ng Vanced, dahil hindi iyon pinatuloy at hindi mai-uupdate gamit nitong app. Tanggalin po ang Magisk module sa pamamagitan ng TWRP Vanced uninstaller. - To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) - MIUI Optimizations are enabled! - Please do NOT exit the app during this process! - I-download ulit - Siguraduhin mo na nai-download mo ang app galing sa vancedapp.com, o sa Discord server ng Vanced, o sa Github ng Vanced + To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) + MIUI Optimizations are enabled! + Please do NOT exit the app during this process! + I-download ulit + Siguraduhin mo na nai-download mo ang app galing sa vancedapp.com, o sa Discord server ng Vanced, o sa Github ng Vanced Bersyon - Maligayang Pagdating + Maligayang Pagdating - Piliin ang ikinagugustong (mga) wika sa Vanced - Pinakabago + Piliin ang ikinagugustong (mga) wika sa Vanced + Pinakabago Puti + %1$s Kumuha ka kahit isang wika! - Itim - Madilim + Itim + Madilim - Manager Devs - Other Contributors - Pinagkukunan - Pangkat Vanced + Manager Devs + Other Contributors + Pinagkukunan + Pangkat Vanced - Nabigo sa `pag-chown` ng APK sa system owner, ulitin muli. - May pagkamali sa pag-download %1$s + Nabigo sa `pag-chown` ng APK sa system owner, ulitin muli. + May pagkamali sa pag-download %1$s Nabigo na gamitin ang bagong kulay aksento - Nabigo sa pag-uninstall ng pakete %1$s - Nabigo ang paghanap sa kailangan na files para sa installation. I-download ulit ang mga installation files, at ulitin muli. - Nabigo ang paghanap ng apk file para sa itim na tema galing sa storage, ulitin muli. - Nabigo ang pag-install dahil kinansela ito. - Nabigo ang pag-install dahil meron hidwaan sa naka-install na app. I-uninstall ang kasalukuyang bersyon ng Vanced, at ulitin muli. - Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. - Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu - Nabigo ang pag-install dahil ang installation file ay hindi tugma sa iyong device. Tanggalin ang mga downloaded files sa Settings, at ulitin muli. - Nabigo ang pag-install dahil ang mga apk files ay nasira, ulitin muli. - Nabigo ang pag-install dahil ang MIUI Optimization ay naka-on. Patayin ang MIUI Optimization, at ulitin muli. - Nabigo ang pag-install dahil ang apk signature verification ay naka-on. Patayin ang apk signature verification, at ulitin muli. - Installation failed because the device doesn\'t have enough free space. - Nabigong hanapin ang apk file para sa itim na tema galing sa installer. Tanggalin ang app data ng Manager, tapos ulitin. - Nabigong hanapin ang stock YouTube installation path pagkatapos ng split installation. + Nabigo sa pag-uninstall ng pakete %1$s + Nabigo ang paghanap sa kailangan na files para sa installation. I-download ulit ang mga installation files, at ulitin muli. + Nabigo ang paghanap ng apk file para sa itim na tema galing sa storage, ulitin muli. + Nabigo ang pag-install dahil kinansela ito. + Nabigo ang pag-install dahil meron hidwaan sa naka-install na app. I-uninstall ang kasalukuyang bersyon ng Vanced, at ulitin muli. + Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. + Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu + Nabigo ang pag-install dahil ang installation file ay hindi tugma sa iyong device. Tanggalin ang mga downloaded files sa Settings, at ulitin muli. + Nabigo ang pag-install dahil ang mga apk files ay nasira, ulitin muli. + Nabigo ang pag-install dahil ang MIUI Optimization ay naka-on. Patayin ang MIUI Optimization, at ulitin muli. + Nabigo ang pag-install dahil ang apk signature verification ay naka-on. Patayin ang apk signature verification, at ulitin muli. + Installation failed because the device doesn\'t have enough free space. + Nabigong hanapin ang apk file para sa itim na tema galing sa installer. Tanggalin ang app data ng Manager, tapos ulitin. + Nabigong hanapin ang stock YouTube installation path pagkatapos ng split installation. diff --git a/app/src/main/res/values-fr-rFR/strings.xml b/app/src/main/res/values-fr-rFR/strings.xml index 7f66918f36..7c56a2e0c7 100644 --- a/app/src/main/res/values-fr-rFR/strings.xml +++ b/app/src/main/res/values-fr-rFR/strings.xml @@ -1,120 +1,120 @@ - Annuler - Fermer - Une implémentation GMS personnalisée pour Vanced basée sur le projet microG. - Un client YouTube modifié avec de nombreuses fonctionnalités utiles ! - Vanced, mais pour YouTube Music ! Relativement moins riche en fonctionnalités mais répond à vos besoins. - Réinitialiser - Sauvegarder - Sélectionnez vos applications + Annuler + Fermer + Une implémentation GMS personnalisée pour Vanced basée sur le projet microG. + Un client YouTube modifié avec de nombreuses fonctionnalités utiles ! + Vanced, mais pour YouTube Music ! Relativement moins riche en fonctionnalités mais répond à vos besoins. + Réinitialiser + Sauvegarder + Sélectionnez vos applications - À propos - Guide - Gestionnaire - Journaux - Paramètres - Gestionnaire de Mise à Jour + À propos + Guide + Gestionnaire + Journaux + Paramètres + Gestionnaire de Mise à Jour - Votre appareil est-il rooté ? - Accorder l’accès root - Commençons - Sélectionnez au moins une application ! - Vous ne savez pas ce que c\'est ou vous ne voulez pas utiliser la version « root » ? Cliquez simplement sur la flèche bleue ci-dessous ! + Votre appareil est-il rooté ? + Accorder l’accès root + Commençons + Sélectionnez au moins une application ! + Vous ne savez pas ce que c\'est ou vous ne voulez pas utiliser la version « root » ? Cliquez simplement sur la flèche bleue ci-dessous ! - À propos de %1$s - Télécharger - Informations - Lancer - Réinstaller - Désinstaller - Mettre à jour - Applications - Changelog - Téléchargement de %1$s - Installer + À propos de %1$s + Télécharger + Informations + Lancer + Réinstaller + Désinstaller + Mettre à jour + Applications + Changelog + Téléchargement de %1$s + Installer Dernière version: - Installez d\'abord Vanced microG + Installez d\'abord Vanced microG Accès root non autorisé - Réseaux sociaux - Soutenez-nous - Indisponible + Réseaux sociaux + Soutenez-nous + Indisponible Version installée: - Couleur d\'accentuation - Apparence - Comportement - Effacer les fichiers téléchargés - Données effacées avec succès - Cela nous permet de recueillir des informations sur les performances de l\'application et les journaux de bord - Analyses Firebase - Langue - Les liens s\'ouvriront dans les onglets personnalisés Chrome - Utiliser les onglets personnalisés Chrome - %1$s Notifications Push - Recevoir une notification push quand une nouvelle version pour %1$s est publiée - Impossible d\'enregistrer la nouvelle valeur de temps - Temps de veille du script root - Ajuster la valeur de l\'heure de veille utilisée dans le script /data/adb/service.d/app.sh, utile pour résoudre les problèmes de montage - Système par défaut - Thème - Thème sombre - Thème clair - Centre de mise à jour du Manager - Aucune nouvelle mise à jour - Variante + Couleur d\'accentuation + Apparence + Comportement + Effacer les fichiers téléchargés + Données effacées avec succès + Cela nous permet de recueillir des informations sur les performances de l\'application et les journaux de bord + Analyses Firebase + Langue + Les liens s\'ouvriront dans les onglets personnalisés Chrome + Utiliser les onglets personnalisés Chrome + %1$s Notifications Push + Recevoir une notification push quand une nouvelle version pour %1$s est publiée + Impossible d\'enregistrer la nouvelle valeur de temps + Temps de veille du script root + Ajuster la valeur de l\'heure de veille utilisée dans le script /data/adb/service.d/app.sh, utile pour résoudre les problèmes de montage + Système par défaut + Thème + Thème sombre + Thème clair + Centre de mise à jour du Manager + Aucune nouvelle mise à jour + Variante - Impossible d\'enregistrer les journaux - Journaux enregistrés avec succès + Impossible d\'enregistrer les journaux + Journaux enregistrés avec succès Détails - %1$s fichiers d\'installation détectés ! - Le gestionnaire a détecté que tous les fichiers nécessaires à l\'installation de %1$s ont été trouvés. Voulez-vous installer ? + %1$s fichiers d\'installation détectés ! + Le gestionnaire a détecté que tous les fichiers nécessaires à l\'installation de %1$s ont été trouvés. Voulez-vous installer ? %1$s Préférences d\'installation - Vérification des mises à jour… + Vérification des mises à jour… Langue(s) : %1$s Thème : %1$s Version : %1$s - Erreur - Guide - Stop! + Erreur + Guide + Stop! Vous utilisez la version Magisk/TWRP de Vanced, qui n\'est plus entretenu et ne peut pas être mise à jour à l\'aide de cette application. Veuillez la retirer en supprimant le module Magisk/en utilisant le désinstallateur TWRP pour Vanced. - Afin d\'installer Vanced, vous DEVEZ désactiver les optimisations MIUI dans les paramètres développeur (vous pouvez ignorer cet avertissement si vous utilisez une ROM basée sur 20.2.20 ou ultérieure de xiaomi.eu) - Les optimisations MIUI sont activées ! - Veuillez NE PAS quitter l\'application pendant que celle-ci est en cours de modification ! - Re-télécharger - Assurez-vous d\'avoir téléchargé l\'application depuis vancedapp.com, le serveur Discord Vanced ou sur le Github Vanced + Afin d\'installer Vanced, vous DEVEZ désactiver les optimisations MIUI dans les paramètres développeur (vous pouvez ignorer cet avertissement si vous utilisez une ROM basée sur 20.2.20 ou ultérieure de xiaomi.eu) + Les optimisations MIUI sont activées ! + Veuillez NE PAS quitter l\'application pendant que celle-ci est en cours de modification ! + Re-télécharger + Assurez-vous d\'avoir téléchargé l\'application depuis vancedapp.com, le serveur Discord Vanced ou sur le Github Vanced Version - Bienvenue + Bienvenue - Choisir votre langage(s) préféré(s) pour Vanced - Dernière version + Choisir votre langage(s) préféré(s) pour Vanced + Dernière version Lumière + %1$s Sélectionnez au moins une langue ! - Noir - Sombre + Noir + Sombre - Développeurs du Manager - Autres Contributeurs - Sources - Équipe Vanced + Développeurs du Manager + Autres Contributeurs + Sources + Équipe Vanced - Échec de la commande `chown` APK vers le propriétaire du système, veuillez réessayer. - Erreur en téléchargeant %1$s + Échec de la commande `chown` APK vers le propriétaire du système, veuillez réessayer. + Erreur en téléchargeant %1$s Impossible d\'appliquer la nouvelle couleur d\'accentuation - N\'a pas pu désinstaller le paquet %1$s - Impossible de localiser les fichiers nécessaires à l\'installation. Retéléchargez les fichiers d\'installation, puis réessayez. - Impossible de localiser le fichier apk pour le thème noir/foncé, veuillez réessayer. - L\'installation a échoué car l\'utilisateur a abandonné l\'installation. - L\'installation a échoué parce que l\'application est en conflit avec une application déjà installée. Désinstallez la version actuelle de Vanced, puis réessayez. - L\'installation a échoué parce que l\'utilisateur a essayé de downgrader le paquet. Désinstallez les mises à jour de l\'application d\'origine, puis réessayez. - L\'installation a échoué pour des raisons inconnues, rejoignez notre Telegram ou Discord pour plus de support. Veuillez également joindre une capture d\'écran dans le menu Avancé - L\'installation a échoué parce que le fichier d\'installation est incompatible avec votre appareil. Effacer les fichiers téléchargés dans les paramètres, puis réessayer. - L\'installation a échouée car les fichiers apk sont corrompus, veuillez réessayer. - L\'installation a échouée car l\'optimisation MIUI est activée. Désactivez l\'optimisation MIUI, puis réessayez. - L\'installation a échoué car la vérification de la signature apk est activée. Désactivez la vérification de la signature apk, puis réessayez. - L\'installation a échoué car l\'appareil n\'a pas assez d\'espace disponible. - Impossible de trouver le fichier apk pour le thème noir/foncé de l\'installateur. Effacez les données de l\'application de Manager, puis réessayez. - Impossible de localiser le chemin d\'installation du YouTube original après l\'installation fractionnée. + N\'a pas pu désinstaller le paquet %1$s + Impossible de localiser les fichiers nécessaires à l\'installation. Retéléchargez les fichiers d\'installation, puis réessayez. + Impossible de localiser le fichier apk pour le thème noir/foncé, veuillez réessayer. + L\'installation a échoué car l\'utilisateur a abandonné l\'installation. + L\'installation a échoué parce que l\'application est en conflit avec une application déjà installée. Désinstallez la version actuelle de Vanced, puis réessayez. + L\'installation a échoué parce que l\'utilisateur a essayé de downgrader le paquet. Désinstallez les mises à jour de l\'application d\'origine, puis réessayez. + L\'installation a échoué pour des raisons inconnues, rejoignez notre Telegram ou Discord pour plus de support. Veuillez également joindre une capture d\'écran dans le menu Avancé + L\'installation a échoué parce que le fichier d\'installation est incompatible avec votre appareil. Effacer les fichiers téléchargés dans les paramètres, puis réessayer. + L\'installation a échouée car les fichiers apk sont corrompus, veuillez réessayer. + L\'installation a échouée car l\'optimisation MIUI est activée. Désactivez l\'optimisation MIUI, puis réessayez. + L\'installation a échoué car la vérification de la signature apk est activée. Désactivez la vérification de la signature apk, puis réessayez. + L\'installation a échoué car l\'appareil n\'a pas assez d\'espace disponible. + Impossible de trouver le fichier apk pour le thème noir/foncé de l\'installateur. Effacez les données de l\'application de Manager, puis réessayez. + Impossible de localiser le chemin d\'installation du YouTube original après l\'installation fractionnée. diff --git a/app/src/main/res/values-hi-rIN/strings.xml b/app/src/main/res/values-hi-rIN/strings.xml index d8f40eb42b..ad480c58ad 100644 --- a/app/src/main/res/values-hi-rIN/strings.xml +++ b/app/src/main/res/values-hi-rIN/strings.xml @@ -1,120 +1,120 @@ - रद्द करें - बंद करे - MicroG प्रोजेक्ट के आधार पर Vanced के लिए एक कस्टम GMS कार्यान्वयन। - कई उपयोगी सुविधाओं के साथ एक संशोधित यूट्यूब क्लाइंट! - Vanced, लेकिन यूट्यूब संगीत के लिए! तुलना में कम सुविधा संपन्न लेकिन आपकी आवश्यकताओं को पूरा करता है। - रिसेट - सहेजें - अपने ऐप्स चुनें + रद्द करें + बंद करे + MicroG प्रोजेक्ट के आधार पर Vanced के लिए एक कस्टम GMS कार्यान्वयन। + कई उपयोगी सुविधाओं के साथ एक संशोधित यूट्यूब क्लाइंट! + Vanced, लेकिन यूट्यूब संगीत के लिए! तुलना में कम सुविधा संपन्न लेकिन आपकी आवश्यकताओं को पूरा करता है। + रिसेट + सहेजें + अपने ऐप्स चुनें - हमारे बारे में - गाइड - मैनेजर - लॉग - सेटिंग्स - अपडेट प्रबंधक + हमारे बारे में + गाइड + मैनेजर + लॉग + सेटिंग्स + अपडेट प्रबंधक - क्या आपका डिवाइस रुट किया गया है? - रूट की अनुमति प्रदान करें - चलिए शुरू करते है - कम से कम एक ऐप चुनें! - नहीं जानते ये क्या है या रूट वर्जन इस्तेमाल नहीं करना चाहते? बस नीचे वाला बटन दबाइए! + क्या आपका डिवाइस रुट किया गया है? + रूट की अनुमति प्रदान करें + चलिए शुरू करते है + कम से कम एक ऐप चुनें! + नहीं जानते ये क्या है या रूट वर्जन इस्तेमाल नहीं करना चाहते? बस नीचे वाला बटन दबाइए! - %1$s के बारे में - Download - Info - Launch - Reinstall - Uninstall - Update - ऐप - परिवर्तन पत्र - डाउनलोड हो रहा है %1$s - इंस्टॉल + %1$s के बारे में + Download + Info + Launch + Reinstall + Uninstall + Update + ऐप + परिवर्तन पत्र + डाउनलोड हो रहा है %1$s + इंस्टॉल सबसे नया - सबसे पहले Vanced microG इंस्टॉल करें + सबसे पहले Vanced microG इंस्टॉल करें रूट एक्सेस प्रदान नहीं किया गया - सोशल मीडिया - हमें सहयोग दीजिये - अनुपलब्ध + सोशल मीडिया + हमें सहयोग दीजिये + अनुपलब्ध इंस्टॉल हुआ। - ऊपरी रंग - दिखावट - व्यवहार - डाउनलोड की गई फ़ाइलें साफ़ करें - फ़ाइलें सफलतापूर्वक साफ़ की गई - इससे हम एप्लिकेशन प्रदर्शन और क्रैश लॉग के बारे में जानकारी एकत्र कर सकते हैं - फायरबेस वैश्लेषिकी - भाषा - क्रोम कस्टम टैब में लिंक खुलेंगे - क्रोम कस्टम टैब का उपयोग करें - %1$s पुश सूचनाएँ - जब %1$s का अपडेट जारी किया जाता है, तो पुश सूचनाएँ प्राप्त करें - नया समय मान सहेजने में विफल - रूट स्क्रिप्ट स्लीप का समय - बढ़ते मुद्दों को ठीक करने के लिए उपयोगी /data/adb/service.d/app.sh स्क्रिप्ट में उपयोग की गई नींद के समय को समायोजित करें - सिस्टम डिफ़ॉल्ट - थीम - डार्क थीम - लाइट थीम - मैनेजर अपडेट केंद्र - कोई नया अपडेट नहीं - संस्करण + ऊपरी रंग + दिखावट + व्यवहार + डाउनलोड की गई फ़ाइलें साफ़ करें + फ़ाइलें सफलतापूर्वक साफ़ की गई + इससे हम एप्लिकेशन प्रदर्शन और क्रैश लॉग के बारे में जानकारी एकत्र कर सकते हैं + फायरबेस वैश्लेषिकी + भाषा + क्रोम कस्टम टैब में लिंक खुलेंगे + क्रोम कस्टम टैब का उपयोग करें + %1$s पुश सूचनाएँ + जब %1$s का अपडेट जारी किया जाता है, तो पुश सूचनाएँ प्राप्त करें + नया समय मान सहेजने में विफल + रूट स्क्रिप्ट स्लीप का समय + बढ़ते मुद्दों को ठीक करने के लिए उपयोगी /data/adb/service.d/app.sh स्क्रिप्ट में उपयोग की गई नींद के समय को समायोजित करें + सिस्टम डिफ़ॉल्ट + थीम + डार्क थीम + लाइट थीम + मैनेजर अपडेट केंद्र + कोई नया अपडेट नहीं + संस्करण - लॉग नहीं सहेजे गए - सफलतापूर्वक लॉग सहेजे गए + लॉग नहीं सहेजे गए + सफलतापूर्वक लॉग सहेजे गए विवरण - %1$s इंस्टालेशन फ़ाइलों का पता चला! - प्रबंधक ने पाया कि %1$s इंस्टॉलेशन के लिए सभी आवश्यक फाइलें मिलीं। क्या आप इंस्टॉल करना चाहते हैं? + %1$s इंस्टालेशन फ़ाइलों का पता चला! + प्रबंधक ने पाया कि %1$s इंस्टॉलेशन के लिए सभी आवश्यक फाइलें मिलीं। क्या आप इंस्टॉल करना चाहते हैं? %1$s इंस्टालेशन प्राथमिकताएँ - अपडेट्स के लिए जांच हो रही है… + अपडेट्स के लिए जांच हो रही है… भाषा (एं): %1$s थीम:%1$s संस्करण:%1$s - त्रुटि - गाइड - रुकें! + त्रुटि + गाइड + रुकें! आप Vanced के Magisk / TWRP संस्करण का उपयोग कर रहे हैं, जिसे बंद कर दिया गया है और इस ऐप का उपयोग करके अपडेट नहीं किया जा सकता है। कृपया इस Magisk मॉड्यूल को हटाकर / TWRP Vanced uninstaller का उपयोग करके हटा दें। - Vanced इनस्टॉल करने के लिए, आप डेवलपर सेटिंग में MIUI ऑप्टिमाइज़ेशन को निष्क्रिय करें। (यदि आप 20.2.20 या बाद में xiaomi.eu आधारित ROM का उपयोग कर रहे हैं तो आप इस चेतावनी को अनदेखा कर सकते हैं) - MIUI Optimizations सक्षम हैं! - कृपया इस प्रक्रिया के दौरान ऐप को बंद ना करें! - फिर से डाउनलोड करें - सुनिश्चित करें कि आपने vancedapp.com, Vanced Discord सर्वर, या Vanced GitHub से ऐप डाउनलोड किया है + Vanced इनस्टॉल करने के लिए, आप डेवलपर सेटिंग में MIUI ऑप्टिमाइज़ेशन को निष्क्रिय करें। (यदि आप 20.2.20 या बाद में xiaomi.eu आधारित ROM का उपयोग कर रहे हैं तो आप इस चेतावनी को अनदेखा कर सकते हैं) + MIUI Optimizations सक्षम हैं! + कृपया इस प्रक्रिया के दौरान ऐप को बंद ना करें! + फिर से डाउनलोड करें + सुनिश्चित करें कि आपने vancedapp.com, Vanced Discord सर्वर, या Vanced GitHub से ऐप डाउनलोड किया है संस्करण - स्वागत है! + स्वागत है! - Vanced के लिए अपनी पसंदीदा भाषा (ए) चुनें - नवीनतम + Vanced के लिए अपनी पसंदीदा भाषा (ए) चुनें + नवीनतम लाइट +%1$s कम से कम एक भाषा का चयन करें! - काला - डार्क + काला + डार्क - प्रबंधक डेवलपर्स - अन्य योगदानकर्ता - स्रोत - वांसड टीम + प्रबंधक डेवलपर्स + अन्य योगदानकर्ता + स्रोत + वांसड टीम - सिस्टम के मालिक को APK को Chown करने में विफल, फिर से प्रयास करें। - डाउनलोड करने में त्रुटि %1$s + सिस्टम के मालिक को APK को Chown करने में विफल, फिर से प्रयास करें। + डाउनलोड करने में त्रुटि %1$s नया ऊपरी रंग लागू करने में विफल - पैकेज की स्थापना रद्द करने में विफल %1$s - स्थापना के लिए आवश्यक फ़ाइलों का पता लगाने में विफल। स्थापना फ़ाइलों को फिर से डाउनलोड करें, फिर पुनः प्रयास करें। - भंडारण से काले / अंधेरे विषय के लिए apk फ़ाइल खोजने में विफल, कृपया पुनः प्रयास करें। - स्थापना विफल रही क्योंकि उपयोगकर्ता ने स्थापना रद्द कर दी। - इंस्टॉलेशन विफल रहा क्योंकि ऐप पहले से इंस्टॉल किए गए ऐप के साथ टकराव करता है। Vanced के वर्तमान संस्करण को अनइंस्टॉल करें, फिर पुनः प्रयास करें। - स्थापना विफल रही क्योंकि उपयोगकर्ता ने पैकेज को डाउनग्रेड करने का प्रयास किया। स्टॉक ऐप से अपडेट अनइंस्टॉल करें, फिर प्रयास करें। - अज्ञात कारणों से इंस्टॉलेशन विफल हो गया, आगे के समर्थन के लिए हमारे टेलीग्राम या डिस्कॉर्ड में शामिल हों। कृपया उन्नत मेनू से स्क्रीनशॉट भी संलग्न करें । - इंस्टॉलेशन विफल हो गया क्योंकि इंस्टॉलेशन फ़ाइल आपके डिवाइस के साथ असंगत है। सेटिंग्स में डाउनलोड की गई फ़ाइलों को साफ़ करें, फिर प्रयास करें। - स्थापना विफल रही क्योंकि एपीके फ़ाइलें दूषित हैं, कृपया पुनः प्रयास करें। - MIUI ऑप्टिमाइज़ेशन सक्षम होने के कारण स्थापना विफल रही। MIUI ऑप्टिमाइज़ेशन अक्षम करें, फिर प्रयास करें। - स्थापना विफल रही क्योंकि एपीके हस्ताक्षर सत्यापन सक्षम है। एपीके हस्ताक्षर सत्यापन अक्षम करें, फिर प्रयास करें। - इंस्टॉलेशन विफल हो गया क्योंकि डिवाइस में पर्याप्त खाली जगह नहीं है। - इंस्टॉलर से ब्लैक / डार्क थीम के लिए एपीके फ़ाइल खोजने में विफल। प्रबंधक का एप्लिकेशन डेटा साफ़ करें, फिर प्रयास करें। - विभाजन स्थापना के बाद स्टॉक YouTube इंस्टॉलेशन पथ का पता लगाने में विफल + पैकेज की स्थापना रद्द करने में विफल %1$s + स्थापना के लिए आवश्यक फ़ाइलों का पता लगाने में विफल। स्थापना फ़ाइलों को फिर से डाउनलोड करें, फिर पुनः प्रयास करें। + भंडारण से काले / अंधेरे विषय के लिए apk फ़ाइल खोजने में विफल, कृपया पुनः प्रयास करें। + स्थापना विफल रही क्योंकि उपयोगकर्ता ने स्थापना रद्द कर दी। + इंस्टॉलेशन विफल रहा क्योंकि ऐप पहले से इंस्टॉल किए गए ऐप के साथ टकराव करता है। Vanced के वर्तमान संस्करण को अनइंस्टॉल करें, फिर पुनः प्रयास करें। + स्थापना विफल रही क्योंकि उपयोगकर्ता ने पैकेज को डाउनग्रेड करने का प्रयास किया। स्टॉक ऐप से अपडेट अनइंस्टॉल करें, फिर प्रयास करें। + अज्ञात कारणों से इंस्टॉलेशन विफल हो गया, आगे के समर्थन के लिए हमारे टेलीग्राम या डिस्कॉर्ड में शामिल हों। कृपया उन्नत मेनू से स्क्रीनशॉट भी संलग्न करें । + इंस्टॉलेशन विफल हो गया क्योंकि इंस्टॉलेशन फ़ाइल आपके डिवाइस के साथ असंगत है। सेटिंग्स में डाउनलोड की गई फ़ाइलों को साफ़ करें, फिर प्रयास करें। + स्थापना विफल रही क्योंकि एपीके फ़ाइलें दूषित हैं, कृपया पुनः प्रयास करें। + MIUI ऑप्टिमाइज़ेशन सक्षम होने के कारण स्थापना विफल रही। MIUI ऑप्टिमाइज़ेशन अक्षम करें, फिर प्रयास करें। + स्थापना विफल रही क्योंकि एपीके हस्ताक्षर सत्यापन सक्षम है। एपीके हस्ताक्षर सत्यापन अक्षम करें, फिर प्रयास करें। + इंस्टॉलेशन विफल हो गया क्योंकि डिवाइस में पर्याप्त खाली जगह नहीं है। + इंस्टॉलर से ब्लैक / डार्क थीम के लिए एपीके फ़ाइल खोजने में विफल। प्रबंधक का एप्लिकेशन डेटा साफ़ करें, फिर प्रयास करें। + विभाजन स्थापना के बाद स्टॉक YouTube इंस्टॉलेशन पथ का पता लगाने में विफल diff --git a/app/src/main/res/values-hr-rHR/strings.xml b/app/src/main/res/values-hr-rHR/strings.xml index 61280abf28..311bea76d1 100644 --- a/app/src/main/res/values-hr-rHR/strings.xml +++ b/app/src/main/res/values-hr-rHR/strings.xml @@ -1,120 +1,120 @@ - Odustani - Zatvori - Prilagođena GMS implementacija za Vanced zasnovana na microG projektu. - Modificirani YouTube klijent sa mnogo korisnih značajki! - Vanced, ali za YouTube Music! S manje značajki ali ispunjava vaše potrebe. - Resetiraj - Spremi - Odaberite svoje aplikacije + Odustani + Zatvori + Prilagođena GMS implementacija za Vanced zasnovana na microG projektu. + Modificirani YouTube klijent sa mnogo korisnih značajki! + Vanced, ali za YouTube Music! S manje značajki ali ispunjava vaše potrebe. + Resetiraj + Spremi + Odaberite svoje aplikacije - O autorima - Vodič - Upravitelj - Zapisi - Postavke - Ažuriranje upravitelja + O autorima + Vodič + Upravitelj + Zapisi + Postavke + Ažuriranje upravitelja - Je li vaš uređaj rootan? - Dopusti root dozvolu - Započnite - Odaberite najmanje jednu aplikaciju! - Ne znate što je ovo ili ne želite koristiti root izdanje? Jednostavno kliknite na plavu strelicu ispod! + Je li vaš uređaj rootan? + Dopusti root dozvolu + Započnite + Odaberite najmanje jednu aplikaciju! + Ne znate što je ovo ili ne želite koristiti root izdanje? Jednostavno kliknite na plavu strelicu ispod! - O %1$s - Preuzmi - Informacije - Pokreni - Reinstaliraj - Deinstaliraj - Ažuriraj - Aplikacije - Zapis promjena - Preuzimam %1$s - Instaliraj + O %1$s + Preuzmi + Informacije + Pokreni + Reinstaliraj + Deinstaliraj + Ažuriraj + Aplikacije + Zapis promjena + Preuzimam %1$s + Instaliraj Dostupno: - Prvo instaliraj Vanced MicroG + Prvo instaliraj Vanced MicroG Root pristup nije dopušten - Društvene mreže - Podržite nas - Nedostupno + Društvene mreže + Podržite nas + Nedostupno Instalirano: - Boja naglašavanja - Izgled - Ponašanje - Ukloni preuzete datoteke - Datoteke su uspješno uklonjene - Ovo nam omogućuje prikupljanje informacija o performansama aplikacije i zapise rušenja - Firebase analitika - Jezik - Poveznice će se otvarati u prilagođenim karticama Chroma - Koristi prilagođene kartice Chroma - %1$s skočne obavijesti - Primite skočnu obavijest kada je ažuriranje za %1$s dostupno - Neuspjelo spremanje nove vrijednosti vremena - Vrijeme spavanja root skripte - Prilagodite vrijeme spavanja korišteno u /data/adb/service.d/app.sh skripti, korisno za ispravak problema s montiranjem - Zadano sustavom - Tema - Tamna tema - Svjetla tema - Središte ažuriranja upravitelja - Nema novih ažuriranja - Izdanje + Boja naglašavanja + Izgled + Ponašanje + Ukloni preuzete datoteke + Datoteke su uspješno uklonjene + Ovo nam omogućuje prikupljanje informacija o performansama aplikacije i zapise rušenja + Firebase analitika + Jezik + Poveznice će se otvarati u prilagođenim karticama Chroma + Koristi prilagođene kartice Chroma + %1$s skočne obavijesti + Primite skočnu obavijest kada je ažuriranje za %1$s dostupno + Neuspjelo spremanje nove vrijednosti vremena + Vrijeme spavanja root skripte + Prilagodite vrijeme spavanja korišteno u /data/adb/service.d/app.sh skripti, korisno za ispravak problema s montiranjem + Zadano sustavom + Tema + Tamna tema + Svjetla tema + Središte ažuriranja upravitelja + Nema novih ažuriranja + Izdanje - Nije moguće spremiti zapise - Uspješno spremljeni zapisi + Nije moguće spremiti zapise + Uspješno spremljeni zapisi Detalji - %1$s instalacijska datoteka je otkrivena! - Upravitelj je otkrio da su sve potrebne datoteke za %1$s instalaciju pronađene. Želite li nastaviti instalaciju? + %1$s instalacijska datoteka je otkrivena! + Upravitelj je otkrio da su sve potrebne datoteke za %1$s instalaciju pronađene. Želite li nastaviti instalaciju? %1$s postavke instalacije - Provjera ažuriranja… + Provjera ažuriranja… Jezik: %1$s Tema: %1$s Inačica: %1$s - Greška - Vodič - Zaustavi! + Greška + Vodič + Zaustavi! Koristite Magisk/TWRP inačicu Vanceda, koja više nije podržana i ne može se ažurirati ovom aplikacijom. Uklonite ju uklanjanjem Magisk modula/koristeći TWRP Vanced deinstalator. - Kako bi instalirali Vanced, MORATE onemogućiti MIUI optimizaciju u razvojnim mogućnostima. (Ovo upozorenje možete zanemariti ako koristite 20.2.20 ili noviji xiaomi.eu ROM) - MIUI optimizacija je omogućena! - NE zatvarajte aplikaciju tijekom ovog postupka! - Ponovno preuzmi - Aplikaciju obavezno preuzmite s vancedapp.com, Vanced Discord poslužitelja ili Vanced GitHuba + Kako bi instalirali Vanced, MORATE onemogućiti MIUI optimizaciju u razvojnim mogućnostima. (Ovo upozorenje možete zanemariti ako koristite 20.2.20 ili noviji xiaomi.eu ROM) + MIUI optimizacija je omogućena! + NE zatvarajte aplikaciju tijekom ovog postupka! + Ponovno preuzmi + Aplikaciju obavezno preuzmite s vancedapp.com, Vanced Discord poslužitelja ili Vanced GitHuba Inačica - Dobrodošli + Dobrodošli - Odaberite željeni jezika za Vanced - Najnovije + Odaberite željeni jezika za Vanced + Najnovije Svjetla + %1$s Odaberite najmanje jedan jezik! - Crna - Tamna + Crna + Tamna - Razvijatelji Vanced upravitelja - Ostali suradnici - Izvori - Vanced tim + Razvijatelji Vanced upravitelja + Ostali suradnici + Izvori + Vanced tim - Neuspjela promjena `chown` APK u vlasnika sustava, pokušajte ponovno. - Greška preuzimanja %1$s + Neuspjela promjena `chown` APK u vlasnika sustava, pokušajte ponovno. + Greška preuzimanja %1$s Neuspjelo primijenjivanje nove boje naglašavanja - Neuspjela deinstalacija %1$s paketa - Neuspjelo lociranje potrebnih datoteka za instalaciju. Ponovno preuzmite datoteke za instalaciju, zatim ponovno pokušajte. - Neuspjelo lociranje apk datoteke za crnu/tamnu temu iz pohrane, pokušajte ponovno. - Instalacija je prekinuta zato jer ju je korisnik prekinuo. - Instalacija nije uspjela jer je aplikacija u sukobu s već instaliranom aplikacijom. Deinstalirajte trenutnu inačicu aplikacije zatim pokušajte ponovno. - Instalacija nije uspjela jer je korisnik pokušao instalirati stariju inačicu paketa. Deinstalirajte ažuriranja izvorne YouTube aplikacije, zatim pokušajte ponovno. - Neuspjela instalacija, nepoznati razlog. Priključite se našem Telegramu ili Diskordu za našu pomoć. Molimo Vas da priključite sliku ekrana iz Proširenog Menua - Instalacija nije uspjela zato jer datoteka instalacije nije kompatibilna s vašim uređajem. Uklonite preuzete datoteke u postavkama, zatim pokušajte ponovno. - Instalacija nije uspjela zato jer je apk datoteka oštećena. - Instalacija nije uspjela zato jer je MIUI optimizacija uključena. Isključite MIUI optimizaciju, zatim pokušajte ponovno. - Instalacija nije uspjela zato jer je provjera potpisa omogućena. Onemogućite apk provjeru potpisa, zatim pokušajte ponovno. - Neuspješna instalacija jer na uređaju nema dovoljno slobodnog prostora. - Neuspjeli pronalazak apk datoteke za crnu/tamnu temu u programu instalacije. Uklonite podatke aplikacije upravitelja, zatim pokušajte ponovno. - Neuspjelo lociranje putanje izvorne YouTube instalacije nakon razdvojene instalacije. + Neuspjela deinstalacija %1$s paketa + Neuspjelo lociranje potrebnih datoteka za instalaciju. Ponovno preuzmite datoteke za instalaciju, zatim ponovno pokušajte. + Neuspjelo lociranje apk datoteke za crnu/tamnu temu iz pohrane, pokušajte ponovno. + Instalacija je prekinuta zato jer ju je korisnik prekinuo. + Instalacija nije uspjela jer je aplikacija u sukobu s već instaliranom aplikacijom. Deinstalirajte trenutnu inačicu aplikacije zatim pokušajte ponovno. + Instalacija nije uspjela jer je korisnik pokušao instalirati stariju inačicu paketa. Deinstalirajte ažuriranja izvorne YouTube aplikacije, zatim pokušajte ponovno. + Neuspjela instalacija, nepoznati razlog. Priključite se našem Telegramu ili Diskordu za našu pomoć. Molimo Vas da priključite sliku ekrana iz Proširenog Menua + Instalacija nije uspjela zato jer datoteka instalacije nije kompatibilna s vašim uređajem. Uklonite preuzete datoteke u postavkama, zatim pokušajte ponovno. + Instalacija nije uspjela zato jer je apk datoteka oštećena. + Instalacija nije uspjela zato jer je MIUI optimizacija uključena. Isključite MIUI optimizaciju, zatim pokušajte ponovno. + Instalacija nije uspjela zato jer je provjera potpisa omogućena. Onemogućite apk provjeru potpisa, zatim pokušajte ponovno. + Neuspješna instalacija jer na uređaju nema dovoljno slobodnog prostora. + Neuspjeli pronalazak apk datoteke za crnu/tamnu temu u programu instalacije. Uklonite podatke aplikacije upravitelja, zatim pokušajte ponovno. + Neuspjelo lociranje putanje izvorne YouTube instalacije nakon razdvojene instalacije. diff --git a/app/src/main/res/values-hu-rHU/strings.xml b/app/src/main/res/values-hu-rHU/strings.xml index 9212751a93..14099d8127 100644 --- a/app/src/main/res/values-hu-rHU/strings.xml +++ b/app/src/main/res/values-hu-rHU/strings.xml @@ -1,122 +1,122 @@ - Visszavonás - Bezárás - Egyedi GMS implementáció a Vanced számára a microG Projekt alapján. - Egy módosított YouTube kliens számos hasznos funkcióval! - Vanced, a YouTube Music-ra! Kevésbé funkciógazdag, de kielégíti az igényeidet. - Visszaállítás - Mentés - Válaszd ki az Appot + Visszavonás + Bezárás + Egyedi GMS implementáció a Vanced számára a microG Projekt alapján. + Egy módosított YouTube kliens számos hasznos funkcióval! + Vanced, a YouTube Music-ra! Kevésbé funkciógazdag, de kielégíti az igényeidet. + Visszaállítás + Mentés + Válaszd ki az Appot - Rólunk - Útmutató - Manager - Naplók - Beállítások - Manager frissitése + Rólunk + Útmutató + Manager + Naplók + Beállítások + Manager frissitése - Rootolt az eszközöd? - Root hozzáférés engedélyezése - Lássunk neki - Legalább egy appot válassz! - Nem tudod mi ez vagy csak nem akarod használni a root verziót? Csak kattins a lenti kék nyílra! + Rootolt az eszközöd? + Root hozzáférés engedélyezése + Lássunk neki + Legalább egy appot válassz! + Nem tudod mi ez vagy csak nem akarod használni a root verziót? Csak kattins a lenti kék nyílra! - %1$s- ról - Download - Info - Launch - Újratelepítés - Uninstall - Update - Alkalmazások - Változáslista - %1$s letöltése - Telepítés + %1$s- ról + Download + Info + Launch + Újratelepítés + Uninstall + Update + Alkalmazások + Változáslista + %1$s letöltése + Telepítés Legújabb: - Először telepítse a Vanced microG-t + Először telepítse a Vanced microG-t A root hozzáférés nincs megadva - Közösségi média - Támogasson bennünket - Nem elérhető + Közösségi média + Támogasson bennünket + Nem elérhető Telepítve: - Kiemelés színe - Megjelenítés - Viselkedés - Letöltött fájlok törlése - Sikeresen törölte a fájlokat - Ezzel megengedi hogy információkat gyűjtsünk az alkalmazás teljesítményéről és az összeomlási naplóról - Firebase Analytics - Nyelv - A linkek egyéni Chrome ablakban nyílnak meg - Egyéni Chrome lapok használata - %1$s Leküldéses (Push) Értesítések - Értesítések fogadása, amikor a %1$s számára frissítés érhető el - Nem sikerült az időzítő új értékének mentése - Root alvás idő script - Alvás idő beállítás a /data/adb/service.d/app.sh scriptben, hasznos a csatlakoztatási problémák javítására - Rendszer alapértelmezett - Kinézet - Sötét téma - Világos téma - Frissítő központ - Új frissítések nem elérhetőek - Változat + Kiemelés színe + Megjelenítés + Viselkedés + Letöltött fájlok törlése + Sikeresen törölte a fájlokat + Ezzel megengedi hogy információkat gyűjtsünk az alkalmazás teljesítményéről és az összeomlási naplóról + Firebase Analytics + Nyelv + A linkek egyéni Chrome ablakban nyílnak meg + Egyéni Chrome lapok használata + %1$s Leküldéses (Push) Értesítések + Értesítések fogadása, amikor a %1$s számára frissítés érhető el + Nem sikerült az időzítő új értékének mentése + Root alvás idő script + Alvás idő beállítás a /data/adb/service.d/app.sh scriptben, hasznos a csatlakoztatási problémák javítására + Rendszer alapértelmezett + Kinézet + Sötét téma + Világos téma + Frissítő központ + Új frissítések nem elérhetőek + Változat - A napló mentése nem sikerült - Napló sikeresen mentve + A napló mentése nem sikerült + Napló sikeresen mentve Részletek - %1$s telepítőfájlok észlelve! - A Manager észlelte a %1$s telepítéséhez szükséges fájlokat. + %1$s telepítőfájlok észlelve! + A Manager észlelte a %1$s telepítéséhez szükséges fájlokat. Akarod telepíteni? %1$s Telepítés személyreszabása - Frissítések ellenőrzése... + Frissítések ellenőrzése... Nyelv: %1$s Kinézet: %1$s Verzió: %1$s - Hiba - Útmutató - Állj! + Hiba + Útmutató + Állj! A Vanced Magisk/TWRP verzióját használja, ami már nem támogatott és nem frissíthető ezzel az alkalmazással. Távolítsa el a Magisk modul eltávolításával vagy TWRP Vanced eltávolítóval. - Hogy a Vanced-et telepítsd, ki KELL kapcsolnod a MIUI Optimalizációt a fejlesztői beállításokban. (Ezt figyelmen kívül hagyhatod ha 20.2.20 vagy későbbi xiaomi.eu alapú ROM-ot használsz) - MIUI optimalizálások engedélyezve! - Kérjük NE lépjen ki a telepítési folyamat alatt! - Újra letölt - Arra kérünk, győződjön meg róla, hogy ezt az alkalmazást a vancedapp.com oldalról, a Vanced Discord szerveréről vagy a Vanced GitHub-ról töltötte le + Hogy a Vanced-et telepítsd, ki KELL kapcsolnod a MIUI Optimalizációt a fejlesztői beállításokban. (Ezt figyelmen kívül hagyhatod ha 20.2.20 vagy későbbi xiaomi.eu alapú ROM-ot használsz) + MIUI optimalizálások engedélyezve! + Kérjük NE lépjen ki a telepítési folyamat alatt! + Újra letölt + Arra kérünk, győződjön meg róla, hogy ezt az alkalmazást a vancedapp.com oldalról, a Vanced Discord szerveréről vagy a Vanced GitHub-ról töltötte le Verzió - Üdvözöljük + Üdvözöljük - Vanced nyelvének kiválasztása - Legújabb + Vanced nyelvének kiválasztása + Legújabb Világos + %1$s Válasszon ki legalább egy nyelvet! - Fekete - Sötét + Fekete + Sötét - Fejlesztői Menedzser - Egyéb Közreműködők - Források - Vanced csapat + Fejlesztői Menedzser + Egyéb Közreműködők + Források + Vanced csapat - Nem sikerült az APK beállítása a rendszer tulajdonoshoz, kérjük próbálja újra. - %1$s letöltése nem sikerült + Nem sikerült az APK beállítása a rendszer tulajdonoshoz, kérjük próbálja újra. + %1$s letöltése nem sikerült Nem sikerült az új kiemelés szín beállítása - A %1$s-t nem sikerült eltávolítani - A telepítéshez szükséges file-ok megtalálása meghiúsult. Töltse le újra a telepítőfile-okat és próbálja újra. - Nem sikerült az apk file-t megtalálni a fekete/sötét kinézethez, kérjük próbálja újra. - A művelet végrehajtása nem sikerült, mert a felhasználó megszakította a telepítést. - A telepítés nem sikerült, mert az alkalmazás egy másik, már telepített alkalmazással ütközik. Távolítsd el a jelenlegi verziót és próbáld újra. - A telepítés nem sikerült, mert a felhasználó, régebbi verzióra próbált frissíteni. Távolítsa el az eredeti alkalmazás frissítéseit, majd próbálja újra. - A telepítés ismeretlen ok miatt meghiúsult, kérjük csatlakozzon a Telegram vagy a Discord csatornánkhoz további támogatásért. Kérjük egy képernyőképet is mellékeljen ami a Haladó menüben készült - A telepítés nem sikerült, mert a telepítő fájl nem kompatibilis az eszközöddel. Töröld ki a letöltött fájlokat a beállításokban és próbáld újra. - A telepítés nem sikerült, mert az apk fájlok korruptak, próbáld újra. - A telepítés nem sikerült, mert a MIUI Optimalizáció engedélyezve van. Kapcsold ki a MIUI Optimalizációt és próbáld újra. - A telepítés nem sikerült, mert az apk aláírás ellenőrzés engedélyezve van. + A %1$s-t nem sikerült eltávolítani + A telepítéshez szükséges file-ok megtalálása meghiúsult. Töltse le újra a telepítőfile-okat és próbálja újra. + Nem sikerült az apk file-t megtalálni a fekete/sötét kinézethez, kérjük próbálja újra. + A művelet végrehajtása nem sikerült, mert a felhasználó megszakította a telepítést. + A telepítés nem sikerült, mert az alkalmazás egy másik, már telepített alkalmazással ütközik. Távolítsd el a jelenlegi verziót és próbáld újra. + A telepítés nem sikerült, mert a felhasználó, régebbi verzióra próbált frissíteni. Távolítsa el az eredeti alkalmazás frissítéseit, majd próbálja újra. + A telepítés ismeretlen ok miatt meghiúsult, kérjük csatlakozzon a Telegram vagy a Discord csatornánkhoz további támogatásért. Kérjük egy képernyőképet is mellékeljen ami a Haladó menüben készült + A telepítés nem sikerült, mert a telepítő fájl nem kompatibilis az eszközöddel. Töröld ki a letöltött fájlokat a beállításokban és próbáld újra. + A telepítés nem sikerült, mert az apk fájlok korruptak, próbáld újra. + A telepítés nem sikerült, mert a MIUI Optimalizáció engedélyezve van. Kapcsold ki a MIUI Optimalizációt és próbáld újra. + A telepítés nem sikerült, mert az apk aláírás ellenőrzés engedélyezve van. Kapcsold ki az apk aláírás ellenőrzését és próbáld újra. - A telepítés nem sikerült, mert nincs elég szabad hely. - Nem sikerült megtalálni az apk file-t a fekete/sötét kinézethez a telepítőből. Törölje a Manager alkalmazás adatait, majd próbálja újra. - Nem sikerült megtalálni az alap YouTube telepítési útvonalat a(z) split telepítés után. + A telepítés nem sikerült, mert nincs elég szabad hely. + Nem sikerült megtalálni az apk file-t a fekete/sötét kinézethez a telepítőből. Törölje a Manager alkalmazás adatait, majd próbálja újra. + Nem sikerült megtalálni az alap YouTube telepítési útvonalat a(z) split telepítés után. diff --git a/app/src/main/res/values-in-rID/strings.xml b/app/src/main/res/values-in-rID/strings.xml index fdc7c431b3..99531baaa0 100644 --- a/app/src/main/res/values-in-rID/strings.xml +++ b/app/src/main/res/values-in-rID/strings.xml @@ -1,120 +1,120 @@ - Batal - Tutup - Penerapan GMS kustom untuk Vanced yang didasarkan pada proyek microG. - Klien YouTube termodifikasi dengan berbagai fitur berguna! - Vanced, tetapi untuk YouTube Musik! Relatif memiliki fitur yang kurang kaya tetapi memenuhi kebutuhan anda. - Atur ulang - Simpan - Pilih Aplikasi Anda + Batal + Tutup + Penerapan GMS kustom untuk Vanced yang didasarkan pada proyek microG. + Klien YouTube termodifikasi dengan berbagai fitur berguna! + Vanced, tetapi untuk YouTube Musik! Relatif memiliki fitur yang kurang kaya tetapi memenuhi kebutuhan anda. + Atur ulang + Simpan + Pilih Aplikasi Anda - Tentang - Petunjuk - Manager - Logs - Pengaturan - Perbarui Manager + Tentang + Petunjuk + Manager + Logs + Pengaturan + Perbarui Manager - Apakah Perangkat Anda Mempunyai Akses Root? - Berikan Izin Root - Mari memulai - Pilih setidaknya satu aplikasi! - Tidak tahu apa ini atau tidak ingin menggunakan versi root? cukup klik panah biru di bawah! + Apakah Perangkat Anda Mempunyai Akses Root? + Berikan Izin Root + Mari memulai + Pilih setidaknya satu aplikasi! + Tidak tahu apa ini atau tidak ingin menggunakan versi root? cukup klik panah biru di bawah! - Tentang %1$s - Unduh - Informasi - Buka - Pasang ulang - Copot pemasangan - Perbarui - Aplikasi - Catatan perubahan - Mengunduh %1$s - Pasang + Tentang %1$s + Unduh + Informasi + Buka + Pasang ulang + Copot pemasangan + Perbarui + Aplikasi + Catatan perubahan + Mengunduh %1$s + Pasang Terbaru: - Pasang Vanced microG terlebih dahulu + Pasang Vanced microG terlebih dahulu Akses Root tidak diberikan - Media Sosial - Dukung kami - Tidak tersedia + Media Sosial + Dukung kami + Tidak tersedia Terpasang: - Aksen Warna - Penampilan - Perilaku - Hapus file yang diunduh - Berhasil menghapus file - Analisis firebase mengizinkan kami mengumpulkan informasi tentang performa aplikasi dan catatan crash - Analisis Firebase - Bahasa - Tautan akan terbuka di Chrome Custom Tabs - Gunakan Chrome Custom Tabs - Notifikasi Push %1$s - Terima notifikasi push saat pembaruan untuk %1$s dirilis - Gagal untuk menyimpan value waktu baru - Waktu Root Script Sleep - Sesuaikan value sleep time yang digunakan dalam skript /data/adb/service.d/app.sh, berguna untuk memperbaiki masalah pemasangan - Standar Sistem - Tema - Tema Gelap - Tema Terang - Pusat Pembaruan Manager - Tidak ada pembaruan - Varian + Aksen Warna + Penampilan + Perilaku + Hapus file yang diunduh + Berhasil menghapus file + Analisis firebase mengizinkan kami mengumpulkan informasi tentang performa aplikasi dan catatan crash + Analisis Firebase + Bahasa + Tautan akan terbuka di Chrome Custom Tabs + Gunakan Chrome Custom Tabs + Notifikasi Push %1$s + Terima notifikasi push saat pembaruan untuk %1$s dirilis + Gagal untuk menyimpan value waktu baru + Waktu Root Script Sleep + Sesuaikan value sleep time yang digunakan dalam skript /data/adb/service.d/app.sh, berguna untuk memperbaiki masalah pemasangan + Standar Sistem + Tema + Tema Gelap + Tema Terang + Pusat Pembaruan Manager + Tidak ada pembaruan + Varian - Tidak bisa menyimpan log - Berhasil menyimpan log + Tidak bisa menyimpan log + Berhasil menyimpan log Rincian - File instalasi %1$s terdeteksi! - Manager mendeteksi bahwa semua file yang diperlukan untuk instalasi %1$s ditemukan. Apakah anda ingin memasangnya? + File instalasi %1$s terdeteksi! + Manager mendeteksi bahwa semua file yang diperlukan untuk instalasi %1$s ditemukan. Apakah anda ingin memasangnya? Preferensi Instalasi %1$s - Memeriksa pembaruan… + Memeriksa pembaruan… Bahasa: %1$s Tema: %1$s Versi: %1$s - Terjadi kesalahan - Petunjuk - Berhenti! + Terjadi kesalahan + Petunjuk + Berhenti! Anda memakai Vanced versi Magisk/TWRP, yang pengembangannya dihentikan dan tidak bisa diperbarui menggunakan aplikasi ini. Mohon untuk menghapusnya dengan menghapus modul Magisk/gunakan pencopot Vanced TWRP. - Untuk memasang Vanced, anda HARUS menonaktifkan Optimisasi MIUI pada pengaturan developer. (Anda dapat mengabaikan peringatan ini apabila anda menggunakan ROM versi 20.2.20 atau lebih yang berbasis xiaomi.eu) - Optimisasi MIUI diaktifkan! - Mohon untuk TIDAK keluar dari aplikasi saat proses ini! - Unduh ulang - Pastikan anda mengunduh aplikasi ini dari vancedapp.com, server Discord Vanced, atau Vanced Github + Untuk memasang Vanced, anda HARUS menonaktifkan Optimisasi MIUI pada pengaturan developer. (Anda dapat mengabaikan peringatan ini apabila anda menggunakan ROM versi 20.2.20 atau lebih yang berbasis xiaomi.eu) + Optimisasi MIUI diaktifkan! + Mohon untuk TIDAK keluar dari aplikasi saat proses ini! + Unduh ulang + Pastikan anda mengunduh aplikasi ini dari vancedapp.com, server Discord Vanced, atau Vanced Github Versi - Selamat datang + Selamat datang - Pilih bahasa yang anda inginkan untuk Vanced - Terbaru + Pilih bahasa yang anda inginkan untuk Vanced + Terbaru Terang + %1$s Pilih setidaknya satu bahasa! - Hitam - Gelap + Hitam + Gelap - Pengembang Manager - Kontributor Lain - Sumber - Tim Vanced + Pengembang Manager + Kontributor Lain + Sumber + Tim Vanced - Gagal untuk `chown` APK ke pemilik sistem, mohon coba lagi. - Gagal Mengunduh %1$s + Gagal untuk `chown` APK ke pemilik sistem, mohon coba lagi. + Gagal Mengunduh %1$s Gagal untuk menerapkan warna aksen baru - Gagal untuk mencopot pemasangan paket %1$s - Gagal untuk menemukan file yang diperlukan untuk instalasi. Unduh ulang file instalasi, lalu coba lagi. - Gagal untuk menemukan file apk untuk tema hitam/gelap dari penyimpanan, mohon coba lagi. - Pemasangan gagal dikarenakan pengguna membatalkan pemasangan. - Pemasangan gagal dikarenakan aplikasi konflik dengan aplikasi yang sudah terpasang. Copot pemasangan aplikasi versi saat ini, lalu coba lagi. - Pemasangan gagal dikarenakan pengguna mencoba menurunkan versi paket. Hapus pembaruan dari aplikasi bawaan, lalu coba lagi. - Pemasangan gagal untuk alasan yang tidak diketahui, gabung Telegram atau Discord kami untuk bantuan lebih lanjut. Mohon untuk melampirkan screenshot dari menu Tingkat Lanjut - Pemasangan gagal dikarenakan file pemasangan tidak kompatibel dengan perangkat anda. Hapus file yang diunduh di pengaturan, lalu coba lagi. - Pemasangan gagal dikarenakan file apk rusak, mohon coba lagi. - Pemasangan gagal dikarenakan Optimisasi MIUI diaktifkan. Nonaktifkan Optimisasi MIUI, lalu coba lagi. - Pemasangan gagal dikarenakan apk signature verification diaktifkan. Nonaktifkan apk signature verification, lalu coba lagi. - Pemasangan gagal dikarenakan perangkat tidak memiliki ruang penyimpanan yang cukup. - Gagal untuk menemukan file apk untuk tema hitam/gelap dari penginstal. Hapus data aplikasi Manager, lalu coba lagi. - Gagal untuk menemukan path instalasi YouTube setelah pemasangan split. + Gagal untuk mencopot pemasangan paket %1$s + Gagal untuk menemukan file yang diperlukan untuk instalasi. Unduh ulang file instalasi, lalu coba lagi. + Gagal untuk menemukan file apk untuk tema hitam/gelap dari penyimpanan, mohon coba lagi. + Pemasangan gagal dikarenakan pengguna membatalkan pemasangan. + Pemasangan gagal dikarenakan aplikasi konflik dengan aplikasi yang sudah terpasang. Copot pemasangan aplikasi versi saat ini, lalu coba lagi. + Pemasangan gagal dikarenakan pengguna mencoba menurunkan versi paket. Hapus pembaruan dari aplikasi bawaan, lalu coba lagi. + Pemasangan gagal untuk alasan yang tidak diketahui, gabung Telegram atau Discord kami untuk bantuan lebih lanjut. Mohon untuk melampirkan screenshot dari menu Tingkat Lanjut + Pemasangan gagal dikarenakan file pemasangan tidak kompatibel dengan perangkat anda. Hapus file yang diunduh di pengaturan, lalu coba lagi. + Pemasangan gagal dikarenakan file apk rusak, mohon coba lagi. + Pemasangan gagal dikarenakan Optimisasi MIUI diaktifkan. Nonaktifkan Optimisasi MIUI, lalu coba lagi. + Pemasangan gagal dikarenakan apk signature verification diaktifkan. Nonaktifkan apk signature verification, lalu coba lagi. + Pemasangan gagal dikarenakan perangkat tidak memiliki ruang penyimpanan yang cukup. + Gagal untuk menemukan file apk untuk tema hitam/gelap dari penginstal. Hapus data aplikasi Manager, lalu coba lagi. + Gagal untuk menemukan path instalasi YouTube setelah pemasangan split. diff --git a/app/src/main/res/values-it-rIT/strings.xml b/app/src/main/res/values-it-rIT/strings.xml index fcb3855fdd..11060915cd 100644 --- a/app/src/main/res/values-it-rIT/strings.xml +++ b/app/src/main/res/values-it-rIT/strings.xml @@ -1,120 +1,120 @@ - Annulla - Chiudi - Un\'implementazione GMS personalizzata per Vanced basata sul progetto microG. - Un client YouTube modificato con molte utili funzionalità! - Vanced, ma per YouTube Music! Relativamente meno ricco di funzionalità ma ugualmente adattabile alle tue esigenze. - Reimposta - Salva - Seleziona le Tue App + Annulla + Chiudi + Un\'implementazione GMS personalizzata per Vanced basata sul progetto microG. + Un client YouTube modificato con molte utili funzionalità! + Vanced, ma per YouTube Music! Relativamente meno ricco di funzionalità ma ugualmente adattabile alle tue esigenze. + Reimposta + Salva + Seleziona le Tue App - Informazioni - Guida - Manager - Registri - Impostazioni - Aggiorna Manager + Informazioni + Guida + Manager + Registri + Impostazioni + Aggiorna Manager - Il Tuo Dispositivo Ha i Permessi di Root? - Concedi i Permessi di Root - Iniziamo - Seleziona almeno un\'app! - Non sai cos\'è o non vuoi utilizzare la versione root? clicca sulla freccia blu qui in basso! + Il Tuo Dispositivo Ha i Permessi di Root? + Concedi i Permessi di Root + Iniziamo + Seleziona almeno un\'app! + Non sai cos\'è o non vuoi utilizzare la versione root? clicca sulla freccia blu qui in basso! - Informazioni su %1$s - Scarica - Informazioni - Avvia - Reinstalla - Disinstalla - Aggiorna - App - Novità - Download in corso di %1$s - Installa + Informazioni su %1$s + Scarica + Informazioni + Avvia + Reinstalla + Disinstalla + Aggiorna + App + Novità + Download in corso di %1$s + Installa Disponibile: - Installa prima Vanced microG + Installa prima Vanced microG Accesso root non consentito - Social Media - Sostienici - Non disponibile + Social Media + Sostienici + Non disponibile Installata: - Colore Evidenziazione - Aspetto - Comportamento - Cancella i file scaricati - Cancellazione file riuscita - Questo ci consente di raccogliere informazioni sulle prestazioni dell\'app ed i registri sui crash - Analisi Firebase - Lingua - I link verranno aperti nelle Schede Personalizzate di Chrome - Utilizza le Schede Personalizzate di Chrome - Notifiche Push di %1$s - Ricevi notifiche push quando un aggiornamento per %1$s è disponibile - Impossibile salvare il nuovo valore temporale - Tempo Di Sospensione Script Root - Regola il valore del tempo di sospensione utilizzato nello script /data/adb/service.d/app.sh, utile per risolvere i problemi di montaggio - Predefinito di Sistema - Tema - Tema Scuro - Tema Chiaro - Centro Aggiornamenti - Nessun nuovo aggiornamento - Variante + Colore Evidenziazione + Aspetto + Comportamento + Cancella i file scaricati + Cancellazione file riuscita + Questo ci consente di raccogliere informazioni sulle prestazioni dell\'app ed i registri sui crash + Analisi Firebase + Lingua + I link verranno aperti nelle Schede Personalizzate di Chrome + Utilizza le Schede Personalizzate di Chrome + Notifiche Push di %1$s + Ricevi notifiche push quando un aggiornamento per %1$s è disponibile + Impossibile salvare il nuovo valore temporale + Tempo Di Sospensione Script Root + Regola il valore del tempo di sospensione utilizzato nello script /data/adb/service.d/app.sh, utile per risolvere i problemi di montaggio + Predefinito di Sistema + Tema + Tema Scuro + Tema Chiaro + Centro Aggiornamenti + Nessun nuovo aggiornamento + Variante - Impossibile salvare i registri - Registri salvati correttamente + Impossibile salvare i registri + Registri salvati correttamente Dettagli - %1$s file di installazione rilevati! - Manager ha trovato tutti i file necessari per l\'installazione di %1$s. Vuoi installarli? + %1$s file di installazione rilevati! + Manager ha trovato tutti i file necessari per l\'installazione di %1$s. Vuoi installarli? Preferenze Installazione di %1$s - Verifica aggiornamenti… + Verifica aggiornamenti… Lingue: %1$s Tema: %1$s Versione: %1$s - Errore - Guida - Aspetta! + Errore + Guida + Aspetta! Stai utilizzando la versione Magisk/TWRP di Vanced, ormai obsoleta e non più aggiornabile tramite questa app. Per favore, rimuovila eliminando il modulo Magisk oppure utilizzando TWRP Vanced uninstaller. - Per installare Vanced, DEVI disabilitare le ottimizzazioni MIUI nelle opzioni sviluppatore. (Puoi ignorare questo avviso se stai usando la ROM 20.2.20 o successiva basata su xiaomi.eu) - Le ottimizzazioni MIUI sono abilitate! - Si prega di NON uscire dall\'app durante questo processo! - Scarica nuovamente - Assicurati di aver scaricato l\'app da vancedapp.com, dal server Discord di Vanced o dalla pagina GitHub di Vanced + Per installare Vanced, DEVI disabilitare le ottimizzazioni MIUI nelle opzioni sviluppatore. (Puoi ignorare questo avviso se stai usando la ROM 20.2.20 o successiva basata su xiaomi.eu) + Le ottimizzazioni MIUI sono abilitate! + Si prega di NON uscire dall\'app durante questo processo! + Scarica nuovamente + Assicurati di aver scaricato l\'app da vancedapp.com, dal server Discord di Vanced o dalla pagina GitHub di Vanced Versione - Benvenuto + Benvenuto - Scegli le tue lingue preferite per Vanced - Versione più recente + Scegli le tue lingue preferite per Vanced + Versione più recente Chiaro + %1$s Seleziona almeno una lingua! - Nero - Scuro + Nero + Scuro - Sviluppatori di Manager - Altri Collaboratori - Codice Sorgente - Il Team di Vanced + Sviluppatori di Manager + Altri Collaboratori + Codice Sorgente + Il Team di Vanced - Impossibile modificare il proprietario dell\'apk nel proprietario di sistema, per favore riprova. - Errore nel Download di %1$s + Impossibile modificare il proprietario dell\'apk nel proprietario di sistema, per favore riprova. + Errore nel Download di %1$s Impossibile applicare il nuovo colore di accento - Impossibile disinstallare il pacchetto %1$s - Impossibile individuare i file richiesti per l\'installazione. Scaricali nuovamente e riprova. - Impossibile individuare il file apk per il tema nero/scuro dalla memoria, per favore riprova. - Installazione non riuscita. L\'utente ha annullato l\'installazione. - Installazione fallita perché l\'applicazione è in conflitto con un\'app già installata. Disinstallare la versione corrente dell\'applicazione, quindi riprovare. - Installazione fallita. È stato effettuato un tentativo di downgrade del pacchetto. Disinstalla gli aggiornamenti dall\'app stock, quindi riprova. - Installazione non riuscita per motivi sconosciuti, unisciti al nostro Telegram o Discord per ulteriore supporto. Allega anche uno screenshot dal menu Avanzate - Installazione non riuscita, il file di installazione non è compatibile con il tuo dispositivo. Elimina i file scaricati nelle impostazioni, poi riprova. - Installazione non riuscita a causa di file apk corrotti, si prega di riprovare. - Installazione non riuscita, le ottimizzazioni di MIUI sono attivate. Disattiva le ottimizzazioni di MIUI, poi riprova. - Installazione non riuscita, la verifica della firma apk è attivata. Disattiva la verifica della firma apk, poi riprova. - Installazione non riuscita perché il dispositivo non dispone di sufficiente spazio libero. - Impossibile trovare il file apk per il tema nero/scuro dall\'installer. Cancella i dati dell\'app Manager, quindi riprova. - Impossibile individuare il percorso di installazione di YouTube stock dopo l\'installazione divisa. + Impossibile disinstallare il pacchetto %1$s + Impossibile individuare i file richiesti per l\'installazione. Scaricali nuovamente e riprova. + Impossibile individuare il file apk per il tema nero/scuro dalla memoria, per favore riprova. + Installazione non riuscita. L\'utente ha annullato l\'installazione. + Installazione fallita perché l\'applicazione è in conflitto con un\'app già installata. Disinstallare la versione corrente dell\'applicazione, quindi riprovare. + Installazione fallita. È stato effettuato un tentativo di downgrade del pacchetto. Disinstalla gli aggiornamenti dall\'app stock, quindi riprova. + Installazione non riuscita per motivi sconosciuti, unisciti al nostro Telegram o Discord per ulteriore supporto. Allega anche uno screenshot dal menu Avanzate + Installazione non riuscita, il file di installazione non è compatibile con il tuo dispositivo. Elimina i file scaricati nelle impostazioni, poi riprova. + Installazione non riuscita a causa di file apk corrotti, si prega di riprovare. + Installazione non riuscita, le ottimizzazioni di MIUI sono attivate. Disattiva le ottimizzazioni di MIUI, poi riprova. + Installazione non riuscita, la verifica della firma apk è attivata. Disattiva la verifica della firma apk, poi riprova. + Installazione non riuscita perché il dispositivo non dispone di sufficiente spazio libero. + Impossibile trovare il file apk per il tema nero/scuro dall\'installer. Cancella i dati dell\'app Manager, quindi riprova. + Impossibile individuare il percorso di installazione di YouTube stock dopo l\'installazione divisa. diff --git a/app/src/main/res/values-iw-rIL/strings.xml b/app/src/main/res/values-iw-rIL/strings.xml index 5f55082b82..0cf2badea9 100644 --- a/app/src/main/res/values-iw-rIL/strings.xml +++ b/app/src/main/res/values-iw-rIL/strings.xml @@ -1,120 +1,120 @@ - ביטול - סגור - שירותים מותאמים אישית של Google במיוחד ל־Vanced, מבוססים על פרויקט microG. - YouTube משופר עם תכונות שימושיות רבות! - Vacned, אבל של YouTube Music! יחסית פחות עשיר בתכונות, אבל ממלא אחר צרכיך. - איפוס - שמור - בחר את היישומים שלך + ביטול + סגור + שירותים מותאמים אישית של Google במיוחד ל־Vanced, מבוססים על פרויקט microG. + YouTube משופר עם תכונות שימושיות רבות! + Vacned, אבל של YouTube Music! יחסית פחות עשיר בתכונות, אבל ממלא אחר צרכיך. + איפוס + שמור + בחר את היישומים שלך - אודות - מדריך - מנהל - יומני רישום - הגדרות - מנהל העדכונים + אודות + מדריך + מנהל + יומני רישום + הגדרות + מנהל העדכונים - האם המכשיר שלך בעל הרשאות Root? - הענק הרשאות Root - בואו נתחיל - בחר לפחות יישום אחד! - לא יודעים מה זה או לא רוצים להשתמש בגרסת ה־Root? פשוט לחצו על החץ הכחול למטה! + האם המכשיר שלך בעל הרשאות Root? + הענק הרשאות Root + בואו נתחיל + בחר לפחות יישום אחד! + לא יודעים מה זה או לא רוצים להשתמש בגרסת ה־Root? פשוט לחצו על החץ הכחול למטה! - אודות %1$s - הורדה - מידע - הפעל - התקן מחדש - הסרת ההתקנה - עדכן - יישומים - היסטורית שינויים - מוריד את %1$s - התקן + אודות %1$s + הורדה + מידע + הפעל + התקן מחדש + הסרת ההתקנה + עדכן + יישומים + היסטורית שינויים + מוריד את %1$s + התקן החדש ביותר: - התקן את שירותי Google של Vanced תחילה + התקן את שירותי Google של Vanced תחילה לא הוענקו הרשאות Root - רשתות חברתיות - תמכו בנו - לא זמין + רשתות חברתיות + תמכו בנו + לא זמין מותקן: - צבע הדגשה - מראה - התנהגות - מחק קבצים שהורדו - מחיקת הקבצים הסתיימה בהצלחה - מאפשר לנו לאסוף מידע על ביצועי היישום וסיבות לקריסתו - ניתוח מידע משתמש - שפה - קישורים יפתחו בכרטיסיות מותאמות אישית של Chrome - השתמש בכרטיסייה מותאמת אישית של Chrome - %1$s התראות דחיפה - קבל התראות דחיפה כשעדכון ל־%1$s משתחרר - נכשל בשמירת ערך הזמן החדש - Root Script Sleep Time - תשנה את זמן השינה הנמצא ב /data/adb/service.d/app.sh, זה עוזר כדי לתקן בעיות אתחול - ברירת מחדל - ערכת נושא - ערכת נושא כהה - ערכת נושא בהירה - מרכז העדכונים - אין עדכונים חדשים - סוג + צבע הדגשה + מראה + התנהגות + מחק קבצים שהורדו + מחיקת הקבצים הסתיימה בהצלחה + מאפשר לנו לאסוף מידע על ביצועי היישום וסיבות לקריסתו + ניתוח מידע משתמש + שפה + קישורים יפתחו בכרטיסיות מותאמות אישית של Chrome + השתמש בכרטיסייה מותאמת אישית של Chrome + %1$s התראות דחיפה + קבל התראות דחיפה כשעדכון ל־%1$s משתחרר + נכשל בשמירת ערך הזמן החדש + Root Script Sleep Time + תשנה את זמן השינה הנמצא ב /data/adb/service.d/app.sh, זה עוזר כדי לתקן בעיות אתחול + ברירת מחדל + ערכת נושא + ערכת נושא כהה + ערכת נושא בהירה + מרכז העדכונים + אין עדכונים חדשים + סוג - לא ניתן היה לשמור יומני רישום - יומני הרישום נשמרו בהצלחה + לא ניתן היה לשמור יומני רישום + יומני הרישום נשמרו בהצלחה פרטים - %1$s קבצי התקנה נמצאו! - המנהל זיהה שכל הקבצים הנדרשים עבור התקנת %1$s נמצאו. האם ברצונך להתקינם? + %1$s קבצי התקנה נמצאו! + המנהל זיהה שכל הקבצים הנדרשים עבור התקנת %1$s נמצאו. האם ברצונך להתקינם? %1$s העדפות התקנה - בודק אחר עדכונים… + בודק אחר עדכונים… שפה: %1$s ערכת נושא: %1$s גרסה: %1$s - שגיאה - מדריך - עצור! + שגיאה + מדריך + עצור! נדמה שאתה משתמש בגרסת ה־Magisk/TWRP של Vanced, שהתמיכה בה הופסקה והיא לא יכולה להתעדכן להתעדכן בעזרת האפליקציה הזו. אנא מחק אותה על ידי מחיקת ה־Module ב־Magisk או בשימוש במסיר ההתקנה של TWRP Vanced. - על מנת להתקין את Vanced, עליך להשבית מיטוב ל־MIUI בהגדרות מפתחים. (אתה יכול להתעלם מאזהרה זו אם אתה משתמש בגרסה 20.2.2 של הרום הבין־לאומי של שיאומי או גרסה מאוחרת יותר) - מיטוב למערכת ההפעלה MIUI פועל! - נא לא לצאת מהיישום במהלך תהליך זה! - הורד מחדש - ודא שהורדת את האפליקציה מהאתר vancedapp.com, שרת הדיסקורד של Vanced או מהעמוד של Vanced ב־GitHub + על מנת להתקין את Vanced, עליך להשבית מיטוב ל־MIUI בהגדרות מפתחים. (אתה יכול להתעלם מאזהרה זו אם אתה משתמש בגרסה 20.2.2 של הרום הבין־לאומי של שיאומי או גרסה מאוחרת יותר) + מיטוב למערכת ההפעלה MIUI פועל! + נא לא לצאת מהיישום במהלך תהליך זה! + הורד מחדש + ודא שהורדת את האפליקציה מהאתר vancedapp.com, שרת הדיסקורד של Vanced או מהעמוד של Vanced ב־GitHub גרסא - ברוכים הבאים + ברוכים הבאים - בחר את השפה המועדפת עליך ל־Vanced - העדכנית ביותר + בחר את השפה המועדפת עליך ל־Vanced + העדכנית ביותר בהיר + %1$s בחר לפחות שפה אחת! - שחור - שחרחר + שחור + שחרחר - מנהל למפתחים - תורמים אחרים - מקורות - צוות Vanced + מנהל למפתחים + תורמים אחרים + מקורות + צוות Vanced - נכשל בהחלפת הבעלים של קובץ ה־APK, אנא נסה בשנית. - תקלה בהורדה של %1$s + נכשל בהחלפת הבעלים של קובץ ה־APK, אנא נסה בשנית. + תקלה בהורדה של %1$s נכשל בהחלת ערכת הנושא החדשה - נכשל במחיקת החבילה %1$s - איתור הקבצים הנדרשים להתקנה נכשל. הורד מחדש את קבצי ההתקנה ונסה שוב. - נכשל האיתור של קובץ APK לערכת נושא שחורה/כהה מהאחסון, אנא נסה שוב. - ההתקנה נכשלה כיוון שהמשתמש ביטל אותה. - ההתקנה נכשלה כיוון שהאפליקציה מתנגשת עם גרסה מותקנת שלה, מחק את הגרסה הנוכחית של Vanced ולאחר מכן נסה שוב. - ההתקנה נכשלה כיוון שהמשתמש ניסה לשנמך את גרסת היישום. מחק עדכונים מאפליקציית YouTube הרגילה, ולאחר מכן נסה שוב. - ההתקנה נכשלה מסיבות לא ידועות, הצטרף לטלגרם או לדיסקורד לקבלת תמיכה נוספת. אנא צרף גם צילום מסך מהתפריט המתקדם - ההתקנה נכשלה מכיוון שההתקנה או הקובץ לא תואמים עם מכשירך. נקה הורדות שהושלמו מתוך ההגדרות, ואז נסה שוב. - ההתקנה נכשלה מכיוון שקבצי הישום הרוסים, בבקשה נסה שוב. - ההתקנה נכשלה מכיוון שאופטימיזצית MIUI פעילה. השבת את אופטימיזצית MIUI, ואז נסה שוב. - ההתקנה נכשלה מכיוון שאימות החתימה בישום פעילה. השבת את אימות החתימה בישום, ואז נסה שוב. - ההתקנה נכשלה כיוון שאין מספיק מקום פנוי במכשיר. - נכשל במציאת קובץ APK של ערכת נושא שחורה/כהה. נקה את נתוני האפליקציה Vanced Manager, ולאחר מכן נסה שוב. - נכשל איתור נתיב ההתקנה של YouTube הרגיל לאחר התקנה מפוצלת. + נכשל במחיקת החבילה %1$s + איתור הקבצים הנדרשים להתקנה נכשל. הורד מחדש את קבצי ההתקנה ונסה שוב. + נכשל האיתור של קובץ APK לערכת נושא שחורה/כהה מהאחסון, אנא נסה שוב. + ההתקנה נכשלה כיוון שהמשתמש ביטל אותה. + ההתקנה נכשלה כיוון שהאפליקציה מתנגשת עם גרסה מותקנת שלה, מחק את הגרסה הנוכחית של Vanced ולאחר מכן נסה שוב. + ההתקנה נכשלה כיוון שהמשתמש ניסה לשנמך את גרסת היישום. מחק עדכונים מאפליקציית YouTube הרגילה, ולאחר מכן נסה שוב. + ההתקנה נכשלה מסיבות לא ידועות, הצטרף לטלגרם או לדיסקורד לקבלת תמיכה נוספת. אנא צרף גם צילום מסך מהתפריט המתקדם + ההתקנה נכשלה מכיוון שההתקנה או הקובץ לא תואמים עם מכשירך. נקה הורדות שהושלמו מתוך ההגדרות, ואז נסה שוב. + ההתקנה נכשלה מכיוון שקבצי הישום הרוסים, בבקשה נסה שוב. + ההתקנה נכשלה מכיוון שאופטימיזצית MIUI פעילה. השבת את אופטימיזצית MIUI, ואז נסה שוב. + ההתקנה נכשלה מכיוון שאימות החתימה בישום פעילה. השבת את אימות החתימה בישום, ואז נסה שוב. + ההתקנה נכשלה כיוון שאין מספיק מקום פנוי במכשיר. + נכשל במציאת קובץ APK של ערכת נושא שחורה/כהה. נקה את נתוני האפליקציה Vanced Manager, ולאחר מכן נסה שוב. + נכשל איתור נתיב ההתקנה של YouTube הרגיל לאחר התקנה מפוצלת. diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml index 3df8266cc1..06b55d186b 100644 --- a/app/src/main/res/values-ja-rJP/strings.xml +++ b/app/src/main/res/values-ja-rJP/strings.xml @@ -1,120 +1,120 @@ - キャンセル - 閉じる - microG Project をベースにした、Vanced のためのGMSのカスタム実装 - 多くの便利な機能を備えた、改造されたYouTubeアプリ! - YouTube Music のための Vanced! 比較的機能は少ないですが、あなたの欲望を満たします。 - リセット - 保存 - アプリの選択 + キャンセル + 閉じる + microG Project をベースにした、Vanced のためのGMSのカスタム実装 + 多くの便利な機能を備えた、改造されたYouTubeアプリ! + YouTube Music のための Vanced! 比較的機能は少ないですが、あなたの欲望を満たします。 + リセット + 保存 + アプリの選択 - このアプリについて - ガイド - Manager - ログ - 設定 - Manager を更新 + このアプリについて + ガイド + Manager + ログ + 設定 + Manager を更新 - 端末をルート化していますか? - root 権限を付与 - さあ、始めましょう - アプリを少なくとも一つ選択してください! - これが何であるか分からないか、またはRootバージョンを使用したくない場合は、下の青い矢印をタップしてください! + 端末をルート化していますか? + root 権限を付与 + さあ、始めましょう + アプリを少なくとも一つ選択してください! + これが何であるか分からないか、またはRootバージョンを使用したくない場合は、下の青い矢印をタップしてください! - %1$s について - Download - Info - Launch - Reinstall - Uninstall - Update - アプリ - 更新履歴 - %1$s をダウンロードしています - インストール + %1$s について + Download + Info + Launch + Reinstall + Uninstall + Update + アプリ + 更新履歴 + %1$s をダウンロードしています + インストール 最新版: - はじめに Vanced microG をインストールしてください + はじめに Vanced microG をインストールしてください Root アクセスは許可されていません - ソーシャルメディア - サポート - 利用不可 + ソーシャルメディア + サポート + 利用不可 インストール済み: - アクセントカラー - 表示設定 - 動作 - ダウンロード済みファイルを消去 - ファイルを消去しました - アプリのパフォーマンスとクラッシュログに関する情報を収集できます - Firebase アナリティクス - 言語 - Chrome カスタムタブでリンクを開く - Chrome カスタムタブを使用 - %1$s プッシュ通知 - %1$s のアップデートがリリースされたときにプッシュ通知を受け取る - 新しいタイマーの値の保存に失敗しました - Root Script Sleep Time - Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues - システム設定 - テーマ - ダークテーマ - ライトテーマ - Manager アップデートセンター - アップデートはありません - 種類 + アクセントカラー + 表示設定 + 動作 + ダウンロード済みファイルを消去 + ファイルを消去しました + アプリのパフォーマンスとクラッシュログに関する情報を収集できます + Firebase アナリティクス + 言語 + Chrome カスタムタブでリンクを開く + Chrome カスタムタブを使用 + %1$s プッシュ通知 + %1$s のアップデートがリリースされたときにプッシュ通知を受け取る + 新しいタイマーの値の保存に失敗しました + Root Script Sleep Time + Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues + システム設定 + テーマ + ダークテーマ + ライトテーマ + Manager アップデートセンター + アップデートはありません + 種類 - ログの保存に失敗しました - ログが正常に保存されました + ログの保存に失敗しました + ログが正常に保存されました 詳細 - %1$s のインストールに必要なファイルが見つかりました - %1$s のインストールに必要な全てのファイル準備が整いました。インストールしますか? + %1$s のインストールに必要なファイルが見つかりました + %1$s のインストールに必要な全てのファイル準備が整いました。インストールしますか? %1$s のインストール設定 - アップデートを確認中... + アップデートを確認中... 言語: %1$s テーマ: %1$s バージョン: %1$s - エラー - ガイド - ストップ! + エラー + ガイド + ストップ! Vanced の Magisk/TWRP バージョンを使用しているようです。このバージョンは廃止されており、このアプリでは更新できません。 まず Magisk モジュールを削除するか、TWRP で Vanced uninstaller を使用してください。 - Vanced をインストールするには、開発者設定から MIUI 最適化を無効にしなければなりません。 (20.2.20 以降の xiaomi.eu ベースの ROM の場合はこの警告は無視してください) - MIUI 最適化が有効です! - この処理中はアプリを終了しないでください! - 再ダウンロード - Vancedapp.com、Vanced の Discord サーバーまたは GitHub からアプリをダウンロードしたことを確認してください + Vanced をインストールするには、開発者設定から MIUI 最適化を無効にしなければなりません。 (20.2.20 以降の xiaomi.eu ベースの ROM の場合はこの警告は無視してください) + MIUI 最適化が有効です! + この処理中はアプリを終了しないでください! + 再ダウンロード + Vancedapp.com、Vanced の Discord サーバーまたは GitHub からアプリをダウンロードしたことを確認してください バージョン - ようこそ + ようこそ - Vanced で使用する言語を選択 - 最新版 + Vanced で使用する言語を選択 + 最新版 ライト + %1$s 少なくとも一つの言語を選択してください! - ブラック - ダーク + ブラック + ダーク - Manager 開発 - 他の貢献者 - ソースコード - Vanced チーム + Manager 開発 + 他の貢献者 + ソースコード + Vanced チーム - システム所有者への APK の Chown ができませんでした、もう一度やり直してください. - %1$s のダウンロード中にエラー + システム所有者への APK の Chown ができませんでした、もう一度やり直してください. + %1$s のダウンロード中にエラー 新しいアクセントカラーの適用に失敗しました - パッケージ %1$s のアンインストールに失敗しました - インストールに必要なファイルが見つかりませんでした。再ダウンロードし、もう一度お試しください。 - ストレージからブラック/ダークテーマの APK ファイルが見つかりませんでした。もう一度お試しください。 - ユーザーがインストールを中断したためインストールに失敗しました。 - 既にインストールされたアプリと競合したため、インストールに失敗しました。インストールされたアプリをアンインストールしてから、もう一度やり直してください。 - アプリをダウングレードしようとしたため、インストールに失敗しました。インストールされたアプリをアンインストールしてから、再度お試しください。 - 不明な理由でインストールに失敗しました。さらなるサポートのためには、Telegram か Discord に参加してください。詳細メニューからスクリーンショットを添付してください。 - インストールするファイルがお使いのデバイスと互換性がないためインストールに失敗しました。設定でダウンロードしたファイルを削除してから、もう一度やり直してください。 - APK ファイルが破損しているためインストールに失敗しました、もう一度やり直してください。 - MIUI の最適化が有効になっているためインストールに失敗しました。MIUI の最適化を無効化してから、もう一度やり直してください。 - APK の署名検証が有効化されているためインストールに失敗しました。APK の署名検証を無効化してから、もう一度やり直してください。 - デバイスに十分な空き容量がないため、インストールに失敗しました。 - インストーラーからブラック/ダークテーマの APK ファイルが見つかりませんでした。Manager のアプリデータを消去してから、もう一度お試しください。 - 分割インストール後にストックの YouTube アプリのインストールパスが見つかりませんでした。 + パッケージ %1$s のアンインストールに失敗しました + インストールに必要なファイルが見つかりませんでした。再ダウンロードし、もう一度お試しください。 + ストレージからブラック/ダークテーマの APK ファイルが見つかりませんでした。もう一度お試しください。 + ユーザーがインストールを中断したためインストールに失敗しました。 + 既にインストールされたアプリと競合したため、インストールに失敗しました。インストールされたアプリをアンインストールしてから、もう一度やり直してください。 + アプリをダウングレードしようとしたため、インストールに失敗しました。インストールされたアプリをアンインストールしてから、再度お試しください。 + 不明な理由でインストールに失敗しました。さらなるサポートのためには、Telegram か Discord に参加してください。詳細メニューからスクリーンショットを添付してください。 + インストールするファイルがお使いのデバイスと互換性がないためインストールに失敗しました。設定でダウンロードしたファイルを削除してから、もう一度やり直してください。 + APK ファイルが破損しているためインストールに失敗しました、もう一度やり直してください。 + MIUI の最適化が有効になっているためインストールに失敗しました。MIUI の最適化を無効化してから、もう一度やり直してください。 + APK の署名検証が有効化されているためインストールに失敗しました。APK の署名検証を無効化してから、もう一度やり直してください。 + デバイスに十分な空き容量がないため、インストールに失敗しました。 + インストーラーからブラック/ダークテーマの APK ファイルが見つかりませんでした。Manager のアプリデータを消去してから、もう一度お試しください。 + 分割インストール後にストックの YouTube アプリのインストールパスが見つかりませんでした。 diff --git a/app/src/main/res/values-ka-rGE/strings.xml b/app/src/main/res/values-ka-rGE/strings.xml index 126bd1df82..a995bfbaa6 100644 --- a/app/src/main/res/values-ka-rGE/strings.xml +++ b/app/src/main/res/values-ka-rGE/strings.xml @@ -1,120 +1,120 @@ - გაუქმება - დახურვა - A custom GMS Implementation for Vanced based on the microG Project. - A modified YouTube client with many useful features! - Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. - განულება - შენახვა - აირჩიეთ თქვენი აპები + გაუქმება + დახურვა + A custom GMS Implementation for Vanced based on the microG Project. + A modified YouTube client with many useful features! + Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. + განულება + შენახვა + აირჩიეთ თქვენი აპები - შესახებ - ინსტრუქცია - მენეჯერი - ჟურნალი - პარამეტრები - მენეჯერის განახლება + შესახებ + ინსტრუქცია + მენეჯერი + ჟურნალი + პარამეტრები + მენეჯერის განახლება - არის თქვენი მოწყობილობა დარუთული? - მიეცით root წვდომა - დავიწყოთ - ერთი აპი მაინც მონიშნეთ! - არ იცით ეს რა არის ან არ გინდათ root ვერსიით სარგებობა? უბრალოდ დააჭირეთ ქვემოთ მოცემულ ლურჯ ისარს! + არის თქვენი მოწყობილობა დარუთული? + მიეცით root წვდომა + დავიწყოთ + ერთი აპი მაინც მონიშნეთ! + არ იცით ეს რა არის ან არ გინდათ root ვერსიით სარგებობა? უბრალოდ დააჭირეთ ქვემოთ მოცემულ ლურჯ ისარს! - %1$s-ის შესახებ - გადმოწერა - ონფორმაცია - ჩართვა - რეინსტალაცია - დეინსტალაცია - განახლება - აპები - ცვლილებები - მიმდინარეობს %1$s-ის გადმოწერა - ინსტალაცია + %1$s-ის შესახებ + გადმოწერა + ონფორმაცია + ჩართვა + რეინსტალაცია + დეინსტალაცია + განახლება + აპები + ცვლილებები + მიმდინარეობს %1$s-ის გადმოწერა + ინსტალაცია უახლესი: - Install Vanced microG first + Install Vanced microG first Root წვდომა არ არის მინიჭებული - სოციალური მედია - დაგვიჭირეთ მხარი - ხელმიუწვდომელია + სოციალური მედია + დაგვიჭირეთ მხარი + ხელმიუწვდომელია დაინსტალირებული: - აქცენტის ფერი - შესახედაობა - ფუნქციები - გადმოწერილი ფაილების გაწმენდა - ფაილები წარმატებით გაიწმინდა - ეს გვაძლევს უფლებას მოვიპოვოთ ინფორმაცია აპის მუშაობის შესახებ - Firebase-ის ანალიტიკა - ენა - ლინკები გაიხსნება Chrome Custom Tabs-ში - გამოიყენეთ Chrome Custom Tabs - %1$s-ს შეტყობინებები - მიიღეთ შეტყობინებები როდესაც %1$s-ის განახლება იქნება ხელმისაწვდომი - Failed to save new time value - Root Script Sleep Time - Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues - სისტემის ნაგულისხმევი - თემა - მუქი თემა - ღია თემა - განახლებების ცენტრი - განახლება არ არის აღმოჩენილი - ვარიანტი + აქცენტის ფერი + შესახედაობა + ფუნქციები + გადმოწერილი ფაილების გაწმენდა + ფაილები წარმატებით გაიწმინდა + ეს გვაძლევს უფლებას მოვიპოვოთ ინფორმაცია აპის მუშაობის შესახებ + Firebase-ის ანალიტიკა + ენა + ლინკები გაიხსნება Chrome Custom Tabs-ში + გამოიყენეთ Chrome Custom Tabs + %1$s-ს შეტყობინებები + მიიღეთ შეტყობინებები როდესაც %1$s-ის განახლება იქნება ხელმისაწვდომი + Failed to save new time value + Root Script Sleep Time + Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues + სისტემის ნაგულისხმევი + თემა + მუქი თემა + ღია თემა + განახლებების ცენტრი + განახლება არ არის აღმოჩენილი + ვარიანტი - Could not save logs - Successfully saved logs + Could not save logs + Successfully saved logs დეტალები - აღმოჩენილია %1$s -ის საინსტალაციო ფაილები! - მენეჯერმა აღმოაჩინა %1$s -ის ყველა საჭირო საინსტალაციო ფაილი. გინდათ დააინსტალიროთ? + აღმოჩენილია %1$s -ის საინსტალაციო ფაილები! + მენეჯერმა აღმოაჩინა %1$s -ის ყველა საჭირო საინსტალაციო ფაილი. გინდათ დააინსტალიროთ? %1$s-ის ინსტალაციის პარამეტრები - მიმდინარეობს განახლებების შემოწმება… + მიმდინარეობს განახლებების შემოწმება… ენა(ები): %1$s თემა: %1$s ვერსია: %1$s - შეცდომა - ინსტრუქცია - შეჩერდი! + შეცდომა + ინსტრუქცია + შეჩერდი! თქვენ იყენებთ Vanced-ის Magisk/TWRP ვერსიას, მაგრამ მისი მენეჯერიდან განახლება შეუძლებელია. გთხოვთ წაშალოთ იგი Magisk-იდან/TWRP-ს დეინსტალერიდან. - To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) - MIUI Optimizations are enabled! - Please do NOT exit the app during this process! - თავიდან გადმოწერა - დარწმუნდით, რომ აპი გადმოწერეთ vancedapp.com-იდან, Vanced Discord სერვერიდან ან GitHub-იდან + To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) + MIUI Optimizations are enabled! + Please do NOT exit the app during this process! + თავიდან გადმოწერა + დარწმუნდით, რომ აპი გადმოწერეთ vancedapp.com-იდან, Vanced Discord სერვერიდან ან GitHub-იდან ვერსია - მოგესალმებით + მოგესალმებით - აირჩიეთ სასურველი ენა(ები) Vanced-ისთვის - უახლესი + აირჩიეთ სასურველი ენა(ები) Vanced-ისთვის + უახლესი ღია + %1$s ერთი ენა მაინც მონიშნეთ! - შავი - მუქი + შავი + მუქი - Manager-ის დეველოპერები - Other Contributors - წყაროები - Vanced-ის გუნდი + Manager-ის დეველოპერები + Other Contributors + წყაროები + Vanced-ის გუნდი - `chown`-ის დროს მოხდა შეცდომა, გთცოვთ სცადოთ თავიდან. - შეცდომა %1$s-ის გადმოწერის დროს + `chown`-ის დროს მოხდა შეცდომა, გთცოვთ სცადოთ თავიდან. + შეცდომა %1$s-ის გადმოწერის დროს შეცდომა აქცენტის ფერის მიღების დროს - პაკეტი %1$s ვერ დეინსტალირდა - Failed to locate the required files for installation. Re-download the installation files, then try again. - Failed to locate apk file for black/dark theme from storage, please try again. - Installation failed because the user aborted the installation. - Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. - Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. - Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu - Installation failed because the installation file is incompatible with your device. Clear downloaded files in the Settings, then try again. - Installation failed because the apk files are corrupted, please try again. - Installation failed because MIUI Optimization is enabled. Disable MIUI Optimization, then try again. - Installation failed because apk signature verification is enabled. Disable apk signature verification, then try again. - Installation failed because the device doesn\'t have enough free space. - Failed to find apk file for black/dark theme from the installer. Clear app data of Manager, then try again. - Failed to locate the stock YouTube installation path after split installation. + პაკეტი %1$s ვერ დეინსტალირდა + Failed to locate the required files for installation. Re-download the installation files, then try again. + Failed to locate apk file for black/dark theme from storage, please try again. + Installation failed because the user aborted the installation. + Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. + Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. + Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu + Installation failed because the installation file is incompatible with your device. Clear downloaded files in the Settings, then try again. + Installation failed because the apk files are corrupted, please try again. + Installation failed because MIUI Optimization is enabled. Disable MIUI Optimization, then try again. + Installation failed because apk signature verification is enabled. Disable apk signature verification, then try again. + Installation failed because the device doesn\'t have enough free space. + Failed to find apk file for black/dark theme from the installer. Clear app data of Manager, then try again. + Failed to locate the stock YouTube installation path after split installation. diff --git a/app/src/main/res/values-kmr-rTR/strings.xml b/app/src/main/res/values-kmr-rTR/strings.xml index 8fa5ab03fa..8f6612ddf4 100644 --- a/app/src/main/res/values-kmr-rTR/strings.xml +++ b/app/src/main/res/values-kmr-rTR/strings.xml @@ -1,120 +1,120 @@ - Betal bike - Bigire - Ji bo Projeya microG ji bo Vanced tê tetbîqkirin. - Mişterîya YouTube bi gelek taybetmendiyên kêrhatî guherî! - Vanced, lê ji bo YouTube Music!. Ji bo hewcedariyên te, hinekî kêm-dewlemend e. - Nûsaz bike - Tomar bike - Sepanên xwe hilbijêre + Betal bike + Bigire + Ji bo Projeya microG ji bo Vanced tê tetbîqkirin. + Mişterîya YouTube bi gelek taybetmendiyên kêrhatî guherî! + Vanced, lê ji bo YouTube Music!. Ji bo hewcedariyên te, hinekî kêm-dewlemend e. + Nûsaz bike + Tomar bike + Sepanên xwe hilbijêre - Derbarê de - Rêber - Rêveber - Tomar - Sazkarî - Rêveberê Nûve bike + Derbarê de + Rêber + Rêveber + Tomar + Sazkarî + Rêveberê Nûve bike - Gelo cîhaza te Root e? - Destûra Root\'ê bide - Em dest pê bikin - Herî kêm sepanekê hilbijêre! - Gelo ev çi ye an naxwazî versiyona root bi kar bîne? tenê tîrê şîn ê jêrîn bitikînin! + Gelo cîhaza te Root e? + Destûra Root\'ê bide + Em dest pê bikin + Herî kêm sepanekê hilbijêre! + Gelo ev çi ye an naxwazî versiyona root bi kar bîne? tenê tîrê şîn ê jêrîn bitikînin! - Derbar %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - Sepanan - Gurankarî - Dakêşe %1$s - Saz bike + Derbar %1$s + Download + Info + Launch + Reinstall + Uninstall + Update + Sepanan + Gurankarî + Dakêşe %1$s + Saz bike Dawîn: - Pêşîn Vanced microG saz bikin + Pêşîn Vanced microG saz bikin Destlênedanên kokê nayê dayîn - Medyaya Civakî - Piştgiriya me bikin - Neberdest + Medyaya Civakî + Piştgiriya me bikin + Neberdest Sazkirî: - Rengê devkî - Xuyang - Tevger - Pelên dakêşandî paqij bikin - Pelên bi serkeftî hatin paqijkirin - Ev dibe ku em di derbarê performansa sepan û tomarê têkçûyî de agahdariyan berhev bikin - Firebase Analytics - Ziman - Girêdan dê di hilpekên taybet ên Chrome\'ê de vebin - Hilpekên Chrome\'ê yên taybet bi kar bîne - %1$s Danezanên Lezgîn - Dema ku hildemînek ji bo %1$s belav bû, danezanên lezgîn werbigire - Barkirina nirxa dema nû bi ser neket - Dema Xewê ya Skrîpta Root - Nirxa dema xewê ya ku tê bikaranîn sererast bikin /data/adb/service.d/app.sh skrîpt, ji bo rastkirina pirsgirêkên pêvekirinê kêrhatî ye - Jixwebera Sîstemê - Rûkar - Rûkara tarî - Rûkara Ronî - Navenda Hildemandina Rêveberê - Nûvekirinên nû tune - Varyant + Rengê devkî + Xuyang + Tevger + Pelên dakêşandî paqij bikin + Pelên bi serkeftî hatin paqijkirin + Ev dibe ku em di derbarê performansa sepan û tomarê têkçûyî de agahdariyan berhev bikin + Firebase Analytics + Ziman + Girêdan dê di hilpekên taybet ên Chrome\'ê de vebin + Hilpekên Chrome\'ê yên taybet bi kar bîne + %1$s Danezanên Lezgîn + Dema ku hildemînek ji bo %1$s belav bû, danezanên lezgîn werbigire + Barkirina nirxa dema nû bi ser neket + Dema Xewê ya Skrîpta Root + Nirxa dema xewê ya ku tê bikaranîn sererast bikin /data/adb/service.d/app.sh skrîpt, ji bo rastkirina pirsgirêkên pêvekirinê kêrhatî ye + Jixwebera Sîstemê + Rûkar + Rûkara tarî + Rûkara Ronî + Navenda Hildemandina Rêveberê + Nûvekirinên nû tune + Varyant - Torkirina rojnivîsk bi ser neket - Rojnivîsk bi serkeftî torandin + Torkirina rojnivîsk bi ser neket + Rojnivîsk bi serkeftî torandin Kîtekît - Pelên sazkirinê %1$s hatin tespîtkirin! - Rêveberê diyar kir ku hemû pelên pêwîst ji bo sazkirina %1$s hatine dîtin. Tu dixwazî saz bikî? + Pelên sazkirinê %1$s hatin tespîtkirin! + Rêveberê diyar kir ku hemû pelên pêwîst ji bo sazkirina %1$s hatine dîtin. Tu dixwazî saz bikî? Vebijarkên Sazkirinê yên %1$s - Li nûvekirinan tê vekolîn… + Li nûvekirinan tê vekolîn… Ziman(ên): %1$s Rûkar: %1$s Guherto: %1$s - Çewtî - Rêber - Bisekine! + Çewtî + Rêber + Bisekine! Tu versiyona Magisk/TWRP ya Vanced ê ku hatiye jêbirin û bi bikaranîna vê sepanê nikare were nûjenkirin, bi kar tîne. Ji kerema xwe rake bi rakirina mobîla Magisk/bi karanîna TWRP Vanced rakirin. - Ji bo sazkirina Vanced, divê tu optimîzasyonên MIUI di mîhengên pêşdebiran de neçalak bikî. (Heke hûn 20.2.20 an jî paşê bi romê xiaomi.eu vê hişyariyê paşguh bikin) - Optimîzasyonên MIUI tên çalak kirin! - Ji kerema xwe di vê pêvajoyê de ji sepanê dernakeve! - Ji nû ve daxîne - Pê bawer bin ku te ev sepan ji vancedapp.com, servera Discord a Vanced an jî JiGitHub ya Vanced dakêşandine + Ji bo sazkirina Vanced, divê tu optimîzasyonên MIUI di mîhengên pêşdebiran de neçalak bikî. (Heke hûn 20.2.20 an jî paşê bi romê xiaomi.eu vê hişyariyê paşguh bikin) + Optimîzasyonên MIUI tên çalak kirin! + Ji kerema xwe di vê pêvajoyê de ji sepanê dernakeve! + Ji nû ve daxîne + Pê bawer bin ku te ev sepan ji vancedapp.com, servera Discord a Vanced an jî JiGitHub ya Vanced dakêşandine Versiyon - Bi xêr hatî + Bi xêr hatî - Ziman(ên) xwe yën dilxwaz ji bo Vanced\'ê hilbijêre - Herî dawî + Ziman(ên) xwe yën dilxwaz ji bo Vanced\'ê hilbijêre + Herî dawî Ronahî + %1$s Bi kêmanî zimanekî hilbijêre! - Reş - Tarî + Reş + Tarî - Pêşvebirên Rêveberê - Beşdarên din - Çavkanî - Koma Vanced\'ê + Pêşvebirên Rêveberê + Beşdarên din + Çavkanî + Koma Vanced\'ê - APK\'yê ji xwediyê pergalê re \'chown\' bi ser neket, ji kerema xwe re careke din biceribînin. - Di daxistina %1$s de çewtî + APK\'yê ji xwediyê pergalê re \'chown\' bi ser neket, ji kerema xwe re careke din biceribînin. + Di daxistina %1$s de çewtî Lêpirandina rengê nû yê zaravayê biserneket - Sazkirina pakêta %1$s bi ser neket - Sazkirina pelên pêwîst bi ser neket. Pelên sazkirinê ji nû ve dakêşin, piştre dîsa biceribînin. - Nekarî pelê apk ji bo dirba reş/tarî ji hilanînê bicîh bike, ji kerema xwe re dîsa biceribîne. - Sazkirin bi ser neket ji ber ku bikarhêner sazkirin bete betalkirin. - Sazkirin bi ser neket ji ber ku pêvek bi pêvek berê sazkirî re naqede. Vê versiyona heyî ya vê appê saz bike, paşê dîsa biceribîne. - Sazkirin bi ser neket ji ber ku bikarhêner hewl da pakêtê kêm bike. Nûvekirinên ji parsûyê rabike, paşê dîsa biceribîne. - Sazkirin ji ber sedemên nediyar têk çû, ji bo piştgiriya zêdetir tevlî Telegram an Jî Discordê me bibin. Ji kerema xwe dîmenek ekranê jî ji menuya Pêşkeftî ve girêdayî bikin - Sazkirin bi ser neket ji ber ku pelê sazkirinê bi cîhaza we re ne hevkar e. Mîhengên daxistinî paqij bike, paşê dîsa biceribîne. - Sazkirin bi ser neket ji ber ku pelên apk\'ê nebaş in, ji kerema xwe careke din biceribînin. - Sazkirin bi ser neket ji ber ku MIUI Optimization çalak e. MIUI Optimization\'ê neçalak bikin, paşê dîsa biceribînin. - Sazkirin bi ser neket ji ber ku rastandina îmzeya apk\'ayê çalak e. Rastandina îmzeya apk\'ayê neçalak bikin, paşê dîsa biceribînin. - Sazkirin bi ser neket ji ber ku cîhaz têra xwe cihê belaş tune. - Dozîna dosiya apk ji bo rûkara reş/tarî ji sazkirinê bi ser neket. Daneyên sepanê ji rêveberê paqij bikin, paşê dîsa biceribîne. - Piştî sazkirina dabeşkirî, dozîna rêka sazkirina YouTube stokê bi ser neket. + Sazkirina pakêta %1$s bi ser neket + Sazkirina pelên pêwîst bi ser neket. Pelên sazkirinê ji nû ve dakêşin, piştre dîsa biceribînin. + Nekarî pelê apk ji bo dirba reş/tarî ji hilanînê bicîh bike, ji kerema xwe re dîsa biceribîne. + Sazkirin bi ser neket ji ber ku bikarhêner sazkirin bete betalkirin. + Sazkirin bi ser neket ji ber ku pêvek bi pêvek berê sazkirî re naqede. Vê versiyona heyî ya vê appê saz bike, paşê dîsa biceribîne. + Sazkirin bi ser neket ji ber ku bikarhêner hewl da pakêtê kêm bike. Nûvekirinên ji parsûyê rabike, paşê dîsa biceribîne. + Sazkirin ji ber sedemên nediyar têk çû, ji bo piştgiriya zêdetir tevlî Telegram an Jî Discordê me bibin. Ji kerema xwe dîmenek ekranê jî ji menuya Pêşkeftî ve girêdayî bikin + Sazkirin bi ser neket ji ber ku pelê sazkirinê bi cîhaza we re ne hevkar e. Mîhengên daxistinî paqij bike, paşê dîsa biceribîne. + Sazkirin bi ser neket ji ber ku pelên apk\'ê nebaş in, ji kerema xwe careke din biceribînin. + Sazkirin bi ser neket ji ber ku MIUI Optimization çalak e. MIUI Optimization\'ê neçalak bikin, paşê dîsa biceribînin. + Sazkirin bi ser neket ji ber ku rastandina îmzeya apk\'ayê çalak e. Rastandina îmzeya apk\'ayê neçalak bikin, paşê dîsa biceribînin. + Sazkirin bi ser neket ji ber ku cîhaz têra xwe cihê belaş tune. + Dozîna dosiya apk ji bo rûkara reş/tarî ji sazkirinê bi ser neket. Daneyên sepanê ji rêveberê paqij bikin, paşê dîsa biceribîne. + Piştî sazkirina dabeşkirî, dozîna rêka sazkirina YouTube stokê bi ser neket. diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml index a5ac9a75db..9339dd6227 100644 --- a/app/src/main/res/values-ko-rKR/strings.xml +++ b/app/src/main/res/values-ko-rKR/strings.xml @@ -1,120 +1,120 @@ - 취소 - 닫기 - microG 프로젝트를 기반으로 커스텀한 Vanced용 Google 모바일 서비스입니다. - 다수의 유용한 기능을 가지는 YouTube 변경 클라이언트입니다! - YouTube Music의 Vanced 버전입니다. 추가된 기능이 그렇게 많지는 않지만 충분히 만족하실 거예요. - 초기화 - 저장 - 설치할 앱 선택하기 + 취소 + 닫기 + microG 프로젝트를 기반으로 커스텀한 Vanced용 Google 모바일 서비스입니다. + 다수의 유용한 기능을 가지는 YouTube 변경 클라이언트입니다! + YouTube Music의 Vanced 버전입니다. 추가된 기능이 그렇게 많지는 않지만 충분히 만족하실 거예요. + 초기화 + 저장 + 설치할 앱 선택하기 - 정보 - 가이드 - Manager - 로그 - 설정 - 매니저 업데이트 + 정보 + 가이드 + Manager + 로그 + 설정 + 매니저 업데이트 - 기기가 루팅되어 있나요? - 루트 권한 부여 - 시작하기 - 적어도 하나의 앱을 선택해주세요 - 이게 무슨 뜻인지 모르시거나 루트 버전을 사용하고 싶지 않으시다고요? 그냥 아래의 파란색 화살표를 클릭하세요! + 기기가 루팅되어 있나요? + 루트 권한 부여 + 시작하기 + 적어도 하나의 앱을 선택해주세요 + 이게 무슨 뜻인지 모르시거나 루트 버전을 사용하고 싶지 않으시다고요? 그냥 아래의 파란색 화살표를 클릭하세요! - %1$s 정보 - 다운로드 - 정보 - 실행 - 재설치 - 제거 - 업데이트 - - 변경 사항 - %1$s 다운로드 중 - 설치 + %1$s 정보 + 다운로드 + 정보 + 실행 + 재설치 + 제거 + 업데이트 + + 변경 사항 + %1$s 다운로드 중 + 설치 최신: - Vanced microG를 우선 설치하십시오 + Vanced microG를 우선 설치하십시오 루트 권한이 부여되지 않았습니다 - 소셜 미디어 - 지원하기 - 사용 불가 + 소셜 미디어 + 지원하기 + 사용 불가 설치됨: - 강조 색상 - 모양 - 동작 - 다운로드된 파일 모두 지우기 - 다운로드된 파일을 모두 삭제했습니다 - 앱 성능과 충돌 기록에 대한 정보를 수집할 수 있게 해줍니다 - Firebase 분석 - 언어 - 링크가 Chrome 커스텀 탭으로 열립니다 - Chrome 커스텀 탭으로 열기 - %1$s 푸시 알림 - 새로운 %1$s 업데이트가 출시되면 알림 받기 - 새 시간 값을 저장할 수 없습니다. - 루트 스크립트 대기 시간 - /data/adb/service.d/app.sh 스크립트에 쓰이는 대기 시간을 조정하십시오. 설치 문제 해결에 유용합니다. - 시스템 기본값 - 테마 - 다크 테마 - 라이트 테마 - 업데이트 센터 - 새로운 업데이트 없음 - 앱 종류 + 강조 색상 + 모양 + 동작 + 다운로드된 파일 모두 지우기 + 다운로드된 파일을 모두 삭제했습니다 + 앱 성능과 충돌 기록에 대한 정보를 수집할 수 있게 해줍니다 + Firebase 분석 + 언어 + 링크가 Chrome 커스텀 탭으로 열립니다 + Chrome 커스텀 탭으로 열기 + %1$s 푸시 알림 + 새로운 %1$s 업데이트가 출시되면 알림 받기 + 새 시간 값을 저장할 수 없습니다. + 루트 스크립트 대기 시간 + /data/adb/service.d/app.sh 스크립트에 쓰이는 대기 시간을 조정하십시오. 설치 문제 해결에 유용합니다. + 시스템 기본값 + 테마 + 다크 테마 + 라이트 테마 + 업데이트 센터 + 새로운 업데이트 없음 + 앱 종류 - 로그 저장 실패 - 로그 저장됨 + 로그 저장 실패 + 로그 저장됨 자세히 - %1$s 설치에 필요한 파일을 찾았습니다! - Manager 앱이 %1$s 설치에 필요한 모든 파일을 찾았습니다. 지금 설치하시겠어요? + %1$s 설치에 필요한 파일을 찾았습니다! + Manager 앱이 %1$s 설치에 필요한 모든 파일을 찾았습니다. 지금 설치하시겠어요? %1$s 설치 설정 - 업데이트 확인 중입니다... + 업데이트 확인 중입니다... 언어: %1$s 테마: %1$s 버전: %1$s - 오류 - 가이드 - 잠깐만요! + 오류 + 가이드 + 잠깐만요! 현재 설치되어 있는 Vanced의 Magisk/TWRP 버전은 더 이상 지원되지 않으며 이 앱으로 업데이트할 수 없습니다. 먼저 삭제 프로그램을 이용하여 Vanced의 TWRP/Magisk 모듈을 제거하여 주시기 바랍니다. - Vanced를 올바르게 설치하려면, 개발자 설정으로 들어가서 MIUI 최적화 기능을 반드시 끄셔야 합니다. (단, 버전이 20.2.20 이상인 xiaomi.eu 기반 ROM을 사용하는 경우 이 경고를 무시하셔도 좋습니다) - MIUI 최적화 기능이 켜져 있습니다! - 이 작업을 하는 동안 이 앱에서 나가지 마세요! - 다시 다운로드 - 항상 vancedapp.com, 공식 Vanced 디스코드 서버 또는 공식 GitHub 저장소에서 Vanced Manager 앱을 다운로드해주세요. + Vanced를 올바르게 설치하려면, 개발자 설정으로 들어가서 MIUI 최적화 기능을 반드시 끄셔야 합니다. (단, 버전이 20.2.20 이상인 xiaomi.eu 기반 ROM을 사용하는 경우 이 경고를 무시하셔도 좋습니다) + MIUI 최적화 기능이 켜져 있습니다! + 이 작업을 하는 동안 이 앱에서 나가지 마세요! + 다시 다운로드 + 항상 vancedapp.com, 공식 Vanced 디스코드 서버 또는 공식 GitHub 저장소에서 Vanced Manager 앱을 다운로드해주세요. 버전 - 환영합니다 + 환영합니다 - Vanced에서 선호하는 언어를 선택해주세요 - 최신 + Vanced에서 선호하는 언어를 선택해주세요 + 최신 라이트 + %1$s 적어도 하나의 언어를 선택해주세요! - 검정 - 다크 + 검정 + 다크 - Manager 개발자 - 기타 기여자 - 소스 코드 - Vanced 팀 + Manager 개발자 + 기타 기여자 + 소스 코드 + Vanced 팀 - APK의 소유권을 시스템 관리자로 변경하던 중에 오류가 발생하였습니다. 다시 시도하십시오. - %1$s 다운로드 중 오류 발생 + APK의 소유권을 시스템 관리자로 변경하던 중에 오류가 발생하였습니다. 다시 시도하십시오. + %1$s 다운로드 중 오류 발생 강조 색상을 적용하지 못했습니다 - %1$s 패키지 제거에 실패하였습니다 - 설치에 필요한 파일을 찾지 못했습니다. 설치 파일을 다시 다운로드한 다음 재시도하십시오. - 저장소에서 블랙/다크 테마에 대한 apk 파일을 찾지 못했습니다. 다시 시도하십시오. - 사용자가 설치를 중단했기 때문에 앱을 설치하지 못했습니다. - 앱이 이미 설치된 앱과 충돌하여 설치하지 못했습니다. 현재 버전의 앱을 제거한 다음 다시 시도하십시오. - 사용자가 패키지를 이전 버전으로 변경하려고 하여 앱을 설치하지 못했습니다. 기본 앱의 업데이트를 제거한 후, 설치를 다시 시도해주세요. - 알 수 없는 이유로 인해 설치가 실패했습니다. 저희 텔레그램 또는 디스코드에 알려주시면 도와드리겠습니다. \'고급\' 메뉴의 스크린샷도 첨부하여 주십시오. - 설치 파일이 기기와 호환되지 않아 앱을 설치하지 못했습니다. Manager 설정에서 다운로드된 파일을 모두 삭제한 다음, 설치를 다시 진행해주세요. - APK 파일이 손상되어 앱을 설치하지 못했습니다. 설치를 다시 진행해주세요. - MIUI 최적화 기능이 켜져 있어 앱을 설치하지 못했습니다. MIUI 최적화 기능을 끄고, 설치를 다시 진행해주세요. - APK 서명 검증 기능이 활성화되어 있어 앱을 설치하지 못했습니다. 먼저 APK 서명 검증 기능을 비활성화한 다음, 설치를 다시 진행해주세요. - 기기에 충분한 여유 공간이 없어 설치하지 못했습니다. - 설치 관리자에서 블랙/다크 테마에 대한 apk 파일을 찾지 못했습니다. Vanced Manager의 앱 데이터를 삭제 한 다음 다시 시도하십시오. - 분할 설치 완료 후 기본 YouTube 앱 설치 경로를 찾을 수 없습니다. + %1$s 패키지 제거에 실패하였습니다 + 설치에 필요한 파일을 찾지 못했습니다. 설치 파일을 다시 다운로드한 다음 재시도하십시오. + 저장소에서 블랙/다크 테마에 대한 apk 파일을 찾지 못했습니다. 다시 시도하십시오. + 사용자가 설치를 중단했기 때문에 앱을 설치하지 못했습니다. + 앱이 이미 설치된 앱과 충돌하여 설치하지 못했습니다. 현재 버전의 앱을 제거한 다음 다시 시도하십시오. + 사용자가 패키지를 이전 버전으로 변경하려고 하여 앱을 설치하지 못했습니다. 기본 앱의 업데이트를 제거한 후, 설치를 다시 시도해주세요. + 알 수 없는 이유로 인해 설치가 실패했습니다. 저희 텔레그램 또는 디스코드에 알려주시면 도와드리겠습니다. \'고급\' 메뉴의 스크린샷도 첨부하여 주십시오. + 설치 파일이 기기와 호환되지 않아 앱을 설치하지 못했습니다. Manager 설정에서 다운로드된 파일을 모두 삭제한 다음, 설치를 다시 진행해주세요. + APK 파일이 손상되어 앱을 설치하지 못했습니다. 설치를 다시 진행해주세요. + MIUI 최적화 기능이 켜져 있어 앱을 설치하지 못했습니다. MIUI 최적화 기능을 끄고, 설치를 다시 진행해주세요. + APK 서명 검증 기능이 활성화되어 있어 앱을 설치하지 못했습니다. 먼저 APK 서명 검증 기능을 비활성화한 다음, 설치를 다시 진행해주세요. + 기기에 충분한 여유 공간이 없어 설치하지 못했습니다. + 설치 관리자에서 블랙/다크 테마에 대한 apk 파일을 찾지 못했습니다. Vanced Manager의 앱 데이터를 삭제 한 다음 다시 시도하십시오. + 분할 설치 완료 후 기본 YouTube 앱 설치 경로를 찾을 수 없습니다. diff --git a/app/src/main/res/values-ku-rTR/strings.xml b/app/src/main/res/values-ku-rTR/strings.xml index c07fd98bfa..99703e60b2 100644 --- a/app/src/main/res/values-ku-rTR/strings.xml +++ b/app/src/main/res/values-ku-rTR/strings.xml @@ -1,120 +1,120 @@ - Betal bike - Bigire - A custom GMS Implementation for Vanced based on the microG Project. - A modified YouTube client with many useful features! - Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. - Nûsaz bike - Tomar bike - Sepanên xwe hilbijêre + Betal bike + Bigire + A custom GMS Implementation for Vanced based on the microG Project. + A modified YouTube client with many useful features! + Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. + Nûsaz bike + Tomar bike + Sepanên xwe hilbijêre - Derbar - Rêzan - Rêvebirin - Logs - Sazkarî - Rêveberê hildemîne + Derbar + Rêzan + Rêvebirin + Logs + Sazkarî + Rêveberê hildemîne - Gelo cîhaza te Root e? - Destûra Root\'ê bide - Dest pê kirin - Herî kêm sepanekê hilbijêre! - Don\'t know what this is or don\'t want to use the root version? just click the blue arrow below! + Gelo cîhaza te Root e? + Destûra Root\'ê bide + Dest pê kirin + Herî kêm sepanekê hilbijêre! + Don\'t know what this is or don\'t want to use the root version? just click the blue arrow below! - Derbar %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - Apps - Guherîn - Tê daxistin %1$s - Saz bike + Derbar %1$s + Download + Info + Launch + Reinstall + Uninstall + Update + Apps + Guherîn + Tê daxistin %1$s + Saz bike Dawîn: - Install Vanced microG first + Install Vanced microG first Rê li gihana Root nehate dayîn - Social Media - Piştgiriya me bike - Berdest nîne + Social Media + Piştgiriya me bike + Berdest nîne Saz bike: - Rengê devokê - Xuyang - Behavior - Dosiyayên daxistî paqij bike - Dosiya, biserketî paqij bûn - Ev yek dihêle ku em di bara performansa sepanê û tomarên hilweşiyayî de agahiyan berhev bikin - Analîza Firebase\'ê - Ziman - Girêdan dê di hilpekên taybet ên Chrome\'ê de vebin - Hilpekên Chrome\'ê yên taybet bi kar bîne - %1$s danezanên lezgîn - Dema ku hildemînek ji bo %1$s belav bû, danezanên lezgîn werbigire - Failed to save new time value - Root Script Sleep Time - Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues - Jixwebera sîstemê - Rûkar - Rûkara tarî - Rûkara ronak - Navenda hildemandina rêveberê - Hildema nû nîne - Guharto + Rengê devokê + Xuyang + Behavior + Dosiyayên daxistî paqij bike + Dosiya, biserketî paqij bûn + Ev yek dihêle ku em di bara performansa sepanê û tomarên hilweşiyayî de agahiyan berhev bikin + Analîza Firebase\'ê + Ziman + Girêdan dê di hilpekên taybet ên Chrome\'ê de vebin + Hilpekên Chrome\'ê yên taybet bi kar bîne + %1$s danezanên lezgîn + Dema ku hildemînek ji bo %1$s belav bû, danezanên lezgîn werbigire + Failed to save new time value + Root Script Sleep Time + Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues + Jixwebera sîstemê + Rûkar + Rûkara tarî + Rûkara ronak + Navenda hildemandina rêveberê + Hildema nû nîne + Guharto - Could not save logs - Successfully saved logs + Could not save logs + Successfully saved logs Details - %1$s dosiyên sazkirinê peyda bûn! - Rêveberê peydabûna hemû ew dosiyên pêwîst ên ji bo sazkirina %1$s tesbît kir. Gelo tu dixwazî saz bikî? + %1$s dosiyên sazkirinê peyda bûn! + Rêveberê peydabûna hemû ew dosiyên pêwîst ên ji bo sazkirina %1$s tesbît kir. Gelo tu dixwazî saz bikî? %1$s sazkariyên bijarde yên sazkirinê - Hildem tên kontrolkirin... + Hildem tên kontrolkirin... Ziman(ên):%1$s Rûkar: %1$s Guherto: %1$s - Çewtî - Rêzan - Rawestîne! + Çewtî + Rêzan + Rawestîne! Hûn niha guhertoya Magisk/TWRP ji Vanced\'ê bi kar tînin, ku qut bûye û bi saya vê sepanê naye hildemandin. Jkx magsik module/bi alîkariya TWRP Vanced uninstaller\'ê rakin. - Ji bo ku Vanced were sazkirin, DIVÊ hûn Optimîzasyonên MIUI-yê di sazkariyên pêşvebirinê de neçalak bikin. (Hûn dikarin vê hişyariyê paşguh bikin heke hûn ROM\'a li ser esasa xiaomi.eu 20.2.20 an jortir bi kar tînin) - MIUI Optimizations are enabled! - Please do NOT exit the app during this process! - Ji nû ve daxîne - Piştrast bin ku we sepan ji vancedapp.com\'ê, ji servera Vanced Discord\'ê an Vanced GitHub\'ê daxistiye + Ji bo ku Vanced were sazkirin, DIVÊ hûn Optimîzasyonên MIUI-yê di sazkariyên pêşvebirinê de neçalak bikin. (Hûn dikarin vê hişyariyê paşguh bikin heke hûn ROM\'a li ser esasa xiaomi.eu 20.2.20 an jortir bi kar tînin) + MIUI Optimizations are enabled! + Please do NOT exit the app during this process! + Ji nû ve daxîne + Piştrast bin ku we sepan ji vancedapp.com\'ê, ji servera Vanced Discord\'ê an Vanced GitHub\'ê daxistiye Guherto - Bi xêr hatî + Bi xêr hatî - Ziman(ên) xwe yën dilxwaz ji bo Vanced\'ê hilbijêre - Dawîn + Ziman(ên) xwe yën dilxwaz ji bo Vanced\'ê hilbijêre + Dawîn Ronak + %1$s Herî kêm zimanekê hilbijêre! - Reş - Tarî + Reş + Tarî - Pêşvebirên rêveberê - Other Contributors - Çavkanî - Koma Vanced\'ê + Pêşvebirên rêveberê + Other Contributors + Çavkanî + Koma Vanced\'ê - \'Chown\' apk ji xwediyê sîstemê re bi ser neket, jkx dîsa biceribîne. - Çewtiya daxistinê %1$s + \'Chown\' apk ji xwediyê sîstemê re bi ser neket, jkx dîsa biceribîne. + Çewtiya daxistinê %1$s Failed to apply new accent color - Rakirina pakêta %1$s bi ser neket - Dozîna dosiyên pêwîst ji bo sazkirinê bi ser neket. Dosiyên sazkirinê dîsa daxîne, paşê dubare biceribîne. - Dozîna dosiya apk ji bo rûkara reş/tarî ji bîrgehê bi ser neket, jkx dîsa biceribîne. - Sazkirin bi ser neket ji ber ku bikarîner dawî li pêvajoya sazkirinê anî. - Sazkirin bi ser neket ji ber ku ev bernameya ligel bernameyeke din ya sazkirî li hev nake. Guhertoya heyî ya Vanced\'ê rakin, paşê dîsa biceribînin. - Sazkirin bi ser neket ji ber ku bikarîner hewl dida derecebendiya pakêtê kêm bike. Hildeman ji bernameya YouTube\'ê ya heyî rakin, paşê dîsa biceribînin. - Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu - Sazkirin bi ser neket ji ber ku dosiya sazkirinê ligel cîhaza te hevaheng nîne. Dosiyên daxistî ji sazkariyan paqij bike, paşê dîsa biceribîne. - Sazkirin bi ser neket ji ber ku dosiyên apk\'ayê xirab in, jkx dîsa biceribîne. - Sazkirin bi ser neket ji ber ku MIUI Optimization çalak e. MIUI Optimization\'ê neçalak bikin, paşê dîsa biceribînin. - Sazkirin bi ser neket ji ber ku rastandina îmzeya apk\'ayê çalak e. Rastandina îmzeya apk\'ayê neçalak bikin, paşê dîsa biceribînin. - Installation failed because the device doesn\'t have enough free space. - Dozîna dosiya apk ji bo rûkara reş/tarî ji sazkirinê bi ser neket. Daneyên sepanê ji rêveberê paqij bikin, paşê dîsa biceribîne. - Piştî sazkirina dabeşkirî, dozîna rêka sazkirina YouTube stokê bi ser neket. + Rakirina pakêta %1$s bi ser neket + Dozîna dosiyên pêwîst ji bo sazkirinê bi ser neket. Dosiyên sazkirinê dîsa daxîne, paşê dubare biceribîne. + Dozîna dosiya apk ji bo rûkara reş/tarî ji bîrgehê bi ser neket, jkx dîsa biceribîne. + Sazkirin bi ser neket ji ber ku bikarîner dawî li pêvajoya sazkirinê anî. + Sazkirin bi ser neket ji ber ku ev bernameya ligel bernameyeke din ya sazkirî li hev nake. Guhertoya heyî ya Vanced\'ê rakin, paşê dîsa biceribînin. + Sazkirin bi ser neket ji ber ku bikarîner hewl dida derecebendiya pakêtê kêm bike. Hildeman ji bernameya YouTube\'ê ya heyî rakin, paşê dîsa biceribînin. + Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu + Sazkirin bi ser neket ji ber ku dosiya sazkirinê ligel cîhaza te hevaheng nîne. Dosiyên daxistî ji sazkariyan paqij bike, paşê dîsa biceribîne. + Sazkirin bi ser neket ji ber ku dosiyên apk\'ayê xirab in, jkx dîsa biceribîne. + Sazkirin bi ser neket ji ber ku MIUI Optimization çalak e. MIUI Optimization\'ê neçalak bikin, paşê dîsa biceribînin. + Sazkirin bi ser neket ji ber ku rastandina îmzeya apk\'ayê çalak e. Rastandina îmzeya apk\'ayê neçalak bikin, paşê dîsa biceribînin. + Installation failed because the device doesn\'t have enough free space. + Dozîna dosiya apk ji bo rûkara reş/tarî ji sazkirinê bi ser neket. Daneyên sepanê ji rêveberê paqij bikin, paşê dîsa biceribîne. + Piştî sazkirina dabeşkirî, dozîna rêka sazkirina YouTube stokê bi ser neket. diff --git a/app/src/main/res/values-lt-rLT/strings.xml b/app/src/main/res/values-lt-rLT/strings.xml index e5224e8f09..212dc55ef4 100644 --- a/app/src/main/res/values-lt-rLT/strings.xml +++ b/app/src/main/res/values-lt-rLT/strings.xml @@ -1,120 +1,120 @@ - Cancel - Close - A custom GMS Implementation for Vanced based on the microG Project. - A modified YouTube client with many useful features! - Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. - Reset - Save - Select Your Apps + Cancel + Close + A custom GMS Implementation for Vanced based on the microG Project. + A modified YouTube client with many useful features! + Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. + Reset + Save + Select Your Apps - About - Guide - Manager - Logs - Settings - Update Manager + About + Guide + Manager + Logs + Settings + Update Manager - Is Your Device Rooted? - Grant Root Permission - Let\'s get started - Select at least one app! - Don\'t know what this is or don\'t want to use the root version? just click the blue arrow below! + Is Your Device Rooted? + Grant Root Permission + Let\'s get started + Select at least one app! + Don\'t know what this is or don\'t want to use the root version? just click the blue arrow below! - About %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - Apps - Changelog - Downloading %1$s - Install + About %1$s + Download + Info + Launch + Reinstall + Uninstall + Update + Apps + Changelog + Downloading %1$s + Install Latest: - Install Vanced microG first + Install Vanced microG first Root access not granted - Social Media - Support us - Unavailable + Social Media + Support us + Unavailable Installed: - Accent Color - Appearance - Behavior - Clear downloaded files - Successfully cleared files - This lets us collect information about app performance and crash logs - Firebase Analytics - Language - Links will open in Chrome Custom Tabs - Use Chrome Custom Tabs - %1$s Push Notifications - Receive push notifications when an update for %1$s is released - Failed to save new time value - Root Script Sleep Time - Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues - System Default - Theme - Dark Theme - Light Theme - Manager Update Center - No new updates - Variant + Accent Color + Appearance + Behavior + Clear downloaded files + Successfully cleared files + This lets us collect information about app performance and crash logs + Firebase Analytics + Language + Links will open in Chrome Custom Tabs + Use Chrome Custom Tabs + %1$s Push Notifications + Receive push notifications when an update for %1$s is released + Failed to save new time value + Root Script Sleep Time + Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues + System Default + Theme + Dark Theme + Light Theme + Manager Update Center + No new updates + Variant - Could not save logs - Successfully saved logs + Could not save logs + Successfully saved logs Details - %1$s installation files detected! - Manager detected that all necessary files for %1$s installation were found. Do you want to install it? + %1$s installation files detected! + Manager detected that all necessary files for %1$s installation were found. Do you want to install it? %1$s Installation Preferences - Checking for updates… + Checking for updates… Language(s): %1$s Theme: %1$s Version: %1$s - Error - Guide - Stop! + Error + Guide + Stop! You are using the Magisk/TWRP version of Vanced, which is discontinued and cannot be updated using this app. Please remove it by removing the Magisk module/using TWRP Vanced uninstaller. - To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) - MIUI Optimizations are enabled! - Please do NOT exit the app during this process! - Redownload - Make sure that you downloaded the app from vancedapp.com, the Vanced Discord server, or the Vanced GitHub + To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) + MIUI Optimizations are enabled! + Please do NOT exit the app during this process! + Redownload + Make sure that you downloaded the app from vancedapp.com, the Vanced Discord server, or the Vanced GitHub Version - Welcome + Welcome - Choose your preferred language(s) for Vanced - Latest + Choose your preferred language(s) for Vanced + Latest Light + %1$s Select at least one language! - Black - Dark + Black + Dark - Manager Devs - Other Contributors - Sources - Vanced Team + Manager Devs + Other Contributors + Sources + Vanced Team - Failed to `chown` APK to system owner, please try again. - Error Downloading %1$s + Failed to `chown` APK to system owner, please try again. + Error Downloading %1$s Failed to apply new accent color - Failed to uninstall package %1$s - Failed to locate the required files for installation. Re-download the installation files, then try again. - Failed to locate apk file for black/dark theme from storage, please try again. - Installation failed because the user aborted the installation. - Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. - Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. - Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu - Installation failed because the installation file is incompatible with your device. Clear downloaded files in the Settings, then try again. - Installation failed because the apk files are corrupted, please try again. - Installation failed because MIUI Optimization is enabled. Disable MIUI Optimization, then try again. - Installation failed because apk signature verification is enabled. Disable apk signature verification, then try again. - Installation failed because the device doesn\'t have enough free space. - Failed to find apk file for black/dark theme from the installer. Clear app data of Manager, then try again. - Failed to locate the stock YouTube installation path after split installation. + Failed to uninstall package %1$s + Failed to locate the required files for installation. Re-download the installation files, then try again. + Failed to locate apk file for black/dark theme from storage, please try again. + Installation failed because the user aborted the installation. + Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. + Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. + Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu + Installation failed because the installation file is incompatible with your device. Clear downloaded files in the Settings, then try again. + Installation failed because the apk files are corrupted, please try again. + Installation failed because MIUI Optimization is enabled. Disable MIUI Optimization, then try again. + Installation failed because apk signature verification is enabled. Disable apk signature verification, then try again. + Installation failed because the device doesn\'t have enough free space. + Failed to find apk file for black/dark theme from the installer. Clear app data of Manager, then try again. + Failed to locate the stock YouTube installation path after split installation. diff --git a/app/src/main/res/values-ml-rIN/strings.xml b/app/src/main/res/values-ml-rIN/strings.xml index d6f1d2f638..79dd22d7c8 100644 --- a/app/src/main/res/values-ml-rIN/strings.xml +++ b/app/src/main/res/values-ml-rIN/strings.xml @@ -1,120 +1,120 @@ - റദ്ദാക്കുക - അടക്കുക - മൈക്രോ ജി പ്രോജക്റ്റിനെ അടിസ്ഥാനമാക്കി വാൻസിനായി ഒരു ഇഷ്‌ടാനുസൃത ജിഎംഎസ് നടപ്പിലാക്കൽ. - ഉപയോഗപ്രദമായ നിരവധി സവിശേഷതകളുള്ള ഒരു പരിഷ്‌ക്കരിച്ച YouTube ക്ലയന്റ്! - വിജയിച്ചു, പക്ഷേ YouTube സംഗീതത്തിനായി! താരതമ്യേന സവിശേഷത കുറവാണെങ്കിലും നിങ്ങളുടെ ആവശ്യങ്ങൾ നിറവേറ്റുന്നു. - പുനഃക്രമീകരിക്കുക - സൂക്ഷിക്കുക - നിങ്ങളുടെ അപ്ലിക്കേഷനുകൾ തിരഞ്ഞെടുക്കുക + റദ്ദാക്കുക + അടക്കുക + മൈക്രോ ജി പ്രോജക്റ്റിനെ അടിസ്ഥാനമാക്കി വാൻസിനായി ഒരു ഇഷ്‌ടാനുസൃത ജിഎംഎസ് നടപ്പിലാക്കൽ. + ഉപയോഗപ്രദമായ നിരവധി സവിശേഷതകളുള്ള ഒരു പരിഷ്‌ക്കരിച്ച YouTube ക്ലയന്റ്! + വിജയിച്ചു, പക്ഷേ YouTube സംഗീതത്തിനായി! താരതമ്യേന സവിശേഷത കുറവാണെങ്കിലും നിങ്ങളുടെ ആവശ്യങ്ങൾ നിറവേറ്റുന്നു. + പുനഃക്രമീകരിക്കുക + സൂക്ഷിക്കുക + നിങ്ങളുടെ അപ്ലിക്കേഷനുകൾ തിരഞ്ഞെടുക്കുക - കുറിച്ച് - മാർഗരേഖ - മാനേജർ - ലോഗുകൾ - ക്രമീകരണങ്ങൾ - മാനേജർ പുതുക്കുക + കുറിച്ച് + മാർഗരേഖ + മാനേജർ + ലോഗുകൾ + ക്രമീകരണങ്ങൾ + മാനേജർ പുതുക്കുക - നിങ്ങളുടെ ഉപകരണം റൂട്ടു ചെയ്തതാണോ? - റൂട്ട് അനുമതി നൽകുക - നമുക്ക് തുടങ്ങാം - ഒരു അപ്ലിക്കേഷനെങ്കിലും തിരഞ്ഞെടുക്കുക! - ഇത് എന്താണെന്ന് അറിയില്ല അല്ലെങ്കിൽ റൂട്ട് പതിപ്പ് ഉപയോഗിക്കാൻ ആഗ്രഹിക്കുന്നില്ലേ? ചുവടെയുള്ള നീല അമ്പടയാളത്തിൽ ക്ലിക്കുചെയ്യുക! + നിങ്ങളുടെ ഉപകരണം റൂട്ടു ചെയ്തതാണോ? + റൂട്ട് അനുമതി നൽകുക + നമുക്ക് തുടങ്ങാം + ഒരു അപ്ലിക്കേഷനെങ്കിലും തിരഞ്ഞെടുക്കുക! + ഇത് എന്താണെന്ന് അറിയില്ല അല്ലെങ്കിൽ റൂട്ട് പതിപ്പ് ഉപയോഗിക്കാൻ ആഗ്രഹിക്കുന്നില്ലേ? ചുവടെയുള്ള നീല അമ്പടയാളത്തിൽ ക്ലിക്കുചെയ്യുക! - ഏകദേശം %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - അപ്ലിക്കേഷനുകൾ - ചേഞ്ച് ലോഗ് - %1$s ഡൗൺലോഡ് ചെയ്യുന്നു - ഇൻസ്റ്റാൾ ചെയ്യുക + ഏകദേശം %1$s + Download + Info + Launch + Reinstall + Uninstall + Update + അപ്ലിക്കേഷനുകൾ + ചേഞ്ച് ലോഗ് + %1$s ഡൗൺലോഡ് ചെയ്യുന്നു + ഇൻസ്റ്റാൾ ചെയ്യുക ഏറ്റവും പുതിയത്: - ആധ്യം വാൻസ്ഡ് മൈക്രോ-ജി ഇൻസ്റ്റാൾ ചെയ്യുക്ക + ആധ്യം വാൻസ്ഡ് മൈക്രോ-ജി ഇൻസ്റ്റാൾ ചെയ്യുക്ക റൂട്ട് ആക്സസ് അനുവദിച്ചിട്ടില്ല - സോഷ്യൽ മീഡിയ - ഞങ്ങളെ പിന്തുണയ്ക്കുക - ലഭ്യമല്ല + സോഷ്യൽ മീഡിയ + ഞങ്ങളെ പിന്തുണയ്ക്കുക + ലഭ്യമല്ല ഇൻസ്റ്റാൾ ചെയ്തു: - ആക്‌സന്റ് വർണ്ണം - രൂപം - പെരുമാറ്റം - ഡൗൺലോഡുചെയ്‌ത ഫയലുകൾ മായ്‌ക്കുക - ഫയലുകൾ വിജയകരമായി മായ്ച്ചു - അപ്ലിക്കേഷൻ പ്രകടനത്തെയും ക്രാഷ് ലോഗുകളെയും കുറിച്ചുള്ള വിവരങ്ങൾ ശേഖരിക്കാൻ ഇത് ഞങ്ങളെ അനുവദിക്കുന്നു - ഫയർബേസ് അനലിറ്റിക്സ് - ഭാഷ - Chrome Custom ടാബുകളിൽ ലിങ്കുകൾ തുറക്കും - Chrome Custom ടാബുകൾ ഉപയോഗിക്കുക - %1$s പുഷ് അറിയിപ്പുകൾ - %1$s ഒരു അപ്‌ഡേറ്റ് പുറത്തിറങ്ങുമ്പോൾ പുഷ് അറിയിപ്പുകൾ സ്വീകരിക്കുക - പുതിയ സമയ മൂല്യം സംരക്ഷിക്കുന്നതിൽ പരാജയപ്പെട്ടു - റൂട്ട് സ്ക്രിപ്റ്റ് ഉറക്ക സമയം - മ d ണ്ടിംഗ് പ്രശ്നങ്ങൾ പരിഹരിക്കുന്നതിന് ഉപയോഗപ്രദമായ /data/adb/service.d/app.sh സ്ക്രിപ്റ്റിൽ ഉപയോഗിച്ചിരിക്കുന്ന ഉറക്ക സമയ മൂല്യം ക്രമീകരിക്കുക - സിസ്റ്റം സ്ഥിരസ്ഥിതി - തീം - ഡാർക്ക് തീം - ലൈറ്റ് തീം - മാനേജർ അപ്‌ഡേറ്റ് സെന്റർ - പുതിയ അപ്‌ഡേറ്റുകളൊന്നുമില്ല - വേരിയൻറ് + ആക്‌സന്റ് വർണ്ണം + രൂപം + പെരുമാറ്റം + ഡൗൺലോഡുചെയ്‌ത ഫയലുകൾ മായ്‌ക്കുക + ഫയലുകൾ വിജയകരമായി മായ്ച്ചു + അപ്ലിക്കേഷൻ പ്രകടനത്തെയും ക്രാഷ് ലോഗുകളെയും കുറിച്ചുള്ള വിവരങ്ങൾ ശേഖരിക്കാൻ ഇത് ഞങ്ങളെ അനുവദിക്കുന്നു + ഫയർബേസ് അനലിറ്റിക്സ് + ഭാഷ + Chrome Custom ടാബുകളിൽ ലിങ്കുകൾ തുറക്കും + Chrome Custom ടാബുകൾ ഉപയോഗിക്കുക + %1$s പുഷ് അറിയിപ്പുകൾ + %1$s ഒരു അപ്‌ഡേറ്റ് പുറത്തിറങ്ങുമ്പോൾ പുഷ് അറിയിപ്പുകൾ സ്വീകരിക്കുക + പുതിയ സമയ മൂല്യം സംരക്ഷിക്കുന്നതിൽ പരാജയപ്പെട്ടു + റൂട്ട് സ്ക്രിപ്റ്റ് ഉറക്ക സമയം + മ d ണ്ടിംഗ് പ്രശ്നങ്ങൾ പരിഹരിക്കുന്നതിന് ഉപയോഗപ്രദമായ /data/adb/service.d/app.sh സ്ക്രിപ്റ്റിൽ ഉപയോഗിച്ചിരിക്കുന്ന ഉറക്ക സമയ മൂല്യം ക്രമീകരിക്കുക + സിസ്റ്റം സ്ഥിരസ്ഥിതി + തീം + ഡാർക്ക് തീം + ലൈറ്റ് തീം + മാനേജർ അപ്‌ഡേറ്റ് സെന്റർ + പുതിയ അപ്‌ഡേറ്റുകളൊന്നുമില്ല + വേരിയൻറ് - ലോഗുകൾ സംരക്ഷിക്കാനായില്ല - ലോഗുകൾ വിജയകരമായി സംരക്ഷിച്ചു + ലോഗുകൾ സംരക്ഷിക്കാനായില്ല + ലോഗുകൾ വിജയകരമായി സംരക്ഷിച്ചു വിശദാംശങ്ങൾ - %1$s ഇൻസ്റ്റാളേഷൻ ഫയലുകൾ കണ്ടെത്തി! - %1$s ഇൻസ്റ്റാളേഷന് ആവശ്യമായ എല്ലാ ഫയലുകൾ മാനേജർ കണ്ടെത്തി. ഇത് ഇൻസ്റ്റാൾ ചെയ്യാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ? + %1$s ഇൻസ്റ്റാളേഷൻ ഫയലുകൾ കണ്ടെത്തി! + %1$s ഇൻസ്റ്റാളേഷന് ആവശ്യമായ എല്ലാ ഫയലുകൾ മാനേജർ കണ്ടെത്തി. ഇത് ഇൻസ്റ്റാൾ ചെയ്യാൻ നിങ്ങൾ ആഗ്രഹിക്കുന്നുണ്ടോ? %1$s ഇൻസ്റ്റാളേഷൻ മുൻഗണനകൾ - അപ്‌ഡേറ്റുകൾക്കായി പരിശോധിക്കുന്നു… + അപ്‌ഡേറ്റുകൾക്കായി പരിശോധിക്കുന്നു… ഭാഷ(കൾ):%1$s തീം: %1$s പതിപ്പ്:%1$s - തെറ്റ് - മാർഗരേഖ - നിർത്തുക! + തെറ്റ് + മാർഗരേഖ + നിർത്തുക! നിങ്ങൾ വാൻ‌സെഡിന്റെ മാജിസ്ക് / ടി‌ഡബ്ല്യുആർ‌പി പതിപ്പ് ഉപയോഗിക്കുന്നു, അത് നിർത്തലാക്കുകയും ഈ അപ്ലിക്കേഷൻ ഉപയോഗിച്ച് അപ്‌ഡേറ്റ് ചെയ്യാൻ കഴിയില്ല. മാജിസ്ക് മൊഡ്യൂൾ നീക്കംചെയ്ത് / ടി‌ഡബ്ല്യുആർ‌പി വാൻ‌സ്ഡ് അൺ‌ഇൻ‌സ്റ്റാളർ ഉപയോഗിച്ച് ഇത് നീക്കംചെയ്യുക. - വാൻ‌സ്ഡ് ഇൻ‌സ്റ്റാൾ‌ ചെയ്യുന്നതിന്, ഡവലപ്പർ‌ ക്രമീകരണങ്ങളിൽ‌ നിങ്ങൾ‌ MIUI ഒപ്റ്റിമൈസേഷനുകൾ‌ അപ്രാപ്‌തമാക്കണം. (നിങ്ങൾ 20.2.20 അല്ലെങ്കിൽ അതിനുശേഷമുള്ള xiaomi.eu അടിസ്ഥാനമാക്കിയുള്ള റോം ഉപയോഗിക്കുകയാണെങ്കിൽ നിങ്ങൾക്ക് ഈ മുന്നറിയിപ്പ് അവഗണിക്കാം) - MIUI ഒപ്റ്റിമൈസേഷനുകൾ പ്രാപ്തമാക്കി! - പ്രോസസ്സ് സമയത്ത് അപ്ലിക്കേഷനിൽ നിന്ന് പുറത്തുകടക്കരുത്! - വീണ്ടും ഡൗൺലോഡുചെയ്യുക - നിങ്ങൾ vancedapp.com, Vanced Discord സെർവർ, അല്ലെങ്കിൽ Vanced GitHub എന്നിവയിൽ നിന്ന് അപ്ലിക്കേഷൻ download ൺലോഡ് ചെയ്തുവെന്ന് ഉറപ്പാക്കുക + വാൻ‌സ്ഡ് ഇൻ‌സ്റ്റാൾ‌ ചെയ്യുന്നതിന്, ഡവലപ്പർ‌ ക്രമീകരണങ്ങളിൽ‌ നിങ്ങൾ‌ MIUI ഒപ്റ്റിമൈസേഷനുകൾ‌ അപ്രാപ്‌തമാക്കണം. (നിങ്ങൾ 20.2.20 അല്ലെങ്കിൽ അതിനുശേഷമുള്ള xiaomi.eu അടിസ്ഥാനമാക്കിയുള്ള റോം ഉപയോഗിക്കുകയാണെങ്കിൽ നിങ്ങൾക്ക് ഈ മുന്നറിയിപ്പ് അവഗണിക്കാം) + MIUI ഒപ്റ്റിമൈസേഷനുകൾ പ്രാപ്തമാക്കി! + പ്രോസസ്സ് സമയത്ത് അപ്ലിക്കേഷനിൽ നിന്ന് പുറത്തുകടക്കരുത്! + വീണ്ടും ഡൗൺലോഡുചെയ്യുക + നിങ്ങൾ vancedapp.com, Vanced Discord സെർവർ, അല്ലെങ്കിൽ Vanced GitHub എന്നിവയിൽ നിന്ന് അപ്ലിക്കേഷൻ download ൺലോഡ് ചെയ്തുവെന്ന് ഉറപ്പാക്കുക പതിപ്പ് - സ്വാഗതം + സ്വാഗതം - വാൻസിനായി നിങ്ങൾ ഭാഷ (കൾ) തിരഞ്ഞെടുക്കുക - ഏറ്റവും പുതിയ + വാൻസിനായി നിങ്ങൾ ഭാഷ (കൾ) തിരഞ്ഞെടുക്കുക + ഏറ്റവും പുതിയ പ്രകാശം +%1$s ഒരു ഭാഷയെങ്കിലും തിരഞ്ഞെടുക്കുക! - കറുപ്പ് - ഇരുണ്ടത് + കറുപ്പ് + ഇരുണ്ടത് - മാനേജർ ഡവലപ്പർമാർ - മറ്റ് സംഭാവകർ - ഉറവിടങ്ങൾ - വാൻ‌സ്ഡ് ടീം + മാനേജർ ഡവലപ്പർമാർ + മറ്റ് സംഭാവകർ + ഉറവിടങ്ങൾ + വാൻ‌സ്ഡ് ടീം - സിസ്റ്റം ഉടമയ്‌ക്ക് APK `chown` ചെയ്യുന്നതിൽ പരാജയപ്പെട്ടു, ദയവായി വീണ്ടും ശ്രമിക്കുക. - %1$s ഡൗൺലോഡുചെയ്യുന്നതിൽ പിശക് + സിസ്റ്റം ഉടമയ്‌ക്ക് APK `chown` ചെയ്യുന്നതിൽ പരാജയപ്പെട്ടു, ദയവായി വീണ്ടും ശ്രമിക്കുക. + %1$s ഡൗൺലോഡുചെയ്യുന്നതിൽ പിശക് പുതിയ ആക്‌സന്റ് വർണ്ണം പ്രയോഗിക്കുന്നതിൽ പരാജയപ്പെട്ടു - %1$s package അൺ‌ഇൻസ്റ്റാൾ ചെയ്യുന്നതിൽ പരാജയപ്പെട്ടു - ഇൻസ്റ്റാളേഷന് ആവശ്യമായ ഫയലുകൾ കണ്ടെത്തുന്നതിൽ പരാജയപ്പെട്ടു. ഇൻസ്റ്റാളേഷൻ ഫയലുകൾ വീണ്ടും ഡ download ൺലോഡ് ചെയ്യുക, തുടർന്ന് വീണ്ടും ശ്രമിക്കുക. - സംഭരണത്തിൽ നിന്ന് കറുപ്പ് / ഇരുണ്ട തീമിനായി Apk ഫയൽ കണ്ടെത്തുന്നതിൽ പരാജയപ്പെട്ടു, ദയവായി വീണ്ടും ശ്രമിക്കുക. - ഉപയോക്താവ് ഇൻസ്റ്റാളേഷൻ നിർത്തലാക്കിയതിനാൽ ഇൻസ്റ്റാളേഷൻ പരാജയപ്പെട്ടു. - ഇതിനകം ഇൻസ്റ്റാളുചെയ്‌ത അപ്ലിക്കേഷനുമായി അപ്ലിക്കേഷൻ പൊരുത്തപ്പെടുന്നതിനാൽ ഇൻസ്റ്റാളേഷൻ പരാജയപ്പെട്ടു. അപ്ലിക്കേഷന്റെ നിലവിലെ പതിപ്പ് അൺ‌ഇൻസ്റ്റാൾ ചെയ്യുക, തുടർന്ന് വീണ്ടും ശ്രമിക്കുക. - ഉപയോക്താവ് പാക്കേജ് തരംതാഴ്ത്താൻ ശ്രമിച്ചതിനാൽ ഇൻസ്റ്റാളേഷൻ പരാജയപ്പെട്ടു. സ്റ്റോക്ക് അപ്ലിക്കേഷനിൽ നിന്ന് അപ്‌ഡേറ്റുകൾ അൺഇൻസ്റ്റാൾ ചെയ്യുക, തുടർന്ന് വീണ്ടും ശ്രമിക്കുക. - അജ്ഞാതമായ കാരണങ്ങളാൽ ഇൻസ്റ്റാളേഷൻ പരാജയപ്പെട്ടു, കൂടുതൽ പിന്തുണയ്ക്കായി ഞങ്ങളുടെ ടെലിഗ്രാം അല്ലെങ്കിൽ ഡിസ്കോർഡിൽ ചേരുക. വിപുലമായ മെനുവിൽ നിന്ന് ഒരു സ്ക്രീൻഷോട്ട് അറ്റാച്ചുചെയ്യുക - ഇൻസ്റ്റാളേഷൻ ഫയൽ നിങ്ങളുടെ ഉപകരണവുമായി പൊരുത്തപ്പെടാത്തതിനാൽ ഇൻസ്റ്റാളേഷൻ പരാജയപ്പെട്ടു. ക്രമീകരണങ്ങളിൽ ഡ download ൺലോഡ് ചെയ്ത ഫയലുകൾ മായ്‌ക്കുക, തുടർന്ന് വീണ്ടും ശ്രമിക്കുക. - Apk ഫയലുകൾ‌ കേടായതിനാൽ‌ ഇൻ‌സ്റ്റാളേഷൻ‌ പരാജയപ്പെട്ടു, ദയവായി വീണ്ടും ശ്രമിക്കുക. - MIUI ഒപ്റ്റിമൈസേഷൻ പ്രാപ്തമാക്കിയതിനാൽ ഇൻസ്റ്റാളേഷൻ പരാജയപ്പെട്ടു. MIUI ഒപ്റ്റിമൈസേഷൻ അപ്രാപ്തമാക്കുക, തുടർന്ന് വീണ്ടും ശ്രമിക്കുക. - Apk സിഗ്നേച്ചർ പരിശോധന പ്രാപ്തമാക്കിയതിനാൽ ഇൻസ്റ്റാളേഷൻ പരാജയപ്പെട്ടു. Apk സിഗ്നേച്ചർ പരിശോധന അപ്രാപ്തമാക്കുക, തുടർന്ന് വീണ്ടും ശ്രമിക്കുക. - ഉപകരണത്തിന് മതിയായ ഇടമില്ലാത്തതിനാൽ ഇൻസ്റ്റാളേഷൻ പരാജയപ്പെട്ടു. - ഇൻസ്റ്റാളറിൽ നിന്ന് കറുപ്പ് / ഇരുണ്ട തീമിനായി Apk ഫയൽ കണ്ടെത്തുന്നതിൽ പരാജയപ്പെട്ടു. മാനേജറിന്റെ അപ്ലിക്കേഷൻ ഡാറ്റ മായ്‌ക്കുക, തുടർന്ന് വീണ്ടും ശ്രമിക്കുക. - വിഭജന ഇൻസ്റ്റാളേഷന് ശേഷം സ്റ്റോക്ക് YouTube ഇൻസ്റ്റാളേഷൻ പാത്ത് കണ്ടെത്തുന്നതിൽ പരാജയപ്പെട്ടു. + %1$s package അൺ‌ഇൻസ്റ്റാൾ ചെയ്യുന്നതിൽ പരാജയപ്പെട്ടു + ഇൻസ്റ്റാളേഷന് ആവശ്യമായ ഫയലുകൾ കണ്ടെത്തുന്നതിൽ പരാജയപ്പെട്ടു. ഇൻസ്റ്റാളേഷൻ ഫയലുകൾ വീണ്ടും ഡ download ൺലോഡ് ചെയ്യുക, തുടർന്ന് വീണ്ടും ശ്രമിക്കുക. + സംഭരണത്തിൽ നിന്ന് കറുപ്പ് / ഇരുണ്ട തീമിനായി Apk ഫയൽ കണ്ടെത്തുന്നതിൽ പരാജയപ്പെട്ടു, ദയവായി വീണ്ടും ശ്രമിക്കുക. + ഉപയോക്താവ് ഇൻസ്റ്റാളേഷൻ നിർത്തലാക്കിയതിനാൽ ഇൻസ്റ്റാളേഷൻ പരാജയപ്പെട്ടു. + ഇതിനകം ഇൻസ്റ്റാളുചെയ്‌ത അപ്ലിക്കേഷനുമായി അപ്ലിക്കേഷൻ പൊരുത്തപ്പെടുന്നതിനാൽ ഇൻസ്റ്റാളേഷൻ പരാജയപ്പെട്ടു. അപ്ലിക്കേഷന്റെ നിലവിലെ പതിപ്പ് അൺ‌ഇൻസ്റ്റാൾ ചെയ്യുക, തുടർന്ന് വീണ്ടും ശ്രമിക്കുക. + ഉപയോക്താവ് പാക്കേജ് തരംതാഴ്ത്താൻ ശ്രമിച്ചതിനാൽ ഇൻസ്റ്റാളേഷൻ പരാജയപ്പെട്ടു. സ്റ്റോക്ക് അപ്ലിക്കേഷനിൽ നിന്ന് അപ്‌ഡേറ്റുകൾ അൺഇൻസ്റ്റാൾ ചെയ്യുക, തുടർന്ന് വീണ്ടും ശ്രമിക്കുക. + അജ്ഞാതമായ കാരണങ്ങളാൽ ഇൻസ്റ്റാളേഷൻ പരാജയപ്പെട്ടു, കൂടുതൽ പിന്തുണയ്ക്കായി ഞങ്ങളുടെ ടെലിഗ്രാം അല്ലെങ്കിൽ ഡിസ്കോർഡിൽ ചേരുക. വിപുലമായ മെനുവിൽ നിന്ന് ഒരു സ്ക്രീൻഷോട്ട് അറ്റാച്ചുചെയ്യുക + ഇൻസ്റ്റാളേഷൻ ഫയൽ നിങ്ങളുടെ ഉപകരണവുമായി പൊരുത്തപ്പെടാത്തതിനാൽ ഇൻസ്റ്റാളേഷൻ പരാജയപ്പെട്ടു. ക്രമീകരണങ്ങളിൽ ഡ download ൺലോഡ് ചെയ്ത ഫയലുകൾ മായ്‌ക്കുക, തുടർന്ന് വീണ്ടും ശ്രമിക്കുക. + Apk ഫയലുകൾ‌ കേടായതിനാൽ‌ ഇൻ‌സ്റ്റാളേഷൻ‌ പരാജയപ്പെട്ടു, ദയവായി വീണ്ടും ശ്രമിക്കുക. + MIUI ഒപ്റ്റിമൈസേഷൻ പ്രാപ്തമാക്കിയതിനാൽ ഇൻസ്റ്റാളേഷൻ പരാജയപ്പെട്ടു. MIUI ഒപ്റ്റിമൈസേഷൻ അപ്രാപ്തമാക്കുക, തുടർന്ന് വീണ്ടും ശ്രമിക്കുക. + Apk സിഗ്നേച്ചർ പരിശോധന പ്രാപ്തമാക്കിയതിനാൽ ഇൻസ്റ്റാളേഷൻ പരാജയപ്പെട്ടു. Apk സിഗ്നേച്ചർ പരിശോധന അപ്രാപ്തമാക്കുക, തുടർന്ന് വീണ്ടും ശ്രമിക്കുക. + ഉപകരണത്തിന് മതിയായ ഇടമില്ലാത്തതിനാൽ ഇൻസ്റ്റാളേഷൻ പരാജയപ്പെട്ടു. + ഇൻസ്റ്റാളറിൽ നിന്ന് കറുപ്പ് / ഇരുണ്ട തീമിനായി Apk ഫയൽ കണ്ടെത്തുന്നതിൽ പരാജയപ്പെട്ടു. മാനേജറിന്റെ അപ്ലിക്കേഷൻ ഡാറ്റ മായ്‌ക്കുക, തുടർന്ന് വീണ്ടും ശ്രമിക്കുക. + വിഭജന ഇൻസ്റ്റാളേഷന് ശേഷം സ്റ്റോക്ക് YouTube ഇൻസ്റ്റാളേഷൻ പാത്ത് കണ്ടെത്തുന്നതിൽ പരാജയപ്പെട്ടു. diff --git a/app/src/main/res/values-mr-rIN/strings.xml b/app/src/main/res/values-mr-rIN/strings.xml index c23c4b428b..78ec99fed8 100644 --- a/app/src/main/res/values-mr-rIN/strings.xml +++ b/app/src/main/res/values-mr-rIN/strings.xml @@ -1,120 +1,120 @@ - रद्द करा - बंद करा - A custom GMS Implementation for Vanced based on the microG Project. - A modified YouTube client with many useful features! - Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. - रीसेट करा - सेव करा - आपले अप्प्स निवडा + रद्द करा + बंद करा + A custom GMS Implementation for Vanced based on the microG Project. + A modified YouTube client with many useful features! + Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. + रीसेट करा + सेव करा + आपले अप्प्स निवडा - अॅप बद्दल माहिती - Guide - मॅनेजर - Logs - सेटिंग - मॅनेजर ला अपडेट करा + अॅप बद्दल माहिती + Guide + मॅनेजर + Logs + सेटिंग + मॅनेजर ला अपडेट करा - आपला मोबाइल रूट आहे का? - रूट ची परवानगी द्या - Let\'s get started - कमीत कमी एक अॅप निवडा! - Don\'t know what this is or don\'t want to use the root version? just click the blue arrow below! + आपला मोबाइल रूट आहे का? + रूट ची परवानगी द्या + Let\'s get started + कमीत कमी एक अॅप निवडा! + Don\'t know what this is or don\'t want to use the root version? just click the blue arrow below! - About %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - Apps - Changelog - Downloading %1$s - Install + About %1$s + Download + Info + Launch + Reinstall + Uninstall + Update + Apps + Changelog + Downloading %1$s + Install Latest: - Install Vanced microG first + Install Vanced microG first Root access not granted - Social Media - Support us - Unavailable + Social Media + Support us + Unavailable Installed: - Accent Color - Appearance - Behavior - Clear downloaded files - Successfully cleared files - This lets us collect information about app performance and crash logs - Firebase Analytics - Language - Links will open in Chrome Custom Tabs - Use Chrome Custom Tabs - %1$s Push Notifications - Receive push notifications when an update for %1$s is released - Failed to save new time value - Root Script Sleep Time - Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues - System Default - Theme - Dark Theme - Light Theme - Manager Update Center - No new updates - Variant + Accent Color + Appearance + Behavior + Clear downloaded files + Successfully cleared files + This lets us collect information about app performance and crash logs + Firebase Analytics + Language + Links will open in Chrome Custom Tabs + Use Chrome Custom Tabs + %1$s Push Notifications + Receive push notifications when an update for %1$s is released + Failed to save new time value + Root Script Sleep Time + Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues + System Default + Theme + Dark Theme + Light Theme + Manager Update Center + No new updates + Variant - Could not save logs - Successfully saved logs + Could not save logs + Successfully saved logs Details - %1$s installation files detected! - Manager detected that all necessary files for %1$s installation were found. Do you want to install it? + %1$s installation files detected! + Manager detected that all necessary files for %1$s installation were found. Do you want to install it? %1$s Installation Preferences - Checking for updates… + Checking for updates… Language(s): %1$s Theme: %1$s Version: %1$s - Error - Guide - Stop! + Error + Guide + Stop! You are using the Magisk/TWRP version of Vanced, which is discontinued and cannot be updated using this app. Please remove it by removing the Magisk module/using TWRP Vanced uninstaller. - To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) - MIUI Optimizations are enabled! - Please do NOT exit the app during this process! - Redownload - Make sure that you downloaded the app from vancedapp.com, the Vanced Discord server, or the Vanced GitHub + To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) + MIUI Optimizations are enabled! + Please do NOT exit the app during this process! + Redownload + Make sure that you downloaded the app from vancedapp.com, the Vanced Discord server, or the Vanced GitHub Version - Welcome + Welcome - Choose your preferred language(s) for Vanced - Latest + Choose your preferred language(s) for Vanced + Latest Light + %1$s Select at least one language! - Black - Dark + Black + Dark - Manager Devs - Other Contributors - Sources - Vanced Team + Manager Devs + Other Contributors + Sources + Vanced Team - Failed to `chown` APK to system owner, please try again. - Error Downloading %1$s + Failed to `chown` APK to system owner, please try again. + Error Downloading %1$s Failed to apply new accent color - Failed to uninstall package %1$s - Failed to locate the required files for installation. Re-download the installation files, then try again. - Failed to locate apk file for black/dark theme from storage, please try again. - Installation failed because the user aborted the installation. - Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. - Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. - Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu - Installation failed because the installation file is incompatible with your device. Clear downloaded files in the Settings, then try again. - Installation failed because the apk files are corrupted, please try again. - Installation failed because MIUI Optimization is enabled. Disable MIUI Optimization, then try again. - Installation failed because apk signature verification is enabled. Disable apk signature verification, then try again. - Installation failed because the device doesn\'t have enough free space. - Failed to find apk file for black/dark theme from the installer. Clear app data of Manager, then try again. - Failed to locate the stock YouTube installation path after split installation. + Failed to uninstall package %1$s + Failed to locate the required files for installation. Re-download the installation files, then try again. + Failed to locate apk file for black/dark theme from storage, please try again. + Installation failed because the user aborted the installation. + Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. + Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. + Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu + Installation failed because the installation file is incompatible with your device. Clear downloaded files in the Settings, then try again. + Installation failed because the apk files are corrupted, please try again. + Installation failed because MIUI Optimization is enabled. Disable MIUI Optimization, then try again. + Installation failed because apk signature verification is enabled. Disable apk signature verification, then try again. + Installation failed because the device doesn\'t have enough free space. + Failed to find apk file for black/dark theme from the installer. Clear app data of Manager, then try again. + Failed to locate the stock YouTube installation path after split installation. diff --git a/app/src/main/res/values-nl-rNL/strings.xml b/app/src/main/res/values-nl-rNL/strings.xml index efce05584c..e0e0ea327d 100644 --- a/app/src/main/res/values-nl-rNL/strings.xml +++ b/app/src/main/res/values-nl-rNL/strings.xml @@ -1,120 +1,120 @@ - Annuleren - Sluiten - Een aangepaste GMS-implementatie voor Vanced gebaseerd op het microG-project. - Een aangepaste versie van YouTube met veel handige functies! - Vanced, maar voor YouTube Music!\nMinder functies maar voldoet aan al je wensen. - Herstellen - Bewaren - Apps selecteren + Annuleren + Sluiten + Een aangepaste GMS-implementatie voor Vanced gebaseerd op het microG-project. + Een aangepaste versie van YouTube met veel handige functies! + Vanced, maar voor YouTube Music!\nMinder functies maar voldoet aan al je wensen. + Herstellen + Bewaren + Apps selecteren - Over - Gids - Manager - Logs - Instellingen - Manager bijwerken + Over + Gids + Manager + Logs + Instellingen + Manager bijwerken - Is je apparaat geroot? - Root-machtiging toestaan - Aan de slag! - Selecteer minstens één app! - Weet je niet wat dit is of wil je de root-versie niet gebruiken? Klik dan op de blauwe pijl hieronder! + Is je apparaat geroot? + Root-machtiging toestaan + Aan de slag! + Selecteer minstens één app! + Weet je niet wat dit is of wil je de root-versie niet gebruiken? Klik dan op de blauwe pijl hieronder! - Over %1$s - Downloaden - Info - Starten - Herinstalleren - Verwijderen - Bijwerken - Apps - Wijzigingen - %1$s downloaden - Installeren + Over %1$s + Downloaden + Info + Starten + Herinstalleren + Verwijderen + Bijwerken + Apps + Wijzigingen + %1$s downloaden + Installeren Recentste: - Installeer eerst Vanced microG + Installeer eerst Vanced microG Root machtiging niet toegestaan - Sociale media - Steun ons - Niet beschikbaar + Sociale media + Steun ons + Niet beschikbaar Geïnstalleerd: - Accentkleur - Weergave - Gedrag - Gedownloade bestanden verwijderen - Bestanden succesvol verwijderd - Hiermee kunnen we informatie over app-prestaties en crashlogs verzamelen - Firebase-analytics - Taal - Links zullen openen in aangepaste Chrome-tabs - Aangepaste Chrome-tabs gebruiken - Pushmeldingen %1$s - Pushmeldingen ontvangen wanneer er een update voor %1$s beschikbaar is - Bewaren van nieuwe waarde voor slaaptimer mislukt - Slaaptimer root script - Aanpassen waarde voor slaaptimer gebruikt in /data/adb/service.d/app.sh script, nuttig bij mount-issues - Systeemstandaard - Thema - Donker thema - Licht thema - Manager bijwerken - Geen nieuwe updates - Versie + Accentkleur + Weergave + Gedrag + Gedownloade bestanden verwijderen + Bestanden succesvol verwijderd + Hiermee kunnen we informatie over app-prestaties en crashlogs verzamelen + Firebase-analytics + Taal + Links zullen openen in aangepaste Chrome-tabs + Aangepaste Chrome-tabs gebruiken + Pushmeldingen %1$s + Pushmeldingen ontvangen wanneer er een update voor %1$s beschikbaar is + Bewaren van nieuwe waarde voor slaaptimer mislukt + Slaaptimer root script + Aanpassen waarde voor slaaptimer gebruikt in /data/adb/service.d/app.sh script, nuttig bij mount-issues + Systeemstandaard + Thema + Donker thema + Licht thema + Manager bijwerken + Geen nieuwe updates + Versie - Logs niet opgeslagen - Logs succesvol opgeslagen + Logs niet opgeslagen + Logs succesvol opgeslagen Details - Installatiebestanden voor %1$s gedetecteerd! - Manager heeft alle nodige bestanden gedetecteerd voor het installeren van %1$s. Wil je ze installeren? + Installatiebestanden voor %1$s gedetecteerd! + Manager heeft alle nodige bestanden gedetecteerd voor het installeren van %1$s. Wil je ze installeren? Installatievoorkeuren voor %1$s - Controleren op updates… + Controleren op updates… Talen: %1$s Thema: %1$s Versie: %1$s - Fout - Handleiding - Stoppen! + Fout + Handleiding + Stoppen! Je gebruikt de Magisk/TWRP-versie van Vanced, die is stopgezet en niet met deze app kan worden bijgewerkt. Verwijder deze eerst door de Magisk-module te verwijderen of door de TWRP Vanced-uninstaller te gebruiken. - Om Vanced te installeren MOET je MIUI-optimalisaties uitschakelen in de ontwikkelaarsinstellingen (je kunt deze waarschuwing negeren als je de op xiaomi.eu gebaseerde ROM 20.2.20 of later gebruikt) - MIUI-optimalisaties zijn ingeschakeld! - Sluit de app NIET af tijdens dit proces! - Opnieuw downloaden - Zorg ervoor dat je de app hebt gedownload van vancedapp.com, de Vanced Discord-server of Vanced GitHub + Om Vanced te installeren MOET je MIUI-optimalisaties uitschakelen in de ontwikkelaarsinstellingen (je kunt deze waarschuwing negeren als je de op xiaomi.eu gebaseerde ROM 20.2.20 of later gebruikt) + MIUI-optimalisaties zijn ingeschakeld! + Sluit de app NIET af tijdens dit proces! + Opnieuw downloaden + Zorg ervoor dat je de app hebt gedownload van vancedapp.com, de Vanced Discord-server of Vanced GitHub Versie - Welkom + Welkom - Kies je gewenste taal/talen voor Vanced - Nieuwste versie + Kies je gewenste taal/talen voor Vanced + Nieuwste versie Licht + %1$s Selecteer minstens één taal! - Zwart - Donker + Zwart + Donker - Ontwikkelaars Manager - Andere bijdrages - Bronnen - Vanced Team + Ontwikkelaars Manager + Andere bijdrages + Bronnen + Vanced Team - Wijzigen van APK-eigenaar naar systeemeigenaar mislukt. Probeer het opnieuw. - Fout bij downloaden van %1$s + Wijzigen van APK-eigenaar naar systeemeigenaar mislukt. Probeer het opnieuw. + Fout bij downloaden van %1$s Nieuwe accentkleur toepassen mislukt - Deïnstalleren van pakket %1$s mislukt - Kan de vereiste bestanden voor de installatie niet vinden. Download de installatiebestanden opnieuw en probeer het opnieuw. - Kan het apk-bestand voor zwart/donker thema niet vinden in opslag. Probeer het opnieuw. - Installatie mislukt omdat de gebruiker de installatie heeft afgebroken. - Installatie mislukt omdat de app conflicten heeft met een reeds geïnstalleerde app. Verwijder de huidige versie van die app en probeer het opnieuw. - Installatie mislukt omdat de gebruiker het pakket probeerde te downgraden. Verwijder updates van de standaard app en probeer het daarna opnieuw. - Installatie is mislukt om onbekende redenen, ga naar Telegram of Discord voor verdere ondersteuning. Voeg een screenshot toe via het menu Geavanceerd. - Installatie mislukt omdat het installatiebestand niet compatibel is met jouw apparaat. Wis de gedownloade bestanden in de instellingen en probeer het opnieuw. - Installatie mislukt omdat de apk-bestanden beschadigd zijn. Probeer het opnieuw. - Installatie mislukt omdat MIUI-optimalisatie is ingeschakeld. Schakel MIUI-optimalisatie uit en probeer het opnieuw. - Installatie mislukt omdat apk-handtekeningverificatie is ingeschakeld. Schakel apk-handtekeningverificatie uit en probeer het opnieuw. - Installatie mislukt omdat het apparaat niet genoeg vrije ruimte heeft. - Kan het apk-bestand voor zwart/donker thema niet vinden in het installatiebestand. Verwijder de appdata van Vanced Manager en probeer het opnieuw. - Kan het standaard YouTube-installatiepad niet vinden na de gesplitste installatie. + Deïnstalleren van pakket %1$s mislukt + Kan de vereiste bestanden voor de installatie niet vinden. Download de installatiebestanden opnieuw en probeer het opnieuw. + Kan het apk-bestand voor zwart/donker thema niet vinden in opslag. Probeer het opnieuw. + Installatie mislukt omdat de gebruiker de installatie heeft afgebroken. + Installatie mislukt omdat de app conflicten heeft met een reeds geïnstalleerde app. Verwijder de huidige versie van die app en probeer het opnieuw. + Installatie mislukt omdat de gebruiker het pakket probeerde te downgraden. Verwijder updates van de standaard app en probeer het daarna opnieuw. + Installatie is mislukt om onbekende redenen, ga naar Telegram of Discord voor verdere ondersteuning. Voeg een screenshot toe via het menu Geavanceerd. + Installatie mislukt omdat het installatiebestand niet compatibel is met jouw apparaat. Wis de gedownloade bestanden in de instellingen en probeer het opnieuw. + Installatie mislukt omdat de apk-bestanden beschadigd zijn. Probeer het opnieuw. + Installatie mislukt omdat MIUI-optimalisatie is ingeschakeld. Schakel MIUI-optimalisatie uit en probeer het opnieuw. + Installatie mislukt omdat apk-handtekeningverificatie is ingeschakeld. Schakel apk-handtekeningverificatie uit en probeer het opnieuw. + Installatie mislukt omdat het apparaat niet genoeg vrije ruimte heeft. + Kan het apk-bestand voor zwart/donker thema niet vinden in het installatiebestand. Verwijder de appdata van Vanced Manager en probeer het opnieuw. + Kan het standaard YouTube-installatiepad niet vinden na de gesplitste installatie. diff --git a/app/src/main/res/values-no-rNO/strings.xml b/app/src/main/res/values-no-rNO/strings.xml index 1532d9a273..ba1df538fa 100644 --- a/app/src/main/res/values-no-rNO/strings.xml +++ b/app/src/main/res/values-no-rNO/strings.xml @@ -1,120 +1,120 @@ - Avbryt - Lukk - En tilpasset GMS-implementering for Vanced basert på microG-prosjektet. - En modifisert YouTube klient med mange nyttige funksjoner! - Vanced, med for YouTube Musikk! Relativt mindre funkjonsrik men dekker dine behov. - Tilbakestill - Lagre - Velg dine apper + Avbryt + Lukk + En tilpasset GMS-implementering for Vanced basert på microG-prosjektet. + En modifisert YouTube klient med mange nyttige funksjoner! + Vanced, med for YouTube Musikk! Relativt mindre funkjonsrik men dekker dine behov. + Tilbakestill + Lagre + Velg dine apper - Om - Guide - Leder - Logger - Innstillinger - Oppdater administrator + Om + Guide + Leder + Logger + Innstillinger + Oppdater administrator - Er enheten tilkoblet? - Gi root-tillatelse - La oss komme i gang - Velg minst en app! - Vet du ikke hva detter er eller ikke ønsker å bruke rot-versjonen? Bare klikk på den blå pilen nedenfor! + Er enheten tilkoblet? + Gi root-tillatelse + La oss komme i gang + Velg minst en app! + Vet du ikke hva detter er eller ikke ønsker å bruke rot-versjonen? Bare klikk på den blå pilen nedenfor! - Om %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - Apper - Endringslogg - Laster ned %1$s - Installer + Om %1$s + Download + Info + Launch + Reinstall + Uninstall + Update + Apper + Endringslogg + Laster ned %1$s + Installer Siste: - Installer Vanced microG først + Installer Vanced microG først Root-tilgang ikke godkjent - Sosiale Medier - Støtt oss - Utilgjengelig + Sosiale Medier + Støtt oss + Utilgjengelig Installert: - Aksentfarge - Utseende - Oppførsel - Fjern nedlastede filer - Valgte filer er fjernet - Dette lar oss samle informasjon om app-ytelse og krasj-logger - Firebase analyser - Språk - Lenker vil åpne i Chrome Custom Tabs - Bruk Chrome Custom Tabs - %1$s Push varsler - Motta push varsler når en oppdatering for %1$s er utgitt - Kan ikke lagre ny tidsverdi - Hviletid for Root skript - Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues - System standard - Tema - Mørkt tema - Lyst tema - Oppdateringssenter - Ingen nye oppdateringer - Variant + Aksentfarge + Utseende + Oppførsel + Fjern nedlastede filer + Valgte filer er fjernet + Dette lar oss samle informasjon om app-ytelse og krasj-logger + Firebase analyser + Språk + Lenker vil åpne i Chrome Custom Tabs + Bruk Chrome Custom Tabs + %1$s Push varsler + Motta push varsler når en oppdatering for %1$s er utgitt + Kan ikke lagre ny tidsverdi + Hviletid for Root skript + Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues + System standard + Tema + Mørkt tema + Lyst tema + Oppdateringssenter + Ingen nye oppdateringer + Variant - Could not save logs - Successfully saved logs + Could not save logs + Successfully saved logs Details - %1$s installasjonsfiler oppdaget! - Manager oppdaget at alle nødvendige filer for %1$s installasjonen ble funnet. Vil du installere den? + %1$s installasjonsfiler oppdaget! + Manager oppdaget at alle nødvendige filer for %1$s installasjonen ble funnet. Vil du installere den? %1$s Installasjonsinnstillinger - Sjekker etter oppdateringer… + Sjekker etter oppdateringer… Språk: %1$s Tema: %1$s Versjon: %1$s - Feil - Guide - Stopp! + Feil + Guide + Stopp! Du bruker Magisk/TWRP-versjonen av Vansert, som seponeres og som ikke kan oppdateres ved hjelp av denne appen. Vennligst fjern den ved å fjerne Magisk modul/bruke TWRP Vanced uninstaller. - To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) - MIUI Optimizations are enabled! - Please do NOT exit the app during this process! - Last ned på nytt - Sørg for at du lastet ned appen fra vancedapp.com, Vanced Discord server, eller Vanced GitHub + To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) + MIUI Optimizations are enabled! + Please do NOT exit the app during this process! + Last ned på nytt + Sørg for at du lastet ned appen fra vancedapp.com, Vanced Discord server, eller Vanced GitHub Versjon - Velkommen + Velkommen - Velg dine foretrukne språk for Vanced - Latest + Velg dine foretrukne språk for Vanced + Latest Lys + %1$s Velg minst ett språk! - Black - Dark + Black + Dark - Manager Devs - Other Contributors - Kilder - Vanced Team + Manager Devs + Other Contributors + Kilder + Vanced Team - Kan ikke `chown` APK til systemeieren, vennligst prøv igjen. - Feil ved nedlasting %1$s + Kan ikke `chown` APK til systemeieren, vennligst prøv igjen. + Feil ved nedlasting %1$s Failed to apply new accent color - Kunne ikke avinstallere pakken %1$s - Kunne ikke finne de nødvendige filene for installasjon. Last ned installasjonsfilene på nytt, og prøv på nytt. - Klarte ikke å finne apk-filen for svart/mørkt tema på enheten, vennligst prøv igjen. - Installasjonen mislyktes fordi brukeren avbrutt installasjonen. - Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. - Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. - Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu - Installasjonen mislyktes på grunn av at installasjonsfilen er inkompatibel med enheten. Fjern nedlastede filer i innstillinger og prøv på nytt. - Installasjonen mislyktes fordi apk-filene er ødelagt, vennligst prøv på nytt. - Installasjonen mislyktes fordi MIUI-optimalisering er aktivert. Deaktiver MIUI-optimalisering og prøv på nytt. - Installasjon feilet fordi apk signaturverifikasjon er aktivert. Deaktiver apk signaturverifikasjon og prøv på nytt. - Installation failed because the device doesn\'t have enough free space. - Finner ikke apk-filen for svart/mørkt tema fra installatøren. Fjern data fra denne appen og prøv på nytt. - Klarte ikke å lokalisere YouTube installasjonsstien etter splittet installasjon. + Kunne ikke avinstallere pakken %1$s + Kunne ikke finne de nødvendige filene for installasjon. Last ned installasjonsfilene på nytt, og prøv på nytt. + Klarte ikke å finne apk-filen for svart/mørkt tema på enheten, vennligst prøv igjen. + Installasjonen mislyktes fordi brukeren avbrutt installasjonen. + Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. + Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. + Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu + Installasjonen mislyktes på grunn av at installasjonsfilen er inkompatibel med enheten. Fjern nedlastede filer i innstillinger og prøv på nytt. + Installasjonen mislyktes fordi apk-filene er ødelagt, vennligst prøv på nytt. + Installasjonen mislyktes fordi MIUI-optimalisering er aktivert. Deaktiver MIUI-optimalisering og prøv på nytt. + Installasjon feilet fordi apk signaturverifikasjon er aktivert. Deaktiver apk signaturverifikasjon og prøv på nytt. + Installation failed because the device doesn\'t have enough free space. + Finner ikke apk-filen for svart/mørkt tema fra installatøren. Fjern data fra denne appen og prøv på nytt. + Klarte ikke å lokalisere YouTube installasjonsstien etter splittet installasjon. diff --git a/app/src/main/res/values-pa-rIN/strings.xml b/app/src/main/res/values-pa-rIN/strings.xml index bf5773a674..3a8ec06c43 100644 --- a/app/src/main/res/values-pa-rIN/strings.xml +++ b/app/src/main/res/values-pa-rIN/strings.xml @@ -1,120 +1,120 @@ - ਰੱਦ ਕਰੋ - ਬੰਦ ਕਰੋ - A custom GMS Implementation for Vanced based on the microG Project. - A modified YouTube client with many useful features! - Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. - ਰੀਸੈੱਟ - ਸੁੱਰਖਿਅਤ ਕਰੋ - ਹੋਰ ਐਪ ਚੁਣੋ + ਰੱਦ ਕਰੋ + ਬੰਦ ਕਰੋ + A custom GMS Implementation for Vanced based on the microG Project. + A modified YouTube client with many useful features! + Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. + ਰੀਸੈੱਟ + ਸੁੱਰਖਿਅਤ ਕਰੋ + ਹੋਰ ਐਪ ਚੁਣੋ - ਸਾਡੇ ਬਾਰੇ ਵਿੱਚ - Guide - ਮੈਨੇਜਰ - Logs - ਸੈਟਿੰਗਜ਼ - ਅਪਡੇਟ ਮੈਨੇਜਰ + ਸਾਡੇ ਬਾਰੇ ਵਿੱਚ + Guide + ਮੈਨੇਜਰ + Logs + ਸੈਟਿੰਗਜ਼ + ਅਪਡੇਟ ਮੈਨੇਜਰ - ਕੀ ਤੁਹਾਡੀ ਡਵਿਾਈਸ ਰੂਟ ਕੀਤਾ ਹੈ? - ਰੂਟ ਹਿਦਾਇਤਾਂ ਜਾਰੀ - ਆਓ ਸ਼ੁਰੂ ਕਰੀਏ - ਘੱਟੋ ਘੱਟ ਇੱਕ ਐਪ ਦੀ ਚੋਣ ਕਰੋ! - ਪਤਾ ਨਹੀਂ ਇਹ ਕੀ ਹੈ ਜਾਂ ਰੂਟ ਵਰਜ਼ਨ ਨਹੀਂ ਵਰਤਣਾ ਚਾਹੁੰਦੇ? ਹੇਠ ਦਿੱਤੇ ਨੀਲੇ ਤੀਰ ਤੇ ਕਲਿਕ ਕਰੋ! + ਕੀ ਤੁਹਾਡੀ ਡਵਿਾਈਸ ਰੂਟ ਕੀਤਾ ਹੈ? + ਰੂਟ ਹਿਦਾਇਤਾਂ ਜਾਰੀ + ਆਓ ਸ਼ੁਰੂ ਕਰੀਏ + ਘੱਟੋ ਘੱਟ ਇੱਕ ਐਪ ਦੀ ਚੋਣ ਕਰੋ! + ਪਤਾ ਨਹੀਂ ਇਹ ਕੀ ਹੈ ਜਾਂ ਰੂਟ ਵਰਜ਼ਨ ਨਹੀਂ ਵਰਤਣਾ ਚਾਹੁੰਦੇ? ਹੇਠ ਦਿੱਤੇ ਨੀਲੇ ਤੀਰ ਤੇ ਕਲਿਕ ਕਰੋ! - ਬਾਰੇ %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - Apps - ਤਬਦੀਲੀਆਂ - ਡਾਊਨਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ %1$s - ਸਥਾਪਨਾ + ਬਾਰੇ %1$s + Download + Info + Launch + Reinstall + Uninstall + Update + Apps + ਤਬਦੀਲੀਆਂ + ਡਾਊਨਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ %1$s + ਸਥਾਪਨਾ ਨਵੀਨਤਮ: - Install Vanced microG first + Install Vanced microG first ਰੂਟ ਐਕਸੈਸ ਨਹੀਂ ਦਿੱਤੀ ਗਈ - ਸੋਸ਼ਲ ਮੀਡੀਆ - ਸਾਡਾ ਸਮਰਥਨ ਕਰੋ - ਮੋਜੂਦ ਨਹੀਂ ਹੈ + ਸੋਸ਼ਲ ਮੀਡੀਆ + ਸਾਡਾ ਸਮਰਥਨ ਕਰੋ + ਮੋਜੂਦ ਨਹੀਂ ਹੈ ਸਥਾਪਿਤ: - ਐੱਕਸੈਂਟ ਰੰਗ - ਦਿੱਖ - ਵਿਹਾਰ - ਡਾਉਨਲੋਡ ਕੀਤੀਆਂ ਫਾਇਲਾਂ ਸਾਫ਼ ਕਰੋ - ਸਫਲਤਾਪੂਰਵਕ ਫਾਈਲਾਂ ਸਾਫ਼ ਕੀਤੀਆਂ - ਇਹ ਸਾਨੂੰ ਐਪ ਪ੍ਰਦਰਸ਼ਨ ਅਤੇ ਕਰੈਸ਼ ਲੌਗਾਂ ਬਾਰੇ ਜਾਣਕਾਰੀ ਇਕੱਠੀ ਕਰਨ ਦਿੰਦਾ ਹੈ - ਫਾਇਰਬੇਸ ਵਿਸ਼ਲੇਸ਼ਣ - ਭਾਸ਼ਾ - ਲਿੰਕ ਕਰੋਮ ਕਸਟਮ ਟੈਬਸ ਵਿੱਚ ਖੁੱਲ੍ਹਣਗੇ - ਕਰੋਮ ਕਸਟਮ ਟੈਬਸ ਦੀ ਵਰਤੋਂ ਕਰੋ - %1$s ਪੁਸ਼ ਸੂਚਨਾਵਾਂ - ਜਦੋਂ %1$s ਦਾ ਅੱਪਡੇਟ ਜਾਰੀ ਕੀਤਾ ਜਾਂਦਾ ਹੈ, ਤਾਂ ਪੁਸ਼ ਸੂਚਨਾਵਾਂ ਪ੍ਰਾਪਤ ਕਰੋ - ਨਵਾਂ ਸਮਾਂ ਮੁੱਲ ਬਚਾਉਣ ਵਿੱਚ ਅਸਫਲ - ਰੂਟ ਸਕ੍ਰਿਪਟ ਨੀਂਦ ਦਾ ਸਮਾਂ - ਮਾdਟ ਕਰਨ ਵਾਲੇ ਮੁੱਦਿਆਂ ਨੂੰ ਹੱਲ ਕਰਨ ਲਈ ਲਾਭਦਾਇਕ, /data/adb/service.d/app.sh ਸਕ੍ਰਿਪਟ ਵਿੱਚ ਸੁੱਤਾ ਸਮਾਂ ਮੁੱਲ ਵਿਵਸਥਿਤ ਕਰੋ - ਸਿਸਟਮ ਡਿਫੌਲਟ - ਥੀਮ - ਡਾਰਕ ਥੀਮ - ਲਾਇਟ ਥੀਮ - ਮੈਨੇਜਰ ਅਪਡੇਟ ਕੇਂਦਰ - ਕੋਈ ਨਵੇਂ ਅਪਡੇਟਸ ਨਹੀਂ - ਕਿਸਮ + ਐੱਕਸੈਂਟ ਰੰਗ + ਦਿੱਖ + ਵਿਹਾਰ + ਡਾਉਨਲੋਡ ਕੀਤੀਆਂ ਫਾਇਲਾਂ ਸਾਫ਼ ਕਰੋ + ਸਫਲਤਾਪੂਰਵਕ ਫਾਈਲਾਂ ਸਾਫ਼ ਕੀਤੀਆਂ + ਇਹ ਸਾਨੂੰ ਐਪ ਪ੍ਰਦਰਸ਼ਨ ਅਤੇ ਕਰੈਸ਼ ਲੌਗਾਂ ਬਾਰੇ ਜਾਣਕਾਰੀ ਇਕੱਠੀ ਕਰਨ ਦਿੰਦਾ ਹੈ + ਫਾਇਰਬੇਸ ਵਿਸ਼ਲੇਸ਼ਣ + ਭਾਸ਼ਾ + ਲਿੰਕ ਕਰੋਮ ਕਸਟਮ ਟੈਬਸ ਵਿੱਚ ਖੁੱਲ੍ਹਣਗੇ + ਕਰੋਮ ਕਸਟਮ ਟੈਬਸ ਦੀ ਵਰਤੋਂ ਕਰੋ + %1$s ਪੁਸ਼ ਸੂਚਨਾਵਾਂ + ਜਦੋਂ %1$s ਦਾ ਅੱਪਡੇਟ ਜਾਰੀ ਕੀਤਾ ਜਾਂਦਾ ਹੈ, ਤਾਂ ਪੁਸ਼ ਸੂਚਨਾਵਾਂ ਪ੍ਰਾਪਤ ਕਰੋ + ਨਵਾਂ ਸਮਾਂ ਮੁੱਲ ਬਚਾਉਣ ਵਿੱਚ ਅਸਫਲ + ਰੂਟ ਸਕ੍ਰਿਪਟ ਨੀਂਦ ਦਾ ਸਮਾਂ + ਮਾdਟ ਕਰਨ ਵਾਲੇ ਮੁੱਦਿਆਂ ਨੂੰ ਹੱਲ ਕਰਨ ਲਈ ਲਾਭਦਾਇਕ, /data/adb/service.d/app.sh ਸਕ੍ਰਿਪਟ ਵਿੱਚ ਸੁੱਤਾ ਸਮਾਂ ਮੁੱਲ ਵਿਵਸਥਿਤ ਕਰੋ + ਸਿਸਟਮ ਡਿਫੌਲਟ + ਥੀਮ + ਡਾਰਕ ਥੀਮ + ਲਾਇਟ ਥੀਮ + ਮੈਨੇਜਰ ਅਪਡੇਟ ਕੇਂਦਰ + ਕੋਈ ਨਵੇਂ ਅਪਡੇਟਸ ਨਹੀਂ + ਕਿਸਮ - Could not save logs - Successfully saved logs + Could not save logs + Successfully saved logs Details - %1$s ਇੰਸਟਾਲੇਸ਼ਨ ਫਾਈਲਾਂ ਲੱਭੀਆਂ! - ਮੈਨੇਜਰ ਨੇ ਖੋਜਿਆ ਕਿ ਇੰਸਟਾਲੇਸ਼ਨ ਲਈ ਲੋੜੀਂਦੀਆਂ ਫਾਇਲਾਂ %1$s ਮਿਲੀਆਂ ਹਨ. ਕੀ ਤੁਸੀਂ ਇਸ ਨੂੰ ਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? + %1$s ਇੰਸਟਾਲੇਸ਼ਨ ਫਾਈਲਾਂ ਲੱਭੀਆਂ! + ਮੈਨੇਜਰ ਨੇ ਖੋਜਿਆ ਕਿ ਇੰਸਟਾਲੇਸ਼ਨ ਲਈ ਲੋੜੀਂਦੀਆਂ ਫਾਇਲਾਂ %1$s ਮਿਲੀਆਂ ਹਨ. ਕੀ ਤੁਸੀਂ ਇਸ ਨੂੰ ਸਥਾਪਤ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ? %1$s ਸਥਾਪਨਾ ਚੁਣੋ - ਅੱਪਡੇਟ ਲਈ ਜਾਂਚ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ… + ਅੱਪਡੇਟ ਲਈ ਜਾਂਚ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ… ਭਾਸ਼ਾ (ਇ): %1$s ਥੀਮ: %1$s ਵਰਜਨ %1$s - ਗਲਤੀ - ਗਾਇਡ - ਉਡੀਕੋ! + ਗਲਤੀ + ਗਾਇਡ + ਉਡੀਕੋ! ਤੁਸੀਂ Vanced ਦੇ Magisk / TWRP ਸੰਸਕਰਣ ਦਾ ਉਪਯੋਗ ਕਰ ਰਹੇ ਹੋ, ਜਿਸਨੂੰ ਬੰਦ ਕਰ ਦਿੱਤਾ ਗਿਆ ਹੈ ਅੱਤੇ ਇਸ ਐਪ ਦਾ ਉਪਯੋਗ ਕਰਕੇ ਅੱਪਡੇਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ| ਕਿਰਪਾ ਇਸ Magisk ਮੋਡੂਅਲ ਨੂੰ / TWRP Vanced uninstaller ਦਾ ਉਪਯੋਗ ਕਰਕੇ ਹੱਟਾ ਦੇਵੋਂ. - To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) - MIUI Optimizations are enabled! - Please do NOT exit the app during this process! - ਮੁੜ ਡਾਉਨਲੋਡ - ਪੱਕਾ ਕਰੋ ਕਿ ਤੁਸੀਂ vancedapp.com, Vanced Discord ਸਰਵਰ ਜਾਂ Vanced GitHub ਤੋਂ ਐਪ ਡਾਉਨਲੋਡ ਕੀਤਾ ਹੈ + To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) + MIUI Optimizations are enabled! + Please do NOT exit the app during this process! + ਮੁੜ ਡਾਉਨਲੋਡ + ਪੱਕਾ ਕਰੋ ਕਿ ਤੁਸੀਂ vancedapp.com, Vanced Discord ਸਰਵਰ ਜਾਂ Vanced GitHub ਤੋਂ ਐਪ ਡਾਉਨਲੋਡ ਕੀਤਾ ਹੈ ਵਰਜਨ - ਜੀ ਆਇਆਂ ਨੂੰ + ਜੀ ਆਇਆਂ ਨੂੰ - Vanced ਦੇ ਲਈ ਆਪਣੀ ਪਸੰਦੀਦਾ ਭਾਸ਼ਾ (ਏ) ਚੁਣੋ - Latest + Vanced ਦੇ ਲਈ ਆਪਣੀ ਪਸੰਦੀਦਾ ਭਾਸ਼ਾ (ਏ) ਚੁਣੋ + Latest ਲਾਇਟ + %1$s ਘੱਟੋ-ਘੱਟ ਇੱਕ ਭਾਸ਼ਾ ਚੁਣੋ! - Black - Dark + Black + Dark - ਪ੍ਬੰਧਕ ਨਿਰਮਾਣਕਰਤਾ - Other Contributors - ਸਰੋਤ - Vanced ਟੋਲੀ + ਪ੍ਬੰਧਕ ਨਿਰਮਾਣਕਰਤਾ + Other Contributors + ਸਰੋਤ + Vanced ਟੋਲੀ - ਸਿਸਟਮ ਦੇ ਮਾਲਕ ਨੂੰ APK ਨੂੰ `chown` ਕਰਨ ਵਿੱਚ ਨਾਕਾਮ, ਫਿਰ ਤੋਂ ਕੋਸ਼ਿਸ਼ ਕਰੋ. - ਡਾਉਨਲੋਡ ਕਰਨ ਦੌਰਾਨ ਗਲਤੀ %1$s + ਸਿਸਟਮ ਦੇ ਮਾਲਕ ਨੂੰ APK ਨੂੰ `chown` ਕਰਨ ਵਿੱਚ ਨਾਕਾਮ, ਫਿਰ ਤੋਂ ਕੋਸ਼ਿਸ਼ ਕਰੋ. + ਡਾਉਨਲੋਡ ਕਰਨ ਦੌਰਾਨ ਗਲਤੀ %1$s ਨਵਾਂ ਲਹਿਜ਼ਾ ਰੰਗ ਲਾਗੂ ਕਰਨ ਵਿੱਚ ਅਸਫਲ - ਪੈਕਜ ਦੀ ਸਥਾਪਨਾ ਰੱਦ ਕਰਨ ਵਿੱਚ ਨਾਕਾਮ %1$s - ਇੰਸਟਾਲੇਸ਼ਨ ਲਈ ਲੋੜੀਂਦੀਆਂ ਫਾਈਲਾਂ ਦਾ ਪਤਾ ਲਗਾਉਣ ਵਿੱਚ ਅਸਫਲ. ਇੰਸਟਾਲੇਸ਼ਨ ਫਾਈਲਾਂ ਨੂੰ ਮੁੜ ਡਾਉਨਲੋਡ ਕਰੋ, ਫਿਰ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ. - ਸਟੋਰੇਜ ਤੋਂ ਕਾਲੇ / ਹਨੇਰੇ ਥੀਮ ਲਈ ਏਪੀਕੇ ਫਾਈਲ ਲੱਭਣ ਵਿੱਚ ਅਸਫਲ, ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ. - ਇੰਸਟਾਲ ਨਾਕਾਮ ਰਹੀ ਕਿਓਂਕਿ ਉਪਯੋਗਕਰਤਾ ਨੇ ਇੰਸਟਾਲੇਸ਼ਨ ਰੱਦ ਕਰ ਦਿੱਤੀ. - ਸਥਾਪਨਾ ਅਸਫਲ ਕਿਉਂਕਿ ਐਪ ਪਹਿਲਾਂ ਤੋਂ ਸਥਾਪਤ ਐਪ ਨਾਲ ਟਕਰਾਉਂਦੀ ਹੈ. ਐਪ ਦੇ ਮੌਜੂਦਾ ਸੰਸਕਰਣ ਨੂੰ ਅਣਇੰਸਟੌਲ ਕਰੋ, ਫਿਰ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ. - Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. - Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu - ਸਥਾਪਨਾ ਅਸਫਲ ਹੋਈ ਕਿਉਂਕਿ ਇੰਸਟਾਲੇਸ਼ਨ ਫਾਈਲ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਦੇ ਅਨੁਕੂਲ ਨਹੀਂ ਹੈ. ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਡਾਉਨਲੋਡ ਕੀਤੀਆਂ ਫਾਈਲਾਂ ਸਾਫ਼ ਕਰੋ, ਫਿਰ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ. - ਸਥਾਪਨਾ ਅਸਫਲ ਹੋਈ ਕਿਉਂਕਿ ਏਪੀਕੇ ਫਾਈਲਾਂ ਖ਼ਰਾਬ ਹਨ, ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ. - MIUI ਸਥਾਪਨਾ ਅਸਫਲ, ਕਿਉਂਕਿ Optimization ਯੋਗ ਕੀਤੀ ਗਈ ਸੀ. MIUI Optimization ਅਯੋਗ ਕਰੋ ਫਿਰ ਕੋਸ਼ਿਸ਼ ਕਰੋ. - ਸਥਾਪਨਾ ਅਸਫਲ ਕਿਉਂਕਿ ਏਪੀਕੇ ਦਸਤਖਤ ਤਸਦੀਕ ਯੋਗ ਹੈ. ਏਪੀਕੇ ਦਸਤਖਤ ਤਸਦੀਕ ਨੂੰ ਅਯੋਗ ਕਰੋ, ਫਿਰ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ. - Installation failed because the device doesn\'t have enough free space. - ਇੰਸਟੌਲਰ ਤੋਂ ਕਾਲੇ / ਹਨੇਰੇ ਥੀਮ ਲਈ ਏਪੀਕੇ ਫਾਈਲ ਲੱਭਣ ਵਿੱਚ ਅਸਫਲ. ਮੈਨੇਜਰ ਐਪ ਦਾ ਡਾਟਾ ਸਾਫ਼ ਕਰੋ, ਫਿਰ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ. - ਸਪਲਿਟ ਇੰਸਟਾਲੇਸ਼ਨ ਦੇ ਬਾਅਦ ਸਟਾਕ YouTube ਇੰਸਟਾਲੇਸ਼ਨ ਮਾਰਗ ਦਾ ਪਤਾ ਲਗਾਉਣ ਵਿੱਚ ਅਸਫਲ. + ਪੈਕਜ ਦੀ ਸਥਾਪਨਾ ਰੱਦ ਕਰਨ ਵਿੱਚ ਨਾਕਾਮ %1$s + ਇੰਸਟਾਲੇਸ਼ਨ ਲਈ ਲੋੜੀਂਦੀਆਂ ਫਾਈਲਾਂ ਦਾ ਪਤਾ ਲਗਾਉਣ ਵਿੱਚ ਅਸਫਲ. ਇੰਸਟਾਲੇਸ਼ਨ ਫਾਈਲਾਂ ਨੂੰ ਮੁੜ ਡਾਉਨਲੋਡ ਕਰੋ, ਫਿਰ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ. + ਸਟੋਰੇਜ ਤੋਂ ਕਾਲੇ / ਹਨੇਰੇ ਥੀਮ ਲਈ ਏਪੀਕੇ ਫਾਈਲ ਲੱਭਣ ਵਿੱਚ ਅਸਫਲ, ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ. + ਇੰਸਟਾਲ ਨਾਕਾਮ ਰਹੀ ਕਿਓਂਕਿ ਉਪਯੋਗਕਰਤਾ ਨੇ ਇੰਸਟਾਲੇਸ਼ਨ ਰੱਦ ਕਰ ਦਿੱਤੀ. + ਸਥਾਪਨਾ ਅਸਫਲ ਕਿਉਂਕਿ ਐਪ ਪਹਿਲਾਂ ਤੋਂ ਸਥਾਪਤ ਐਪ ਨਾਲ ਟਕਰਾਉਂਦੀ ਹੈ. ਐਪ ਦੇ ਮੌਜੂਦਾ ਸੰਸਕਰਣ ਨੂੰ ਅਣਇੰਸਟੌਲ ਕਰੋ, ਫਿਰ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ. + Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. + Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu + ਸਥਾਪਨਾ ਅਸਫਲ ਹੋਈ ਕਿਉਂਕਿ ਇੰਸਟਾਲੇਸ਼ਨ ਫਾਈਲ ਤੁਹਾਡੀ ਡਿਵਾਈਸ ਦੇ ਅਨੁਕੂਲ ਨਹੀਂ ਹੈ. ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਡਾਉਨਲੋਡ ਕੀਤੀਆਂ ਫਾਈਲਾਂ ਸਾਫ਼ ਕਰੋ, ਫਿਰ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ. + ਸਥਾਪਨਾ ਅਸਫਲ ਹੋਈ ਕਿਉਂਕਿ ਏਪੀਕੇ ਫਾਈਲਾਂ ਖ਼ਰਾਬ ਹਨ, ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ. + MIUI ਸਥਾਪਨਾ ਅਸਫਲ, ਕਿਉਂਕਿ Optimization ਯੋਗ ਕੀਤੀ ਗਈ ਸੀ. MIUI Optimization ਅਯੋਗ ਕਰੋ ਫਿਰ ਕੋਸ਼ਿਸ਼ ਕਰੋ. + ਸਥਾਪਨਾ ਅਸਫਲ ਕਿਉਂਕਿ ਏਪੀਕੇ ਦਸਤਖਤ ਤਸਦੀਕ ਯੋਗ ਹੈ. ਏਪੀਕੇ ਦਸਤਖਤ ਤਸਦੀਕ ਨੂੰ ਅਯੋਗ ਕਰੋ, ਫਿਰ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ. + Installation failed because the device doesn\'t have enough free space. + ਇੰਸਟੌਲਰ ਤੋਂ ਕਾਲੇ / ਹਨੇਰੇ ਥੀਮ ਲਈ ਏਪੀਕੇ ਫਾਈਲ ਲੱਭਣ ਵਿੱਚ ਅਸਫਲ. ਮੈਨੇਜਰ ਐਪ ਦਾ ਡਾਟਾ ਸਾਫ਼ ਕਰੋ, ਫਿਰ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ. + ਸਪਲਿਟ ਇੰਸਟਾਲੇਸ਼ਨ ਦੇ ਬਾਅਦ ਸਟਾਕ YouTube ਇੰਸਟਾਲੇਸ਼ਨ ਮਾਰਗ ਦਾ ਪਤਾ ਲਗਾਉਣ ਵਿੱਚ ਅਸਫਲ. diff --git a/app/src/main/res/values-pa-rPK/strings.xml b/app/src/main/res/values-pa-rPK/strings.xml index e5224e8f09..212dc55ef4 100644 --- a/app/src/main/res/values-pa-rPK/strings.xml +++ b/app/src/main/res/values-pa-rPK/strings.xml @@ -1,120 +1,120 @@ - Cancel - Close - A custom GMS Implementation for Vanced based on the microG Project. - A modified YouTube client with many useful features! - Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. - Reset - Save - Select Your Apps + Cancel + Close + A custom GMS Implementation for Vanced based on the microG Project. + A modified YouTube client with many useful features! + Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. + Reset + Save + Select Your Apps - About - Guide - Manager - Logs - Settings - Update Manager + About + Guide + Manager + Logs + Settings + Update Manager - Is Your Device Rooted? - Grant Root Permission - Let\'s get started - Select at least one app! - Don\'t know what this is or don\'t want to use the root version? just click the blue arrow below! + Is Your Device Rooted? + Grant Root Permission + Let\'s get started + Select at least one app! + Don\'t know what this is or don\'t want to use the root version? just click the blue arrow below! - About %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - Apps - Changelog - Downloading %1$s - Install + About %1$s + Download + Info + Launch + Reinstall + Uninstall + Update + Apps + Changelog + Downloading %1$s + Install Latest: - Install Vanced microG first + Install Vanced microG first Root access not granted - Social Media - Support us - Unavailable + Social Media + Support us + Unavailable Installed: - Accent Color - Appearance - Behavior - Clear downloaded files - Successfully cleared files - This lets us collect information about app performance and crash logs - Firebase Analytics - Language - Links will open in Chrome Custom Tabs - Use Chrome Custom Tabs - %1$s Push Notifications - Receive push notifications when an update for %1$s is released - Failed to save new time value - Root Script Sleep Time - Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues - System Default - Theme - Dark Theme - Light Theme - Manager Update Center - No new updates - Variant + Accent Color + Appearance + Behavior + Clear downloaded files + Successfully cleared files + This lets us collect information about app performance and crash logs + Firebase Analytics + Language + Links will open in Chrome Custom Tabs + Use Chrome Custom Tabs + %1$s Push Notifications + Receive push notifications when an update for %1$s is released + Failed to save new time value + Root Script Sleep Time + Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues + System Default + Theme + Dark Theme + Light Theme + Manager Update Center + No new updates + Variant - Could not save logs - Successfully saved logs + Could not save logs + Successfully saved logs Details - %1$s installation files detected! - Manager detected that all necessary files for %1$s installation were found. Do you want to install it? + %1$s installation files detected! + Manager detected that all necessary files for %1$s installation were found. Do you want to install it? %1$s Installation Preferences - Checking for updates… + Checking for updates… Language(s): %1$s Theme: %1$s Version: %1$s - Error - Guide - Stop! + Error + Guide + Stop! You are using the Magisk/TWRP version of Vanced, which is discontinued and cannot be updated using this app. Please remove it by removing the Magisk module/using TWRP Vanced uninstaller. - To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) - MIUI Optimizations are enabled! - Please do NOT exit the app during this process! - Redownload - Make sure that you downloaded the app from vancedapp.com, the Vanced Discord server, or the Vanced GitHub + To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) + MIUI Optimizations are enabled! + Please do NOT exit the app during this process! + Redownload + Make sure that you downloaded the app from vancedapp.com, the Vanced Discord server, or the Vanced GitHub Version - Welcome + Welcome - Choose your preferred language(s) for Vanced - Latest + Choose your preferred language(s) for Vanced + Latest Light + %1$s Select at least one language! - Black - Dark + Black + Dark - Manager Devs - Other Contributors - Sources - Vanced Team + Manager Devs + Other Contributors + Sources + Vanced Team - Failed to `chown` APK to system owner, please try again. - Error Downloading %1$s + Failed to `chown` APK to system owner, please try again. + Error Downloading %1$s Failed to apply new accent color - Failed to uninstall package %1$s - Failed to locate the required files for installation. Re-download the installation files, then try again. - Failed to locate apk file for black/dark theme from storage, please try again. - Installation failed because the user aborted the installation. - Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. - Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. - Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu - Installation failed because the installation file is incompatible with your device. Clear downloaded files in the Settings, then try again. - Installation failed because the apk files are corrupted, please try again. - Installation failed because MIUI Optimization is enabled. Disable MIUI Optimization, then try again. - Installation failed because apk signature verification is enabled. Disable apk signature verification, then try again. - Installation failed because the device doesn\'t have enough free space. - Failed to find apk file for black/dark theme from the installer. Clear app data of Manager, then try again. - Failed to locate the stock YouTube installation path after split installation. + Failed to uninstall package %1$s + Failed to locate the required files for installation. Re-download the installation files, then try again. + Failed to locate apk file for black/dark theme from storage, please try again. + Installation failed because the user aborted the installation. + Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. + Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. + Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu + Installation failed because the installation file is incompatible with your device. Clear downloaded files in the Settings, then try again. + Installation failed because the apk files are corrupted, please try again. + Installation failed because MIUI Optimization is enabled. Disable MIUI Optimization, then try again. + Installation failed because apk signature verification is enabled. Disable apk signature verification, then try again. + Installation failed because the device doesn\'t have enough free space. + Failed to find apk file for black/dark theme from the installer. Clear app data of Manager, then try again. + Failed to locate the stock YouTube installation path after split installation. diff --git a/app/src/main/res/values-pl-rPL/strings.xml b/app/src/main/res/values-pl-rPL/strings.xml index c6d4b4e1d1..e1d2bc3858 100644 --- a/app/src/main/res/values-pl-rPL/strings.xml +++ b/app/src/main/res/values-pl-rPL/strings.xml @@ -1,120 +1,120 @@ - Anuluj - Zamknij - Niestandardowa implementacja GMS dla Vanced w oparciu o projekt microG. - Zmodyfikowany klient YouTube z wieloma przydatnymi funkcjami! - Vanced, ale dla Muzyki YouTube! Stosunkowo mniej bogaty w funkcje, ale spełnia Twoje potrzeby. - Zresetuj - Zapisz - Wybierz swoje aplikacje + Anuluj + Zamknij + Niestandardowa implementacja GMS dla Vanced w oparciu o projekt microG. + Zmodyfikowany klient YouTube z wieloma przydatnymi funkcjami! + Vanced, ale dla Muzyki YouTube! Stosunkowo mniej bogaty w funkcje, ale spełnia Twoje potrzeby. + Zresetuj + Zapisz + Wybierz swoje aplikacje - O nas - Przewodnik - Menedżer - Dzienniki - Ustawienia - Zaktualizuj Menedżera + O nas + Przewodnik + Menedżer + Dzienniki + Ustawienia + Zaktualizuj Menedżera - Czy Twoje urządzenie jest zakorzenione (root)? - Przyznaj uprawnienie root - Zaczynajmy - Wybierz co najmniej jedną aplikację! - Nie wiesz, co to jest lub nie chcesz użyć wersji z rootem? Po prostu kliknij niebieską strzałkę poniżej! + Czy Twoje urządzenie jest zakorzenione (root)? + Przyznaj uprawnienie root + Zaczynajmy + Wybierz co najmniej jedną aplikację! + Nie wiesz, co to jest lub nie chcesz użyć wersji z rootem? Po prostu kliknij niebieską strzałkę poniżej! - O %1$s - Pobierz - Informacja - Uruchom - Przeinstaluj - Odinstaluj - Aktualizuj - Aplikacje - Lista zmian - Pobieranie %1$s - Zainstaluj + O %1$s + Pobierz + Informacja + Uruchom + Przeinstaluj + Odinstaluj + Aktualizuj + Aplikacje + Lista zmian + Pobieranie %1$s + Zainstaluj Najnowsza: - Najpierw zainstaluj Vanced microG + Najpierw zainstaluj Vanced microG Root nie został przyznany - Media Społecznościowe - Wesprzyj nas - Niedostępne + Media Społecznościowe + Wesprzyj nas + Niedostępne Zainstalowano: - Kolor Akcentu - Wygląd - Zachowanie - Wyczyść pobrane pliki - Pomyślnie wyczyszczono pliki - To pozwala nam zbierać informacje o wydajności aplikacji i dziennikach awarii - Analityka Firebase - Język - Linki zostaną otwarte w niestandardowych kartach Chrome - Używaj niestandardowych kart Chrome - %1$s Powiadomień Push - Otrzymuj powiadomienia push po wydaniu aktualizacji dla %1$s - Nie udało się zapisać nowej wartości czasu - Czas snu skryptu root - Dostosuj wartość czasu uśpienia w skrypcie /data/adb/service.d/app.sh, przydatne do naprawy problemów z montowaniem - Domyślny systemowy - Motyw - Ciemny Motyw - Jasny Motyw - Centrum aktualizacji - Brak nowych aktualizacji - Wariant + Kolor Akcentu + Wygląd + Zachowanie + Wyczyść pobrane pliki + Pomyślnie wyczyszczono pliki + To pozwala nam zbierać informacje o wydajności aplikacji i dziennikach awarii + Analityka Firebase + Język + Linki zostaną otwarte w niestandardowych kartach Chrome + Używaj niestandardowych kart Chrome + %1$s Powiadomień Push + Otrzymuj powiadomienia push po wydaniu aktualizacji dla %1$s + Nie udało się zapisać nowej wartości czasu + Czas snu skryptu root + Dostosuj wartość czasu uśpienia w skrypcie /data/adb/service.d/app.sh, przydatne do naprawy problemów z montowaniem + Domyślny systemowy + Motyw + Ciemny Motyw + Jasny Motyw + Centrum aktualizacji + Brak nowych aktualizacji + Wariant - Nie udało się zapisać dzienników - Pomyślnie zapisano dzienniki + Nie udało się zapisać dzienników + Pomyślnie zapisano dzienniki Szczegóły - Wykryto %1$s plików instalacyjnych! - Menedżer wykrył, że znaleziono wszystkie pliki niezbędne do instalacji %1$s. Czy chcesz zainstalować? + Wykryto %1$s plików instalacyjnych! + Menedżer wykrył, że znaleziono wszystkie pliki niezbędne do instalacji %1$s. Czy chcesz zainstalować? Preferencje instalacji %1$s - Sprawdzam aktualizacje… + Sprawdzam aktualizacje… Język(i): %1$s Motyw: %1$s Wersja: %1$s - Błąd - Przewodnik - Stop! + Błąd + Przewodnik + Stop! Używasz wersji Magisk/TWRP Vanced, która została przerwana i nie może zostać zaktualizowana za pomocą tej aplikacji. Proszę go usunąć usuwając moduł Magisk/używając TWRP Vanced deinstalatora. - Aby zainstalować Vanced, MUSISZ wyłączyć optymalizację MIUI w ustawieniach dewelopera. (Możesz zignorować to ostrzeżenie, jeśli korzystasz z ROM 20.2.20 lub późniejszego xiaomi.eu) - Optymalizacja MIUI jest włączona! - NIE wychodź z aplikacji podczas trwania tego procesu! - Pobierz ponownie - Upewnij się, że pobrałeś aplikację z vancedapp.com, serwera Vanced Discord lub Vanced GitHub + Aby zainstalować Vanced, MUSISZ wyłączyć optymalizację MIUI w ustawieniach dewelopera. (Możesz zignorować to ostrzeżenie, jeśli korzystasz z ROM 20.2.20 lub późniejszego xiaomi.eu) + Optymalizacja MIUI jest włączona! + NIE wychodź z aplikacji podczas trwania tego procesu! + Pobierz ponownie + Upewnij się, że pobrałeś aplikację z vancedapp.com, serwera Vanced Discord lub Vanced GitHub Wersja - Witaj + Witaj - Wybierz preferowany język(i) dla Vanced - Najnowsza + Wybierz preferowany język(i) dla Vanced + Najnowsza Jasny + %1$s Wybierz co najmniej jeden język! - Czarny - Ciemny + Czarny + Ciemny - Deweloperzy Menedżera - Inni współtwórcy - Źródła - Zespół Vanced + Deweloperzy Menedżera + Inni współtwórcy + Źródła + Zespół Vanced - Nie udało się `chown` APK dla właściciela systemu, spróbuj ponownie. - Błąd pobierania %1$s + Nie udało się `chown` APK dla właściciela systemu, spróbuj ponownie. + Błąd pobierania %1$s Nie udało się zastosować nowego koloru akcentu - Nie udało się odinstalować pakietu %1$s - Nie udało się zlokalizować wymaganych plików do instalacji. Pobierz ponownie pliki instalacyjne, a następnie spróbuj ponownie. - Nie udało się zlokalizować pliku apk dla czarnego/ciemnego motywu, spróbuj ponownie. - Instalacja nie powiodła się, ponieważ użytkownik przerwał instalację. - Instalacja nie powiodła się ponieważ aplikacja konfliktuje z już zainstalowaną aplikacją. Odinstaluj aktualną wersję aplikacji a następnie spróbuj ponownie. - Instalacja nie powiodła się, ponieważ użytkownik próbował obniżyć paczkę. Odinstaluj aktualizacje z domyślnej aplikacji YouTube, a następnie spróbuj ponownie. - Instalacja nie powiodła się z nieznanych powodów, dołącz do naszego Telegrama lub Discorda, aby uzyskać dalsze wsparcie. Proszę również dołączyć zrzut ekranu z zaawansowanego menu - Instalacja nie powiodła się, ponieważ plik instalacyjny jest niezgodny z Twoim urządzeniem. Wyczyść pobrane pliki w Ustawieniach, a następnie spróbuj ponownie. - Instalacja nie powiodła się, bo pliki apk są uszkodzone, spróbuj jeszcze raz. - Instalacja nie powiodła się, ponieważ optymalizacja MIUI jest włączona. Wyłącz optymalizację MIUI, a następnie spróbuj ponownie. - Instalacja nie powiodła się, ponieważ włączona jest weryfikacja podpisu apk. Wyłącz weryfikację podpisu apk, a następnie spróbuj ponownie. - Instalacja nie powiodła się, ponieważ urządzenie nie ma wystarczającej ilości wolnego miejsca. - Nie udało się znaleźć pliku apk dla czarnego/ciemnego motywu z instalatora. Wyczyść dane aplikacji Menedżera i spróbuj ponownie. - Nie udało się zlokalizować ścieżki instalacji YouTube po podzieleniu instalacji. + Nie udało się odinstalować pakietu %1$s + Nie udało się zlokalizować wymaganych plików do instalacji. Pobierz ponownie pliki instalacyjne, a następnie spróbuj ponownie. + Nie udało się zlokalizować pliku apk dla czarnego/ciemnego motywu, spróbuj ponownie. + Instalacja nie powiodła się, ponieważ użytkownik przerwał instalację. + Instalacja nie powiodła się ponieważ aplikacja konfliktuje z już zainstalowaną aplikacją. Odinstaluj aktualną wersję aplikacji a następnie spróbuj ponownie. + Instalacja nie powiodła się, ponieważ użytkownik próbował obniżyć paczkę. Odinstaluj aktualizacje z domyślnej aplikacji YouTube, a następnie spróbuj ponownie. + Instalacja nie powiodła się z nieznanych powodów, dołącz do naszego Telegrama lub Discorda, aby uzyskać dalsze wsparcie. Proszę również dołączyć zrzut ekranu z zaawansowanego menu + Instalacja nie powiodła się, ponieważ plik instalacyjny jest niezgodny z Twoim urządzeniem. Wyczyść pobrane pliki w Ustawieniach, a następnie spróbuj ponownie. + Instalacja nie powiodła się, bo pliki apk są uszkodzone, spróbuj jeszcze raz. + Instalacja nie powiodła się, ponieważ optymalizacja MIUI jest włączona. Wyłącz optymalizację MIUI, a następnie spróbuj ponownie. + Instalacja nie powiodła się, ponieważ włączona jest weryfikacja podpisu apk. Wyłącz weryfikację podpisu apk, a następnie spróbuj ponownie. + Instalacja nie powiodła się, ponieważ urządzenie nie ma wystarczającej ilości wolnego miejsca. + Nie udało się znaleźć pliku apk dla czarnego/ciemnego motywu z instalatora. Wyczyść dane aplikacji Menedżera i spróbuj ponownie. + Nie udało się zlokalizować ścieżki instalacji YouTube po podzieleniu instalacji. diff --git a/app/src/main/res/values-ps-rAF/strings.xml b/app/src/main/res/values-ps-rAF/strings.xml index e5224e8f09..212dc55ef4 100644 --- a/app/src/main/res/values-ps-rAF/strings.xml +++ b/app/src/main/res/values-ps-rAF/strings.xml @@ -1,120 +1,120 @@ - Cancel - Close - A custom GMS Implementation for Vanced based on the microG Project. - A modified YouTube client with many useful features! - Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. - Reset - Save - Select Your Apps + Cancel + Close + A custom GMS Implementation for Vanced based on the microG Project. + A modified YouTube client with many useful features! + Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. + Reset + Save + Select Your Apps - About - Guide - Manager - Logs - Settings - Update Manager + About + Guide + Manager + Logs + Settings + Update Manager - Is Your Device Rooted? - Grant Root Permission - Let\'s get started - Select at least one app! - Don\'t know what this is or don\'t want to use the root version? just click the blue arrow below! + Is Your Device Rooted? + Grant Root Permission + Let\'s get started + Select at least one app! + Don\'t know what this is or don\'t want to use the root version? just click the blue arrow below! - About %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - Apps - Changelog - Downloading %1$s - Install + About %1$s + Download + Info + Launch + Reinstall + Uninstall + Update + Apps + Changelog + Downloading %1$s + Install Latest: - Install Vanced microG first + Install Vanced microG first Root access not granted - Social Media - Support us - Unavailable + Social Media + Support us + Unavailable Installed: - Accent Color - Appearance - Behavior - Clear downloaded files - Successfully cleared files - This lets us collect information about app performance and crash logs - Firebase Analytics - Language - Links will open in Chrome Custom Tabs - Use Chrome Custom Tabs - %1$s Push Notifications - Receive push notifications when an update for %1$s is released - Failed to save new time value - Root Script Sleep Time - Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues - System Default - Theme - Dark Theme - Light Theme - Manager Update Center - No new updates - Variant + Accent Color + Appearance + Behavior + Clear downloaded files + Successfully cleared files + This lets us collect information about app performance and crash logs + Firebase Analytics + Language + Links will open in Chrome Custom Tabs + Use Chrome Custom Tabs + %1$s Push Notifications + Receive push notifications when an update for %1$s is released + Failed to save new time value + Root Script Sleep Time + Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues + System Default + Theme + Dark Theme + Light Theme + Manager Update Center + No new updates + Variant - Could not save logs - Successfully saved logs + Could not save logs + Successfully saved logs Details - %1$s installation files detected! - Manager detected that all necessary files for %1$s installation were found. Do you want to install it? + %1$s installation files detected! + Manager detected that all necessary files for %1$s installation were found. Do you want to install it? %1$s Installation Preferences - Checking for updates… + Checking for updates… Language(s): %1$s Theme: %1$s Version: %1$s - Error - Guide - Stop! + Error + Guide + Stop! You are using the Magisk/TWRP version of Vanced, which is discontinued and cannot be updated using this app. Please remove it by removing the Magisk module/using TWRP Vanced uninstaller. - To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) - MIUI Optimizations are enabled! - Please do NOT exit the app during this process! - Redownload - Make sure that you downloaded the app from vancedapp.com, the Vanced Discord server, or the Vanced GitHub + To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) + MIUI Optimizations are enabled! + Please do NOT exit the app during this process! + Redownload + Make sure that you downloaded the app from vancedapp.com, the Vanced Discord server, or the Vanced GitHub Version - Welcome + Welcome - Choose your preferred language(s) for Vanced - Latest + Choose your preferred language(s) for Vanced + Latest Light + %1$s Select at least one language! - Black - Dark + Black + Dark - Manager Devs - Other Contributors - Sources - Vanced Team + Manager Devs + Other Contributors + Sources + Vanced Team - Failed to `chown` APK to system owner, please try again. - Error Downloading %1$s + Failed to `chown` APK to system owner, please try again. + Error Downloading %1$s Failed to apply new accent color - Failed to uninstall package %1$s - Failed to locate the required files for installation. Re-download the installation files, then try again. - Failed to locate apk file for black/dark theme from storage, please try again. - Installation failed because the user aborted the installation. - Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. - Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. - Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu - Installation failed because the installation file is incompatible with your device. Clear downloaded files in the Settings, then try again. - Installation failed because the apk files are corrupted, please try again. - Installation failed because MIUI Optimization is enabled. Disable MIUI Optimization, then try again. - Installation failed because apk signature verification is enabled. Disable apk signature verification, then try again. - Installation failed because the device doesn\'t have enough free space. - Failed to find apk file for black/dark theme from the installer. Clear app data of Manager, then try again. - Failed to locate the stock YouTube installation path after split installation. + Failed to uninstall package %1$s + Failed to locate the required files for installation. Re-download the installation files, then try again. + Failed to locate apk file for black/dark theme from storage, please try again. + Installation failed because the user aborted the installation. + Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. + Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. + Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu + Installation failed because the installation file is incompatible with your device. Clear downloaded files in the Settings, then try again. + Installation failed because the apk files are corrupted, please try again. + Installation failed because MIUI Optimization is enabled. Disable MIUI Optimization, then try again. + Installation failed because apk signature verification is enabled. Disable apk signature verification, then try again. + Installation failed because the device doesn\'t have enough free space. + Failed to find apk file for black/dark theme from the installer. Clear app data of Manager, then try again. + Failed to locate the stock YouTube installation path after split installation. diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 6f87f5c3dc..19504ec17f 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -1,120 +1,120 @@ - Cancelar - Fechar - Uma implementação personalizada de GMS para Vanced com base no projeto microG. - Um cliente modificado do YouTube com muitos recursos úteis! - Vanced, mas para o YouTube Music! Relativamente menos funções, mas satisfaz suas necessidades. - Resetar - Salvar - Selecione Seus Aplicativos + Cancelar + Fechar + Uma implementação personalizada de GMS para Vanced com base no projeto microG. + Um cliente modificado do YouTube com muitos recursos úteis! + Vanced, mas para o YouTube Music! Relativamente menos funções, mas satisfaz suas necessidades. + Resetar + Salvar + Selecione Seus Aplicativos - Sobre - Guia - Gerenciador - Registros - Configurações - Gerenciador de Atualização + Sobre + Guia + Gerenciador + Registros + Configurações + Gerenciador de Atualização - Seu Dispositivo Tem Root? - Conceder Permissão de Root - Vamos começar - Selecione pelo menos um aplicativo! - Não sabe o que isto é ou não quer usar a versão root? basta clicar na seta azul abaixo! + Seu Dispositivo Tem Root? + Conceder Permissão de Root + Vamos começar + Selecione pelo menos um aplicativo! + Não sabe o que isto é ou não quer usar a versão root? basta clicar na seta azul abaixo! - Sobre %1$s - Baixar - Informações - Iniciar - Reinstalar - Desinstalar - Atualizar - Aplicativos - Registro de mudanças - Baixando %1$s - Instalar + Sobre %1$s + Baixar + Informações + Iniciar + Reinstalar + Desinstalar + Atualizar + Aplicativos + Registro de mudanças + Baixando %1$s + Instalar Mais recente: - Instale o microG Vanced primeiro + Instale o microG Vanced primeiro Acesso root não concedido - Mídias Sociais - Apoie-nos - Indisponível + Mídias Sociais + Apoie-nos + Indisponível Instalado: - Cor de destaque - Aparência - Comportamento - Limpar arquivos baixados - Arquivos limpos com sucesso - Isto nos permite coletar informações sobre o desempenho do aplicativo e registros de falhas - Análises de Firebase - Idioma - Os links serão abertos nas abas personalizadas do Chrome - Usar abas personalizadas do Chrome - %1$s notificações push - Receber notificações quando uma atualização para o %1$s for lançado - Falha ao salvar o novo valor de tempo - Tempo de repouso do script root - Ajuste o valor do tempo de suspensão usado no script/data/adb/service.d/app.sh, útil para corrigir problemas de montagem - Padrão do sistema - Tema - Escuro - Claro - Centro de Atualizações - Não há novas atualizações - Variante + Cor de destaque + Aparência + Comportamento + Limpar arquivos baixados + Arquivos limpos com sucesso + Isto nos permite coletar informações sobre o desempenho do aplicativo e registros de falhas + Análises de Firebase + Idioma + Os links serão abertos nas abas personalizadas do Chrome + Usar abas personalizadas do Chrome + %1$s notificações push + Receber notificações quando uma atualização para o %1$s for lançado + Falha ao salvar o novo valor de tempo + Tempo de repouso do script root + Ajuste o valor do tempo de suspensão usado no script/data/adb/service.d/app.sh, útil para corrigir problemas de montagem + Padrão do sistema + Tema + Escuro + Claro + Centro de Atualizações + Não há novas atualizações + Variante - Não foi possível salvar os registros - Registros salvos com sucesso + Não foi possível salvar os registros + Registros salvos com sucesso Detalhes - %1$s arquivos de instalação detectados! - O gerenciador detectou que todos os arquivos necessários para a instalação de %1$s foram encontrados. Você quer instalar? + %1$s arquivos de instalação detectados! + O gerenciador detectou que todos os arquivos necessários para a instalação de %1$s foram encontrados. Você quer instalar? %1$s Preferências de Instalação - Verificando por atualizações… + Verificando por atualizações… Idioma(s): %1$s Tema: %1$s Versão: %1$s - Erro - Guia - Pare! + Erro + Guia + Pare! Você está usando a versão Magisk/TWRP do Vanced, que foi descontinuada e não pode ser atualizada com este aplicativo. Desinstale-o removendo o módulo em Magisk/usando o desinstalador TWRP Vanced. - Para instalar o Vanced, você PRECISA desligar as otimizações da MIUI nas opções de desenvolvedor. (Você pode ignorar esse aviso caso estiver usando uma ROM baseada na xiaomi.eu versão 20.2.20 ou superior) - Otimização MIUI está habilitada! - Por favor NÃO saia do aplicativo durante este processo! - Baixar novamente - Certifique-se de fazer o download do aplicativo em vancedapp.com, no servidor Vanced Discord ou no Vanced GitHub + Para instalar o Vanced, você PRECISA desligar as otimizações da MIUI nas opções de desenvolvedor. (Você pode ignorar esse aviso caso estiver usando uma ROM baseada na xiaomi.eu versão 20.2.20 ou superior) + Otimização MIUI está habilitada! + Por favor NÃO saia do aplicativo durante este processo! + Baixar novamente + Certifique-se de fazer o download do aplicativo em vancedapp.com, no servidor Vanced Discord ou no Vanced GitHub Versão - Bem-vindo + Bem-vindo - Escolha o seu idioma preferido para o Vanced - Mais recente + Escolha o seu idioma preferido para o Vanced + Mais recente Claro + %1$s Selecione pelo menos um idioma! - Preto - Escuro + Preto + Escuro - Desenvolvedores do Manager - Outros contribuidores - Fontes - Equipe Vanced + Desenvolvedores do Manager + Outros contribuidores + Fontes + Equipe Vanced - Falha ao enviar o Apk para o proprietário do sistema, Tente Novamente. - Erro ao baixar %1$s + Falha ao enviar o Apk para o proprietário do sistema, Tente Novamente. + Erro ao baixar %1$s Falha ao aplicar nova cor de destaque - Falha ao desinstalar o pacote %1$s - Falha ao localizar os arquivos necessários para instalação. Baixe novamente os arquivos de instalação e tente novamente. - Falha ao localizar o arquivo apk para o tema preto/escuro a partir do armazenamento, por favor tente novamente. - A instalação falhou porque o usuário abortou a instalação. - A instalação falhou porque o app está em conflito com um app já instalado. Desinstale a versão atual do aplicativo e tente novamente. - A instalação falhou porque o usuário tentou fazer o downgrade do pacote. Desinstale as atualizações do aplicativo padrão e tente novamente. - A instalação falhou por razões desconhecidas, junte-se ao nosso Telegram ou Discord para obter mais suporte. Por favor, anexe também uma captura de tela do menu Avançado - A instalação falhou porque o arquivo de instalação é incompatível com o seu dispositivo. Limpe os arquivos baixados nas configurações e tente novamente. - A instalação falhou porque os arquivos apk estão corrompidos, tente novamente. - A instalação falhou porque a Otimização MIUI está ativada. Desative a Otimização MIUI e tente novamente. - A instalação falhou porque a verificação de assinatura do apk está ativado. Desative a verificação de assinatura do apk e tente novamente. - A instalação falhou porque o dispositivo não tem espaço livre suficiente. - Falha ao encontrar o arquivo apk para o tema preto/escuro a partir do instalador. Limpe os \"dados do app\" do Manager e tente novamente. - Falha ao localizar o caminho de instalação padrão do YouTube após a instalação dividida (split). + Falha ao desinstalar o pacote %1$s + Falha ao localizar os arquivos necessários para instalação. Baixe novamente os arquivos de instalação e tente novamente. + Falha ao localizar o arquivo apk para o tema preto/escuro a partir do armazenamento, por favor tente novamente. + A instalação falhou porque o usuário abortou a instalação. + A instalação falhou porque o app está em conflito com um app já instalado. Desinstale a versão atual do aplicativo e tente novamente. + A instalação falhou porque o usuário tentou fazer o downgrade do pacote. Desinstale as atualizações do aplicativo padrão e tente novamente. + A instalação falhou por razões desconhecidas, junte-se ao nosso Telegram ou Discord para obter mais suporte. Por favor, anexe também uma captura de tela do menu Avançado + A instalação falhou porque o arquivo de instalação é incompatível com o seu dispositivo. Limpe os arquivos baixados nas configurações e tente novamente. + A instalação falhou porque os arquivos apk estão corrompidos, tente novamente. + A instalação falhou porque a Otimização MIUI está ativada. Desative a Otimização MIUI e tente novamente. + A instalação falhou porque a verificação de assinatura do apk está ativado. Desative a verificação de assinatura do apk e tente novamente. + A instalação falhou porque o dispositivo não tem espaço livre suficiente. + Falha ao encontrar o arquivo apk para o tema preto/escuro a partir do instalador. Limpe os \"dados do app\" do Manager e tente novamente. + Falha ao localizar o caminho de instalação padrão do YouTube após a instalação dividida (split). diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 68422acf26..6d46e171c6 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -1,120 +1,120 @@ - Cancelar - Fechar - Uma implementação personalizada de GMS para Vanced com base no projeto microG. - Um cliente modificado do YouTube com muitos recursos úteis! - Vanced, mas para o YouTube Music! Relativamente menos rico em recursos, mas atende às suas necessidades. - Resetar - Guardar - Selecione as suas aplicações + Cancelar + Fechar + Uma implementação personalizada de GMS para Vanced com base no projeto microG. + Um cliente modificado do YouTube com muitos recursos úteis! + Vanced, mas para o YouTube Music! Relativamente menos rico em recursos, mas atende às suas necessidades. + Resetar + Guardar + Selecione as suas aplicações - Sobre - Guia - Gestor - Registo de Eventos - Configurações - Gestor de Atualização + Sobre + Guia + Gestor + Registo de Eventos + Configurações + Gestor de Atualização - Seu Dispositivo Tem Root? - Conceder Permissão de Root - Vamos começar - Selecione pelo menos uma aplicação! - Não sabes o que é isto ou não queres utilizar a versão root? apenas clique a seta azul abaixo! + Seu Dispositivo Tem Root? + Conceder Permissão de Root + Vamos começar + Selecione pelo menos uma aplicação! + Não sabes o que é isto ou não queres utilizar a versão root? apenas clique a seta azul abaixo! - Acerca de %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - Aplicações - Lista de alterações - Transferindo %1$s - Instalar + Acerca de %1$s + Download + Info + Launch + Reinstall + Uninstall + Update + Aplicações + Lista de alterações + Transferindo %1$s + Instalar Mais Recente: - Instale o microG Vanced primeiro + Instale o microG Vanced primeiro Acesso root negado. - Redes Sociais - Suporte-nos - Indisponível + Redes Sociais + Suporte-nos + Indisponível Instalado: - Cor de Destaque - Aparência - Comportamento - Limpar ficheiros descarregados - Arquivos limpos com sucesso - Isto permite-nos recolher informações sobre o desempenho da aplicação e registos de falhas - Análise do Firebase - Idioma - Os links serão abertos em abas personalizadas do Chrome - Usar abas personalizadas do Chrome - Notificações Push %1$s - Receber notificações Push quando uma actualização para %1$s estiver disponível - Falhou ao salvar novo valor de tempo - Tempo de suspensão do script Root - Ajuste o valor de tempo de suspensão usado no script /data/adb/service.d/app.sh, útil para a correção de problemas de montagem - Padrão do sistema - Tema - Tema Escuro - Tema Claro - Centro de Actualizações - Sem atualizações - Variante + Cor de Destaque + Aparência + Comportamento + Limpar ficheiros descarregados + Arquivos limpos com sucesso + Isto permite-nos recolher informações sobre o desempenho da aplicação e registos de falhas + Análise do Firebase + Idioma + Os links serão abertos em abas personalizadas do Chrome + Usar abas personalizadas do Chrome + Notificações Push %1$s + Receber notificações Push quando uma actualização para %1$s estiver disponível + Falhou ao salvar novo valor de tempo + Tempo de suspensão do script Root + Ajuste o valor de tempo de suspensão usado no script /data/adb/service.d/app.sh, útil para a correção de problemas de montagem + Padrão do sistema + Tema + Tema Escuro + Tema Claro + Centro de Actualizações + Sem atualizações + Variante - Não foi possível salvar os registos - Registos salvos com sucesso + Não foi possível salvar os registos + Registos salvos com sucesso Detalhes - %1$s arquivos de instalação detetados! - O gestor detectou que todos os arquivos necessários para a instalação %1$s foram encontrados. Você quer instalá-lo? + %1$s arquivos de instalação detetados! + O gestor detectou que todos os arquivos necessários para a instalação %1$s foram encontrados. Você quer instalá-lo? Preferências de instalação %1$s - A procurar por atualizações… + A procurar por atualizações… Língua(s): %1$s Tema: %1$s Versão: %1$s - Erro - Guia - Parar! + Erro + Guia + Parar! Você está usando a versão Magisk/TWRP do Vanced, que está descontinuada e não pode ser atualizada usando este aplicativo. Por favor, remova-o removendo o módulo Magisk/usando a desinstalação TWRP Vanced Uninstaler. - Para instalar o Vanced, você DEVE desativar as Otimizações MIUI nas configurações do desenvolvedor. (Você pode ignorar este aviso se você estiver usando ROM baseada em 20.2.20 ou mais tarde xiaomi.eu) - Optimizações MIUI estão habilitadas! - Por favor NÃO saia do aplicativo durante este processo! - Voltar a descarregar - Certifique-se de que você baixou o aplicativo do vancedapp.com, o servidor Vanced Discord ou o Vanced GitHub + Para instalar o Vanced, você DEVE desativar as Otimizações MIUI nas configurações do desenvolvedor. (Você pode ignorar este aviso se você estiver usando ROM baseada em 20.2.20 ou mais tarde xiaomi.eu) + Optimizações MIUI estão habilitadas! + Por favor NÃO saia do aplicativo durante este processo! + Voltar a descarregar + Certifique-se de que você baixou o aplicativo do vancedapp.com, o servidor Vanced Discord ou o Vanced GitHub Versão - Bem-Vindo + Bem-Vindo - Escolha a(s) sua(s) língua(s) de preferência para o Vanced - Mais Recente + Escolha a(s) sua(s) língua(s) de preferência para o Vanced + Mais Recente Claro + %1$s Selecione ao menos um idioma! - Preto - Escuro + Preto + Escuro - Desenvolvedores do Manager - Outros Colaboradores - Fontes - Equipa Vanced + Desenvolvedores do Manager + Outros Colaboradores + Fontes + Equipa Vanced - Falhou na mudança de dono do Apk para o proprietário do sistema, por favor, tente novamente. - Erro Transferindo %1$s + Falhou na mudança de dono do Apk para o proprietário do sistema, por favor, tente novamente. + Erro Transferindo %1$s Falha ao aplicar nova cor de destaque - Erro a desinstalar pacote %1$s - Falha ao localizar os arquivos necessários para instalação. Faça o download dos arquivos de instalação e tente novamente. - Falha ao localizar o apk para o tema preto/escuro no armazenamento, por favor, tente novamente. - A instalação falhou porque o usuário abortou a instalação. - A instalação falhou porque o app entra em conflito com um app já instalado. Desinstale a versão atual do app e tente novamente. - A instalação falhou porque o usuário tentou fazer o downgrade do pacote. Desinstale as atualizações do app do YouTube e, em seguida, tente novamente. - A instalação falhou por razões desconhecidas, junte-se ao nosso Telegram ou Discord para mais suporte. Por favor, anexe também uma captura de tela do menu Avançado - Falha na instalação porque o pacote de instalação é incompatível com o seu dispositivo. Limpe os pacotes transferidos nas Configurações e tente novamente. - A instalação falhou porque os pacotes apk estão corrompidos, por favor tente novamente. - A instalação falhou porque a Otimização MIUI está ativada. Desative a Otimização MIUI e tente novamente. - A instalação falhou porque a verificação de assinatura apk está ativa. Desative a verificação de assinatura apk e tente novamente. - A instalação falhou porque o dispositivo não tem espaço livre suficiente. - Falha ao encontrar o arquivo apk para o tema preto/escuro no instalador. Limpe os dados do app do Gerenciador (Vanced Manager) e tente novamente. - Falha ao localizar o caminho de instalação padrão do YouTube após instalação dividida. + Erro a desinstalar pacote %1$s + Falha ao localizar os arquivos necessários para instalação. Faça o download dos arquivos de instalação e tente novamente. + Falha ao localizar o apk para o tema preto/escuro no armazenamento, por favor, tente novamente. + A instalação falhou porque o usuário abortou a instalação. + A instalação falhou porque o app entra em conflito com um app já instalado. Desinstale a versão atual do app e tente novamente. + A instalação falhou porque o usuário tentou fazer o downgrade do pacote. Desinstale as atualizações do app do YouTube e, em seguida, tente novamente. + A instalação falhou por razões desconhecidas, junte-se ao nosso Telegram ou Discord para mais suporte. Por favor, anexe também uma captura de tela do menu Avançado + Falha na instalação porque o pacote de instalação é incompatível com o seu dispositivo. Limpe os pacotes transferidos nas Configurações e tente novamente. + A instalação falhou porque os pacotes apk estão corrompidos, por favor tente novamente. + A instalação falhou porque a Otimização MIUI está ativada. Desative a Otimização MIUI e tente novamente. + A instalação falhou porque a verificação de assinatura apk está ativa. Desative a verificação de assinatura apk e tente novamente. + A instalação falhou porque o dispositivo não tem espaço livre suficiente. + Falha ao encontrar o arquivo apk para o tema preto/escuro no instalador. Limpe os dados do app do Gerenciador (Vanced Manager) e tente novamente. + Falha ao localizar o caminho de instalação padrão do YouTube após instalação dividida. diff --git a/app/src/main/res/values-ro-rRO/strings.xml b/app/src/main/res/values-ro-rRO/strings.xml index 636d4c07d6..40a6cfa1ac 100644 --- a/app/src/main/res/values-ro-rRO/strings.xml +++ b/app/src/main/res/values-ro-rRO/strings.xml @@ -1,120 +1,120 @@ - Anulaţi - Închide - O implementare personalizată a GMS pentru Vanced pe baza proiectului microG. - Un client YouTube modificat, cu multe caracteristici utile! - Vansat, dar pentru muzica YouTube! Relativ mai puțin bogat în caracteristici, dar îți îndeplinește nevoile. - Resetează - Salvează - Selectați aplicațiile + Anulaţi + Închide + O implementare personalizată a GMS pentru Vanced pe baza proiectului microG. + Un client YouTube modificat, cu multe caracteristici utile! + Vansat, dar pentru muzica YouTube! Relativ mai puțin bogat în caracteristici, dar îți îndeplinește nevoile. + Resetează + Salvează + Selectați aplicațiile - Despre - Ghid - Manager - Jurnale - Configurări - Actualizați Manager + Despre + Ghid + Manager + Jurnale + Configurări + Actualizați Manager - Dispozitivul tău este rootat? - Acordați permisiunea Root - Să începem - Selectaţi cel puţin o aplicație! - Nu știți ce este sau nu vreți să folosiți versiunea root? Apăsați săgeata albastră de mai jos! + Dispozitivul tău este rootat? + Acordați permisiunea Root + Să începem + Selectaţi cel puţin o aplicație! + Nu știți ce este sau nu vreți să folosiți versiunea root? Apăsați săgeata albastră de mai jos! - Despre %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - Aplicații - Schimbări - Se descarcă %1$s - Instalează + Despre %1$s + Download + Info + Launch + Reinstall + Uninstall + Update + Aplicații + Schimbări + Se descarcă %1$s + Instalează Ultima: - Instalați Vanced microG mai întâi + Instalați Vanced microG mai întâi Accesul root nu este permis - Rețele sociale - Ajutați-ne - Indisponibil + Rețele sociale + Ajutați-ne + Indisponibil Instalat: - Nuanță culoare - Aspect - Comportament - Ştergeţi fişierele descărcate - Fişiere şterse cu succes - Acest lucru ne permite să colectăm informații despre performanța aplicației și jurnale de eroare - Statistici Firebase - Limbă - Link-uri se vor deschide în filele personalizate Chrome - Utilizează file personalizate Chrome - %1$s Notificari push - Primiți notificări push când o actualizare pentru %1$s este lansată - Salvarea noii valori de timp a eșuat - După cât timp se activează script-ul root - Reglați după cât timp este activat script-ul root folosit în /data/adb/service.d/app.sh script, util pentru remedierea problemelor de montare - Setarea implicită a sistemului - Temă - Temă întunecată - Temă deschisă - Actualizator - Nu există actualizări noi - Variantă + Nuanță culoare + Aspect + Comportament + Ştergeţi fişierele descărcate + Fişiere şterse cu succes + Acest lucru ne permite să colectăm informații despre performanța aplicației și jurnale de eroare + Statistici Firebase + Limbă + Link-uri se vor deschide în filele personalizate Chrome + Utilizează file personalizate Chrome + %1$s Notificari push + Primiți notificări push când o actualizare pentru %1$s este lansată + Salvarea noii valori de timp a eșuat + După cât timp se activează script-ul root + Reglați după cât timp este activat script-ul root folosit în /data/adb/service.d/app.sh script, util pentru remedierea problemelor de montare + Setarea implicită a sistemului + Temă + Temă întunecată + Temă deschisă + Actualizator + Nu există actualizări noi + Variantă - Jurnalele nu pot fi salvate - Jurnale salvate cu succes + Jurnalele nu pot fi salvate + Jurnale salvate cu succes Detalii - %1$s fișiere de instalare detectate! - Manager a detectat că au fost găsite toate fişierele necesare pentru instalarea %1$s . Doriţi să le instalaţi? + %1$s fișiere de instalare detectate! + Manager a detectat că au fost găsite toate fişierele necesare pentru instalarea %1$s . Doriţi să le instalaţi? %1$s Preferințe de instalare - Verificare actualizări… + Verificare actualizări… Limbă: %1$s Temă: %1$s Versiune: %1$s - Eroare - Ghid - Oprește! + Eroare + Ghid + Oprește! Folosiți versiunea Magisk/TWRP a Vanced, care nu mai este în uz și nu poate fi actualizată folosind această aplicație. Vă rugăm să o eliminați prin eliminarea modulului Magisk/folosind dezinstalatorul Vanced TWRP. - Pentru a instala Vanced, TREBUIE să dezactivați Optimizările MIUI în setările pentru dezvoltatori. (Puteți ignora această avertizare dacă utilizați un ROM bazat pe xiaomi.eu cu versiunea 20.2.20 sau mai recent) - Optimizările MIUI sunt activate! - Vă rugăm să NU ieșiți din aplicație în timpul acestui proces! - Redescărcare - Asigurați-vă că ați descărcat aplicația de pe vancedapp.com, de pe serverul Discord Vanced sau de pe GitHub Vanced + Pentru a instala Vanced, TREBUIE să dezactivați Optimizările MIUI în setările pentru dezvoltatori. (Puteți ignora această avertizare dacă utilizați un ROM bazat pe xiaomi.eu cu versiunea 20.2.20 sau mai recent) + Optimizările MIUI sunt activate! + Vă rugăm să NU ieșiți din aplicație în timpul acestui proces! + Redescărcare + Asigurați-vă că ați descărcat aplicația de pe vancedapp.com, de pe serverul Discord Vanced sau de pe GitHub Vanced Versiune - Bun venit + Bun venit - Alegeți limba preferată pentru Vanced - Cel mai recent + Alegeți limba preferată pentru Vanced + Cel mai recent Alb + %1$s Selectaţi cel puţin o limbă! - Negru - Întunecat + Negru + Întunecat - Dezvoltatori - Alți Contribuitori - Surse - Echipa Vanced + Dezvoltatori + Alți Contribuitori + Surse + Echipa Vanced - Nu s-a reușit comanda chown pentru APK la proprietarul sistemului. Încercați din nou. - Eroare la descărcarea %1$s + Nu s-a reușit comanda chown pentru APK la proprietarul sistemului. Încercați din nou. + Eroare la descărcarea %1$s Nu s-a putut aplica noua culoare de evidențiere - Dezinstalarea pachetului %1$s a eșuat - Nu s-a reușit localizarea fișierelor necesare pentru instalare. Redescărcați fișierele de instalare, apoi încercați din nou. - Nu s-a reuşit localizarea fişierului apk pentru tema neagră/întunecată din stocare, vă rugăm să încercaţi din nou. - Instalarea a eșuat deoarece utilizatorul a anulat instalarea. - Instalarea a eșuat deoarece aplicația intră în conflict cu o aplicație deja instalată. Dezinstalați versiunea curentă a aplicației, apoi încercați din nou. - Instalarea a eșuat deoarece utilizatorul a încercat să retrogradeze pachetul. Dezinstalați actualizările din aplicația stock YouTube, apoi încercați din nou. - Instalarea a eșuat din motive necunoscute. Pentru asistență, intră pe grupul nostru de Telegram sau Discord. Te rugăm să atașezi și o captură de ecran din meniul Avansat - Instalarea a eșuat deoarece fișierul de instalare este incompatibil cu dispozitivul dvs. Ștergeți fișierele descărcate din Setări, apoi încercați din nou. - Instalarea a eșuat deoarece fișierele apk sunt corupte, încercați din nou. - Instalarea a eșuat deoarece este activată optimizarea MIUI. Dezactivați optimizarea MIUI, apoi încercați din nou. - Instalarea a eșuat deoarece verificarea semnăturii apk este activată. Dezactivați verificarea semnăturii apk, apoi încercați din nou. - Instalarea a eșuat deoarece dispozitivul nu are suficient spațiu liber. - Nu s-a putut găsi fișierul apk pentru tema neagră/întunecată din instalator. Ștergeți datele aplicației Manager, apoi încercați din nou. - Localizarea instalarii YouTube-ului stock a eșuat dupa instalarea divizată. + Dezinstalarea pachetului %1$s a eșuat + Nu s-a reușit localizarea fișierelor necesare pentru instalare. Redescărcați fișierele de instalare, apoi încercați din nou. + Nu s-a reuşit localizarea fişierului apk pentru tema neagră/întunecată din stocare, vă rugăm să încercaţi din nou. + Instalarea a eșuat deoarece utilizatorul a anulat instalarea. + Instalarea a eșuat deoarece aplicația intră în conflict cu o aplicație deja instalată. Dezinstalați versiunea curentă a aplicației, apoi încercați din nou. + Instalarea a eșuat deoarece utilizatorul a încercat să retrogradeze pachetul. Dezinstalați actualizările din aplicația stock YouTube, apoi încercați din nou. + Instalarea a eșuat din motive necunoscute. Pentru asistență, intră pe grupul nostru de Telegram sau Discord. Te rugăm să atașezi și o captură de ecran din meniul Avansat + Instalarea a eșuat deoarece fișierul de instalare este incompatibil cu dispozitivul dvs. Ștergeți fișierele descărcate din Setări, apoi încercați din nou. + Instalarea a eșuat deoarece fișierele apk sunt corupte, încercați din nou. + Instalarea a eșuat deoarece este activată optimizarea MIUI. Dezactivați optimizarea MIUI, apoi încercați din nou. + Instalarea a eșuat deoarece verificarea semnăturii apk este activată. Dezactivați verificarea semnăturii apk, apoi încercați din nou. + Instalarea a eșuat deoarece dispozitivul nu are suficient spațiu liber. + Nu s-a putut găsi fișierul apk pentru tema neagră/întunecată din instalator. Ștergeți datele aplicației Manager, apoi încercați din nou. + Localizarea instalarii YouTube-ului stock a eșuat dupa instalarea divizată. diff --git a/app/src/main/res/values-ru-rRU/strings.xml b/app/src/main/res/values-ru-rRU/strings.xml index 93ac21a436..8fc09dfcb4 100644 --- a/app/src/main/res/values-ru-rRU/strings.xml +++ b/app/src/main/res/values-ru-rRU/strings.xml @@ -1,120 +1,120 @@ - Отмена - Закрыть - Пользовательская реализация GMS (сервисов Google) для Vanced создана на основе microG. - Модифицированный клиент YouTube с массой полезных функций! - Vanced, но для YouTube Music! Относительно меньше возможностей, но удовлетворит ваши потребности. - Сброс - Сохранить - Выберите ваши приложения + Отмена + Закрыть + Пользовательская реализация GMS (сервисов Google) для Vanced создана на основе microG. + Модифицированный клиент YouTube с массой полезных функций! + Vanced, но для YouTube Music! Относительно меньше возможностей, но удовлетворит ваши потребности. + Сброс + Сохранить + Выберите ваши приложения - О нас - Руководство - Менеджер - Логи - Настройки - Обновить Менеджер + О нас + Руководство + Менеджер + Логи + Настройки + Обновить Менеджер - На устройстве есть рут-права? - Предоставить root-права - Давайте приступим - Выберите хотя бы одно приложение! - Не знаете, что это, или не хотите использовать рут версию? Просто нажмите на синюю стрелку ниже! + На устройстве есть рут-права? + Предоставить root-права + Давайте приступим + Выберите хотя бы одно приложение! + Не знаете, что это, или не хотите использовать рут версию? Просто нажмите на синюю стрелку ниже! - О %1$s - Скачать - Информация - Запустить - Переустановить - Удалить - Обновить - Приложения - Список изменений - Загрузка %1$s - Установить + О %1$s + Скачать + Информация + Запустить + Переустановить + Удалить + Обновить + Приложения + Список изменений + Загрузка %1$s + Установить Последняя: - Сначала установите Vanced microG + Сначала установите Vanced microG Рут-доступ не предоставлен - Социальные сети - Поддержите нас - Недоступно + Социальные сети + Поддержите нас + Недоступно Установлена: - Второстепенный цвет - Оформление - Поведение - Удалить загруженные файлы - Файлы успешно удалены - Это позволяет нам собирать информацию о производительности приложения и журналы сбоев - Аналитика Firebase - Язык - Открывать ссылки в Chrome Custom Tabs - Использовать Chrome Custom Tabs - Push Уведомления для %1$s - Получать уведомления о выходе обновления для %1$s - Не удалось сохранить новое значение времени - Скрипт Таймера сна - Настройка значения времени сна, используемого в скрипте /data/adb/service.d/app.sh, полезно для решения проблем монтирования - Как в системе - Тема оформления - Тёмная тема - Светлая тема - Центр обновлений - Обновлений не найдено - Вариант + Второстепенный цвет + Оформление + Поведение + Удалить загруженные файлы + Файлы успешно удалены + Это позволяет нам собирать информацию о производительности приложения и журналы сбоев + Аналитика Firebase + Язык + Открывать ссылки в Chrome Custom Tabs + Использовать Chrome Custom Tabs + Push Уведомления для %1$s + Получать уведомления о выходе обновления для %1$s + Не удалось сохранить новое значение времени + Скрипт Таймера сна + Настройка значения времени сна, используемого в скрипте /data/adb/service.d/app.sh, полезно для решения проблем монтирования + Как в системе + Тема оформления + Тёмная тема + Светлая тема + Центр обновлений + Обновлений не найдено + Вариант - Не удалось сохранить логи - Логи успешно сохранены + Не удалось сохранить логи + Логи успешно сохранены Подробнее - Обнаружены установочные файлы для %1$s! - Менеджер обнаружил все необходимые файлы для установки %1$s. Продолжить установку? + Обнаружены установочные файлы для %1$s! + Менеджер обнаружил все необходимые файлы для установки %1$s. Продолжить установку? Параметры установки %1$s - Проверка обновлений… + Проверка обновлений… Язык(и): %1$s Тема: %1$s Версия: %1$s - Ошибка - Руководство - Стойте! + Ошибка + Руководство + Стойте! Похоже, вы используете Magisk/TWRP версию Vanced, которая больше не поддерживается и не может быть обновлена с помощью этого приложения. Пожалуйста, удалите модуль Vanced через Magisk или с помощью деинсталлятора Vanced для TWRP. - Чтобы установить Vanced, вы ДОЛЖНЫ отключить оптимизацию MIUI в настройках разработчика. (Вы можете проигнорировать это предупреждение, если вы используете прошивку на xiaomi.eu версии 20.2.20+) - Оптимизация MIUI включена! - Пожалуйста, НЕ выходите из приложения в течение этого процесса! - Скачать заново - Пожалуйста, убедитесь, что вы скачали это приложение с vancedapp.com, сервера Vanced в Discord или с официального GitHub + Чтобы установить Vanced, вы ДОЛЖНЫ отключить оптимизацию MIUI в настройках разработчика. (Вы можете проигнорировать это предупреждение, если вы используете прошивку на xiaomi.eu версии 20.2.20+) + Оптимизация MIUI включена! + Пожалуйста, НЕ выходите из приложения в течение этого процесса! + Скачать заново + Пожалуйста, убедитесь, что вы скачали это приложение с vancedapp.com, сервера Vanced в Discord или с официального GitHub Версия - Добро пожаловать + Добро пожаловать - Выберите предпочитаемый язык для Vanced - Последняя + Выберите предпочитаемый язык для Vanced + Последняя Светлая + %1$s Выберите хотя бы один язык! - Черный - Темный + Черный + Темный - Разработчики Менеджера - Другие участники - Исходники - Команда Vanced + Разработчики Менеджера + Другие участники + Исходники + Команда Vanced - Не удалось передать apk владельцу системы, попробуйте еще раз. - Ошибка загрузки %1$s + Не удалось передать apk владельцу системы, попробуйте еще раз. + Ошибка загрузки %1$s Не удалось применить новый второстепенный цвет - Ошибка установки пакета %1$s - Не удалось найти необходимые файлы для установки. Повторно загрузите установочные файлы и попробуйте еще раз. - Не удалось найти apk-файл для черной/темной темы в памяти устройства, повторите попытку. - Установка не была выполнена, поскольку пользователь прервал установку. - Установка не удалась, так как приложение конфликтует с уже установленным приложением. Удалите текущую версию приложения, затем повторите попытку. - Установка не удалась, так как пользователь попытался понизить версию приложения. Удалите обновления обычного приложения YouTube, затем повторите попытку. - Установка не удалась по неизвестным причинам, присоединитесь к нашим каналам Telegram или Discord для дальнейшей поддержки. Пожалуйста, также прикрепите скриншот из расширенного меню - Установка не удалась, так как установочный файл несовместим с вашим устройством. Очистите загруженные файлы в настройках, затем повторите попытку. - Установка не удалась, так как установочные файлы повреждены, попробуйте еще раз. - Установка не удалась, так как включена Оптимизация MIUI. Отключите Оптимизацию MIUI, затем повторите попытку. - Установка не удалась, так как включена проверка подписи apk. Отключите проверку подписи apk, а затем повторите попытку. - Установка не удалась из-за отсутствия на устройстве свободного места. - Не удалось найти apk-файл для черной/темной темы в программе установки. Удалите данные приложения из Менеджера и повторите попытку. - Не удалось найти стандартный путь установки YouTube после раздельной установки. + Ошибка установки пакета %1$s + Не удалось найти необходимые файлы для установки. Повторно загрузите установочные файлы и попробуйте еще раз. + Не удалось найти apk-файл для черной/темной темы в памяти устройства, повторите попытку. + Установка не была выполнена, поскольку пользователь прервал установку. + Установка не удалась, так как приложение конфликтует с уже установленным приложением. Удалите текущую версию приложения, затем повторите попытку. + Установка не удалась, так как пользователь попытался понизить версию приложения. Удалите обновления обычного приложения YouTube, затем повторите попытку. + Установка не удалась по неизвестным причинам, присоединитесь к нашим каналам Telegram или Discord для дальнейшей поддержки. Пожалуйста, также прикрепите скриншот из расширенного меню + Установка не удалась, так как установочный файл несовместим с вашим устройством. Очистите загруженные файлы в настройках, затем повторите попытку. + Установка не удалась, так как установочные файлы повреждены, попробуйте еще раз. + Установка не удалась, так как включена Оптимизация MIUI. Отключите Оптимизацию MIUI, затем повторите попытку. + Установка не удалась, так как включена проверка подписи apk. Отключите проверку подписи apk, а затем повторите попытку. + Установка не удалась из-за отсутствия на устройстве свободного места. + Не удалось найти apk-файл для черной/темной темы в программе установки. Удалите данные приложения из Менеджера и повторите попытку. + Не удалось найти стандартный путь установки YouTube после раздельной установки. diff --git a/app/src/main/res/values-si-rLK/strings.xml b/app/src/main/res/values-si-rLK/strings.xml index 1a889ce6ef..d4dee3adcd 100644 --- a/app/src/main/res/values-si-rLK/strings.xml +++ b/app/src/main/res/values-si-rLK/strings.xml @@ -1,120 +1,120 @@ - අවලංගු කරන්න - වසන්න - A custom GMS Implementation for Vanced based on the microG Project. - A modified YouTube client with many useful features! - Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. - ප්‍රතිස්ථාපනය කරන්න - සුරකින්න - ඔබගේ යෙදුම් තෝරන්න + අවලංගු කරන්න + වසන්න + A custom GMS Implementation for Vanced based on the microG Project. + A modified YouTube client with many useful features! + Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. + ප්‍රතිස්ථාපනය කරන්න + සුරකින්න + ඔබගේ යෙදුම් තෝරන්න - මේ ගැන - Guide - Manager - Logs - සැකසුම් - Update Manager + මේ ගැන + Guide + Manager + Logs + සැකසුම් + Update Manager - Is Your Device Rooted? - Grant Root Permission - Let\'s get started - Select at least one app! - Don\'t know what this is or don\'t want to use the root version? just click the blue arrow below! + Is Your Device Rooted? + Grant Root Permission + Let\'s get started + Select at least one app! + Don\'t know what this is or don\'t want to use the root version? just click the blue arrow below! - About %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - Apps - Changelog - Downloading %1$s - ස්ථාපනය + About %1$s + Download + Info + Launch + Reinstall + Uninstall + Update + Apps + Changelog + Downloading %1$s + ස්ථාපනය අලුත් - Install Vanced microG first + Install Vanced microG first මූල ප්‍රවේශය ලබා දී නොමැත - Social Media - Support us - නොමැත + Social Media + Support us + නොමැත ස්ථාපනය: - අනෙක් වර්ණය - Appearance - Behavior - Clear downloaded files - Successfully cleared files - This lets us collect information about app performance and crash logs - Firebase Analytics - භාෂාව - Links will open in Chrome Custom Tabs - Use Chrome Custom Tabs - %1$s Push Notifications - Receive push notifications when an update for %1$s is released - Failed to save new time value - Root Script Sleep Time - Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues - System Default - තේමාව - අඳුරු තේමාව - Light Theme - Manager Update Center - No new updates - Variant + අනෙක් වර්ණය + Appearance + Behavior + Clear downloaded files + Successfully cleared files + This lets us collect information about app performance and crash logs + Firebase Analytics + භාෂාව + Links will open in Chrome Custom Tabs + Use Chrome Custom Tabs + %1$s Push Notifications + Receive push notifications when an update for %1$s is released + Failed to save new time value + Root Script Sleep Time + Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues + System Default + තේමාව + අඳුරු තේමාව + Light Theme + Manager Update Center + No new updates + Variant - Could not save logs - Successfully saved logs + Could not save logs + Successfully saved logs Details - %1$s installation files detected! - Manager detected that all necessary files for %1$s installation were found. Do you want to install it? + %1$s installation files detected! + Manager detected that all necessary files for %1$s installation were found. Do you want to install it? %1$s Installation Preferences - Checking for updates… + Checking for updates… Language(s): %1$s Theme: %1$s Version: %1$s - දෝෂය - මාර්ගෝපදේශය - නවත්වන්න! + දෝෂය + මාර්ගෝපදේශය + නවත්වන්න! You are using the Magisk/TWRP version of Vanced, which is discontinued and cannot be updated using this app. Please remove it by removing the Magisk module/using TWRP Vanced uninstaller. - To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) - MIUI Optimizations are enabled! - Please do NOT exit the app during this process! - Redownload - Make sure that you downloaded the app from vancedapp.com, the Vanced Discord server, or the Vanced GitHub + To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) + MIUI Optimizations are enabled! + Please do NOT exit the app during this process! + Redownload + Make sure that you downloaded the app from vancedapp.com, the Vanced Discord server, or the Vanced GitHub අනුවාදය - ආයුබෝවන් + ආයුබෝවන් - Choose your preferred language(s) for Vanced - Latest + Choose your preferred language(s) for Vanced + Latest Light + %1$s Select at least one language! - Black - Dark + Black + Dark - Manager Devs - Other Contributors - මූලාශ්‍ර - Vanced Team + Manager Devs + Other Contributors + මූලාශ්‍ර + Vanced Team - Failed to `chown` APK to system owner, please try again. - Error Downloading %1$s + Failed to `chown` APK to system owner, please try again. + Error Downloading %1$s Failed to apply new accent color - Failed to uninstall package %1$s - Failed to locate the required files for installation. Re-download the installation files, then try again. - Failed to locate apk file for black/dark theme from storage, please try again. - Installation failed because the user aborted the installation. - Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. - Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. - Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu - Installation failed because the installation file is incompatible with your device. Clear downloaded files in the Settings, then try again. - Installation failed because the apk files are corrupted, please try again. - Installation failed because MIUI Optimization is enabled. Disable MIUI Optimization, then try again. - Installation failed because apk signature verification is enabled. Disable apk signature verification, then try again. - Installation failed because the device doesn\'t have enough free space. - Failed to find apk file for black/dark theme from the installer. Clear app data of Manager, then try again. - Failed to locate the stock YouTube installation path after split installation. + Failed to uninstall package %1$s + Failed to locate the required files for installation. Re-download the installation files, then try again. + Failed to locate apk file for black/dark theme from storage, please try again. + Installation failed because the user aborted the installation. + Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. + Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. + Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu + Installation failed because the installation file is incompatible with your device. Clear downloaded files in the Settings, then try again. + Installation failed because the apk files are corrupted, please try again. + Installation failed because MIUI Optimization is enabled. Disable MIUI Optimization, then try again. + Installation failed because apk signature verification is enabled. Disable apk signature verification, then try again. + Installation failed because the device doesn\'t have enough free space. + Failed to find apk file for black/dark theme from the installer. Clear app data of Manager, then try again. + Failed to locate the stock YouTube installation path after split installation. diff --git a/app/src/main/res/values-sk-rSK/strings.xml b/app/src/main/res/values-sk-rSK/strings.xml index 536233c919..8ad6999e60 100644 --- a/app/src/main/res/values-sk-rSK/strings.xml +++ b/app/src/main/res/values-sk-rSK/strings.xml @@ -1,120 +1,120 @@ - Zrušiť - Zavrieť - Vlastná implementácia GMS pre Vanced založená na projekte microG. - Upravený YouTube klient s mnohými užitočnými funkciami! - Vanced, ale YouTube Music! Obsahuje o trochu menej funkcií, ale splní vaše potreby. - Resetovať - Uložiť - Vyberte svoje aplikácie + Zrušiť + Zavrieť + Vlastná implementácia GMS pre Vanced založená na projekte microG. + Upravený YouTube klient s mnohými užitočnými funkciami! + Vanced, ale YouTube Music! Obsahuje o trochu menej funkcií, ale splní vaše potreby. + Resetovať + Uložiť + Vyberte svoje aplikácie - O aplikácií - Sprievodca - Manažér - Logy - Nastavenia - Aktualizovať Manažéra + O aplikácií + Sprievodca + Manažér + Logy + Nastavenia + Aktualizovať Manažéra - Má vaše zariadenie oprávnenie root? - Udeliť oprávnenie root - Začnime - Vyberte aspoň jednu aplikáciu! - Neviete, čo to je alebo nechcete používať verziu s prístupom root? Stačí kliknúť na modrú šípku dole! + Má vaše zariadenie oprávnenie root? + Udeliť oprávnenie root + Začnime + Vyberte aspoň jednu aplikáciu! + Neviete, čo to je alebo nechcete používať verziu s prístupom root? Stačí kliknúť na modrú šípku dole! - O aplikácií %1$s - Stiahnuť - Informácie - Spustiť - Preinštalovať - Odinštalovať - Aktualizovať - Aplikácie - Zoznam zmien - Sťahovanie %1$s - Inštalovať + O aplikácií %1$s + Stiahnuť + Informácie + Spustiť + Preinštalovať + Odinštalovať + Aktualizovať + Aplikácie + Zoznam zmien + Sťahovanie %1$s + Inštalovať Najnovšie: - Najprv nainštalujte Vanced microG + Najprv nainštalujte Vanced microG Root prístup nebol udelený - Sociálne médiá - Podporte nás - Nedostupné + Sociálne médiá + Podporte nás + Nedostupné Nainštalované: - Sekundárna farba - Vzhľad - Správanie - Vymazať stiahnuté súbory - Súbory boli úspešne vymazané - Toto nám umožňuje zhromažďovať informácie o výkone aplikácie a logy o zlyhaní - Firebase Analytics - Jazyk - Odkazy sa otvoria na vlastných kartách prehliadača Chrome - Používať vlastné karty prehliadača Chrome - %1$s Vyskakovacie oznámenia - Dostávať upozornenia ak je dostupná aktualizácia pre %1$s - Nepodarilo sa uložiť novú hodnotu času - Doba nečinnosti root skriptu - Upravte hodnotu doby nečinnosti použitú v skripte /data/adb/service.d/app.sh, ktorá je užitočná na riešenie problémov s pripojením - Systémovo predvolené - Téma - Tmavá téma - Svetlá téma - Centrum aktualizácií - Žiadne nové aktualizácie - Varianta + Sekundárna farba + Vzhľad + Správanie + Vymazať stiahnuté súbory + Súbory boli úspešne vymazané + Toto nám umožňuje zhromažďovať informácie o výkone aplikácie a logy o zlyhaní + Firebase Analytics + Jazyk + Odkazy sa otvoria na vlastných kartách prehliadača Chrome + Používať vlastné karty prehliadača Chrome + %1$s Vyskakovacie oznámenia + Dostávať upozornenia ak je dostupná aktualizácia pre %1$s + Nepodarilo sa uložiť novú hodnotu času + Doba nečinnosti root skriptu + Upravte hodnotu doby nečinnosti použitú v skripte /data/adb/service.d/app.sh, ktorá je užitočná na riešenie problémov s pripojením + Systémovo predvolené + Téma + Tmavá téma + Svetlá téma + Centrum aktualizácií + Žiadne nové aktualizácie + Varianta - Logy nebolo možné uložiť - Logy boli úspešne uložené + Logy nebolo možné uložiť + Logy boli úspešne uložené Podrobnosti - Nájdených %1$s inštalačných súborov! - Manažér zistil, že všetky potrebné súbory na inštaláciu aplikácie %1$s boli nájdené. Prajete si spustiť inštaláciu? + Nájdených %1$s inštalačných súborov! + Manažér zistil, že všetky potrebné súbory na inštaláciu aplikácie %1$s boli nájdené. Prajete si spustiť inštaláciu? %1$s Predvoľby inštalácie - Kontrola aktualizácií… + Kontrola aktualizácií… Jazyk(y): %1$s Téma: %1$s Verzia: %1$s - Chyba - Sprievodca - Zadržte! + Chyba + Sprievodca + Zadržte! Používate verziu Vanced pre Magisk/TWRP, ktorej vývoj bol ukončený, a ktorú nie je možno pomocou tejto aplikácie aktualizovať. Odstráňte ju prosím odobraním modulu Magisk/použitím TWRP Vanced odinštalátora. - Ak chcete nainštalovať Vanced, MUSÍTE deaktivovať optimalizáciu MIUI v nastaveniach pre vývojárov. (Toto varovanie môžete ignorovať, ak používate ROM 20.2.20 alebo novšiu, založenú na xiaomi.eu) - Optimalizácie MIUI sú zapnuté! - Počas tohto procesu NEODCHÁDZAJTE z aplikácie! - Stiahnuť znova - Uistite sa, že ste si aplikáciu stiahli zo stránky vancedapp.com, servera Vanced Discord alebo Vanced GitHub + Ak chcete nainštalovať Vanced, MUSÍTE deaktivovať optimalizáciu MIUI v nastaveniach pre vývojárov. (Toto varovanie môžete ignorovať, ak používate ROM 20.2.20 alebo novšiu, založenú na xiaomi.eu) + Optimalizácie MIUI sú zapnuté! + Počas tohto procesu NEODCHÁDZAJTE z aplikácie! + Stiahnuť znova + Uistite sa, že ste si aplikáciu stiahli zo stránky vancedapp.com, servera Vanced Discord alebo Vanced GitHub Verzia - Vitajte + Vitajte - Vyberte si jeden alebo viac preferovaných jazykov pre Vanced - Najnovšie + Vyberte si jeden alebo viac preferovaných jazykov pre Vanced + Najnovšie Svetlý + %1$s Vyberte aspoň jeden jazyk! - Čierna - Tmavá + Čierna + Tmavá - Vývojári aplikácie - Ostatní prispievatelia - Zdrojové kódy - Tím Vanced + Vývojári aplikácie + Ostatní prispievatelia + Zdrojové kódy + Tím Vanced - Nepodarilo sa zmeniť vlastníka súboru APK na vlastníka systému. Skúste to znovu prosím. - Chyba pri sťahovaní %1$s + Nepodarilo sa zmeniť vlastníka súboru APK na vlastníka systému. Skúste to znovu prosím. + Chyba pri sťahovaní %1$s Nepodarilo sa nastaviť novú sekundárnu farbu - Nepodarilo sa odinštalovať balíček %1$s - Nepodarilo sa nájsť požadované súbory na inštaláciu. Opätovne stiahnite inštalačné súbory a skúste to znova. - V lokálnom úložisku sa nepodarilo nájsť APK súbor pre čiernu/tmavú tému. Skúste to znovu prosím. - Inštalácia zlyhala, kvôli zrušeniu užívateľom. - Inštalácia zlyhala, pretože aplikácia je v konflikte s už nainštalovanou aplikáciou. Odinštalujte aktuálnu verziu aplikácie a potom to skúste znova. - Inštalácia zlyhala, pretože užívateľ sa pokúsil downgradovať balík. Odinštalujte aktualizácie z pôvodnej aplikácie a potom to skúste znova. - Inštalácia zlyhala z neznámych dôvodov. Pre poskytnutie podpory sa pripojte sa k nášmu Telegramu alebo Discordu. Pripojte tiež snímky obrazovky z ponuky Pokročilé - Inštalácia zlyhala, pretože inštalačný súbor nie je kompatibilný s vaším zariadením. V Nastaveniach vymažte stiahnuté súbory a potom to skúste znova. - Inštalácia zlyhala, pretože súbory APK sú poškodené. Skúste to prosím znova. - Inštalácia zlyhala, pretože je povolená optimalizácia MIUI. Zakážte optimalizáciu MIUI a potom to skúste znova. - Inštalácia zlyhala, pretože overenie podpisu APK je povolené. Zakážte overenie podpisu APK a potom to skúste znova. - Inštalácia zlyhala, pretože v zariadení nie je dostatok voľného miesta. - Z inštalačného programu sa nepodarilo nájsť súbor APK pre čiernu/tmavú tému. Vymažte údaje aplikácie Vanced Manager a potom to skúste znova. - Po split inštalácii aplikácie sa nepodarilo nájsť cestu inštalácie originálnej YouTube aplikácie. + Nepodarilo sa odinštalovať balíček %1$s + Nepodarilo sa nájsť požadované súbory na inštaláciu. Opätovne stiahnite inštalačné súbory a skúste to znova. + V lokálnom úložisku sa nepodarilo nájsť APK súbor pre čiernu/tmavú tému. Skúste to znovu prosím. + Inštalácia zlyhala, kvôli zrušeniu užívateľom. + Inštalácia zlyhala, pretože aplikácia je v konflikte s už nainštalovanou aplikáciou. Odinštalujte aktuálnu verziu aplikácie a potom to skúste znova. + Inštalácia zlyhala, pretože užívateľ sa pokúsil downgradovať balík. Odinštalujte aktualizácie z pôvodnej aplikácie a potom to skúste znova. + Inštalácia zlyhala z neznámych dôvodov. Pre poskytnutie podpory sa pripojte sa k nášmu Telegramu alebo Discordu. Pripojte tiež snímky obrazovky z ponuky Pokročilé + Inštalácia zlyhala, pretože inštalačný súbor nie je kompatibilný s vaším zariadením. V Nastaveniach vymažte stiahnuté súbory a potom to skúste znova. + Inštalácia zlyhala, pretože súbory APK sú poškodené. Skúste to prosím znova. + Inštalácia zlyhala, pretože je povolená optimalizácia MIUI. Zakážte optimalizáciu MIUI a potom to skúste znova. + Inštalácia zlyhala, pretože overenie podpisu APK je povolené. Zakážte overenie podpisu APK a potom to skúste znova. + Inštalácia zlyhala, pretože v zariadení nie je dostatok voľného miesta. + Z inštalačného programu sa nepodarilo nájsť súbor APK pre čiernu/tmavú tému. Vymažte údaje aplikácie Vanced Manager a potom to skúste znova. + Po split inštalácii aplikácie sa nepodarilo nájsť cestu inštalácie originálnej YouTube aplikácie. diff --git a/app/src/main/res/values-so-rSO/strings.xml b/app/src/main/res/values-so-rSO/strings.xml index 1a4945b9b7..6bed32e9df 100644 --- a/app/src/main/res/values-so-rSO/strings.xml +++ b/app/src/main/res/values-so-rSO/strings.xml @@ -1,120 +1,120 @@ - Ka noqo - Xidh - A custom GMS Implementation for Vanced based on the microG Project. - A modified YouTube client with many useful features! - Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. - Dib uceli - Kaydi - Dooro apps-ka + Ka noqo + Xidh + A custom GMS Implementation for Vanced based on the microG Project. + A modified YouTube client with many useful features! + Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. + Dib uceli + Kaydi + Dooro apps-ka - Anaga - Guide - Maamule - Logs - Fadhiga - Cusboonaysii + Anaga + Guide + Maamule + Logs + Fadhiga + Cusboonaysii - Aaladaada miyay root-garaysan tahay? - U Ogolow Fasaxa Root-ka - Aan bilawno - Ugu yaraan hal app dooro! - Ma aqaano wuxuu kani yahay ama ma doonayo inaan isticmaalo midka root-ka ah? Aayar taabo falaadha buluuga ah ee hoose! + Aaladaada miyay root-garaysan tahay? + U Ogolow Fasaxa Root-ka + Aan bilawno + Ugu yaraan hal app dooro! + Ma aqaano wuxuu kani yahay ama ma doonayo inaan isticmaalo midka root-ka ah? Aayar taabo falaadha buluuga ah ee hoose! - Ku saabsan %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - Apps - Waxa isbadalay - Dajinaya %1$s - Kushub + Ku saabsan %1$s + Download + Info + Launch + Reinstall + Uninstall + Update + Apps + Waxa isbadalay + Dajinaya %1$s + Kushub U dambeeyay: - Install Vanced microG first + Install Vanced microG first \'Root\' looma fasaxin - Baraha Bulshada - Na taageer - Lama heli karo + Baraha Bulshada + Na taageer + Lama heli karo Ka kujira: - Midabka - Muuqaalka - Dabeecada - Nadiifi waxyaabaha lasoo dajiyay - Waa la nadiifiyay - Tani waxay noo ogolaanaysaa inaan uruurino xog ku saabsan shaqaynta app-ka iyo kaydinta xogta khaladaadka dhaca - Falanqaynta Firebase - Luuqada - Linkiyadu waxay ku furmi doonaan daaqadaha Chrome-ka ee loogu talagalay - Isticmaal Daaqadaha Chrome - %1$s Ogaysiisyadiisa - Ha kuu soo dhacaan ogaysiisyo marka mid cusub oo %1$s ah lasoo saaro - Laguma guulaysan in cadadka wakhtiga la kaydiyo - Qormada Wakhtiga Jiifka ee Root-ka - Habee cadadka wakhtiga jiifka ee loo isticmaalay qormada /data/adb/service.d/app.s, waxay muhiim u tahay cilladaha galinta - Sida aaladu tahay - Nashqada - Nashqad Madow - Nashqad Cad - Xarunta Cusboonaysiinta Manager-ka - Majiro wax cusub - Nooca + Midabka + Muuqaalka + Dabeecada + Nadiifi waxyaabaha lasoo dajiyay + Waa la nadiifiyay + Tani waxay noo ogolaanaysaa inaan uruurino xog ku saabsan shaqaynta app-ka iyo kaydinta xogta khaladaadka dhaca + Falanqaynta Firebase + Luuqada + Linkiyadu waxay ku furmi doonaan daaqadaha Chrome-ka ee loogu talagalay + Isticmaal Daaqadaha Chrome + %1$s Ogaysiisyadiisa + Ha kuu soo dhacaan ogaysiisyo marka mid cusub oo %1$s ah lasoo saaro + Laguma guulaysan in cadadka wakhtiga la kaydiyo + Qormada Wakhtiga Jiifka ee Root-ka + Habee cadadka wakhtiga jiifka ee loo isticmaalay qormada /data/adb/service.d/app.s, waxay muhiim u tahay cilladaha galinta + Sida aaladu tahay + Nashqada + Nashqad Madow + Nashqad Cad + Xarunta Cusboonaysiinta Manager-ka + Majiro wax cusub + Nooca - Could not save logs - Successfully saved logs + Could not save logs + Successfully saved logs Details - %1$s faylashiisii kushubi lahaa ayaa la helay! - Manager-ku wuxuu helay dhamaan faylashii loo baahnaa %1$s inuu ku shubmo. Ma rabtaa inaad ku shubto? + %1$s faylashiisii kushubi lahaa ayaa la helay! + Manager-ku wuxuu helay dhamaan faylashii loo baahnaa %1$s inuu ku shubmo. Ma rabtaa inaad ku shubto? Fadhiga Kushubida %1$s - Hubinaya wax cusub… + Hubinaya wax cusub… Luuqada(ha): %1$s Nashqada: %1$s Tirsiga: %1$s - Khalad - Hagitaan - Jooji! + Khalad + Hagitaan + Jooji! Waxaad isticmaalaysaa version-ka Vanced ee loogu talagalay Magisk/TWRP, kaasoo aan hada la taageerin halkana lagama cusboonaysiin karo. Fadlan iska saar lifaaqa Magisk/adoo isticmaalaya kasaaraha Vanced ee TWRP-ga xagiisa. - To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) - MIUI Optimizations are enabled! - Please do NOT exit the app during this process! - Dib udaji - Iska hubi inaad app-ka kaso dajisatay vancedapp.com, xaga martigaliyaha Discord, ama meesha Vanced ee GitHub + To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) + MIUI Optimizations are enabled! + Please do NOT exit the app during this process! + Dib udaji + Iska hubi inaad app-ka kaso dajisatay vancedapp.com, xaga martigaliyaha Discord, ama meesha Vanced ee GitHub Tirsiga - Soo dhawoow + Soo dhawoow - Dooro luuqada(ha) aad rabto ee app-ka Vanced - Latest + Dooro luuqada(ha) aad rabto ee app-ka Vanced + Latest Cadiin + %1$s Ugu yaraan hal luuqad dooro! - Black - Dark + Black + Dark - Sameeyaasha Manager-ka - Other Contributors - Tixraacyo - Kooxda Vanced + Sameeyaasha Manager-ka + Other Contributors + Tixraacyo + Kooxda Vanced - Laguma guulaysan in APK-ga `mulkiilihiisa loo badalo` barnaamijka aaladu kushaqayso, fadlan markale kuceli. - Khalad ayaa ka dhacay soo dajintii %1$s + Laguma guulaysan in APK-ga `mulkiilihiisa loo badalo` barnaamijka aaladu kushaqayso, fadlan markale kuceli. + Khalad ayaa ka dhacay soo dajintii %1$s Laguma guulaysanin in midabka cusub lagu fadhiisiyo - Laguma guulaysan in laga saaro %1$s - Laguma guulaysan in la helo faylashii ku shubi lahaa. Dib-usoodaji faylasha, kadibna isku day markale. - Laguma guulaysanin in faylka apk-ga ee nashqada madow/mugdiga laga helo kaydka aalaada, fadlan markale isku day. - Ku shubidii way guuldaraysatay sababtoo ah qofka aalada isticmaalaya ayaa joojiyay. - Ku shubidii way guuldaraysatay sababtoo ah app-ka waxay iskhilaafeen mid horay ugu jiray aalada. Ka saar nooca hadda ee kujira, kadib markale ku celi. - Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. - Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu - Ku shubidii way guuldaraysatay sababtoo ah faylka kuma shaqaynayo aaladaada. Xaga Fadhiga ka saar waxyaabaha lasoo dajiyay, kadib markale isku day. - Ku shubidii way guuldaraysatay sababtoo ah faylashii apk-ga ayaa khalkhalsan, markale isku day. - Ku shubidii way guuldaraysatay sababtoo ah waxaa furan MIUI Optimization. Xidh MIUI Optimization-ka, kadib markale ku celi. - Ku shubidii way guuldaraysatay sababtoo ah waxaa furan xaqiijinta saxiixa apk-ga. Xidh xaqiijinta saxiixa apk-ga, kadibna markale ku celi. - Installation failed because the device doesn\'t have enough free space. - Lama helin faylka apk-ga ee nashqada madow/mugdiga ah. Tirtir xogta Manager-ka, kadib markale ku celi. - Waa lagu guuldaraysatay in la helo wadadii ku shubida app-ka caadiga ah ee YouTube-ka ee kuxigtay ku shubida kala qaybsan. + Laguma guulaysan in laga saaro %1$s + Laguma guulaysan in la helo faylashii ku shubi lahaa. Dib-usoodaji faylasha, kadibna isku day markale. + Laguma guulaysanin in faylka apk-ga ee nashqada madow/mugdiga laga helo kaydka aalaada, fadlan markale isku day. + Ku shubidii way guuldaraysatay sababtoo ah qofka aalada isticmaalaya ayaa joojiyay. + Ku shubidii way guuldaraysatay sababtoo ah app-ka waxay iskhilaafeen mid horay ugu jiray aalada. Ka saar nooca hadda ee kujira, kadib markale ku celi. + Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. + Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu + Ku shubidii way guuldaraysatay sababtoo ah faylka kuma shaqaynayo aaladaada. Xaga Fadhiga ka saar waxyaabaha lasoo dajiyay, kadib markale isku day. + Ku shubidii way guuldaraysatay sababtoo ah faylashii apk-ga ayaa khalkhalsan, markale isku day. + Ku shubidii way guuldaraysatay sababtoo ah waxaa furan MIUI Optimization. Xidh MIUI Optimization-ka, kadib markale ku celi. + Ku shubidii way guuldaraysatay sababtoo ah waxaa furan xaqiijinta saxiixa apk-ga. Xidh xaqiijinta saxiixa apk-ga, kadibna markale ku celi. + Installation failed because the device doesn\'t have enough free space. + Lama helin faylka apk-ga ee nashqada madow/mugdiga ah. Tirtir xogta Manager-ka, kadib markale ku celi. + Waa lagu guuldaraysatay in la helo wadadii ku shubida app-ka caadiga ah ee YouTube-ka ee kuxigtay ku shubida kala qaybsan. diff --git a/app/src/main/res/values-sr-rSP/strings.xml b/app/src/main/res/values-sr-rSP/strings.xml index 61e47df224..d23f364fcf 100644 --- a/app/src/main/res/values-sr-rSP/strings.xml +++ b/app/src/main/res/values-sr-rSP/strings.xml @@ -1,120 +1,120 @@ - Откажи - Затвори - Независна GMS имплементација за Vanced заснована на microG пројекту. - Модификовани YouTube клијент са многим корисним функцијама! - Vanced, али за YouTube Music! Релативно са мање напредних карактеристикама, али ће задовољити ваше потребе. - Ресетуј - Сачувај - Одабери своје апликације + Откажи + Затвори + Независна GMS имплементација за Vanced заснована на microG пројекту. + Модификовани YouTube клијент са многим корисним функцијама! + Vanced, али за YouTube Music! Релативно са мање напредних карактеристикама, али ће задовољити ваше потребе. + Ресетуј + Сачувај + Одабери своје апликације - О апликацији - Водич - Менаџер - Дневници - Поставке - Освежи Менаџера + О апликацији + Водич + Менаџер + Дневници + Поставке + Освежи Менаџера - Да ли је ваш уређај рутован? - Омогућите дозволу за рут - Хајде да почнемо - Одабери барем једну апликацију! - Не знате шта је ово или не желите да користите роот верзију апликације? Само кликните на плаву стрелицу испод! + Да ли је ваш уређај рутован? + Омогућите дозволу за рут + Хајде да почнемо + Одабери барем једну апликацију! + Не знате шта је ово или не желите да користите роот верзију апликације? Само кликните на плаву стрелицу испод! - О %s - Преузми - Инфо - Покрени - Reinstall - Деинсталирај - Ажурирај - Апликације - Историја измена - Преузимање %1$s - Инсталација + О %s + Преузми + Инфо + Покрени + Reinstall + Деинсталирај + Ажурирај + Апликације + Историја измена + Преузимање %1$s + Инсталација Најновија: - Инсталирајте прво Vanced microG + Инсталирајте прво Vanced microG Root приступ није омогућен - Социјалне мреже - Подржите нас - Недоступно + Социјалне мреже + Подржите нас + Недоступно Инсталирана: - Боја наглашавања - Изглед - Понашање - Обриши преузете датотеке - Успешно брисање датотека - Ово нам омогућава да прикупљамо извештаје о перформансама и грешкама - Firebase Анализа - Језик - Линкови ће бити отворени у Chrome Custom Tabs - Користите Chrome Custom Tabs - %1$s слање обавештења - Примај обавештења када је достигнута верзија %1$s - Грешка при снимању вредности за ново време - Роот скрипта за Време спавања - Подесите време спавања путем у /data/adb/service.d/app.sh скрипти, ово је корисно код грешке при повезивању - Системски подразумевано - Тема - Тамна тема - Светла тема - Менаџер ажурирања - Нема нове верзије - Варијанта + Боја наглашавања + Изглед + Понашање + Обриши преузете датотеке + Успешно брисање датотека + Ово нам омогућава да прикупљамо извештаје о перформансама и грешкама + Firebase Анализа + Језик + Линкови ће бити отворени у Chrome Custom Tabs + Користите Chrome Custom Tabs + %1$s слање обавештења + Примај обавештења када је достигнута верзија %1$s + Грешка при снимању вредности за ново време + Роот скрипта за Време спавања + Подесите време спавања путем у /data/adb/service.d/app.sh скрипти, ово је корисно код грешке при повезивању + Системски подразумевано + Тема + Тамна тема + Светла тема + Менаџер ажурирања + Нема нове верзије + Варијанта - Није могуће снимити дневнике - Успешно сачувани дневници + Није могуће снимити дневнике + Успешно сачувани дневници Детаљи - %1$s верзија је пронађена! - Менаџер је пронашао све датотеке за %1$s верзију инсталације. Да ли желите да инсталирате? + %1$s верзија је пронађена! + Менаџер је пронашао све датотеке за %1$s верзију инсталације. Да ли желите да инсталирате? %1$s Инсталациона подешавања - Провера ажурирања… + Провера ажурирања… Језик (Језици):%1$s Тема: %1$s Верзија: %1$s - Грешка - Водич - Заустави! + Грешка + Водич + Заустави! Користите Magisk/TWRP верзију Vanced апликације, која више није подржана и чије коришћење није могуће. Молимо Вас да уклоните ову апликацију из Magisk/TWRP-а путем Vanced апликације за деинсталацију. - Да би апликација Vanced била исправно инсталирана морате да искључите оптимизацију за ову апликацију у MIUI подешавањима за програмере.( Ову напомену можете да занемарите у случају ако користите верзију 20.2.20 и новију xiaomi.eu ROM-а) - MIUI оптимизација је укључена! - Немојте излазити из апликације у току овога процеса! - Поново преузми - Преузмите апликацију само са официјелног Vanced сајта vancedapp.com, Vanced Discord сервера или Vanced GitHub-а + Да би апликација Vanced била исправно инсталирана морате да искључите оптимизацију за ову апликацију у MIUI подешавањима за програмере.( Ову напомену можете да занемарите у случају ако користите верзију 20.2.20 и новију xiaomi.eu ROM-а) + MIUI оптимизација је укључена! + Немојте излазити из апликације у току овога процеса! + Поново преузми + Преузмите апликацију само са официјелног Vanced сајта vancedapp.com, Vanced Discord сервера или Vanced GitHub-а Верзија - Добро дошли + Добро дошли - Одаберите језик за коришћење Vanced апликације - Најновија + Одаберите језик за коришћење Vanced апликације + Најновија Осветљење+%1$s Одаберите барем један језик! - Црно - Тамно + Црно + Тамно - Менаџер развоја - Други покровитељи - Извор - Vanced Тим + Менаџер развоја + Други покровитељи + Извор + Vanced Тим - Грешка при додели apk власнику система, покушајте поново. - Грешка приликом преузимања %1$s + Грешка при додели apk власнику система, покушајте поново. + Грешка приликом преузимања %1$s Неуспешно постављање нове носеће боје - Неуспешно деинсталирање пакета %1$s - Није могуће пронаћи датотеке за инсталацију. Преузмите их поново и поновите инсталацију. - Није могуће пронаћи apk датотеку за црно/тамну тему у меморијском простору, покушајте поново. - Инсталација није успешна, корисник је обуставио инсталацију. - Инсталација неуспешна, зато што је дошло до конфликта са већ инсталираном верзијом. Деинсталирајте тренутну верзију Vanced-а и затим покушајте поново. - Инсталација није успешна, корисник је покушао да инсталира старију верзију преко новије верзије апликације. Деинсталирајте све до предодређене инсталиране верзије YouTubе апликације, затим покушајте поново. - Неуспешна инсталација услед непознатих разлога, Прикључите се нашем Telegram или Discord каналима за помоћ. Молимо да прикључите снимак екрана из Проширеног Менија - Инсталација је неуспешна јер инсталациона датотека није компатибилна са вашим уређајем. Очистите преузете датотеке у Подешавањима и затим покушајте поново. - Инсталација није успеla јер је apk датотека оштећена, покушајте поново. - Инсталација неуспешна јер је укључена оптимизација за ову апликацију у MIUI систему. Искључите MIUI оптимизацију за ову апликацију и затим покушајте поново. - Инсталација неуспешна јер је укључена провера потписа преузете apk датотеке. Искључите apk проверу и затим покушајте поново. - Инсталација неуспешна јер на уређају нема довољно слободног простора. - Није могуће пронаћи apk датотеку за црно/тамну тему у инсталационим датотекама. Очистите податке у Менаџеру и покушајте поново. - Није могуће пронаћи подразумевану YouTube локацију за инсталацију после подељене инсталације. + Неуспешно деинсталирање пакета %1$s + Није могуће пронаћи датотеке за инсталацију. Преузмите их поново и поновите инсталацију. + Није могуће пронаћи apk датотеку за црно/тамну тему у меморијском простору, покушајте поново. + Инсталација није успешна, корисник је обуставио инсталацију. + Инсталација неуспешна, зато што је дошло до конфликта са већ инсталираном верзијом. Деинсталирајте тренутну верзију Vanced-а и затим покушајте поново. + Инсталација није успешна, корисник је покушао да инсталира старију верзију преко новије верзије апликације. Деинсталирајте све до предодређене инсталиране верзије YouTubе апликације, затим покушајте поново. + Неуспешна инсталација услед непознатих разлога, Прикључите се нашем Telegram или Discord каналима за помоћ. Молимо да прикључите снимак екрана из Проширеног Менија + Инсталација је неуспешна јер инсталациона датотека није компатибилна са вашим уређајем. Очистите преузете датотеке у Подешавањима и затим покушајте поново. + Инсталација није успеla јер је apk датотека оштећена, покушајте поново. + Инсталација неуспешна јер је укључена оптимизација за ову апликацију у MIUI систему. Искључите MIUI оптимизацију за ову апликацију и затим покушајте поново. + Инсталација неуспешна јер је укључена провера потписа преузете apk датотеке. Искључите apk проверу и затим покушајте поново. + Инсталација неуспешна јер на уређају нема довољно слободног простора. + Није могуће пронаћи apk датотеку за црно/тамну тему у инсталационим датотекама. Очистите податке у Менаџеру и покушајте поново. + Није могуће пронаћи подразумевану YouTube локацију за инсталацију после подељене инсталације. diff --git a/app/src/main/res/values-sv-rSE/strings.xml b/app/src/main/res/values-sv-rSE/strings.xml index edcd8e1646..b33bb7f250 100644 --- a/app/src/main/res/values-sv-rSE/strings.xml +++ b/app/src/main/res/values-sv-rSE/strings.xml @@ -1,120 +1,120 @@ - Avbryt - Stäng - En anpassad GMS-implementering för Vanced baserad på microG-projektet. - En modifierad YouTube-klient med många användbara funktioner! - Vanced, men för YouTube Music! Relativt mindre funktionsrika men uppfyller dina behov. - Återställ - Spara - Välj dina appar + Avbryt + Stäng + En anpassad GMS-implementering för Vanced baserad på microG-projektet. + En modifierad YouTube-klient med många användbara funktioner! + Vanced, men för YouTube Music! Relativt mindre funktionsrika men uppfyller dina behov. + Återställ + Spara + Välj dina appar - Om - Guide - Hanterare - Loggar - Inställningar - Uppdatera hanteraren + Om + Guide + Hanterare + Loggar + Inställningar + Uppdatera hanteraren - Är din enhet rotad? - Ge Posting Permission - Nu sätter vi igång - Välj minst en zoomnivå! - Vet du inte vad detta är eller inte vill använda rotversionen? Klicka bara på den blå pilen nedan! + Är din enhet rotad? + Ge Posting Permission + Nu sätter vi igång + Välj minst en zoomnivå! + Vet du inte vad detta är eller inte vill använda rotversionen? Klicka bara på den blå pilen nedan! - Cirka %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - Appar - Ändringslogg - Laddar ned %1$s - Install + Cirka %1$s + Download + Info + Launch + Reinstall + Uninstall + Update + Appar + Ändringslogg + Laddar ned %1$s + Install Senaste: - Installera Vanced microG först + Installera Vanced microG först Root-åtkomst inte beviljat - Sociala medier - Stöd oss - Ej tillgänglig + Sociala medier + Stöd oss + Ej tillgänglig Installerad: - Accentfärg - Utseende - Beteende - Rensa nedladdade filer - Rensade data - Detta gör att vi kan samla in information om appens prestanda och kraschloggar - Firebase Analys - Språk - Länkar öppnas i Chrome Custom Tabs - Använd Chrome-anpassade flikar - %1$s push-meddelanden - Få push-meddelanden när en uppdatering för %1$s släpps - Det gick inte att spara nytt tidsvärde - Root-skript sömntid - Justera vilotidsvärde som används i /data/adb/service.d/app.sh skript, användbart för att fixa monteringsproblem - Systemstandard - Tema - Mörkt tema - Ljust tema - Ansvarig uppdateringscenter - Inga nya uppdateringar - Variant + Accentfärg + Utseende + Beteende + Rensa nedladdade filer + Rensade data + Detta gör att vi kan samla in information om appens prestanda och kraschloggar + Firebase Analys + Språk + Länkar öppnas i Chrome Custom Tabs + Använd Chrome-anpassade flikar + %1$s push-meddelanden + Få push-meddelanden när en uppdatering för %1$s släpps + Det gick inte att spara nytt tidsvärde + Root-skript sömntid + Justera vilotidsvärde som används i /data/adb/service.d/app.sh skript, användbart för att fixa monteringsproblem + Systemstandard + Tema + Mörkt tema + Ljust tema + Ansvarig uppdateringscenter + Inga nya uppdateringar + Variant - Kunde inte spara sida - Sparades + Kunde inte spara sida + Sparades Detaljer - %1$s installationsfiler upptäckt! - Manager upptäckte att alla nödvändiga filer för %1$s installation hittades. Vill du installera? + %1$s installationsfiler upptäckt! + Manager upptäckte att alla nödvändiga filer för %1$s installation hittades. Vill du installera? %1$s Valda installationsinställningar - Söker efter uppdateringar… + Söker efter uppdateringar… Språk: %1$s Tema: %1$s Version %1$s - Fel - Guide - Stopp! + Fel + Guide + Stopp! Ser ut som om du använder Magisk versionen av Vanced, som är avbruten och inte kan uppdateras med den här appen. Ta bort den först genom att ta bort magisk modulen. - För att installera Vanced, måste du inaktivera MIUI Optimisations i utvecklarinställningarna. (Du kan ignorera denna varning om du använder 20.2.20 eller senare xiaomi.eu-baserad ROM) - MIUI Optimeringar är aktiverade! - Vänligen avsluta INTE appen under denna process! - Ladda ner igen - Se till att du laddade ner appen från vancedapp.com, den Vanced Discord-servern eller den Vanced GitHub + För att installera Vanced, måste du inaktivera MIUI Optimisations i utvecklarinställningarna. (Du kan ignorera denna varning om du använder 20.2.20 eller senare xiaomi.eu-baserad ROM) + MIUI Optimeringar är aktiverade! + Vänligen avsluta INTE appen under denna process! + Ladda ner igen + Se till att du laddade ner appen från vancedapp.com, den Vanced Discord-servern eller den Vanced GitHub Version - Välkommen + Välkommen - Välj önskade språk för Vanced - Senaste + Välj önskade språk för Vanced + Senaste Ljus + %1$s Välj minst ett språk! - Svart - Mörk + Svart + Mörk - Hanteraren Dev - Andra bidragsgivare - Källor - Vanced Team + Hanteraren Dev + Andra bidragsgivare + Källor + Vanced Team - Misslyckades att Chown Apk till systemägare, Försök igen. - Laddar ned %1$s + Misslyckades att Chown Apk till systemägare, Försök igen. + Laddar ned %1$s Det gick inte att tillämpa ny accentfärg - Det gick inte att avinstallera paket %1$s - Det gick inte att hitta de nödvändiga filerna för installationen. Ladda ner installationsfilerna igen och försök igen. - Det gick inte att hitta apk-fil för svart/mörkt tema från lagring, försök igen. - Åtgärden misslyckades eftersom användaren avbröt installationen. - Installationen misslyckades eftersom appen står i konflikt med en redan installerad app. Avinstallera den aktuella versionen av Vanced, försök sedan igen. - Installationen misslyckades eftersom användaren försökte nedgradera paketet. Avinstallera uppdateringar från lagerappen YouTube, försök sedan igen. - Installationen misslyckades av okända skäl, gå med i vårt Telegram eller Discord för ytterligare stöd. Vänligen bifoga även en skärmdump från menyn Avancerat - Installationen misslyckades eftersom installationsfilen är inkompatibel med din enhet. Rensa nedladdade filer i Inställningarna och försök igen. - Installationen misslyckades eftersom apk-filerna är skadade, försök igen. - Installationen misslyckades eftersom MIUI-optimering är aktiverad. Inaktivera MIUI-optimering och försök igen. - Installationen misslyckades eftersom apk signaturverifiering är aktiverad. Inaktivera apk signaturverifiering och försök igen. - Installationen misslyckades eftersom enheten inte har tillräckligt med ledigt utrymme. - Det gick inte att hitta apk-fil för svart/mörkt tema från installationsprogrammet. Rensa appdata från Manager och försök igen. - Det gick inte att hitta sökvägen för lagerinstallationen på YouTube efter delad installation. + Det gick inte att avinstallera paket %1$s + Det gick inte att hitta de nödvändiga filerna för installationen. Ladda ner installationsfilerna igen och försök igen. + Det gick inte att hitta apk-fil för svart/mörkt tema från lagring, försök igen. + Åtgärden misslyckades eftersom användaren avbröt installationen. + Installationen misslyckades eftersom appen står i konflikt med en redan installerad app. Avinstallera den aktuella versionen av Vanced, försök sedan igen. + Installationen misslyckades eftersom användaren försökte nedgradera paketet. Avinstallera uppdateringar från lagerappen YouTube, försök sedan igen. + Installationen misslyckades av okända skäl, gå med i vårt Telegram eller Discord för ytterligare stöd. Vänligen bifoga även en skärmdump från menyn Avancerat + Installationen misslyckades eftersom installationsfilen är inkompatibel med din enhet. Rensa nedladdade filer i Inställningarna och försök igen. + Installationen misslyckades eftersom apk-filerna är skadade, försök igen. + Installationen misslyckades eftersom MIUI-optimering är aktiverad. Inaktivera MIUI-optimering och försök igen. + Installationen misslyckades eftersom apk signaturverifiering är aktiverad. Inaktivera apk signaturverifiering och försök igen. + Installationen misslyckades eftersom enheten inte har tillräckligt med ledigt utrymme. + Det gick inte att hitta apk-fil för svart/mörkt tema från installationsprogrammet. Rensa appdata från Manager och försök igen. + Det gick inte att hitta sökvägen för lagerinstallationen på YouTube efter delad installation. diff --git a/app/src/main/res/values-ta-rIN/strings.xml b/app/src/main/res/values-ta-rIN/strings.xml index c7f5f91cf5..e5e6228039 100644 --- a/app/src/main/res/values-ta-rIN/strings.xml +++ b/app/src/main/res/values-ta-rIN/strings.xml @@ -1,120 +1,120 @@ - ரத்துசெய் - மூடுக - மைக்ஜிக் திட்டத்தின் அடிப்படையில் ஒரு தனிபயன் GMS செயல்படுத்துதல். - பல பயனுள்ள அம்சங்களுடன் ஒரு திருத்தப்பட்ட YouTube வாடிக்கையாளர்! - Vanced, ஆனால் YouTube இசை! ஒப்பீட்டளவில் குறைவான அம்சம் நிறைந்த பணக்காரர்கள் ஆனால் உங்கள் தேவைகளை பூர்த்தி செய்கிறார்கள். - மீட்டமை - சேமிக்கவும் - உங்கள் பயன்பாடுகளைத் தேர்ந்தெடுக்கவும் + ரத்துசெய் + மூடுக + மைக்ஜிக் திட்டத்தின் அடிப்படையில் ஒரு தனிபயன் GMS செயல்படுத்துதல். + பல பயனுள்ள அம்சங்களுடன் ஒரு திருத்தப்பட்ட YouTube வாடிக்கையாளர்! + Vanced, ஆனால் YouTube இசை! ஒப்பீட்டளவில் குறைவான அம்சம் நிறைந்த பணக்காரர்கள் ஆனால் உங்கள் தேவைகளை பூர்த்தி செய்கிறார்கள். + மீட்டமை + சேமிக்கவும் + உங்கள் பயன்பாடுகளைத் தேர்ந்தெடுக்கவும் - பற்றி - வழிகாட்டி - மேலாளர் - பதிவுகள் - அமைப்புகள் - புதுப்பிப்பு மேலாளர் + பற்றி + வழிகாட்டி + மேலாளர் + பதிவுகள் + அமைப்புகள் + புதுப்பிப்பு மேலாளர் - உங்கள் சாதனம் வேரூன்றியதா? - கிராண்ட் ரூட் அனுமதி - தொடங்குவோம் - குறைந்தது ஒரு பயன்பாட்டையாவது தேர்ந்தெடுக்கவும்! - இது என்னவென்று தெரியவில்லையா அல்லது ரூட் பதிப்பைப் பயன்படுத்த விரும்பவில்லையா? கீழே உள்ள நீல அம்புக்குறியைக் கிளிக் செய்க! + உங்கள் சாதனம் வேரூன்றியதா? + கிராண்ட் ரூட் அனுமதி + தொடங்குவோம் + குறைந்தது ஒரு பயன்பாட்டையாவது தேர்ந்தெடுக்கவும்! + இது என்னவென்று தெரியவில்லையா அல்லது ரூட் பதிப்பைப் பயன்படுத்த விரும்பவில்லையா? கீழே உள்ள நீல அம்புக்குறியைக் கிளிக் செய்க! - பற்றி %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - பயன்பாடுகள் - சேஞ்ச்லாக் - %1$s ஐப் பதிவிறக்குகிறது - நிறுவு + பற்றி %1$s + Download + Info + Launch + Reinstall + Uninstall + Update + பயன்பாடுகள் + சேஞ்ச்லாக் + %1$s ஐப் பதிவிறக்குகிறது + நிறுவு சமீபத்தியது: - முதலில் Vanced Microg ஐ நிறுவவும் + முதலில் Vanced Microg ஐ நிறுவவும் ரூட் அக்சஸ் வழங்கப்படவில்லை - சமூக ஊடகம் - எங்களை ஆதரியுங்கள் - கிடைக்கவில்லை + சமூக ஊடகம் + எங்களை ஆதரியுங்கள் + கிடைக்கவில்லை நிறுவப்பட்டது: - கவனங்கவர் நிறம் - தோற்றம் - செயல்பாடு - பதிவிறக்கிய கோப்புகளை அழிக்கவும் - கோப்புகளை வெற்றிகரமாக அழித்துவிட்டது - பயன்பாட்டு செயல்திறன் மற்றும் செயலிழப்பு பதிவுகள் பற்றிய தகவல்களை சேகரிக்க இது எங்களுக்கு உதவுகிறது - ஃபயர்பேஸ் அனலிட்டிக்ஸ் - மொழி - Chrome தனிப்பயன் தாவல்களில் இணைப்புகள் திறக்கப்படும் - Chrome தனிப்பயன் தாவல்களைப் பயன்படுத்தவும் - %1$s புஷ் அறிவிப்புகள் - %1$s க்கான புதுப்பிப்பு வெளியிடப்படும் போது புஷ் அறிவிப்புகளைப் பெறுக - புதிய நேர மதிப்பைச் சேமிப்பதில் தோல்வி - ரூட் ஸ்கிரிப்ட் தூக்க நேரம் - பெருகிவரும் சிக்கல்களை சரிசெய்ய பயனுள்ளதாக இருக்கும் /data/adb/service.d/app.sh ஸ்கிரிப்டில் பயன்படுத்தப்படும் தூக்க நேர மதிப்பை சரிசெய்யவும் - கணினி இயல்புநிலை - தீம் - இருண்ட தீம் - ஒளி தீம் - மேலாளர் புதுப்பிப்பு மையம் - புதிய புதுப்பிப்புகள் இல்லை - மாறுபாடு + கவனங்கவர் நிறம் + தோற்றம் + செயல்பாடு + பதிவிறக்கிய கோப்புகளை அழிக்கவும் + கோப்புகளை வெற்றிகரமாக அழித்துவிட்டது + பயன்பாட்டு செயல்திறன் மற்றும் செயலிழப்பு பதிவுகள் பற்றிய தகவல்களை சேகரிக்க இது எங்களுக்கு உதவுகிறது + ஃபயர்பேஸ் அனலிட்டிக்ஸ் + மொழி + Chrome தனிப்பயன் தாவல்களில் இணைப்புகள் திறக்கப்படும் + Chrome தனிப்பயன் தாவல்களைப் பயன்படுத்தவும் + %1$s புஷ் அறிவிப்புகள் + %1$s க்கான புதுப்பிப்பு வெளியிடப்படும் போது புஷ் அறிவிப்புகளைப் பெறுக + புதிய நேர மதிப்பைச் சேமிப்பதில் தோல்வி + ரூட் ஸ்கிரிப்ட் தூக்க நேரம் + பெருகிவரும் சிக்கல்களை சரிசெய்ய பயனுள்ளதாக இருக்கும் /data/adb/service.d/app.sh ஸ்கிரிப்டில் பயன்படுத்தப்படும் தூக்க நேர மதிப்பை சரிசெய்யவும் + கணினி இயல்புநிலை + தீம் + இருண்ட தீம் + ஒளி தீம் + மேலாளர் புதுப்பிப்பு மையம் + புதிய புதுப்பிப்புகள் இல்லை + மாறுபாடு - பதிவுகளைச் சேமிக்க முடியவில்லை - பதிவுகள் வெற்றிகரமாக சேமிக்கப்பட்டன + பதிவுகளைச் சேமிக்க முடியவில்லை + பதிவுகள் வெற்றிகரமாக சேமிக்கப்பட்டன விவரங்கள் - %1$s நிறுவல் கோப்புகள் கண்டறியப்பட்டன! - %1$s நிறுவலுக்கு தேவையான அனைத்து கோப்புகளும் கண்டறியப்பட்டதை மேலாளர் கண்டறிந்தார். நீங்கள் அதை நிறுவ விரும்புகிறீர்களா? + %1$s நிறுவல் கோப்புகள் கண்டறியப்பட்டன! + %1$s நிறுவலுக்கு தேவையான அனைத்து கோப்புகளும் கண்டறியப்பட்டதை மேலாளர் கண்டறிந்தார். நீங்கள் அதை நிறுவ விரும்புகிறீர்களா? %1$s நிறுவல் விருப்பத்தேர்வுகள் - புதுப்பிப்புகளைச் சரிபார்க்கிறது… + புதுப்பிப்புகளைச் சரிபார்க்கிறது… மொழி: %1$s தீம் %1$s பதிப்பு: %1$s - பிழை - வழிகாட்டி - நிறுத்து! + பிழை + வழிகாட்டி + நிறுத்து! நீங்கள் வேன்ஸின் மேஜிஸ்க் / டி. டபிள்யூ. ஆர். பி பதிப்பைப் பயன்படுத்துகிறீர்கள், இது நிறுத்தப்பட்டது மற்றும் இந்த பயன்பாட்டைப் பயன்படுத்தி புதுப்பிக்க முடியாது. மேஜிஸ்க் தொகுதியை அகற்றி / TWRP Vanced uninstaller ஐப் பயன்படுத்தி அதை அகற்றவும். - Vanced நிறுவ, நீங்கள் டெவலப்பர் அமைப்புகளில் Miui மேம்படுத்தல்களை முடக்க வேண்டும். (நீங்கள் 20.2.20 அல்லது பின்னர் xiaomi.eu அடிப்படையிலான ROM ஐப் பயன்படுத்துகிறீர்களானால் இந்த எச்சரிக்கையை நீங்கள் புறக்கணிக்கலாம்) - MIUI மேம்படுத்தல்கள் இயக்கப்பட்டன! - இந்த செயல்முறையின் போது பயன்பாட்டை விட்டு வெளியேற வேண்டாம்! - மீண்டும் பதிவிறக்கு - பயன்பாட்டை vancedapp.com, Vanced Discord சேவையகம் அல்லது Vanced GitHub இலிருந்து பதிவிறக்கம் செய்துள்ளீர்கள் என்பதை உறுதிப்படுத்திக் கொள்ளுங்கள் + Vanced நிறுவ, நீங்கள் டெவலப்பர் அமைப்புகளில் Miui மேம்படுத்தல்களை முடக்க வேண்டும். (நீங்கள் 20.2.20 அல்லது பின்னர் xiaomi.eu அடிப்படையிலான ROM ஐப் பயன்படுத்துகிறீர்களானால் இந்த எச்சரிக்கையை நீங்கள் புறக்கணிக்கலாம்) + MIUI மேம்படுத்தல்கள் இயக்கப்பட்டன! + இந்த செயல்முறையின் போது பயன்பாட்டை விட்டு வெளியேற வேண்டாம்! + மீண்டும் பதிவிறக்கு + பயன்பாட்டை vancedapp.com, Vanced Discord சேவையகம் அல்லது Vanced GitHub இலிருந்து பதிவிறக்கம் செய்துள்ளீர்கள் என்பதை உறுதிப்படுத்திக் கொள்ளுங்கள் பதிப்பு - வரவேற்பு + வரவேற்பு - வேன்ஸ்டுக்காக உங்களுக்கு விருப்பமான மொழியைத் தேர்வுசெய்க - சமீபத்தியது + வேன்ஸ்டுக்காக உங்களுக்கு விருப்பமான மொழியைத் தேர்வுசெய்க + சமீபத்தியது ஒளி + %1$s குறைந்தது ஒரு மொழியையாவது தேர்ந்தெடுக்கவும்! - கருப்பு - இருள் + கருப்பு + இருள் - மேலாளர் டெவலப்பர்கள் - பிற பங்களிப்பாளர்கள் - மூலம் - Vanced கூட்டணி + மேலாளர் டெவலப்பர்கள் + பிற பங்களிப்பாளர்கள் + மூலம் + Vanced கூட்டணி - கணினி உரிமையாளருக்கு APK ஐத் தேடுவதில் தோல்வி, தயவுசெய்து மீண்டும் முயற்சிக்கவும். - %1$s பதிவிறக்குவதில் தோழ்வி + கணினி உரிமையாளருக்கு APK ஐத் தேடுவதில் தோல்வி, தயவுசெய்து மீண்டும் முயற்சிக்கவும். + %1$s பதிவிறக்குவதில் தோழ்வி புதிய உச்சரிப்பு வண்ணத்தைப் பயன்படுத்துவதில் தோல்வி - %1$s நீக்குவதில் தோல்வி - நிறுவலுக்கு தேவையான கோப்புகளை கண்டுபிடிப்பதில் தோல்வி. நிறுவல் கோப்புகளை மீண்டும் பதிவிறக்கவும், பின்னர் மீண்டும் முயற்சிக்கவும். - சேமிப்பகத்திலிருந்து கருப்பு / இருண்ட கருப்பொருளுக்கான Apk கோப்பை கண்டுபிடிப்பதில் தோல்வி, தயவுசெய்து மீண்டும் முயற்சிக்கவும். - பயனர் நிறுவலை நிறுத்தியதால் நிறுவல் தோல்வியடைந்தது. - ஏற்கனவே நிறுவப்பட்ட பயன்பாட்டுடன் பயன்பாடு முரண்படுவதால் நிறுவல் தோல்வியடைந்தது. பயன்பாட்டின் தற்போதைய பதிப்பை நிறுவல் நீக்கி, பின்னர் மீண்டும் முயற்சிக்கவும். - பயனர் தொகுப்பை தரமிறக்க முயற்சித்ததால் நிறுவல் தோல்வியடைந்தது. பங்கு பயன்பாட்டிலிருந்து புதுப்பிப்புகளை நிறுவல் நீக்க, பின்னர் மீண்டும் முயற்சிக்கவும். - நிறுவல் அறியப்படாத காரணங்களுக்காக தோல்வியடைந்தது, எங்கள் டெலிகிராம் அல்லது மேலும் ஆதரவுக்கு இணக்கமாக இருக்கலாம். மேம்பட்ட மெனுவிலிருந்து ஒரு ஸ்கிரீன் ஷாட்டை இணைக்கவும் - நிறுவல் கோப்பு உங்கள் சாதனத்துடன் பொருந்தாததால் நிறுவல் தோல்வியடைந்தது. அமைப்புகளில் பதிவிறக்கம் செய்யப்பட்ட கோப்புகளை அழிக்கவும், பின்னர் மீண்டும் முயற்சிக்கவும். - நிறுவல் தோல்வியுற்றது, ஏனெனில் Apk கோப்புகள் சிதைந்துள்ளன, தயவுசெய்து மீண்டும் முயற்சிக்கவும். - MIUI உகப்பாக்கம் இயக்கப்பட்டிருப்பதால் நிறுவல் தோல்வியடைந்தது. MIUI உகப்பாக்கத்தை முடக்கு, பின்னர் மீண்டும் முயற்சிக்கவும். - Apk கையொப்ப சரிபார்ப்பு இயக்கப்பட்டிருப்பதால் நிறுவல் தோல்வியடைந்தது. Apk கையொப்ப சரிபார்ப்பை முடக்கு, பின்னர் மீண்டும் முயற்சிக்கவும். - சாதனம் போதுமான இலவச இடம் இல்லை என்பதால் நிறுவல் தோல்வியடைந்தது. - நிறுவியிலிருந்து கருப்பு / இருண்ட கருப்பொருளுக்கான Apk கோப்பைக் கண்டுபிடிப்பதில் தோல்வி. மேலாளரின் பயன்பாட்டுத் தரவை அழிக்கவும், பின்னர் மீண்டும் முயற்சிக்கவும். - பிளவு நிறுவலுக்குப் பிறகு பங்கு YouTube நிறுவல் பாதையை கண்டுபிடிப்பதில் தோல்வி. + %1$s நீக்குவதில் தோல்வி + நிறுவலுக்கு தேவையான கோப்புகளை கண்டுபிடிப்பதில் தோல்வி. நிறுவல் கோப்புகளை மீண்டும் பதிவிறக்கவும், பின்னர் மீண்டும் முயற்சிக்கவும். + சேமிப்பகத்திலிருந்து கருப்பு / இருண்ட கருப்பொருளுக்கான Apk கோப்பை கண்டுபிடிப்பதில் தோல்வி, தயவுசெய்து மீண்டும் முயற்சிக்கவும். + பயனர் நிறுவலை நிறுத்தியதால் நிறுவல் தோல்வியடைந்தது. + ஏற்கனவே நிறுவப்பட்ட பயன்பாட்டுடன் பயன்பாடு முரண்படுவதால் நிறுவல் தோல்வியடைந்தது. பயன்பாட்டின் தற்போதைய பதிப்பை நிறுவல் நீக்கி, பின்னர் மீண்டும் முயற்சிக்கவும். + பயனர் தொகுப்பை தரமிறக்க முயற்சித்ததால் நிறுவல் தோல்வியடைந்தது. பங்கு பயன்பாட்டிலிருந்து புதுப்பிப்புகளை நிறுவல் நீக்க, பின்னர் மீண்டும் முயற்சிக்கவும். + நிறுவல் அறியப்படாத காரணங்களுக்காக தோல்வியடைந்தது, எங்கள் டெலிகிராம் அல்லது மேலும் ஆதரவுக்கு இணக்கமாக இருக்கலாம். மேம்பட்ட மெனுவிலிருந்து ஒரு ஸ்கிரீன் ஷாட்டை இணைக்கவும் + நிறுவல் கோப்பு உங்கள் சாதனத்துடன் பொருந்தாததால் நிறுவல் தோல்வியடைந்தது. அமைப்புகளில் பதிவிறக்கம் செய்யப்பட்ட கோப்புகளை அழிக்கவும், பின்னர் மீண்டும் முயற்சிக்கவும். + நிறுவல் தோல்வியுற்றது, ஏனெனில் Apk கோப்புகள் சிதைந்துள்ளன, தயவுசெய்து மீண்டும் முயற்சிக்கவும். + MIUI உகப்பாக்கம் இயக்கப்பட்டிருப்பதால் நிறுவல் தோல்வியடைந்தது. MIUI உகப்பாக்கத்தை முடக்கு, பின்னர் மீண்டும் முயற்சிக்கவும். + Apk கையொப்ப சரிபார்ப்பு இயக்கப்பட்டிருப்பதால் நிறுவல் தோல்வியடைந்தது. Apk கையொப்ப சரிபார்ப்பை முடக்கு, பின்னர் மீண்டும் முயற்சிக்கவும். + சாதனம் போதுமான இலவச இடம் இல்லை என்பதால் நிறுவல் தோல்வியடைந்தது. + நிறுவியிலிருந்து கருப்பு / இருண்ட கருப்பொருளுக்கான Apk கோப்பைக் கண்டுபிடிப்பதில் தோல்வி. மேலாளரின் பயன்பாட்டுத் தரவை அழிக்கவும், பின்னர் மீண்டும் முயற்சிக்கவும். + பிளவு நிறுவலுக்குப் பிறகு பங்கு YouTube நிறுவல் பாதையை கண்டுபிடிப்பதில் தோல்வி. diff --git a/app/src/main/res/values-th-rTH/strings.xml b/app/src/main/res/values-th-rTH/strings.xml index da23ef3b42..b48b43af35 100644 --- a/app/src/main/res/values-th-rTH/strings.xml +++ b/app/src/main/res/values-th-rTH/strings.xml @@ -1,120 +1,120 @@ - ยกเลิก - ปิด - การปรับใช้ GMS แบบกำหนดเองสำหรับ Vanced ตามโครงการ microG - ไคลเอนต์ YouTube ที่ได้รับการแก้ไขพร้อมคุณสมบัติที่มีประโยชน์มากมาย! - Vanced สำหรับ YouTube Music! คุณสมบัติค่อนข้างน้อย แต่ตอบสนองความต้องการของคุณ - ล้างค่าเริ่มต้น - บันทึก - เลือกแอปพลิเคชันของคุณ + ยกเลิก + ปิด + การปรับใช้ GMS แบบกำหนดเองสำหรับ Vanced ตามโครงการ microG + ไคลเอนต์ YouTube ที่ได้รับการแก้ไขพร้อมคุณสมบัติที่มีประโยชน์มากมาย! + Vanced สำหรับ YouTube Music! คุณสมบัติค่อนข้างน้อย แต่ตอบสนองความต้องการของคุณ + ล้างค่าเริ่มต้น + บันทึก + เลือกแอปพลิเคชันของคุณ - ข้อมูลเกี่ยวกับทีมนักพัฒนา - แนะนำ - ตัวจัดการ - บันทึกข้อมูลระบบ - ตั้งค่า - อัพเดทตัวจัดการ + ข้อมูลเกี่ยวกับทีมนักพัฒนา + แนะนำ + ตัวจัดการ + บันทึกข้อมูลระบบ + ตั้งค่า + อัพเดทตัวจัดการ - อุปกรณ์ของคุณได้รูทหรือไม่? - ให้สิทธิ์การใช้งานของรูท - เริ่มกันเลย! - เลือกแอปพลิเคชั่นอย่างน้อยหนึ่งรายการ! - ไม่รู้/ไม่ต้องการใช้เวอร์ชั่นรูท? แค่คลิ๊กบนไอคอนธนูสีฟ้า! + อุปกรณ์ของคุณได้รูทหรือไม่? + ให้สิทธิ์การใช้งานของรูท + เริ่มกันเลย! + เลือกแอปพลิเคชั่นอย่างน้อยหนึ่งรายการ! + ไม่รู้/ไม่ต้องการใช้เวอร์ชั่นรูท? แค่คลิ๊กบนไอคอนธนูสีฟ้า! - เกี่ยวกับ %1$s - ดาวน์โหลด - ข้อมูล - เปิด - Reinstall - ถอนการติดตั้ง - อัพเดท - แอป - บันทึกการเปลี่ยนแปลง - กำลังดาวน์โหลด %1$s - ติดตั้ง + เกี่ยวกับ %1$s + ดาวน์โหลด + ข้อมูล + เปิด + Reinstall + ถอนการติดตั้ง + อัพเดท + แอป + บันทึกการเปลี่ยนแปลง + กำลังดาวน์โหลด %1$s + ติดตั้ง ล่าสุด: - ติดตั้ง Vanced microG ก่อน + ติดตั้ง Vanced microG ก่อน ไม่ได้รับสิทธิ์ของรูท - สื่อสังคม - สนับสนุนพวกเรา - ไม่สามารถใช้ได้ + สื่อสังคม + สนับสนุนพวกเรา + ไม่สามารถใช้ได้ ติดตั้งแล้ว: - สีหลัก - ลักษณะที่ปรากฏ - ลักษณะการทำงาน - ล้างไฟล์ที่ดาวน์โหลดไว้ - ล้างข้อมูลเรียบร้อยแล้ว - สำหรับ รวบรวมข้อมูลเกี่ยวกับประสิทธิภาพของแอป และบันทึกข้อขัดข้อง - การวิเคราะห์ Firebase - ภาษา - ลิ้งค์จะเปิดไปยังแท็บที่กำหนดเองของ Chrome - ใช้แท็บที่กำหนดเองของ Chrome - %1$s การแจ้งเตือนแบบพุช - รับการแจ้งเตือนแบบพุช เมื่อมีการเผยแพร่อัปเดต %1$s ล่าสุด - Failed to save new time value - Root Script Sleep Time - Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues - ค่าเริ่มต้นของระบบ - ธีม - ธีมมืด - ธีมสว่าง - การจัดการอัพเดพหลัก - ไม่มีอัพเดตใหม่ - ตัวแปร + สีหลัก + ลักษณะที่ปรากฏ + ลักษณะการทำงาน + ล้างไฟล์ที่ดาวน์โหลดไว้ + ล้างข้อมูลเรียบร้อยแล้ว + สำหรับ รวบรวมข้อมูลเกี่ยวกับประสิทธิภาพของแอป และบันทึกข้อขัดข้อง + การวิเคราะห์ Firebase + ภาษา + ลิ้งค์จะเปิดไปยังแท็บที่กำหนดเองของ Chrome + ใช้แท็บที่กำหนดเองของ Chrome + %1$s การแจ้งเตือนแบบพุช + รับการแจ้งเตือนแบบพุช เมื่อมีการเผยแพร่อัปเดต %1$s ล่าสุด + Failed to save new time value + Root Script Sleep Time + Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues + ค่าเริ่มต้นของระบบ + ธีม + ธีมมืด + ธีมสว่าง + การจัดการอัพเดพหลัก + ไม่มีอัพเดตใหม่ + ตัวแปร - ไม่สามารถบันทึกได้ - ดำเนินการบันทึกเรียบร้อยแล้ว + ไม่สามารถบันทึกได้ + ดำเนินการบันทึกเรียบร้อยแล้ว รายละเอียด - %1$s ตรวจพบไฟล์สำหรับการติดตั้ง! - ตรวจพบการอัพเดทไฟล์สำหรับติดตั้งใหม่ที่จำเป็น %1$s คุณต้องการติดตั้งหรือไม่? + %1$s ตรวจพบไฟล์สำหรับการติดตั้ง! + ตรวจพบการอัพเดทไฟล์สำหรับติดตั้งใหม่ที่จำเป็น %1$s คุณต้องการติดตั้งหรือไม่? %1$s กำหนดค่าการติดตั้ง - ตรวจหาการปรับปรุงใหม่ๆ… + ตรวจหาการปรับปรุงใหม่ๆ… ภาษา: %1$s ธีม: %1$s รุ่น: %1$s - ผิดพลาด - คู่มือ - หยุด! + ผิดพลาด + คู่มือ + หยุด! คุณกำลังใช้ Vanced เวอร์ชัน Magisk / TWRP ซึ่งถูกยกเลิกและไม่สามารถอัปเดตได้จากแอปนี้ กรุณาลบออกโดยการถอดโมดูล Magisk / ใช้โปรแกรมถอนการติดตั้ง TWRP Vanced - ในการติดตั้ง Vanced คุณต้องปิดใช้งาน การเพิ่มประสิทธิภาพ MIUI ในการตั้งค่าสำหรับนักพัฒนา (คุณสามารถเพิกเฉยต่อคำเตือนนี้ได้ หากคุณใช้ based ROM xiaomi.eu 20.2.20 หรือใหม่กว่า) - เปิดใช้งานการเพิ่มประสิทธิภาพ MIUI แล้ว! - โปรดอย่าออกจากแอปในระหว่างขั้นตอนนี้! - ดาวน์โหลดอีกครั้ง - ตรวจสอบให้แน่ใจว่าคุณดาวน์โหลดแอพจากช่องทางที่ถูกต้อง vancedapp.com, เซิร์ฟเวอร์ Vanced Discord หรือ Vanced GitHub + ในการติดตั้ง Vanced คุณต้องปิดใช้งาน การเพิ่มประสิทธิภาพ MIUI ในการตั้งค่าสำหรับนักพัฒนา (คุณสามารถเพิกเฉยต่อคำเตือนนี้ได้ หากคุณใช้ based ROM xiaomi.eu 20.2.20 หรือใหม่กว่า) + เปิดใช้งานการเพิ่มประสิทธิภาพ MIUI แล้ว! + โปรดอย่าออกจากแอปในระหว่างขั้นตอนนี้! + ดาวน์โหลดอีกครั้ง + ตรวจสอบให้แน่ใจว่าคุณดาวน์โหลดแอพจากช่องทางที่ถูกต้อง vancedapp.com, เซิร์ฟเวอร์ Vanced Discord หรือ Vanced GitHub รุ่น - ยินดีต้อนรับ + ยินดีต้อนรับ - เลือกภาษาที่คุณต้องการใช้สำหรับ Vanced - ล่าสุด + เลือกภาษาที่คุณต้องการใช้สำหรับ Vanced + ล่าสุด เบา + %1$s เลือกอย่างน้อยหนึ่งภาษา! - สีดำ - สีเข้ม + สีดำ + สีเข้ม - ตัวจัดการ Devs - ผู้ร่วมให้ข้อมูลอื่น ๆ - แหล่งที่มา - ทีมงาน Vanced + ตัวจัดการ Devs + ผู้ร่วมให้ข้อมูลอื่น ๆ + แหล่งที่มา + ทีมงาน Vanced - ไม่สามารถ `chown` APK ในระบบได้ โปรดลองอีกครั้ง - เกิดข้อผิดพลาดในการดาวน์โหลด %1$s + ไม่สามารถ `chown` APK ในระบบได้ โปรดลองอีกครั้ง + เกิดข้อผิดพลาดในการดาวน์โหลด %1$s การใช้สีที่เน้นใหม่มีความผิดพลาด - ถอนการติดตั้งแพ็กเกจไม่สำเร็จ %1$s - ไม่สามารถค้นหาไฟล์สำหรับการติดตั้งที่ต้องการได้. กรุณาดาวน์โหลดไฟล์สำหรับการติดตั้งใหม่แล้วลองอีกครั้ง - ไม่พบไฟล์ apk สำหรับธีมสีดำ / สีเข้ม จากที่เก็บข้อมูล โปรดลองอีกครั้ง - การติดตั้งล้มเหลวเนื่องจากผู้ใช้ยกเลิกการติดตั้ง - การติดตั้งล้มเหลวเนื่องจากแอปขัดแย้งกับแอปที่ติดตั้งไว้ก่อนหน้า ถอนการติดตั้งแอปเวอร์ชันปัจจุบันแล้วลองอีกครั้ง - การติดตั้งล้มเหลวเนื่องจากผู้ใช้พยายามดาวน์เกรดแพ็กเกจ ถอนการติดตั้งการอัปเดตจากแอปเดิมก่อน แล้วลองอีกครั้ง - การติดตั้งล้มเหลวโดยไม่ทราบสาเหตุเข้าร่วม Telegram หรือ Discord ของเราเพื่อรับการสนับสนุนเพิ่มเติม โปรดแนบภาพหน้าจอจากเมนู - การติดตั้งล้มเหลวเนื่องจากไฟล์การติดตั้งเข้ากันไม่ได้กับอุปกรณ์ของคุณ กรุณาล้างไฟล์ที่ดาวน์โหลดในการตั้งค่า แล้วลองอีกครั้ง - การติดตั้งล้มเหลวเนื่องจากไฟล์ apk เสียหายโปรดลองอีกครั้ง - การติดตั้งล้มเหลวเนื่องจากเปิดใช้งาน MIUI Optimization โปรดปิดการใช้งาน MIUI Optimization แล้วลองอีกครั้ง - การติดตั้งล้มเหลวเนื่องจากเปิดใช้งานการตรวจสอบลายเซ็น apk กรุณาปิดใช้งานการตรวจสอบลายเซ็น apk แล้วลองอีกครั้ง - การติดตั้งล้มเหลวเนื่องจากอุปกรณ์มีพื้นที่ว่างไม่เพียงพอ - ไม่พบไฟล์ apk สำหรับธีมสีดำ / สีเข้มจากโปรแกรมติดตั้ง กรุณาล้างข้อมูลแอปVanced-Manager แล้วลองอีกครั้ง - ไม่พบเส้นทางการติดตั้งสต็อกของ YouTube หลังจากการติดตั้งแบบแยก + ถอนการติดตั้งแพ็กเกจไม่สำเร็จ %1$s + ไม่สามารถค้นหาไฟล์สำหรับการติดตั้งที่ต้องการได้. กรุณาดาวน์โหลดไฟล์สำหรับการติดตั้งใหม่แล้วลองอีกครั้ง + ไม่พบไฟล์ apk สำหรับธีมสีดำ / สีเข้ม จากที่เก็บข้อมูล โปรดลองอีกครั้ง + การติดตั้งล้มเหลวเนื่องจากผู้ใช้ยกเลิกการติดตั้ง + การติดตั้งล้มเหลวเนื่องจากแอปขัดแย้งกับแอปที่ติดตั้งไว้ก่อนหน้า ถอนการติดตั้งแอปเวอร์ชันปัจจุบันแล้วลองอีกครั้ง + การติดตั้งล้มเหลวเนื่องจากผู้ใช้พยายามดาวน์เกรดแพ็กเกจ ถอนการติดตั้งการอัปเดตจากแอปเดิมก่อน แล้วลองอีกครั้ง + การติดตั้งล้มเหลวโดยไม่ทราบสาเหตุเข้าร่วม Telegram หรือ Discord ของเราเพื่อรับการสนับสนุนเพิ่มเติม โปรดแนบภาพหน้าจอจากเมนู + การติดตั้งล้มเหลวเนื่องจากไฟล์การติดตั้งเข้ากันไม่ได้กับอุปกรณ์ของคุณ กรุณาล้างไฟล์ที่ดาวน์โหลดในการตั้งค่า แล้วลองอีกครั้ง + การติดตั้งล้มเหลวเนื่องจากไฟล์ apk เสียหายโปรดลองอีกครั้ง + การติดตั้งล้มเหลวเนื่องจากเปิดใช้งาน MIUI Optimization โปรดปิดการใช้งาน MIUI Optimization แล้วลองอีกครั้ง + การติดตั้งล้มเหลวเนื่องจากเปิดใช้งานการตรวจสอบลายเซ็น apk กรุณาปิดใช้งานการตรวจสอบลายเซ็น apk แล้วลองอีกครั้ง + การติดตั้งล้มเหลวเนื่องจากอุปกรณ์มีพื้นที่ว่างไม่เพียงพอ + ไม่พบไฟล์ apk สำหรับธีมสีดำ / สีเข้มจากโปรแกรมติดตั้ง กรุณาล้างข้อมูลแอปVanced-Manager แล้วลองอีกครั้ง + ไม่พบเส้นทางการติดตั้งสต็อกของ YouTube หลังจากการติดตั้งแบบแยก diff --git a/app/src/main/res/values-tr-rTR/strings.xml b/app/src/main/res/values-tr-rTR/strings.xml index 51572d4c07..5fb329db1d 100644 --- a/app/src/main/res/values-tr-rTR/strings.xml +++ b/app/src/main/res/values-tr-rTR/strings.xml @@ -1,120 +1,120 @@ - İptal - Kapat - Vanced için geliştirilmiş microG Projesi tabanlı GMH sürümü. - İşe yarar birçok özellikle modifiye edilmiş YouTube sürümü! - Yine Vanced, ama YouTube Music için! Kıyasen daha az özelliğe sahip ama beklentilerini karşılayacaktır. - Sıfırla - Kaydet - Uygulamalarınızı Seçin + İptal + Kapat + Vanced için geliştirilmiş microG Projesi tabanlı GMH sürümü. + İşe yarar birçok özellikle modifiye edilmiş YouTube sürümü! + Yine Vanced, ama YouTube Music için! Kıyasen daha az özelliğe sahip ama beklentilerini karşılayacaktır. + Sıfırla + Kaydet + Uygulamalarınızı Seçin - Hakkında - Rehber - Manager - Geçmiş kayıtlar - Ayarlar - Manager\'ı güncelle + Hakkında + Rehber + Manager + Geçmiş kayıtlar + Ayarlar + Manager\'ı güncelle - Cihazın rootlu mu? - Root yetkisi ver - Haydi başlayalım - En az bir uygulama seçin! - Root\'un ne olduğunu bilmiyor veya root sürümünü kullanmak istemiyorsan, alttaki mavi oka tıklayabilirsin! + Cihazın rootlu mu? + Root yetkisi ver + Haydi başlayalım + En az bir uygulama seçin! + Root\'un ne olduğunu bilmiyor veya root sürümünü kullanmak istemiyorsan, alttaki mavi oka tıklayabilirsin! - %1$s hakkında - İndir - Bilgi - Başlat - Yeniden yükle - Kaldır - Güncelleştir - Uygulamalar - Sürüm Notları - %1$s indiriliyor - Yükle + %1$s hakkında + İndir + Bilgi + Başlat + Yeniden yükle + Kaldır + Güncelleştir + Uygulamalar + Sürüm Notları + %1$s indiriliyor + Yükle En son: - Vanced microG\'yi kurmalısın + Vanced microG\'yi kurmalısın Root erişimi verilmedi - Sosyal Medya - Tıkla, destek ol - Yüklenmemiş + Sosyal Medya + Tıkla, destek ol + Yüklenmemiş Yüklü: - Tema Rengi - Görünüm - Davranış - İndirilen dosyaları temizle - Dosyalar başarıyla temizlendi - Uygulama hakkında performans ve hata kayıtlarını toplamamıza izin verir - Firebase Analizi - Dil - Bağlantılar Chrome Özel Sekmelerinde açılacaktır - Chrome Özel Sekmelerini kullan - %1$s Anlık Bildirimleri - %1$s için bir güncelleme yayınlandığında anlık bildirimler alın - Yeni zaman değeri kaydedilemedi - Root kurulumu, bekletme süresi - [Gelişmiş] Kurulum sırasında çalıştırılan /data/adb/service.d/app.sh dosyasındaki uyku/bekletme süresinin değer ayarı. Kurulum sırasında oluşan hatalara çözüm olabilir - Sistem varsayılanı - Tema - Koyu Tema - Açık Tema - Manager Güncelleme Merkezi - Yeni güncelleme yok - Sürüm yapısı + Tema Rengi + Görünüm + Davranış + İndirilen dosyaları temizle + Dosyalar başarıyla temizlendi + Uygulama hakkında performans ve hata kayıtlarını toplamamıza izin verir + Firebase Analizi + Dil + Bağlantılar Chrome Özel Sekmelerinde açılacaktır + Chrome Özel Sekmelerini kullan + %1$s Anlık Bildirimleri + %1$s için bir güncelleme yayınlandığında anlık bildirimler alın + Yeni zaman değeri kaydedilemedi + Root kurulumu, bekletme süresi + [Gelişmiş] Kurulum sırasında çalıştırılan /data/adb/service.d/app.sh dosyasındaki uyku/bekletme süresinin değer ayarı. Kurulum sırasında oluşan hatalara çözüm olabilir + Sistem varsayılanı + Tema + Koyu Tema + Açık Tema + Manager Güncelleme Merkezi + Yeni güncelleme yok + Sürüm yapısı - Kayıtlar kaydedilemedi - Kayıtlar başarıyla kaydedildi + Kayıtlar kaydedilemedi + Kayıtlar başarıyla kaydedildi Ayrıntılar - %1$s için kurulum dosyaları bulundu! - Manager, %1$s kurulumu için gerekli olan dosyaları belirledi. Yüklemek ister misiniz? + %1$s için kurulum dosyaları bulundu! + Manager, %1$s kurulumu için gerekli olan dosyaları belirledi. Yüklemek ister misiniz? %1$s Kurulum Tercihleri - Güncellemeler kontrol ediliyor… + Güncellemeler kontrol ediliyor… Dil(ler): %1$s Tema: %1$s Sürüm: %1$s - Hata - Kılavuz - Durdur! + Hata + Kılavuz + Durdur! Geliştirilmesi durdurulan ve bu uygulama ile güncellenemeyen Vanced\'ın, Magisk/TWRP sürümünü kullanıyorsunuz. Lütfen Magisk/TWRP sürümünü cihazınızdan kaldırın. - Vanced\'ı yükleyebilmek için, geliştirici ayarlarından/seçeneklerinden MIUI optimizasyonunu devre dışı bırakmalısın. (xiaomi.eu tabanlı 20.2.20 sürüm veya üzeri ROM kullanıyorsan, bu uyarıyı göz ardı edebilirsin) - MIUI Optimizasyonu aktif gözüküyor! - İşlem süresince LÜTFEN uygulamadan çıkmayın! - Tekrar İndir - Uygulamayı vancedapp.com, Vanced Discord sunucusu, veya Vanced GitHub\'dan indirdiğinizden emin olun + Vanced\'ı yükleyebilmek için, geliştirici ayarlarından/seçeneklerinden MIUI optimizasyonunu devre dışı bırakmalısın. (xiaomi.eu tabanlı 20.2.20 sürüm veya üzeri ROM kullanıyorsan, bu uyarıyı göz ardı edebilirsin) + MIUI Optimizasyonu aktif gözüküyor! + İşlem süresince LÜTFEN uygulamadan çıkmayın! + Tekrar İndir + Uygulamayı vancedapp.com, Vanced Discord sunucusu, veya Vanced GitHub\'dan indirdiğinizden emin olun Sürüm - Hoş Geldiniz + Hoş Geldiniz - Vanced için tercih ettiğiniz dil(ler)i seçin - En yeni + Vanced için tercih ettiğiniz dil(ler)i seçin + En yeni Açık renk + %1$s En az bir dil seçmelisin! - Siyah (amoled) - Koyu renk + Siyah (amoled) + Koyu renk - Manager Geliştiricileri - Katkıda bulunan diğer kişiler - Kaynaklar - Vanced Ekibi + Manager Geliştiricileri + Katkıda bulunan diğer kişiler + Kaynaklar + Vanced Ekibi - APK dosyasına sistem yetkisi atanamadı, lütfen tekrar deneyin. - %1$s indirilirken hata oluştu + APK dosyasına sistem yetkisi atanamadı, lütfen tekrar deneyin. + %1$s indirilirken hata oluştu Yeni vurgu rengi uygulanamadı - %1$s kaldırılırken hata oluştu - Kurulum için gerekli olan dosyaları belirlerken bir hata oluştu. Kurulum dosyalarını tekrar indirip, yeniden deneyin. - Depolama alanında Siyah/Koyu temanın APK dosyasını belirlerken bir hata oluştu. Tekrar deneyin lütfen. - Kullanıcı kurulumu iptal ettiği için kurulum başarısız oldu. - Uygulama önceden yüklenmiş bir uygulamayla çakıştığından yükleme başarısız oldu. Uygulamanın mevcut sürümünü kaldırın ve ardından tekrar deneyin. - Kullanıcı eski sürümü yüklemeye çalıştığı için kurulum tamamlanamadı. Orijinal YouTube uygulamasının güncellemelerini kaldırdıktan sonra yeniden deneyin. - Kurulum, bilinmeyen sebeplerden dolayı başarısız oldu. Telegram grubu veya Discord sunucusundan destek alabilirsin. Ayrıca, detaylar ekranının bir ekran görüntüsünü alıp, yardım talebinle birlikte iletmeyi unutma lütfen. - Kurulum dosyası cihazınız ile uyumsuz olduğu için kurulum işlemi başarısız oldu. Ayarlar\'da indirilen dosyaları temizleyip, tekrar deneyin. - APK dosyaları çözümlenemediğinden, kurulum başarısız oldu. Lütfen yeniden deneyin. - MIUI Optimizasyonu etkin olduğundan, kurulum başarısız oldu. MIUI Optimizasyonunu devre dışı bırakıp, yeniden deneyin. - APK imza doğrulaması etkin olduğundan, kurulum başarısız oldu. APK imza doğrulamasını devre dışı bırakıp, yeniden deneyin. - Yetersiz depolama alanından dolayı kurulum başarısız oldu. - Yükleyicide Siyah/Koyu tema için APK dosyalarını ararken bir hata oluştu. Manager\'ın verilerini temizleyip, yeniden deneyin. - Ayrı kurulum işleminden sonra orijinal YouTube kurulum yolu belirlenemedi. + %1$s kaldırılırken hata oluştu + Kurulum için gerekli olan dosyaları belirlerken bir hata oluştu. Kurulum dosyalarını tekrar indirip, yeniden deneyin. + Depolama alanında Siyah/Koyu temanın APK dosyasını belirlerken bir hata oluştu. Tekrar deneyin lütfen. + Kullanıcı kurulumu iptal ettiği için kurulum başarısız oldu. + Uygulama önceden yüklenmiş bir uygulamayla çakıştığından yükleme başarısız oldu. Uygulamanın mevcut sürümünü kaldırın ve ardından tekrar deneyin. + Kullanıcı eski sürümü yüklemeye çalıştığı için kurulum tamamlanamadı. Orijinal YouTube uygulamasının güncellemelerini kaldırdıktan sonra yeniden deneyin. + Kurulum, bilinmeyen sebeplerden dolayı başarısız oldu. Telegram grubu veya Discord sunucusundan destek alabilirsin. Ayrıca, detaylar ekranının bir ekran görüntüsünü alıp, yardım talebinle birlikte iletmeyi unutma lütfen. + Kurulum dosyası cihazınız ile uyumsuz olduğu için kurulum işlemi başarısız oldu. Ayarlar\'da indirilen dosyaları temizleyip, tekrar deneyin. + APK dosyaları çözümlenemediğinden, kurulum başarısız oldu. Lütfen yeniden deneyin. + MIUI Optimizasyonu etkin olduğundan, kurulum başarısız oldu. MIUI Optimizasyonunu devre dışı bırakıp, yeniden deneyin. + APK imza doğrulaması etkin olduğundan, kurulum başarısız oldu. APK imza doğrulamasını devre dışı bırakıp, yeniden deneyin. + Yetersiz depolama alanından dolayı kurulum başarısız oldu. + Yükleyicide Siyah/Koyu tema için APK dosyalarını ararken bir hata oluştu. Manager\'ın verilerini temizleyip, yeniden deneyin. + Ayrı kurulum işleminden sonra orijinal YouTube kurulum yolu belirlenemedi. diff --git a/app/src/main/res/values-uk-rUA/strings.xml b/app/src/main/res/values-uk-rUA/strings.xml index ee64b4c47a..cb832ace2e 100644 --- a/app/src/main/res/values-uk-rUA/strings.xml +++ b/app/src/main/res/values-uk-rUA/strings.xml @@ -1,120 +1,120 @@ - Скасувати - Закрити - Модифікований GMS для Vanced на основі проекту microG. - Модифікований клієнт YouTube з безліччю корисних функцій! - Vanced, але для YouTube Music! Відносно менш функціональний, але задовольняє ваші потреби. - Скинути - Зберегти - Виберіть Ваші Додатки + Скасувати + Закрити + Модифікований GMS для Vanced на основі проекту microG. + Модифікований клієнт YouTube з безліччю корисних функцій! + Vanced, але для YouTube Music! Відносно менш функціональний, але задовольняє ваші потреби. + Скинути + Зберегти + Виберіть Ваші Додатки - Про нас - Посібник - Менеджер - Логи - Налаштування - Оновіть Менеджер + Про нас + Посібник + Менеджер + Логи + Налаштування + Оновіть Менеджер - На Пристрої Є Root Права? - Надати Root Права - Почнімо - Оберіть принаймні один додаток! - Не знаєте, що це або не хочете використовувати рутовану версію? Просто натисніть синю стрілку внизу! + На Пристрої Є Root Права? + Надати Root Права + Почнімо + Оберіть принаймні один додаток! + Не знаєте, що це або не хочете використовувати рутовану версію? Просто натисніть синю стрілку внизу! - Про %1$s - Download - Інформація - Відкрити - Reinstall - Видалити - Update - Додатки - Список змін - Завантаження %1$s - Встановити + Про %1$s + Download + Інформація + Відкрити + Reinstall + Видалити + Update + Додатки + Список змін + Завантаження %1$s + Встановити Найновіша: - Спочатку встановіть Vanced microG + Спочатку встановіть Vanced microG Права суперкористувача не були надані - Соціальні мережі - Підтримайте нас - Недоступно + Соціальні мережі + Підтримайте нас + Недоступно Встановлена: - Вторинний колір - Вигляд - Поведінка - Очистити завантажені файли - Файли було успішно очищено - Це дозволяє нам збирати інформацію про продуктивність додатка та журнали збоїв - Аналітика Firebase - Мова - Відкривати посилання в Chrome Custom Tabs - Використовувати Chrome Custom Tabs - %1$s Спливаючі Сповіщення - Отримувати спливаючі сповіщення, коли доступне оновлення для %1$s - Не вдалося зберегти нове значення часу - Скрипт Таймера сну - Налаштування значення часу сну, використовуваного в скрипті /data/adb/service.d/app.sh, корисно для вирішення проблем монтування - Системна - Тема - Темна тема - Світла тема - Центр Оновлень - Оновлень не знайдено - Варіант + Вторинний колір + Вигляд + Поведінка + Очистити завантажені файли + Файли було успішно очищено + Це дозволяє нам збирати інформацію про продуктивність додатка та журнали збоїв + Аналітика Firebase + Мова + Відкривати посилання в Chrome Custom Tabs + Використовувати Chrome Custom Tabs + %1$s Спливаючі Сповіщення + Отримувати спливаючі сповіщення, коли доступне оновлення для %1$s + Не вдалося зберегти нове значення часу + Скрипт Таймера сну + Налаштування значення часу сну, використовуваного в скрипті /data/adb/service.d/app.sh, корисно для вирішення проблем монтування + Системна + Тема + Темна тема + Світла тема + Центр Оновлень + Оновлень не знайдено + Варіант - Не вдалося зберегти логи - Логи успішно збережені + Не вдалося зберегти логи + Логи успішно збережені Детальніше - Знайдено %1$s файлів для встановлення! - Менеджер виявив, що всі необхідні файли для %1$s встановлення було знайдено. Бажаєте встановити їх? + Знайдено %1$s файлів для встановлення! + Менеджер виявив, що всі необхідні файли для %1$s встановлення було знайдено. Бажаєте встановити їх? Параметри встановлення %1$s - Перевірка оновлень… + Перевірка оновлень… Мова(и): %1$s Тема: %1$s Версія: %1$s - Помилка - Гайд - Зупинись! + Помилка + Гайд + Зупинись! Ви використовуєте Magisk/TWRP версію Vanced, яка припиняється і не може бути оновлена за допомогою цього застосунку. Будь ласка, видаліть його, видаливши модуль Magisk / з використання TWRP Vanced uninstaller. - Щоб встановити Vanced, ви ПОВИННІ вимкнути оптимізацію MIUI у налаштуваннях розробника. (Ви можете ігнорувати це попередження якщо ви використовуєте 20.2.20 або новіші xiaomi.eu ROM) - Оптимізацію MIUI увімкнено! - Будь ласка, НЕ завершуйте роботу додатку під час цього процесу! - Завантажити заново - Переконайтеся, що ви завантажили додаток з vancedapp.com, Vanced Discord сервер або Vanced GitHub + Щоб встановити Vanced, ви ПОВИННІ вимкнути оптимізацію MIUI у налаштуваннях розробника. (Ви можете ігнорувати це попередження якщо ви використовуєте 20.2.20 або новіші xiaomi.eu ROM) + Оптимізацію MIUI увімкнено! + Будь ласка, НЕ завершуйте роботу додатку під час цього процесу! + Завантажити заново + Переконайтеся, що ви завантажили додаток з vancedapp.com, Vanced Discord сервер або Vanced GitHub Версія - Привіт! + Привіт! - Виберіть бажану мову(и) для Vanced - Найновіша + Виберіть бажану мову(и) для Vanced + Найновіша Світла + %1$s Оберіть принаймні одну мову! - Чорний - Темний + Чорний + Темний - Розробники Менеджера - Інші учасники - Джерела - Команда Vanced + Розробники Менеджера + Інші учасники + Джерела + Команда Vanced - Не вдалося створити файл APK системного власника програми, будь ласка, повторіть спробу. - Помилка Завантаження %1$s + Не вдалося створити файл APK системного власника програми, будь ласка, повторіть спробу. + Помилка Завантаження %1$s Не вдалося застосувати новий другорядний колір - Не вдалося видалити пакет %1$s - Не вдалося знайти необхідні файли для встановлення. Повторно завантажте файли і спробуйте ще раз. - Не вдалося знайти apk-файл для чорної/темної теми зі сховища, спробуйте ще раз. - Встановлення не вдалося, оскільки користувач перервав встановлення. - Встановлення не вдалася, так як додаток конфліктує з уже встановленим додатком. Видаліть поточну версію додатку, і спробуйте ще раз. - Встановлення не вдалася, так як користувач спробував знизити версію програми. Видаліть поновлення звичайного додатку YouTube, спробуйте ще раз. - Не вдалося встановити з невідомих причин, підключіться до нашої Telegram групи або Discord сервера для подальшої підтримки. Будь ласка, додайте знімок екрану з розширеного меню - Помилка встановлення, оскільки файл несумісний з вашим пристроєм. Очистіть завантажені файли в Налаштуваннях, а потім спробуйте ще раз. - Встановлення неможливе, оскільки apk-файли пошкоджені, будь ласка, спробуйте ще раз. - Помилка встановлення, оскільки увімкнена оптимізація MIUI. Вимкніть оптимізацію MIUI і спробуйте ще раз. - Помилка встановлення, оскільки увімкнено перевірку підпису apk. Вимкніть перевірку підпису apk, а потім спробуйте ще раз. - Помилка встановлення, так як на пристрої недостатньо вільного місця. - Не вдалося знайти apk-файл для чорної/темної теми в програмі встановлення. Видаліть дані додатка з Менеджера і спробуйте ще раз. - Не вдалося знайти типовий шлях встановлення YouTube після роздільного встановлення. + Не вдалося видалити пакет %1$s + Не вдалося знайти необхідні файли для встановлення. Повторно завантажте файли і спробуйте ще раз. + Не вдалося знайти apk-файл для чорної/темної теми зі сховища, спробуйте ще раз. + Встановлення не вдалося, оскільки користувач перервав встановлення. + Встановлення не вдалася, так як додаток конфліктує з уже встановленим додатком. Видаліть поточну версію додатку, і спробуйте ще раз. + Встановлення не вдалася, так як користувач спробував знизити версію програми. Видаліть поновлення звичайного додатку YouTube, спробуйте ще раз. + Не вдалося встановити з невідомих причин, підключіться до нашої Telegram групи або Discord сервера для подальшої підтримки. Будь ласка, додайте знімок екрану з розширеного меню + Помилка встановлення, оскільки файл несумісний з вашим пристроєм. Очистіть завантажені файли в Налаштуваннях, а потім спробуйте ще раз. + Встановлення неможливе, оскільки apk-файли пошкоджені, будь ласка, спробуйте ще раз. + Помилка встановлення, оскільки увімкнена оптимізація MIUI. Вимкніть оптимізацію MIUI і спробуйте ще раз. + Помилка встановлення, оскільки увімкнено перевірку підпису apk. Вимкніть перевірку підпису apk, а потім спробуйте ще раз. + Помилка встановлення, так як на пристрої недостатньо вільного місця. + Не вдалося знайти apk-файл для чорної/темної теми в програмі встановлення. Видаліть дані додатка з Менеджера і спробуйте ще раз. + Не вдалося знайти типовий шлях встановлення YouTube після роздільного встановлення. diff --git a/app/src/main/res/values-vi-rVN/strings.xml b/app/src/main/res/values-vi-rVN/strings.xml index 7b02be3fce..c1bbe1183a 100644 --- a/app/src/main/res/values-vi-rVN/strings.xml +++ b/app/src/main/res/values-vi-rVN/strings.xml @@ -1,120 +1,120 @@ - Hủy - Đóng - GMS Nhúng đã được tuỳ chỉnh cho Vanced dựa trên Dự án microG. - Một ứng dụng YouTube đã được sửa đổi với nhiều tính năng hữu ích! - Vanced, nhưng cho YouTube Music! Khá ít tính năng nhưng đáp ứng được nhu cầu của bạn. - Đặt lại - Lưu - Chọn ứng dụng của bạn + Hủy + Đóng + GMS Nhúng đã được tuỳ chỉnh cho Vanced dựa trên Dự án microG. + Một ứng dụng YouTube đã được sửa đổi với nhiều tính năng hữu ích! + Vanced, nhưng cho YouTube Music! Khá ít tính năng nhưng đáp ứng được nhu cầu của bạn. + Đặt lại + Lưu + Chọn ứng dụng của bạn - Giới thiệu - Hướng dẫn - Manager - Nhật ký - Cài đặt - Cập nhật Manager + Giới thiệu + Hướng dẫn + Manager + Nhật ký + Cài đặt + Cập nhật Manager - Thiết Bị Của Bạn Đã Được Root? - Cấp quyền root - Bắt đầu - Chọn ít nhất một ứng dụng! - Bạn không biết đây là gì hoặc không muốn sử dụng phiên bản root? hãy nhấp vào dấu > bên dưới! + Thiết Bị Của Bạn Đã Được Root? + Cấp quyền root + Bắt đầu + Chọn ít nhất một ứng dụng! + Bạn không biết đây là gì hoặc không muốn sử dụng phiên bản root? hãy nhấp vào dấu > bên dưới! - Thông tin về %1$s - Tải xuống - Thông tin - Mở - Cài đặt lại - Gỡ cài đặt - Cập nhật - Các ứng dụng - Các thay đổi - Đang tải xuống %1$s - Cài đặt + Thông tin về %1$s + Tải xuống + Thông tin + Mở + Cài đặt lại + Gỡ cài đặt + Cập nhật + Các ứng dụng + Các thay đổi + Đang tải xuống %1$s + Cài đặt Mới nhất: - Bạn phải cài Vanced microG trước + Bạn phải cài Vanced microG trước Quyền root không được cấp - Mạng xã hội - Hỗ trợ chúng tôi - Chưa cài + Mạng xã hội + Hỗ trợ chúng tôi + Chưa cài Đã cài đặt: - Màu chủ đạo - Giao diện - Ứng dụng - Xóa các tệp tin đã tải về - Xóa các tệp tin thành công - Cho phép chúng tôi thu thập thông tin về hiệu suất và sự cố của ứng dụng - Firebase Analytics - Ngôn ngữ - Các liên kết sẽ mở trong Chrome Custom Tabs - Sử dụng Chrome Custom Tabs - Thông báo cho %1$s - Nhận thông báo khi một bản cập nhật của %1$s được phát hành - Lưu giá trị thời gian mới thất bại - Thời gian ngủ của tập lệnh root - Điều chỉnh giá trị thời gian ngủ được sử dụng trong tập lệnh /data/adb/service.d/app.sh, hữu ích khi khắc phục các vấn đề về mounting - Mặc định hệ thống - Nền - Nền tối - Nền sáng - Cập nhật Manager - Không có cập nhật mới - Phiên bản + Màu chủ đạo + Giao diện + Ứng dụng + Xóa các tệp tin đã tải về + Xóa các tệp tin thành công + Cho phép chúng tôi thu thập thông tin về hiệu suất và sự cố của ứng dụng + Firebase Analytics + Ngôn ngữ + Các liên kết sẽ mở trong Chrome Custom Tabs + Sử dụng Chrome Custom Tabs + Thông báo cho %1$s + Nhận thông báo khi một bản cập nhật của %1$s được phát hành + Lưu giá trị thời gian mới thất bại + Thời gian ngủ của tập lệnh root + Điều chỉnh giá trị thời gian ngủ được sử dụng trong tập lệnh /data/adb/service.d/app.sh, hữu ích khi khắc phục các vấn đề về mounting + Mặc định hệ thống + Nền + Nền tối + Nền sáng + Cập nhật Manager + Không có cập nhật mới + Phiên bản - Lưu nhật ký thất bại - Lưu nhật ký thành công + Lưu nhật ký thất bại + Lưu nhật ký thành công Chi tiết - Phát hiện tệp cài đặt của %1$s! - Manager đã tìm thấy tất cả các tệp cần thiết để cài đặt %1$s. Bạn có muốn cài đặt nó không? + Phát hiện tệp cài đặt của %1$s! + Manager đã tìm thấy tất cả các tệp cần thiết để cài đặt %1$s. Bạn có muốn cài đặt nó không? %1$s Tùy biến Cài đặt - Đang kiểm tra cập nhật… + Đang kiểm tra cập nhật… Ngôn ngữ: %1$s Nền: %1$s Phiên bản: %1$s - Lỗi - Hướng dẫn - Khoan đã! + Lỗi + Hướng dẫn + Khoan đã! Bạn đang sử dụng phiên bản Magisk/TWRP của Vanced, hiện đã bị ngừng phát triển và không thể được cập nhập bằng ứng dụng này. Hãy gỡ mô-đun Magisk/flash trình gỡ cài đặt TWRP. - Để cài Vanced, bạn PHẢI vô hiệu hóa Tối ưu hóa MIUI trong cài đặt nhà phát triển. (Bỏ qua cảnh báo này nếu bạn đang sử dụng ROM dựa trên xiaomi.eu phiên bản 20.2.20 hoặc mới hơn) - Tối ưu hoá MIUI đang được kích hoạt! - Vui lòng KHÔNG thoát khỏi ứng dụng trong tiến trình này! - Tải lại - Chắc chắn rằng bạn đã tải ứng dụng này từ vancedapp.com, server Discord của Vanced hoặc GitHub của Vanced + Để cài Vanced, bạn PHẢI vô hiệu hóa Tối ưu hóa MIUI trong cài đặt nhà phát triển. (Bỏ qua cảnh báo này nếu bạn đang sử dụng ROM dựa trên xiaomi.eu phiên bản 20.2.20 hoặc mới hơn) + Tối ưu hoá MIUI đang được kích hoạt! + Vui lòng KHÔNG thoát khỏi ứng dụng trong tiến trình này! + Tải lại + Chắc chắn rằng bạn đã tải ứng dụng này từ vancedapp.com, server Discord của Vanced hoặc GitHub của Vanced Phiên bản - Chào mừng + Chào mừng - Chọn ngôn ngữ mong muốn cho Vanced - Mới nhất + Chọn ngôn ngữ mong muốn cho Vanced + Mới nhất Sáng + %1$s Chọn ít nhất một ngôn ngữ! - Đen - Tối + Đen + Tối - Đội ngũ phát triển - Những người đóng góp khác - Nguồn - Đội ngũ Vanced + Đội ngũ phát triển + Những người đóng góp khác + Nguồn + Đội ngũ Vanced - Thay đổi quyền sở hữu APK cho chủ hệ thống thất bại, vui lòng thử lại. - Lỗi khi tải xuống %1$s + Thay đổi quyền sở hữu APK cho chủ hệ thống thất bại, vui lòng thử lại. + Lỗi khi tải xuống %1$s Áp dụng màu chủ đạo mới thất bại - Gỡ cài đặt %1$s thất bại - Không thể xác định các tệp tin cần thiết để cài đặt. Tải lại các tệp cài đặt rồi thử lại. - Xác định tệp tin apk cho nền đen/tối từ bộ nhớ thất bại, vui lòng thử lại. - Cài đặt thất bại do người dùng hủy. - Cài đặt thất bại do có xung đột với ứng dụng đã được cài đặt trước đó. Gỡ cài đặt phiên bản hiện tại của ứng dụng rồi thử lại. - Cài đặt thất bại do người dùng cố hạ cấp ứng dụng. Gỡ cài đặt các bản cập nhật khỏi ứng dụng gốc rồi thử lại. - Cài đặt thất bại do lí do không xác định, tham gia Telegram hoặc Discord để được hỗ trợ. Vui lòng kèm theo ảnh chụp màn hình từ phần Chi tiết - Cài đặt thất bại do tệp tin cài đặt không tương thích với thiết bị của bạn. Xóa các tệp tin đã tải về trong Cài đặt rồi thử lại. - Cài đặt thất bại do các tệp tin apk bị lỗi, xin hãy thử lại. - Cài đặt thất bại do Tối ưu hóa MIUI được kích hoạt. Vô hiệu hóa Tối ưu hóa MIUI rồi thử lại. - Cài đặt thất bại do xác minh chứng chỉ apk được kích hoạt. Vô hiệu hóa xác minh chứng chỉ apk rồi thử lại. - Cài đặt thất bại do thiết bị của bạn không có đủ bộ nhớ trống. - Tìm kiếm tệp tin apk cho nền đen/tối từ trình cài đặt thất bại. Xoá dữ liệu của Manager rồi thử lại. - Không thể xác định thư mục cài đặt của YouTube gốc sau khi tải split. + Gỡ cài đặt %1$s thất bại + Không thể xác định các tệp tin cần thiết để cài đặt. Tải lại các tệp cài đặt rồi thử lại. + Xác định tệp tin apk cho nền đen/tối từ bộ nhớ thất bại, vui lòng thử lại. + Cài đặt thất bại do người dùng hủy. + Cài đặt thất bại do có xung đột với ứng dụng đã được cài đặt trước đó. Gỡ cài đặt phiên bản hiện tại của ứng dụng rồi thử lại. + Cài đặt thất bại do người dùng cố hạ cấp ứng dụng. Gỡ cài đặt các bản cập nhật khỏi ứng dụng gốc rồi thử lại. + Cài đặt thất bại do lí do không xác định, tham gia Telegram hoặc Discord để được hỗ trợ. Vui lòng kèm theo ảnh chụp màn hình từ phần Chi tiết + Cài đặt thất bại do tệp tin cài đặt không tương thích với thiết bị của bạn. Xóa các tệp tin đã tải về trong Cài đặt rồi thử lại. + Cài đặt thất bại do các tệp tin apk bị lỗi, xin hãy thử lại. + Cài đặt thất bại do Tối ưu hóa MIUI được kích hoạt. Vô hiệu hóa Tối ưu hóa MIUI rồi thử lại. + Cài đặt thất bại do xác minh chứng chỉ apk được kích hoạt. Vô hiệu hóa xác minh chứng chỉ apk rồi thử lại. + Cài đặt thất bại do thiết bị của bạn không có đủ bộ nhớ trống. + Tìm kiếm tệp tin apk cho nền đen/tối từ trình cài đặt thất bại. Xoá dữ liệu của Manager rồi thử lại. + Không thể xác định thư mục cài đặt của YouTube gốc sau khi tải split. diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 49ef31c7a5..2d5423a6b3 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -1,120 +1,120 @@ - 取消 - 关闭 - 以 microG 项目为基础並只用于 Vanced 的自定义 Google 移动服务。 - 经过修改的 YouTube 客户端,具有许多有用的功能! - Vanced ,不过是 YouTube Music !功能相对较少,但足以满足您的需求。 - 重置 - 保存 - 选择您的应用 + 取消 + 关闭 + 以 microG 项目为基础並只用于 Vanced 的自定义 Google 移动服务。 + 经过修改的 YouTube 客户端,具有许多有用的功能! + Vanced ,不过是 YouTube Music !功能相对较少,但足以满足您的需求。 + 重置 + 保存 + 选择您的应用 - 关于 - 指南 - Manager - 日志 - 设置 - 更新 Manager + 关于 + 指南 + Manager + 日志 + 设置 + 更新 Manager - 您的设备是否拥有 Root 权限? - 授予 Root 权限 - 让我们开始吧 - 选择至少一个应用! - 不知道这是什么或不想使用 Root 版本?只需点击下面的蓝色箭头! + 您的设备是否拥有 Root 权限? + 授予 Root 权限 + 让我们开始吧 + 选择至少一个应用! + 不知道这是什么或不想使用 Root 版本?只需点击下面的蓝色箭头! - 关于 %1$s - 下载 - 信息 - 打开 - Reinstall - 卸载 - 更新 - 应用 - 变更日志 - 正在下载 %1$s - 安装 + 关于 %1$s + 下载 + 信息 + 打开 + Reinstall + 卸载 + 更新 + 应用 + 变更日志 + 正在下载 %1$s + 安装 最新: - 请先安装 Vanced microG + 请先安装 Vanced microG 未授予 Root 权限 - 社交媒体 - 支持我们 - 不可用 + 社交媒体 + 支持我们 + 不可用 已安装: - 强调色 - 外观 - 行为 - 清除已下载文件 - 成功清除文件 - 这允许我们收集有关应用性能和崩溃日志的信息 - Firebase 分析 - 语言 - 链接会使用 Chrome Custom Tabs 打开 - 使用 Chrome Custom Tabs - %1$s 推送通知 - %1$s 有可用更新时接收推送通知 - 保存新定时器值失败 - Root 脚本睡眠定时器 - 调整 /data/adb/service.d/app.sh 脚本中的睡眠定时器值,有助于修复挂载问题。 - 系统默认 - 主题 - 深色主题 - 浅色主题 - Manager 更新中心 - 无可用更新 - 版本 + 强调色 + 外观 + 行为 + 清除已下载文件 + 成功清除文件 + 这允许我们收集有关应用性能和崩溃日志的信息 + Firebase 分析 + 语言 + 链接会使用 Chrome Custom Tabs 打开 + 使用 Chrome Custom Tabs + %1$s 推送通知 + %1$s 有可用更新时接收推送通知 + 保存新定时器值失败 + Root 脚本睡眠定时器 + 调整 /data/adb/service.d/app.sh 脚本中的睡眠定时器值,有助于修复挂载问题。 + 系统默认 + 主题 + 深色主题 + 浅色主题 + Manager 更新中心 + 无可用更新 + 版本 - 无法保存日志 - 日志保存成功 + 无法保存日志 + 日志保存成功 详细信息 - 检测到 %1$s 安装文件! - Manager 检测到 %1$s 所需要的安装文件。您想现在安装吗? + 检测到 %1$s 安装文件! + Manager 检测到 %1$s 所需要的安装文件。您想现在安装吗? %1$s 安装首选设定 - 正在检查更新… + 正在检查更新… 语言: %1$s 主题: %1$s 版本: %1$s - 错误 - 说明 - 警告! + 错误 + 说明 + 警告! 您正在使用 Magisk/TWRP 版的 Vanced,它已被停止支持且无法通过此应用更新。请通过移除 Magisk 模块 / 使用 TWRP Vanced 卸载器来移除它。 - 为了能够安装 Vanced,您必须在开发者设置中禁用 MIUI 优化。(如果您正在使用基于 xiaomi.eu 20.2.20 或更新的 ROM,您可以忽略此警告) - MIUI 优化已启用! - 请不要在此过程中退出应用! - 重新下载 - 请确保您是从 vancedapp.com 、 Vanced Discord 服务器或 Vanced Github 下载本应用 + 为了能够安装 Vanced,您必须在开发者设置中禁用 MIUI 优化。(如果您正在使用基于 xiaomi.eu 20.2.20 或更新的 ROM,您可以忽略此警告) + MIUI 优化已启用! + 请不要在此过程中退出应用! + 重新下载 + 请确保您是从 vancedapp.com 、 Vanced Discord 服务器或 Vanced Github 下载本应用 版本 - 欢迎 + 欢迎 - 为 Vanced 选择您的首选语言 - 最新 + 为 Vanced 选择您的首选语言 + 最新 浅色 + %1$s 选择至少一种语言! - 黑色 - 深色 + 黑色 + 深色 - Manager 开发人员 - 其它贡献者: - 源码 - Vanced 团队 + Manager 开发人员 + 其它贡献者: + 源码 + Vanced 团队 - 无法 `chown` apk 为系统拥有者,请重试。 - %1$s 下载错误 + 无法 `chown` apk 为系统拥有者,请重试。 + %1$s 下载错误 无法应用新的强调色 - %1$s 卸载失败 - 无法找到需要安装的文件。重新下载安装文件,然后重试。 - 无法从存储中找到黑色/深色主题的 apk 文件,请重试。 - 用户放弃安装导致安装失败。 - 应用与已安装的应用发生冲突导致安装失败。卸载当前的版本,然后重试。 - 用户试图降级应用导致安装失败。卸载官方应用的更新,然后重试。 - 未知原因导致安装失败,请加入我们的 Telegram 或 Discord 并附上高级设置中的截图以获得更多支援。 - 安装文件与您的设备不相容导致安装失败。请在设置中清除已下载的文件,然后重试。 - apk 文件已被损坏导致安装失败,请重试。 - MIUI 优化已被启用导致安装失败。禁用 MIUI 优化,然后重试。 - apk 签名验证已被启用导致安装失败。禁用apk 签名验证,然后重试。 - 设备的可用空间不足导致安装失败。 - 无法从安装程式中找到黑色/深色主题的 apk 文件。清除 Manager 的应用数据,然后重试。 - 分包安装后无法定位原生 YouTube 的安装路径。 + %1$s 卸载失败 + 无法找到需要安装的文件。重新下载安装文件,然后重试。 + 无法从存储中找到黑色/深色主题的 apk 文件,请重试。 + 用户放弃安装导致安装失败。 + 应用与已安装的应用发生冲突导致安装失败。卸载当前的版本,然后重试。 + 用户试图降级应用导致安装失败。卸载官方应用的更新,然后重试。 + 未知原因导致安装失败,请加入我们的 Telegram 或 Discord 并附上高级设置中的截图以获得更多支援。 + 安装文件与您的设备不相容导致安装失败。请在设置中清除已下载的文件,然后重试。 + apk 文件已被损坏导致安装失败,请重试。 + MIUI 优化已被启用导致安装失败。禁用 MIUI 优化,然后重试。 + apk 签名验证已被启用导致安装失败。禁用apk 签名验证,然后重试。 + 设备的可用空间不足导致安装失败。 + 无法从安装程式中找到黑色/深色主题的 apk 文件。清除 Manager 的应用数据,然后重试。 + 分包安装后无法定位原生 YouTube 的安装路径。 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 8acf799491..97c4410869 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -1,120 +1,120 @@ - 取消 - 關閉 - 以 microG 項目為基礎並用於 Vanced 的 GMS 工具。 - 經過修改而具有許多有用功能的 YouTube 客戶端! - Vanced ,不過是 YouTube Music!功能相對較少但足以滿足您的需要。 - 重設 - 儲存 - 選擇您需要的應用程式 + 取消 + 關閉 + 以 microG 項目為基礎並用於 Vanced 的 GMS 工具。 + 經過修改而具有許多有用功能的 YouTube 客戶端! + Vanced ,不過是 YouTube Music!功能相對較少但足以滿足您的需要。 + 重設 + 儲存 + 選擇您需要的應用程式 - 關於 - 說明 - Manager - 日誌 - 設定 - 更新 Manager + 關於 + 說明 + Manager + 日誌 + 設定 + 更新 Manager - 您的裝置擁有 Root 權限嗎? - 授予 Root 權限 - 讓我們開始吧 - 請至少選擇一個應用程式! - 不知道這是什麼,或者不想使用 Root 版本?只需點選下面的藍色箭頭! + 您的裝置擁有 Root 權限嗎? + 授予 Root 權限 + 讓我們開始吧 + 請至少選擇一個應用程式! + 不知道這是什麼,或者不想使用 Root 版本?只需點選下面的藍色箭頭! - 關於 %1$s - 下載 - 關於 - 啟動 - 重新安裝 - 解除安裝 - 更新 - 應用程式 - 更新日誌 - 正在下載 %1$s - 安裝 + 關於 %1$s + 下載 + 關於 + 啟動 + 重新安裝 + 解除安裝 + 更新 + 應用程式 + 更新日誌 + 正在下載 %1$s + 安裝 最新: - 請先安裝 Vanced microG + 請先安裝 Vanced microG 未授予 Root 權限 - 社交媒體 - 支持我們 - 無法使用 + 社交媒體 + 支持我們 + 無法使用 已安裝: - 輔色 - 外觀 - 行為 - 清除已下載的檔案 - 成功清除檔案 - 這讓我們可以收集關於應用程式效能和崩潰日誌的資訊 - Firebase 分析 - 語言 - 連結會使用 Chrome Custom Tabs 開啟 - 使用 Chrome Custom Tabs - %1$s 推送通知 - 有可用更新時接收 %1$s 推送通知 - 儲存定時器時間失敗 - Root 腳本休眠時間 - 調整 /data/adb/service.d/app.sh 指令碼中的休眠時間值,對修復掛載問題很有用 - 系統預設 - 主題 - 深色主題 - 淺色主題 - Manager 更新中心 - 沒有更新 - 版本 + 輔色 + 外觀 + 行為 + 清除已下載的檔案 + 成功清除檔案 + 這讓我們可以收集關於應用程式效能和崩潰日誌的資訊 + Firebase 分析 + 語言 + 連結會使用 Chrome Custom Tabs 開啟 + 使用 Chrome Custom Tabs + %1$s 推送通知 + 有可用更新時接收 %1$s 推送通知 + 儲存定時器時間失敗 + Root 腳本休眠時間 + 調整 /data/adb/service.d/app.sh 指令碼中的休眠時間值,對修復掛載問題很有用 + 系統預設 + 主題 + 深色主題 + 淺色主題 + Manager 更新中心 + 沒有更新 + 版本 - 無法儲存日誌 - 日誌成功儲存 + 無法儲存日誌 + 日誌成功儲存 詳細資訊 - 偵測到 %1$s 的安裝檔案! - Manager 找到所有 %1$s 所需的安裝檔案。您打算安裝嗎? + 偵測到 %1$s 的安裝檔案! + Manager 找到所有 %1$s 所需的安裝檔案。您打算安裝嗎? %1$s 安裝偏好設定 - 正在檢查更新… + 正在檢查更新… 語言:%1$s 主題: %1$s 版本: %1$s - 錯誤 - 說明 - 警告! + 錯誤 + 說明 + 警告! 您正使用 Magisk/TWRP 版本的 Vanced ,它已停止支援並無法透過此程式更新。請透過移除 Magisk 模組/使用 TWRP Vanced 解除安裝程式來移除它。 - 欲安裝 Vanced,請先至開發人員選項停用 MIUI 優化。(若您正在使用 20.2.20 或更新版本且基於的 xiaomi.eu 的系統,請忽略此警告) - 已啟用 MIUI 優化! - 在此過程中請不要退出應用程式! - 重新下載 - 請確保您從 vancedapp.com、Vanced Discord 伺服器或 Vanced GitHub 下載本程式 + 欲安裝 Vanced,請先至開發人員選項停用 MIUI 優化。(若您正在使用 20.2.20 或更新版本且基於的 xiaomi.eu 的系統,請忽略此警告) + 已啟用 MIUI 優化! + 在此過程中請不要退出應用程式! + 重新下載 + 請確保您從 vancedapp.com、Vanced Discord 伺服器或 Vanced GitHub 下載本程式 版本 - 歡迎 + 歡迎 - 為 Vanced 選擇您偏好的語言 - 最新 + 為 Vanced 選擇您偏好的語言 + 最新 淺色 + %1$s 請至少選擇一種語言! - 黑色 - 深色 + 黑色 + 深色 - Manager 開發者 - 其他貢獻者: - 原始碼 - Vanced 團隊 + Manager 開發者 + 其他貢獻者: + 原始碼 + Vanced 團隊 - 無法 `chown` apk 為系統擁有者,請重試。 - %1$s 下載錯誤 + 無法 `chown` apk 為系統擁有者,請重試。 + %1$s 下載錯誤 無法套用新的輔色 - %1$s 解除安裝失敗 - 無法找到安裝所需的檔案。請重新下載安裝檔案,然後再試。 - 無法在儲存空間中找到深色/黑色主題的 apk 檔案,請再試。 - 使用者放棄安裝導致安裝失敗。 - 程式與已安裝的程式發生衝突導致安裝失敗。解除安裝當前的版本,然後重試。 - 使用者試圖降級導致安裝失敗。解除安裝原生應用程式的更新,然後重試。 - 未知原因導致安裝失敗,請附上進階設定的截圖至我們的 Telegram 或 Discord 取得更多支援 - 安裝檔案與您的裝置不相容導致安裝失敗。請在設定中清除已下載的檔案,然後重試。 - apk 檔案已被損毀導致安裝失敗,請重試。 - MIUI 優化已被啟用導致安裝失敗。停用 MIUI 優化,然後重試。 - apk 簽名驗證已被啟用導致安裝失敗。停用 apk 簽名驗證,然後重試。 - 裝置的可用空間不足導致安裝失敗。 - 在安裝程式中找不到深色/黑色主題的 apk 檔案。請清除 Manager 應用程式的資料,然後再試。 - 分割安裝後無法找到原生 YouTube 安裝路徑。 + %1$s 解除安裝失敗 + 無法找到安裝所需的檔案。請重新下載安裝檔案,然後再試。 + 無法在儲存空間中找到深色/黑色主題的 apk 檔案,請再試。 + 使用者放棄安裝導致安裝失敗。 + 程式與已安裝的程式發生衝突導致安裝失敗。解除安裝當前的版本,然後重試。 + 使用者試圖降級導致安裝失敗。解除安裝原生應用程式的更新,然後重試。 + 未知原因導致安裝失敗,請附上進階設定的截圖至我們的 Telegram 或 Discord 取得更多支援 + 安裝檔案與您的裝置不相容導致安裝失敗。請在設定中清除已下載的檔案,然後重試。 + apk 檔案已被損毀導致安裝失敗,請重試。 + MIUI 優化已被啟用導致安裝失敗。停用 MIUI 優化,然後重試。 + apk 簽名驗證已被啟用導致安裝失敗。停用 apk 簽名驗證,然後重試。 + 裝置的可用空間不足導致安裝失敗。 + 在安裝程式中找不到深色/黑色主題的 apk 檔案。請清除 Manager 應用程式的資料,然後再試。 + 分割安裝後無法找到原生 YouTube 安裝路徑。 diff --git a/app/src/main/res/values/resources.xml b/app/src/main/res/values/resources.xml index c651662380..83cfe78feb 100644 --- a/app/src/main/res/values/resources.xml +++ b/app/src/main/res/values/resources.xml @@ -2,18 +2,5 @@ Vanced Manager - YouTube Vanced - Vanced microG - YouTube Music Vanced - - nonroot - - Xinto (Main stuff)\nKoopah (Shell God)\nAioiLight (GitHub)\nLogan (UI) - xfileFIN\nKevinX8\nZaneZam\nLaura Almeida - bhatVikrant (Website)\nbawm (Sponsorblock) - GPL - - - use_custom_tabs diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e7130d408b..004c7063e6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,134 +1,158 @@ - - Cancel - Close - A custom GMS Implementation for Vanced based on the microG Project. - A modified YouTube client with many useful features! - Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. - Reset - Save - Select Your Apps - - - About - Guide - Manager - Logs - Settings - Update Manager - - Is Your Device Rooted? - Grant Root Permission - Let\'s get started - Select at least one app! - Don\'t know what this is or don\'t want to use the root version? just click the blue arrow below! + A custom GMS Implementation for Vanced based on the microG Project. + A modified YouTube client with many useful features! + Vanced, but for YouTube Music! Relatively less feature-rich but fulfills your needs. + Is Your Device Rooted? + Grant Root Permission + Let\'s get started + Don\'t know what this is or don\'t want to use the root version? just click the blue arrow below! + Select Your Apps + Select at least one app! - About %1$s - Download - Info - Launch - Reinstall - Uninstall - Update - Apps - Changelog - Downloading %1$s - Install - Latest: - Install Vanced microG first + Apps + Social Media + Support us Root access not granted - Social Media - Support us - Unavailable - Installed: - - - Accent Color - Appearance - Behavior - Clear downloaded files - Successfully cleared files - This lets us collect information about app performance and crash logs - Firebase Analytics - Language - Links will open in Chrome Custom Tabs - Use Chrome Custom Tabs - %1$s Push Notifications - Receive push notifications when an update for %1$s is released - Failed to save new time value - Root Script Sleep Time - Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues - System Default - Theme - Dark Theme - Light Theme - Manager Update Center - No new updates - Channel URL - Variant - - - Could not save logs - Successfully saved logs - - - Details - %1$s installation files detected! - Manager detected that all necessary files for %1$s installation were found. Do you want to install it? - %1$s Installation Preferences - Checking for updates… - Language(s): %1$s - Theme: %1$s - Version: %1$s - Error - Guide - Stop! - You are using the Magisk/TWRP version of Vanced, which is discontinued and cannot be updated using this app. Please remove it by removing the Magisk module/using TWRP Vanced uninstaller. - To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) - MIUI Optimizations are enabled! - Please do NOT exit the app during this process! - Are you sure you want to uninstall %1$s ? - Uninstall - Redownload - Make sure that you downloaded the app from vancedapp.com, the Vanced Discord server, or the Vanced GitHub - Version - Welcome - - - Choose your preferred language(s) for Vanced - Latest - Light + %1$s - Select at least one language! - Black - Dark + + + Appearance + Behavior + System Default + Accent Color + Clear downloaded files + Successfully cleared files + This lets us collect information about app performance and crash logs + Firebase Analytics + Language + Receive push notifications when an update for %1$s is released + %1$s Push Notifications + Failed to save new time value + Adjust sleep time value used in /data/adb/service.d/app.sh script, useful for fixing mounting issues + Root Script Sleep Time + Dark Theme + Light Theme + Theme + Links will open in Chrome Custom Tabs + Use Chrome Custom Tabs + Variant + + + Base download URL - Manager Devs - Other Contributors - Sources - Vanced Team - - - Failed to `chown` APK to system owner, please try again. - Error Downloading %1$s - Failed to apply new accent color - Failed to uninstall package %1$s - Failed to locate the required files for installation. Re-download the installation files, then try again. - Failed to locate apk file for black/dark theme from storage, please try again. - Installation failed because the user aborted the installation. - Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. - Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. - Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu - Installation failed because the installation file is incompatible with your device. Clear downloaded files in the Settings, then try again. - Installation failed because the apk files are corrupted, please try again. - Installation failed because MIUI Optimization is enabled. Disable MIUI Optimization, then try again. - Installation failed because apk signature verification is enabled. Disable apk signature verification, then try again. - Installation failed because the device doesn\'t have enough free space. - Failed to find apk file for black/dark theme from the installer. Clear app data of Manager, then try again. - Failed to locate the stock YouTube installation path after split installation. + Manager Devs + Other Contributors + Vanced Team + Sources + + + Successfully saved logs + Could not save logs + + + Cancel + Close + Reset + Save + Stop! + + + About + Guide + Manager + Logs + Settings + Update Manager + + + Unavailable + Install Vanced microG first + Install + Installed: %1$s + Latest: %1$s + + + Language(s) + Theme + Version + + + Make sure that you downloaded the app from vancedapp.com, the Vanced Discord server, or the Vanced GitHub + Welcome + + + Guide + To install Vanced, you MUST disable MIUI Optimizations in the developer settings. (You can ignore this warning if you are using 20.2.20 or later xiaomi.eu based ROM) + MIUI Optimizations are enabled! + + + Changelog + About %1$s + + + Install + Redownload + Manager detected that all necessary files for %1$s installation were found. Do you want to install it? + %1$s installation files detected! + + + Download + Downloading %1$s + Please do NOT exit the app during this process! + + + Uninstall + Are you sure you want to uninstall %1$s ? + + + Choose your preferred language(s) for %1$s + + + Black + Dark + Choose your preferred theme for %1$s + + + Latest + Choose your preferred version for %1$s + + + Checking for updates… + Manager Update Center + No new updates + + + Download + Info + Launch + Reinstall + Uninstall + Update + + + Details + Error + + + Failed to `chown` APK to system owner, please try again. + Error Downloading %1$s + Failed to uninstall package %1$s + Failed to locate the required files for installation. Re-download the installation files, then try again. + Failed to locate apk file for black/dark theme from storage, please try again. + Installation failed because the user aborted the installation. + Installation failed because the app conflicts with an already installed app. Uninstall the current version of the app, then try again. + Installation failed because the user tried to downgrade the package. Uninstall updates from the stock app, then try again. + Installation failed for unknown reasons, join our Telegram or Discord for further support. Please also attach a screenshot from the Advanced menu + Installation failed because the installation file is incompatible with your device. Clear downloaded files in the Settings, then try again. + Installation failed because the apk files are corrupted, please try again. + Installation failed because MIUI Optimization is enabled. Disable MIUI Optimization, then try again. + Installation failed because apk signature verification is enabled. Disable apk signature verification, then try again. + Installation failed because the device doesn\'t have enough free space. + Failed to find apk file for black/dark theme from the installer. Clear app data of Manager, then try again. + Failed to locate the stock YouTube installation path after split installation. From e6214a1734087b389a51d7f069674a6354051389 Mon Sep 17 00:00:00 2001 From: X1nto Date: Sat, 26 Jun 2021 21:09:39 +0400 Subject: [PATCH 005/118] refactor --- app/build.gradle.kts | 42 +-- app/src/main/AndroidManifest.xml | 2 +- .../com/vanced/manager/ManagerApplication.kt | 12 +- .../vanced/manager/SplashScreenActivity.kt | 1 + .../java/com/vanced/manager/di/APIModule.kt | 21 ++ .../com/vanced/manager/di/DownloaderModule.kt | 24 +- .../com/vanced/manager/di/InstallerModuke.kt | 15 + .../com/vanced/manager/di/PreferenceModule.kt | 15 + .../com/vanced/manager/domain/model/App.kt | 5 +- .../manager/domain/util/EntityMapper.kt | 2 - .../manager/downloader/api/VancedAPI.kt | 2 +- .../manager/downloader/base/BaseDownloader.kt | 18 +- .../downloader/impl/MicrogDownloader.kt | 4 - .../downloader/impl/MusicDownloader.kt | 4 - .../downloader/impl/VancedDownloader.kt | 111 +++---- .../vanced/manager/installer/AppInstaller.kt | 9 +- .../vanced/manager/network/model/AppDto.kt | 1 + .../manager/network/model/AppDtoMapper.kt | 78 +++-- .../manager/network/model/JsonDtoMapper.kt | 11 - .../manager/preference/ManagerPreferences.kt | 16 - .../vanced/manager/{ => ui}/MainActivity.kt | 76 +++-- .../ui/components/GlobalComposables.kt | 46 +++ .../ui/components/button/ManagerIconButton.kt | 41 +++ .../components/button/ManagerThemedButton.kt | 37 +++ .../button/ManagerThemedTextButton.kt | 20 ++ .../manager/ui/components/card/ManagerCard.kt | 46 +++ .../ui/components/card/ManagerItemCard.kt | 84 ++++++ .../ui/components/card/ManagerLinkCard.kt | 33 +++ .../ui/components/card/ManagerThemedCard.kt | 38 +++ .../ui/components/checkbox/ManagerCheckbox.kt | 67 +++++ .../components/color/ColorContentProvider.kt | 35 +++ .../ui/components/color/ColorPicker.kt | 26 ++ .../ui/components/color/ManagerColors.kt | 44 +++ .../ui/components/dialog/ManagerDialog.kt | 82 ++++++ .../ui/components/layout/ManagerLazyColumn.kt | 21 ++ .../layout/ManagerScrollableColumn.kt | 31 ++ .../ui/components/layout/ManagerSurface.kt | 18 ++ .../ui/components/layout/ScrollableItemRow.kt | 27 ++ .../ui/components/lifecycle/ManagerString.kt | 17 ++ .../ui/components/list/CheckboxItem.kt | 54 ++++ .../ui/components/list/ManagerListItem.kt | 57 ++++ .../ui/components/list/RadiobuttonItem.kt | 53 ++++ .../menu/ManagerDropdownMenuItem.kt | 21 ++ .../placeholder/ManagerPlaceholder.kt | 18 ++ .../preference/CheckboxPreference.kt | 68 +++++ .../components/preference/DialogPreference.kt | 93 ++++++ .../ui/components/preference/Preference.kt | 98 ++++++ .../preference/PreferenceComponents.kt | 66 +++++ .../preference/RadiobuttonDialogPreference.kt | 63 ++++ .../manager/ui/components/text/ManagerText.kt | 40 +++ .../manager/ui/composables/AppComposables.kt | 226 -------------- .../manager/ui/composables/ColorPicker.kt | 105 ------- .../ui/composables/DialogComposables.kt | 2 - .../ui/composables/DownloadComposables.kt | 111 ------- .../ui/composables/GlobalComposables.kt | 140 --------- .../manager/ui/composables/HomeComposables.kt | 80 ----- .../ui/composables/ManagerComponents.kt | 229 --------------- .../manager/ui/composables/ManagerListItem.kt | 95 ------ .../ui/composables/PreferenceComposables.kt | 148 ---------- .../vanced/manager/ui/layouts/AboutLayout.kt | 278 +++++++++--------- .../vanced/manager/ui/layouts/HomeLayout.kt | 68 ++--- .../vanced/manager/ui/layouts/LogLayout.kt | 6 +- .../manager/ui/layouts/SettingsLayout.kt | 149 +++++----- .../ui/preferences/CheckboxPreference.kt | 6 + .../ui/preferences/ManagerPreference.kt | 69 +++++ .../ui/preferences/RadioButtonPreference.kt | 2 +- .../holder/PreferenceDefaultValueHolder.kt | 6 + .../ui/preferences/holder/PreferenceHolder.kt | 23 ++ .../preferences/holder/PreferenceKeyHolder.kt | 19 ++ .../holder/PreferenceKeyNameHolder.kt | 13 + .../com/vanced/manager/ui/screens/Screen.kt | 50 +++- .../java/com/vanced/manager/ui/theme/Shape.kt | 6 +- .../java/com/vanced/manager/ui/theme/Theme.kt | 13 +- .../java/com/vanced/manager/ui/theme/Type.kt | 50 +++- .../java/com/vanced/manager/ui/utils/Const.kt | 6 + .../manager/ui/viewmodel/HomeViewModel.kt | 26 +- .../widgets/home/apps/card/AppActionCard.kt | 72 +++++ .../ui/widgets/home/apps/card/AppCard.kt | 81 +++++ .../ui/widgets/home/apps/card/AppInfoCard.kt | 48 +++ .../home/apps/dialog/AppChangelogDialog.kt | 42 +++ .../home/apps/dialog/AppDownloadDialog.kt | 53 ++++ .../home/download/AppDownloadDialogButtons.kt | 28 ++ .../download/AppDownloadDialogProgress.kt | 42 +++ .../CheckboxInstallationOption.kt | 20 ++ .../home/installation/InstallationOption.kt | 7 + .../RadiobuttonInstallationOption.kt | 20 ++ .../ui/widgets/layout/CategoryLayout.kt | 30 ++ .../ui/widgets/settings/AccentColorItem.kt | 23 ++ .../manager/ui/widgets/settings/ThemeItem.kt | 29 ++ .../manager/ui/widgets/text/AppVersionText.kt | 20 ++ .../ui/widgets/text/CategoryTitleText.kt | 20 ++ .../ui/widgets/text/ToolbarTitleText.kt | 15 + app/src/main/res/drawable/ic_adguard.xml | 19 +- app/src/main/res/drawable/ic_brave.xml | 17 +- app/src/main/res/drawable/ic_discord.xml | 26 +- app/src/main/res/drawable/ic_github.xml | 13 +- app/src/main/res/drawable/ic_instagram.xml | 18 +- app/src/main/res/drawable/ic_reddit.xml | 22 +- .../res/drawable/ic_round_assignment_24.xml | 11 + .../main/res/drawable/ic_round_close_24.xml | 10 + .../main/res/drawable/ic_round_done_24.xml | 10 + app/src/main/res/drawable/ic_telegram.xml | 14 +- app/src/main/res/drawable/ic_twitter.xml | 14 +- app/src/main/res/drawable/ic_website.xml | 19 +- app/src/main/res/drawable/ic_youtube.xml | 19 +- app/src/main/res/font/inter_black.ttf | Bin 0 -> 294396 bytes app/src/main/res/font/inter_bold.ttf | Bin 0 -> 293448 bytes app/src/main/res/font/inter_extralight.ttf | Bin 0 -> 288400 bytes app/src/main/res/font/inter_extranold.ttf | Bin 0 -> 294072 bytes app/src/main/res/font/inter_light.ttf | Bin 0 -> 288088 bytes app/src/main/res/font/inter_medium.ttf | Bin 0 -> 292140 bytes app/src/main/res/font/inter_regular.ttf | Bin 0 -> 287928 bytes app/src/main/res/font/inter_semibold.ttf | Bin 0 -> 293028 bytes app/src/main/res/font/inter_thin.ttf | Bin 0 -> 288568 bytes app/src/main/res/values-af-rZA/strings.xml | 14 +- app/src/main/res/values-ar-rSA/strings.xml | 14 +- app/src/main/res/values-az-rAZ/strings.xml | 14 +- app/src/main/res/values-bg-rBG/strings.xml | 14 +- app/src/main/res/values-bn-rBD/strings.xml | 14 +- app/src/main/res/values-bn-rIN/strings.xml | 14 +- app/src/main/res/values-ca-rES/strings.xml | 14 +- app/src/main/res/values-ckb-rIR/strings.xml | 14 +- app/src/main/res/values-cs-rCZ/strings.xml | 14 +- app/src/main/res/values-da-rDK/strings.xml | 14 +- app/src/main/res/values-de-rDE/strings.xml | 14 +- app/src/main/res/values-el-rGR/strings.xml | 14 +- app/src/main/res/values-es-rES/strings.xml | 14 +- app/src/main/res/values-et-rEE/strings.xml | 14 +- app/src/main/res/values-fi-rFI/strings.xml | 14 +- app/src/main/res/values-fil-rPH/strings.xml | 14 +- app/src/main/res/values-fr-rFR/strings.xml | 14 +- app/src/main/res/values-hi-rIN/strings.xml | 14 +- app/src/main/res/values-hr-rHR/strings.xml | 14 +- app/src/main/res/values-hu-rHU/strings.xml | 14 +- app/src/main/res/values-in-rID/strings.xml | 14 +- app/src/main/res/values-it-rIT/strings.xml | 14 +- app/src/main/res/values-iw-rIL/strings.xml | 14 +- app/src/main/res/values-ja-rJP/strings.xml | 14 +- app/src/main/res/values-ka-rGE/strings.xml | 14 +- app/src/main/res/values-kmr-rTR/strings.xml | 14 +- app/src/main/res/values-ko-rKR/strings.xml | 14 +- app/src/main/res/values-ku-rTR/strings.xml | 14 +- app/src/main/res/values-lt-rLT/strings.xml | 14 +- app/src/main/res/values-ml-rIN/strings.xml | 14 +- app/src/main/res/values-mr-rIN/strings.xml | 14 +- app/src/main/res/values-nl-rNL/strings.xml | 14 +- app/src/main/res/values-no-rNO/strings.xml | 14 +- app/src/main/res/values-pa-rIN/strings.xml | 14 +- app/src/main/res/values-pa-rPK/strings.xml | 14 +- app/src/main/res/values-pl-rPL/strings.xml | 14 +- app/src/main/res/values-ps-rAF/strings.xml | 14 +- app/src/main/res/values-pt-rBR/strings.xml | 14 +- app/src/main/res/values-pt-rPT/strings.xml | 14 +- app/src/main/res/values-ro-rRO/strings.xml | 14 +- app/src/main/res/values-ru-rRU/strings.xml | 14 +- app/src/main/res/values-si-rLK/strings.xml | 14 +- app/src/main/res/values-sk-rSK/strings.xml | 14 +- app/src/main/res/values-so-rSO/strings.xml | 14 +- app/src/main/res/values-sr-rSP/strings.xml | 14 +- app/src/main/res/values-sv-rSE/strings.xml | 14 +- app/src/main/res/values-ta-rIN/strings.xml | 14 +- app/src/main/res/values-th-rTH/strings.xml | 14 +- app/src/main/res/values-tr-rTR/strings.xml | 14 +- app/src/main/res/values-uk-rUA/strings.xml | 14 +- app/src/main/res/values-vi-rVN/strings.xml | 14 +- app/src/main/res/values-zh-rCN/strings.xml | 14 +- app/src/main/res/values-zh-rTW/strings.xml | 14 +- app/src/main/res/values/resources.xml | 4 + app/src/main/res/values/strings.xml | 20 +- build.gradle.kts | 2 +- buildSrc/src/main/java/Config.kt | 2 +- buildSrc/src/main/java/Dependencies.kt | 9 + 172 files changed, 3121 insertions(+), 2159 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/di/APIModule.kt create mode 100644 app/src/main/java/com/vanced/manager/di/InstallerModuke.kt create mode 100644 app/src/main/java/com/vanced/manager/di/PreferenceModule.kt delete mode 100644 app/src/main/java/com/vanced/manager/preference/ManagerPreferences.kt rename app/src/main/java/com/vanced/manager/{ => ui}/MainActivity.kt (62%) create mode 100644 app/src/main/java/com/vanced/manager/ui/components/GlobalComposables.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/button/ManagerIconButton.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedButton.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedTextButton.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/card/ManagerCard.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/card/ManagerItemCard.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/card/ManagerLinkCard.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/card/ManagerThemedCard.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/color/ColorContentProvider.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/color/ColorPicker.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/color/ManagerColors.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/dialog/ManagerDialog.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/layout/ManagerLazyColumn.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/layout/ManagerScrollableColumn.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/layout/ManagerSurface.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/layout/ScrollableItemRow.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/lifecycle/ManagerString.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/list/ManagerListItem.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/menu/ManagerDropdownMenuItem.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/placeholder/ManagerPlaceholder.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxPreference.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/preference/DialogPreference.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/preference/Preference.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/preference/PreferenceComponents.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/text/ManagerText.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/composables/AppComposables.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/composables/ColorPicker.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/composables/DialogComposables.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/composables/DownloadComposables.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/composables/GlobalComposables.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/composables/HomeComposables.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/composables/ManagerComponents.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/composables/ManagerListItem.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/composables/PreferenceComposables.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/preferences/CheckboxPreference.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/preferences/ManagerPreference.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceDefaultValueHolder.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceHolder.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceKeyHolder.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceKeyNameHolder.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/utils/Const.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppInfoCard.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppChangelogDialog.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppDownloadDialog.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogButtons.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/home/installation/CheckboxInstallationOption.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/home/installation/InstallationOption.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/home/installation/RadiobuttonInstallationOption.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/layout/CategoryLayout.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/settings/AccentColorItem.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/settings/ThemeItem.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/text/AppVersionText.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/text/CategoryTitleText.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/text/ToolbarTitleText.kt create mode 100644 app/src/main/res/drawable/ic_round_assignment_24.xml create mode 100644 app/src/main/res/drawable/ic_round_close_24.xml create mode 100644 app/src/main/res/drawable/ic_round_done_24.xml create mode 100644 app/src/main/res/font/inter_black.ttf create mode 100644 app/src/main/res/font/inter_bold.ttf create mode 100644 app/src/main/res/font/inter_extralight.ttf create mode 100644 app/src/main/res/font/inter_extranold.ttf create mode 100644 app/src/main/res/font/inter_light.ttf create mode 100644 app/src/main/res/font/inter_medium.ttf create mode 100644 app/src/main/res/font/inter_regular.ttf create mode 100644 app/src/main/res/font/inter_semibold.ttf create mode 100644 app/src/main/res/font/inter_thin.ttf create mode 100644 buildSrc/src/main/java/Dependencies.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4acd73aa82..73960162c1 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,3 +1,9 @@ +import Dependencies.accompanistVersion +import Dependencies.composeVersion +import Dependencies.koinVersion +import Dependencies.orchestraVersion +import Dependencies.retrofitVersion + plugins { id("com.android.application") kotlin("android") @@ -47,13 +53,16 @@ android { targetCompatibility = JavaVersion.VERSION_1_8 } + composeOptions { + kotlinCompilerExtensionVersion = composeVersion + } + } tasks.withType { kotlinOptions { jvmTarget = "1.8" - useIR = true - freeCompilerArgs = freeCompilerArgs + "-Xopt-in=kotlin.RequiresOptIn" + freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn" } } @@ -81,39 +90,36 @@ dependencies { implementation("com.google.android.material:material:1.3.0") implementation("androidx.browser:browser:1.3.0") - val composeVersion = "1.0.0-beta07" - implementation("androidx.compose.ui:ui:$composeVersion") - implementation("androidx.compose.material:material:$composeVersion") - implementation("androidx.compose.ui:ui-tooling:$composeVersion") - implementation("androidx.compose.ui:ui-util:$composeVersion") + implementation("androidx.compose.compiler:compiler:$composeVersion") implementation("androidx.compose.foundation:foundation:$composeVersion") - implementation("androidx.compose.material:material:$composeVersion") implementation("androidx.compose.material:material-icons-core:$composeVersion") implementation("androidx.compose.material:material-icons-extended:$composeVersion") + implementation("androidx.compose.material:material:$composeVersion") + implementation("androidx.compose.material:material:$composeVersion") implementation("androidx.compose.runtime:runtime-livedata:$composeVersion") + implementation("androidx.compose.ui:ui-tooling:$composeVersion") + implementation("androidx.compose.ui:ui-util:$composeVersion") + implementation("androidx.compose.ui:ui:$composeVersion") - implementation("androidx.activity:activity-compose:1.3.0-alpha08") - implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.3.1") - implementation("androidx.navigation:navigation-compose:2.4.0-alpha01") - implementation("androidx.preference:preference-ktx:1.1.1") + implementation("androidx.activity:activity-compose:1.3.0-beta02") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-alpha02") + implementation("androidx.navigation:navigation-compose:2.4.0-alpha03") - val accompanistVersion = "0.10.0" implementation("com.google.accompanist:accompanist-glide:$accompanistVersion") implementation("com.google.accompanist:accompanist-swiperefresh:$accompanistVersion") implementation("com.google.accompanist:accompanist-systemuicontroller:$accompanistVersion") + implementation("com.google.accompanist:accompanist-placeholder-material:$accompanistVersion") + + implementation("com.github.skydoves:orchestra-colorpicker:$orchestraVersion") - implementation("com.github.madrapps:pikolo:2.0.1") + implementation("androidx.datastore:datastore-preferences:1.0.0-beta02") - val koinVersion = "3.0.1" implementation("io.insert-koin:koin-android:$koinVersion") implementation("io.insert-koin:koin-androidx-compose:$koinVersion") - val retrofitVersion = "2.9.0" implementation("com.squareup.retrofit2:retrofit:$retrofitVersion") implementation("com.squareup.retrofit2:converter-gson:$retrofitVersion") - implementation("dev.burnoo:compose-remember-preference:0.3.0") - implementation("com.github.x1nto:apkhelper:1.1.0") testImplementation("junit:junit:4.13.2") diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 611e07b498..d65962c97e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -25,7 +25,7 @@ diff --git a/app/src/main/java/com/vanced/manager/ManagerApplication.kt b/app/src/main/java/com/vanced/manager/ManagerApplication.kt index 4c374b7ddc..3568efa821 100644 --- a/app/src/main/java/com/vanced/manager/ManagerApplication.kt +++ b/app/src/main/java/com/vanced/manager/ManagerApplication.kt @@ -14,13 +14,15 @@ class ManagerApplication : Application() { androidContext(this@ManagerApplication) modules( + apiModule, + downloaderModule, mapperModule, - viewModelModule, - serviceModule, - repositoryModule, - packageManagerModule, networkModule, - downloaderModule + packageManagerModule, + preferenceModule, + repositoryModule, + serviceModule, + viewModelModule, ) } } diff --git a/app/src/main/java/com/vanced/manager/SplashScreenActivity.kt b/app/src/main/java/com/vanced/manager/SplashScreenActivity.kt index d9e9868c1c..92f2f02398 100644 --- a/app/src/main/java/com/vanced/manager/SplashScreenActivity.kt +++ b/app/src/main/java/com/vanced/manager/SplashScreenActivity.kt @@ -3,6 +3,7 @@ package com.vanced.manager import android.content.Intent import android.os.Bundle import androidx.activity.ComponentActivity +import com.vanced.manager.ui.MainActivity class SplashScreenActivity : ComponentActivity() { diff --git a/app/src/main/java/com/vanced/manager/di/APIModule.kt b/app/src/main/java/com/vanced/manager/di/APIModule.kt new file mode 100644 index 0000000000..f40d6dbf51 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/di/APIModule.kt @@ -0,0 +1,21 @@ +package com.vanced.manager.di + +import com.vanced.manager.downloader.api.VancedAPI +import com.vanced.manager.network.util.BASE +import okhttp3.OkHttpClient +import org.koin.dsl.module +import retrofit2.Retrofit + +val apiModule = module { + + fun provideVancedAPI( + okHttpClient: OkHttpClient + ): VancedAPI = Retrofit.Builder() + .baseUrl(BASE) + .client(okHttpClient) + .build() + .create(VancedAPI::class.java) + + single { provideVancedAPI(get()) } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt b/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt index e35a0a40b3..4b22504e3b 100644 --- a/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt +++ b/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt @@ -1,29 +1,17 @@ package com.vanced.manager.di -import com.vanced.manager.downloader.impl.VancedDownloader import com.vanced.manager.downloader.api.VancedAPI -import com.vanced.manager.network.util.BASE -import okhttp3.OkHttpClient +import com.vanced.manager.downloader.impl.VancedDownloader import org.koin.dsl.module -import retrofit2.Retrofit val downloaderModule = module { - fun provideVancedAPI( - okHttpClient: OkHttpClient - ): VancedAPI = Retrofit.Builder() - .baseUrl(BASE) - .client(okHttpClient) - .build() - .create(VancedAPI::class.java) - fun provideVancedDownloader( - vancedAPI: VancedAPI - ): VancedDownloader = VancedDownloader( - vancedAPI = vancedAPI - ) + vancedAPI: VancedAPI, + ): VancedDownloader = VancedDownloader(vancedAPI) - single { provideVancedAPI(get()) } - single { provideVancedDownloader(get()) } + single { + provideVancedDownloader(get()) + } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt b/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt new file mode 100644 index 0000000000..a512419e3c --- /dev/null +++ b/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt @@ -0,0 +1,15 @@ +package com.vanced.manager.di + +import android.content.Context +import com.vanced.manager.installer.AppInstaller +import com.vanced.manager.ui.viewmodel.HomeViewModel +import org.koin.dsl.module + +val installerModule = module { + fun provideAppInstaller( + context: Context, + homeViewModel: HomeViewModel + ) = AppInstaller(context, homeViewModel) + + single { provideAppInstaller(get(), get()) } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/PreferenceModule.kt b/app/src/main/java/com/vanced/manager/di/PreferenceModule.kt new file mode 100644 index 0000000000..0af88be287 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/di/PreferenceModule.kt @@ -0,0 +1,15 @@ +package com.vanced.manager.di + +import android.content.Context +import androidx.datastore.preferences.preferencesDataStore +import org.koin.dsl.module + +val Context.dataStore by preferencesDataStore("manager_settings") + +val preferenceModule = module { + fun provideDatastore( + context: Context + ) = context.dataStore + + single { provideDatastore(get()) } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/domain/model/App.kt b/app/src/main/java/com/vanced/manager/domain/model/App.kt index b1b8beccfb..494d4cb4db 100644 --- a/app/src/main/java/com/vanced/manager/domain/model/App.kt +++ b/app/src/main/java/com/vanced/manager/domain/model/App.kt @@ -1,6 +1,7 @@ package com.vanced.manager.domain.model import com.vanced.manager.downloader.base.BaseDownloader +import com.vanced.manager.ui.widgets.home.installation.InstallationOption data class App( val name: String? = null, @@ -17,7 +18,9 @@ data class App( val packageNameRoot: String? = null, val changelog: String? = null, val url: String? = null, + val versions: List? = null, val themes: List? = null, val languages: List? = null, - val downloader: BaseDownloader? = null + val downloader: BaseDownloader? = null, + val installationOptions: List? = null ) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/domain/util/EntityMapper.kt b/app/src/main/java/com/vanced/manager/domain/util/EntityMapper.kt index bd8bf88c42..6ec1d4773a 100644 --- a/app/src/main/java/com/vanced/manager/domain/util/EntityMapper.kt +++ b/app/src/main/java/com/vanced/manager/domain/util/EntityMapper.kt @@ -4,6 +4,4 @@ interface EntityMapper { suspend fun mapToModel(entity: T): Model - suspend fun mapFromModel(model: Model): T - } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt b/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt index c6749f7cd1..939349c29d 100644 --- a/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt +++ b/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt @@ -8,7 +8,7 @@ import retrofit2.http.Streaming interface VancedAPI { - @GET("apks/v{version}/{variant}/{type}/{apkName}.apk") + @GET("apks/{version}/{variant}/{type}/{apkName}.apk") @Streaming fun getApk( @Path("version") version: String, diff --git a/app/src/main/java/com/vanced/manager/downloader/base/BaseDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/base/BaseDownloader.kt index b431db7d46..2454e119bd 100644 --- a/app/src/main/java/com/vanced/manager/downloader/base/BaseDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/base/BaseDownloader.kt @@ -4,17 +4,19 @@ import android.content.Context import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue -import com.vanced.manager.ui.composables.InstallationOption +import com.vanced.manager.installer.AppInstaller import com.vanced.manager.util.log import okhttp3.ResponseBody import org.koin.core.component.KoinComponent import org.koin.core.component.inject import retrofit2.Call import retrofit2.awaitResponse -import java.io.* +import java.io.File +import java.io.FileOutputStream +import java.io.IOException abstract class BaseDownloader( - private val appName: String + val appName: String ) : KoinComponent { var downloadProgress by mutableStateOf(0f) @@ -27,13 +29,12 @@ abstract class BaseDownloader( private lateinit var call: Call - private val context: Context by inject() - - abstract suspend fun download() + private val tag = this::class.simpleName!! - abstract val installationOptions: List + val context: Context by inject() + val appInstaller: AppInstaller by inject() - private val tag = this::class.simpleName!! + abstract suspend fun download() suspend fun downloadFile( call: Call, @@ -61,7 +62,6 @@ abstract class BaseDownloader( val error = response.errorBody()?.toString() if (error != null) { error(error) - log(tag, error) } } } catch (e: Exception) { diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt index 84c9123f99..c0f30e2e56 100644 --- a/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt @@ -1,7 +1,6 @@ package com.vanced.manager.downloader.impl import com.vanced.manager.downloader.base.BaseDownloader -import com.vanced.manager.ui.composables.InstallationOption object MicrogDownloader : BaseDownloader("") { @@ -9,7 +8,4 @@ object MicrogDownloader : BaseDownloader("") { } - override val installationOptions: List - get() = TODO("Not yet implemented") - } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt index e7c9fc54be..b2fe2aba34 100644 --- a/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt @@ -1,7 +1,6 @@ package com.vanced.manager.downloader.impl import com.vanced.manager.downloader.base.BaseDownloader -import com.vanced.manager.ui.composables.InstallationOption object MusicDownloader : BaseDownloader("") { @@ -9,7 +8,4 @@ object MusicDownloader : BaseDownloader("") { } - override val installationOptions: List - get() = TODO("Not yet implemented") - } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt index 873a1af2b7..bb00e24da7 100644 --- a/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt @@ -2,110 +2,71 @@ package com.vanced.manager.downloader.impl import com.vanced.manager.downloader.api.VancedAPI import com.vanced.manager.downloader.base.BaseDownloader -import com.vanced.manager.ui.composables.InstallationOption -import com.vanced.manager.ui.composables.InstallationOptionKey class VancedDownloader( - private val vancedAPI: VancedAPI + private val vancedAPI: VancedAPI, ) : BaseDownloader( appName = "vanced" ) { - private val themeInstallationOption = InstallationOption( - title = "Languages", - descriptionKey = InstallationOptionKey( - keyName = "vanced_languages", - keyDefaultValue = "en" - ) - ) { show, preference -> -// DialogRadioButtonPreference( -// preferenceTitle = "Language", -// preferenceKey = , -// defaultValue = , -// buttons = -// ) - } - - private val versionInstallationOption = InstallationOption( - title = "Languages", - descriptionKey = InstallationOptionKey( - keyName = "vanced_languages", - keyDefaultValue = "en" - ) - ) { show, preference -> -// DialogRadioButtonPreference( -// preferenceTitle = "Language", -// preferenceKey = , -// defaultValue = , -// buttons = -// ) - } - - private val languageInstallationOption = InstallationOption( - title = "Languages", - descriptionKey = InstallationOptionKey( - keyName = "vanced_languages", - keyDefaultValue = "en" - ) - ) { show, preference -> -// DialogRadioButtonPreference( -// preferenceTitle = "Language", -// preferenceKey = , -// defaultValue = , -// buttons = -// ) - } + private lateinit var version: String + private lateinit var variant: String - override val installationOptions: List get() = listOf( - languageInstallationOption - ) + private lateinit var folderStructure: String override suspend fun download() { + version = "v16.16.38" + variant = "nonroot" + folderStructure = "$appName/$version/$variant" downloadTheme() } private suspend fun downloadTheme() { - downloadFile( - vancedAPI.getApk( - version = "16.16.38", - variant = "nonroot", - type = "Theme", - apkName = "black.apk" - ), - folderStructure = "vanced/nonroot/v16.16.38", - fileName = "black.apk" + downloadVancedApk( + type = "Theme", + apkName = "black.apk" ) { downloadArch() } } private suspend fun downloadArch() { - downloadFile( - vancedAPI.getApk( - version = "16.16.38", - variant = "nonroot", - type = "Arch", - apkName = "split_config.x86.apk" - ), - folderStructure = "vanced/nonroot/arch", - fileName = "black.apk" + downloadVancedApk( + type = "Arch", + apkName = "split_config.x86.apk" ) { downloadLanguage() } } private suspend fun downloadLanguage() { + downloadVancedApk( + type = "Language", + apkName = "split_config.en.apk" + ) { + appInstaller.installVanced(version) + } + } + + private suspend fun downloadVancedApk( + type: String, + apkName: String, + onDownload: suspend () -> Unit, + ) { downloadFile( vancedAPI.getApk( - version = "16.16.38", - variant = "nonroot", - type = "Arch", - apkName = "split_config.x86.apk" + version = version, + variant = variant, + type = type, + apkName = apkName ), - folderStructure = "vanced/nonroot/lang", - fileName = "black.apk" + folderStructure = folderStructure, + fileName = apkName, + onError = { + + } ) { - downloadLanguage() + onDownload() } } diff --git a/app/src/main/java/com/vanced/manager/installer/AppInstaller.kt b/app/src/main/java/com/vanced/manager/installer/AppInstaller.kt index b3ce353fd4..d93f718ed1 100644 --- a/app/src/main/java/com/vanced/manager/installer/AppInstaller.kt +++ b/app/src/main/java/com/vanced/manager/installer/AppInstaller.kt @@ -1,15 +1,18 @@ package com.vanced.manager.installer +import android.content.Context +import com.vanced.manager.ui.viewmodel.HomeViewModel +import com.xinto.apkhelper.installSplitApks import com.xinto.apkhelper.statusCallback import com.xinto.apkhelper.statusCallbackBuilder -import com.vanced.manager.ui.viewmodel.HomeViewModel class AppInstaller( + private val context: Context, private val viewModel: HomeViewModel ) { - fun installVanced() { - + fun installVanced(version: String) { + installSplitApks(context.getExternalFilesDir("vanced/$version")!!.path, context) } fun installMusic() { diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDto.kt b/app/src/main/java/com/vanced/manager/network/model/AppDto.kt index eb39b3dbda..0487ce328f 100644 --- a/app/src/main/java/com/vanced/manager/network/model/AppDto.kt +++ b/app/src/main/java/com/vanced/manager/network/model/AppDto.kt @@ -11,6 +11,7 @@ data class AppDto( @SerializedName("package_name_root") val packageNameRoot: String? = null, @SerializedName("icon_url") val iconUrl: String? = null, @SerializedName("url") val url: String? = null, + @SerializedName("versions") val versions: List? = null, @SerializedName("themes") val themes: List? = null, @SerializedName("languages") val languages: List? = null ) diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt index 16e6657346..201bb98857 100644 --- a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt +++ b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt @@ -1,5 +1,6 @@ package com.vanced.manager.network.model +import com.vanced.manager.R import com.vanced.manager.domain.datasource.PackageInformationDataSource import com.vanced.manager.domain.model.App import com.vanced.manager.domain.model.AppStatus @@ -11,6 +12,14 @@ import com.vanced.manager.downloader.impl.VancedDownloader import com.vanced.manager.network.util.MICROG_NAME import com.vanced.manager.network.util.MUSIC_NAME import com.vanced.manager.network.util.VANCED_NAME +import com.vanced.manager.ui.preferences.* +import com.vanced.manager.ui.preferences.holder.musicVersionPref +import com.vanced.manager.ui.preferences.holder.vancedLanguagesPref +import com.vanced.manager.ui.preferences.holder.vancedThemePref +import com.vanced.manager.ui.preferences.holder.vancedVersionPref +import com.vanced.manager.ui.widgets.home.installation.CheckboxInstallationOption +import com.vanced.manager.ui.widgets.home.installation.InstallationOption +import com.vanced.manager.ui.widgets.home.installation.RadiobuttonInstallationOption class AppDtoMapper( private val packageInformationDataSource: PackageInformationDataSource, @@ -38,25 +47,11 @@ class AppDtoMapper( iconUrl = iconUrl, changelog = changelog, url = url, + versions = versions, themes = themes, languages = languages, - downloader = getDownloader(name) - ) - } - - override suspend fun mapFromModel(model: App): AppDto = - with (model) { - AppDto( - name = name, - version = remoteVersion, - versionCode = remoteVersionCode, - changelog = changelog, - url = url, - themes = themes, - languages = languages, - packageName = packageName, - packageNameRoot = packageNameRoot, - iconUrl = iconUrl + downloader = getDownloader(name), + installationOptions = getInstallationOptions(entity) ) } @@ -78,4 +73,53 @@ class AppDtoMapper( MICROG_NAME -> MicrogDownloader else -> null } + + private fun getInstallationOptions(app: AppDto): List? = + when (app.name) { + VANCED_NAME -> listOf( + RadiobuttonInstallationOption( + title = R.string.app_installation_options_theme, + preference = vancedThemePref, + buttons = app.versions?.map { + RadioButtonPreference( + title = it, + key = it + ) + } ?: emptyList() + ), + RadiobuttonInstallationOption( + title = R.string.app_installation_options_version, + preference = vancedVersionPref, + buttons = app.versions?.map { + RadioButtonPreference( + title = it, + key = it + ) + } ?: emptyList() + ), + CheckboxInstallationOption( + title = R.string.app_installation_options_language, + preference = vancedLanguagesPref, + buttons = app.versions?.map { + CheckboxPreference( + title = it, + key = it + ) + } ?: emptyList() + ), + ) + MUSIC_NAME -> listOf( + RadiobuttonInstallationOption( + title = R.string.app_installation_options_version, + preference = musicVersionPref, + buttons = app.versions?.map { + RadioButtonPreference( + title = it, + key = it + ) + } ?: emptyList() + ), + ) + else -> null + } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/model/JsonDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/JsonDtoMapper.kt index f04730ace2..5bfada0c54 100644 --- a/app/src/main/java/com/vanced/manager/network/model/JsonDtoMapper.kt +++ b/app/src/main/java/com/vanced/manager/network/model/JsonDtoMapper.kt @@ -18,15 +18,4 @@ class JsonDtoMapper( ) } - override suspend fun mapFromModel(model: Json): JsonDto = - with (model) { - JsonDto( - isMicrogBroken = isMicrogBroken, - manager = appDtoMapper.mapFromModel(manager), - vanced = appDtoMapper.mapFromModel(vanced), - music = appDtoMapper.mapFromModel(music), - microg = appDtoMapper.mapFromModel(microg) - ) - } - } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/preference/ManagerPreferences.kt b/app/src/main/java/com/vanced/manager/preference/ManagerPreferences.kt deleted file mode 100644 index 51569b40e2..0000000000 --- a/app/src/main/java/com/vanced/manager/preference/ManagerPreferences.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.vanced.manager.preference - -import android.content.Context -import android.content.SharedPreferences -import androidx.core.content.edit -import androidx.preference.PreferenceManager - -val Context.defPrefs: SharedPreferences get() = PreferenceManager.getDefaultSharedPreferences(this) - -var SharedPreferences.managerTheme - get() = getString("manager_theme", "Light") - set(value) { - edit { - putString("manager_theme", value) - } - } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt similarity index 62% rename from app/src/main/java/com/vanced/manager/MainActivity.kt rename to app/src/main/java/com/vanced/manager/ui/MainActivity.kt index 738f91e244..705e4504f9 100644 --- a/app/src/main/java/com/vanced/manager/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -1,9 +1,8 @@ -package com.vanced.manager +package com.vanced.manager.ui import android.os.Bundle import androidx.activity.compose.setContent import androidx.appcompat.app.AppCompatActivity -import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.background import androidx.compose.material.* import androidx.compose.material.icons.Icons @@ -11,37 +10,36 @@ import androidx.compose.material.icons.filled.ArrowBackIos import androidx.compose.material.icons.filled.MoreVert import androidx.compose.runtime.* import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import androidx.compose.ui.util.fastForEach import androidx.navigation.NavController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable +import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import com.google.accompanist.systemuicontroller.rememberSystemUiController -import com.vanced.manager.preference.defPrefs -import com.vanced.manager.preference.managerTheme -import com.vanced.manager.ui.composables.* -import com.vanced.manager.ui.layouts.* +import com.vanced.manager.ui.components.color.managerAnimatedColor +import com.vanced.manager.ui.components.color.managerCardColor +import com.vanced.manager.ui.components.color.managerSurfaceColor +import com.vanced.manager.ui.components.color.managerTextColor +import com.vanced.manager.ui.components.menu.ManagerDropdownMenuItem import com.vanced.manager.ui.screens.Screen -import com.vanced.manager.ui.theme.ComposeTestTheme +import com.vanced.manager.ui.theme.ManagerTheme import com.vanced.manager.ui.theme.isDark -import com.vanced.manager.ui.theme.managerTheme +import com.vanced.manager.ui.widgets.text.ToolbarTitleText class MainActivity : AppCompatActivity() { - @ExperimentalAnimationApi override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { - managerTheme = defPrefs.managerTheme - - ComposeTestTheme { - //ButtonLayoutActivity() + ManagerTheme { MainActivityLayout() } } } - @ExperimentalAnimationApi @Composable fun MainActivityLayout() { val isMenuExpanded = remember { mutableStateOf(false) } @@ -50,10 +48,11 @@ class MainActivity : AppCompatActivity() { val isDark = isDark() val navController = rememberNavController() - val dropdownScreens = listOf( + val screens = listOf( + Screen.Home, Screen.Settings, - Screen.Logs, - Screen.About + Screen.About, + Screen.Logs ) SideEffect { @@ -63,9 +62,9 @@ class MainActivity : AppCompatActivity() { Scaffold( topBar = { MainToolbar( - navController, - dropdownScreens, - isMenuExpanded + navController = navController, + screens = screens, + isMenuExpanded = isMenuExpanded ) }, backgroundColor = managerSurfaceColor() @@ -74,8 +73,10 @@ class MainActivity : AppCompatActivity() { navController = navController, startDestination = Screen.Home.route ) { - composable(Screen.Home.route) { - HomeLayout() + screens.fastForEach { screen -> + composable(screen.route) { + screen.content() + } } } } @@ -84,23 +85,17 @@ class MainActivity : AppCompatActivity() { @Composable fun MainToolbar( navController: NavController, - dropdownScreens: List, + screens: List, isMenuExpanded: MutableState ) { + val currentScreenRoute = navController.currentBackStackEntryAsState().value?.destination?.route TopAppBar( title = { - navController.currentDestination - Text( - //This does not look good at all - text = Screen::class.sealedSubclasses.find { - it.objectInstance?.route == navController.currentDestination?.route - }?.objectInstance?.displayName ?: "", - color = managerAnimatedColor(color = MaterialTheme.colors.onSurface) - ) + ToolbarTitleText(screens.find { it.route == currentScreenRoute }?.displayName) }, backgroundColor = managerAnimatedColor(color = MaterialTheme.colors.surface), actions = { - if (navController.currentDestination?.route == Screen.Home.route) { + if (currentScreenRoute == Screen.Home.route) { IconButton( onClick = { isMenuExpanded.value = !isMenuExpanded.value } ) { @@ -118,27 +113,22 @@ class MainActivity : AppCompatActivity() { }, modifier = Modifier.background(managerCardColor()) ) { - dropdownScreens.forEach { + screens.filter { it.route != currentScreenRoute }.forEach { ManagerDropdownMenuItem( - isMenuExpanded = isMenuExpanded, - title = it.displayName + title = stringResource(id = it.displayName) ) { + isMenuExpanded.value = !isMenuExpanded.value navController.navigate(it.route) { - popUpTo(Screen.Home.route) - anim { - enter = R.animator.fragment_enter - exit = R.animator.fragment_exit - popEnter = R.animator.fragment_enter_pop - popEnter = R.animator.fragment_exit_pop + popUpTo(Screen.Home.route) { + saveState = true } - restoreState = true } } } } } }, - navigationIcon = if (navController.currentDestination?.route != Screen.Home.route) { { + navigationIcon = if (currentScreenRoute != Screen.Home.route) { { IconButton(onClick = { navController.popBackStack() }) { diff --git a/app/src/main/java/com/vanced/manager/ui/components/GlobalComposables.kt b/app/src/main/java/com/vanced/manager/ui/components/GlobalComposables.kt new file mode 100644 index 0000000000..727d97eb09 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/GlobalComposables.kt @@ -0,0 +1,46 @@ +package com.vanced.manager.ui.components + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.padding +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.em +import androidx.compose.ui.unit.sp +import com.vanced.manager.ui.theme.managerAccentColor +import java.util.* + +@Composable +fun HeaderView( + modifier: Modifier = Modifier, + headerName: String, + headerPadding: Dp = 11.dp, + content: @Composable ColumnScope.() -> Unit +) { + Column( + modifier = modifier + ) { + Header(headerName = headerName, headerPadding = headerPadding) + content() + } +} + +@Composable +fun Header( + headerName: String, + headerPadding: Dp = 11.dp, +) { + Text( + headerName.uppercase(Locale.ROOT), + letterSpacing = 0.15.em, + color = MaterialTheme.colors.managerAccentColor, + modifier = Modifier.padding(horizontal = headerPadding), + fontWeight = FontWeight.Bold, + fontSize = 13.sp + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/button/ManagerIconButton.kt b/app/src/main/java/com/vanced/manager/ui/components/button/ManagerIconButton.kt new file mode 100644 index 0000000000..11baf94b37 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/button/ManagerIconButton.kt @@ -0,0 +1,41 @@ +package com.vanced.manager.ui.components.button + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.size +import androidx.compose.material.Icon +import androidx.compose.material.ripple.rememberRipple +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.unit.dp + +@Composable +fun IconButton( + icon: ImageVector, + contentDescription: String, + onClick: () -> Unit +) { + val interactionSource = remember { MutableInteractionSource() } + val buttonSize = 36.dp + Box( + modifier = Modifier + .clickable( + onClick = onClick, + role = Role.Button, + interactionSource = interactionSource, + indication = rememberRipple(bounded = false, radius = 18.dp) + ) + .size(buttonSize), + contentAlignment = Alignment.Center + ) { + Icon( + imageVector = icon, + contentDescription = contentDescription + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedButton.kt b/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedButton.kt new file mode 100644 index 0000000000..e4bda53c6e --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedButton.kt @@ -0,0 +1,37 @@ +package com.vanced.manager.ui.components.button + +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material.Button +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.LocalContentColor +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.luminance +import androidx.compose.ui.unit.dp +import com.vanced.manager.ui.components.color.managerAccentColor + +@Composable +fun ManagerThemedButton( + modifier: Modifier = Modifier, + onClick: () -> Unit, + content: @Composable RowScope.() -> Unit +) { + val accentColor = managerAccentColor() + Button( + modifier = modifier.fillMaxWidth(), + onClick = onClick, + shape = MaterialTheme.shapes.medium, + colors = ButtonDefaults.buttonColors( + backgroundColor = managerAccentColor() + ), + elevation = ButtonDefaults.elevation(0.dp, 0.dp, 0.dp) + ) { + CompositionLocalProvider(LocalContentColor provides if (accentColor.luminance() > 0.7) Color.Black else Color.White) { + content() + } + } +} diff --git a/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedTextButton.kt b/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedTextButton.kt new file mode 100644 index 0000000000..f0d97c463d --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedTextButton.kt @@ -0,0 +1,20 @@ +package com.vanced.manager.ui.components.button + +import androidx.annotation.StringRes +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.vanced.manager.ui.components.text.ManagerText + +@Composable +fun ManagerThemedTextButton( + modifier: Modifier = Modifier, + @StringRes stringId: Int, + onClick: () -> Unit +) { + ManagerThemedButton( + modifier = modifier, + onClick = onClick + ) { + ManagerText(stringId = stringId) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/card/ManagerCard.kt b/app/src/main/java/com/vanced/manager/ui/components/card/ManagerCard.kt new file mode 100644 index 0000000000..23ff06cc97 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/card/ManagerCard.kt @@ -0,0 +1,46 @@ +package com.vanced.manager.ui.components.card + +import androidx.compose.material.Card +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.unit.dp +import com.vanced.manager.ui.components.color.managerCardColor + +@Composable +fun ManagerCard( + modifier: Modifier = Modifier, + shape: Shape = MaterialTheme.shapes.medium, + backgroundColor: Color = MaterialTheme.colors.surface, + content: @Composable () -> Unit, +) { + Card( + modifier = modifier, + shape = shape, + backgroundColor = backgroundColor, + elevation = 0.dp, + content = content + ) +} + +@OptIn(ExperimentalMaterialApi::class) +@Composable +fun ManagerCard( + modifier: Modifier = Modifier, + shape: Shape = MaterialTheme.shapes.medium, + backgroundColor: Color = managerCardColor(), + onClick: () -> Unit, + content: @Composable () -> Unit, +) { + Card( + modifier = modifier, + shape = shape, + backgroundColor = backgroundColor, + elevation = 0.dp, + content = content, + onClick = onClick + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/card/ManagerItemCard.kt b/app/src/main/java/com/vanced/manager/ui/components/card/ManagerItemCard.kt new file mode 100644 index 0000000000..32d7675607 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/card/ManagerItemCard.kt @@ -0,0 +1,84 @@ +package com.vanced.manager.ui.components.card + +import androidx.annotation.DrawableRes +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.layout.* +import androidx.compose.material.Icon +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.vanced.manager.ui.components.color.ThemedItemContentColorProvider +import com.vanced.manager.ui.components.color.managerAccentColor + +private val cardModifier = Modifier.sizeIn( + minHeight = 95.dp, + minWidth = 95.dp +) + +@Composable +fun ManagerItemCard( + title: String, + @DrawableRes icon: Int? = null +) { + ManagerThemedCard( + modifier = cardModifier, + ) { + ManagerItemCardContent(title, icon) + } +} + +@Composable +fun ManagerClickableItemCard( + title: String, + @DrawableRes icon: Int? = null, + onClick: () -> Unit +) { + ManagerClickableThemedCard( + modifier = cardModifier, + onClick = onClick + ) { + ManagerItemCardContent(title, icon) + } +} + +@Composable +private fun ManagerItemCardContent( + title: String, + @DrawableRes icon: Int? = null, +) { + Canvas(modifier = Modifier.requiredSize(72.dp)) { + drawCircle( + color = managerAccentColor(), + center = Offset(32f,32f) + ) + } + Box( + modifier = Modifier.padding(12.dp) + ) { + if (icon != null) { + ThemedItemContentColorProvider { + Icon( + modifier = Modifier + .size(28.dp) + .align(Alignment.TopStart), + painter = painterResource(id = icon), + contentDescription = title + ) + } + } + Text( + modifier = Modifier.align(Alignment.BottomStart), + text = title, + fontSize = 12.sp, + fontWeight = FontWeight.Medium, + color = MaterialTheme.colors.onSurface + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/card/ManagerLinkCard.kt b/app/src/main/java/com/vanced/manager/ui/components/card/ManagerLinkCard.kt new file mode 100644 index 0000000000..76179210d1 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/card/ManagerLinkCard.kt @@ -0,0 +1,33 @@ +package com.vanced.manager.ui.components.card + +import android.content.Intent +import android.net.Uri +import androidx.annotation.DrawableRes +import androidx.browser.customtabs.CustomTabsIntent +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.platform.LocalContext +import com.vanced.manager.ui.preferences.holder.useCustomTabsPref + +@Composable +fun ManagerLinkCard( + title: String, + @DrawableRes icon: Int, + link: String +) { + val context = LocalContext.current + val customTabs = remember { CustomTabsIntent.Builder().build() } + val uri = remember { Uri.parse(link) } + val intent = remember { Intent(Intent.ACTION_VIEW, uri) } + val useCustomTabs by useCustomTabsPref + ManagerClickableItemCard( + title = title, + icon = icon + ) { + if (useCustomTabs) { + customTabs.launchUrl(context, uri) + } else { + context.startActivity(intent) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/card/ManagerThemedCard.kt b/app/src/main/java/com/vanced/manager/ui/components/card/ManagerThemedCard.kt new file mode 100644 index 0000000000..bc75156861 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/card/ManagerThemedCard.kt @@ -0,0 +1,38 @@ +package com.vanced.manager.ui.components.card + +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Shape +import com.vanced.manager.ui.components.color.managerThemedCardColor + +@Composable +fun ManagerThemedCard( + modifier: Modifier = Modifier, + shape: Shape = MaterialTheme.shapes.medium, + content: @Composable () -> Unit, +) { + ManagerCard( + modifier = modifier, + shape = shape, + backgroundColor = managerThemedCardColor(), + content = content + ) +} + +@Composable +fun ManagerClickableThemedCard( + modifier: Modifier = Modifier, + shape: Shape = MaterialTheme.shapes.medium, + onClick: () -> Unit, + content: @Composable () -> Unit, +) { + ManagerCard( + modifier = modifier, + shape = shape, + backgroundColor = managerThemedCardColor(), + onClick = onClick, + ) { + content() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt b/app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt new file mode 100644 index 0000000000..8020c1f777 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt @@ -0,0 +1,67 @@ +package com.vanced.manager.ui.components.checkbox + +import android.annotation.SuppressLint +import androidx.compose.animation.core.animateDp +import androidx.compose.animation.core.keyframes +import androidx.compose.animation.core.updateTransition +import androidx.compose.foundation.layout.requiredSize +import androidx.compose.foundation.layout.size +import androidx.compose.material.Icon +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.Close +import androidx.compose.material.icons.rounded.Done +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.vanced.manager.ui.components.card.ManagerCard +import com.vanced.manager.ui.components.color.contentColorForColor +import com.vanced.manager.ui.components.color.managerAccentColor +import com.vanced.manager.ui.components.color.managerAnimatedColor +import com.vanced.manager.ui.components.color.managerThemedCardColor + +@SuppressLint("UnusedTransitionTargetStateParameter") +@Composable +fun ManagerCheckbox( + isChecked: Boolean, + onCheckedChange: (isChecked: Boolean) -> Unit +) { + val transition = updateTransition(targetState = isChecked, label = "Checked") + val cardSize by transition.animateDp( + transitionSpec = { + keyframes { + durationMillis = 250 + 32.dp at 50 + 48.dp at 150 + 40.dp at 250 + } + }, + label = "Checkbox size" + ) { 40.dp } + val iconSize by transition.animateDp( + transitionSpec = { + keyframes { + durationMillis = 250 + 18.dp at 50 + 30.dp at 150 + 24.dp at 250 + } + }, + label = "Icon size" + ) { 24.dp } + val cardColor = managerAnimatedColor(if (isChecked) managerAccentColor() else managerThemedCardColor()) + val iconTint = managerAnimatedColor(if (isChecked) contentColorForColor(cardColor) else managerAccentColor()) + + ManagerCard( + modifier = Modifier.size(cardSize), + onClick = { onCheckedChange(!isChecked) }, + backgroundColor = cardColor + ) { + Icon( + modifier = Modifier.requiredSize(iconSize), + imageVector = if (isChecked) Icons.Rounded.Done else Icons.Rounded.Close, + tint = iconTint, + contentDescription = null + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/color/ColorContentProvider.kt b/app/src/main/java/com/vanced/manager/ui/components/color/ColorContentProvider.kt new file mode 100644 index 0000000000..d089582ac9 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/color/ColorContentProvider.kt @@ -0,0 +1,35 @@ +package com.vanced.manager.ui.components.color + +import androidx.compose.material.LocalContentColor +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider + +@Composable +fun ThemedItemContentColorProvider( + content: @Composable () -> Unit +) { + CompositionLocalProvider( + LocalContentColor provides contentColorForColor(managerAccentColor()), + content = content + ) +} + +@Composable +fun ThemedCardContentColorProvider( + content: @Composable () -> Unit +) { + CompositionLocalProvider( + LocalContentColor provides contentColorForColor(managerThemedCardColor()), + content = content + ) +} + +@Composable +fun ThemedContentColorProvider( + content: @Composable () -> Unit +) { + CompositionLocalProvider( + LocalContentColor provides managerAccentColor(), + content = content + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/color/ColorPicker.kt b/app/src/main/java/com/vanced/manager/ui/components/color/ColorPicker.kt new file mode 100644 index 0000000000..4bcb7fb667 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/color/ColorPicker.kt @@ -0,0 +1,26 @@ +package com.vanced.manager.ui.components.color + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.skydoves.colorpickerview.ColorEnvelope +import com.skydoves.orchestra.colorpicker.ColorPicker + +@Composable +fun ManagerColorPicker( + onColorSelected: (color: Long) -> Unit +) { + val (selectedColor, setColor) = remember { mutableStateOf(ColorEnvelope(0)) } + ColorPicker( + modifier = Modifier + .fillMaxWidth() + .height(400.dp), + onColorListener = { envelope, _ -> setColor(envelope) }, + children = {} + ) + onColorSelected(selectedColor.color.toLong()) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/color/ManagerColors.kt b/app/src/main/java/com/vanced/manager/ui/components/color/ManagerColors.kt new file mode 100644 index 0000000000..63949eaf74 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/color/ManagerColors.kt @@ -0,0 +1,44 @@ +package com.vanced.manager.ui.components.color + +import androidx.compose.animation.animateColorAsState +import androidx.compose.animation.core.tween +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.luminance +import com.vanced.manager.ui.preferences.holder.managerAccentColorPref +import com.vanced.manager.ui.theme.cardColor + +fun managerAccentColor(): Color = Color(managerAccentColorPref.value.value) + +@Composable +fun contentColorForColor(color: Color) = + if (color.luminance() > 0.7) + Color.Black + else + Color.White + +@Composable +fun managerThemedCardColor() = managerAccentColor().copy(alpha = 0.2f) + +@Composable +fun managerTextColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.onSurface) + +@Composable +fun managerSurfaceColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.surface) + +@Composable +fun managerCardColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.cardColor) + +@Composable +fun animatedManagerAccentColor(): Color = managerAnimatedColor(color = managerAccentColor()) + +@Composable +fun managerAnimatedColor( + color: Color +): Color { + return animateColorAsState( + targetValue = color, + animationSpec = tween(500) + ).value +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/dialog/ManagerDialog.kt b/app/src/main/java/com/vanced/manager/ui/components/dialog/ManagerDialog.kt new file mode 100644 index 0000000000..15989a39d6 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/dialog/ManagerDialog.kt @@ -0,0 +1,82 @@ +package com.vanced.manager.ui.components.dialog + +import androidx.annotation.StringRes +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.padding +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog +import com.vanced.manager.ui.components.card.ManagerCard +import com.vanced.manager.ui.components.text.ManagerText +import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal + +@Composable +fun ManagerDialog( + @StringRes titleId: Int, + onDismissRequest: () -> Unit, + buttons: @Composable ColumnScope.() -> Unit, + content: @Composable ColumnScope.() -> Unit, +) { + ManagerDialog( + title = { + ManagerText( + modifier = Modifier.align(Alignment.CenterHorizontally), + stringId = titleId, + textStyle = MaterialTheme.typography.h2 + ) + }, + onDismissRequest = onDismissRequest, + buttons = buttons, + content = content + ) +} + +@Composable +fun ManagerDialog( + title: String, + onDismissRequest: () -> Unit, + buttons: @Composable ColumnScope.() -> Unit, + content: @Composable ColumnScope.() -> Unit, +) { + ManagerDialog( + title = { + ManagerText( + modifier = Modifier.align(Alignment.CenterHorizontally), + textStyle = MaterialTheme.typography.h2, + text = title + ) + }, + onDismissRequest = onDismissRequest, + buttons = buttons, + content = content + ) +} + +@Composable +fun ManagerDialog( + title: @Composable ColumnScope.() -> Unit, + onDismissRequest: () -> Unit, + buttons: @Composable ColumnScope.() -> Unit, + content: @Composable ColumnScope.() -> Unit, +) { + Dialog( + onDismissRequest = onDismissRequest, + content = { + ManagerCard { + Column( + modifier = Modifier.padding(defaultContentPaddingHorizontal), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + title() + content() + buttons() + } + } + } + ) +} diff --git a/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerLazyColumn.kt b/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerLazyColumn.kt new file mode 100644 index 0000000000..681314b6c7 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerLazyColumn.kt @@ -0,0 +1,21 @@ +package com.vanced.manager.ui.components.layout + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListScope +import androidx.compose.runtime.Composable +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp + +@Composable +fun ManagerLazyColumn( + itemSpacing: Dp = 0.dp, + content: LazyListScope.() -> Unit +) { + LazyColumn( + contentPadding = PaddingValues(12.dp), + verticalArrangement = Arrangement.spacedBy(itemSpacing), + content = content + ) +} diff --git a/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerScrollableColumn.kt b/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerScrollableColumn.kt new file mode 100644 index 0000000000..40eb440b70 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerScrollableColumn.kt @@ -0,0 +1,31 @@ +package com.vanced.manager.ui.components.layout + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import com.vanced.manager.ui.utils.defaultContentPaddingVertical + +@Composable +fun ManagerScrollableColumn( + contentPaddingVertical: Dp = defaultContentPaddingVertical, + itemSpacing: Dp = 0.dp, + content: @Composable ColumnScope.() -> Unit +) { + val scrollState = rememberScrollState() + Column( + modifier = Modifier + .verticalScroll(scrollState) + .padding(vertical = contentPaddingVertical), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(itemSpacing), + content = content + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerSurface.kt b/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerSurface.kt new file mode 100644 index 0000000000..f2a6c7a055 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerSurface.kt @@ -0,0 +1,18 @@ +package com.vanced.manager.ui.components.layout + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material.Surface +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.vanced.manager.ui.components.color.managerSurfaceColor + +@Composable +fun ManagerSurface( + content: @Composable () -> Unit +) { + Surface( + modifier = Modifier.fillMaxSize(), + color = managerSurfaceColor(), + content = content + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/layout/ScrollableItemRow.kt b/app/src/main/java/com/vanced/manager/ui/components/layout/ScrollableItemRow.kt new file mode 100644 index 0000000000..0b33fffea9 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/layout/ScrollableItemRow.kt @@ -0,0 +1,27 @@ +package com.vanced.manager.ui.components.layout + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +@Composable +fun ScrollableItemRow( + items: List, + content: @Composable (T) -> Unit +) { + val state = rememberLazyListState() + LazyRow( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(8.dp), + state = state + ) { + items(items) { item -> + content(item) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/lifecycle/ManagerString.kt b/app/src/main/java/com/vanced/manager/ui/components/lifecycle/ManagerString.kt new file mode 100644 index 0000000000..3af1af083d --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/lifecycle/ManagerString.kt @@ -0,0 +1,17 @@ +package com.vanced.manager.ui.components.lifecycle + +import androidx.annotation.StringRes +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import com.vanced.manager.R + +@Composable +fun managerString( + @StringRes stringId: Int? +) = stringResource(id = stringId ?: R.string.dummy_placeholder_text) + +@Composable +fun managerString( + @StringRes stringId: Int?, + vararg formatArgs: Any +) = stringResource(id = stringId ?: R.string.dummy_placeholder_text, *formatArgs) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt b/app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt new file mode 100644 index 0000000000..7cb16b9b04 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt @@ -0,0 +1,54 @@ +package com.vanced.manager.ui.components.list + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material.Checkbox +import androidx.compose.material.CheckboxDefaults +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.vanced.manager.ui.components.color.managerTextColor +import com.vanced.manager.ui.theme.managerAccentColor + +@Composable +fun CheckboxItem( + text: String, + isChecked: Boolean, + onCheck: (Boolean) -> Unit = {} +) { + fun toggle() { + onCheck(isChecked) + } + + Row( + modifier = Modifier + .fillMaxWidth() + .clickable { toggle() } + .padding(horizontal = 8.dp, vertical = 6.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Checkbox( + checked = isChecked, + onCheckedChange = { + toggle() + }, + colors = CheckboxDefaults.colors( + MaterialTheme.colors.managerAccentColor, + Color.LightGray + ) + ) + Text( + modifier = Modifier.padding(start = 12.dp), + text = text, + color = managerTextColor(), + fontSize = 18.sp + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/list/ManagerListItem.kt b/app/src/main/java/com/vanced/manager/ui/components/list/ManagerListItem.kt new file mode 100644 index 0000000000..63560220e7 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/list/ManagerListItem.kt @@ -0,0 +1,57 @@ +package com.vanced.manager.ui.components.list + +import androidx.compose.foundation.layout.* +import androidx.compose.material.ContentAlpha +import androidx.compose.material.LocalContentAlpha +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +@Composable +fun ManagerListItem( + modifier: Modifier = Modifier, + title: @Composable () -> Unit, + description: @Composable (() -> Unit)? = null, + icon: @Composable (() -> Unit)? = null, + trailing: @Composable (() -> Unit)? = null +) { + Row(modifier = modifier) { + if (icon != null) { + Box( + modifier = Modifier.align(Alignment.CenterVertically) + ) { + icon() + } + } + Column( + modifier = Modifier + .weight(1f) + .padding( + start = if (icon != null) 12.dp else 0.dp, + top = if (description != null) 6.dp else 12.dp, + bottom = if (description != null) 6.dp else 12.dp, + end = if (trailing != null) 12.dp else 0.dp, + ) + .align(Alignment.CenterVertically) + ) { + title() + if (description != null) { + CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) { + description() + } + } + } + if (trailing != null) { + Box( + modifier = Modifier + .size(56.dp) + .align(Alignment.CenterVertically), + contentAlignment = Alignment.Center, + ) { + trailing() + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt b/app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt new file mode 100644 index 0000000000..2b13cd12bb --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt @@ -0,0 +1,53 @@ +package com.vanced.manager.ui.components.list + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material.MaterialTheme +import androidx.compose.material.RadioButton +import androidx.compose.material.RadioButtonDefaults +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.vanced.manager.ui.components.color.managerTextColor +import com.vanced.manager.ui.theme.managerAccentColor + +@Composable +fun RadiobuttonItem( + text: String, + tag: T, + selected: Boolean, + onSelect: (tag: T) -> Unit +) { + val onClick = { + onSelect(tag) + } + + Row( + modifier = Modifier + .fillMaxWidth() + .clickable(onClick = onClick) + .padding(horizontal = 8.dp, vertical = 6.dp), + verticalAlignment = Alignment.CenterVertically + ) { + RadioButton( + selected = selected, + onClick = onClick, + colors = RadioButtonDefaults.colors( + MaterialTheme.colors.managerAccentColor, + Color.LightGray + ) + ) + Text( + modifier = Modifier.padding(start = 12.dp), + text = text, + color = managerTextColor(), + fontSize = 18.sp + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/menu/ManagerDropdownMenuItem.kt b/app/src/main/java/com/vanced/manager/ui/components/menu/ManagerDropdownMenuItem.kt new file mode 100644 index 0000000000..d1277a6670 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/menu/ManagerDropdownMenuItem.kt @@ -0,0 +1,21 @@ +package com.vanced.manager.ui.components.menu + +import androidx.compose.material.DropdownMenuItem +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import com.vanced.manager.ui.components.text.ManagerText + +@Composable +fun ManagerDropdownMenuItem( + title: String, + onClick: () -> Unit +) { + DropdownMenuItem( + onClick = onClick, + ) { + ManagerText( + text = title, + textStyle = MaterialTheme.typography.body1 + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/placeholder/ManagerPlaceholder.kt b/app/src/main/java/com/vanced/manager/ui/components/placeholder/ManagerPlaceholder.kt new file mode 100644 index 0000000000..93f47a3bfc --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/placeholder/ManagerPlaceholder.kt @@ -0,0 +1,18 @@ +package com.vanced.manager.ui.components.placeholder + +import androidx.compose.ui.Modifier +import androidx.compose.ui.composed +import com.google.accompanist.placeholder.PlaceholderHighlight +import com.google.accompanist.placeholder.material.placeholder +import com.google.accompanist.placeholder.material.shimmer + +fun Modifier.managerPlaceholder( + visible: Boolean +) = composed { + then( + placeholder( + visible = visible, + highlight = PlaceholderHighlight.shimmer() + ) + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxPreference.kt b/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxPreference.kt new file mode 100644 index 0000000000..0ca0ce8fd3 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxPreference.kt @@ -0,0 +1,68 @@ +package com.vanced.manager.ui.components.preference + +import androidx.annotation.StringRes +import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope +import com.vanced.manager.ui.components.checkbox.ManagerCheckbox +import com.vanced.manager.ui.preferences.ManagerPreference +import kotlinx.coroutines.launch + +@Composable +fun CheckboxPreference( + @StringRes preferenceTitle: Int, + @StringRes preferenceDescription: Int? = null, + preference: ManagerPreference, + onCheckedChange: (isChecked: Boolean) -> Unit = {} +) { + val isChecked by preference + val coroutineScope = rememberCoroutineScope() + + val onClick: () -> Unit = { + coroutineScope.launch { + preference.save(!isChecked) + onCheckedChange(isChecked) + } + } + + Preference( + preferenceTitleId = preferenceTitle, + preferenceDescriptionId = preferenceDescription, + onClick = onClick, + trailing = { + ManagerCheckbox( + isChecked = isChecked, + onCheckedChange = { onClick() } + ) + } + ) +} + +@Composable +fun CheckboxPreference( + preferenceTitle: String, + preferenceDescription: String? = null, + preference: ManagerPreference, + onCheckedChange: (isChecked: Boolean) -> Unit = {} +) { + val isChecked by preference + val coroutineScope = rememberCoroutineScope() + + val onClick: () -> Unit = { + coroutineScope.launch { + preference.save(!isChecked) + onCheckedChange(isChecked) + } + } + + Preference( + preferenceTitle = preferenceTitle, + preferenceDescription = preferenceDescription, + onClick = onClick, + trailing = { + ManagerCheckbox( + isChecked = isChecked, + onCheckedChange = { onClick() } + ) + } + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/DialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/components/preference/DialogPreference.kt new file mode 100644 index 0000000000..8d2fadea6b --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/preference/DialogPreference.kt @@ -0,0 +1,93 @@ +package com.vanced.manager.ui.components.preference + +import androidx.annotation.StringRes +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import com.vanced.manager.ui.components.dialog.ManagerDialog + +@Composable +fun DialogPreference( + @StringRes preferenceTitleId: Int, + @StringRes preferenceDescriptionId: Int? = null, + trailing: @Composable () -> Unit = {}, + buttons: @Composable ColumnScope.(isShown: MutableState) -> Unit, + content: @Composable ColumnScope.() -> Unit +) { + val isShown = remember { mutableStateOf(false) } + Preference( + preferenceTitleId = preferenceTitleId, + preferenceDescriptionId = preferenceDescriptionId, + trailing = trailing + ) { + isShown.value = true + } + if (isShown.value) { + ManagerDialog( + titleId = preferenceTitleId, + onDismissRequest = { + isShown.value = false + }, + buttons = { buttons(isShown) }, + content = content + ) + } +} + +@Composable +fun DialogPreference( + @StringRes preferenceTitleId: Int, + preferenceDescription: String? = null, + trailing: @Composable () -> Unit = {}, + buttons: @Composable ColumnScope.(isShown: MutableState) -> Unit, + content: @Composable ColumnScope.() -> Unit +) { + val isShown = remember { mutableStateOf(false) } + Preference( + preferenceTitleId = preferenceTitleId, + preferenceDescription = preferenceDescription, + trailing = trailing + ) { + isShown.value = true + } + if (isShown.value) { + ManagerDialog( + titleId = preferenceTitleId, + onDismissRequest = { + isShown.value = false + }, + buttons = { buttons(isShown) }, + content = content + ) + } +} + +@Composable +fun DialogPreference( + preferenceTitle: String, + preferenceDescription: String? = null, + trailing: @Composable () -> Unit = {}, + buttons: @Composable ColumnScope.(isShown: MutableState) -> Unit, + content: @Composable ColumnScope.() -> Unit +) { + val isShown = remember { mutableStateOf(false) } + Preference( + preferenceTitle = preferenceTitle, + preferenceDescription = preferenceDescription, + trailing = trailing + ) { + isShown.value = true + } + if (isShown.value) { + ManagerDialog( + title = preferenceTitle, + onDismissRequest = { + isShown.value = false + }, + buttons = { buttons(isShown) }, + content = content + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/Preference.kt b/app/src/main/java/com/vanced/manager/ui/components/preference/Preference.kt new file mode 100644 index 0000000000..7bb82ff178 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/preference/Preference.kt @@ -0,0 +1,98 @@ +package com.vanced.manager.ui.components.preference + +import androidx.annotation.StringRes +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.padding +import androidx.compose.material.LocalContentColor +import androidx.compose.material.LocalTextStyle +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Modifier +import com.vanced.manager.ui.components.color.managerAnimatedColor +import com.vanced.manager.ui.components.list.ManagerListItem +import com.vanced.manager.ui.components.text.ManagerText +import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal + +@Composable +fun Preference( + @StringRes preferenceTitleId: Int, + @StringRes preferenceDescriptionId: Int? = null, + trailing: @Composable () -> Unit = {}, + onClick: () -> Unit +) { + Preference( + preferenceTitle = { ManagerText(stringId = preferenceTitleId) }, + preferenceDescription = if (preferenceDescriptionId != null) {{ + ManagerText(stringId = preferenceDescriptionId) + }} else null, + trailing = trailing, + onClick = onClick + ) +} + +@Composable +fun Preference( + @StringRes preferenceTitleId: Int, + preferenceDescription: String? = null, + trailing: @Composable () -> Unit = {}, + onClick: () -> Unit +) { + Preference( + preferenceTitle = { ManagerText(stringId = preferenceTitleId) }, + preferenceDescription = if (preferenceDescription != null) {{ + ManagerText(text = preferenceDescription) + }} else null, + trailing = trailing, + onClick = onClick + ) +} + +@Composable +fun Preference( + preferenceTitle: String, + preferenceDescription: String? = null, + trailing: @Composable () -> Unit = {}, + onClick: () -> Unit +) { + Preference( + preferenceTitle = { ManagerText(text = preferenceTitle) }, + preferenceDescription = if (preferenceDescription != null) {{ + ManagerText(text = preferenceDescription) + }} else null, + trailing = trailing, + onClick = onClick + ) +} + +@Composable +fun Preference( + preferenceTitle: @Composable () -> Unit, + preferenceDescription: @Composable (() -> Unit)? = null, + trailing: @Composable () -> Unit = {}, + onClick: () -> Unit +) { + val color = managerAnimatedColor(color = MaterialTheme.colors.onSurface) + ManagerListItem( + modifier = Modifier + .clickable(onClick = onClick) + .padding(horizontal = defaultContentPaddingHorizontal), + title = { + CompositionLocalProvider( + LocalContentColor provides color, + LocalTextStyle provides MaterialTheme.typography.h6 + ) { + preferenceTitle() + } + }, + description = if (preferenceDescription != null) {{ + CompositionLocalProvider( + LocalContentColor provides color, + LocalTextStyle provides MaterialTheme.typography.subtitle1 + ) { + preferenceDescription() + } + }} else null, + trailing = trailing, + ) +} diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/PreferenceComponents.kt b/app/src/main/java/com/vanced/manager/ui/components/preference/PreferenceComponents.kt new file mode 100644 index 0000000000..d4b2bcb3d6 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/preference/PreferenceComponents.kt @@ -0,0 +1,66 @@ +package com.vanced.manager.ui.components.preference + +import androidx.annotation.StringRes +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.* +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import com.vanced.manager.R +import com.vanced.manager.ui.components.* +import com.vanced.manager.ui.components.button.ManagerThemedButton +import com.vanced.manager.ui.components.button.ManagerThemedTextButton +import com.vanced.manager.ui.components.list.CheckboxItem +import com.vanced.manager.ui.preferences.* +import kotlinx.coroutines.launch + +@Composable +fun CheckboxDialogPreference( + @StringRes preferenceTitle: Int, + @StringRes preferenceDescription: Int? = null, + preference: ManagerPreference>, + trailing: @Composable () -> Unit = {}, + buttons: List, + onSave: (checkedButtons: List) -> Unit = {} +) { + val selectedButtons = remember { preference.value.value.toMutableStateList() } + val coroutineScope = rememberCoroutineScope() + DialogPreference( + preferenceTitleId = preferenceTitle, + preferenceDescriptionId = preferenceDescription, + trailing = trailing, + buttons = { isShown -> + ManagerThemedTextButton( + stringId = R.string.dialog_button_save, + modifier = Modifier.fillMaxWidth(), + onClick = { + coroutineScope.launch { + preference.save(selectedButtons.toSet()) + onSave(selectedButtons) + isShown.value = false + } + } + ) + } + ) { + LazyColumn( + modifier = Modifier + ) { + items(buttons) { button -> + val (title, key) = button + CheckboxItem( + text = title, + isChecked = selectedButtons.contains(key), + onCheck = { isChecked -> + if (isChecked) { + selectedButtons.add(key) + } else { + selectedButtons.remove(key) + } + } + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt new file mode 100644 index 0000000000..bd4d042340 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt @@ -0,0 +1,63 @@ +package com.vanced.manager.ui.components.preference + +import androidx.annotation.StringRes +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.Text +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.vanced.manager.R +import com.vanced.manager.ui.components.button.ManagerThemedTextButton +import com.vanced.manager.ui.components.list.RadiobuttonItem +import com.vanced.manager.ui.preferences.ManagerPreference +import com.vanced.manager.ui.preferences.RadioButtonPreference +import kotlinx.coroutines.launch + +@Composable +fun RadiobuttonDialogPreference( + @StringRes preferenceTitle: Int, + preference: ManagerPreference, + trailing: @Composable () -> Unit = {}, + buttons: List, + onSave: (newPref: String?) -> Unit = {} +) { + val coroutineScope = rememberCoroutineScope() + var currentSelection by remember { mutableStateOf(preference.value.value) } + DialogPreference( + preferenceTitleId = preferenceTitle, + preferenceDescription = currentSelection, + trailing = trailing, + buttons = { isShown -> + ManagerThemedTextButton( + stringId = R.string.dialog_button_save, + modifier = Modifier.fillMaxWidth(), + onClick = { + coroutineScope.launch { + preference.save(currentSelection) + onSave(currentSelection) + isShown.value = false + } + } + ) + } + ) { + LazyColumn( + modifier = Modifier.heightIn(max = 400.dp) + ) { + items(buttons) { button -> + val (title, key) = button + RadiobuttonItem( + text = title, + tag = key, + selected = currentSelection == key, + onSelect = { + currentSelection = it + } + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/text/ManagerText.kt b/app/src/main/java/com/vanced/manager/ui/components/text/ManagerText.kt new file mode 100644 index 0000000000..09eb4844f0 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/text/ManagerText.kt @@ -0,0 +1,40 @@ +package com.vanced.manager.ui.components.text + +import androidx.compose.material.LocalTextStyle +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.TextStyle +import com.vanced.manager.ui.components.lifecycle.managerString + +@Composable +fun ManagerText( + vararg formatArgs: Any, + modifier: Modifier = Modifier, + color: Color = Color.Unspecified, + textStyle: TextStyle = LocalTextStyle.current, + stringId: Int?, +) { + ManagerText( + modifier = modifier, + color = color, + textStyle = textStyle, + text = managerString(stringId, *formatArgs), + ) +} + +@Composable +fun ManagerText( + modifier: Modifier = Modifier, + color: Color = Color.Unspecified, + textStyle: TextStyle = LocalTextStyle.current, + text: String, +) { + Text( + modifier = modifier, + text = text, + color = color, + style = textStyle + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/composables/AppComposables.kt b/app/src/main/java/com/vanced/manager/ui/composables/AppComposables.kt deleted file mode 100644 index 0b84f5aa59..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/composables/AppComposables.kt +++ /dev/null @@ -1,226 +0,0 @@ -package com.vanced.manager.ui.composables - -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* -import androidx.compose.material.* -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.DeleteForever -import androidx.compose.material.icons.filled.Download -import androidx.compose.material.icons.filled.Launch -import androidx.compose.material.icons.outlined.Info -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.painter.Painter -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import com.google.accompanist.glide.rememberGlidePainter -import com.vanced.manager.R -import com.vanced.manager.domain.model.App -import com.vanced.manager.downloader.base.BaseDownloader -import com.vanced.manager.ui.theme.managerAccentColor - -@OptIn(ExperimentalAnimationApi::class) -@Composable -fun AppCard( - app: App, - installationOptions: List? = null -) { - val showDownloadDialog = remember { mutableStateOf(false) } - val showAppInfo = remember { mutableStateOf(false) } - val showInstallationOptions = remember { mutableStateOf(false) } - val icon = rememberGlidePainter( - request = app.iconUrl ?: "", - requestBuilder = { - placeholder(R.drawable.ic_app_icon_placeholder) - }, - fadeIn = true - ) - ManagerCard { - Column { - AppInfoCard( - appName = app.name, - icon = icon - ) - AppActionCard( - appInstalledVersion = app.installedVersion, - appRemoteVersion = app.remoteVersion, - showDownloadDialog = showDownloadDialog, - showAppInfo = showAppInfo, - showInstallationOptions = showInstallationOptions - ) - if (installationOptions != null) { - AnimatedVisibility( - modifier = Modifier.fillMaxWidth(), - visible = showInstallationOptions.value - ) { - installationOptions.forEach { - it.Content() - } - } - } - } - } - - if (app.name != null && app.downloader != null) { - AppDownloadDialog( - app = app.name, - downloader = app.downloader, - showDialog = showDownloadDialog - ) - } - - if (app.name != null && app.changelog != null) { - ChangeLogDialog( - appName = app.name, - changelog = app.changelog, - icon = icon, - show = showAppInfo - ) - } -} - -@Composable -fun AppInfoCard( - appName: String?, - icon: Painter -) { - ManagerListItem( - title = appName ?: "", - icon = { - Image( - painter = icon, - contentDescription = "", - modifier = Modifier.size(48.dp, 48.dp), - ) - }, - topPadding = 8.dp, - bottomPadding = 8.dp - ) -} - -@Composable -fun AppActionCard( - appRemoteVersion: String?, - appInstalledVersion: String?, - showDownloadDialog: MutableState, - showAppInfo: MutableState, - showInstallationOptions: MutableState -) { - CompositionLocalProvider(LocalContentColor provides MaterialTheme.colors.managerAccentColor) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 12.dp, vertical = 4.dp) - .background(managerAccentColor().copy(alpha = 0.15f)), - verticalAlignment = Alignment.CenterVertically - ) { - Column( - modifier = Modifier - .weight(1f) - .wrapContentWidth(Alignment.Start) - ) { - Text( - text = "Latest: ${appRemoteVersion ?: "Unavailable"}", - fontSize = 12.sp - ) - Text( - text = "Installed: ${appInstalledVersion ?: "Unavailable"}", - fontSize = 12.sp - ) - } - Row( - modifier = Modifier - .weight(1f) - .padding(start = 4.dp) - .wrapContentWidth(Alignment.End) - ) { - IconButton(icon = Icons.Outlined.Info, contentDescription = "App Info") { - showAppInfo.value = true - } - IconButton(icon = Icons.Default.DeleteForever, contentDescription = "Uninstall") {} - IconButton(icon = Icons.Default.Launch, contentDescription = "Launch") {} - IconButton(icon = Icons.Default.Download, contentDescription = "Install") { - showInstallationOptions.value = true - } - } - } - } -} - -@Composable -fun AppDownloadDialog( - app: String, - downloader: BaseDownloader, - showDialog: MutableState -) { - val coroutineScope = rememberCoroutineScope() - - val rememberProgress = remember { downloader.downloadProgress } - val rememberFile = remember { downloader.downloadFile } - val rememberInstalling = remember { downloader.installing } - - val showProgress = remember { mutableStateOf(false) } - ManagerDialog(title = app, isShown = showDialog, buttons = { - AppDownloadDialogButtons( - showProgress = showProgress, - showDialog = showDialog, - downloader = downloader, - coroutineScope = coroutineScope - ) - }) { - AppDownloadDialogProgress( - progress = rememberProgress, - file = rememberFile, - showProgress = showProgress.value, - installing = rememberInstalling - ) - } -} - -@Composable -fun ChangeLogDialog( - appName: String, - changelog: String, - icon: Painter, - show: MutableState -) { - if (show.value) { - ManagerDialog( - title = "About $appName", - isShown = show, - buttons = { - ManagerThemedButton( - modifier = Modifier.fillMaxWidth(), - onClick = { show.value = false } - ) { - Text(text = "Close") - } - } - ) { - Image( - painter = icon, - contentDescription = null, - modifier = Modifier - .size(64.dp) - .align(Alignment.CenterHorizontally) - ) - HeaderView( - modifier = Modifier.padding(horizontal = 8.dp), - headerName = "Changelog", - headerPadding = 0.dp - ) { - Text( - modifier = Modifier.padding(top = 4.dp), - text = changelog, - fontSize = 14.sp - ) - } - } - } -} - - diff --git a/app/src/main/java/com/vanced/manager/ui/composables/ColorPicker.kt b/app/src/main/java/com/vanced/manager/ui/composables/ColorPicker.kt deleted file mode 100644 index 70e66ba9a0..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/composables/ColorPicker.kt +++ /dev/null @@ -1,105 +0,0 @@ -package com.vanced.manager.ui.composables - -import androidx.compose.foundation.Canvas -import androidx.compose.foundation.gestures.detectDragGestures -import androidx.compose.foundation.layout.size -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.graphics.Brush -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.drawscope.DrawScope -import androidx.compose.ui.graphics.drawscope.Stroke -import androidx.compose.ui.graphics.drawscope.inset -import androidx.compose.ui.input.pointer.PointerInputChange -import androidx.compose.ui.input.pointer.pointerInput -import androidx.compose.ui.unit.dp -import androidx.core.graphics.ColorUtils - -//TODO -@Composable -fun HSLColorPicker( - modifier: Modifier = Modifier -) { - val hslColors = floatArrayOf(0f, 1f, 0.5f) - val hueColors = getColors(hslColors, length = 360, index = 0) { it } - val saturationColors = getColors(hslColors, length = 11, index = 1) { it / 10 } - val lightnessColors = getColors(hslColors, length = 11, index = 2) { it / 10 } - - val hueCircle by remember { mutableStateOf(Offset(0f, 0f)) } - val saturationCircle by remember { mutableStateOf(Offset(0f, 0f)) } - val lightnessCircle by remember { mutableStateOf(Offset(0f, 0f)) } - Canvas(modifier = modifier - .size(250.dp, 250.dp) - .pointerInput(Unit) { - detectDragGestures { change: PointerInputChange, dragAmount: Offset -> - val (changeX, changeY) = change.position - } - } - ) { - colorArc( - brush = Brush.sweepGradient(hueColors), - startAngle = 0f, - sweepAngle = 360f, - circleOffset = hueCircle - ) - inset( - inset = 60f - ) { - colorArc( - brush = Brush.linearGradient( - colors = saturationColors, - start = Offset.Infinite, - end = Offset.Zero - ), - startAngle = 100f, - sweepAngle = 155f, - circleOffset = saturationCircle - ) - colorArc( - brush = Brush.linearGradient(lightnessColors), - startAngle = 280f, - sweepAngle = 155f, - circleOffset = lightnessCircle - ) - } - } -} - -fun DrawScope.colorArc( - brush: Brush, - startAngle: Float, - sweepAngle: Float, - circleOffset: Offset -) { - drawArc( - brush = brush, - startAngle = startAngle, - sweepAngle = sweepAngle, - useCenter = false, - style = Stroke(width = 15f) - ) - - inset(circleOffset.x, circleOffset.y) { - drawCircle( - brush = brush, - radius = 50f - ) - } -} - -fun getColors( - hslColors: FloatArray, - length: Int, - index: Int, - calculate: (Float) -> Float -): List { - val colorsCopy = hslColors.copyOf() - return List(length) { - colorsCopy[index] = calculate(it.toFloat()) - Color(ColorUtils.HSLToColor(colorsCopy)) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/composables/DialogComposables.kt b/app/src/main/java/com/vanced/manager/ui/composables/DialogComposables.kt deleted file mode 100644 index 7f3dc152c9..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/composables/DialogComposables.kt +++ /dev/null @@ -1,2 +0,0 @@ -package com.vanced.manager.ui.composables - diff --git a/app/src/main/java/com/vanced/manager/ui/composables/DownloadComposables.kt b/app/src/main/java/com/vanced/manager/ui/composables/DownloadComposables.kt deleted file mode 100644 index ae47523512..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/composables/DownloadComposables.kt +++ /dev/null @@ -1,111 +0,0 @@ -package com.vanced.manager.ui.composables - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.wrapContentWidth -import androidx.compose.material.Icon -import androidx.compose.material.LinearProgressIndicator -import androidx.compose.material.Text -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowForwardIos -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import com.vanced.manager.downloader.base.BaseDownloader -import dev.burnoo.compose.rememberpreference.rememberStringPreference -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch - -data class InstallationOptionKey( - val keyName: String, - val keyDefaultValue: String = "", - val keyInitialValue: String = keyDefaultValue -) - -data class InstallationOption( - val title: String, - val descriptionKey: InstallationOptionKey, - val dialog: @Composable (show: MutableState, preference: MutableState) -> Unit -) { - - @Composable - fun Content() { - val showDialog = remember { mutableStateOf(false) } - val preference = rememberStringPreference( - keyName = descriptionKey.keyName, - defaultValue = descriptionKey.keyDefaultValue, - initialValue = descriptionKey.keyInitialValue - ) - ManagerListItem( - modifier = Modifier.clickable { - showDialog.value = true - }, - title = title, - description = preference.value, - trailing = { - Icon(imageVector = Icons.Default.ArrowForwardIos, contentDescription = null) - } - ) - if (showDialog.value) { - dialog(showDialog, preference) - } - } -} - -@Composable -fun AppDownloadDialogButtons( - showProgress: MutableState, - showDialog: MutableState, - downloader: BaseDownloader, - coroutineScope: CoroutineScope -) { - when(showProgress.value) { - true -> ManagerThemedButton(onClick = { - downloader.cancelDownload() - showDialog.value = false - showProgress.value = false - }) { - Text(text = "Cancel") - } - false -> ManagerThemedButton(onClick = { - coroutineScope.launch { - showProgress.value = true - downloader.download() - } - }) { - Text(text = "Download") - } - } -} - -@Composable -fun AppDownloadDialogProgress( - progress: Float, - file: String, - showProgress: Boolean, - installing: Boolean -) { - if (showProgress) { - when (installing) { - true -> LinearProgressIndicator(color = managerAccentColor()) - false -> LinearProgressIndicator( - progress = progress, - color = managerAccentColor() - ) - } - Row { - Text( - modifier = Modifier - .weight(1f) - .wrapContentWidth(Alignment.Start), - text = "Downloading $file" - ) - Text( - modifier = Modifier - .weight(1f) - .wrapContentWidth(Alignment.End), - text = "$progress" - ) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/composables/GlobalComposables.kt b/app/src/main/java/com/vanced/manager/ui/composables/GlobalComposables.kt deleted file mode 100644 index 2b3da173d8..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/composables/GlobalComposables.kt +++ /dev/null @@ -1,140 +0,0 @@ -package com.vanced.manager.ui.composables - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.* -import androidx.compose.material.* -import androidx.compose.material.ripple.rememberRipple -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.semantics.Role -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.em -import androidx.compose.ui.unit.sp -import com.vanced.manager.ui.theme.managerAccentColor - -@ExperimentalStdlibApi -@Composable -fun HeaderCard( - headerName: String, - headerPadding: Dp = 11.dp, - content: @Composable ColumnScope.() -> Unit -) { - ManagerCard( - modifier = Modifier - .fillMaxWidth() - ) { - Column { - Spacer(modifier = Modifier.size(height = 4.dp, width = 0.dp)) - HeaderView( - headerName = headerName, - content = content, - headerPadding = headerPadding - ) - } - } -} - -@Composable -fun HeaderView( - modifier: Modifier = Modifier, - headerName: String, - headerPadding: Dp = 11.dp, - content: @Composable ColumnScope.() -> Unit -) { - Column( - modifier = modifier - ) { - Header(headerName = headerName, headerPadding = headerPadding) - content() - } -} - -@OptIn(ExperimentalStdlibApi::class) -@Composable -fun Header( - headerName: String, - headerPadding: Dp = 11.dp, -) { - Text( - headerName.uppercase(), - letterSpacing = 0.15.em, - color = MaterialTheme.colors.managerAccentColor, - modifier = Modifier.padding(horizontal = headerPadding), - fontWeight = FontWeight.Bold, - fontSize = 13.sp - ) -} - -@Composable -fun IconButton( - icon: ImageVector, - contentDescription: String, - onClick: () -> Unit -) { - val interactionSource = remember { MutableInteractionSource() } - val buttonSize = 36.dp - val enabled = true - Box( - modifier = Modifier - .clickable( - onClick = onClick, - enabled = enabled, - role = Role.Button, - interactionSource = interactionSource, - indication = rememberRipple(bounded = false, radius = 18.dp) - ) - .size(buttonSize), - contentAlignment = Alignment.Center - ) { - val contentAlpha = if (enabled) LocalContentAlpha.current else ContentAlpha.disabled - CompositionLocalProvider(LocalContentAlpha provides contentAlpha) { - Icon( - imageVector = icon, - contentDescription = contentDescription - ) - } - } -} - -@Composable -fun RadiobuttonItem( - currentSelection: MutableState, - text: String, - preferenceValue: String, -) { - Row( - modifier = Modifier - .fillMaxWidth() - .clickable { - currentSelection.value = preferenceValue - } - .padding(horizontal = 8.dp, vertical = 6.dp), - verticalAlignment = Alignment.CenterVertically - ) { - RadioButton( - selected = preferenceValue == currentSelection.value, - onClick = { - currentSelection.value = preferenceValue - }, - colors = RadioButtonDefaults.colors( - MaterialTheme.colors.managerAccentColor, - Color.LightGray - ) - ) - Text( - modifier = Modifier.padding(start = 4.dp), - text = text, - color = managerTextColor(), - fontSize = 18.sp - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/composables/HomeComposables.kt b/app/src/main/java/com/vanced/manager/ui/composables/HomeComposables.kt deleted file mode 100644 index b30469da76..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/composables/HomeComposables.kt +++ /dev/null @@ -1,80 +0,0 @@ -package com.vanced.manager.ui.composables - -import android.net.Uri -import androidx.annotation.DrawableRes -import androidx.browser.customtabs.CustomTabsIntent -import androidx.compose.foundation.Image -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyRow -import androidx.compose.foundation.lazy.itemsIndexed -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.LocalContentColor -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp - -@Composable -fun LinkCard( - @DrawableRes icon: Int, - title: String, - link: String -) { - val context = LocalContext.current - val customTabs = remember { CustomTabsIntent.Builder().build() } - ManagerCard( - modifier = Modifier - .clip(RoundedCornerShape(12.dp)) - .clickable { - customTabs.launchUrl(context, Uri.parse(link)) - } - .size(width = 120.dp, height = 100.dp) - ) { - CompositionLocalProvider(LocalContentColor provides managerTextColor()) { - Column( - modifier = Modifier.padding(all = 16.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - Image( - modifier = Modifier.size(36.dp), - painter = painterResource(id = icon), - contentDescription = null, - ) - Spacer(modifier = Modifier.height(8.dp)) - Text( - text = title, - textAlign = TextAlign.Center - ) - } - } - } -} - -@Composable -fun ScrollableLinkRow( - items: List, - content: @Composable (T) -> Unit -) { - val state = rememberLazyListState() - LazyRow( - modifier = Modifier.fillMaxWidth(), - state = state - ) { - itemsIndexed(items) { index, item -> - content(item) - if (index < items.size - 1) { - Spacer(modifier = Modifier.width(8.dp)) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/composables/ManagerComponents.kt b/app/src/main/java/com/vanced/manager/ui/composables/ManagerComponents.kt deleted file mode 100644 index 506b90b305..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/composables/ManagerComponents.kt +++ /dev/null @@ -1,229 +0,0 @@ -package com.vanced.manager.ui.composables - -import androidx.annotation.StringRes -import androidx.compose.animation.animateColorAsState -import androidx.compose.animation.core.tween -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyListScope -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.verticalScroll -import androidx.compose.material.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.graphics.luminance -import androidx.compose.ui.platform.LocalConfiguration -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.compose.ui.window.Dialog -import com.vanced.manager.ui.theme.cardColor -import com.vanced.manager.ui.theme.managerAccentColor -import java.util.* - -@Composable -fun managerShape() = RoundedCornerShape(12.dp) - -@Composable -fun ManagerCard( - modifier: Modifier = Modifier, - shape: Shape = managerShape(), - content: @Composable () -> Unit, -) { - Card( - modifier = modifier, - shape = shape, - backgroundColor = managerCardColor(), - elevation = 0.dp, - content = content - ) -} - -@Composable -fun ManagerThemedButton( - modifier: Modifier = Modifier, - onClick: () -> Unit, - content: @Composable RowScope.() -> Unit -) { - val accentColor = managerAccentColor() - Button( - modifier = modifier, - onClick = onClick, - shape = managerShape(), - colors = ButtonDefaults.buttonColors( - backgroundColor = managerAccentColor() - ), - elevation = ButtonDefaults.elevation(0.dp) - ) { - CompositionLocalProvider(LocalContentColor provides if (accentColor.luminance() > 0.7) Color.Black else Color.White) { - content() - } - } -} - -@Composable -fun ManagerDialog( - title: String, - isShown: MutableState, - buttons: @Composable ColumnScope.() -> Unit, - content: @Composable ColumnScope.() -> Unit, -) { - Dialog( - onDismissRequest = { isShown.value = false }, - content = { - ManagerCard { - Column( - modifier = Modifier.padding(all = 8.dp) - ) { - Text( - modifier = Modifier.fillMaxWidth(), - text = title, - letterSpacing = 2.sp, - fontWeight = FontWeight.Bold, - color = managerTextColor().copy(alpha = 0.8f), - fontSize = 24.sp, - textAlign = TextAlign.Center - ) - Spacer(Modifier.height(8.dp)) - content() - Spacer(Modifier.height(8.dp)) - buttons() - } - } - } - ) -} - -@Composable -fun ManagerSurface( - content: @Composable () -> Unit -) { - Surface( - modifier = Modifier.fillMaxSize(), - color = managerSurfaceColor(), - content = content - ) -} - -@Composable -fun ManagerLazyColumn( - content: LazyListScope.() -> Unit -) { - LazyColumn( - contentPadding = PaddingValues(12.dp), - content = content - ) -} - -@Composable -fun ManagerScrollableColumn( - content: @Composable ColumnScope.() -> Unit -) { - val scrollState = rememberScrollState() - Column( - modifier = Modifier - .verticalScroll(scrollState) - .padding(12.dp), - horizontalAlignment = Alignment.CenterHorizontally, - content = content - ) -} - -@Composable -fun ManagerDropdownMenuItem( - isMenuExpanded: MutableState, - title: String, - onClick: () -> Unit -) { - DropdownMenuItem( - onClick = { - isMenuExpanded.value = false - onClick() - }, - ) { - Text(text = title) - } -} - -@Composable -fun animateManagerColor( - color: Color -): State { - return animateColorAsState( - targetValue = color, - animationSpec = tween(500) - ) -} - -@Composable -fun HomeHeaderView( - modifier: Modifier = Modifier, - headerName: String, - content: @Composable () -> Unit -) { - HeaderView( - modifier = modifier, - headerName = headerName, - headerPadding = 4.dp - ) { - ManagerHomeHeaderSeparator() - content() - } -} - -@Composable -fun managerAnimatedColor( - color: Color -): Color { - val animColor by animateColorAsState( - targetValue = color, - animationSpec = tween(500) - ) - return animColor -} - -@Composable -fun managerAnimatedText( - @StringRes stringId: Int -): String { - var text by remember { mutableStateOf("") } - CompositionLocalProvider( - LocalConfiguration provides LocalConfiguration.current.apply { - setLocale(Locale("ru")) - } - ) { - text = stringResource(id = stringId) - } - return text -} - -@Composable -fun ManagerCardSeparator() { - Spacer(modifier = Modifier.height(8.dp)) -} - -@Composable -fun ManagerHomeHeaderSeparator() { - Spacer(modifier = Modifier.height(4.dp)) -} - -@Composable -fun managerTextColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.onSurface) - -@Composable -fun managerSurfaceColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.surface) - -@Composable -fun managerCardColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.cardColor) - -@Composable -fun managerAccentColor(): Color = MaterialTheme.colors.managerAccentColor - -@Composable -fun animatedManagerAccentColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.managerAccentColor) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/composables/ManagerListItem.kt b/app/src/main/java/com/vanced/manager/ui/composables/ManagerListItem.kt deleted file mode 100644 index 77a4582225..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/composables/ManagerListItem.kt +++ /dev/null @@ -1,95 +0,0 @@ -package com.vanced.manager.ui.composables - -import androidx.compose.foundation.layout.* -import androidx.compose.material.* -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp - -const val defaultPadding = 12 - -@Composable -fun ManagerListItem( - modifier: Modifier = Modifier, - title: String, - description: String? = null, - startPadding: Dp = defaultPadding.dp, - endPadding: Dp = defaultPadding.dp, - topPadding: Dp = defaultPadding.dp, - bottomPadding: Dp = defaultPadding.dp, - icon: @Composable (() -> Unit)? = null, - trailing: @Composable (() -> Unit)? = null -) { - val typography = MaterialTheme.typography - val textColor by animateManagerColor(color = MaterialTheme.colors.onBackground) - Box( - modifier = modifier - ) { - Row( - modifier = Modifier - .padding(top = topPadding, bottom = bottomPadding) - ) { - if (icon != null) { - Box( - modifier = Modifier - .padding(start = startPadding) - .align(Alignment.CenterVertically) - ) { - icon() - } - } - Column( - modifier = Modifier - .padding( - start = startPadding, - end = endPadding - ) - .weight(1f) - .align(Alignment.CenterVertically) - ) { - if (description == null) { - Spacer(modifier = Modifier.size(6.dp)) - } - Text( - text = title, - fontSize = 16.sp, - modifier = Modifier.fillMaxWidth(), - style = typography.subtitle1, - color = textColor - ) - if (description != null) { - CompositionLocalProvider( - LocalContentAlpha provides ContentAlpha.medium, - LocalContentColor provides textColor - ) { - Text( - text = description, - fontSize = 12.sp, - modifier = Modifier.fillMaxWidth() - ) - } - } - if (description == null) { - Spacer(modifier = Modifier.size(6.dp)) - } - - } - if (trailing != null) { - Box( - modifier = Modifier - .padding(end = endPadding) - .align(Alignment.CenterVertically) - ) { - CompositionLocalProvider(LocalContentColor provides textColor) { - trailing() - } - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/composables/PreferenceComposables.kt b/app/src/main/java/com/vanced/manager/ui/composables/PreferenceComposables.kt deleted file mode 100644 index 8283b498d2..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/composables/PreferenceComposables.kt +++ /dev/null @@ -1,148 +0,0 @@ -package com.vanced.manager.ui.composables - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material.* -import androidx.compose.runtime.* -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.unit.dp -import androidx.core.content.edit -import androidx.preference.PreferenceManager -import com.vanced.manager.ui.preferences.RadioButtonPreference - -@Composable -fun SwitchPreference( - preferenceTitle: String, - preferenceDescription: String?, - preferenceKey: String, - defaultValue: Boolean = true, - onCheckedChange: (isChecked: Boolean) -> Unit = {} -) { - val prefs = PreferenceManager.getDefaultSharedPreferences(LocalContext.current) - var isChecked by remember { mutableStateOf(prefs.getBoolean(preferenceKey, defaultValue)) } - - fun savePreference() { - isChecked = !isChecked - prefs.edit { - putBoolean(preferenceKey, isChecked) - } - onCheckedChange(isChecked) - } - - Preference( - preferenceTitle = preferenceTitle, - preferenceDescription = preferenceDescription, - onClick = { savePreference() }, - trailing = { - Switch( - checked = isChecked, - onCheckedChange = { savePreference() }, - colors = SwitchDefaults.colors( - checkedThumbColor = managerAccentColor(), - checkedTrackColor = managerAccentColor(), - uncheckedThumbColor = Color.Gray, - uncheckedTrackColor = Color.Gray - ) - ) - } - ) -} - -@Composable -fun Preference( - preferenceTitle: String, - preferenceDescription: String? = null, - trailing: @Composable (() -> Unit)? = null, - onClick: () -> Unit -) { - ManagerListItem( - modifier = Modifier.clickable(onClick = onClick), - title = preferenceTitle, - description = preferenceDescription, - trailing = trailing, - bottomPadding = 4.dp, - topPadding = 4.dp - ) -} - -@Composable -fun DialogPreference( - preferenceTitle: String, - preferenceDescription: String? = null, - trailing: @Composable (() -> Unit)? = null, - buttons: @Composable ColumnScope.(isShown: MutableState) -> Unit, - content: @Composable ColumnScope.() -> Unit -) { - val isShown = remember { mutableStateOf(false) } - Preference( - preferenceTitle = preferenceTitle, - preferenceDescription = preferenceDescription, - trailing = trailing - ) { - isShown.value = true - } - if (isShown.value) { - ManagerDialog( - title = preferenceTitle, - isShown = isShown, - buttons = { buttons(isShown) }, - content = content - ) - } -} - -@Composable -fun DialogRadioButtonPreference( - preferenceTitle: String, - preferenceKey: String, - defaultValue: String, - preferenceDescription: String? = null, - trailing: @Composable (() -> Unit)? = null, - buttons: List, - onSave: (newPref: String?) -> Unit = {} -) { - val prefs = PreferenceManager.getDefaultSharedPreferences(LocalContext.current) - val currentSelection = remember { mutableStateOf(prefs.getString(preferenceKey, defaultValue)) } - DialogPreference( - preferenceTitle = preferenceTitle, - preferenceDescription = preferenceDescription, - trailing = trailing, - buttons = { isShown -> - ManagerThemedButton( - modifier = Modifier.fillMaxWidth(), - onClick = { - prefs.edit { - putString(preferenceKey, currentSelection.value) - } - onSave(currentSelection.value) - isShown.value = false - } - ) { - Text(text = "Save") - } - } - ) { - LazyColumn( - modifier = Modifier - .weight( - weight = 1f, - fill = false - ) - - ) { - items(buttons) { button -> - val (title, key) = button - RadiobuttonItem( - currentSelection = currentSelection, - text = title, - preferenceValue = key - ) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/AboutLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/AboutLayout.kt index faacd8b4ad..01866bf0fe 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/AboutLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/layouts/AboutLayout.kt @@ -1,193 +1,205 @@ package com.vanced.manager.ui.layouts -import android.content.res.Configuration.UI_MODE_NIGHT_YES -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.items -import androidx.compose.material.* -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Circle +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.withStyle -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.vanced.manager.ui.composables.HeaderCard -import com.vanced.manager.ui.composables.ManagerCard -import com.vanced.manager.ui.composables.ManagerLazyColumn -import com.vanced.manager.ui.composables.managerTextColor -import com.vanced.manager.ui.theme.ComposeTestTheme -import com.vanced.manager.ui.theme.vancedBlue -import com.vanced.manager.ui.theme.vancedRed +import androidx.compose.ui.util.fastForEach +import com.vanced.manager.R +import com.vanced.manager.ui.components.card.ManagerLinkCard +import com.vanced.manager.ui.components.card.ManagerThemedCard +import com.vanced.manager.ui.components.layout.ManagerScrollableColumn +import com.vanced.manager.ui.components.layout.ScrollableItemRow +import com.vanced.manager.ui.components.lifecycle.managerString +import com.vanced.manager.ui.components.list.ManagerListItem +import com.vanced.manager.ui.components.text.ManagerText +import com.vanced.manager.ui.widgets.layout.CategoryLayout + +data class Person( + val name: String, + val contribution: String +) data class Credit( - val creditName: String, - val persons: List + @StringRes val nameId: Int, + val persons: List ) data class Source( - val sourceLink: String + @StringRes val nameId: Int, + @DrawableRes val iconId: Int, + val link: String ) private val credits = listOf( Credit( - creditName = "Vanced Team", + nameId = R.string.about_category_credits_vanced_team, persons = listOf( - "xfileFIN", - "ZaneZam", - "Laura Almeida", - "KevinX8" + Person( + name = "xfileFIN", + contribution = "Mods, Theming, Support" + ), + Person( + name = "Laura", + contribution = "Theming, Support" + ), + Person( + name = "ZaneZam", + contribution = "Publishing, Support" + ), + Person( + name = "KevinX8", + contribution = "Overlord, Support" + ) ) ), Credit( - creditName = "Manager Team", + nameId = R.string.about_category_credits_manager_devs, persons = listOf( - "Xinto", - "Koopah", - "Logan" + Person( + name = "Xinto", + contribution = "Manager Core" + ), + Person( + name = "Koopah", + contribution = "Root installer" + ), + Person( + name = "Logan", + contribution = "UI" + ), + Person( + name = "HaliksaR", + contribution = "Refactoring, UI" + ), ) ), Credit( - creditName = "Other Contributors", + nameId = R.string.about_category_credits_other, persons = listOf( - "bhatVikrant", - "bawm", - "AioiLight", - "HaliksaR" + Person( + name = "bhatVikrant", + contribution = "Website" + ), + Person( + name = "bawm", + contribution = "Sponsorblock" + ), + Person( + name = "cane", + contribution = "Sponsorblock" + ), ) ) ) private val sources = listOf( Source( - "" + nameId = R.string.about_sources_source_code, + iconId = R.drawable.ic_github, + link = "https://github.com/YTVanced/VancedManager" ), Source( - "" + nameId = R.string.about_sources_license, + iconId = R.drawable.ic_round_assignment_24, + link = "https://raw.githubusercontent.com/YTVanced/VancedManager/dev/LICENSE" ) ) -@ExperimentalStdlibApi -@Composable -@Preview( - showSystemUi = true, - uiMode = UI_MODE_NIGHT_YES -) -fun AboutDarkMode() { - ComposeTestTheme { - AboutLayout() - } -} - -@ExperimentalStdlibApi -@Composable -@Preview( - showSystemUi = true -) -fun AboutLightMode() { - MaterialTheme { - AboutLayout() - } -} - -@ExperimentalStdlibApi @Composable fun AboutLayout() { - ManagerLazyColumn { - item { - ManagerCard { - Column( - modifier = Modifier - .background( - Brush.horizontalGradient( - colors = listOf( - vancedBlue, - vancedRed - ), - ) - ) - ) { - Spacer(modifier = Modifier.size(width = 0.dp, height = 8.dp)) - Text( - text = "Vanced Manager", - textAlign = TextAlign.Center, - modifier = Modifier.fillMaxWidth(), - fontSize = 30.sp, - color = Color.White - ) - Text( - text = buildAnnotatedString { - append("Re") - withStyle(style = SpanStyle(Color(0xFFBBB529))) { - append("@Compose") + ManagerScrollableColumn( + itemSpacing = 12.dp + ) { + AboutManagerCard() + credits.fastForEach { credit -> + CategoryLayout( + categoryNameId = credit.nameId, + categoryNameSpacing = 4.dp + ) { + Column { + credit.persons.fastForEach { person -> + ManagerListItem( + title = { + ManagerText( + text = person.name, + textStyle = MaterialTheme.typography.h6 + ) + }, + description = { + ManagerText( + text = person.contribution, + textStyle = MaterialTheme.typography.subtitle1 + ) } - append("d") - }, - textAlign = TextAlign.Center, - modifier = Modifier.fillMaxWidth(), - fontSize = 16.sp, - color = Color.White - ) - Spacer(modifier = Modifier.size(width = 0.dp, height = 8.dp)) + ) + } } } } - - items(credits) { credit -> - Spacer(modifier = Modifier.size(width = 0.dp, height = 12.dp)) - CreditsCard(creditName = credit.creditName, persons = credit.persons) - } - - item { - Spacer(modifier = Modifier.size(width = 0.dp, height = 12.dp)) - HeaderCard( - headerName = "Sources" - ) { - Row(modifier = Modifier.fillMaxWidth()) { - sources.forEach { _ -> - Box( - modifier = Modifier.weight(1f), - contentAlignment = Alignment.Center - ) { - Icon(imageVector = Icons.Default.Circle, contentDescription = null, modifier = Modifier.size(36.dp)) - } - } - } - Spacer(modifier = Modifier.size(8.dp)) + CategoryLayout(categoryNameId = R.string.about_category_sources) { + ScrollableItemRow(items = sources) { source -> + ManagerLinkCard( + title = managerString(source.nameId), + icon = source.iconId, + link = source.link + ) } } } } @Composable -@ExperimentalStdlibApi -fun CreditsCard( - creditName: String, - persons: List -) { - HeaderCard( - headerName = creditName - ) { - CompositionLocalProvider( - LocalContentAlpha provides ContentAlpha.medium, - LocalContentColor provides managerTextColor() +fun AboutManagerCard() { + ManagerThemedCard { + Column( + modifier = Modifier +// .clip(managerShape()) +// .background( +// Brush.horizontalGradient( +// colors = listOf( +// vancedBlue, +// vancedRed +// ) +// ) +// ) ) { Text( - text = persons.joinToString("\n"), + text = "Vanced Manager", + textAlign = TextAlign.Center, + modifier = Modifier + .fillMaxWidth() + .padding(top = 8.dp), + fontSize = 30.sp, + color = Color.White + ) + Text( + text = buildAnnotatedString { + append("Re") + withStyle(style = SpanStyle(Color(0xFFBBB529))) { + append("@Compose") + } + append("d") + }, + textAlign = TextAlign.Center, modifier = Modifier .fillMaxWidth() - .padding(horizontal = 12.dp), - fontSize = 13.sp + .padding(bottom = 8.dp), + fontSize = 16.sp, + color = Color.White ) } - Spacer(modifier = Modifier.size(width = 0.dp, height = 2.dp)) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt index 90f2c8b5c1..3806300d89 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt @@ -1,28 +1,31 @@ package com.vanced.manager.ui.layouts -import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState -import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.compose.ui.util.fastForEachIndexed +import androidx.compose.ui.util.fastForEach import com.google.accompanist.swiperefresh.SwipeRefresh import com.google.accompanist.swiperefresh.SwipeRefreshIndicator import com.google.accompanist.swiperefresh.rememberSwipeRefreshState import com.vanced.manager.R import com.vanced.manager.domain.model.App -import com.vanced.manager.ui.composables.* +import com.vanced.manager.ui.components.* +import com.vanced.manager.ui.components.card.ManagerLinkCard +import com.vanced.manager.ui.components.color.managerAccentColor +import com.vanced.manager.ui.components.layout.ManagerScrollableColumn +import com.vanced.manager.ui.components.layout.ScrollableItemRow +import com.vanced.manager.ui.utils.defaultContentPaddingVertical import com.vanced.manager.ui.viewmodel.HomeViewModel +import com.vanced.manager.ui.widgets.home.apps.card.AppCard +import com.vanced.manager.ui.widgets.layout.CategoryLayout import com.vanced.manager.util.socialMedia import com.vanced.manager.util.sponsors import org.koin.androidx.compose.getViewModel -@ExperimentalAnimationApi @Composable @Preview fun HomeLayout() { @@ -41,39 +44,38 @@ fun HomeLayout() { ) } ) { - ManagerScrollableColumn { - HomeHeaderView(headerName = "Apps") { - viewModel.apps.fastForEachIndexed { index, app -> - val rememberedApp by app.observeAsState(initial = App()) - AppCard(rememberedApp) - if (index != viewModel.apps.size - 1) { - Spacer(modifier = Modifier.size(height = 8.dp, width = 0.dp)) + ManagerScrollableColumn( + contentPaddingVertical = defaultContentPaddingVertical, + itemSpacing = 18.dp + ) { + CategoryLayout( + categoryNameId = R.string.home_category_apps, + contentPaddingHorizontal = 0.dp + ) { + Column( + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + viewModel.apps.fastForEach { app -> + val observedApp by app.observeAsState(initial = App()) + AppCard(observedApp, isFetching) } } } - ManagerCardSeparator() - HomeHeaderView( - modifier = Modifier.fillMaxWidth(), - headerName = "Support Us" - ) { - ScrollableLinkRow(items = sponsors) { sponsor -> - LinkCard( - icon = R.drawable.ic_android_black_24dp, + CategoryLayout(categoryNameId = R.string.home_category_support_us) { + ScrollableItemRow(items = sponsors) { sponsor -> + ManagerLinkCard( + icon = sponsor.icon, title = sponsor.title, - link = "https://m.youtube.com" + link = sponsor.link ) } } - ManagerCardSeparator() - HomeHeaderView( - modifier = Modifier.fillMaxWidth(), - headerName = "Social media" - ) { - ScrollableLinkRow(items = socialMedia) { socialMedia -> - LinkCard( - icon = R.drawable.ic_android_black_24dp, + CategoryLayout(categoryNameId = R.string.home_category_social_media) { + ScrollableItemRow(items = socialMedia) { socialMedia -> + ManagerLinkCard( + icon = socialMedia.icon, title = socialMedia.title, - link = "https://m.youtube.com" + link = socialMedia.link ) } } diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt index 5cd985b629..fbb8483aa6 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt @@ -10,9 +10,9 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Share import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import com.vanced.manager.ui.composables.ManagerLazyColumn -import com.vanced.manager.ui.composables.managerAccentColor -import com.vanced.manager.ui.composables.managerSurfaceColor +import com.vanced.manager.ui.components.color.managerAccentColor +import com.vanced.manager.ui.components.color.managerSurfaceColor +import com.vanced.manager.ui.components.layout.ManagerLazyColumn import com.vanced.manager.util.logs @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt index ac6ad0d636..cd89268af2 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt @@ -1,13 +1,23 @@ package com.vanced.manager.ui.layouts -import androidx.compose.foundation.layout.* -import androidx.compose.material.* +import androidx.compose.foundation.layout.Column import androidx.compose.runtime.* -import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.composables.* +import androidx.datastore.preferences.core.booleanPreferencesKey +import com.vanced.manager.R +import com.vanced.manager.ui.components.* +import com.vanced.manager.ui.components.layout.ManagerScrollableColumn +import com.vanced.manager.ui.components.preference.CheckboxPreference +import com.vanced.manager.ui.components.preference.Preference +import com.vanced.manager.ui.components.preference.RadiobuttonDialogPreference import com.vanced.manager.ui.preferences.RadioButtonPreference -import com.vanced.manager.ui.theme.managerTheme +import com.vanced.manager.ui.preferences.holder.managerVariantPref +import com.vanced.manager.ui.preferences.holder.useCustomTabsPref +import com.vanced.manager.ui.preferences.managerBooleanPreference +import com.vanced.manager.ui.utils.defaultContentPaddingVertical +import com.vanced.manager.ui.widgets.layout.CategoryLayout +import com.vanced.manager.ui.widgets.settings.SettingsAccentColorItem +import com.vanced.manager.ui.widgets.settings.ThemeSettingsItem data class NotificationPrefModel( val app: String, @@ -29,89 +39,66 @@ private val notificationApps = arrayOf( ) ) -@ExperimentalStdlibApi -@ExperimentalMaterialApi @Composable fun SettingsLayout() { - var showDialog by remember { mutableStateOf(false) } - ManagerScrollableColumn { - HeaderCard(headerName = "Behaviour") { - SwitchPreference( - preferenceTitle = "Use Custom Tabs", - preferenceDescription = "Links will open in chrome custom tabs", - preferenceKey = "use_custom_tabs" - ) - notificationApps.forEach { - with (it) { - SwitchPreference( - preferenceTitle = "$app Push Notifications", - preferenceDescription = "Receive push notifications when an update for $app is released", - preferenceKey = "${prefKey}_notifications" - ) - } - } - Preference( - preferenceTitle = "Variant", - preferenceDescription = "nonroot", - onClick = {} - ) - Preference( - preferenceTitle = "Clear downloaded files", - onClick = {} - ) - } - Spacer(modifier = Modifier.size(12.dp)) - HeaderCard(headerName = "Appearance") { - Preference( - preferenceTitle = "Accent Color", - onClick = { - showDialog = true + ManagerScrollableColumn( + contentPaddingVertical = defaultContentPaddingVertical, + itemSpacing = 12.dp + ) { + CategoryLayout( + categoryNameId = R.string.settings_category_behaviour, + contentPaddingHorizontal = 0.dp, + categoryNameSpacing = 4.dp + ) { + Column { + CheckboxPreference( + preferenceTitle = R.string.settings_preference_use_custom_tabs_title, + preferenceDescription = R.string.settings_preference_use_custom_tabs_summary, + preference = useCustomTabsPref + ) + notificationApps.forEach { + with(it) { + CheckboxPreference( + preferenceTitle = "$app Push Notifications", + preferenceDescription = "Receive push notifications when an update for $app is released", + preference = managerBooleanPreference( + key = booleanPreferencesKey("${prefKey}_notifications"), + defaultValue = true + ) + ) + } } - ) - DialogRadioButtonPreference( - preferenceTitle = "Theme", - preferenceKey = "manager_theme", - defaultValue = "Light", - buttons = listOf( - RadioButtonPreference( - title = "Light Theme", - preferenceValue = "Light" - ), - RadioButtonPreference( - title = "Dark Theme", - preferenceValue = "Dark" - ), - RadioButtonPreference( - title = "System Default", - preferenceValue = "System Default" + RadiobuttonDialogPreference( + preferenceTitle = R.string.settings_preference_variant_title, + preference = managerVariantPref, + buttons = listOf( + RadioButtonPreference( + title = "nonroot", + key = "nonroot" + ), + RadioButtonPreference( + title = "root", + key = "root" + ), ) ) - ) { - managerTheme = it + Preference( + preferenceTitleId = R.string.settings_preference_clear_files_title, + preferenceDescriptionId = null, + onClick = {} + ) + } + } + CategoryLayout( + categoryNameId = R.string.settings_category_appearance, + contentPaddingHorizontal = 0.dp, + categoryNameSpacing = 4.dp + ) { + Column { + SettingsAccentColorItem() + ThemeSettingsItem() } } - } - if (showDialog) { - AlertDialog( - onDismissRequest = { showDialog = false }, - text = { - HSLColorPicker() -// AndroidView( -// factory = { -// HSLColorPicker(it) -// }, -// update = { view -> -// view.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 800) -// view.setColorSelectionListener(object : SimpleColorSelectionListener() { -// override fun onColorSelected(color: Int) { -// accentColorInt = color -// } -// }) -// } -// ) - }, - buttons = {} - ) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/CheckboxPreference.kt b/app/src/main/java/com/vanced/manager/ui/preferences/CheckboxPreference.kt new file mode 100644 index 0000000000..630c3342d6 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/preferences/CheckboxPreference.kt @@ -0,0 +1,6 @@ +package com.vanced.manager.ui.preferences + +data class CheckboxPreference( + val title: String, + val key: String, +) diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/ManagerPreference.kt b/app/src/main/java/com/vanced/manager/ui/preferences/ManagerPreference.kt new file mode 100644 index 0000000000..98c6bb9347 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/preferences/ManagerPreference.kt @@ -0,0 +1,69 @@ +package com.vanced.manager.ui.preferences + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.State +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.edit +import kotlinx.coroutines.flow.map +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject +import kotlin.reflect.KProperty + +class ManagerPreference( + val key: Preferences.Key, + val defaultValue: T, +) : KoinComponent { + + private val dataStore: DataStore by inject() + + private val _value = mutableStateOf(defaultValue) + val value: State = _value + + @Composable + fun rememberValue() = remember { value } + + operator fun getValue(thisRef: Any?, property: KProperty<*>) = value.value + + suspend fun save(newValue: T) { + _value.value = newValue + dataStore.edit { + it[key] = value.value + } + } + + //It's Chewsday innit - © Bri'ish ppl + init { + dataStore.data.map { + _value.value = it[key] ?: defaultValue + } + } + +} + +fun managerStringPreference( + key: Preferences.Key, + defaultValue: String = "" +) = ManagerPreference(key, defaultValue) + +fun managerStringSetPreference( + key: Preferences.Key>, + defaultValue: Set = setOf() +) = ManagerPreference(key, defaultValue) + +fun managerBooleanPreference( + key: Preferences.Key, + defaultValue: Boolean = false +) = ManagerPreference(key, defaultValue) + +fun managerIntPreference( + key: Preferences.Key, + defaultValue: Int = 0 +) = ManagerPreference(key, defaultValue) + +fun managerLongPreference( + key: Preferences.Key, + defaultValue: Long = 0 +) = ManagerPreference(key, defaultValue) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/RadioButtonPreference.kt b/app/src/main/java/com/vanced/manager/ui/preferences/RadioButtonPreference.kt index 7ab5325d66..ab797fbc3e 100644 --- a/app/src/main/java/com/vanced/manager/ui/preferences/RadioButtonPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/preferences/RadioButtonPreference.kt @@ -2,5 +2,5 @@ package com.vanced.manager.ui.preferences data class RadioButtonPreference( val title: String, - val preferenceValue: String + val key: String ) diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceDefaultValueHolder.kt b/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceDefaultValueHolder.kt new file mode 100644 index 0000000000..ef48dd0d54 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceDefaultValueHolder.kt @@ -0,0 +1,6 @@ +package com.vanced.manager.ui.preferences.holder + +const val MANAGER_VARIANT_DEFAULT_VALUE = "nonroot" + +const val VANCED_ENABLED_DEFAULT_VALUE = true +const val MUSIC_ENABLED_DEFAULT_VALUE = true \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceHolder.kt b/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceHolder.kt new file mode 100644 index 0000000000..960a465d56 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceHolder.kt @@ -0,0 +1,23 @@ +package com.vanced.manager.ui.preferences.holder + +import com.vanced.manager.ui.preferences.managerBooleanPreference +import com.vanced.manager.ui.preferences.managerLongPreference +import com.vanced.manager.ui.preferences.managerStringPreference +import com.vanced.manager.ui.preferences.managerStringSetPreference +import com.vanced.manager.ui.theme.defAccentColor + +val useCustomTabsPref = managerBooleanPreference(useCustomTabsKey) + +val managerVariantPref = managerStringPreference(managerVariantKey, MANAGER_VARIANT_DEFAULT_VALUE) + +val managerThemePref = managerStringPreference(managerThemeKey, "System Default") +val managerAccentColorPref = managerLongPreference(managerAccentColorKey, defAccentColor) + +val vancedThemePref = managerStringPreference(vancedThemeKey, "Dark") +val vancedVersionPref = managerStringPreference(vancedVersionKey, "latest") +val vancedLanguagesPref = managerStringSetPreference(vancedLanguageKey, setOf("en")) + +val musicVersionPref = managerStringPreference(musicVersionKey, "latest") + +val vancedEnabled = managerBooleanPreference(vancedEnabledKey, VANCED_ENABLED_DEFAULT_VALUE) +val musicEnabled = managerBooleanPreference(musicEnabledKey, MUSIC_ENABLED_DEFAULT_VALUE) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceKeyHolder.kt b/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceKeyHolder.kt new file mode 100644 index 0000000000..ac8ddda5d4 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceKeyHolder.kt @@ -0,0 +1,19 @@ +package com.vanced.manager.ui.preferences.holder + +import androidx.datastore.preferences.core.booleanPreferencesKey +import androidx.datastore.preferences.core.longPreferencesKey +import androidx.datastore.preferences.core.stringPreferencesKey +import androidx.datastore.preferences.core.stringSetPreferencesKey + +val useCustomTabsKey = booleanPreferencesKey(USE_CUSTOM_TABS_KEY) +val managerVariantKey = stringPreferencesKey(MANAGER_VARIANT_KEY) +val managerThemeKey = stringPreferencesKey("manager_theme") +val managerAccentColorKey = longPreferencesKey("manager_accent_color") + +val vancedThemeKey = stringPreferencesKey(APP_VANCED_THEME_KEY) +val vancedVersionKey = stringPreferencesKey(APP_VANCED_VERSION_KEY) +val vancedLanguageKey = stringSetPreferencesKey(APP_VANCED_LANGUAGE_KEY) +val musicVersionKey = stringPreferencesKey(APP_MUSIC_VERSION_KEY) + +val vancedEnabledKey = booleanPreferencesKey(VANCED_ENABLED_KEY) +val musicEnabledKey = booleanPreferencesKey(MUSIC_ENABLED_KEY) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceKeyNameHolder.kt b/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceKeyNameHolder.kt new file mode 100644 index 0000000000..d87ad826d8 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceKeyNameHolder.kt @@ -0,0 +1,13 @@ +package com.vanced.manager.ui.preferences.holder + +const val USE_CUSTOM_TABS_KEY = "use_custom_tabs" +const val MANAGER_VARIANT_KEY = "manager_variant" + +const val APP_VANCED_THEME_KEY = "app_vanced_theme" +const val APP_VANCED_VERSION_KEY = "app_vanced_version" +const val APP_VANCED_LANGUAGE_KEY = "app_vanced_language" + +const val APP_MUSIC_VERSION_KEY = "app_music_version" + +const val VANCED_ENABLED_KEY = "manager_vanced_enabled" +const val MUSIC_ENABLED_KEY = "manager_music_enabled" \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/screens/Screen.kt b/app/src/main/java/com/vanced/manager/ui/screens/Screen.kt index 8bb151c9c8..0b6bfbd6ca 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/Screen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/Screen.kt @@ -1,8 +1,48 @@ package com.vanced.manager.ui.screens -sealed class Screen(val route: String, val displayName: String) { - object Home : Screen("home", "Manager") - object Settings : Screen("settings", "Settings") - object About : Screen("about", "About") - object Logs : Screen("logs", "Logs") +import androidx.annotation.StringRes +import androidx.compose.runtime.Composable +import com.vanced.manager.R +import com.vanced.manager.ui.layouts.AboutLayout +import com.vanced.manager.ui.layouts.HomeLayout +import com.vanced.manager.ui.layouts.LogLayout +import com.vanced.manager.ui.layouts.SettingsLayout + +sealed class Screen( + val route: String, + @StringRes val displayName: Int, + val content: @Composable () -> Unit +) { + + object Home : Screen( + route = "home", + displayName = R.string.toolbar_home, + content = { + HomeLayout() + } + ) + + object Settings : Screen( + route = "settings", + displayName = R.string.toolbar_settings, + content = { + SettingsLayout() + } + ) + + object About : Screen( + route = "about", + displayName = R.string.toolbar_about, + content = { + AboutLayout() + } + ) + + object Logs : Screen( + route = "logs", + displayName = R.string.toolbar_logs, + content = { + LogLayout() + } + ) } diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Shape.kt b/app/src/main/java/com/vanced/manager/ui/theme/Shape.kt index 2cfab954dd..82c29e3961 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Shape.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Shape.kt @@ -5,7 +5,7 @@ import androidx.compose.material.Shapes import androidx.compose.ui.unit.dp val shapes = Shapes( - small = RoundedCornerShape(4.dp), - medium = RoundedCornerShape(4.dp), - large = RoundedCornerShape(0.dp) + small = RoundedCornerShape(8.dp), + medium = RoundedCornerShape(12.dp), + large = RoundedCornerShape(8.dp) ) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt index 70b25b9c13..f9b2f315ad 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt @@ -6,12 +6,11 @@ import androidx.compose.material.MaterialTheme import androidx.compose.material.darkColors import androidx.compose.material.lightColors import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue import androidx.compose.ui.graphics.Color +import com.vanced.manager.ui.preferences.holder.managerAccentColorPref +import com.vanced.manager.ui.preferences.holder.managerThemePref -var managerTheme by mutableStateOf("") +const val defAccentColor = 0xFF0477E1 private val DarkColorPalette = darkColors( primary = purple200, @@ -28,10 +27,10 @@ private val LightColorPalette = lightColors( val Colors.cardColor: Color get() = if (isLight) Color(0xFFF7F7F7) else Color(0xFF191919) -val Colors.managerAccentColor: Color get() = Color(0xFF2E73FF) +val Colors.managerAccentColor: Color get() = Color(managerAccentColorPref.value.value) @Composable -fun isDark(): Boolean = when (managerTheme) { +fun isDark(): Boolean = when (managerThemePref.value.value) { "Dark" -> true "Light" -> false "System Default" -> isSystemInDarkTheme() @@ -39,7 +38,7 @@ fun isDark(): Boolean = when (managerTheme) { } @Composable -fun ComposeTestTheme( +fun ManagerTheme( content: @Composable () -> Unit ) { val colors = if (isDark()) DarkColorPalette else LightColorPalette diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Type.kt b/app/src/main/java/com/vanced/manager/ui/theme/Type.kt index 42a97096a0..b271cc387a 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Type.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Type.kt @@ -2,27 +2,53 @@ package com.vanced.manager.ui.theme import androidx.compose.material.Typography import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.sp +import com.vanced.manager.R + +private val light = Font(R.font.inter_light, FontWeight.Light) +private val regular = Font(R.font.inter_regular, FontWeight.Normal) +private val medium = Font(R.font.inter_medium, FontWeight.Medium) +private val semibold = Font(R.font.inter_semibold, FontWeight.SemiBold) +private val bold = Font(R.font.inter_bold, FontWeight.Bold) + +private val interFontFamily = FontFamily(light, regular, medium, semibold, bold) // Set of Material typography styles to start with val typography = Typography( + defaultFontFamily = interFontFamily, + h1 = TextStyle( + fontSize = 24.sp, + fontWeight = FontWeight.Bold, + ), + h2 = TextStyle( + fontSize = 20.sp, + fontWeight = FontWeight.SemiBold + ), + h5 = TextStyle( + fontSize = 16.sp, + fontWeight = FontWeight.SemiBold, + ), + h6 = TextStyle( + fontSize = 14.sp, + fontWeight = FontWeight.Bold + ), body1 = TextStyle( - fontFamily = FontFamily.Default, + fontWeight = FontWeight.Medium, + fontSize = 12.sp + ), + body2 = TextStyle( fontWeight = FontWeight.Normal, - fontSize = 16.sp - ) - /* Other default text styles to override - button = TextStyle( - fontFamily = FontFamily.Default, - fontWeight = FontWeight.W500, - fontSize = 14.sp + fontSize = 10.sp, ), - caption = TextStyle( - fontFamily = FontFamily.Default, + subtitle1 = TextStyle( fontWeight = FontWeight.Normal, - fontSize = 12.sp + fontSize = 12.sp, + ), + button = TextStyle( + fontSize = 14.sp, + fontWeight = FontWeight.Medium ) - */ ) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/utils/Const.kt b/app/src/main/java/com/vanced/manager/ui/utils/Const.kt new file mode 100644 index 0000000000..75cd4d68b0 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/utils/Const.kt @@ -0,0 +1,6 @@ +package com.vanced.manager.ui.utils + +import androidx.compose.ui.unit.dp + +val defaultContentPaddingHorizontal = 16.dp +val defaultContentPaddingVertical = 12.dp \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt index c1a6c1c4be..1d5b9885a8 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt @@ -7,9 +7,11 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import androidx.preference.PreferenceManager.getDefaultSharedPreferences import com.vanced.manager.domain.model.App import com.vanced.manager.repository.JsonRepository +import com.vanced.manager.ui.preferences.holder.managerVariantPref +import com.vanced.manager.ui.preferences.holder.musicEnabled +import com.vanced.manager.ui.preferences.holder.vancedEnabled import kotlinx.coroutines.launch class HomeViewModel( @@ -45,26 +47,10 @@ class HomeViewModel( } init { - - - val prefs = getDefaultSharedPreferences(context) - val variant = prefs.getString("manager_variant", "nonroot") - val vancedEnabled = prefs.getBoolean("manager_vanced_enabled", true) - val musicEnabled = prefs.getBoolean("manager_music_enabled", true) - apps.apply { - if (vancedEnabled) { - add(vanced) - } - - if (musicEnabled) { - add(music) - } - - if (variant == "nonroot") { - add(microg) - } - + if (vancedEnabled.value.value) add(vanced) + if (musicEnabled.value.value) add(music) + if (managerVariantPref.value.value == "nonroot") add(microg) } fetch() diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt new file mode 100644 index 0000000000..8b6c5a9a87 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt @@ -0,0 +1,72 @@ +package com.vanced.manager.ui.widgets.home.apps.card + +import androidx.compose.foundation.layout.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Info +import androidx.compose.material.icons.rounded.DeleteForever +import androidx.compose.material.icons.rounded.Download +import androidx.compose.material.icons.rounded.Launch +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.vanced.manager.R +import com.vanced.manager.ui.components.button.IconButton +import com.vanced.manager.ui.components.color.ThemedCardContentColorProvider +import com.vanced.manager.ui.components.text.ManagerText +import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal +import com.vanced.manager.ui.widgets.text.AppVersionText + +@Composable +fun AppActionCard( + appRemoteVersion: String?, + appInstalledVersion: String?, + showDownloadDialog: MutableState, + showAppInfo: MutableState, + showInstallationOptions: MutableState, + hasInstallationOptions: Boolean +) { + ThemedCardContentColorProvider { + Row( + modifier = Modifier.padding(horizontal = defaultContentPaddingHorizontal, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier + .weight(1f) + .wrapContentWidth(Alignment.Start), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + ManagerText(stringId = R.string.app_versions) + AppVersionText( + stringId = R.string.app_version_latest, + version = appRemoteVersion + ) + AppVersionText( + stringId = R.string.app_version_installed, + version = appInstalledVersion + ) + } + Row( + modifier = Modifier + .weight(1f) + .padding(start = 4.dp) + .wrapContentWidth(Alignment.End) + ) { + IconButton(icon = Icons.Outlined.Info, contentDescription = "App Info") { + showAppInfo.value = true + } + IconButton(icon = Icons.Rounded.DeleteForever, contentDescription = "Uninstall") {} + IconButton(icon = Icons.Rounded.Launch, contentDescription = "Launch") {} + IconButton(icon = Icons.Rounded.Download, contentDescription = "Install") { + if (hasInstallationOptions) { + showInstallationOptions.value = true + } else { + showDownloadDialog.value = true + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt new file mode 100644 index 0000000000..0e8cea4840 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt @@ -0,0 +1,81 @@ +package com.vanced.manager.ui.widgets.home.apps.card + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import com.google.accompanist.glide.rememberGlidePainter +import com.vanced.manager.domain.model.App +import com.vanced.manager.ui.components.button.ManagerThemedButton +import com.vanced.manager.ui.components.card.ManagerThemedCard +import com.vanced.manager.ui.widgets.home.apps.dialog.AppChangelogDialog +import com.vanced.manager.ui.widgets.home.apps.dialog.AppDownloadDialog + +@OptIn(ExperimentalAnimationApi::class) +@Composable +fun AppCard( + app: App, + fetching: Boolean +) { + val showDownloadDialog = remember { mutableStateOf(false) } + val showAppInfo = remember { mutableStateOf(false) } + val showInstallationOptions = remember { mutableStateOf(false) } + val icon = rememberGlidePainter( + request = app.iconUrl ?: "", + fadeIn = true + ) + val hasInstallationOption = app.installationOptions != null + + ManagerThemedCard { + Column { + AppInfoCard( + appName = app.name ?: "", + icon = icon, + fetching = fetching + ) + AppActionCard( + appInstalledVersion = app.installedVersion, + appRemoteVersion = app.remoteVersion, + showDownloadDialog = showDownloadDialog, + showAppInfo = showAppInfo, + showInstallationOptions = showInstallationOptions, + hasInstallationOptions = hasInstallationOption + ) + if (hasInstallationOption) { + AnimatedVisibility( + modifier = Modifier.fillMaxWidth(), + visible = showInstallationOptions.value + ) { + app.installationOptions?.forEach { + it.item() + } + ManagerThemedButton(onClick = { + showDownloadDialog.value = true + }) { + + } + } + } + } + } + + if (app.name != null && app.downloader != null) { + AppDownloadDialog( + app = app.name, + downloader = app.downloader, + showDialog = showDownloadDialog + ) + } + + if (app.name != null && app.changelog != null) { + AppChangelogDialog( + appName = app.name, + changelog = app.changelog, + showDialog = showAppInfo + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppInfoCard.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppInfoCard.kt new file mode 100644 index 0000000000..eb757ae559 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppInfoCard.kt @@ -0,0 +1,48 @@ +package com.vanced.manager.ui.widgets.home.apps.card + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.google.accompanist.imageloading.ImageLoadState +import com.google.accompanist.imageloading.LoadPainter +import com.vanced.manager.ui.components.card.ManagerCard +import com.vanced.manager.ui.components.list.ManagerListItem +import com.vanced.manager.ui.components.placeholder.managerPlaceholder +import com.vanced.manager.ui.components.text.ManagerText +import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal + +@Composable +fun AppInfoCard( + appName: String, + icon: LoadPainter, + fetching: Boolean +) { + ManagerCard { + ManagerListItem( + modifier = Modifier.padding( + horizontal = defaultContentPaddingHorizontal, + vertical = 12.dp + ), + title = { + ManagerText( + modifier = Modifier.managerPlaceholder(fetching), + text = appName, + textStyle = MaterialTheme.typography.h5 + ) + }, + icon = { + Image( + painter = icon, + contentDescription = "", + modifier = Modifier + .size(48.dp, 48.dp) + .managerPlaceholder(icon.loadState is ImageLoadState.Loading) + ) + } + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppChangelogDialog.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppChangelogDialog.kt new file mode 100644 index 0000000000..5836b88995 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppChangelogDialog.kt @@ -0,0 +1,42 @@ +package com.vanced.manager.ui.widgets.home.apps.dialog + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.vanced.manager.R +import com.vanced.manager.ui.components.button.ManagerThemedTextButton +import com.vanced.manager.ui.components.dialog.ManagerDialog +import com.vanced.manager.ui.components.lifecycle.managerString +import com.vanced.manager.ui.components.text.ManagerText + +@Composable +fun AppChangelogDialog( + appName: String, + changelog: String, + showDialog: MutableState +) { + if (showDialog.value) { + ManagerDialog( + title = managerString(R.string.app_info_title, appName), + onDismissRequest = { showDialog.value = false }, + buttons = { + ManagerThemedTextButton( + modifier = Modifier.fillMaxWidth(), + stringId = R.string.dialog_button_close + ) { + showDialog.value = false + } + } + ) { + ManagerText( + modifier = Modifier.padding(top = 4.dp), + text = changelog, + textStyle = MaterialTheme.typography.subtitle1 + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppDownloadDialog.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppDownloadDialog.kt new file mode 100644 index 0000000000..905e9f91e9 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppDownloadDialog.kt @@ -0,0 +1,53 @@ +package com.vanced.manager.ui.widgets.home.apps.dialog + +import androidx.compose.runtime.* +import com.vanced.manager.downloader.base.BaseDownloader +import com.vanced.manager.ui.components.dialog.ManagerDialog +import com.vanced.manager.ui.widgets.home.download.AppDownloadDialogButtons +import com.vanced.manager.ui.widgets.home.download.AppDownloadDialogProgress +import kotlinx.coroutines.launch + +@Composable +fun AppDownloadDialog( + app: String, + downloader: BaseDownloader, + showDialog: MutableState +) { + val coroutineScope = rememberCoroutineScope() + + val rememberProgress = remember { downloader.downloadProgress } + val rememberFile = remember { downloader.downloadFile } + val rememberInstalling = remember { downloader.installing } + + val showProgress = remember { mutableStateOf(false) } + + if (showDialog.value) { + ManagerDialog( + title = app, + onDismissRequest = { showDialog.value = false }, + buttons = { + AppDownloadDialogButtons( + showProgress = showProgress, + onDownloadClick = { + coroutineScope.launch { + showProgress.value = true + downloader.download() + } + }, + onCancelClick = { + downloader.cancelDownload() + showDialog.value = false + showProgress.value = false + } + ) + } + ) { + AppDownloadDialogProgress( + progress = rememberProgress, + file = rememberFile, + showProgress = showProgress.value, + installing = rememberInstalling + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogButtons.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogButtons.kt new file mode 100644 index 0000000000..9ea86aa2a0 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogButtons.kt @@ -0,0 +1,28 @@ +package com.vanced.manager.ui.widgets.home.download + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.ui.Modifier +import com.vanced.manager.R +import com.vanced.manager.ui.components.button.ManagerThemedTextButton + +@Composable +fun AppDownloadDialogButtons( + showProgress: MutableState, + onDownloadClick: () -> Unit, + onCancelClick: () -> Unit, +) { + when (showProgress.value) { + true -> ManagerThemedTextButton( + stringId = R.string.dialog_button_cancel, + modifier = Modifier.fillMaxWidth(), + onClick = onCancelClick + ) + false -> ManagerThemedTextButton( + stringId = R.string.app_download_dialog_confirm, + modifier = Modifier.fillMaxWidth(), + onClick = onDownloadClick + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt new file mode 100644 index 0000000000..9618c154b8 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt @@ -0,0 +1,42 @@ +package com.vanced.manager.ui.widgets.home.download + +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.material.LinearProgressIndicator +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import com.vanced.manager.ui.components.color.managerAccentColor + +@Composable +fun AppDownloadDialogProgress( + progress: Float, + file: String, + showProgress: Boolean, + installing: Boolean +) { + if (showProgress) { + when (installing) { + true -> LinearProgressIndicator(color = managerAccentColor()) + false -> LinearProgressIndicator( + progress = progress, + color = managerAccentColor() + ) + } + Row { + Text( + modifier = Modifier + .weight(1f) + .wrapContentWidth(Alignment.Start), + text = "Downloading $file" + ) + Text( + modifier = Modifier + .weight(1f) + .wrapContentWidth(Alignment.End), + text = "$progress" + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/CheckboxInstallationOption.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/CheckboxInstallationOption.kt new file mode 100644 index 0000000000..f3c7e80c93 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/CheckboxInstallationOption.kt @@ -0,0 +1,20 @@ +package com.vanced.manager.ui.widgets.home.installation + +import androidx.annotation.StringRes +import com.vanced.manager.ui.components.preference.CheckboxDialogPreference +import com.vanced.manager.ui.preferences.CheckboxPreference +import com.vanced.manager.ui.preferences.ManagerPreference + +data class CheckboxInstallationOption( + @StringRes val title: Int, + val preference: ManagerPreference>, + val buttons: List +) : InstallationOption( + item = { + CheckboxDialogPreference( + preferenceTitle = title, + preference = preference, + buttons = buttons + ) + } +) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/InstallationOption.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/InstallationOption.kt new file mode 100644 index 0000000000..5c3601ffe2 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/InstallationOption.kt @@ -0,0 +1,7 @@ +package com.vanced.manager.ui.widgets.home.installation + +import androidx.compose.runtime.Composable + +open class InstallationOption( + val item: @Composable () -> Unit +) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/RadiobuttonInstallationOption.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/RadiobuttonInstallationOption.kt new file mode 100644 index 0000000000..ceb4260bac --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/RadiobuttonInstallationOption.kt @@ -0,0 +1,20 @@ +package com.vanced.manager.ui.widgets.home.installation + +import androidx.annotation.StringRes +import com.vanced.manager.ui.components.preference.RadiobuttonDialogPreference +import com.vanced.manager.ui.preferences.ManagerPreference +import com.vanced.manager.ui.preferences.RadioButtonPreference + +data class RadiobuttonInstallationOption( + @StringRes val title: Int, + val preference: ManagerPreference, + val buttons: List +) : InstallationOption( + item = { + RadiobuttonDialogPreference( + preferenceTitle = title, + preference = preference, + buttons = buttons + ) + } +) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/layout/CategoryLayout.kt b/app/src/main/java/com/vanced/manager/ui/widgets/layout/CategoryLayout.kt new file mode 100644 index 0000000000..7fd31d4f77 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/layout/CategoryLayout.kt @@ -0,0 +1,30 @@ +package com.vanced.manager.ui.widgets.layout + +import androidx.annotation.StringRes +import androidx.compose.foundation.layout.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.Dp +import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal +import com.vanced.manager.ui.utils.defaultContentPaddingVertical +import com.vanced.manager.ui.widgets.text.CategoryTitleText + +@Composable +fun CategoryLayout( + @StringRes categoryNameId: Int, + contentPaddingHorizontal: Dp = defaultContentPaddingHorizontal, + categoryNameSpacing: Dp = defaultContentPaddingVertical, + content: @Composable () -> Unit, +) { + Column( + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(categoryNameSpacing), + ) { + CategoryTitleText(stringId = categoryNameId) + Box( + modifier = Modifier.padding(horizontal = contentPaddingHorizontal) + ) { + content() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/settings/AccentColorItem.kt b/app/src/main/java/com/vanced/manager/ui/widgets/settings/AccentColorItem.kt new file mode 100644 index 0000000000..3319daecfc --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/settings/AccentColorItem.kt @@ -0,0 +1,23 @@ +package com.vanced.manager.ui.widgets.settings + +import androidx.compose.runtime.* +import com.vanced.manager.R +import com.vanced.manager.ui.components.color.ManagerColorPicker +import com.vanced.manager.ui.components.preference.DialogPreference +import com.vanced.manager.ui.preferences.holder.managerAccentColorPref + +@Composable +fun SettingsAccentColorItem() { + var localAccentColor by remember { mutableStateOf(managerAccentColorPref.value.value) } + DialogPreference( + preferenceTitleId = R.string.settings_preference_accent_color_title, + preferenceDescription = localAccentColor.toString(), + buttons = { + + } + ) { + ManagerColorPicker { + localAccentColor = it + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/settings/ThemeItem.kt b/app/src/main/java/com/vanced/manager/ui/widgets/settings/ThemeItem.kt new file mode 100644 index 0000000000..3ede43286d --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/settings/ThemeItem.kt @@ -0,0 +1,29 @@ +package com.vanced.manager.ui.widgets.settings + +import androidx.compose.runtime.Composable +import com.vanced.manager.R +import com.vanced.manager.ui.components.preference.RadiobuttonDialogPreference +import com.vanced.manager.ui.preferences.RadioButtonPreference +import com.vanced.manager.ui.preferences.holder.managerThemePref + +@Composable +fun ThemeSettingsItem() { + RadiobuttonDialogPreference( + preferenceTitle = R.string.settings_preference_theme_title, + preference = managerThemePref, + buttons = listOf( + RadioButtonPreference( + title = "Light Theme", + key = "Light" + ), + RadioButtonPreference( + title = "Dark Theme", + key = "Dark" + ), + RadioButtonPreference( + title = "System Default", + key = "System Default" + ) + ) + ) +} diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/text/AppVersionText.kt b/app/src/main/java/com/vanced/manager/ui/widgets/text/AppVersionText.kt new file mode 100644 index 0000000000..112b52f4c3 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/text/AppVersionText.kt @@ -0,0 +1,20 @@ +package com.vanced.manager.ui.widgets.text + +import androidx.annotation.StringRes +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import com.vanced.manager.R +import com.vanced.manager.ui.components.lifecycle.managerString +import com.vanced.manager.ui.components.text.ManagerText + +@Composable +fun AppVersionText( + @StringRes stringId: Int, + version: String? +) { + ManagerText( + version ?: managerString(stringId = R.string.app_content_unavailable), + stringId = stringId, + textStyle = MaterialTheme.typography.body2, + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/text/CategoryTitleText.kt b/app/src/main/java/com/vanced/manager/ui/widgets/text/CategoryTitleText.kt new file mode 100644 index 0000000000..17a895ba3c --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/text/CategoryTitleText.kt @@ -0,0 +1,20 @@ +package com.vanced.manager.ui.widgets.text + +import androidx.annotation.StringRes +import androidx.compose.foundation.layout.padding +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.vanced.manager.ui.components.text.ManagerText +import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal + +@Composable +fun CategoryTitleText( + @StringRes stringId: Int +) { + ManagerText( + modifier = Modifier.padding(start = defaultContentPaddingHorizontal), + stringId = stringId, + textStyle = MaterialTheme.typography.h2 + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/text/ToolbarTitleText.kt b/app/src/main/java/com/vanced/manager/ui/widgets/text/ToolbarTitleText.kt new file mode 100644 index 0000000000..e196ef0fe9 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/text/ToolbarTitleText.kt @@ -0,0 +1,15 @@ +package com.vanced.manager.ui.widgets.text + +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import com.vanced.manager.ui.components.text.ManagerText + +@Composable +fun ToolbarTitleText( + stringId: Int? +) { + ManagerText( + stringId = stringId, + textStyle = MaterialTheme.typography.h1 + ) +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_adguard.xml b/app/src/main/res/drawable/ic_adguard.xml index ab9063622d..f22d9c6d59 100644 --- a/app/src/main/res/drawable/ic_adguard.xml +++ b/app/src/main/res/drawable/ic_adguard.xml @@ -1,16 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> - + android:fillColor="#FF000000" + android:pathData="M11.7,2.1c3.6,0.1 6.7,0.7 9.7,2.1c0.3,0.1 0.4,0.3 0.4,0.6c0,3.2 -0.5,6.3 -1.9,9.2c-1.7,3.4 -4.3,6 -7.5,7.9c-0.1,0.1 -0.3,0.1 -0.4,0c-4.8,-3 -8.1,-7.1 -9.1,-12.7c-0.3,-1.5 -0.2,-3 -0.4,-4.5c0,-0.3 0.1,-0.4 0.3,-0.5c2,-1 4.2,-1.6 6.4,-1.9C10.1,2.2 11.1,2.1 11.7,2.1zM7.6,10.5c1.4,1.7 2.8,3.3 4.2,5c2,-2.7 3.9,-5.3 5.8,-7.9c-0.5,-0.3 -0.7,-0.2 -1.2,0.2c-1.5,1.6 -3,3.1 -4.4,4.7c-0.1,0.1 -0.2,0.2 -0.3,0.3c-0.6,-0.7 -1.1,-1.4 -1.7,-2.1C9.3,9.8 8.4,9.8 7.6,10.5z"/> diff --git a/app/src/main/res/drawable/ic_brave.xml b/app/src/main/res/drawable/ic_brave.xml index 5f2e6ad59a..536c6d03e2 100644 --- a/app/src/main/res/drawable/ic_brave.xml +++ b/app/src/main/res/drawable/ic_brave.xml @@ -1,14 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> - + android:fillColor="#FF000000" + android:pathData="M5.4,2.7c0.3,0 0.6,0.1 1,0.1c0,0 0.1,0 0.1,0c0.6,-0.7 1.2,-1.4 1.8,-2.1c0.1,-0.1 0.2,-0.1 0.3,-0.1c2.2,0 4.4,0 6.7,0c0.3,0 0.4,0.1 0.6,0.3c0.4,0.4 0.7,0.8 1.1,1.3c0.2,0.2 0.4,0.5 0.6,0.7c0,0 0.1,0.1 0.2,0c0.5,-0.1 1,-0.2 1.5,-0.1c0.4,0.1 0.8,0.2 1.2,0.5c0.3,0.4 0.7,0.7 1,1c0.1,0.1 0.2,0.2 0.4,0.4c0.1,0.1 0.1,0.1 0,0.2c-0.2,0.4 -0.3,0.7 -0.5,1.1c0,0.1 0,0.2 0,0.3c0.2,0.6 0.4,1.1 0.6,1.7c0,0.1 0,0.2 0,0.3c-0.1,0.4 -0.2,0.9 -0.3,1.3c-0.5,1.8 -0.9,3.5 -1.4,5.3c-0.3,1 -0.5,2 -0.8,3c-0.1,0.5 -0.3,0.9 -0.6,1.3c-0.3,0.3 -0.6,0.7 -1,0.9c-0.6,0.4 -1.2,0.8 -1.8,1.2c-0.5,0.3 -1,0.7 -1.5,1c-0.5,0.3 -1,0.7 -1.5,1c-0.2,0.1 -0.4,0.2 -0.6,0.3c-0.2,0.1 -0.5,0.1 -0.7,0c-0.2,-0.1 -0.4,-0.2 -0.5,-0.3c-0.8,-0.6 -1.7,-1.1 -2.5,-1.7c-0.5,-0.3 -1,-0.6 -1.4,-1c-0.4,-0.3 -0.8,-0.6 -1.2,-0.8c-0.7,-0.5 -1.1,-1.3 -1.4,-2.2c-0.1,-0.4 -0.2,-0.8 -0.3,-1.2c-0.3,-1.2 -0.6,-2.3 -1,-3.5c-0.2,-0.7 -0.4,-1.4 -0.5,-2.1C2.6,9.9 2.4,9 2.1,8.2c0,-0.1 0,-0.2 0,-0.3c0.2,-0.6 0.4,-1.1 0.6,-1.6c0,-0.1 0,-0.2 0,-0.3C2.6,5.6 2.4,5.2 2.3,4.9c0,-0.1 0,-0.1 0,-0.2c0.5,-0.5 1,-1 1.5,-1.5c0.3,-0.3 0.6,-0.3 1,-0.4C5,2.7 5.1,2.7 5.4,2.7zM6.7,6.7C6.7,6.7 6.7,6.7 6.7,6.7C6.8,6.7 6.9,6.6 7,6.6c0.3,0 0.5,-0.1 0.8,-0.1c0.4,0 0.9,-0.1 1.3,0c0.5,0.1 1.1,0.3 1.6,0.4C11,7.1 11.1,7.2 11,7.5c-0.1,0.7 -0.3,1.4 -0.4,2.1c-0.1,0.4 -0.1,0.7 -0.2,1.1c0,0.2 0.1,0.3 0.3,0.4c0.3,0.1 0.6,0.1 1,0.2c0.2,0 0.4,0 0.5,0c0.4,-0.1 0.8,-0.1 1.1,-0.2c0.3,-0.1 0.3,-0.2 0.3,-0.4c-0.1,-0.5 -0.2,-1 -0.2,-1.5c-0.1,-0.6 -0.2,-1.2 -0.3,-1.7c0,-0.3 0,-0.4 0.3,-0.5c0.2,-0.1 0.4,-0.1 0.6,-0.2c0.6,-0.2 1.1,-0.3 1.7,-0.3c0.5,0 0.9,0.1 1.4,0.1c0.1,0 0.2,0 0.2,0.1c0,0 0,0 0,0c0,0 -0.1,0 -0.1,0.1c-1,0.4 -1.9,0.7 -2.9,1.1C14,8 13.8,8.4 13.9,8.7c0.1,0.4 0.3,0.7 0.4,1c0.2,0.3 0.4,0.6 0.5,0.9c0.1,0.3 0.1,0.4 -0.2,0.6c-0.4,0.3 -0.8,0.5 -1.2,0.8c-0.3,0.2 -0.7,0.4 -1,0.7c-0.2,0.2 -0.2,0.3 0,0.5c0.2,0.2 0.4,0.4 0.6,0.6c0.7,0.6 1.5,1 2.3,1.4c0.3,0.1 0.5,0.1 0.7,-0.1c0.3,-0.2 0.6,-0.5 0.8,-0.8c0.2,-0.4 0.3,-0.8 0.2,-1.2c-0.1,-0.3 -0.2,-0.5 -0.3,-0.8c-0.1,-0.3 -0.1,-0.6 0.2,-0.9c0.1,-0.1 0.3,-0.2 0.4,-0.4c0.7,-0.7 1.3,-1.4 2,-2.1c0.4,-0.4 0.5,-0.9 0.2,-1.4c-0.3,-0.5 -0.6,-0.9 -1,-1.4c-0.4,-0.6 -0.8,-1.1 -1.3,-1.7c-0.1,-0.1 -0.1,-0.2 -0.3,-0.2c-0.6,0.1 -1.2,0.2 -1.8,0.3c-0.4,0.1 -0.8,0.1 -1.2,0c-0.3,-0.1 -0.6,-0.2 -0.9,-0.3c-0.6,-0.2 -1.2,-0.3 -1.8,-0.1c-0.4,0.1 -0.7,0.2 -1.1,0.4C9.9,4.6 9.6,4.7 9.3,4.7C8.6,4.6 7.9,4.4 7.1,4.3c-0.1,0 -0.2,0 -0.3,0.1C6.4,4.9 6,5.4 5.6,5.9C5.2,6.5 4.9,7.1 4.5,7.6c-0.3,0.5 -0.1,1 0.2,1.3c0.5,0.6 1.1,1.1 1.6,1.7c0.3,0.3 0.6,0.6 0.8,0.9c0.2,0.2 0.3,0.5 0.2,0.8c0,0.1 -0.1,0.2 -0.1,0.3C7.1,12.8 7,13 7,13.3c-0.1,0.3 0,0.7 0.2,1c0.2,0.3 0.4,0.6 0.7,0.8c0.3,0.2 0.6,0.3 1,0.1c0.4,-0.2 0.7,-0.3 1.1,-0.5c0.7,-0.3 1.2,-0.8 1.7,-1.4c0.2,-0.3 0.2,-0.4 0,-0.6c0,0 -0.1,-0.1 -0.1,-0.1c-0.3,-0.2 -0.6,-0.4 -0.9,-0.6c-0.4,-0.3 -0.8,-0.5 -1.2,-0.8c-0.3,-0.2 -0.3,-0.3 -0.2,-0.7c0.1,-0.3 0.3,-0.6 0.5,-0.9c0.2,-0.3 0.3,-0.6 0.4,-0.9c0.1,-0.2 0.1,-0.4 -0.1,-0.6C9.9,8 9.8,7.9 9.7,7.9C8.8,7.6 8,7.2 7.1,6.9C7,6.9 6.8,6.8 6.7,6.7zM12.1,14.8c-0.1,0 -0.1,0 -0.1,0c-0.2,0.1 -0.5,0.1 -0.7,0.2c-0.7,0.3 -1.4,0.7 -2.2,1.1c-0.2,0.1 -0.2,0.3 0,0.4c0,0 0.1,0.1 0.1,0.1c0.5,0.4 1,0.7 1.5,1.1c0.4,0.3 0.8,0.6 1.2,0.9c0.3,0.2 0.4,0.2 0.6,0c0.2,-0.2 0.4,-0.3 0.6,-0.5c0.7,-0.5 1.4,-1.1 2.1,-1.6c0.3,-0.2 0.2,-0.3 0,-0.5c-0.3,-0.2 -0.6,-0.3 -0.9,-0.5c-0.5,-0.2 -1,-0.5 -1.6,-0.7C12.4,14.9 12.2,14.9 12.1,14.8z"/> diff --git a/app/src/main/res/drawable/ic_discord.xml b/app/src/main/res/drawable/ic_discord.xml index 38cec852fe..9dc3b8c15e 100644 --- a/app/src/main/res/drawable/ic_discord.xml +++ b/app/src/main/res/drawable/ic_discord.xml @@ -1,18 +1,10 @@ - - - - - + + diff --git a/app/src/main/res/drawable/ic_github.xml b/app/src/main/res/drawable/ic_github.xml index b9dc44f345..3e66680dd3 100644 --- a/app/src/main/res/drawable/ic_github.xml +++ b/app/src/main/res/drawable/ic_github.xml @@ -1,6 +1,9 @@ - - + + diff --git a/app/src/main/res/drawable/ic_instagram.xml b/app/src/main/res/drawable/ic_instagram.xml index 92de5310c8..951f6a1bdb 100644 --- a/app/src/main/res/drawable/ic_instagram.xml +++ b/app/src/main/res/drawable/ic_instagram.xml @@ -1,15 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> - - + android:fillColor="#FF000000" + android:pathData="M12,2.163c3.204,0 3.584,0.012 4.85,0.07 3.252,0.148 4.771,1.691 4.919,4.919 0.058,1.265 0.069,1.645 0.069,4.849 0,3.205 -0.012,3.584 -0.069,4.849 -0.149,3.225 -1.664,4.771 -4.919,4.919 -1.266,0.058 -1.644,0.07 -4.85,0.07 -3.204,0 -3.584,-0.012 -4.849,-0.07 -3.26,-0.149 -4.771,-1.699 -4.919,-4.92 -0.058,-1.265 -0.07,-1.644 -0.07,-4.849 0,-3.204 0.013,-3.583 0.07,-4.849 0.149,-3.227 1.664,-4.771 4.919,-4.919 1.266,-0.057 1.645,-0.069 4.849,-0.069zM12,0c-3.259,0 -3.667,0.014 -4.947,0.072 -4.358,0.2 -6.78,2.618 -6.98,6.98 -0.059,1.281 -0.073,1.689 -0.073,4.948 0,3.259 0.014,3.668 0.072,4.948 0.2,4.358 2.618,6.78 6.98,6.98 1.281,0.058 1.689,0.072 4.948,0.072 3.259,0 3.668,-0.014 4.948,-0.072 4.354,-0.2 6.782,-2.618 6.979,-6.98 0.059,-1.28 0.073,-1.689 0.073,-4.948 0,-3.259 -0.014,-3.667 -0.072,-4.947 -0.196,-4.354 -2.617,-6.78 -6.979,-6.98 -1.281,-0.059 -1.69,-0.073 -4.949,-0.073zM12,5.838c-3.403,0 -6.162,2.759 -6.162,6.162s2.759,6.163 6.162,6.163 6.162,-2.759 6.162,-6.163c0,-3.403 -2.759,-6.162 -6.162,-6.162zM12,16c-2.209,0 -4,-1.79 -4,-4 0,-2.209 1.791,-4 4,-4s4,1.791 4,4c0,2.21 -1.791,4 -4,4zM18.406,4.155c-0.796,0 -1.441,0.645 -1.441,1.44s0.645,1.44 1.441,1.44c0.795,0 1.439,-0.645 1.439,-1.44s-0.644,-1.44 -1.439,-1.44z"/> diff --git a/app/src/main/res/drawable/ic_reddit.xml b/app/src/main/res/drawable/ic_reddit.xml index aeab636dc4..e11069eb2d 100644 --- a/app/src/main/res/drawable/ic_reddit.xml +++ b/app/src/main/res/drawable/ic_reddit.xml @@ -1,21 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> - - - - + android:pathData="M14.238,15.348c0.085,0.084 0.085,0.221 0,0.306 -0.465,0.462 -1.194,0.687 -2.231,0.687l-0.008,-0.002 -0.008,0.002c-1.036,0 -1.766,-0.225 -2.231,-0.688 -0.085,-0.084 -0.085,-0.221 0,-0.305 0.084,-0.084 0.222,-0.084 0.307,0 0.379,0.377 1.008,0.561 1.924,0.561l0.008,0.002 0.008,-0.002c0.915,0 1.544,-0.184 1.924,-0.561 0.085,-0.084 0.223,-0.084 0.307,0zM10.798,12.93c0,-0.507 -0.414,-0.919 -0.922,-0.919 -0.509,0 -0.923,0.412 -0.923,0.919 0,0.506 0.414,0.918 0.923,0.918 0.508,0.001 0.922,-0.411 0.922,-0.918zM24,12c0,6.627 -5.373,12 -12,12s-12,-5.373 -12,-12 5.373,-12 12,-12 12,5.373 12,12zM19,11.871c0,-0.851 -0.695,-1.543 -1.55,-1.543 -0.417,0 -0.795,0.167 -1.074,0.435 -1.056,-0.695 -2.485,-1.137 -4.066,-1.194l0.865,-2.724 2.343,0.549 -0.003,0.034c0,0.696 0.569,1.262 1.268,1.262 0.699,0 1.267,-0.566 1.267,-1.262s-0.568,-1.262 -1.267,-1.262c-0.537,0 -0.994,0.335 -1.179,0.804l-2.525,-0.592c-0.11,-0.027 -0.223,0.037 -0.257,0.145l-0.965,3.038c-1.656,0.02 -3.155,0.466 -4.258,1.181 -0.277,-0.255 -0.644,-0.415 -1.05,-0.415 -0.854,0.001 -1.549,0.693 -1.549,1.544 0,0.566 0.311,1.056 0.768,1.325 -0.03,0.164 -0.05,0.331 -0.05,0.5 0,2.281 2.805,4.137 6.253,4.137s6.253,-1.856 6.253,-4.137c0,-0.16 -0.017,-0.317 -0.044,-0.472 0.486,-0.261 0.82,-0.766 0.82,-1.353zM14.128,12.012c-0.509,0 -0.922,0.412 -0.922,0.919 0,0.506 0.414,0.918 0.922,0.918s0.922,-0.412 0.922,-0.918c0,-0.507 -0.413,-0.919 -0.922,-0.919z"/> diff --git a/app/src/main/res/drawable/ic_round_assignment_24.xml b/app/src/main/res/drawable/ic_round_assignment_24.xml new file mode 100644 index 0000000000..54fb9d7604 --- /dev/null +++ b/app/src/main/res/drawable/ic_round_assignment_24.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/ic_round_close_24.xml b/app/src/main/res/drawable/ic_round_close_24.xml new file mode 100644 index 0000000000..a864ec280e --- /dev/null +++ b/app/src/main/res/drawable/ic_round_close_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_round_done_24.xml b/app/src/main/res/drawable/ic_round_done_24.xml new file mode 100644 index 0000000000..8f3250db52 --- /dev/null +++ b/app/src/main/res/drawable/ic_round_done_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_telegram.xml b/app/src/main/res/drawable/ic_telegram.xml index 44f6f4868e..bcb3724fa5 100644 --- a/app/src/main/res/drawable/ic_telegram.xml +++ b/app/src/main/res/drawable/ic_telegram.xml @@ -1,11 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + android:fillColor="#FF000000" + android:pathData="M18.384,22.779c0.322,0.228 0.737,0.285 1.107,0.145c0.37,-0.141 0.642,-0.457 0.724,-0.84c0.869,-4.084 2.977,-14.421 3.768,-18.136c0.06,-0.28 -0.04,-0.571 -0.26,-0.758c-0.22,-0.187 -0.525,-0.241 -0.797,-0.14c-4.193,1.552 -17.106,6.397 -22.384,8.35c-0.335,0.124 -0.553,0.446 -0.542,0.799c0.012,0.354 0.25,0.661 0.593,0.764c2.367,0.708 5.474,1.693 5.474,1.693c0,0 1.452,4.385 2.209,6.615c0.095,0.28 0.314,0.5 0.603,0.576c0.288,0.075 0.596,-0.004 0.811,-0.207c1.216,-1.148 3.096,-2.923 3.096,-2.923c0,0 3.572,2.619 5.598,4.062ZM7.374,14.102l1.679,5.538l0.373,-3.507c0,0 6.487,-5.851 10.185,-9.186c0.108,-0.098 0.123,-0.262 0.033,-0.377c-0.089,-0.115 -0.253,-0.142 -0.376,-0.064c-4.286,2.737 -11.894,7.596 -11.894,7.596Z"/> diff --git a/app/src/main/res/drawable/ic_twitter.xml b/app/src/main/res/drawable/ic_twitter.xml index 8f58f9167d..1a097f6b91 100644 --- a/app/src/main/res/drawable/ic_twitter.xml +++ b/app/src/main/res/drawable/ic_twitter.xml @@ -1,11 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + android:fillColor="#FF000000" + android:pathData="M24,4.557c-0.883,0.392 -1.832,0.656 -2.828,0.775 1.017,-0.609 1.798,-1.574 2.165,-2.724 -0.951,0.564 -2.005,0.974 -3.127,1.195 -0.897,-0.957 -2.178,-1.555 -3.594,-1.555 -3.179,0 -5.515,2.966 -4.797,6.045 -4.091,-0.205 -7.719,-2.165 -10.148,-5.144 -1.29,2.213 -0.669,5.108 1.523,6.574 -0.806,-0.026 -1.566,-0.247 -2.229,-0.616 -0.054,2.281 1.581,4.415 3.949,4.89 -0.693,0.188 -1.452,0.232 -2.224,0.084 0.626,1.956 2.444,3.379 4.6,3.419 -2.07,1.623 -4.678,2.348 -7.29,2.04 2.179,1.397 4.768,2.212 7.548,2.212 9.142,0 14.307,-7.721 13.995,-14.646 0.962,-0.695 1.797,-1.562 2.457,-2.549z"/> diff --git a/app/src/main/res/drawable/ic_website.xml b/app/src/main/res/drawable/ic_website.xml index 940a0fda4a..36ce05483b 100644 --- a/app/src/main/res/drawable/ic_website.xml +++ b/app/src/main/res/drawable/ic_website.xml @@ -1,16 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> - + android:fillColor="#FF000000" + android:pathData="M12,0c-6.627,0 -12,5.373 -12,12s5.373,12 12,12 12,-5.373 12,-12 -5.373,-12 -12,-12zM13,16.057v-3.057h2.994c-0.059,1.143 -0.212,2.24 -0.456,3.279 -0.823,-0.12 -1.674,-0.188 -2.538,-0.222zM14.957,18.219c-0.499,1.33 -1.159,2.497 -1.957,3.456v-3.62c0.666,0.028 1.319,0.081 1.957,0.164zM13,11v-3.015c0.868,-0.034 1.721,-0.103 2.548,-0.224 0.238,1.027 0.389,2.111 0.446,3.239h-2.994zM13,5.986v-3.661c0.806,0.969 1.471,2.15 1.971,3.496 -0.642,0.084 -1.3,0.137 -1.971,0.165zM15.703,2.719c1.237,0.496 2.354,1.228 3.29,2.146 -0.642,0.234 -1.311,0.442 -2.019,0.607 -0.344,-0.992 -0.775,-1.91 -1.271,-2.753zM8.462,16.279c-0.244,-1.039 -0.398,-2.136 -0.456,-3.279h2.994v3.057c-0.865,0.034 -1.714,0.102 -2.538,0.222zM11,18.055v3.62c-0.798,-0.959 -1.458,-2.126 -1.957,-3.456 0.638,-0.083 1.291,-0.136 1.957,-0.164zM8.006,11c0.057,-1.128 0.207,-2.212 0.446,-3.239 0.827,0.121 1.68,0.19 2.548,0.224v3.015h-2.994zM9.03,5.821c0.5,-1.346 1.165,-2.527 1.97,-3.496v3.661c-0.671,-0.028 -1.329,-0.081 -1.97,-0.165zM7.025,5.471c-0.708,-0.165 -1.377,-0.373 -2.018,-0.607 0.937,-0.918 2.053,-1.65 3.29,-2.146 -0.496,0.844 -0.927,1.762 -1.272,2.753zM6.476,7.389c-0.264,1.151 -0.434,2.36 -0.492,3.611h-3.933c0.165,-1.658 0.739,-3.197 1.617,-4.518 0.88,0.361 1.816,0.67 2.808,0.907zM6.485,16.651c-0.988,0.236 -1.92,0.542 -2.797,0.9 -0.89,-1.328 -1.471,-2.879 -1.637,-4.551h3.934c0.058,1.265 0.231,2.488 0.5,3.651zM7.038,18.568c0.342,0.976 0.768,1.881 1.257,2.712 -1.223,-0.49 -2.326,-1.211 -3.256,-2.115 0.636,-0.229 1.299,-0.435 1.999,-0.597zM16.962,18.568c0.7,0.163 1.362,0.367 1.999,0.597 -0.931,0.903 -2.034,1.625 -3.257,2.116 0.489,-0.832 0.915,-1.737 1.258,-2.713zM17.515,16.651c0.27,-1.163 0.442,-2.386 0.501,-3.651h3.934c-0.167,1.672 -0.748,3.223 -1.638,4.551 -0.877,-0.358 -1.81,-0.664 -2.797,-0.9zM18.016,11c-0.058,-1.251 -0.229,-2.46 -0.492,-3.611 0.992,-0.237 1.929,-0.546 2.809,-0.907 0.877,1.321 1.451,2.86 1.616,4.518h-3.933z"/> diff --git a/app/src/main/res/drawable/ic_youtube.xml b/app/src/main/res/drawable/ic_youtube.xml index b10d0d5061..d52b0c4c8e 100644 --- a/app/src/main/res/drawable/ic_youtube.xml +++ b/app/src/main/res/drawable/ic_youtube.xml @@ -1,16 +1,9 @@ + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> - + android:fillColor="#FF000000" + android:pathData="M19.615,3.184c-3.604,-0.246 -11.631,-0.245 -15.23,0 -3.897,0.266 -4.356,2.62 -4.385,8.816 0.029,6.185 0.484,8.549 4.385,8.816 3.6,0.245 11.626,0.246 15.23,0 3.897,-0.266 4.356,-2.62 4.385,-8.816 -0.029,-6.185 -0.484,-8.549 -4.385,-8.816zM9,16v-8l8,3.993 -8,4.007z"/> diff --git a/app/src/main/res/font/inter_black.ttf b/app/src/main/res/font/inter_black.ttf new file mode 100644 index 0000000000000000000000000000000000000000..565375773523cf29adce38a9fbf71a3badf2082c GIT binary patch literal 294396 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

A`y}8fD@XcF*bg(?aZEx<~j>dXSdRp1b=S<#@CX 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


b6j$2m#p6~C!rY9!9d*3s^ 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 QYnf3{HI-Ghx~bCt4-ah3x&QzG literal 0 HcmV?d00001 diff --git a/app/src/main/res/font/inter_extralight.ttf b/app/src/main/res/font/inter_extralight.ttf new file mode 100644 index 0000000000000000000000000000000000000000..69426a3eb5660eda166c828d3606ab7bcbc46133 GIT binary patch literal 288400 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

dHNwv~(;@i|a^Zdd0x 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 bq*mpmO7dsEdP8*!D+;Q)uAxPDSNgvJqt^P8 literal 0 HcmV?d00001 diff --git a/app/src/main/res/font/inter_extranold.ttf b/app/src/main/res/font/inter_extranold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..7f16a0f0f5947925f4f93bc96ebb52f387f8b2b1 GIT binary patch literal 294072 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

IpRpceDL>@u>`6fvS>>yFhe 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

Xa4+qGrJ&NNqSq9fo9 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

cQMf?Fv~EuMU@QXf`y}4 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

EgldKWv84`FE}6|o^51~BB|TA!2q;5^Gy=j2^A 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 GrT-t|qF|Z; literal 0 HcmV?d00001 diff --git a/app/src/main/res/font/inter_regular.ttf b/app/src/main/res/font/inter_regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..96fd6a12d0e20d7010b196e425ca48b0b5286df2 GIT binary patch literal 287928 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

Qe?PT{|VxcO4J23`XEyBR&d89m>IY`5{-wz+U6 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 K>9chcrT;%KY-A|_ literal 0 HcmV?d00001 diff --git a/app/src/main/res/font/inter_semibold.ttf b/app/src/main/res/font/inter_semibold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ddb279290ba32b02722d7bee592d7df22a16e86f GIT binary patch literal 293028 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%0D38jB&{w}Bz~6@Z)fNgB$^HtzXy?o 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 UK5^r`24)mgeNAnHZmsnH17|=S#Q*>R literal 0 HcmV?d00001 diff --git a/app/src/main/res/font/inter_thin.ttf b/app/src/main/res/font/inter_thin.ttf new file mode 100644 index 0000000000000000000000000000000000000000..76be6252b91e87ab5ead604b99d6945c13869f08 GIT binary patch literal 288568 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%0A2If4Bfd4GGEOY<C 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/values-af-rZA/strings.xml b/app/src/main/res/values-af-rZA/strings.xml index a5ae4f4797..caecfc4740 100644 --- a/app/src/main/res/values-af-rZA/strings.xml +++ b/app/src/main/res/values-af-rZA/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Apps</string> + <string name="home_category_apps">Apps</string> <string name="app_info_changelog_header">Changelog</string> <string name="app_download_dialog_downloading_file">Downloading %1$s</string> <string name="app_options_install">Install</string> <string name="latest">Latest:</string> <string name="app_microg_error">Install Vanced microG first</string> <string name="root_not_granted">Root access not granted</string> - <string name="home_header_social_media">Social Media</string> - <string name="home_header_support_us">Support us</string> + <string name="home_category_social_media">Social Media</string> + <string name="home_category_support_us">Support us</string> <string name="app_content_unavailable">Unavailable</string> <string name="version_installed">Installed:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Black</string> <string name="app_theme_dialog_option_dark">Dark</string> <!-- About Page --> - <string name="about_credits_manager_devs">Manager Devs</string> - <string name="about_credits_other">Other Contributors</string> - <string name="about_sources">Sources</string> - <string name="about_credits_vanced_team">Vanced Team</string> + <string name="about_category_credits_manager_devs">Manager Devs</string> + <string name="about_category_credits_other">Other Contributors</string> + <string name="about_category_sources">Sources</string> + <string name="about_category_credits_vanced_team">Vanced Team</string> <!-- Error messages --> <string name="install_error_chown_fail">Failed to `chown` APK to system owner, please try again.</string> <string name="install_error_downloading">Error Downloading %1$s</string> diff --git a/app/src/main/res/values-ar-rSA/strings.xml b/app/src/main/res/values-ar-rSA/strings.xml index 47bb521c4f..847b879a7f 100644 --- a/app/src/main/res/values-ar-rSA/strings.xml +++ b/app/src/main/res/values-ar-rSA/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">أعد التثبيت</string> <string name="accessibility_app_uninstall">إلغاء التثبيت</string> <string name="accessibility_app_update">تحديث</string> - <string name="home_header_apps">التطبيقات</string> + <string name="home_category_apps">التطبيقات</string> <string name="app_info_changelog_header">سجل التغييرات</string> <string name="app_download_dialog_downloading_file">جارٍ تنزيل %1$s</string> <string name="app_options_install">تثبيت</string> <string name="latest">الأحدث:</string> <string name="app_microg_error">قم بتثبيت Vanced microG أولاً</string> <string name="root_not_granted">لم يتم منح صلاحيات الروت</string> - <string name="home_header_social_media">وسائل التواصل الإجتماعي</string> - <string name="home_header_support_us">ادعمنا</string> + <string name="home_category_social_media">وسائل التواصل الإجتماعي</string> + <string name="home_category_support_us">ادعمنا</string> <string name="app_content_unavailable">غير متاح</string> <string name="version_installed">مثبت:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">أسود</string> <string name="app_theme_dialog_option_dark">داكن</string> <!-- About Page --> - <string name="about_credits_manager_devs">مطوري المدير</string> - <string name="about_credits_other">مساهمين آخرين</string> - <string name="about_sources">المصادر</string> - <string name="about_credits_vanced_team">فريق ڤانسد</string> + <string name="about_category_credits_manager_devs">مطوري المدير</string> + <string name="about_category_credits_other">مساهمين آخرين</string> + <string name="about_category_sources">المصادر</string> + <string name="about_category_credits_vanced_team">فريق ڤانسد</string> <!-- Error messages --> <string name="install_error_chown_fail">فشل تغيير ملكية حزمة التثبيت الى مالك النظام، الرجاء المحاولة مرة أخرى.</string> <string name="install_error_downloading">خطأ في تنزيل %1$s</string> diff --git a/app/src/main/res/values-az-rAZ/strings.xml b/app/src/main/res/values-az-rAZ/strings.xml index 7e100b2e17..3e2cdf985f 100644 --- a/app/src/main/res/values-az-rAZ/strings.xml +++ b/app/src/main/res/values-az-rAZ/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Tətbiqlər</string> + <string name="home_category_apps">Tətbiqlər</string> <string name="app_info_changelog_header">Dəyişikliklər</string> <string name="app_download_dialog_downloading_file">%1$s endirilir</string> <string name="app_options_install">Quraşdır</string> <string name="latest">Ən son:</string> <string name="app_microg_error">Əvvəlcə Vanced microG-ni quraşdırın</string> <string name="root_not_granted">Root icazəsi verilməyib</string> - <string name="home_header_social_media">Sosial Media</string> - <string name="home_header_support_us">Bizi dəstəklə</string> + <string name="home_category_social_media">Sosial Media</string> + <string name="home_category_support_us">Bizi dəstəklə</string> <string name="app_content_unavailable">Əlçatmazdır</string> <string name="version_installed">Qurulan:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Qara</string> <string name="app_theme_dialog_option_dark">Qaranlıq</string> <!-- About Page --> - <string name="about_credits_manager_devs">Menecer Tərtibatçıları</string> - <string name="about_credits_other">Digər Dəstəkçilər</string> - <string name="about_sources">Mənbələr</string> - <string name="about_credits_vanced_team">Vanced Birliyi</string> + <string name="about_category_credits_manager_devs">Menecer Tərtibatçıları</string> + <string name="about_category_credits_other">Digər Dəstəkçilər</string> + <string name="about_category_sources">Mənbələr</string> + <string name="about_category_credits_vanced_team">Vanced Birliyi</string> <!-- Error messages --> <string name="install_error_chown_fail">Apk, sistem sahibinə dəyişdirilmədi, yenidən sınayın.</string> <string name="install_error_downloading">%1$s Yüklənərkən xəta</string> diff --git a/app/src/main/res/values-bg-rBG/strings.xml b/app/src/main/res/values-bg-rBG/strings.xml index 533b2a9acf..845aa7506e 100644 --- a/app/src/main/res/values-bg-rBG/strings.xml +++ b/app/src/main/res/values-bg-rBG/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Деинсталиране</string> <string name="accessibility_app_update">Актуализиране</string> - <string name="home_header_apps">Приложения</string> + <string name="home_category_apps">Приложения</string> <string name="app_info_changelog_header">Списък с промени</string> <string name="app_download_dialog_downloading_file">Изтегляне на %1$s</string> <string name="app_options_install">Инсталиране</string> <string name="latest">Най-нова:</string> <string name="app_microg_error">Инсталирайте първо Vanced microG</string> <string name="root_not_granted">Root достъп не е разрешен</string> - <string name="home_header_social_media">Социални медии</string> - <string name="home_header_support_us">Подкрепете ни</string> + <string name="home_category_social_media">Социални медии</string> + <string name="home_category_support_us">Подкрепете ни</string> <string name="app_content_unavailable">Недостъпно</string> <string name="version_installed">Инсталиранa:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Черна</string> <string name="app_theme_dialog_option_dark">Тъмна</string> <!-- About Page --> - <string name="about_credits_manager_devs">Разработчици</string> - <string name="about_credits_other">Други сътрудници</string> - <string name="about_sources">Източници</string> - <string name="about_credits_vanced_team">Екип на Vanced</string> + <string name="about_category_credits_manager_devs">Разработчици</string> + <string name="about_category_credits_other">Други сътрудници</string> + <string name="about_category_sources">Източници</string> + <string name="about_category_credits_vanced_team">Екип на Vanced</string> <!-- Error messages --> <string name="install_error_chown_fail">Неуспешно`chown` APK към собственика на системата, моля опитайте отново.</string> <string name="install_error_downloading">Грешка при изтегляне на %1$s</string> diff --git a/app/src/main/res/values-bn-rBD/strings.xml b/app/src/main/res/values-bn-rBD/strings.xml index c2f1986f38..14f6fb12dc 100644 --- a/app/src/main/res/values-bn-rBD/strings.xml +++ b/app/src/main/res/values-bn-rBD/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Apps</string> + <string name="home_category_apps">Apps</string> <string name="app_info_changelog_header">পরিবর্তন তালিকা</string> <string name="app_download_dialog_downloading_file">%1$s ডাউনলোড করা হচ্ছে</string> <string name="app_options_install">ইনস্টল করুন</string> <string name="latest">সর্বশেষ:</string> <string name="app_microg_error">Install Vanced microG first</string> <string name="root_not_granted">রুট অনুমতি দেয়া হয়নি</string> - <string name="home_header_social_media">Social Media</string> - <string name="home_header_support_us">Support us</string> + <string name="home_category_social_media">Social Media</string> + <string name="home_category_support_us">Support us</string> <string name="app_content_unavailable">অনুপলব্ধ</string> <string name="version_installed">ইনস্টল করা আছে:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Black</string> <string name="app_theme_dialog_option_dark">Dark</string> <!-- About Page --> - <string name="about_credits_manager_devs">পরিচালক বিকাশকারী</string> - <string name="about_credits_other">Other Contributors</string> - <string name="about_sources">সূত্রসমূহ</string> - <string name="about_credits_vanced_team">ভান্সড দল</string> + <string name="about_category_credits_manager_devs">পরিচালক বিকাশকারী</string> + <string name="about_category_credits_other">Other Contributors</string> + <string name="about_category_sources">সূত্রসমূহ</string> + <string name="about_category_credits_vanced_team">ভান্সড দল</string> <!-- Error messages --> <string name="install_error_chown_fail">Failed to `chown` APK to system owner, please try again.</string> <string name="install_error_downloading">%1$s ডাউনলোড করার সময় ত্রুটি</string> diff --git a/app/src/main/res/values-bn-rIN/strings.xml b/app/src/main/res/values-bn-rIN/strings.xml index 4c9f76c73a..5e1e5e38b5 100644 --- a/app/src/main/res/values-bn-rIN/strings.xml +++ b/app/src/main/res/values-bn-rIN/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">আনইনস্টল</string> <string name="accessibility_app_update">আপডেট</string> - <string name="home_header_apps">অ্যাপস</string> + <string name="home_category_apps">অ্যাপস</string> <string name="app_info_changelog_header">পরিবর্তন নথি</string> <string name="app_download_dialog_downloading_file">%1$s ডাউনলোড করা হচ্ছে</string> <string name="app_options_install">ইনস্টল করুন</string> <string name="latest">সর্বশেষ:</string> <string name="app_microg_error">প্রথমে ভ্যান্সড মাইক্রোজি ইনস্টল করুন</string> <string name="root_not_granted">রুট অনুমতি দেয়া হয়নি</string> - <string name="home_header_social_media">সোশ্যাল মিডিয়া</string> - <string name="home_header_support_us">আমাদের সমর্থন করুন</string> + <string name="home_category_social_media">সোশ্যাল মিডিয়া</string> + <string name="home_category_support_us">আমাদের সমর্থন করুন</string> <string name="app_content_unavailable">অনুপলব্ধ</string> <string name="version_installed">ইনস্টল করা আছে:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">কালো</string> <string name="app_theme_dialog_option_dark">অন্ধকার</string> <!-- About Page --> - <string name="about_credits_manager_devs">ম্যানেজার বিকাশকারীরা</string> - <string name="about_credits_other">অন্যান্য অবদানকারী</string> - <string name="about_sources">উৎসগুলি</string> - <string name="about_credits_vanced_team">ভ্যান্সড টীম</string> + <string name="about_category_credits_manager_devs">ম্যানেজার বিকাশকারীরা</string> + <string name="about_category_credits_other">অন্যান্য অবদানকারী</string> + <string name="about_category_sources">উৎসগুলি</string> + <string name="about_category_credits_vanced_team">ভ্যান্সড টীম</string> <!-- Error messages --> <string name="install_error_chown_fail">System owner কে APK `chown` করতে ব্যর্থ, দয়া করে আবার চেষ্টা করুন।</string> <string name="install_error_downloading">%1$s ডাউনলোড করার সময় ত্রুটি</string> diff --git a/app/src/main/res/values-ca-rES/strings.xml b/app/src/main/res/values-ca-rES/strings.xml index 6b0086dcd4..9619762d97 100644 --- a/app/src/main/res/values-ca-rES/strings.xml +++ b/app/src/main/res/values-ca-rES/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Desinstal·la</string> <string name="accessibility_app_update">Actualitza</string> - <string name="home_header_apps">Aplicacions</string> + <string name="home_category_apps">Aplicacions</string> <string name="app_info_changelog_header">Registre de canvis</string> <string name="app_download_dialog_downloading_file">Descarregant %1$s</string> <string name="app_options_install">Instal·lar</string> <string name="latest">Darrera:</string> <string name="app_microg_error">Instal·la primer Vanced microG</string> <string name="root_not_granted">L\'accés arrel no s\'ha concedit</string> - <string name="home_header_social_media">Xarxes socials</string> - <string name="home_header_support_us">Dóna\'ns suport</string> + <string name="home_category_social_media">Xarxes socials</string> + <string name="home_category_support_us">Dóna\'ns suport</string> <string name="app_content_unavailable">No disponible</string> <string name="version_installed">Instal·lat:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Black</string> <string name="app_theme_dialog_option_dark">Dark</string> <!-- About Page --> - <string name="about_credits_manager_devs">Gestor de desenvolupadors</string> - <string name="about_credits_other">Other Contributors</string> - <string name="about_sources">Fonts</string> - <string name="about_credits_vanced_team">Equip avançat</string> + <string name="about_category_credits_manager_devs">Gestor de desenvolupadors</string> + <string name="about_category_credits_other">Other Contributors</string> + <string name="about_category_sources">Fonts</string> + <string name="about_category_credits_vanced_team">Equip avançat</string> <!-- Error messages --> <string name="install_error_chown_fail">Failed to `chown` APK to system owner, please try again.</string> <string name="install_error_downloading">Error en descarregar %1$s</string> diff --git a/app/src/main/res/values-ckb-rIR/strings.xml b/app/src/main/res/values-ckb-rIR/strings.xml index 3d4a2a43b0..2e8c19e443 100644 --- a/app/src/main/res/values-ckb-rIR/strings.xml +++ b/app/src/main/res/values-ckb-rIR/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">بەرنامەکان</string> + <string name="home_category_apps">بەرنامەکان</string> <string name="app_info_changelog_header">گۆڕانکارییەکان</string> <string name="app_download_dialog_downloading_file">داگرتنی %1$s</string> <string name="app_options_install">دامەزراندن</string> <string name="latest">دوایین:</string> <string name="app_microg_error">Install Vanced microG first</string> <string name="root_not_granted">ڕێگەپێدانی Root نەدراوە</string> - <string name="home_header_social_media">تۆڕە کۆمەڵایەتییەکان</string> - <string name="home_header_support_us">پشتگیریکردن</string> + <string name="home_category_social_media">تۆڕە کۆمەڵایەتییەکان</string> + <string name="home_category_support_us">پشتگیریکردن</string> <string name="app_content_unavailable">بەردەست نیە</string> <string name="version_installed">دامەزرێنراو:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">ڕەش</string> <string name="app_theme_dialog_option_dark">تاریک</string> <!-- About Page --> - <string name="about_credits_manager_devs">کراوە بە کوردی لەلایەن: گۆران غەریب(کوردرۆید)</string> - <string name="about_credits_other">وەرگێڕانی کوردی - گۆران غەریب </string> - <string name="about_sources">سەرچاوەکان</string> - <string name="about_credits_vanced_team">Vanced تیمی</string> + <string name="about_category_credits_manager_devs">کراوە بە کوردی لەلایەن: گۆران غەریب(کوردرۆید)</string> + <string name="about_category_credits_other">وەرگێڕانی کوردی - گۆران غەریب </string> + <string name="about_category_sources">سەرچاوەکان</string> + <string name="about_category_credits_vanced_team">Vanced تیمی</string> <!-- Error messages --> <string name="install_error_chown_fail">سەرکەوتو نەبوو `chown` بۆ دانان وەک بەرنامەی سیستەم, تکایە دووبارە هەوڵبدەرەوە.</string> <string name="install_error_downloading">کێشە ڕوویدا لە داگرتنی %1$s</string> diff --git a/app/src/main/res/values-cs-rCZ/strings.xml b/app/src/main/res/values-cs-rCZ/strings.xml index 7cda59faaa..faa271f5a1 100644 --- a/app/src/main/res/values-cs-rCZ/strings.xml +++ b/app/src/main/res/values-cs-rCZ/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Přeinstalovat</string> <string name="accessibility_app_uninstall">Odinstalovat</string> <string name="accessibility_app_update">Aktualizovat</string> - <string name="home_header_apps">Aplikace</string> + <string name="home_category_apps">Aplikace</string> <string name="app_info_changelog_header">Seznam změn</string> <string name="app_download_dialog_downloading_file">Stahování %1$s</string> <string name="app_options_install">Nainstalovat</string> <string name="latest">Nejnovější:</string> <string name="app_microg_error">Nejprve nainstalujte Vanced microG</string> <string name="root_not_granted">Root přístup nebyl udělen</string> - <string name="home_header_social_media">Sociální média</string> - <string name="home_header_support_us">Podpořte nás</string> + <string name="home_category_social_media">Sociální média</string> + <string name="home_category_support_us">Podpořte nás</string> <string name="app_content_unavailable">Není k dispozici</string> <string name="version_installed">Nainstalováno:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Černý</string> <string name="app_theme_dialog_option_dark">Tmavý</string> <!-- About Page --> - <string name="about_credits_manager_devs">Vývojáři aplikace Manager</string> - <string name="about_credits_other">Další přispěvatelé</string> - <string name="about_sources">Zdrojové kódy</string> - <string name="about_credits_vanced_team">Tým Vanced</string> + <string name="about_category_credits_manager_devs">Vývojáři aplikace Manager</string> + <string name="about_category_credits_other">Další přispěvatelé</string> + <string name="about_category_sources">Zdrojové kódy</string> + <string name="about_category_credits_vanced_team">Tým Vanced</string> <!-- Error messages --> <string name="install_error_chown_fail">Nepodařilo se změnit vlastníka souboru APK na vlastníka systému, zkuste to prosím znovu.</string> <string name="install_error_downloading">Chyba při stahování %1$s</string> diff --git a/app/src/main/res/values-da-rDK/strings.xml b/app/src/main/res/values-da-rDK/strings.xml index 3d98057837..df8cbe007d 100644 --- a/app/src/main/res/values-da-rDK/strings.xml +++ b/app/src/main/res/values-da-rDK/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Apps</string> + <string name="home_category_apps">Apps</string> <string name="app_info_changelog_header">Ændringslog</string> <string name="app_download_dialog_downloading_file">Downloader %1$s</string> <string name="app_options_install">Installer</string> <string name="latest">Seneste:</string> <string name="app_microg_error">Installer først Vanced microG</string> <string name="root_not_granted">Root adgang ikke tildelt</string> - <string name="home_header_social_media">Sociale medier</string> - <string name="home_header_support_us">Støt os</string> + <string name="home_category_social_media">Sociale medier</string> + <string name="home_category_support_us">Støt os</string> <string name="app_content_unavailable">Utilgængelig</string> <string name="version_installed">Installeret:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Sort</string> <string name="app_theme_dialog_option_dark">Mørk</string> <!-- About Page --> - <string name="about_credits_manager_devs">Manager udviklere</string> - <string name="about_credits_other">Øvrige Bidragsydere</string> - <string name="about_sources">Kilder</string> - <string name="about_credits_vanced_team">Vanced holdet</string> + <string name="about_category_credits_manager_devs">Manager udviklere</string> + <string name="about_category_credits_other">Øvrige Bidragsydere</string> + <string name="about_category_sources">Kilder</string> + <string name="about_category_credits_vanced_team">Vanced holdet</string> <!-- Error messages --> <string name="install_error_chown_fail">Kunne ikke vælge Apk til systemejer, Prøv igen.</string> <string name="install_error_downloading">Fejl i download af %1$s</string> diff --git a/app/src/main/res/values-de-rDE/strings.xml b/app/src/main/res/values-de-rDE/strings.xml index 8185681786..6eac627fe8 100644 --- a/app/src/main/res/values-de-rDE/strings.xml +++ b/app/src/main/res/values-de-rDE/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Neu installieren</string> <string name="accessibility_app_uninstall">Deinstallieren</string> <string name="accessibility_app_update">Aktualisieren</string> - <string name="home_header_apps">Anwendungen</string> + <string name="home_category_apps">Anwendungen</string> <string name="app_info_changelog_header">Änderungen</string> <string name="app_download_dialog_downloading_file">%1$s wird heruntergeladen</string> <string name="app_options_install">Installieren</string> <string name="latest">Neueste:</string> <string name="app_microg_error">Installiere zuerst Vanced MicroG</string> <string name="root_not_granted">Root-Zugriff nicht erteilt</string> - <string name="home_header_social_media">Soziale Medien</string> - <string name="home_header_support_us">Unterstütze uns</string> + <string name="home_category_social_media">Soziale Medien</string> + <string name="home_category_support_us">Unterstütze uns</string> <string name="app_content_unavailable">Nicht verfügbar</string> <string name="version_installed">Installiert:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Schwarz</string> <string name="app_theme_dialog_option_dark">Dunkel</string> <!-- About Page --> - <string name="about_credits_manager_devs">Manager-Entwickler</string> - <string name="about_credits_other">Weitere Mitwirkende</string> - <string name="about_sources">Quellen</string> - <string name="about_credits_vanced_team">Vanced Team</string> + <string name="about_category_credits_manager_devs">Manager-Entwickler</string> + <string name="about_category_credits_other">Weitere Mitwirkende</string> + <string name="about_category_sources">Quellen</string> + <string name="about_category_credits_vanced_team">Vanced Team</string> <!-- Error messages --> <string name="install_error_chown_fail">Fehler beim `chown` der APK zum Systembesitzer, bitte versuche es erneut.</string> <string name="install_error_downloading">Download von %1$s fehlgeschlagen</string> diff --git a/app/src/main/res/values-el-rGR/strings.xml b/app/src/main/res/values-el-rGR/strings.xml index 38b920645f..a6fe9b073d 100644 --- a/app/src/main/res/values-el-rGR/strings.xml +++ b/app/src/main/res/values-el-rGR/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Επανεγκατάσταση</string> <string name="accessibility_app_uninstall">Απεγκατάσταση</string> <string name="accessibility_app_update">Ενημέρωση</string> - <string name="home_header_apps">Εφαρμογές</string> + <string name="home_category_apps">Εφαρμογές</string> <string name="app_info_changelog_header">Αρχείο καταγραφής αλλαγών</string> <string name="app_download_dialog_downloading_file">Λήψη %1$s</string> <string name="app_options_install">Εγκατάσταση</string> <string name="latest">Τελευταία έκδοση:</string> <string name="app_microg_error">Εγκαταστήστε πρώτα το Vanced microG</string> <string name="root_not_granted">Δεν επιτράπηκε η πρόσβαση Root</string> - <string name="home_header_social_media">Μέσα Κοινωνικής Δικτύωσης</string> - <string name="home_header_support_us">Υποστηρίξτε μας</string> + <string name="home_category_social_media">Μέσα Κοινωνικής Δικτύωσης</string> + <string name="home_category_support_us">Υποστηρίξτε μας</string> <string name="app_content_unavailable">Μη διαθέσιμο</string> <string name="version_installed">Εγκατεστημένη έκδοση:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Μαύρο</string> <string name="app_theme_dialog_option_dark">Σκουρόχρωμο</string> <!-- About Page --> - <string name="about_credits_manager_devs">Προγραμματιστές Διαχειριστή Vanced</string> - <string name="about_credits_other">Άλλοι Συνεισφέροντες</string> - <string name="about_sources">Πηγές</string> - <string name="about_credits_vanced_team">Η ομάδα του Vanced</string> + <string name="about_category_credits_manager_devs">Προγραμματιστές Διαχειριστή Vanced</string> + <string name="about_category_credits_other">Άλλοι Συνεισφέροντες</string> + <string name="about_category_sources">Πηγές</string> + <string name="about_category_credits_vanced_team">Η ομάδα του Vanced</string> <!-- Error messages --> <string name="install_error_chown_fail">Αποτυχία παραχώρησης ιδιοκτησίας του APK στον κάτοχο συστήματος, παρακαλούμε προσπαθείστε ξανά.</string> <string name="install_error_downloading">Σφάλμα λήψης του %1$s</string> diff --git a/app/src/main/res/values-es-rES/strings.xml b/app/src/main/res/values-es-rES/strings.xml index b4998cc7b7..4b0800b3eb 100644 --- a/app/src/main/res/values-es-rES/strings.xml +++ b/app/src/main/res/values-es-rES/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstalar</string> <string name="accessibility_app_uninstall">Desinstalar</string> <string name="accessibility_app_update">Actualizar</string> - <string name="home_header_apps">Apps</string> + <string name="home_category_apps">Apps</string> <string name="app_info_changelog_header">Historial de actualizaciones</string> <string name="app_download_dialog_downloading_file">Descargando %1$s</string> <string name="app_options_install">Instalar</string> <string name="latest">Más reciente:</string> <string name="app_microg_error">Primero, instala Vanced microG</string> <string name="root_not_granted">Acceso root no concedido</string> - <string name="home_header_social_media">Redes Sociales</string> - <string name="home_header_support_us">Apóyanos</string> + <string name="home_category_social_media">Redes Sociales</string> + <string name="home_category_support_us">Apóyanos</string> <string name="app_content_unavailable">No Disponible</string> <string name="version_installed">Instalado:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Negro</string> <string name="app_theme_dialog_option_dark">Oscuro</string> <!-- About Page --> - <string name="about_credits_manager_devs">Desarrolladores del Manager</string> - <string name="about_credits_other">Otros colaboradores</string> - <string name="about_sources">Fuentes</string> - <string name="about_credits_vanced_team">Equipo Vanced</string> + <string name="about_category_credits_manager_devs">Desarrolladores del Manager</string> + <string name="about_category_credits_other">Otros colaboradores</string> + <string name="about_category_sources">Fuentes</string> + <string name="about_category_credits_vanced_team">Equipo Vanced</string> <!-- Error messages --> <string name="install_error_chown_fail">Fallo al ejecutar `chown` al propietario del sistema, por favor inténtalo de nuevo.</string> <string name="install_error_downloading">Error al descargar %1$s</string> diff --git a/app/src/main/res/values-et-rEE/strings.xml b/app/src/main/res/values-et-rEE/strings.xml index 249569f428..c43ffd82c6 100644 --- a/app/src/main/res/values-et-rEE/strings.xml +++ b/app/src/main/res/values-et-rEE/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Rakendused</string> + <string name="home_category_apps">Rakendused</string> <string name="app_info_changelog_header">Muudatuste logi</string> <string name="app_download_dialog_downloading_file">Allalaadimine %1$s</string> <string name="app_options_install">Installi</string> <string name="latest">Uusim:</string> <string name="app_microg_error">Installi Vanced MicroG esimesena</string> <string name="root_not_granted">Administraatoriõigusi ei tagatud</string> - <string name="home_header_social_media">Sotsiaalmeedia</string> - <string name="home_header_support_us">Toetage meid</string> + <string name="home_category_social_media">Sotsiaalmeedia</string> + <string name="home_category_support_us">Toetage meid</string> <string name="app_content_unavailable">Pole saadaval</string> <string name="version_installed">Installitud:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Must</string> <string name="app_theme_dialog_option_dark">Tume</string> <!-- About Page --> - <string name="about_credits_manager_devs">Halduri arendajad</string> - <string name="about_credits_other">Teised kaastöötajad</string> - <string name="about_sources">Allikad</string> - <string name="about_credits_vanced_team">Vanced Meeskond</string> + <string name="about_category_credits_manager_devs">Halduri arendajad</string> + <string name="about_category_credits_other">Teised kaastöötajad</string> + <string name="about_category_sources">Allikad</string> + <string name="about_category_credits_vanced_team">Vanced Meeskond</string> <!-- Error messages --> <string name="install_error_chown_fail">APK edastamine süsteemi omanikule ebaõnnestus, proovige uuesti.</string> <string name="install_error_downloading">Viga allalaadimisel %1$s</string> diff --git a/app/src/main/res/values-fi-rFI/strings.xml b/app/src/main/res/values-fi-rFI/strings.xml index c52dcdd681..1737f8c7ce 100644 --- a/app/src/main/res/values-fi-rFI/strings.xml +++ b/app/src/main/res/values-fi-rFI/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Sovellukset</string> + <string name="home_category_apps">Sovellukset</string> <string name="app_info_changelog_header">Muutoshistoria</string> <string name="app_download_dialog_downloading_file">Ladataan %1$s</string> <string name="app_options_install">Asenna</string> <string name="latest">Uusin:</string> <string name="app_microg_error">Asenna Vanced microG ensin</string> <string name="root_not_granted">Pääkäyttäjän oikeuksia ei ole annettu</string> - <string name="home_header_social_media">Sosiaalinen media</string> - <string name="home_header_support_us">Tue meitä</string> + <string name="home_category_social_media">Sosiaalinen media</string> + <string name="home_category_support_us">Tue meitä</string> <string name="app_content_unavailable">Ei saatavilla</string> <string name="version_installed">Asennettu:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Musta</string> <string name="app_theme_dialog_option_dark">Tumma</string> <!-- About Page --> - <string name="about_credits_manager_devs">Managerin kehittäjät</string> - <string name="about_credits_other">Muut avustajat</string> - <string name="about_sources">Lähdekoodi</string> - <string name="about_credits_vanced_team">Vanced kehitystiimi</string> + <string name="about_category_credits_manager_devs">Managerin kehittäjät</string> + <string name="about_category_credits_other">Muut avustajat</string> + <string name="about_category_sources">Lähdekoodi</string> + <string name="about_category_credits_vanced_team">Vanced kehitystiimi</string> <!-- Error messages --> <string name="install_error_chown_fail">Ei voitu `chown` APK järjestelmän omistajalle, yritä uudelleen.</string> <string name="install_error_downloading">%1$s lataus epäonnistui</string> diff --git a/app/src/main/res/values-fil-rPH/strings.xml b/app/src/main/res/values-fil-rPH/strings.xml index 2a27ba3472..fed16f97b6 100644 --- a/app/src/main/res/values-fil-rPH/strings.xml +++ b/app/src/main/res/values-fil-rPH/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Mga Apps</string> + <string name="home_category_apps">Mga Apps</string> <string name="app_info_changelog_header">Changelog</string> <string name="app_download_dialog_downloading_file">Downloading %1$s</string> <string name="app_options_install">I-install</string> <string name="latest">Bago:</string> <string name="app_microg_error">I-install muna ang Vanced microG</string> <string name="root_not_granted">Walang binigay na root access</string> - <string name="home_header_social_media">Social Media</string> - <string name="home_header_support_us">Suportahin kami</string> + <string name="home_category_social_media">Social Media</string> + <string name="home_category_support_us">Suportahin kami</string> <string name="app_content_unavailable">Di-makukuha</string> <string name="version_installed">Naka-install:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Itim</string> <string name="app_theme_dialog_option_dark">Madilim</string> <!-- About Page --> - <string name="about_credits_manager_devs">Manager Devs</string> - <string name="about_credits_other">Other Contributors</string> - <string name="about_sources">Pinagkukunan</string> - <string name="about_credits_vanced_team">Pangkat Vanced</string> + <string name="about_category_credits_manager_devs">Manager Devs</string> + <string name="about_category_credits_other">Other Contributors</string> + <string name="about_category_sources">Pinagkukunan</string> + <string name="about_category_credits_vanced_team">Pangkat Vanced</string> <!-- Error messages --> <string name="install_error_chown_fail">Nabigo sa `pag-chown` ng APK sa system owner, ulitin muli.</string> <string name="install_error_downloading">May pagkamali sa pag-download %1$s</string> diff --git a/app/src/main/res/values-fr-rFR/strings.xml b/app/src/main/res/values-fr-rFR/strings.xml index 7c56a2e0c7..737c23fdb8 100644 --- a/app/src/main/res/values-fr-rFR/strings.xml +++ b/app/src/main/res/values-fr-rFR/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Réinstaller</string> <string name="accessibility_app_uninstall">Désinstaller</string> <string name="accessibility_app_update">Mettre à jour</string> - <string name="home_header_apps">Applications</string> + <string name="home_category_apps">Applications</string> <string name="app_info_changelog_header">Changelog</string> <string name="app_download_dialog_downloading_file">Téléchargement de %1$s</string> <string name="app_options_install">Installer</string> <string name="latest">Dernière version:</string> <string name="app_microg_error">Installez d\'abord Vanced microG</string> <string name="root_not_granted">Accès root non autorisé</string> - <string name="home_header_social_media">Réseaux sociaux</string> - <string name="home_header_support_us">Soutenez-nous</string> + <string name="home_category_social_media">Réseaux sociaux</string> + <string name="home_category_support_us">Soutenez-nous</string> <string name="app_content_unavailable">Indisponible</string> <string name="version_installed">Version installée:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Noir</string> <string name="app_theme_dialog_option_dark">Sombre</string> <!-- About Page --> - <string name="about_credits_manager_devs">Développeurs du Manager</string> - <string name="about_credits_other">Autres Contributeurs</string> - <string name="about_sources">Sources</string> - <string name="about_credits_vanced_team">Équipe Vanced</string> + <string name="about_category_credits_manager_devs">Développeurs du Manager</string> + <string name="about_category_credits_other">Autres Contributeurs</string> + <string name="about_category_sources">Sources</string> + <string name="about_category_credits_vanced_team">Équipe Vanced</string> <!-- Error messages --> <string name="install_error_chown_fail">Échec de la commande `chown` APK vers le propriétaire du système, veuillez réessayer.</string> <string name="install_error_downloading">Erreur en téléchargeant %1$s</string> diff --git a/app/src/main/res/values-hi-rIN/strings.xml b/app/src/main/res/values-hi-rIN/strings.xml index ad480c58ad..287ac63fb6 100644 --- a/app/src/main/res/values-hi-rIN/strings.xml +++ b/app/src/main/res/values-hi-rIN/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">ऐप</string> + <string name="home_category_apps">ऐप</string> <string name="app_info_changelog_header">परिवर्तन पत्र</string> <string name="app_download_dialog_downloading_file">डाउनलोड हो रहा है %1$s</string> <string name="app_options_install">इंस्टॉल</string> <string name="latest">सबसे नया</string> <string name="app_microg_error">सबसे पहले Vanced microG इंस्टॉल करें</string> <string name="root_not_granted">रूट एक्सेस प्रदान नहीं किया गया</string> - <string name="home_header_social_media">सोशल मीडिया</string> - <string name="home_header_support_us">हमें सहयोग दीजिये</string> + <string name="home_category_social_media">सोशल मीडिया</string> + <string name="home_category_support_us">हमें सहयोग दीजिये</string> <string name="app_content_unavailable">अनुपलब्ध</string> <string name="version_installed">इंस्टॉल हुआ।</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">काला</string> <string name="app_theme_dialog_option_dark">डार्क</string> <!-- About Page --> - <string name="about_credits_manager_devs">प्रबंधक डेवलपर्स</string> - <string name="about_credits_other">अन्य योगदानकर्ता</string> - <string name="about_sources">स्रोत</string> - <string name="about_credits_vanced_team">वांसड टीम</string> + <string name="about_category_credits_manager_devs">प्रबंधक डेवलपर्स</string> + <string name="about_category_credits_other">अन्य योगदानकर्ता</string> + <string name="about_category_sources">स्रोत</string> + <string name="about_category_credits_vanced_team">वांसड टीम</string> <!-- Error messages --> <string name="install_error_chown_fail">सिस्टम के मालिक को APK को Chown करने में विफल, फिर से प्रयास करें।</string> <string name="install_error_downloading">डाउनलोड करने में त्रुटि %1$s</string> diff --git a/app/src/main/res/values-hr-rHR/strings.xml b/app/src/main/res/values-hr-rHR/strings.xml index 311bea76d1..7482d6370d 100644 --- a/app/src/main/res/values-hr-rHR/strings.xml +++ b/app/src/main/res/values-hr-rHR/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstaliraj</string> <string name="accessibility_app_uninstall">Deinstaliraj</string> <string name="accessibility_app_update">Ažuriraj</string> - <string name="home_header_apps">Aplikacije</string> + <string name="home_category_apps">Aplikacije</string> <string name="app_info_changelog_header">Zapis promjena</string> <string name="app_download_dialog_downloading_file">Preuzimam %1$s</string> <string name="app_options_install">Instaliraj</string> <string name="latest">Dostupno:</string> <string name="app_microg_error">Prvo instaliraj Vanced MicroG</string> <string name="root_not_granted">Root pristup nije dopušten</string> - <string name="home_header_social_media">Društvene mreže</string> - <string name="home_header_support_us">Podržite nas</string> + <string name="home_category_social_media">Društvene mreže</string> + <string name="home_category_support_us">Podržite nas</string> <string name="app_content_unavailable">Nedostupno</string> <string name="version_installed">Instalirano:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Crna</string> <string name="app_theme_dialog_option_dark">Tamna</string> <!-- About Page --> - <string name="about_credits_manager_devs">Razvijatelji Vanced upravitelja</string> - <string name="about_credits_other">Ostali suradnici</string> - <string name="about_sources">Izvori</string> - <string name="about_credits_vanced_team">Vanced tim</string> + <string name="about_category_credits_manager_devs">Razvijatelji Vanced upravitelja</string> + <string name="about_category_credits_other">Ostali suradnici</string> + <string name="about_category_sources">Izvori</string> + <string name="about_category_credits_vanced_team">Vanced tim</string> <!-- Error messages --> <string name="install_error_chown_fail">Neuspjela promjena `chown` APK u vlasnika sustava, pokušajte ponovno.</string> <string name="install_error_downloading">Greška preuzimanja %1$s</string> diff --git a/app/src/main/res/values-hu-rHU/strings.xml b/app/src/main/res/values-hu-rHU/strings.xml index 14099d8127..f7f5a80f65 100644 --- a/app/src/main/res/values-hu-rHU/strings.xml +++ b/app/src/main/res/values-hu-rHU/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Újratelepítés</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Alkalmazások</string> + <string name="home_category_apps">Alkalmazások</string> <string name="app_info_changelog_header">Változáslista</string> <string name="app_download_dialog_downloading_file">%1$s letöltése</string> <string name="app_options_install">Telepítés</string> <string name="latest">Legújabb:</string> <string name="app_microg_error">Először telepítse a Vanced microG-t</string> <string name="root_not_granted">A root hozzáférés nincs megadva</string> - <string name="home_header_social_media">Közösségi média</string> - <string name="home_header_support_us">Támogasson bennünket</string> + <string name="home_category_social_media">Közösségi média</string> + <string name="home_category_support_us">Támogasson bennünket</string> <string name="app_content_unavailable">Nem elérhető</string> <string name="version_installed">Telepítve:</string> <!-- Settings --> @@ -96,10 +96,10 @@ Akarod telepíteni?</string> <string name="app_theme_dialog_option_black">Fekete</string> <string name="app_theme_dialog_option_dark">Sötét</string> <!-- About Page --> - <string name="about_credits_manager_devs">Fejlesztői Menedzser</string> - <string name="about_credits_other">Egyéb Közreműködők</string> - <string name="about_sources">Források</string> - <string name="about_credits_vanced_team">Vanced csapat</string> + <string name="about_category_credits_manager_devs">Fejlesztői Menedzser</string> + <string name="about_category_credits_other">Egyéb Közreműködők</string> + <string name="about_category_sources">Források</string> + <string name="about_category_credits_vanced_team">Vanced csapat</string> <!-- Error messages --> <string name="install_error_chown_fail">Nem sikerült az APK beállítása a rendszer tulajdonoshoz, kérjük próbálja újra.</string> <string name="install_error_downloading">%1$s letöltése nem sikerült</string> diff --git a/app/src/main/res/values-in-rID/strings.xml b/app/src/main/res/values-in-rID/strings.xml index 99531baaa0..115445e586 100644 --- a/app/src/main/res/values-in-rID/strings.xml +++ b/app/src/main/res/values-in-rID/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Pasang ulang</string> <string name="accessibility_app_uninstall">Copot pemasangan</string> <string name="accessibility_app_update">Perbarui</string> - <string name="home_header_apps">Aplikasi</string> + <string name="home_category_apps">Aplikasi</string> <string name="app_info_changelog_header">Catatan perubahan</string> <string name="app_download_dialog_downloading_file">Mengunduh %1$s</string> <string name="app_options_install">Pasang</string> <string name="latest">Terbaru:</string> <string name="app_microg_error">Pasang Vanced microG terlebih dahulu</string> <string name="root_not_granted">Akses Root tidak diberikan</string> - <string name="home_header_social_media">Media Sosial</string> - <string name="home_header_support_us">Dukung kami</string> + <string name="home_category_social_media">Media Sosial</string> + <string name="home_category_support_us">Dukung kami</string> <string name="app_content_unavailable">Tidak tersedia</string> <string name="version_installed">Terpasang:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Hitam</string> <string name="app_theme_dialog_option_dark">Gelap</string> <!-- About Page --> - <string name="about_credits_manager_devs">Pengembang Manager</string> - <string name="about_credits_other">Kontributor Lain</string> - <string name="about_sources">Sumber</string> - <string name="about_credits_vanced_team">Tim Vanced</string> + <string name="about_category_credits_manager_devs">Pengembang Manager</string> + <string name="about_category_credits_other">Kontributor Lain</string> + <string name="about_category_sources">Sumber</string> + <string name="about_category_credits_vanced_team">Tim Vanced</string> <!-- Error messages --> <string name="install_error_chown_fail">Gagal untuk `chown` APK ke pemilik sistem, mohon coba lagi.</string> <string name="install_error_downloading">Gagal Mengunduh %1$s</string> diff --git a/app/src/main/res/values-it-rIT/strings.xml b/app/src/main/res/values-it-rIT/strings.xml index 11060915cd..4177075a3c 100644 --- a/app/src/main/res/values-it-rIT/strings.xml +++ b/app/src/main/res/values-it-rIT/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstalla</string> <string name="accessibility_app_uninstall">Disinstalla</string> <string name="accessibility_app_update">Aggiorna</string> - <string name="home_header_apps">App</string> + <string name="home_category_apps">App</string> <string name="app_info_changelog_header">Novità</string> <string name="app_download_dialog_downloading_file">Download in corso di %1$s</string> <string name="app_options_install">Installa</string> <string name="latest">Disponibile:</string> <string name="app_microg_error">Installa prima Vanced microG</string> <string name="root_not_granted">Accesso root non consentito</string> - <string name="home_header_social_media">Social Media</string> - <string name="home_header_support_us">Sostienici</string> + <string name="home_category_social_media">Social Media</string> + <string name="home_category_support_us">Sostienici</string> <string name="app_content_unavailable">Non disponibile</string> <string name="version_installed">Installata:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Nero</string> <string name="app_theme_dialog_option_dark">Scuro</string> <!-- About Page --> - <string name="about_credits_manager_devs">Sviluppatori di Manager</string> - <string name="about_credits_other">Altri Collaboratori</string> - <string name="about_sources">Codice Sorgente</string> - <string name="about_credits_vanced_team">Il Team di Vanced</string> + <string name="about_category_credits_manager_devs">Sviluppatori di Manager</string> + <string name="about_category_credits_other">Altri Collaboratori</string> + <string name="about_category_sources">Codice Sorgente</string> + <string name="about_category_credits_vanced_team">Il Team di Vanced</string> <!-- Error messages --> <string name="install_error_chown_fail">Impossibile modificare il proprietario dell\'apk nel proprietario di sistema, per favore riprova.</string> <string name="install_error_downloading">Errore nel Download di %1$s</string> diff --git a/app/src/main/res/values-iw-rIL/strings.xml b/app/src/main/res/values-iw-rIL/strings.xml index 0cf2badea9..eaa578fb28 100644 --- a/app/src/main/res/values-iw-rIL/strings.xml +++ b/app/src/main/res/values-iw-rIL/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">התקן מחדש</string> <string name="accessibility_app_uninstall">הסרת ההתקנה</string> <string name="accessibility_app_update">עדכן</string> - <string name="home_header_apps">יישומים</string> + <string name="home_category_apps">יישומים</string> <string name="app_info_changelog_header">היסטורית שינויים</string> <string name="app_download_dialog_downloading_file">מוריד את %1$s</string> <string name="app_options_install">התקן</string> <string name="latest">החדש ביותר:</string> <string name="app_microg_error">התקן את שירותי Google של Vanced תחילה</string> <string name="root_not_granted">לא הוענקו הרשאות Root</string> - <string name="home_header_social_media">רשתות חברתיות</string> - <string name="home_header_support_us">תמכו בנו</string> + <string name="home_category_social_media">רשתות חברתיות</string> + <string name="home_category_support_us">תמכו בנו</string> <string name="app_content_unavailable">לא זמין</string> <string name="version_installed">מותקן:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">שחור</string> <string name="app_theme_dialog_option_dark">שחרחר</string> <!-- About Page --> - <string name="about_credits_manager_devs">מנהל למפתחים</string> - <string name="about_credits_other">תורמים אחרים</string> - <string name="about_sources">מקורות</string> - <string name="about_credits_vanced_team">צוות Vanced</string> + <string name="about_category_credits_manager_devs">מנהל למפתחים</string> + <string name="about_category_credits_other">תורמים אחרים</string> + <string name="about_category_sources">מקורות</string> + <string name="about_category_credits_vanced_team">צוות Vanced</string> <!-- Error messages --> <string name="install_error_chown_fail">נכשל בהחלפת הבעלים של קובץ ה־APK, אנא נסה בשנית.</string> <string name="install_error_downloading">תקלה בהורדה של %1$s</string> diff --git a/app/src/main/res/values-ja-rJP/strings.xml b/app/src/main/res/values-ja-rJP/strings.xml index 06b55d186b..17b1acdde4 100644 --- a/app/src/main/res/values-ja-rJP/strings.xml +++ b/app/src/main/res/values-ja-rJP/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">アプリ</string> + <string name="home_category_apps">アプリ</string> <string name="app_info_changelog_header">更新履歴</string> <string name="app_download_dialog_downloading_file">%1$s をダウンロードしています</string> <string name="app_options_install">インストール</string> <string name="latest">最新版:</string> <string name="app_microg_error">はじめに Vanced microG をインストールしてください</string> <string name="root_not_granted">Root アクセスは許可されていません</string> - <string name="home_header_social_media">ソーシャルメディア</string> - <string name="home_header_support_us">サポート</string> + <string name="home_category_social_media">ソーシャルメディア</string> + <string name="home_category_support_us">サポート</string> <string name="app_content_unavailable">利用不可</string> <string name="version_installed">インストール済み:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">ブラック</string> <string name="app_theme_dialog_option_dark">ダーク</string> <!-- About Page --> - <string name="about_credits_manager_devs">Manager 開発</string> - <string name="about_credits_other">他の貢献者</string> - <string name="about_sources">ソースコード</string> - <string name="about_credits_vanced_team">Vanced チーム</string> + <string name="about_category_credits_manager_devs">Manager 開発</string> + <string name="about_category_credits_other">他の貢献者</string> + <string name="about_category_sources">ソースコード</string> + <string name="about_category_credits_vanced_team">Vanced チーム</string> <!-- Error messages --> <string name="install_error_chown_fail">システム所有者への APK の Chown ができませんでした、もう一度やり直してください.</string> <string name="install_error_downloading">%1$s のダウンロード中にエラー</string> diff --git a/app/src/main/res/values-ka-rGE/strings.xml b/app/src/main/res/values-ka-rGE/strings.xml index a995bfbaa6..e85739a3aa 100644 --- a/app/src/main/res/values-ka-rGE/strings.xml +++ b/app/src/main/res/values-ka-rGE/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">რეინსტალაცია</string> <string name="accessibility_app_uninstall">დეინსტალაცია</string> <string name="accessibility_app_update">განახლება</string> - <string name="home_header_apps">აპები</string> + <string name="home_category_apps">აპები</string> <string name="app_info_changelog_header">ცვლილებები</string> <string name="app_download_dialog_downloading_file">მიმდინარეობს %1$s-ის გადმოწერა</string> <string name="app_options_install">ინსტალაცია</string> <string name="latest">უახლესი:</string> <string name="app_microg_error">Install Vanced microG first</string> <string name="root_not_granted">Root წვდომა არ არის მინიჭებული</string> - <string name="home_header_social_media">სოციალური მედია</string> - <string name="home_header_support_us">დაგვიჭირეთ მხარი</string> + <string name="home_category_social_media">სოციალური მედია</string> + <string name="home_category_support_us">დაგვიჭირეთ მხარი</string> <string name="app_content_unavailable">ხელმიუწვდომელია</string> <string name="version_installed">დაინსტალირებული:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">შავი</string> <string name="app_theme_dialog_option_dark">მუქი</string> <!-- About Page --> - <string name="about_credits_manager_devs">Manager-ის დეველოპერები</string> - <string name="about_credits_other">Other Contributors</string> - <string name="about_sources">წყაროები</string> - <string name="about_credits_vanced_team">Vanced-ის გუნდი</string> + <string name="about_category_credits_manager_devs">Manager-ის დეველოპერები</string> + <string name="about_category_credits_other">Other Contributors</string> + <string name="about_category_sources">წყაროები</string> + <string name="about_category_credits_vanced_team">Vanced-ის გუნდი</string> <!-- Error messages --> <string name="install_error_chown_fail">`chown`-ის დროს მოხდა შეცდომა, გთცოვთ სცადოთ თავიდან.</string> <string name="install_error_downloading">შეცდომა %1$s-ის გადმოწერის დროს</string> diff --git a/app/src/main/res/values-kmr-rTR/strings.xml b/app/src/main/res/values-kmr-rTR/strings.xml index 8f6612ddf4..5b9440f3aa 100644 --- a/app/src/main/res/values-kmr-rTR/strings.xml +++ b/app/src/main/res/values-kmr-rTR/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Sepanan</string> + <string name="home_category_apps">Sepanan</string> <string name="app_info_changelog_header">Gurankarî</string> <string name="app_download_dialog_downloading_file">Dakêşe %1$s</string> <string name="app_options_install">Saz bike</string> <string name="latest">Dawîn:</string> <string name="app_microg_error">Pêşîn Vanced microG saz bikin</string> <string name="root_not_granted">Destlênedanên kokê nayê dayîn</string> - <string name="home_header_social_media">Medyaya Civakî</string> - <string name="home_header_support_us">Piştgiriya me bikin</string> + <string name="home_category_social_media">Medyaya Civakî</string> + <string name="home_category_support_us">Piştgiriya me bikin</string> <string name="app_content_unavailable">Neberdest</string> <string name="version_installed">Sazkirî:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Reş</string> <string name="app_theme_dialog_option_dark">Tarî</string> <!-- About Page --> - <string name="about_credits_manager_devs">Pêşvebirên Rêveberê</string> - <string name="about_credits_other">Beşdarên din</string> - <string name="about_sources">Çavkanî</string> - <string name="about_credits_vanced_team">Koma Vanced\'ê</string> + <string name="about_category_credits_manager_devs">Pêşvebirên Rêveberê</string> + <string name="about_category_credits_other">Beşdarên din</string> + <string name="about_category_sources">Çavkanî</string> + <string name="about_category_credits_vanced_team">Koma Vanced\'ê</string> <!-- Error messages --> <string name="install_error_chown_fail">APK\'yê ji xwediyê pergalê re \'chown\' bi ser neket, ji kerema xwe re careke din biceribînin.</string> <string name="install_error_downloading">Di daxistina %1$s de çewtî</string> diff --git a/app/src/main/res/values-ko-rKR/strings.xml b/app/src/main/res/values-ko-rKR/strings.xml index 9339dd6227..21c57d4694 100644 --- a/app/src/main/res/values-ko-rKR/strings.xml +++ b/app/src/main/res/values-ko-rKR/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">재설치</string> <string name="accessibility_app_uninstall">제거</string> <string name="accessibility_app_update">업데이트</string> - <string name="home_header_apps">앱</string> + <string name="home_category_apps">앱</string> <string name="app_info_changelog_header">변경 사항</string> <string name="app_download_dialog_downloading_file">%1$s 다운로드 중</string> <string name="app_options_install">설치</string> <string name="latest">최신:</string> <string name="app_microg_error">Vanced microG를 우선 설치하십시오</string> <string name="root_not_granted">루트 권한이 부여되지 않았습니다</string> - <string name="home_header_social_media">소셜 미디어</string> - <string name="home_header_support_us">지원하기</string> + <string name="home_category_social_media">소셜 미디어</string> + <string name="home_category_support_us">지원하기</string> <string name="app_content_unavailable">사용 불가</string> <string name="version_installed">설치됨:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">검정</string> <string name="app_theme_dialog_option_dark">다크</string> <!-- About Page --> - <string name="about_credits_manager_devs">Manager 개발자</string> - <string name="about_credits_other">기타 기여자</string> - <string name="about_sources">소스 코드</string> - <string name="about_credits_vanced_team">Vanced 팀</string> + <string name="about_category_credits_manager_devs">Manager 개발자</string> + <string name="about_category_credits_other">기타 기여자</string> + <string name="about_category_sources">소스 코드</string> + <string name="about_category_credits_vanced_team">Vanced 팀</string> <!-- Error messages --> <string name="install_error_chown_fail">APK의 소유권을 시스템 관리자로 변경하던 중에 오류가 발생하였습니다. 다시 시도하십시오.</string> <string name="install_error_downloading">%1$s 다운로드 중 오류 발생</string> diff --git a/app/src/main/res/values-ku-rTR/strings.xml b/app/src/main/res/values-ku-rTR/strings.xml index 99703e60b2..fcbddb040d 100644 --- a/app/src/main/res/values-ku-rTR/strings.xml +++ b/app/src/main/res/values-ku-rTR/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Apps</string> + <string name="home_category_apps">Apps</string> <string name="app_info_changelog_header">Guherîn</string> <string name="app_download_dialog_downloading_file">Tê daxistin %1$s</string> <string name="app_options_install">Saz bike</string> <string name="latest">Dawîn:</string> <string name="app_microg_error">Install Vanced microG first</string> <string name="root_not_granted">Rê li gihana Root nehate dayîn</string> - <string name="home_header_social_media">Social Media</string> - <string name="home_header_support_us">Piştgiriya me bike</string> + <string name="home_category_social_media">Social Media</string> + <string name="home_category_support_us">Piştgiriya me bike</string> <string name="app_content_unavailable">Berdest nîne</string> <string name="version_installed">Saz bike:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Reş</string> <string name="app_theme_dialog_option_dark">Tarî</string> <!-- About Page --> - <string name="about_credits_manager_devs">Pêşvebirên rêveberê</string> - <string name="about_credits_other">Other Contributors</string> - <string name="about_sources">Çavkanî</string> - <string name="about_credits_vanced_team">Koma Vanced\'ê</string> + <string name="about_category_credits_manager_devs">Pêşvebirên rêveberê</string> + <string name="about_category_credits_other">Other Contributors</string> + <string name="about_category_sources">Çavkanî</string> + <string name="about_category_credits_vanced_team">Koma Vanced\'ê</string> <!-- Error messages --> <string name="install_error_chown_fail">\'Chown\' apk ji xwediyê sîstemê re bi ser neket, jkx dîsa biceribîne.</string> <string name="install_error_downloading">Çewtiya daxistinê %1$s</string> diff --git a/app/src/main/res/values-lt-rLT/strings.xml b/app/src/main/res/values-lt-rLT/strings.xml index 212dc55ef4..7d697f5571 100644 --- a/app/src/main/res/values-lt-rLT/strings.xml +++ b/app/src/main/res/values-lt-rLT/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Apps</string> + <string name="home_category_apps">Apps</string> <string name="app_info_changelog_header">Changelog</string> <string name="app_download_dialog_downloading_file">Downloading %1$s</string> <string name="app_options_install">Install</string> <string name="latest">Latest:</string> <string name="app_microg_error">Install Vanced microG first</string> <string name="root_not_granted">Root access not granted</string> - <string name="home_header_social_media">Social Media</string> - <string name="home_header_support_us">Support us</string> + <string name="home_category_social_media">Social Media</string> + <string name="home_category_support_us">Support us</string> <string name="app_content_unavailable">Unavailable</string> <string name="version_installed">Installed:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Black</string> <string name="app_theme_dialog_option_dark">Dark</string> <!-- About Page --> - <string name="about_credits_manager_devs">Manager Devs</string> - <string name="about_credits_other">Other Contributors</string> - <string name="about_sources">Sources</string> - <string name="about_credits_vanced_team">Vanced Team</string> + <string name="about_category_credits_manager_devs">Manager Devs</string> + <string name="about_category_credits_other">Other Contributors</string> + <string name="about_category_sources">Sources</string> + <string name="about_category_credits_vanced_team">Vanced Team</string> <!-- Error messages --> <string name="install_error_chown_fail">Failed to `chown` APK to system owner, please try again.</string> <string name="install_error_downloading">Error Downloading %1$s</string> diff --git a/app/src/main/res/values-ml-rIN/strings.xml b/app/src/main/res/values-ml-rIN/strings.xml index 79dd22d7c8..a1e2e9953c 100644 --- a/app/src/main/res/values-ml-rIN/strings.xml +++ b/app/src/main/res/values-ml-rIN/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">അപ്ലിക്കേഷനുകൾ</string> + <string name="home_category_apps">അപ്ലിക്കേഷനുകൾ</string> <string name="app_info_changelog_header">ചേഞ്ച് ലോഗ്</string> <string name="app_download_dialog_downloading_file">%1$s ഡൗൺലോഡ് ചെയ്യുന്നു</string> <string name="app_options_install">ഇൻസ്റ്റാൾ ചെയ്യുക</string> <string name="latest">ഏറ്റവും പുതിയത്:</string> <string name="app_microg_error">ആധ്യം വാൻസ്ഡ് മൈക്രോ-ജി ഇൻസ്റ്റാൾ ചെയ്യുക്ക</string> <string name="root_not_granted">റൂട്ട് ആക്സസ് അനുവദിച്ചിട്ടില്ല</string> - <string name="home_header_social_media">സോഷ്യൽ മീഡിയ</string> - <string name="home_header_support_us">ഞങ്ങളെ പിന്തുണയ്ക്കുക</string> + <string name="home_category_social_media">സോഷ്യൽ മീഡിയ</string> + <string name="home_category_support_us">ഞങ്ങളെ പിന്തുണയ്ക്കുക</string> <string name="app_content_unavailable">ലഭ്യമല്ല</string> <string name="version_installed">ഇൻസ്റ്റാൾ ചെയ്തു:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">കറുപ്പ്</string> <string name="app_theme_dialog_option_dark">ഇരുണ്ടത്</string> <!-- About Page --> - <string name="about_credits_manager_devs">മാനേജർ ഡവലപ്പർമാർ</string> - <string name="about_credits_other">മറ്റ് സംഭാവകർ</string> - <string name="about_sources">ഉറവിടങ്ങൾ</string> - <string name="about_credits_vanced_team">വാൻ‌സ്ഡ് ടീം</string> + <string name="about_category_credits_manager_devs">മാനേജർ ഡവലപ്പർമാർ</string> + <string name="about_category_credits_other">മറ്റ് സംഭാവകർ</string> + <string name="about_category_sources">ഉറവിടങ്ങൾ</string> + <string name="about_category_credits_vanced_team">വാൻ‌സ്ഡ് ടീം</string> <!-- Error messages --> <string name="install_error_chown_fail">സിസ്റ്റം ഉടമയ്‌ക്ക് APK `chown` ചെയ്യുന്നതിൽ പരാജയപ്പെട്ടു, ദയവായി വീണ്ടും ശ്രമിക്കുക.</string> <string name="install_error_downloading">%1$s ഡൗൺലോഡുചെയ്യുന്നതിൽ പിശക്</string> diff --git a/app/src/main/res/values-mr-rIN/strings.xml b/app/src/main/res/values-mr-rIN/strings.xml index 78ec99fed8..13a8602c7f 100644 --- a/app/src/main/res/values-mr-rIN/strings.xml +++ b/app/src/main/res/values-mr-rIN/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Apps</string> + <string name="home_category_apps">Apps</string> <string name="app_info_changelog_header">Changelog</string> <string name="app_download_dialog_downloading_file">Downloading %1$s</string> <string name="app_options_install">Install</string> <string name="latest">Latest:</string> <string name="app_microg_error">Install Vanced microG first</string> <string name="root_not_granted">Root access not granted</string> - <string name="home_header_social_media">Social Media</string> - <string name="home_header_support_us">Support us</string> + <string name="home_category_social_media">Social Media</string> + <string name="home_category_support_us">Support us</string> <string name="app_content_unavailable">Unavailable</string> <string name="version_installed">Installed:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Black</string> <string name="app_theme_dialog_option_dark">Dark</string> <!-- About Page --> - <string name="about_credits_manager_devs">Manager Devs</string> - <string name="about_credits_other">Other Contributors</string> - <string name="about_sources">Sources</string> - <string name="about_credits_vanced_team">Vanced Team</string> + <string name="about_category_credits_manager_devs">Manager Devs</string> + <string name="about_category_credits_other">Other Contributors</string> + <string name="about_category_sources">Sources</string> + <string name="about_category_credits_vanced_team">Vanced Team</string> <!-- Error messages --> <string name="install_error_chown_fail">Failed to `chown` APK to system owner, please try again.</string> <string name="install_error_downloading">Error Downloading %1$s</string> diff --git a/app/src/main/res/values-nl-rNL/strings.xml b/app/src/main/res/values-nl-rNL/strings.xml index e0e0ea327d..e06ea290b6 100644 --- a/app/src/main/res/values-nl-rNL/strings.xml +++ b/app/src/main/res/values-nl-rNL/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Herinstalleren</string> <string name="accessibility_app_uninstall">Verwijderen</string> <string name="accessibility_app_update">Bijwerken</string> - <string name="home_header_apps">Apps</string> + <string name="home_category_apps">Apps</string> <string name="app_info_changelog_header">Wijzigingen</string> <string name="app_download_dialog_downloading_file">%1$s downloaden</string> <string name="app_options_install">Installeren</string> <string name="latest">Recentste:</string> <string name="app_microg_error">Installeer eerst Vanced microG</string> <string name="root_not_granted">Root machtiging niet toegestaan</string> - <string name="home_header_social_media">Sociale media</string> - <string name="home_header_support_us">Steun ons</string> + <string name="home_category_social_media">Sociale media</string> + <string name="home_category_support_us">Steun ons</string> <string name="app_content_unavailable">Niet beschikbaar</string> <string name="version_installed">Geïnstalleerd:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Zwart</string> <string name="app_theme_dialog_option_dark">Donker</string> <!-- About Page --> - <string name="about_credits_manager_devs">Ontwikkelaars Manager</string> - <string name="about_credits_other">Andere bijdrages</string> - <string name="about_sources">Bronnen</string> - <string name="about_credits_vanced_team">Vanced Team</string> + <string name="about_category_credits_manager_devs">Ontwikkelaars Manager</string> + <string name="about_category_credits_other">Andere bijdrages</string> + <string name="about_category_sources">Bronnen</string> + <string name="about_category_credits_vanced_team">Vanced Team</string> <!-- Error messages --> <string name="install_error_chown_fail">Wijzigen van APK-eigenaar naar systeemeigenaar mislukt. Probeer het opnieuw.</string> <string name="install_error_downloading">Fout bij downloaden van %1$s</string> diff --git a/app/src/main/res/values-no-rNO/strings.xml b/app/src/main/res/values-no-rNO/strings.xml index ba1df538fa..60239efb26 100644 --- a/app/src/main/res/values-no-rNO/strings.xml +++ b/app/src/main/res/values-no-rNO/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Apper</string> + <string name="home_category_apps">Apper</string> <string name="app_info_changelog_header">Endringslogg</string> <string name="app_download_dialog_downloading_file">Laster ned %1$s</string> <string name="app_options_install">Installer</string> <string name="latest">Siste:</string> <string name="app_microg_error">Installer Vanced microG først</string> <string name="root_not_granted">Root-tilgang ikke godkjent</string> - <string name="home_header_social_media">Sosiale Medier</string> - <string name="home_header_support_us">Støtt oss</string> + <string name="home_category_social_media">Sosiale Medier</string> + <string name="home_category_support_us">Støtt oss</string> <string name="app_content_unavailable">Utilgjengelig</string> <string name="version_installed">Installert:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Black</string> <string name="app_theme_dialog_option_dark">Dark</string> <!-- About Page --> - <string name="about_credits_manager_devs">Manager Devs</string> - <string name="about_credits_other">Other Contributors</string> - <string name="about_sources">Kilder</string> - <string name="about_credits_vanced_team">Vanced Team</string> + <string name="about_category_credits_manager_devs">Manager Devs</string> + <string name="about_category_credits_other">Other Contributors</string> + <string name="about_category_sources">Kilder</string> + <string name="about_category_credits_vanced_team">Vanced Team</string> <!-- Error messages --> <string name="install_error_chown_fail">Kan ikke `chown` APK til systemeieren, vennligst prøv igjen.</string> <string name="install_error_downloading">Feil ved nedlasting %1$s</string> diff --git a/app/src/main/res/values-pa-rIN/strings.xml b/app/src/main/res/values-pa-rIN/strings.xml index 3a8ec06c43..3c274c089b 100644 --- a/app/src/main/res/values-pa-rIN/strings.xml +++ b/app/src/main/res/values-pa-rIN/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Apps</string> + <string name="home_category_apps">Apps</string> <string name="app_info_changelog_header">ਤਬਦੀਲੀਆਂ</string> <string name="app_download_dialog_downloading_file">ਡਾਊਨਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ %1$s</string> <string name="app_options_install">ਸਥਾਪਨਾ</string> <string name="latest">ਨਵੀਨਤਮ:</string> <string name="app_microg_error">Install Vanced microG first</string> <string name="root_not_granted">ਰੂਟ ਐਕਸੈਸ ਨਹੀਂ ਦਿੱਤੀ ਗਈ</string> - <string name="home_header_social_media">ਸੋਸ਼ਲ ਮੀਡੀਆ</string> - <string name="home_header_support_us">ਸਾਡਾ ਸਮਰਥਨ ਕਰੋ</string> + <string name="home_category_social_media">ਸੋਸ਼ਲ ਮੀਡੀਆ</string> + <string name="home_category_support_us">ਸਾਡਾ ਸਮਰਥਨ ਕਰੋ</string> <string name="app_content_unavailable">ਮੋਜੂਦ ਨਹੀਂ ਹੈ</string> <string name="version_installed">ਸਥਾਪਿਤ:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Black</string> <string name="app_theme_dialog_option_dark">Dark</string> <!-- About Page --> - <string name="about_credits_manager_devs">ਪ੍ਬੰਧਕ ਨਿਰਮਾਣਕਰਤਾ</string> - <string name="about_credits_other">Other Contributors</string> - <string name="about_sources">ਸਰੋਤ</string> - <string name="about_credits_vanced_team">Vanced ਟੋਲੀ</string> + <string name="about_category_credits_manager_devs">ਪ੍ਬੰਧਕ ਨਿਰਮਾਣਕਰਤਾ</string> + <string name="about_category_credits_other">Other Contributors</string> + <string name="about_category_sources">ਸਰੋਤ</string> + <string name="about_category_credits_vanced_team">Vanced ਟੋਲੀ</string> <!-- Error messages --> <string name="install_error_chown_fail">ਸਿਸਟਮ ਦੇ ਮਾਲਕ ਨੂੰ APK ਨੂੰ `chown` ਕਰਨ ਵਿੱਚ ਨਾਕਾਮ, ਫਿਰ ਤੋਂ ਕੋਸ਼ਿਸ਼ ਕਰੋ.</string> <string name="install_error_downloading">ਡਾਉਨਲੋਡ ਕਰਨ ਦੌਰਾਨ ਗਲਤੀ %1$s</string> diff --git a/app/src/main/res/values-pa-rPK/strings.xml b/app/src/main/res/values-pa-rPK/strings.xml index 212dc55ef4..7d697f5571 100644 --- a/app/src/main/res/values-pa-rPK/strings.xml +++ b/app/src/main/res/values-pa-rPK/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Apps</string> + <string name="home_category_apps">Apps</string> <string name="app_info_changelog_header">Changelog</string> <string name="app_download_dialog_downloading_file">Downloading %1$s</string> <string name="app_options_install">Install</string> <string name="latest">Latest:</string> <string name="app_microg_error">Install Vanced microG first</string> <string name="root_not_granted">Root access not granted</string> - <string name="home_header_social_media">Social Media</string> - <string name="home_header_support_us">Support us</string> + <string name="home_category_social_media">Social Media</string> + <string name="home_category_support_us">Support us</string> <string name="app_content_unavailable">Unavailable</string> <string name="version_installed">Installed:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Black</string> <string name="app_theme_dialog_option_dark">Dark</string> <!-- About Page --> - <string name="about_credits_manager_devs">Manager Devs</string> - <string name="about_credits_other">Other Contributors</string> - <string name="about_sources">Sources</string> - <string name="about_credits_vanced_team">Vanced Team</string> + <string name="about_category_credits_manager_devs">Manager Devs</string> + <string name="about_category_credits_other">Other Contributors</string> + <string name="about_category_sources">Sources</string> + <string name="about_category_credits_vanced_team">Vanced Team</string> <!-- Error messages --> <string name="install_error_chown_fail">Failed to `chown` APK to system owner, please try again.</string> <string name="install_error_downloading">Error Downloading %1$s</string> diff --git a/app/src/main/res/values-pl-rPL/strings.xml b/app/src/main/res/values-pl-rPL/strings.xml index e1d2bc3858..78472c42da 100644 --- a/app/src/main/res/values-pl-rPL/strings.xml +++ b/app/src/main/res/values-pl-rPL/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Przeinstaluj</string> <string name="accessibility_app_uninstall">Odinstaluj</string> <string name="accessibility_app_update">Aktualizuj</string> - <string name="home_header_apps">Aplikacje</string> + <string name="home_category_apps">Aplikacje</string> <string name="app_info_changelog_header">Lista zmian</string> <string name="app_download_dialog_downloading_file">Pobieranie %1$s</string> <string name="app_options_install">Zainstaluj</string> <string name="latest">Najnowsza:</string> <string name="app_microg_error">Najpierw zainstaluj Vanced microG</string> <string name="root_not_granted">Root nie został przyznany</string> - <string name="home_header_social_media">Media Społecznościowe</string> - <string name="home_header_support_us">Wesprzyj nas</string> + <string name="home_category_social_media">Media Społecznościowe</string> + <string name="home_category_support_us">Wesprzyj nas</string> <string name="app_content_unavailable">Niedostępne</string> <string name="version_installed">Zainstalowano:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Czarny</string> <string name="app_theme_dialog_option_dark">Ciemny</string> <!-- About Page --> - <string name="about_credits_manager_devs">Deweloperzy Menedżera</string> - <string name="about_credits_other">Inni współtwórcy</string> - <string name="about_sources">Źródła</string> - <string name="about_credits_vanced_team">Zespół Vanced</string> + <string name="about_category_credits_manager_devs">Deweloperzy Menedżera</string> + <string name="about_category_credits_other">Inni współtwórcy</string> + <string name="about_category_sources">Źródła</string> + <string name="about_category_credits_vanced_team">Zespół Vanced</string> <!-- Error messages --> <string name="install_error_chown_fail">Nie udało się `chown` APK dla właściciela systemu, spróbuj ponownie.</string> <string name="install_error_downloading">Błąd pobierania %1$s</string> diff --git a/app/src/main/res/values-ps-rAF/strings.xml b/app/src/main/res/values-ps-rAF/strings.xml index 212dc55ef4..7d697f5571 100644 --- a/app/src/main/res/values-ps-rAF/strings.xml +++ b/app/src/main/res/values-ps-rAF/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Apps</string> + <string name="home_category_apps">Apps</string> <string name="app_info_changelog_header">Changelog</string> <string name="app_download_dialog_downloading_file">Downloading %1$s</string> <string name="app_options_install">Install</string> <string name="latest">Latest:</string> <string name="app_microg_error">Install Vanced microG first</string> <string name="root_not_granted">Root access not granted</string> - <string name="home_header_social_media">Social Media</string> - <string name="home_header_support_us">Support us</string> + <string name="home_category_social_media">Social Media</string> + <string name="home_category_support_us">Support us</string> <string name="app_content_unavailable">Unavailable</string> <string name="version_installed">Installed:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Black</string> <string name="app_theme_dialog_option_dark">Dark</string> <!-- About Page --> - <string name="about_credits_manager_devs">Manager Devs</string> - <string name="about_credits_other">Other Contributors</string> - <string name="about_sources">Sources</string> - <string name="about_credits_vanced_team">Vanced Team</string> + <string name="about_category_credits_manager_devs">Manager Devs</string> + <string name="about_category_credits_other">Other Contributors</string> + <string name="about_category_sources">Sources</string> + <string name="about_category_credits_vanced_team">Vanced Team</string> <!-- Error messages --> <string name="install_error_chown_fail">Failed to `chown` APK to system owner, please try again.</string> <string name="install_error_downloading">Error Downloading %1$s</string> diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 19504ec17f..8b94184bff 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstalar</string> <string name="accessibility_app_uninstall">Desinstalar</string> <string name="accessibility_app_update">Atualizar</string> - <string name="home_header_apps">Aplicativos</string> + <string name="home_category_apps">Aplicativos</string> <string name="app_info_changelog_header">Registro de mudanças</string> <string name="app_download_dialog_downloading_file">Baixando %1$s</string> <string name="app_options_install">Instalar</string> <string name="latest">Mais recente:</string> <string name="app_microg_error">Instale o microG Vanced primeiro</string> <string name="root_not_granted">Acesso root não concedido</string> - <string name="home_header_social_media">Mídias Sociais</string> - <string name="home_header_support_us">Apoie-nos</string> + <string name="home_category_social_media">Mídias Sociais</string> + <string name="home_category_support_us">Apoie-nos</string> <string name="app_content_unavailable">Indisponível</string> <string name="version_installed">Instalado:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Preto</string> <string name="app_theme_dialog_option_dark">Escuro</string> <!-- About Page --> - <string name="about_credits_manager_devs">Desenvolvedores do Manager</string> - <string name="about_credits_other">Outros contribuidores</string> - <string name="about_sources">Fontes</string> - <string name="about_credits_vanced_team">Equipe Vanced</string> + <string name="about_category_credits_manager_devs">Desenvolvedores do Manager</string> + <string name="about_category_credits_other">Outros contribuidores</string> + <string name="about_category_sources">Fontes</string> + <string name="about_category_credits_vanced_team">Equipe Vanced</string> <!-- Error messages --> <string name="install_error_chown_fail">Falha ao enviar o Apk para o proprietário do sistema, Tente Novamente.</string> <string name="install_error_downloading">Erro ao baixar %1$s</string> diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 6d46e171c6..f02897f556 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Aplicações</string> + <string name="home_category_apps">Aplicações</string> <string name="app_info_changelog_header">Lista de alterações</string> <string name="app_download_dialog_downloading_file">Transferindo %1$s</string> <string name="app_options_install">Instalar</string> <string name="latest">Mais Recente:</string> <string name="app_microg_error">Instale o microG Vanced primeiro</string> <string name="root_not_granted">Acesso root negado.</string> - <string name="home_header_social_media">Redes Sociais</string> - <string name="home_header_support_us">Suporte-nos</string> + <string name="home_category_social_media">Redes Sociais</string> + <string name="home_category_support_us">Suporte-nos</string> <string name="app_content_unavailable">Indisponível</string> <string name="version_installed">Instalado:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Preto</string> <string name="app_theme_dialog_option_dark">Escuro</string> <!-- About Page --> - <string name="about_credits_manager_devs">Desenvolvedores do Manager</string> - <string name="about_credits_other">Outros Colaboradores</string> - <string name="about_sources">Fontes</string> - <string name="about_credits_vanced_team">Equipa Vanced</string> + <string name="about_category_credits_manager_devs">Desenvolvedores do Manager</string> + <string name="about_category_credits_other">Outros Colaboradores</string> + <string name="about_category_sources">Fontes</string> + <string name="about_category_credits_vanced_team">Equipa Vanced</string> <!-- Error messages --> <string name="install_error_chown_fail">Falhou na mudança de dono do Apk para o proprietário do sistema, por favor, tente novamente.</string> <string name="install_error_downloading">Erro Transferindo %1$s</string> diff --git a/app/src/main/res/values-ro-rRO/strings.xml b/app/src/main/res/values-ro-rRO/strings.xml index 40a6cfa1ac..5fa66bf3b0 100644 --- a/app/src/main/res/values-ro-rRO/strings.xml +++ b/app/src/main/res/values-ro-rRO/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Aplicații</string> + <string name="home_category_apps">Aplicații</string> <string name="app_info_changelog_header">Schimbări</string> <string name="app_download_dialog_downloading_file">Se descarcă %1$s</string> <string name="app_options_install">Instalează</string> <string name="latest">Ultima:</string> <string name="app_microg_error">Instalați Vanced microG mai întâi</string> <string name="root_not_granted">Accesul root nu este permis</string> - <string name="home_header_social_media">Rețele sociale</string> - <string name="home_header_support_us">Ajutați-ne</string> + <string name="home_category_social_media">Rețele sociale</string> + <string name="home_category_support_us">Ajutați-ne</string> <string name="app_content_unavailable">Indisponibil</string> <string name="version_installed">Instalat:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Negru</string> <string name="app_theme_dialog_option_dark">Întunecat</string> <!-- About Page --> - <string name="about_credits_manager_devs">Dezvoltatori</string> - <string name="about_credits_other">Alți Contribuitori</string> - <string name="about_sources">Surse</string> - <string name="about_credits_vanced_team">Echipa Vanced</string> + <string name="about_category_credits_manager_devs">Dezvoltatori</string> + <string name="about_category_credits_other">Alți Contribuitori</string> + <string name="about_category_sources">Surse</string> + <string name="about_category_credits_vanced_team">Echipa Vanced</string> <!-- Error messages --> <string name="install_error_chown_fail">Nu s-a reușit comanda chown pentru APK la proprietarul sistemului. Încercați din nou.</string> <string name="install_error_downloading">Eroare la descărcarea %1$s</string> diff --git a/app/src/main/res/values-ru-rRU/strings.xml b/app/src/main/res/values-ru-rRU/strings.xml index 8fc09dfcb4..7eb74ee8d0 100644 --- a/app/src/main/res/values-ru-rRU/strings.xml +++ b/app/src/main/res/values-ru-rRU/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Переустановить</string> <string name="accessibility_app_uninstall">Удалить</string> <string name="accessibility_app_update">Обновить</string> - <string name="home_header_apps">Приложения</string> + <string name="home_category_apps">Приложения</string> <string name="app_info_changelog_header">Список изменений</string> <string name="app_download_dialog_downloading_file">Загрузка %1$s</string> <string name="app_options_install">Установить</string> <string name="latest">Последняя:</string> <string name="app_microg_error">Сначала установите Vanced microG</string> <string name="root_not_granted">Рут-доступ не предоставлен</string> - <string name="home_header_social_media">Социальные сети</string> - <string name="home_header_support_us">Поддержите нас</string> + <string name="home_category_social_media">Социальные сети</string> + <string name="home_category_support_us">Поддержите нас</string> <string name="app_content_unavailable">Недоступно</string> <string name="version_installed">Установлена:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Черный</string> <string name="app_theme_dialog_option_dark">Темный</string> <!-- About Page --> - <string name="about_credits_manager_devs">Разработчики Менеджера</string> - <string name="about_credits_other">Другие участники</string> - <string name="about_sources">Исходники</string> - <string name="about_credits_vanced_team">Команда Vanced</string> + <string name="about_category_credits_manager_devs">Разработчики Менеджера</string> + <string name="about_category_credits_other">Другие участники</string> + <string name="about_category_sources">Исходники</string> + <string name="about_category_credits_vanced_team">Команда Vanced</string> <!-- Error messages --> <string name="install_error_chown_fail">Не удалось передать apk владельцу системы, попробуйте еще раз.</string> <string name="install_error_downloading">Ошибка загрузки %1$s</string> diff --git a/app/src/main/res/values-si-rLK/strings.xml b/app/src/main/res/values-si-rLK/strings.xml index d4dee3adcd..743585c862 100644 --- a/app/src/main/res/values-si-rLK/strings.xml +++ b/app/src/main/res/values-si-rLK/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Apps</string> + <string name="home_category_apps">Apps</string> <string name="app_info_changelog_header">Changelog</string> <string name="app_download_dialog_downloading_file">Downloading %1$s</string> <string name="app_options_install">ස්ථාපනය</string> <string name="latest">අලුත්</string> <string name="app_microg_error">Install Vanced microG first</string> <string name="root_not_granted">මූල ප්‍රවේශය ලබා දී නොමැත</string> - <string name="home_header_social_media">Social Media</string> - <string name="home_header_support_us">Support us</string> + <string name="home_category_social_media">Social Media</string> + <string name="home_category_support_us">Support us</string> <string name="app_content_unavailable">නොමැත</string> <string name="version_installed">ස්ථාපනය:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Black</string> <string name="app_theme_dialog_option_dark">Dark</string> <!-- About Page --> - <string name="about_credits_manager_devs">Manager Devs</string> - <string name="about_credits_other">Other Contributors</string> - <string name="about_sources">මූලාශ්‍ර</string> - <string name="about_credits_vanced_team">Vanced Team</string> + <string name="about_category_credits_manager_devs">Manager Devs</string> + <string name="about_category_credits_other">Other Contributors</string> + <string name="about_category_sources">මූලාශ්‍ර</string> + <string name="about_category_credits_vanced_team">Vanced Team</string> <!-- Error messages --> <string name="install_error_chown_fail">Failed to `chown` APK to system owner, please try again.</string> <string name="install_error_downloading">Error Downloading %1$s</string> diff --git a/app/src/main/res/values-sk-rSK/strings.xml b/app/src/main/res/values-sk-rSK/strings.xml index 8ad6999e60..3a37fb064d 100644 --- a/app/src/main/res/values-sk-rSK/strings.xml +++ b/app/src/main/res/values-sk-rSK/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Preinštalovať</string> <string name="accessibility_app_uninstall">Odinštalovať</string> <string name="accessibility_app_update">Aktualizovať</string> - <string name="home_header_apps">Aplikácie</string> + <string name="home_category_apps">Aplikácie</string> <string name="app_info_changelog_header">Zoznam zmien</string> <string name="app_download_dialog_downloading_file">Sťahovanie %1$s</string> <string name="app_options_install">Inštalovať</string> <string name="latest">Najnovšie:</string> <string name="app_microg_error">Najprv nainštalujte Vanced microG</string> <string name="root_not_granted">Root prístup nebol udelený</string> - <string name="home_header_social_media">Sociálne médiá</string> - <string name="home_header_support_us">Podporte nás</string> + <string name="home_category_social_media">Sociálne médiá</string> + <string name="home_category_support_us">Podporte nás</string> <string name="app_content_unavailable">Nedostupné</string> <string name="version_installed">Nainštalované:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Čierna</string> <string name="app_theme_dialog_option_dark">Tmavá</string> <!-- About Page --> - <string name="about_credits_manager_devs">Vývojári aplikácie</string> - <string name="about_credits_other">Ostatní prispievatelia</string> - <string name="about_sources">Zdrojové kódy</string> - <string name="about_credits_vanced_team">Tím Vanced</string> + <string name="about_category_credits_manager_devs">Vývojári aplikácie</string> + <string name="about_category_credits_other">Ostatní prispievatelia</string> + <string name="about_category_sources">Zdrojové kódy</string> + <string name="about_category_credits_vanced_team">Tím Vanced</string> <!-- Error messages --> <string name="install_error_chown_fail">Nepodarilo sa zmeniť vlastníka súboru APK na vlastníka systému. Skúste to znovu prosím.</string> <string name="install_error_downloading">Chyba pri sťahovaní %1$s</string> diff --git a/app/src/main/res/values-so-rSO/strings.xml b/app/src/main/res/values-so-rSO/strings.xml index 6bed32e9df..92d17a0c17 100644 --- a/app/src/main/res/values-so-rSO/strings.xml +++ b/app/src/main/res/values-so-rSO/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Apps</string> + <string name="home_category_apps">Apps</string> <string name="app_info_changelog_header">Waxa isbadalay</string> <string name="app_download_dialog_downloading_file">Dajinaya %1$s</string> <string name="app_options_install">Kushub</string> <string name="latest">U dambeeyay:</string> <string name="app_microg_error">Install Vanced microG first</string> <string name="root_not_granted">\'Root\' looma fasaxin</string> - <string name="home_header_social_media">Baraha Bulshada</string> - <string name="home_header_support_us">Na taageer</string> + <string name="home_category_social_media">Baraha Bulshada</string> + <string name="home_category_support_us">Na taageer</string> <string name="app_content_unavailable">Lama heli karo</string> <string name="version_installed">Ka kujira:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Black</string> <string name="app_theme_dialog_option_dark">Dark</string> <!-- About Page --> - <string name="about_credits_manager_devs">Sameeyaasha Manager-ka</string> - <string name="about_credits_other">Other Contributors</string> - <string name="about_sources">Tixraacyo</string> - <string name="about_credits_vanced_team">Kooxda Vanced</string> + <string name="about_category_credits_manager_devs">Sameeyaasha Manager-ka</string> + <string name="about_category_credits_other">Other Contributors</string> + <string name="about_category_sources">Tixraacyo</string> + <string name="about_category_credits_vanced_team">Kooxda Vanced</string> <!-- Error messages --> <string name="install_error_chown_fail">Laguma guulaysan in APK-ga `mulkiilihiisa loo badalo` barnaamijka aaladu kushaqayso, fadlan markale kuceli.</string> <string name="install_error_downloading">Khalad ayaa ka dhacay soo dajintii %1$s</string> diff --git a/app/src/main/res/values-sr-rSP/strings.xml b/app/src/main/res/values-sr-rSP/strings.xml index d23f364fcf..d18bc535a4 100644 --- a/app/src/main/res/values-sr-rSP/strings.xml +++ b/app/src/main/res/values-sr-rSP/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Деинсталирај</string> <string name="accessibility_app_update">Ажурирај</string> - <string name="home_header_apps">Апликације</string> + <string name="home_category_apps">Апликације</string> <string name="app_info_changelog_header">Историја измена</string> <string name="app_download_dialog_downloading_file">Преузимање %1$s</string> <string name="app_options_install">Инсталација</string> <string name="latest">Најновија:</string> <string name="app_microg_error">Инсталирајте прво Vanced microG</string> <string name="root_not_granted">Root приступ није омогућен</string> - <string name="home_header_social_media">Социјалне мреже</string> - <string name="home_header_support_us">Подржите нас</string> + <string name="home_category_social_media">Социјалне мреже</string> + <string name="home_category_support_us">Подржите нас</string> <string name="app_content_unavailable">Недоступно</string> <string name="version_installed">Инсталирана:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Црно</string> <string name="app_theme_dialog_option_dark">Тамно</string> <!-- About Page --> - <string name="about_credits_manager_devs">Менаџер развоја</string> - <string name="about_credits_other">Други покровитељи</string> - <string name="about_sources">Извор</string> - <string name="about_credits_vanced_team">Vanced Тим</string> + <string name="about_category_credits_manager_devs">Менаџер развоја</string> + <string name="about_category_credits_other">Други покровитељи</string> + <string name="about_category_sources">Извор</string> + <string name="about_category_credits_vanced_team">Vanced Тим</string> <!-- Error messages --> <string name="install_error_chown_fail">Грешка при додели apk власнику система, покушајте поново.</string> <string name="install_error_downloading">Грешка приликом преузимања %1$s</string> diff --git a/app/src/main/res/values-sv-rSE/strings.xml b/app/src/main/res/values-sv-rSE/strings.xml index b33bb7f250..9a1ddbfc8d 100644 --- a/app/src/main/res/values-sv-rSE/strings.xml +++ b/app/src/main/res/values-sv-rSE/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Appar</string> + <string name="home_category_apps">Appar</string> <string name="app_info_changelog_header">Ändringslogg</string> <string name="app_download_dialog_downloading_file">Laddar ned %1$s</string> <string name="app_options_install">Install</string> <string name="latest">Senaste:</string> <string name="app_microg_error">Installera Vanced microG först</string> <string name="root_not_granted">Root-åtkomst inte beviljat</string> - <string name="home_header_social_media">Sociala medier</string> - <string name="home_header_support_us">Stöd oss</string> + <string name="home_category_social_media">Sociala medier</string> + <string name="home_category_support_us">Stöd oss</string> <string name="app_content_unavailable">Ej tillgänglig</string> <string name="version_installed">Installerad:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Svart</string> <string name="app_theme_dialog_option_dark">Mörk</string> <!-- About Page --> - <string name="about_credits_manager_devs">Hanteraren Dev</string> - <string name="about_credits_other">Andra bidragsgivare</string> - <string name="about_sources">Källor</string> - <string name="about_credits_vanced_team">Vanced Team</string> + <string name="about_category_credits_manager_devs">Hanteraren Dev</string> + <string name="about_category_credits_other">Andra bidragsgivare</string> + <string name="about_category_sources">Källor</string> + <string name="about_category_credits_vanced_team">Vanced Team</string> <!-- Error messages --> <string name="install_error_chown_fail">Misslyckades att Chown Apk till systemägare, Försök igen.</string> <string name="install_error_downloading">Laddar ned %1$s</string> diff --git a/app/src/main/res/values-ta-rIN/strings.xml b/app/src/main/res/values-ta-rIN/strings.xml index e5e6228039..7bd81c6b48 100644 --- a/app/src/main/res/values-ta-rIN/strings.xml +++ b/app/src/main/res/values-ta-rIN/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Uninstall</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">பயன்பாடுகள்</string> + <string name="home_category_apps">பயன்பாடுகள்</string> <string name="app_info_changelog_header">சேஞ்ச்லாக்</string> <string name="app_download_dialog_downloading_file">%1$s ஐப் பதிவிறக்குகிறது</string> <string name="app_options_install">நிறுவு</string> <string name="latest">சமீபத்தியது:</string> <string name="app_microg_error">முதலில் Vanced Microg ஐ நிறுவவும்</string> <string name="root_not_granted">ரூட் அக்சஸ் வழங்கப்படவில்லை</string> - <string name="home_header_social_media">சமூக ஊடகம்</string> - <string name="home_header_support_us">எங்களை ஆதரியுங்கள்</string> + <string name="home_category_social_media">சமூக ஊடகம்</string> + <string name="home_category_support_us">எங்களை ஆதரியுங்கள்</string> <string name="app_content_unavailable">கிடைக்கவில்லை</string> <string name="version_installed">நிறுவப்பட்டது:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">கருப்பு</string> <string name="app_theme_dialog_option_dark">இருள்</string> <!-- About Page --> - <string name="about_credits_manager_devs">மேலாளர் டெவலப்பர்கள்</string> - <string name="about_credits_other">பிற பங்களிப்பாளர்கள்</string> - <string name="about_sources">மூலம்</string> - <string name="about_credits_vanced_team">Vanced கூட்டணி</string> + <string name="about_category_credits_manager_devs">மேலாளர் டெவலப்பர்கள்</string> + <string name="about_category_credits_other">பிற பங்களிப்பாளர்கள்</string> + <string name="about_category_sources">மூலம்</string> + <string name="about_category_credits_vanced_team">Vanced கூட்டணி</string> <!-- Error messages --> <string name="install_error_chown_fail">கணினி உரிமையாளருக்கு APK ஐத் தேடுவதில் தோல்வி, தயவுசெய்து மீண்டும் முயற்சிக்கவும்.</string> <string name="install_error_downloading">%1$s பதிவிறக்குவதில் தோழ்வி</string> diff --git a/app/src/main/res/values-th-rTH/strings.xml b/app/src/main/res/values-th-rTH/strings.xml index b48b43af35..d608e6c37b 100644 --- a/app/src/main/res/values-th-rTH/strings.xml +++ b/app/src/main/res/values-th-rTH/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">ถอนการติดตั้ง</string> <string name="accessibility_app_update">อัพเดท</string> - <string name="home_header_apps">แอป</string> + <string name="home_category_apps">แอป</string> <string name="app_info_changelog_header">บันทึกการเปลี่ยนแปลง</string> <string name="app_download_dialog_downloading_file">กำลังดาวน์โหลด %1$s</string> <string name="app_options_install">ติดตั้ง</string> <string name="latest">ล่าสุด:</string> <string name="app_microg_error">ติดตั้ง Vanced microG ก่อน</string> <string name="root_not_granted">ไม่ได้รับสิทธิ์ของรูท</string> - <string name="home_header_social_media">สื่อสังคม</string> - <string name="home_header_support_us">สนับสนุนพวกเรา</string> + <string name="home_category_social_media">สื่อสังคม</string> + <string name="home_category_support_us">สนับสนุนพวกเรา</string> <string name="app_content_unavailable">ไม่สามารถใช้ได้</string> <string name="version_installed">ติดตั้งแล้ว:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">สีดำ</string> <string name="app_theme_dialog_option_dark">สีเข้ม</string> <!-- About Page --> - <string name="about_credits_manager_devs">ตัวจัดการ Devs</string> - <string name="about_credits_other">ผู้ร่วมให้ข้อมูลอื่น ๆ</string> - <string name="about_sources">แหล่งที่มา</string> - <string name="about_credits_vanced_team">ทีมงาน Vanced</string> + <string name="about_category_credits_manager_devs">ตัวจัดการ Devs</string> + <string name="about_category_credits_other">ผู้ร่วมให้ข้อมูลอื่น ๆ</string> + <string name="about_category_sources">แหล่งที่มา</string> + <string name="about_category_credits_vanced_team">ทีมงาน Vanced</string> <!-- Error messages --> <string name="install_error_chown_fail">ไม่สามารถ `chown` APK ในระบบได้ โปรดลองอีกครั้ง</string> <string name="install_error_downloading">เกิดข้อผิดพลาดในการดาวน์โหลด %1$s</string> diff --git a/app/src/main/res/values-tr-rTR/strings.xml b/app/src/main/res/values-tr-rTR/strings.xml index 5fb329db1d..ce42d3f0df 100644 --- a/app/src/main/res/values-tr-rTR/strings.xml +++ b/app/src/main/res/values-tr-rTR/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Yeniden yükle</string> <string name="accessibility_app_uninstall">Kaldır</string> <string name="accessibility_app_update">Güncelleştir</string> - <string name="home_header_apps">Uygulamalar</string> + <string name="home_category_apps">Uygulamalar</string> <string name="app_info_changelog_header">Sürüm Notları</string> <string name="app_download_dialog_downloading_file">%1$s indiriliyor</string> <string name="app_options_install">Yükle</string> <string name="latest">En son:</string> <string name="app_microg_error">Vanced microG\'yi kurmalısın</string> <string name="root_not_granted">Root erişimi verilmedi</string> - <string name="home_header_social_media">Sosyal Medya</string> - <string name="home_header_support_us">Tıkla, destek ol</string> + <string name="home_category_social_media">Sosyal Medya</string> + <string name="home_category_support_us">Tıkla, destek ol</string> <string name="app_content_unavailable">Yüklenmemiş</string> <string name="version_installed">Yüklü:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Siyah (amoled)</string> <string name="app_theme_dialog_option_dark">Koyu renk</string> <!-- About Page --> - <string name="about_credits_manager_devs">Manager Geliştiricileri</string> - <string name="about_credits_other">Katkıda bulunan diğer kişiler</string> - <string name="about_sources">Kaynaklar</string> - <string name="about_credits_vanced_team">Vanced Ekibi</string> + <string name="about_category_credits_manager_devs">Manager Geliştiricileri</string> + <string name="about_category_credits_other">Katkıda bulunan diğer kişiler</string> + <string name="about_category_sources">Kaynaklar</string> + <string name="about_category_credits_vanced_team">Vanced Ekibi</string> <!-- Error messages --> <string name="install_error_chown_fail">APK dosyasına sistem yetkisi atanamadı, lütfen tekrar deneyin.</string> <string name="install_error_downloading">%1$s indirilirken hata oluştu</string> diff --git a/app/src/main/res/values-uk-rUA/strings.xml b/app/src/main/res/values-uk-rUA/strings.xml index cb832ace2e..c06c467f3b 100644 --- a/app/src/main/res/values-uk-rUA/strings.xml +++ b/app/src/main/res/values-uk-rUA/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">Видалити</string> <string name="accessibility_app_update">Update</string> - <string name="home_header_apps">Додатки</string> + <string name="home_category_apps">Додатки</string> <string name="app_info_changelog_header">Список змін</string> <string name="app_download_dialog_downloading_file">Завантаження %1$s</string> <string name="app_options_install">Встановити</string> <string name="latest">Найновіша:</string> <string name="app_microg_error">Спочатку встановіть Vanced microG</string> <string name="root_not_granted">Права суперкористувача не були надані</string> - <string name="home_header_social_media">Соціальні мережі</string> - <string name="home_header_support_us">Підтримайте нас</string> + <string name="home_category_social_media">Соціальні мережі</string> + <string name="home_category_support_us">Підтримайте нас</string> <string name="app_content_unavailable">Недоступно</string> <string name="version_installed">Встановлена:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Чорний</string> <string name="app_theme_dialog_option_dark">Темний</string> <!-- About Page --> - <string name="about_credits_manager_devs">Розробники Менеджера</string> - <string name="about_credits_other">Інші учасники</string> - <string name="about_sources">Джерела</string> - <string name="about_credits_vanced_team">Команда Vanced</string> + <string name="about_category_credits_manager_devs">Розробники Менеджера</string> + <string name="about_category_credits_other">Інші учасники</string> + <string name="about_category_sources">Джерела</string> + <string name="about_category_credits_vanced_team">Команда Vanced</string> <!-- Error messages --> <string name="install_error_chown_fail">Не вдалося створити файл APK системного власника програми, будь ласка, повторіть спробу.</string> <string name="install_error_downloading">Помилка Завантаження %1$s</string> diff --git a/app/src/main/res/values-vi-rVN/strings.xml b/app/src/main/res/values-vi-rVN/strings.xml index c1bbe1183a..a4bf461657 100644 --- a/app/src/main/res/values-vi-rVN/strings.xml +++ b/app/src/main/res/values-vi-rVN/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Cài đặt lại</string> <string name="accessibility_app_uninstall">Gỡ cài đặt</string> <string name="accessibility_app_update">Cập nhật</string> - <string name="home_header_apps">Các ứng dụng</string> + <string name="home_category_apps">Các ứng dụng</string> <string name="app_info_changelog_header">Các thay đổi</string> <string name="app_download_dialog_downloading_file">Đang tải xuống %1$s</string> <string name="app_options_install">Cài đặt</string> <string name="latest">Mới nhất:</string> <string name="app_microg_error">Bạn phải cài Vanced microG trước</string> <string name="root_not_granted">Quyền root không được cấp</string> - <string name="home_header_social_media">Mạng xã hội</string> - <string name="home_header_support_us">Hỗ trợ chúng tôi</string> + <string name="home_category_social_media">Mạng xã hội</string> + <string name="home_category_support_us">Hỗ trợ chúng tôi</string> <string name="app_content_unavailable">Chưa cài</string> <string name="version_installed">Đã cài đặt:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">Đen</string> <string name="app_theme_dialog_option_dark">Tối</string> <!-- About Page --> - <string name="about_credits_manager_devs">Đội ngũ phát triển</string> - <string name="about_credits_other">Những người đóng góp khác</string> - <string name="about_sources">Nguồn</string> - <string name="about_credits_vanced_team">Đội ngũ Vanced</string> + <string name="about_category_credits_manager_devs">Đội ngũ phát triển</string> + <string name="about_category_credits_other">Những người đóng góp khác</string> + <string name="about_category_sources">Nguồn</string> + <string name="about_category_credits_vanced_team">Đội ngũ Vanced</string> <!-- Error messages --> <string name="install_error_chown_fail">Thay đổi quyền sở hữu APK cho chủ hệ thống thất bại, vui lòng thử lại.</string> <string name="install_error_downloading">Lỗi khi tải xuống %1$s</string> diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 2d5423a6b3..a1953c5735 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">Reinstall</string> <string name="accessibility_app_uninstall">卸载</string> <string name="accessibility_app_update">更新</string> - <string name="home_header_apps">应用</string> + <string name="home_category_apps">应用</string> <string name="app_info_changelog_header">变更日志</string> <string name="app_download_dialog_downloading_file">正在下载 %1$s</string> <string name="app_options_install">安装</string> <string name="latest">最新:</string> <string name="app_microg_error">请先安装 Vanced microG</string> <string name="root_not_granted">未授予 Root 权限</string> - <string name="home_header_social_media">社交媒体</string> - <string name="home_header_support_us">支持我们</string> + <string name="home_category_social_media">社交媒体</string> + <string name="home_category_support_us">支持我们</string> <string name="app_content_unavailable">不可用</string> <string name="version_installed">已安装:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">黑色</string> <string name="app_theme_dialog_option_dark">深色</string> <!-- About Page --> - <string name="about_credits_manager_devs">Manager 开发人员</string> - <string name="about_credits_other">其它贡献者:</string> - <string name="about_sources">源码</string> - <string name="about_credits_vanced_team">Vanced 团队</string> + <string name="about_category_credits_manager_devs">Manager 开发人员</string> + <string name="about_category_credits_other">其它贡献者:</string> + <string name="about_category_sources">源码</string> + <string name="about_category_credits_vanced_team">Vanced 团队</string> <!-- Error messages --> <string name="install_error_chown_fail">无法 `chown` apk 为系统拥有者,请重试。</string> <string name="install_error_downloading">%1$s 下载错误</string> diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 97c4410869..3a046b75d5 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -30,15 +30,15 @@ <string name="accessibility_app_reinstall">重新安裝</string> <string name="accessibility_app_uninstall">解除安裝</string> <string name="accessibility_app_update">更新</string> - <string name="home_header_apps">應用程式</string> + <string name="home_category_apps">應用程式</string> <string name="app_info_changelog_header">更新日誌</string> <string name="app_download_dialog_downloading_file">正在下載 %1$s</string> <string name="app_options_install">安裝</string> <string name="latest">最新:</string> <string name="app_microg_error">請先安裝 Vanced microG</string> <string name="root_not_granted">未授予 Root 權限</string> - <string name="home_header_social_media">社交媒體</string> - <string name="home_header_support_us">支持我們</string> + <string name="home_category_social_media">社交媒體</string> + <string name="home_category_support_us">支持我們</string> <string name="app_content_unavailable">無法使用</string> <string name="version_installed">已安裝:</string> <!-- Settings --> @@ -95,10 +95,10 @@ <string name="app_theme_dialog_option_black">黑色</string> <string name="app_theme_dialog_option_dark">深色</string> <!-- About Page --> - <string name="about_credits_manager_devs">Manager 開發者</string> - <string name="about_credits_other">其他貢獻者:</string> - <string name="about_sources">原始碼</string> - <string name="about_credits_vanced_team">Vanced 團隊</string> + <string name="about_category_credits_manager_devs">Manager 開發者</string> + <string name="about_category_credits_other">其他貢獻者:</string> + <string name="about_category_sources">原始碼</string> + <string name="about_category_credits_vanced_team">Vanced 團隊</string> <!-- Error messages --> <string name="install_error_chown_fail">無法 `chown` apk 為系統擁有者,請重試。</string> <string name="install_error_downloading">%1$s 下載錯誤</string> diff --git a/app/src/main/res/values/resources.xml b/app/src/main/res/values/resources.xml index 83cfe78feb..39812c561e 100644 --- a/app/src/main/res/values/resources.xml +++ b/app/src/main/res/values/resources.xml @@ -3,4 +3,8 @@ <string name="app_name" translatable="false">Vanced Manager</string> + <string name="app_name_vanced" translatable="false">YouTube Vanced</string> + <string name="app_name_music" translatable="false">YouTube Music Vanced</string> + <string name="app_name_microg" translatable="false">Vanced microG</string> + </resources> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 004c7063e6..924686fd58 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,6 +1,9 @@ <?xml version="1.0" encoding="UTF-8" standalone="no"?> <resources> + <!-- Dummy --> + <string name="dummy_placeholder_text">DPT</string> + <!-- Welcome Page --> <string name="welcome_app_description_microg">A custom GMS Implementation for Vanced based on the microG Project.</string> <string name="welcome_app_description_vanced">A modified YouTube client with many useful features!</string> @@ -13,9 +16,9 @@ <string name="welcome_select_apps_error">Select at least one app!</string> <!-- Home Page --> - <string name="home_header_apps">Apps</string> - <string name="home_header_social_media">Social Media</string> - <string name="home_header_support_us">Support us</string> + <string name="home_category_apps">Apps</string> + <string name="home_category_social_media">Social Media</string> + <string name="home_category_support_us">Support us</string> <string name="root_not_granted">Root access not granted</string> <!-- Settings Page--> @@ -44,10 +47,12 @@ <string name="dev_settings_preference_update_url_title">Base download URL</string> <!-- About Page --> - <string name="about_credits_manager_devs">Manager Devs</string> - <string name="about_credits_other">Other Contributors</string> - <string name="about_credits_vanced_team">Vanced Team</string> - <string name="about_sources">Sources</string> + <string name="about_category_credits_manager_devs">Manager Devs</string> + <string name="about_category_credits_other">Other Contributors</string> + <string name="about_category_credits_vanced_team">Vanced Team</string> + <string name="about_category_sources">Sources</string> + <string name="about_sources_source_code">Source Code</string> + <string name="about_sources_license">License</string> <!-- Logs Page--> <string name="logs_save_error">Successfully saved logs</string> @@ -74,6 +79,7 @@ <string name="app_options_install">Install</string> <string name="app_version_installed">Installed: %1$s</string> <string name="app_version_latest">Latest: %1$s</string> + <string name="app_versions">Versions</string> <!-- App Installation Options Menu --> <string name="app_installation_options_language">Language(s)</string> diff --git a/build.gradle.kts b/build.gradle.kts index 37390083aa..ac8f89b525 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,7 +5,7 @@ buildscript { } dependencies { - classpath("com.android.tools.build:gradle:7.0.0-beta03") + classpath("com.android.tools.build:gradle:7.0.0-beta04") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${Config.kotlinVersion}") } } diff --git a/buildSrc/src/main/java/Config.kt b/buildSrc/src/main/java/Config.kt index dc5a7b8c9d..c376c1b48d 100644 --- a/buildSrc/src/main/java/Config.kt +++ b/buildSrc/src/main/java/Config.kt @@ -1,5 +1,5 @@ object Config { - const val kotlinVersion = "1.4.32" + const val kotlinVersion = "1.5.10" } \ No newline at end of file diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt new file mode 100644 index 0000000000..8b868f465a --- /dev/null +++ b/buildSrc/src/main/java/Dependencies.kt @@ -0,0 +1,9 @@ +object Dependencies { + + const val accompanistVersion = "0.12.0" + const val composeVersion = "1.0.0-beta09" + const val koinVersion = "3.1.0" + const val retrofitVersion = "2.9.0" + const val orchestraVersion = "1.0.7" + +} \ No newline at end of file From 890944377f670e97ae7173e9e38af09deaf4ec4b Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 27 Jun 2021 10:12:24 +0400 Subject: [PATCH 006/118] Text adjustments --- .../java/com/vanced/manager/ui/MainActivity.kt | 2 +- .../text/AppVersionText.kt | 3 +-- .../text/CategoryTitleText.kt | 7 ++++--- .../ui/components/text/ToolbarTitleText.kt | 16 ++++++++++++++++ .../ui/widgets/home/apps/card/AppActionCard.kt | 2 +- .../manager/ui/widgets/layout/CategoryLayout.kt | 2 +- .../manager/ui/widgets/text/ToolbarTitleText.kt | 15 --------------- 7 files changed, 24 insertions(+), 23 deletions(-) rename app/src/main/java/com/vanced/manager/ui/{widgets => components}/text/AppVersionText.kt (83%) rename app/src/main/java/com/vanced/manager/ui/{widgets => components}/text/CategoryTitleText.kt (67%) create mode 100644 app/src/main/java/com/vanced/manager/ui/components/text/ToolbarTitleText.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/text/ToolbarTitleText.kt diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index 705e4504f9..2c1c87aa0d 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -27,7 +27,7 @@ import com.vanced.manager.ui.components.menu.ManagerDropdownMenuItem import com.vanced.manager.ui.screens.Screen import com.vanced.manager.ui.theme.ManagerTheme import com.vanced.manager.ui.theme.isDark -import com.vanced.manager.ui.widgets.text.ToolbarTitleText +import com.vanced.manager.ui.components.text.ToolbarTitleText class MainActivity : AppCompatActivity() { diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/text/AppVersionText.kt b/app/src/main/java/com/vanced/manager/ui/components/text/AppVersionText.kt similarity index 83% rename from app/src/main/java/com/vanced/manager/ui/widgets/text/AppVersionText.kt rename to app/src/main/java/com/vanced/manager/ui/components/text/AppVersionText.kt index 112b52f4c3..ad0604c319 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/text/AppVersionText.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/text/AppVersionText.kt @@ -1,11 +1,10 @@ -package com.vanced.manager.ui.widgets.text +package com.vanced.manager.ui.components.text import androidx.annotation.StringRes import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import com.vanced.manager.R import com.vanced.manager.ui.components.lifecycle.managerString -import com.vanced.manager.ui.components.text.ManagerText @Composable fun AppVersionText( diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/text/CategoryTitleText.kt b/app/src/main/java/com/vanced/manager/ui/components/text/CategoryTitleText.kt similarity index 67% rename from app/src/main/java/com/vanced/manager/ui/widgets/text/CategoryTitleText.kt rename to app/src/main/java/com/vanced/manager/ui/components/text/CategoryTitleText.kt index 17a895ba3c..283764aba0 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/text/CategoryTitleText.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/text/CategoryTitleText.kt @@ -1,11 +1,11 @@ -package com.vanced.manager.ui.widgets.text +package com.vanced.manager.ui.components.text import androidx.annotation.StringRes import androidx.compose.foundation.layout.padding import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import com.vanced.manager.ui.components.text.ManagerText +import com.vanced.manager.ui.components.color.managerAnimatedColor import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal @Composable @@ -15,6 +15,7 @@ fun CategoryTitleText( ManagerText( modifier = Modifier.padding(start = defaultContentPaddingHorizontal), stringId = stringId, - textStyle = MaterialTheme.typography.h2 + textStyle = MaterialTheme.typography.h2, + color = managerAnimatedColor(MaterialTheme.colors.onSurface) ) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/text/ToolbarTitleText.kt b/app/src/main/java/com/vanced/manager/ui/components/text/ToolbarTitleText.kt new file mode 100644 index 0000000000..916ece22e4 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/text/ToolbarTitleText.kt @@ -0,0 +1,16 @@ +package com.vanced.manager.ui.components.text + +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import com.vanced.manager.ui.components.color.managerAnimatedColor + +@Composable +fun ToolbarTitleText( + stringId: Int? +) { + ManagerText( + stringId = stringId, + textStyle = MaterialTheme.typography.h1, + color = managerAnimatedColor(MaterialTheme.colors.onSurface) + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt index 8b6c5a9a87..7b3e29eb60 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt @@ -16,7 +16,7 @@ import com.vanced.manager.ui.components.button.IconButton import com.vanced.manager.ui.components.color.ThemedCardContentColorProvider import com.vanced.manager.ui.components.text.ManagerText import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal -import com.vanced.manager.ui.widgets.text.AppVersionText +import com.vanced.manager.ui.components.text.AppVersionText @Composable fun AppActionCard( diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/layout/CategoryLayout.kt b/app/src/main/java/com/vanced/manager/ui/widgets/layout/CategoryLayout.kt index 7fd31d4f77..75edce1bd9 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/layout/CategoryLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/layout/CategoryLayout.kt @@ -7,7 +7,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.Dp import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal import com.vanced.manager.ui.utils.defaultContentPaddingVertical -import com.vanced.manager.ui.widgets.text.CategoryTitleText +import com.vanced.manager.ui.components.text.CategoryTitleText @Composable fun CategoryLayout( diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/text/ToolbarTitleText.kt b/app/src/main/java/com/vanced/manager/ui/widgets/text/ToolbarTitleText.kt deleted file mode 100644 index e196ef0fe9..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widgets/text/ToolbarTitleText.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.vanced.manager.ui.widgets.text - -import androidx.compose.material.MaterialTheme -import androidx.compose.runtime.Composable -import com.vanced.manager.ui.components.text.ManagerText - -@Composable -fun ToolbarTitleText( - stringId: Int? -) { - ManagerText( - stringId = stringId, - textStyle = MaterialTheme.typography.h1 - ) -} \ No newline at end of file From 20cf7f11a3eb5e0b1bf40d176468190c58fee2cf Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 27 Jun 2021 10:52:40 +0400 Subject: [PATCH 007/118] cleanup --- .../ui/components/GlobalComposables.kt | 46 ------------------- 1 file changed, 46 deletions(-) delete mode 100644 app/src/main/java/com/vanced/manager/ui/components/GlobalComposables.kt diff --git a/app/src/main/java/com/vanced/manager/ui/components/GlobalComposables.kt b/app/src/main/java/com/vanced/manager/ui/components/GlobalComposables.kt deleted file mode 100644 index 727d97eb09..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/components/GlobalComposables.kt +++ /dev/null @@ -1,46 +0,0 @@ -package com.vanced.manager.ui.components - -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.foundation.layout.padding -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.em -import androidx.compose.ui.unit.sp -import com.vanced.manager.ui.theme.managerAccentColor -import java.util.* - -@Composable -fun HeaderView( - modifier: Modifier = Modifier, - headerName: String, - headerPadding: Dp = 11.dp, - content: @Composable ColumnScope.() -> Unit -) { - Column( - modifier = modifier - ) { - Header(headerName = headerName, headerPadding = headerPadding) - content() - } -} - -@Composable -fun Header( - headerName: String, - headerPadding: Dp = 11.dp, -) { - Text( - headerName.uppercase(Locale.ROOT), - letterSpacing = 0.15.em, - color = MaterialTheme.colors.managerAccentColor, - modifier = Modifier.padding(horizontal = headerPadding), - fontWeight = FontWeight.Bold, - fontSize = 13.sp - ) -} \ No newline at end of file From cc2a308d6e874bcac24c910b1e0d28d77dc0eae1 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 27 Jun 2021 10:53:23 +0400 Subject: [PATCH 008/118] adjusted dialog preferences --- .../preference/CheckboxDialogPreference.kt | 67 +++++++++++++++++++ .../preference/RadiobuttonDialogPreference.kt | 3 +- 2 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxDialogPreference.kt diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxDialogPreference.kt new file mode 100644 index 0000000000..4eae73920e --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxDialogPreference.kt @@ -0,0 +1,67 @@ +package com.vanced.manager.ui.components.preference + +import androidx.annotation.StringRes +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.toMutableStateList +import androidx.compose.ui.Modifier +import com.vanced.manager.R +import com.vanced.manager.ui.components.button.ManagerThemedTextButton +import com.vanced.manager.ui.components.list.CheckboxItem +import com.vanced.manager.ui.preferences.CheckboxPreference +import com.vanced.manager.ui.preferences.ManagerPreference +import kotlinx.coroutines.launch + +@Composable +fun CheckboxDialogPreference( + @StringRes preferenceTitle: Int, + @StringRes preferenceDescription: Int? = null, + preference: ManagerPreference<Set<String>>, + trailing: @Composable () -> Unit = {}, + buttons: List<CheckboxPreference>, + onSave: (checkedButtons: List<String>) -> Unit = {} +) { + val selectedButtons = remember { preference.value.value.toMutableStateList() } + val coroutineScope = rememberCoroutineScope() + DialogPreference( + preferenceTitleId = preferenceTitle, + preferenceDescriptionId = preferenceDescription, + trailing = trailing, + buttons = { isShown -> + ManagerThemedTextButton( + stringId = R.string.dialog_button_save, + modifier = Modifier.fillMaxWidth(), + onClick = { + coroutineScope.launch { + isShown.value = false + preference.save(selectedButtons.toSet()) + onSave(selectedButtons) + } + } + ) + } + ) { + LazyColumn( + modifier = Modifier + ) { + items(buttons) { button -> + val (title, key) = button + CheckboxItem( + text = title, + isChecked = selectedButtons.contains(key), + onCheck = { isChecked -> + if (isChecked) { + selectedButtons.add(key) + } else { + selectedButtons.remove(key) + } + } + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt index bd4d042340..7018348e4e 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt @@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items -import androidx.compose.material.Text import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp @@ -36,9 +35,9 @@ fun RadiobuttonDialogPreference( modifier = Modifier.fillMaxWidth(), onClick = { coroutineScope.launch { + isShown.value = false preference.save(currentSelection) onSave(currentSelection) - isShown.value = false } } ) From 19b93febcb85ca4e325f102404a360e4d6c9eb95 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 27 Jun 2021 12:24:35 +0400 Subject: [PATCH 009/118] updated theme --- .../com/vanced/manager/ui/MainActivity.kt | 3 +- .../components/button/ManagerThemedButton.kt | 14 ++-- .../manager/ui/components/card/ManagerCard.kt | 3 +- .../ui/components/card/ManagerItemCard.kt | 4 +- .../ui/components/checkbox/ManagerCheckbox.kt | 7 +- .../components/color/ColorContentProvider.kt | 7 +- .../ui/components/color/ManagerColors.kt | 12 +--- .../ui/components/list/CheckboxItem.kt | 3 +- .../ui/components/list/RadiobuttonItem.kt | 3 +- .../preference/PreferenceComponents.kt | 66 ------------------- .../vanced/manager/ui/layouts/HomeLayout.kt | 5 +- .../vanced/manager/ui/layouts/LogLayout.kt | 8 +-- .../java/com/vanced/manager/ui/theme/Color.kt | 10 +-- .../java/com/vanced/manager/ui/theme/Theme.kt | 20 ++---- .../download/AppDownloadDialogProgress.kt | 6 +- 15 files changed, 40 insertions(+), 131 deletions(-) delete mode 100644 app/src/main/java/com/vanced/manager/ui/components/preference/PreferenceComponents.kt diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index 2c1c87aa0d..d8d0b04a93 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -20,7 +20,6 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.vanced.manager.ui.components.color.managerAnimatedColor -import com.vanced.manager.ui.components.color.managerCardColor import com.vanced.manager.ui.components.color.managerSurfaceColor import com.vanced.manager.ui.components.color.managerTextColor import com.vanced.manager.ui.components.menu.ManagerDropdownMenuItem @@ -111,7 +110,7 @@ class MainActivity : AppCompatActivity() { onDismissRequest = { isMenuExpanded.value = false }, - modifier = Modifier.background(managerCardColor()) + modifier = Modifier.background(MaterialTheme.colors.surface) ) { screens.filter { it.route != currentScreenRoute }.forEach { ManagerDropdownMenuItem( diff --git a/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedButton.kt b/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedButton.kt index e4bda53c6e..d48c2a691b 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedButton.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedButton.kt @@ -4,15 +4,12 @@ import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.Button import androidx.compose.material.ButtonDefaults -import androidx.compose.material.LocalContentColor import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.luminance import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.components.color.managerAccentColor @Composable fun ManagerThemedButton( @@ -20,18 +17,19 @@ fun ManagerThemedButton( onClick: () -> Unit, content: @Composable RowScope.() -> Unit ) { - val accentColor = managerAccentColor() Button( modifier = modifier.fillMaxWidth(), onClick = onClick, shape = MaterialTheme.shapes.medium, colors = ButtonDefaults.buttonColors( - backgroundColor = managerAccentColor() + contentColor = + if (MaterialTheme.colors.primary.luminance() > 0.7) + Color.Black + else + Color.White ), elevation = ButtonDefaults.elevation(0.dp, 0.dp, 0.dp) ) { - CompositionLocalProvider(LocalContentColor provides if (accentColor.luminance() > 0.7) Color.Black else Color.White) { - content() - } + content() } } diff --git a/app/src/main/java/com/vanced/manager/ui/components/card/ManagerCard.kt b/app/src/main/java/com/vanced/manager/ui/components/card/ManagerCard.kt index 23ff06cc97..81787834fe 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/card/ManagerCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/card/ManagerCard.kt @@ -8,7 +8,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.components.color.managerCardColor @Composable fun ManagerCard( @@ -31,7 +30,7 @@ fun ManagerCard( fun ManagerCard( modifier: Modifier = Modifier, shape: Shape = MaterialTheme.shapes.medium, - backgroundColor: Color = managerCardColor(), + backgroundColor: Color = MaterialTheme.colors.surface, onClick: () -> Unit, content: @Composable () -> Unit, ) { diff --git a/app/src/main/java/com/vanced/manager/ui/components/card/ManagerItemCard.kt b/app/src/main/java/com/vanced/manager/ui/components/card/ManagerItemCard.kt index 32d7675607..1ac13eba0e 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/card/ManagerItemCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/card/ManagerItemCard.kt @@ -15,7 +15,6 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.vanced.manager.ui.components.color.ThemedItemContentColorProvider -import com.vanced.manager.ui.components.color.managerAccentColor private val cardModifier = Modifier.sizeIn( minHeight = 95.dp, @@ -53,9 +52,10 @@ private fun ManagerItemCardContent( title: String, @DrawableRes icon: Int? = null, ) { + val accentColor = MaterialTheme.colors.primary Canvas(modifier = Modifier.requiredSize(72.dp)) { drawCircle( - color = managerAccentColor(), + color = accentColor, center = Offset(32f,32f) ) } diff --git a/app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt b/app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt index 8020c1f777..64a9d025fa 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt @@ -7,6 +7,7 @@ import androidx.compose.animation.core.updateTransition import androidx.compose.foundation.layout.requiredSize import androidx.compose.foundation.layout.size import androidx.compose.material.Icon +import androidx.compose.material.MaterialTheme import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.Close import androidx.compose.material.icons.rounded.Done @@ -16,7 +17,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.vanced.manager.ui.components.card.ManagerCard import com.vanced.manager.ui.components.color.contentColorForColor -import com.vanced.manager.ui.components.color.managerAccentColor import com.vanced.manager.ui.components.color.managerAnimatedColor import com.vanced.manager.ui.components.color.managerThemedCardColor @@ -26,6 +26,7 @@ fun ManagerCheckbox( isChecked: Boolean, onCheckedChange: (isChecked: Boolean) -> Unit ) { + val accentColor = MaterialTheme.colors.primary val transition = updateTransition(targetState = isChecked, label = "Checked") val cardSize by transition.animateDp( transitionSpec = { @@ -49,8 +50,8 @@ fun ManagerCheckbox( }, label = "Icon size" ) { 24.dp } - val cardColor = managerAnimatedColor(if (isChecked) managerAccentColor() else managerThemedCardColor()) - val iconTint = managerAnimatedColor(if (isChecked) contentColorForColor(cardColor) else managerAccentColor()) + val cardColor = managerAnimatedColor(if (isChecked) accentColor else managerThemedCardColor()) + val iconTint = managerAnimatedColor(if (isChecked) contentColorForColor(cardColor) else accentColor) ManagerCard( modifier = Modifier.size(cardSize), diff --git a/app/src/main/java/com/vanced/manager/ui/components/color/ColorContentProvider.kt b/app/src/main/java/com/vanced/manager/ui/components/color/ColorContentProvider.kt index d089582ac9..ae55bc2261 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/color/ColorContentProvider.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/color/ColorContentProvider.kt @@ -1,6 +1,7 @@ package com.vanced.manager.ui.components.color import androidx.compose.material.LocalContentColor +import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider @@ -9,7 +10,7 @@ fun ThemedItemContentColorProvider( content: @Composable () -> Unit ) { CompositionLocalProvider( - LocalContentColor provides contentColorForColor(managerAccentColor()), + LocalContentColor provides contentColorForColor(MaterialTheme.colors.primary), content = content ) } @@ -19,7 +20,7 @@ fun ThemedCardContentColorProvider( content: @Composable () -> Unit ) { CompositionLocalProvider( - LocalContentColor provides contentColorForColor(managerThemedCardColor()), + LocalContentColor provides contentColorForColor(MaterialTheme.colors.primaryVariant), content = content ) } @@ -29,7 +30,7 @@ fun ThemedContentColorProvider( content: @Composable () -> Unit ) { CompositionLocalProvider( - LocalContentColor provides managerAccentColor(), + LocalContentColor provides MaterialTheme.colors.primary, content = content ) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/color/ManagerColors.kt b/app/src/main/java/com/vanced/manager/ui/components/color/ManagerColors.kt index 63949eaf74..7a5905fc20 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/color/ManagerColors.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/color/ManagerColors.kt @@ -6,10 +6,6 @@ import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.luminance -import com.vanced.manager.ui.preferences.holder.managerAccentColorPref -import com.vanced.manager.ui.theme.cardColor - -fun managerAccentColor(): Color = Color(managerAccentColorPref.value.value) @Composable fun contentColorForColor(color: Color) = @@ -19,7 +15,7 @@ fun contentColorForColor(color: Color) = Color.White @Composable -fun managerThemedCardColor() = managerAccentColor().copy(alpha = 0.2f) +fun managerThemedCardColor() = MaterialTheme.colors.primary.copy(alpha = 0.2f) @Composable fun managerTextColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.onSurface) @@ -27,12 +23,6 @@ fun managerTextColor(): Color = managerAnimatedColor(color = MaterialTheme.color @Composable fun managerSurfaceColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.surface) -@Composable -fun managerCardColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.cardColor) - -@Composable -fun animatedManagerAccentColor(): Color = managerAnimatedColor(color = managerAccentColor()) - @Composable fun managerAnimatedColor( color: Color diff --git a/app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt b/app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt index 7cb16b9b04..c290fada5c 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt @@ -15,7 +15,6 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.vanced.manager.ui.components.color.managerTextColor -import com.vanced.manager.ui.theme.managerAccentColor @Composable fun CheckboxItem( @@ -40,7 +39,7 @@ fun CheckboxItem( toggle() }, colors = CheckboxDefaults.colors( - MaterialTheme.colors.managerAccentColor, + MaterialTheme.colors.primary, Color.LightGray ) ) diff --git a/app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt b/app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt index 2b13cd12bb..b3d20e85e4 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt @@ -15,7 +15,6 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.vanced.manager.ui.components.color.managerTextColor -import com.vanced.manager.ui.theme.managerAccentColor @Composable fun <T> RadiobuttonItem( @@ -39,7 +38,7 @@ fun <T> RadiobuttonItem( selected = selected, onClick = onClick, colors = RadioButtonDefaults.colors( - MaterialTheme.colors.managerAccentColor, + MaterialTheme.colors.primary, Color.LightGray ) ) diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/PreferenceComponents.kt b/app/src/main/java/com/vanced/manager/ui/components/preference/PreferenceComponents.kt deleted file mode 100644 index d4b2bcb3d6..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/components/preference/PreferenceComponents.kt +++ /dev/null @@ -1,66 +0,0 @@ -package com.vanced.manager.ui.components.preference - -import androidx.annotation.StringRes -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material.* -import androidx.compose.runtime.* -import androidx.compose.ui.Modifier -import com.vanced.manager.R -import com.vanced.manager.ui.components.* -import com.vanced.manager.ui.components.button.ManagerThemedButton -import com.vanced.manager.ui.components.button.ManagerThemedTextButton -import com.vanced.manager.ui.components.list.CheckboxItem -import com.vanced.manager.ui.preferences.* -import kotlinx.coroutines.launch - -@Composable -fun CheckboxDialogPreference( - @StringRes preferenceTitle: Int, - @StringRes preferenceDescription: Int? = null, - preference: ManagerPreference<Set<String>>, - trailing: @Composable () -> Unit = {}, - buttons: List<CheckboxPreference>, - onSave: (checkedButtons: List<String>) -> Unit = {} -) { - val selectedButtons = remember { preference.value.value.toMutableStateList() } - val coroutineScope = rememberCoroutineScope() - DialogPreference( - preferenceTitleId = preferenceTitle, - preferenceDescriptionId = preferenceDescription, - trailing = trailing, - buttons = { isShown -> - ManagerThemedTextButton( - stringId = R.string.dialog_button_save, - modifier = Modifier.fillMaxWidth(), - onClick = { - coroutineScope.launch { - preference.save(selectedButtons.toSet()) - onSave(selectedButtons) - isShown.value = false - } - } - ) - } - ) { - LazyColumn( - modifier = Modifier - ) { - items(buttons) { button -> - val (title, key) = button - CheckboxItem( - text = title, - isChecked = selectedButtons.contains(key), - onCheck = { isChecked -> - if (isChecked) { - selectedButtons.add(key) - } else { - selectedButtons.remove(key) - } - } - ) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt index 3806300d89..a19d1de7bc 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt @@ -2,6 +2,7 @@ package com.vanced.manager.ui.layouts import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState @@ -13,9 +14,7 @@ import com.google.accompanist.swiperefresh.SwipeRefreshIndicator import com.google.accompanist.swiperefresh.rememberSwipeRefreshState import com.vanced.manager.R import com.vanced.manager.domain.model.App -import com.vanced.manager.ui.components.* import com.vanced.manager.ui.components.card.ManagerLinkCard -import com.vanced.manager.ui.components.color.managerAccentColor import com.vanced.manager.ui.components.layout.ManagerScrollableColumn import com.vanced.manager.ui.components.layout.ScrollableItemRow import com.vanced.manager.ui.utils.defaultContentPaddingVertical @@ -40,7 +39,7 @@ fun HomeLayout() { state = state, refreshTriggerDistance = trigger, scale = true, - contentColor = managerAccentColor() + contentColor = MaterialTheme.colors.primary ) } ) { diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt index fbb8483aa6..991d1660bc 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt @@ -2,15 +2,11 @@ package com.vanced.manager.ui.layouts import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.lazy.items -import androidx.compose.material.FloatingActionButton -import androidx.compose.material.Icon -import androidx.compose.material.Scaffold -import androidx.compose.material.Text +import androidx.compose.material.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Share import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import com.vanced.manager.ui.components.color.managerAccentColor import com.vanced.manager.ui.components.color.managerSurfaceColor import com.vanced.manager.ui.components.layout.ManagerLazyColumn import com.vanced.manager.util.logs @@ -22,7 +18,7 @@ fun LogLayout() { floatingActionButton = { FloatingActionButton( onClick = { /*TODO*/ }, - backgroundColor = managerAccentColor() + backgroundColor = MaterialTheme.colors.primary ) { Icon( imageVector = Icons.Default.Share, diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Color.kt b/app/src/main/java/com/vanced/manager/ui/theme/Color.kt index 740269d383..76e43574af 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Color.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Color.kt @@ -1,11 +1,13 @@ package com.vanced.manager.ui.theme import androidx.compose.ui.graphics.Color +import com.vanced.manager.ui.preferences.holder.managerAccentColorPref -val purple200 = Color(0xFFBB86FC) -val purple500 = Color(0xFF6200EE) -val purple700 = Color(0xFF3700B3) -val teal200 = Color(0xFF03DAC5) +val accentColor = Color(managerAccentColorPref.value.value) +val accentColorVariant = accentColor.copy(alpha = 0.25f) + +val lightOnSurface = Color(0xFFD7D7D7) +val lightSurface = Color(0xFFE9E9E9) val vancedBlue = Color(0xFF2E73FF) val vancedRed = Color(0xFFFF0032) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt index f9b2f315ad..94e3206d73 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt @@ -1,34 +1,26 @@ package com.vanced.manager.ui.theme import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.material.Colors import androidx.compose.material.MaterialTheme import androidx.compose.material.darkColors import androidx.compose.material.lightColors import androidx.compose.runtime.Composable -import androidx.compose.ui.graphics.Color -import com.vanced.manager.ui.preferences.holder.managerAccentColorPref import com.vanced.manager.ui.preferences.holder.managerThemePref const val defAccentColor = 0xFF0477E1 private val DarkColorPalette = darkColors( - primary = purple200, - primaryVariant = purple700, - secondary = teal200 + primary = accentColor, + primaryVariant = accentColorVariant, ) private val LightColorPalette = lightColors( - primary = purple500, - primaryVariant = purple700, - secondary = teal200, - surface = Color(0xFFE9E9E9) + primary = accentColor, + primaryVariant = accentColorVariant, + surface = lightSurface, + onSurface = lightOnSurface ) -val Colors.cardColor: Color get() = if (isLight) Color(0xFFF7F7F7) else Color(0xFF191919) - -val Colors.managerAccentColor: Color get() = Color(managerAccentColorPref.value.value) - @Composable fun isDark(): Boolean = when (managerThemePref.value.value) { "Dark" -> true diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt index 9618c154b8..025c95f8b4 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt @@ -3,11 +3,11 @@ package com.vanced.manager.ui.widgets.home.download import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.material.LinearProgressIndicator +import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import com.vanced.manager.ui.components.color.managerAccentColor @Composable fun AppDownloadDialogProgress( @@ -18,10 +18,10 @@ fun AppDownloadDialogProgress( ) { if (showProgress) { when (installing) { - true -> LinearProgressIndicator(color = managerAccentColor()) + true -> LinearProgressIndicator(color = MaterialTheme.colors.primary) false -> LinearProgressIndicator( progress = progress, - color = managerAccentColor() + color = MaterialTheme.colors.primary ) } Row { From bb237d754de930fbbf20918b4ec5026f0d2d5066 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 27 Jun 2021 13:28:18 +0400 Subject: [PATCH 010/118] switched back to AndroidX preferences --- app/build.gradle.kts | 4 +- .../com/vanced/manager/di/PreferenceModule.kt | 5 +- .../manager/ui/layouts/SettingsLayout.kt | 4 +- .../ui/preferences/ManagerPreference.kt | 86 ++++++++++++++----- .../ui/preferences/holder/PreferenceHolder.kt | 20 ++--- .../preferences/holder/PreferenceKeyHolder.kt | 25 +++--- .../holder/PreferenceKeyNameHolder.kt | 13 --- 7 files changed, 88 insertions(+), 69 deletions(-) delete mode 100644 app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceKeyNameHolder.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 73960162c1..cd0e62f81e 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -101,6 +101,8 @@ dependencies { implementation("androidx.compose.ui:ui-util:$composeVersion") implementation("androidx.compose.ui:ui:$composeVersion") + implementation("androidx.preference:preference-ktx:1.1.1") + implementation("androidx.activity:activity-compose:1.3.0-beta02") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-alpha02") implementation("androidx.navigation:navigation-compose:2.4.0-alpha03") @@ -112,8 +114,6 @@ dependencies { implementation("com.github.skydoves:orchestra-colorpicker:$orchestraVersion") - implementation("androidx.datastore:datastore-preferences:1.0.0-beta02") - implementation("io.insert-koin:koin-android:$koinVersion") implementation("io.insert-koin:koin-androidx-compose:$koinVersion") diff --git a/app/src/main/java/com/vanced/manager/di/PreferenceModule.kt b/app/src/main/java/com/vanced/manager/di/PreferenceModule.kt index 0af88be287..d43742ffb4 100644 --- a/app/src/main/java/com/vanced/manager/di/PreferenceModule.kt +++ b/app/src/main/java/com/vanced/manager/di/PreferenceModule.kt @@ -1,15 +1,12 @@ package com.vanced.manager.di import android.content.Context -import androidx.datastore.preferences.preferencesDataStore import org.koin.dsl.module -val Context.dataStore by preferencesDataStore("manager_settings") - val preferenceModule = module { fun provideDatastore( context: Context - ) = context.dataStore + ) = context.getSharedPreferences("manager_settings", Context.MODE_PRIVATE) single { provideDatastore(get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt index cd89268af2..f51f24d18c 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt @@ -3,9 +3,7 @@ package com.vanced.manager.ui.layouts import androidx.compose.foundation.layout.Column import androidx.compose.runtime.* import androidx.compose.ui.unit.dp -import androidx.datastore.preferences.core.booleanPreferencesKey import com.vanced.manager.R -import com.vanced.manager.ui.components.* import com.vanced.manager.ui.components.layout.ManagerScrollableColumn import com.vanced.manager.ui.components.preference.CheckboxPreference import com.vanced.manager.ui.components.preference.Preference @@ -62,7 +60,7 @@ fun SettingsLayout() { preferenceTitle = "$app Push Notifications", preferenceDescription = "Receive push notifications when an update for $app is released", preference = managerBooleanPreference( - key = booleanPreferencesKey("${prefKey}_notifications"), + key = "${prefKey}_notifications", defaultValue = true ) ) diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/ManagerPreference.kt b/app/src/main/java/com/vanced/manager/ui/preferences/ManagerPreference.kt index 98c6bb9347..44807d7a73 100644 --- a/app/src/main/java/com/vanced/manager/ui/preferences/ManagerPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/preferences/ManagerPreference.kt @@ -1,23 +1,23 @@ package com.vanced.manager.ui.preferences +import android.content.SharedPreferences import androidx.compose.runtime.Composable import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.datastore.core.DataStore -import androidx.datastore.preferences.core.Preferences -import androidx.datastore.preferences.core.edit -import kotlinx.coroutines.flow.map +import androidx.core.content.edit import org.koin.core.component.KoinComponent import org.koin.core.component.inject import kotlin.reflect.KProperty class ManagerPreference<T>( - val key: Preferences.Key<T>, - val defaultValue: T, + private val key: String, + private val defaultValue: T, + private val getter: (SharedPreferences) -> T, + private val setter: (SharedPreferences.Editor, key: String, newValue: T) -> Unit ) : KoinComponent { - private val dataStore: DataStore<Preferences> by inject() + private val sharedPreferences: SharedPreferences by inject() private val _value = mutableStateOf(defaultValue) val value: State<T> = _value @@ -27,43 +27,83 @@ class ManagerPreference<T>( operator fun getValue(thisRef: Any?, property: KProperty<*>) = value.value - suspend fun save(newValue: T) { + fun save(newValue: T) { _value.value = newValue - dataStore.edit { - it[key] = value.value + sharedPreferences.edit { + setter(this, key, newValue) } } //It's Chewsday innit - © Bri'ish ppl init { - dataStore.data.map { - _value.value = it[key] ?: defaultValue - } + _value.value = getter(sharedPreferences) } } +fun <T> managerPreference( + key: String, + defaultValue: T, + getter: (SharedPreferences) -> T, + setter: (SharedPreferences.Editor, key: String, newValue: T) -> Unit +) = ManagerPreference(key, defaultValue, getter, setter) + fun managerStringPreference( - key: Preferences.Key<String>, + key: String, defaultValue: String = "" -) = ManagerPreference(key, defaultValue) +) = managerPreference( + key = key, + defaultValue = defaultValue, + getter = { sharedPreferences -> + SharedPreferences::getString.invoke(sharedPreferences, key, defaultValue) ?: defaultValue + }, + setter = SharedPreferences.Editor::putString +) fun managerStringSetPreference( - key: Preferences.Key<Set<String>>, + key: String, defaultValue: Set<String> = setOf() -) = ManagerPreference(key, defaultValue) +) = managerPreference( + key = key, + defaultValue = defaultValue, + getter = { sharedPreferences -> + SharedPreferences::getStringSet.invoke(sharedPreferences, key, defaultValue) ?: defaultValue + }, + setter = SharedPreferences.Editor::putStringSet +) fun managerBooleanPreference( - key: Preferences.Key<Boolean>, + key: String, defaultValue: Boolean = false -) = ManagerPreference(key, defaultValue) +) =managerPreference( + key = key, + defaultValue = defaultValue, + getter = { sharedPreferences -> + SharedPreferences::getBoolean.invoke(sharedPreferences, key, defaultValue) + }, + setter = SharedPreferences.Editor::putBoolean +) fun managerIntPreference( - key: Preferences.Key<Int>, + key: String, defaultValue: Int = 0 -) = ManagerPreference(key, defaultValue) +) = managerPreference( + key = key, + defaultValue = defaultValue, + getter = { sharedPreferences -> + SharedPreferences::getInt.invoke(sharedPreferences, key, defaultValue) + }, + setter = SharedPreferences.Editor::putInt +) fun managerLongPreference( - key: Preferences.Key<Long>, + key: String, defaultValue: Long = 0 -) = ManagerPreference(key, defaultValue) \ No newline at end of file +) = managerPreference( + key = key, + defaultValue = defaultValue, + getter = { sharedPreferences -> + SharedPreferences::getLong.invoke(sharedPreferences, key, defaultValue) + }, + setter = SharedPreferences.Editor::putLong +) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceHolder.kt b/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceHolder.kt index 960a465d56..6f719e6e40 100644 --- a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceHolder.kt +++ b/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceHolder.kt @@ -6,18 +6,18 @@ import com.vanced.manager.ui.preferences.managerStringPreference import com.vanced.manager.ui.preferences.managerStringSetPreference import com.vanced.manager.ui.theme.defAccentColor -val useCustomTabsPref = managerBooleanPreference(useCustomTabsKey) +val useCustomTabsPref = managerBooleanPreference(USE_CUSTOM_TABS_KEY) -val managerVariantPref = managerStringPreference(managerVariantKey, MANAGER_VARIANT_DEFAULT_VALUE) +val managerVariantPref = managerStringPreference(MANAGER_VARIANT_KEY, MANAGER_VARIANT_DEFAULT_VALUE) -val managerThemePref = managerStringPreference(managerThemeKey, "System Default") -val managerAccentColorPref = managerLongPreference(managerAccentColorKey, defAccentColor) +val managerThemePref = managerStringPreference(MANAGER_THEME_KEY, "System Default") +val managerAccentColorPref = managerLongPreference(MANAGER_ACCENT_COLOR_KEY, defAccentColor) -val vancedThemePref = managerStringPreference(vancedThemeKey, "Dark") -val vancedVersionPref = managerStringPreference(vancedVersionKey, "latest") -val vancedLanguagesPref = managerStringSetPreference(vancedLanguageKey, setOf("en")) +val vancedThemePref = managerStringPreference(APP_VANCED_THEME_KEY, "Dark") +val vancedVersionPref = managerStringPreference(APP_VANCED_VERSION_KEY, "latest") +val vancedLanguagesPref = managerStringSetPreference(APP_VANCED_LANGUAGE_KEY, setOf("en")) -val musicVersionPref = managerStringPreference(musicVersionKey, "latest") +val musicVersionPref = managerStringPreference(APP_MUSIC_VERSION_KEY, "latest") -val vancedEnabled = managerBooleanPreference(vancedEnabledKey, VANCED_ENABLED_DEFAULT_VALUE) -val musicEnabled = managerBooleanPreference(musicEnabledKey, MUSIC_ENABLED_DEFAULT_VALUE) \ No newline at end of file +val vancedEnabled = managerBooleanPreference(VANCED_ENABLED_KEY, VANCED_ENABLED_DEFAULT_VALUE) +val musicEnabled = managerBooleanPreference(MUSIC_ENABLED_KEY, MUSIC_ENABLED_DEFAULT_VALUE) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceKeyHolder.kt b/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceKeyHolder.kt index ac8ddda5d4..34f941eb09 100644 --- a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceKeyHolder.kt +++ b/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceKeyHolder.kt @@ -1,19 +1,16 @@ package com.vanced.manager.ui.preferences.holder -import androidx.datastore.preferences.core.booleanPreferencesKey -import androidx.datastore.preferences.core.longPreferencesKey -import androidx.datastore.preferences.core.stringPreferencesKey -import androidx.datastore.preferences.core.stringSetPreferencesKey +const val USE_CUSTOM_TABS_KEY = "use_custom_tabs" +const val MANAGER_VARIANT_KEY = "manager_variant" -val useCustomTabsKey = booleanPreferencesKey(USE_CUSTOM_TABS_KEY) -val managerVariantKey = stringPreferencesKey(MANAGER_VARIANT_KEY) -val managerThemeKey = stringPreferencesKey("manager_theme") -val managerAccentColorKey = longPreferencesKey("manager_accent_color") +const val MANAGER_THEME_KEY = "manager_theme" +const val MANAGER_ACCENT_COLOR_KEY = "manager_accent_color" -val vancedThemeKey = stringPreferencesKey(APP_VANCED_THEME_KEY) -val vancedVersionKey = stringPreferencesKey(APP_VANCED_VERSION_KEY) -val vancedLanguageKey = stringSetPreferencesKey(APP_VANCED_LANGUAGE_KEY) -val musicVersionKey = stringPreferencesKey(APP_MUSIC_VERSION_KEY) +const val APP_VANCED_THEME_KEY = "app_vanced_theme" +const val APP_VANCED_VERSION_KEY = "app_vanced_version" +const val APP_VANCED_LANGUAGE_KEY = "app_vanced_language" -val vancedEnabledKey = booleanPreferencesKey(VANCED_ENABLED_KEY) -val musicEnabledKey = booleanPreferencesKey(MUSIC_ENABLED_KEY) \ No newline at end of file +const val APP_MUSIC_VERSION_KEY = "app_music_version" + +const val VANCED_ENABLED_KEY = "manager_vanced_enabled" +const val MUSIC_ENABLED_KEY = "manager_music_enabled" \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceKeyNameHolder.kt b/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceKeyNameHolder.kt deleted file mode 100644 index d87ad826d8..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceKeyNameHolder.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.vanced.manager.ui.preferences.holder - -const val USE_CUSTOM_TABS_KEY = "use_custom_tabs" -const val MANAGER_VARIANT_KEY = "manager_variant" - -const val APP_VANCED_THEME_KEY = "app_vanced_theme" -const val APP_VANCED_VERSION_KEY = "app_vanced_version" -const val APP_VANCED_LANGUAGE_KEY = "app_vanced_language" - -const val APP_MUSIC_VERSION_KEY = "app_music_version" - -const val VANCED_ENABLED_KEY = "manager_vanced_enabled" -const val MUSIC_ENABLED_KEY = "manager_music_enabled" \ No newline at end of file From ebfab7f498bde32400bd8d22ed54bba368800a40 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 27 Jun 2021 13:33:26 +0400 Subject: [PATCH 011/118] adjusted colors --- app/src/main/java/com/vanced/manager/ui/theme/Color.kt | 6 ++++-- app/src/main/java/com/vanced/manager/ui/theme/Theme.kt | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Color.kt b/app/src/main/java/com/vanced/manager/ui/theme/Color.kt index 76e43574af..63ecdd5fe1 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Color.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Color.kt @@ -6,8 +6,10 @@ import com.vanced.manager.ui.preferences.holder.managerAccentColorPref val accentColor = Color(managerAccentColorPref.value.value) val accentColorVariant = accentColor.copy(alpha = 0.25f) -val lightOnSurface = Color(0xFFD7D7D7) -val lightSurface = Color(0xFFE9E9E9) +val darkOnSurface = Color(0xFFD5D5D5) + +val lightOnSurface = Color.Black +val lightSurface = Color(0xFFE5E5E5) val vancedBlue = Color(0xFF2E73FF) val vancedRed = Color(0xFFFF0032) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt index 94e3206d73..70970efb45 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt @@ -12,6 +12,7 @@ const val defAccentColor = 0xFF0477E1 private val DarkColorPalette = darkColors( primary = accentColor, primaryVariant = accentColorVariant, + onSurface = darkOnSurface ) private val LightColorPalette = lightColors( From 68c095924ef39193401798f4ebae239e88428b47 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 27 Jun 2021 13:58:10 +0400 Subject: [PATCH 012/118] more accent color adjustments --- .../components/button/ManagerThemedButton.kt | 6 +- .../button/ManagerThemedTextButton.kt | 6 ++ .../ui/components/card/ManagerItemCard.kt | 5 +- .../ui/components/checkbox/ManagerCheckbox.kt | 5 +- .../components/color/ColorContentProvider.kt | 8 ++- .../ui/components/color/ColorPicker.kt | 9 ++- .../ui/components/color/ManagerColors.kt | 10 ++- .../ui/components/list/CheckboxItem.kt | 6 +- .../ui/components/list/RadiobuttonItem.kt | 6 +- .../vanced/manager/ui/layouts/HomeLayout.kt | 5 +- .../vanced/manager/ui/layouts/LogLayout.kt | 5 +- .../java/com/vanced/manager/ui/theme/Color.kt | 5 +- .../java/com/vanced/manager/ui/theme/Theme.kt | 8 +-- .../widgets/home/apps/card/AppActionCard.kt | 68 +++++++++---------- .../download/AppDownloadDialogProgress.kt | 8 ++- .../ui/widgets/settings/AccentColorItem.kt | 14 +++- 16 files changed, 112 insertions(+), 62 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedButton.kt b/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedButton.kt index d48c2a691b..fb2bea852f 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedButton.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedButton.kt @@ -10,10 +10,13 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.luminance import androidx.compose.ui.unit.dp +import com.vanced.manager.ui.components.color.managerAccentColor +import com.vanced.manager.ui.preferences.holder.managerAccentColorPref @Composable fun ManagerThemedButton( modifier: Modifier = Modifier, + backgroundColor: Color = managerAccentColor(), onClick: () -> Unit, content: @Composable RowScope.() -> Unit ) { @@ -22,8 +25,9 @@ fun ManagerThemedButton( onClick = onClick, shape = MaterialTheme.shapes.medium, colors = ButtonDefaults.buttonColors( + backgroundColor = backgroundColor, contentColor = - if (MaterialTheme.colors.primary.luminance() > 0.7) + if (backgroundColor.luminance() > 0.7) Color.Black else Color.White diff --git a/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedTextButton.kt b/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedTextButton.kt index f0d97c463d..e230c38ab4 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedTextButton.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedTextButton.kt @@ -1,18 +1,24 @@ package com.vanced.manager.ui.components.button import androidx.annotation.StringRes +import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import com.vanced.manager.ui.components.color.managerAccentColor import com.vanced.manager.ui.components.text.ManagerText +import com.vanced.manager.ui.preferences.holder.managerAccentColorPref @Composable fun ManagerThemedTextButton( modifier: Modifier = Modifier, + backgroundColor: Color = managerAccentColor(), @StringRes stringId: Int, onClick: () -> Unit ) { ManagerThemedButton( modifier = modifier, + backgroundColor = backgroundColor, onClick = onClick ) { ManagerText(stringId = stringId) diff --git a/app/src/main/java/com/vanced/manager/ui/components/card/ManagerItemCard.kt b/app/src/main/java/com/vanced/manager/ui/components/card/ManagerItemCard.kt index 1ac13eba0e..93d96b846f 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/card/ManagerItemCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/card/ManagerItemCard.kt @@ -10,11 +10,14 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.vanced.manager.ui.components.color.ThemedItemContentColorProvider +import com.vanced.manager.ui.components.color.managerAccentColor +import com.vanced.manager.ui.preferences.holder.managerAccentColorPref private val cardModifier = Modifier.sizeIn( minHeight = 95.dp, @@ -52,7 +55,7 @@ private fun ManagerItemCardContent( title: String, @DrawableRes icon: Int? = null, ) { - val accentColor = MaterialTheme.colors.primary + val accentColor = managerAccentColor() Canvas(modifier = Modifier.requiredSize(72.dp)) { drawCircle( color = accentColor, diff --git a/app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt b/app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt index 64a9d025fa..60d758c598 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt @@ -14,11 +14,14 @@ import androidx.compose.material.icons.rounded.Done import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import com.vanced.manager.ui.components.card.ManagerCard import com.vanced.manager.ui.components.color.contentColorForColor +import com.vanced.manager.ui.components.color.managerAccentColor import com.vanced.manager.ui.components.color.managerAnimatedColor import com.vanced.manager.ui.components.color.managerThemedCardColor +import com.vanced.manager.ui.preferences.holder.managerAccentColorPref @SuppressLint("UnusedTransitionTargetStateParameter") @Composable @@ -26,7 +29,7 @@ fun ManagerCheckbox( isChecked: Boolean, onCheckedChange: (isChecked: Boolean) -> Unit ) { - val accentColor = MaterialTheme.colors.primary + val accentColor = managerAccentColor() val transition = updateTransition(targetState = isChecked, label = "Checked") val cardSize by transition.animateDp( transitionSpec = { diff --git a/app/src/main/java/com/vanced/manager/ui/components/color/ColorContentProvider.kt b/app/src/main/java/com/vanced/manager/ui/components/color/ColorContentProvider.kt index ae55bc2261..857913836c 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/color/ColorContentProvider.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/color/ColorContentProvider.kt @@ -4,13 +4,15 @@ import androidx.compose.material.LocalContentColor import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.graphics.Color +import com.vanced.manager.ui.preferences.holder.managerAccentColorPref @Composable fun ThemedItemContentColorProvider( content: @Composable () -> Unit ) { CompositionLocalProvider( - LocalContentColor provides contentColorForColor(MaterialTheme.colors.primary), + LocalContentColor provides contentColorForColor(managerAccentColor()), content = content ) } @@ -20,7 +22,7 @@ fun ThemedCardContentColorProvider( content: @Composable () -> Unit ) { CompositionLocalProvider( - LocalContentColor provides contentColorForColor(MaterialTheme.colors.primaryVariant), + LocalContentColor provides contentColorForColor(managerAccentColor()), content = content ) } @@ -30,7 +32,7 @@ fun ThemedContentColorProvider( content: @Composable () -> Unit ) { CompositionLocalProvider( - LocalContentColor provides MaterialTheme.colors.primary, + LocalContentColor provides managerAccentColor(), content = content ) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/color/ColorPicker.kt b/app/src/main/java/com/vanced/manager/ui/components/color/ColorPicker.kt index 4bcb7fb667..268097c04a 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/color/ColorPicker.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/color/ColorPicker.kt @@ -2,13 +2,17 @@ package com.vanced.manager.ui.components.color import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import com.skydoves.colorpickerview.ColorEnvelope import com.skydoves.orchestra.colorpicker.ColorPicker +import com.vanced.manager.ui.preferences.holder.managerAccentColorPref @Composable fun ManagerColorPicker( @@ -18,9 +22,10 @@ fun ManagerColorPicker( ColorPicker( modifier = Modifier .fillMaxWidth() - .height(400.dp), + .height(300.dp), onColorListener = { envelope, _ -> setColor(envelope) }, - children = {} + children = {}, + initialColor = managerAccentColor() ) onColorSelected(selectedColor.color.toLong()) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/color/ManagerColors.kt b/app/src/main/java/com/vanced/manager/ui/components/color/ManagerColors.kt index 7a5905fc20..4a38e1d503 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/color/ManagerColors.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/color/ManagerColors.kt @@ -4,8 +4,10 @@ import androidx.compose.animation.animateColorAsState import androidx.compose.animation.core.tween import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.luminance +import com.vanced.manager.ui.preferences.holder.managerAccentColorPref @Composable fun contentColorForColor(color: Color) = @@ -15,7 +17,13 @@ fun contentColorForColor(color: Color) = Color.White @Composable -fun managerThemedCardColor() = MaterialTheme.colors.primary.copy(alpha = 0.2f) +fun managerAccentColor(): Color { + val accentColor by managerAccentColorPref + return Color(accentColor) +} + +@Composable +fun managerThemedCardColor() = managerAccentColor().copy(alpha = 0.2f) @Composable fun managerTextColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.onSurface) diff --git a/app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt b/app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt index c290fada5c..6312715e3c 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt @@ -14,7 +14,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.vanced.manager.ui.components.color.managerAccentColor import com.vanced.manager.ui.components.color.managerTextColor +import com.vanced.manager.ui.preferences.holder.managerAccentColorPref @Composable fun CheckboxItem( @@ -39,8 +41,8 @@ fun CheckboxItem( toggle() }, colors = CheckboxDefaults.colors( - MaterialTheme.colors.primary, - Color.LightGray + checkedColor = managerAccentColor(), + uncheckedColor = Color.LightGray ) ) Text( diff --git a/app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt b/app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt index b3d20e85e4..8db2b0e350 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt @@ -14,7 +14,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.vanced.manager.ui.components.color.managerAccentColor import com.vanced.manager.ui.components.color.managerTextColor +import com.vanced.manager.ui.preferences.holder.managerAccentColorPref @Composable fun <T> RadiobuttonItem( @@ -38,8 +40,8 @@ fun <T> RadiobuttonItem( selected = selected, onClick = onClick, colors = RadioButtonDefaults.colors( - MaterialTheme.colors.primary, - Color.LightGray + selectedColor = managerAccentColor(), + unselectedColor = Color.LightGray ) ) Text( diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt index a19d1de7bc..d41ee2b719 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt @@ -6,6 +6,7 @@ import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEach @@ -15,8 +16,10 @@ import com.google.accompanist.swiperefresh.rememberSwipeRefreshState import com.vanced.manager.R import com.vanced.manager.domain.model.App import com.vanced.manager.ui.components.card.ManagerLinkCard +import com.vanced.manager.ui.components.color.managerAccentColor import com.vanced.manager.ui.components.layout.ManagerScrollableColumn import com.vanced.manager.ui.components.layout.ScrollableItemRow +import com.vanced.manager.ui.preferences.holder.managerAccentColorPref import com.vanced.manager.ui.utils.defaultContentPaddingVertical import com.vanced.manager.ui.viewmodel.HomeViewModel import com.vanced.manager.ui.widgets.home.apps.card.AppCard @@ -39,7 +42,7 @@ fun HomeLayout() { state = state, refreshTriggerDistance = trigger, scale = true, - contentColor = MaterialTheme.colors.primary + contentColor = managerAccentColor() ) } ) { diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt index 991d1660bc..81189fee3a 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt @@ -7,8 +7,11 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Share import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import com.vanced.manager.ui.components.color.managerAccentColor import com.vanced.manager.ui.components.color.managerSurfaceColor import com.vanced.manager.ui.components.layout.ManagerLazyColumn +import com.vanced.manager.ui.preferences.holder.managerAccentColorPref import com.vanced.manager.util.logs @Composable @@ -18,7 +21,7 @@ fun LogLayout() { floatingActionButton = { FloatingActionButton( onClick = { /*TODO*/ }, - backgroundColor = MaterialTheme.colors.primary + backgroundColor = managerAccentColor() ) { Icon( imageVector = Icons.Default.Share, diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Color.kt b/app/src/main/java/com/vanced/manager/ui/theme/Color.kt index 63ecdd5fe1..3bb279fc4a 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Color.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Color.kt @@ -1,10 +1,11 @@ package com.vanced.manager.ui.theme import androidx.compose.ui.graphics.Color +import com.vanced.manager.ui.components.color.managerAccentColor import com.vanced.manager.ui.preferences.holder.managerAccentColorPref -val accentColor = Color(managerAccentColorPref.value.value) -val accentColorVariant = accentColor.copy(alpha = 0.25f) +val primaryColor = Color(defAccentColor) +val primaryColorVariant = primaryColor.copy(alpha = 0.25f) val darkOnSurface = Color(0xFFD5D5D5) diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt index 70970efb45..30f1da9b02 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt @@ -10,14 +10,14 @@ import com.vanced.manager.ui.preferences.holder.managerThemePref const val defAccentColor = 0xFF0477E1 private val DarkColorPalette = darkColors( - primary = accentColor, - primaryVariant = accentColorVariant, + primary = primaryColor, + primaryVariant = primaryColorVariant, onSurface = darkOnSurface ) private val LightColorPalette = lightColors( - primary = accentColor, - primaryVariant = accentColorVariant, + primary = primaryColor, + primaryVariant = primaryColorVariant, surface = lightSurface, onSurface = lightOnSurface ) diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt index 7b3e29eb60..3d46ffd975 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt @@ -27,44 +27,42 @@ fun AppActionCard( showInstallationOptions: MutableState<Boolean>, hasInstallationOptions: Boolean ) { - ThemedCardContentColorProvider { + Row( + modifier = Modifier.padding(horizontal = defaultContentPaddingHorizontal, vertical = 12.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier + .weight(1f) + .wrapContentWidth(Alignment.Start), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + ManagerText(stringId = R.string.app_versions) + AppVersionText( + stringId = R.string.app_version_latest, + version = appRemoteVersion + ) + AppVersionText( + stringId = R.string.app_version_installed, + version = appInstalledVersion + ) + } Row( - modifier = Modifier.padding(horizontal = defaultContentPaddingHorizontal, vertical = 12.dp), - verticalAlignment = Alignment.CenterVertically + modifier = Modifier + .weight(1f) + .padding(start = 4.dp) + .wrapContentWidth(Alignment.End) ) { - Column( - modifier = Modifier - .weight(1f) - .wrapContentWidth(Alignment.Start), - verticalArrangement = Arrangement.spacedBy(4.dp) - ) { - ManagerText(stringId = R.string.app_versions) - AppVersionText( - stringId = R.string.app_version_latest, - version = appRemoteVersion - ) - AppVersionText( - stringId = R.string.app_version_installed, - version = appInstalledVersion - ) + IconButton(icon = Icons.Outlined.Info, contentDescription = "App Info") { + showAppInfo.value = true } - Row( - modifier = Modifier - .weight(1f) - .padding(start = 4.dp) - .wrapContentWidth(Alignment.End) - ) { - IconButton(icon = Icons.Outlined.Info, contentDescription = "App Info") { - showAppInfo.value = true - } - IconButton(icon = Icons.Rounded.DeleteForever, contentDescription = "Uninstall") {} - IconButton(icon = Icons.Rounded.Launch, contentDescription = "Launch") {} - IconButton(icon = Icons.Rounded.Download, contentDescription = "Install") { - if (hasInstallationOptions) { - showInstallationOptions.value = true - } else { - showDownloadDialog.value = true - } + IconButton(icon = Icons.Rounded.DeleteForever, contentDescription = "Uninstall") {} + IconButton(icon = Icons.Rounded.Launch, contentDescription = "Launch") {} + IconButton(icon = Icons.Rounded.Download, contentDescription = "Install") { + if (hasInstallationOptions) { + showInstallationOptions.value = true + } else { + showDownloadDialog.value = true } } } diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt index 025c95f8b4..3e4b17b5d6 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt @@ -3,11 +3,13 @@ package com.vanced.manager.ui.widgets.home.download import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.material.LinearProgressIndicator -import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import com.vanced.manager.ui.components.color.managerAccentColor +import com.vanced.manager.ui.preferences.holder.managerAccentColorPref @Composable fun AppDownloadDialogProgress( @@ -18,10 +20,10 @@ fun AppDownloadDialogProgress( ) { if (showProgress) { when (installing) { - true -> LinearProgressIndicator(color = MaterialTheme.colors.primary) + true -> LinearProgressIndicator(color = managerAccentColor()) false -> LinearProgressIndicator( progress = progress, - color = MaterialTheme.colors.primary + color = managerAccentColor() ) } Row { diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/settings/AccentColorItem.kt b/app/src/main/java/com/vanced/manager/ui/widgets/settings/AccentColorItem.kt index 3319daecfc..30a8dfaa0e 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/settings/AccentColorItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/settings/AccentColorItem.kt @@ -1,7 +1,9 @@ package com.vanced.manager.ui.widgets.settings import androidx.compose.runtime.* +import androidx.compose.ui.graphics.Color import com.vanced.manager.R +import com.vanced.manager.ui.components.button.ManagerThemedTextButton import com.vanced.manager.ui.components.color.ManagerColorPicker import com.vanced.manager.ui.components.preference.DialogPreference import com.vanced.manager.ui.preferences.holder.managerAccentColorPref @@ -11,9 +13,15 @@ fun SettingsAccentColorItem() { var localAccentColor by remember { mutableStateOf(managerAccentColorPref.value.value) } DialogPreference( preferenceTitleId = R.string.settings_preference_accent_color_title, - preferenceDescription = localAccentColor.toString(), - buttons = { - + preferenceDescription = "#" + Integer.toHexString(localAccentColor.toInt()), + buttons = { isShown -> + ManagerThemedTextButton( + stringId = R.string.dialog_button_save, + backgroundColor = Color(localAccentColor) + ) { + isShown.value = false + managerAccentColorPref.save(localAccentColor) + } } ) { ManagerColorPicker { From c882e448cad56863dc1abb36aaed6b8c343f6623 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 27 Jun 2021 14:16:42 +0400 Subject: [PATCH 013/118] fixed splash screen --- app/src/main/res/drawable-hdpi/ic_splash.png | Bin 9280 -> 0 bytes .../main/res/drawable-hdpi/ic_splash_logo.png | Bin 0 -> 11966 bytes .../main/res/drawable-ldpi/ic_splash_logo.png | Bin 0 -> 5705 bytes app/src/main/res/drawable-mdpi/ic_splash.png | Bin 6555 -> 0 bytes .../main/res/drawable-mdpi/ic_splash_logo.png | Bin 0 -> 7763 bytes app/src/main/res/drawable-xhdpi/ic_splash.png | Bin 13833 -> 0 bytes .../main/res/drawable-xhdpi/ic_splash_logo.png | Bin 0 -> 16122 bytes app/src/main/res/drawable-xxhdpi/ic_splash.png | Bin 19270 -> 0 bytes .../main/res/drawable-xxhdpi/ic_splash_logo.png | Bin 0 -> 24774 bytes .../res/drawable-xxxhdpi/ic_splash_logo.png | Bin 0 -> 34484 bytes app/src/main/res/drawable/ic_splash.xml | 2 +- app/src/main/res/values/themes.xml | 2 +- 12 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 app/src/main/res/drawable-hdpi/ic_splash.png create mode 100644 app/src/main/res/drawable-hdpi/ic_splash_logo.png create mode 100644 app/src/main/res/drawable-ldpi/ic_splash_logo.png delete mode 100644 app/src/main/res/drawable-mdpi/ic_splash.png create mode 100644 app/src/main/res/drawable-mdpi/ic_splash_logo.png delete mode 100644 app/src/main/res/drawable-xhdpi/ic_splash.png create mode 100644 app/src/main/res/drawable-xhdpi/ic_splash_logo.png delete mode 100644 app/src/main/res/drawable-xxhdpi/ic_splash.png create mode 100644 app/src/main/res/drawable-xxhdpi/ic_splash_logo.png create mode 100644 app/src/main/res/drawable-xxxhdpi/ic_splash_logo.png diff --git a/app/src/main/res/drawable-hdpi/ic_splash.png b/app/src/main/res/drawable-hdpi/ic_splash.png deleted file mode 100644 index b316b5cca44e7b38a78d6a0ab9780a708ab4d6c1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9280 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 QEkS4sGOE(mk{<*92P>+gd;kCd diff --git a/app/src/main/res/drawable-hdpi/ic_splash_logo.png b/app/src/main/res/drawable-hdpi/ic_splash_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..bad8cb8167d8d8e591ebd14b2f1b065444d7fb12 GIT binary patch literal 11966 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-ldpi/ic_splash_logo.png b/app/src/main/res/drawable-ldpi/ic_splash_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..30ba36ea71e1f5b85974b82b3f07f923f5a61d59 GIT binary patch literal 5705 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/ic_splash.png b/app/src/main/res/drawable-mdpi/ic_splash.png deleted file mode 100644 index bf18b1efc190507314b483899f5b9857f71d7acd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6555 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 diff --git a/app/src/main/res/drawable-mdpi/ic_splash_logo.png b/app/src/main/res/drawable-mdpi/ic_splash_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..36c3cf3ee6e6e97d3186e7e1de76afadd682f50d GIT binary patch literal 7763 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xhdpi/ic_splash.png b/app/src/main/res/drawable-xhdpi/ic_splash.png deleted file mode 100644 index 25f4b20c29e4d95356a24a3d2001369289b16339..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13833 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 diff --git a/app/src/main/res/drawable-xhdpi/ic_splash_logo.png b/app/src/main/res/drawable-xhdpi/ic_splash_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..54b52d0f5b71c7fcc7c9ac9ee752617e52fbc1bf GIT binary patch literal 16122 zcmd5@^;aBCu*EIN;t+gU+}(W%3j~6@dyoJjxD#Y?4Fq?0{eU3B9RdV*cXxlA_x_3Z z!<?Pdr>A$iy1M69)xF^=%5qp3?=j%u;IQN&U^O^6__%);8Val>pp$<T_Ji&O(RG1? zBcl6v!ON?G&f(yw;pD+m8Xg%ZE9f2?JM9wZXCH~E(b0o`1MnneRq!lvE0EZlWy<ZD z^}bYk5H8uWG#sA1t!niZrY{mTXtL<#xE2nZRhrDaZ(xnUK!aaM3FbUrxJ!MII7{Uj z`Z$|9lp%EHJ$`p3%Ed{)F`AlqmAUpy*hicS3WWl9wn=G$c{ZGqP$(laCIASGz(5R! zLi4)eXn=Vo|KFO!MI9{Y*tK`j;Kb6z3Z)+9ynFAWZ1&!${zwQXtPQ`d9lH^yoJ-S| zJKy_=ca(q%txP#-_DR0Kv3AhQ)M`7u3y{n~LRCM{CKU#Wp`fJ#8Oc%jo&d2}d*xFl z8o}YODUz=Bx;WIKn5hx)(xJ{R+zd#3Sjeb-l36!D_440po+WFb3jHVS*u_K9jJBA7 zLxL0*9snRPjwIKnK0(uAGQE!<6?w$UI}0O%4+SkmshW|5VD^uw4u8E_E`&?6BqXN{ zD9Aa_Vd`7h6_^)>QBG)!j~E=p5-Dj@6B`s%Ir*fmQ>uc70v&5MNd2CsNxXI9r_5-E z`n@d4CkCaS0|nZ55XeQd|9u9T)KpO=XS-gZ78TaG|3VC8EUFWV`1p+zKo6%?BV9|6 z0!7}}?ALhtuA~N{Rn4vV(-TZ_MbrhSnk1g+oor<36iiUMokK|<NlI^P9>54Hnff_W z#8ihC8s1GpoiP2xTXZ;sl3qMG4E{Mfm)<guUJZu=Ex4vHYw_}MY7$r&Q)p+_?b0?f z!UPP#-nL%H0l<f$K^G~MpeT+BK;IwJaJgAGSwm4(G)w)_2mCnSMu&p}4Zl{t(Dm}D zNsV9>RfHQgkNX)5Z-yWyxC`Gr=JqLz(TxN|ZywMazp6nOWFF&?#T$PCYcUPzl~SQX zO)rB+sg}7nO;}rdKXXcA7R8pO4U9YIH3Ou$=T6v-MyDM_QJ_-Sp5#|T<SBy$cGuJ! z$8LyRl4ema<X|=3oV(Z>-4Qs<IFhd|+{K6HGYb<^ARI1I=j0{BjEOl=6A3j}jy45Q zu!!-^0$LF{1Bv326b{!!jaLKnasTk8t?hyfPcU*F-LsGc(ur-l5l?I>&Iw`0G49h= z5V_DY01GQ8%W?TX%MO)ptENM;=i(>MsnxPb%={(&Wgx010pQ;|!vvZGz*~2KZs@(? zYC$Jg0a`6O3#OMpYB@I0P9HWV4+Qud?jXQub+`VIx(@j^5*(nUbMhx_pIa1qEOQ;X zeN>747aj#dcFjMzgNXxNA{`&UIj=!4CuG+yBB6S%`G#7Q6BYGsdwcsZ+vV6#cr!02 z2d=Qtl96$~$hW8@{D&`t)0F8F3H8`MZKa?PCk7C7d3o6oySz*uMIoZqvS%WDG*>;) z<bbU6-<QnWE|qXJnF0#TIBLw;K}&0E^QnUH=7-(%_(YzMjXnPr1_hmXY()#y*v{Az z5D_iDd<*_gGlhZzjoH8@#U=S~nftqD=qA|p^6^NqQ8L$!3#``#XX+8G#H%`%B}V4H z!bf&+a1cSx7m{C5fyvQU19(TwZh^18L;@U}7ndZVq%e1yNBv$PgBefVgbhexabXXT zfH*Nu;VEh2h&oZ#)zuyQG20iGl%RbQe-Pn!XjBd!q*mr{a1PkN5+#y%VpPM+-1;OT zmhDT<&+rI2ZFgrES<+w3(*`zS<LWDe{#yU!5nZG%i@}lb$=;A!<fE=ac2-hB<63YE zS@{%x!VIW#nBkwCyO=kRHS3Qet)m2{+8j(3dYpHK%?scS&%WbaWR|?XaRBelNup!R zF#|=D+4TEc$p5l)g;_jaA7I9-{P%06FVa#t$D>vsUrW3vpN`AUXRCjLgz_(qb2QXW z)_~`)O}ydUSe;V9evfNQwj9sqhZ_3@eex_tQ~bGzW-AgPjeSc{H5&q$%DJzFa*R`y zQ4ceoi2HcH^veU>q~gc}9(jZYY&>09YyT08=Tc~)$Ycwl!x1>F#b&_DLxmN(aAe+Z zFdB11p8|WEhdT18_zI)IQFD)AjHo6v50#30mUzp>M%lDJw*#D7`vBOc#)lh?Usovr z?s_^k5cZ`t7xgyEzUP{nChGBGBc=9wT=Gk{aWUfpE8~Ikp>~P}<^`#F)gGpwlaCQ$ zr>CsP$A3@L%r@aEs?{7sM1dY<s@g7Xt1@@2A7qKyh^f7%XXO69cQS{+VnkzQ@1~DM z)b%wcQyN2`ov6biRuNSgNUL?FFS!!TN=R)`R^Vzz(}w(Rv(vWSL!i~`#<s%nm(fyW z`kBI(3}*S*&`@8qvpJXZCRn{}T*$?*yKp^S$4w)71_2z^>ZKDT6CX+{<JO{7W-vPM z_fy7OhWy*FNL2Z6qFm;w%HLp~1%RzgZK6qAcTeY^)o8sd<Q^Hy%|<|VxQ9cp9Rbc} z8vY#RXB0ixpj=C4m?x?yLAU4x2|o9hKLXD9v%L=87qv=25?pGBuTN)@Bd%S{1@ZeT zR2y!@RB_uLX5Dy%P;rBpjmeLqWjGfxT2Za09wjnuTGPdACLVm<%ph>6c<q83t7;(3 z^r-XBl+2Vfr~)Kv>CGRASakxz@vHfcJ!>#Ncd1bv4r^1xzJvy$a*BCdfA`M;-j-MW zIqVmUV`;9xZuQ>F8hl^I76>jZ0~8{HshaG{XE=H+w>ccBMF-#a+I_Zwa!N`^{Wpc_ zI>Qpzvb@wr_a+KwPM;L+<}zt7I}0>Y&wm8>HV)FQ$>>;lqgx_^tHtm6n+ZR(Z{eRT z<PCiv)0)M%8ON)x#nlN3CMj|JS}gj51)xRc@RRp*9*u-H=FE=$*CV{@N{{GhlfQhW zoQk~dETq&G;*0b|N~6QW5f2lD^&>(WbC11t_Pt(~n`s1d^n7(-!aQ5#?!$a6PfyR# z=VgX$-rY>5p@EXQ#S%Mp(_w9zVPv%O*xPXAYcr)bTEa-01TpB`B9yroYNzgus7V!H zXok%FV@7VNm${<0zli0DYm-l4bFl%ga1E1106(*Sd}+^(c;I@EkdV;ydOy<KKL^xq z_^Tu4!9pX2C6U8Nad=!=y9{A+L@ZQ}EXu~*sL|GS)Stdo>Uamw?ils+kGjl*GCtGV zvwR9OhkPCLHMvAykQtJf3FnlB5J=`?OlEnx$Wbmg1FVUyBhh8x{2zsoP;K^!-5wln zpflT}DY=(j*G9mnhKFvN*W!t=_LARL8U4%ys>f~`Y5u>tta|OTQv{M774!rY`&4y@ zkzmuk$A6)6%W!26GH*4f{vz3QYmG}3Ef#|9?;%Kzow23ZV^Xk5@91yuoV1=2vm&@z z!gaT94r#kJvuY*P-&~AKfX`FIPo^t+C1awcZTdcaEO_)xE+?Gz%_!<jcw8!ic8H1` zyK)zB6ZY1#VdEouez(y<sk2QHnBG2n2x4bsgdR*p-tgJdC}1CG0wu3W)7vhE0Y}J3 z$6CG_Cy)VrbmA>mxmHTNT+={oX%M0OeeIb&>qS&=ONT~cc63H_iP^6t@5BlPWV6(r zSj{?zCH^H*ZRe{uhfO+&RKo1X83Mfc5a_)Rwp#5x51zXR>d)s2VaF4_TkYOSf*IlI zLL9(Lurll@8SM5;;52v_D~a}vAMAs@-r0^=Q(?;c;Xy}KeLl&nzCs%2Jl`>01M7*| zom<mFr0t~(I9fMjvkXRWGIq}57;LlE#&npG&_pJNRCw@1ALX<g(L&~fq4%OaDdC;` zm;;Pda=fa)LVp>g(rO6Fs-Z$xefSK5WN0D}w;)n6SEKzk0f97|cry?gcE2OiVcX!v z{Lyr)1r`9maeQt^{GV!Bo!`F!xUt5&Cm}mG`R7WGpE{cVzPCK}u0usjuO3us$$NBa zz<ftS4lITIWsbKd`}${ME`);{nXE*CC%FN>dzU35Ohc~DtzLi@+`AXw@vYKvo5)e3 zW0l}zxWELrHnn{Ru!nDDbnIO`FUTau8jxj2(r+7#kktG(L{5zl5=5yJ%m&c_qs}c& zJbNIcx4nL!yw%1f3F!$HNU0y28Z$&8p(4BGU)mN%0Km;FidEJ&1Am&(do>UE`Sfc| zXayl!IZj06%W6UqSu2=^n}q3J|0U$U)S9}LHjwzc7?)&TFI;Z({ir(mdlI}5sK>L_ zCkfaP@a&gg5%RF2=k(1B=<EV&5HmM7o2&7b+6M};aZ{>Uvg`z@BpgV7+xGeu`0=nA z2JBPFE#GBqT77<TJIPKE0{2>T{dKoILHl@~)fL$zPC|`qc175y8Mr5SDTdnUuXYQN zcL8mNKe}9KytM3}n)8_<s{PkL*i4Os*lPv@FpECY3kwT_<EI|;ht19oZ&9}}G{av} zZO2&tVJD_%(XDX|`O8)pc}H?=Ze#TgyydTV8><b7U2lr9vHcU9>VxLuzxBT%xS}pc zuWkQ%GrV}4xU*b$G@R%vDxc_@+hJH-5v$8FNoV_yz6s4iuzJbRN3y@T2QHT%izF^O z-La#k4@+D?fS8mtH?#HNfOK$(wCH%~<HxhmC`U~GZR_Hl%&^g=D%hRzRQMU8_o@I6 zB`$9lS-33OGJ*PLR<lmOI<sa#&6^B6kJacO@xe40v}uUlrB`lCu5LCUp*B^sqVUm$ z?$W4Y!LXgpm=u^Bf9~LN$B|D<*wS*-B~S~!aSqekWvXdd(5JHDA+2v`I0MHdh8Got zi;LaTBDBbnW1|Jgo}LyG2&k}pdA!k!gR1EM!+5E@*3Bz@baj~+3kV?Nk6Hh|+tdg$ z*HRzTcxz{hP=F#j?T=y=dX4YPwX5r{OaeZCalgPokD(2=hX+n{{RH#M{R4CVEq~>a z`CgJ*sF<>OGnZmJ6Fw&T4<#p_Fe&0wKcX<Fg9HiGk%G3Wep%IjjwnIQD?J)w@V73e z*4=U=R-7XSPJ^YF+;SrS%r{@~Ec?ItV&dd+LLbCNlH0@kB8e9)&!I_oa<DL>H-zIu zf#~BtEhcszBa~)<%J05oR@=szl=~E?8;&b{pM;p$ubHPXyu@{LY%U1d|M&E#2}iE3 z8MA_4a>Kkhz5MXNv<mQyl!g3*G2BD;Q}zNh_xxrbdmuOx)4#}U%1&9Cz35Z+mzhbu zO-iO22rHBD<js_Q=K(4n>ZT!{wR@sv<sfR&%3OnFK@WU&&w(+?R}~49dw}2v%s`iC z2*}5!fW}&ib&}g|_CzZ~252bP$_fuu9+oSjf_9NmTDW$gyLa7P6!p)9wCh0y$q;3q zL^7f`Hrwox66lR13XV8JTujz}W>RqVybQBcH!U9De*fZLtMNizcO9tX2QSOj9kC&$ z#n9bNcJCB1fiC6m)^zW(vRGMizmV<ByywlBdJR`*>?uKS4Y`hl;_49{;m3c;l+;D& zoqC}%3x=WrfFtQonf*@ZNMZ6@YxsJv{$eV&vqU-Drw@W@-l%0pFE!KF3KiIF(!C1T z4_~L^3eoL&0yd^Hevsge#Ix$(5``TkIC#w22kmVso!c)Up5^AB`!s4h4%^yxT=IX( zDSQ(vnE;*hjl=u?Ia=_ZbT#-=th~}4!m-(fN>w*}(7AlVKAy5J$Xka5wM^lBIPbwp zT4ngoNF-`}61can`q%%G@O{T(*kYr84|Y<L{F-F8#448c2iw1L+`f;|TB(ifGYRxX zsL&rNoVa6J_N_o$!!Z#um8%J?lE*z1kKuBe9uT8S?;6EH>Hgc?Q(OY^N;(%8_YusV zb=~Ky$S@~1K#!53m7#)ut7kEn8s#Rw5`&hw8dm>863a?|H#eK&)Sta;lV8(D^Fpum zLWi}(C&>At&FHz6STbIu^HZaO&l+CsCU6iyoqR0mzYbqzCrf}m$@_!<3d6#|kFx#s znpP0?+TqyXj+boGb)SJF*XcA;HB<W{bQ~eS&I{s%8LbmYBB?<|UZ+UVa;;BqvM%?D zdaKIuKdy+8aD2zAfv)UVy36d$tS=$V;Igg{m;glR;df}>)+j`3ZNRbbx21$!cYwIk zn6A{7Tuf&R{F7fRXfxX}gt>QTIH?FDo<@?j5iz$}kU=?vu`3=>%Eou*lkwDLzMsHT z)0cr8OA9}c>>JVj@D{Z%6v5n!z;dTBee7r(Fql+O%k8`gy7dM0L8QGfLOb5j#(#2E z&7enw5moe03P?onQ`Jib)F4diRv{X)PAh|JU1!f6<tEZEubB%ze@iZb+=_M}@W~c; zzuxt>vGxh%njz=a8@z?huZKd-&N9|kLZj?HH0<kCmzVTtOBj$(b`A)5{fn`4+uB4& zM2Uf<nNNQ!_xV{xY@pShF75WkWZv26{xl!@{Iv^peUg=QxRO!^R*=J^l76mY2~DiQ zTYD+&7swRjKfSeL&xCynyQ#i%=i?v61}M7b#gYwR1P|I6)_a+)x8ut^N+T%g{(2=? zZIU+2iPYKGP(4PR)Gb5Uc-;kGaGA_n?mJ%yjop&U|IYoPuj1MasxSvEtuZspB=_)( zNEQg;W)`0RA_dazyzUlh-BB!DET`3E#SC}WKk}~^@vuo+ERht}6HpOB3NpUDOi1qj zRizQ3^2$&q_wZ&p9I+Gj5sv6QsCN(0seGel2qQ#OZNqBWi?Cw3f0VfGY;WwLHBEHc zOC_aFE|Z)OR3`9edhw?A9v&oOxjXg#MO|U8+Potfk=s@wX%?)c1K!<t@ADjcl)`iR zI)Sc1;NIp*;O{6hFbY@u7bIP4iiO)}yh|t(_orPSVhp`!99^5<sAUwT>b>=)PDTgB z{04Gszp;ci%?BS27WGh2s(%QrLzHr$qE7zYt?=o;Q5y>&-3_IfWVv`ydR;^(>*;yv z`Izw@DDB=+v9Vsu+DR7)=yF4mS&15kD1HHtYRfD}L7CX?ORa_}onR`%1k6*GKT3)D zl1fS=<B8wuesV6yyzI^-TOY;*Z`LRuOx~?%(ZQ14h8@20>#>KnoveSnowve#6H>9C zIumT!l8F{RXwV*-5xykejL+bf-J801i}9ob4uEAGnC}i-V4>>r>81})Y*z(6t0FR* zbpzfIZNfPmOPn$nizMrRKiF_fnMBfEn)57o8CezAIVFKD_MYZsv*PVWB1NZFydNLO z_;9u9A^?uP3&Dll<M1>IVf$}r!C@+=RloaFI&ALl2`G`wAAOUQbTX6T<EySO@O6ha zIAR+-_@5+%2IuCfGf=1G4f-=7lrM5OcFwHUhWs@vTk6gDD@}xGxT>S!9Wn2$c^x!a z9wqyiomGFmMRg~lD>)8vmE-%i$-jLW#UlAl69DFJ`8KY@#ycFFq~CaD@V)|;e=;8o z-=3yp6WSaKCJ;hF!(GVAgExCjICaK>#h}w_^?!t-QXsx-i`u!HE;jz(B*}lO2I|-n zc`1)`qQ?Y5g|~`U2z3mnaD=diL}PJH@QH92R)=2OojMpu%M~6siZw|gcNeoH*jaSI zI<ah-4EV5H&o7!dZSIR9wKo)J3})__amwq$I$*7hwINOb@TFZ|M{g1Jig_Zg^*xuj zBOT9p6hV5|0D{P$@QN-^Eq@2H<#hnAe`kK{FRkd06({sZSG=w&38eVwZ1~im&c(b$ zM&nL=*ARwvg8z`RaXy=e0bz$yhu7ahftqR}lJ}_V=iydtClZ5~^k$}>j?d*y7!n75 z7?#)^pE6=bS`z8_k~GcN%txG_$FQ6pMIqN->(`#~>sP-YL^xV+&%!(IKFRivt!*Pq zzOSU}o%4bUuJ`b{GTmQW5Q}DL1r-{yIQUQf7LOY@rGjP*yAznN>~w-JE;-g+g*RM5 zIbEqaCqGV{K{l~7<l-TDEgYNc4FjsbqRSiAY^F8s#&o6M<DEZUW_i>X2-Jz8H%ZvR z>;w6<r*>Lb%2C~Ay`~RcjPPP(L<pSJgL;rFYuL|+_-emUElc=euc~#FH<X|1zUU!+ z(5C@X{wnBTS(R8Jt}mam_gy8SwqQc;^doNk;W`$S_W}zfvR|M4Ywq&Aoe#r1uYziF zdHQ3&@Nq7}z`rrVuIBA;{o)C*vP^<5!`NTtZzyQGp(Wzj9WOtK&?wnBf$!o&Bi@ty z+md2OwW9tw^Xq@tV+CdezXxtkr0{<0dn$fh?@&<J1KA5ixd)-Y(J%bIh(_ITrRPPF z=A{9?8t8w+ko)3|(U(Xi-IHtH_RYR~E*yZHeO7)PgQI*SWn@Ual)<A#of(&&ZZ|(s zG?=;SI!cAag@${fGxJ#OY_q*0c;oMH`UX{k#cQE_ppCHvo(mgK6mI((aty=*{AQ|F zgSHq+onCfWsFNVk8QIg*8GE_6+VsTK#3~odD@HC%1?<k8`Fy`_;kZ4c>+SsE-xTk6 zZUphM&~Ya_zaH*II&XI`l)Ox68SxS&I&G}y?0huChq-9D9_rHz;R>7gKckXvrf4ID zsKV@B&H~#{b8iU6R^r$bx%q7#ti5xB#2_~synQmy)`~E?^oD=^qm^_}!k``%UuQm$ zx34Q}JU<fNEBsiFf~KJ_KS!g*r<bYM9BX_U2|+^)W|gt){tD`41NTlaJ&hd+CcB8( z8hK_DCv5tlgbmh&TCjmDg5jsog@g=-!StKNO&1@i1^^dHb2-~#{=W~}eyP3<5&i1K z9KKw;j>f^A%&;W<x8Kz0zkaTe{0K8<i`x=>lFyNKN!yXU2TtqB>sQ7>+!O%rn6A5K zq24AeM?J`$7J89J4BR}^toDUYDf$JZ8M6mg2fxsk39d5meWAI8c%pnYuYZ;gPc2S? zmrmZG3YmE>a#V&wEmh0>Zn%dzQllR`D|cm!0z#9jq~J|_praho^6IlzJQJ+{rueM( z*drYSz#W)W@j&>o=8vGMJrU?W^2Nv=&yEzMKXj1uQ{ANt_@C_p;o@Po$Ud6=BD*7C zm47>KT&t_7Rv8vlO9Qm37-`${lKa=KOG$@26lUVn9sgXf!Dt(gV>%;`gav^-s$q(( z=1?da&W}3+(||ZjUL5RtY0$&eyFYh{$oustbRc7iDp{z<u&v6|z1d&v4)|3*<4c63 z-qnp4&e9_{pCpy{bAXl>df5e+emI&Dv`mPN5tKJcn^wpjfLH&Nv&SMKH{qTg;Bvnn z2blCz-r)Lc_+tLo*jd179gPEw4#lwelJerg`Jl2a4X#M#t8FSz*o%b6qdN^_r>gE* z3$}EFY7i1^{!R1``>#SlL~bZ$H*e1W71|)NhI2+r%9h^zT954dy}0KoaSf4f$IYL# z@Z4>)v^jLJw{^b^@ZT@Nwb83SxNtQuuh4`62TO4zgsx|R(CaogfwBkOPPM>`pL@C| zp_hYk&^FcDJP_P_$18f}?lGQ)FzP>Z%27xFhKk1f2(r_Bb#M@%o4|#wP>%!#i&Pq* zlu0-wU&4<_j$R@vtr2<gvs*zi@I+uuu0KXQ?tDxYhUL|@uqJ%3HpsZ}1yx2Pr!A^M zlmmO?7(Fr|EOe{Wa!NiPgx<g592SO3Jsvygu)VzVNWqx(%&GjkAFJ0H7RQ-`(^~C^ z5wjtq7Ye;!t@I`VCV140<ThhoQ0P}1NkB>A%?|&1*H!)YqlT^Uy}_fNc#O}Lc+$)5 zP5<0)p=X1WqYU*9^fg$ZOrvImyjJ1aX0~PVJK$LBE!Rwrq644_?V<q^>1inCHL}Ck z@l>w{7q+uq9x?#WiJ0!sHlB5#Z9T}kpD15kzT-oV*N+ZI%A6nnQ&fF841<gxMn8Vy zr?tGag!rD&cr=~L&ioXS?%YcpgXqNLe9Zi9w`8)gP>Bky;XWW>FH@S9hQ|(*pdb(E zL1lwmzv2_GdeMCH@8ItcKUd0)we+Ozph!vc9slRC;_bG7AmqSJ7sCyCUUK13Bsqk` zcd=dCTH$FD?9*i#yK7rIEhx$;&{BjKYKJiCJsD6099O$Yz`qT*h6BpYl#F8mBgD>p z5rgLI3ea@z%^(y$yxrL^j7+lA<B#bC?$YN=7j$a3|KCyW56rFqE*ZxIUVM35x|MF% zkGz30TQmra{Q;<A{af<#*zPGEMld;|K^ue)un#yBBoM|0MsU$e_Kuc?{Seg$HU2h> z*gy^vrb!SqL*o!d$Gj-Ims1WQ#JEMn)%rIjU+9<nz?=_I(8rD_;?LwTIMwtJ`%Ml( zjUxP9mH;C@1d=+9e~`%QN{Y`ZIjDdT$z;ol2Soq=Nd5V;uuXYu{ZDQaqD7Lxio^u% z<}mQNdM!((cv;9Cwr_2GsVgzRpPWy`34o`vI;mnXUGE}mA}&_57ROeL*N$PwD0lIv zmU_z%0Z#P7q}`oA^Na!+DS_kH1QySSZXjbf8V;hwLK@t)%bQ#4AjHs+!P{WHopGgQ z#NHG3)#I<0{ZH9+WH$EQ5yF6NwD`Y{u~KIPjxw78;%)YH=lB!U?GMA*NFPE5i^FH) z#TO8*vMKmYWlJkYuQicMQi*yza<!l!%gpc!<ofsocX4Aq`KU`vlZ5|bwbtHK07dX@ zfxc6i08NJ_Et5NS>P)S$3+Y#Y{QfG|i=UU6*P3UetT8EH=8<Awwb-7(t*;;^W;{*; zv&!x{vwPMkM%;Hel(cKdL|Noymsln0UIsAi5uv(0KQi=#!_!Cy**zfEga?OY8Ex)? zk>jhE{~H_}WzIh?fC<zmu3%R=$qIQ89tEvW@0eJfmmTaCC62l$c0uuN>~QEvl3Rf0 z-GAPwK-qUV#*sCgK(IKZ0=f(ODNY@(q+>y9BtxVg<pBNWa`W5s&7I=Wpik_^a=N?* zfx`?F<w@;E1+4%M6D$5lc(Lj!)B`V<pL*z6-9{_GiIJl(!#R@4O&pw{)@pWMx%NBG zn|<#c2k9qW!sSj6Qeuu3MAX)!k%;?swA4FO1L!l;Lv!8Ucm*8pkWgQNe>y934MXdP zJOHWSgLKq=c6t0?!*({s%G2KNJE!N;o%3YP&l9{g?e^42QP}Z6<cpo>OII<k;rLDC zE${CT(Ou|;qj2Io^6NRDt3<C!S8kQvEn*^WjPqe(a|wrNVE>rS%`g8p>4NTqKF7rT z)hnY2Pb4e1Jp4WlbB5MjP1ynCl;j19{L?m)J)?mK^14zMVOXWzSZ=}F_|frDYD_+` z2C5AeP2Y|wJCm{YdP60l&Q#aZ3cbGm_9Hu}(4)tpo0}1wFrCPCS!CLLzWXjNW47;< zBkWs*{~Hdu_l2*=NO^;y7&$hTkGPx)V=o6-T!FQZCH(N#7YSB_#mB(F;B-6Iv5Z}_ zZNLD1iDU|WeK~G}C-Fb)gSb0y$Sh>|Ir3oawFkE5B`(Gb{ULa76+Fl;$499kY!mKc zXT>0_`q8s7b$>JA3sfI^EmV$L)oKl@le^xDWJ-l0=Xv)vyd=l@LOxQV>vTUG#$Ew1 zvk#Vs;DMxdS{1^_wRcEX$j~K2gKlI(rdb#&cuxg1R7>PMKy4xM!`kZ^F3PQVFZX)s zNHF$R-09M$+h?i;O?nc&mrBW;-zljZZQ-v+SBwG<a$c-4L|%lj7TFj;4V;ev+e$+3 z45t%3(B*gc)3fuOUVoK{_^5RbJxT8x{v-qvigWn=Z0k|mfKNmO^O{Es{CoU!%TF_V zneF3u6TjJ9LN}s1Ry+<MMPHvxkA08XlKfhWOAl?9JA0M^xVg@srreV9X_6VnX7g*H zW>q(0lOj|=u_w2#N(suKt`@QTJoyj2+7upMd=bQzlV4{4oNYx1ntp}0Z3qTEpg%<m zepaj4HMI)ZE;kB<RRv@6Ye1WaGqaql`_cva3JCOTf&gu!xd}f8b$GdChu*9K?ceHJ zD}vcQxodyNu;azXF<70Bd+5U&@372}rIVc}g-)=xqFKRJsej4T9i3?C_yUQc7Rvsu z#J~I=_?bJ!$-k-NbUdV!0V6X|YX?p5ISrQtOr2r-N5krq$+igt|H)?-a$)TFs|m#} zhqaT)K*W|WKkUISGjpAfs4=W>-4d+CF>cZ{uQYXi?(aL@{ICRotGb+KW}tFRj@VTA zZbDC{UCN(_y=<L!)!jB?V6Quc-b^0vjZM{3A63vdry;%Lm#rro#yQ7v(-3JN=>h~w z)-Lh39mc4+@Wdj+C_)GWwD2Q@U4|#n^FKkZvzv2iP-8m&bd^Ha=n%Oodwyc}$-wNJ zFFs#i@l6@xBT>CLle9(V7E;zZVGgi~wn7*<);`?;SKDnNeHzJL%w!&Lx{~2xi|ll* zu|)HAY#!`$)~a!R(&vZ0ph3ajb!*%ing6z0Rh>-6ORDk-g-2$)r273Q)AU(;OKU6l zJV$uW<=JXD(#;5ii;dnTG76pgnZRLYRB~~Sj1Htqg;ZxxZiDs=(FeT6hhw?<w>c~u z#_HLi9{;Vm|IQMr!O7k@8<uCM9@-RLI)VH1IMShMqWytG=HQSnW*IlR*B8E~S2w;g zoRnY<ipTclYrsMn_w(u%;qAjm$JXTCj?ZoZPW;00W1561>ygH7(TQX@yekL3xq+ru zP>sj;HB-NEs=eHXE~Vw`DNtaEgMZ|Qx&dX2rpL?o$9@ky#~!cdzKsT9$vB(iCy5|% zljkQhzaA^{8~MgiLPRiwRlbD%B^N+7gTmv9g+TO<O2clNlsq~=janY6A@u(I+e*s( zx)^Y)u#29R;z<%}zkNM!K7YN9D)`!$8&}rjPn$vuzHARWS9{Sext>vc=!T`_kHKMn zKn<#4eGQG^iV9Zrm|%#J>rUhR?Ox;j!{Oc{m#|)`@F;ftR!KjVoj~4imK&{lHMT0c z9z7kiNfJx<9VS**ivU2Q`I!X9d7t{*2N~Juj!`csSOftidraPVczH{1Iz$7`AlZ|m zbSqBNfWfs}uX$)^qdufZl%6=QKU^1`bh7=KTW%epD(4cr*+;n{NP7OP*GH50d`iZ# zIcM)iS8N_h#b1unB$9<IBtE=u`JWpp#A9s0FQmO#mPjTU%^GS@o3b4ksbP=$VhB1R z{dB_RJbStj6wPbKAJfc!@x!|9nC6XaE3G@%#>CEU`2msEBhGL=YaGnFQ99uY(fScr zh5$=sCRIsdQ((BjH=?`4>t8!>+jX3y4nIF(iSg%ouz2|L@UuM=-0U<;jZ{1#$|M60 zd^NE{pMAJtDS^_>8=9Gy1b9502V>q4x!*x^{{Wp_hiFtR)eGDYxoh3Uu}4x1Sf0jp z`_&5N(clOE*Tp_bk`PYGG*vIn)o$rRcJaKQ%o1ubH&=6;>uJ8PyUZu_)sAc|s!+^l zBTAIFeP&S6f6Eg_yfQ4Xgk0CPrf1(DUb?wy?4wP5U&@}aU@aP#4)c9yT+)-P6!C#s zfsU!P@}MV@XMwLmup_FI$7!S5QF0=3qN)2vg?Z$I8hoAoXS)}^+Dl_NqPL#4J1$22 zpRVmlsImktzS-oxiw{RC8|*k~m?YnL!pLd3@3UAqx3gG;ef*9kW3yP{^Nt}EHFG_O zlN3KiruTbjxId=;LZA}wK<P_=8SzFso5V%KB$Y0h+pmv%dZVX#5!Kcy&TG&pYw<jZ zuj<rEhTAXz0Oe=2{+eD*A^0@e;0IahHsE3GhC<BlssztY(FONr6@kL>7$>a5aG$?V z!K<m%z>3{H-A|iiB7vS9_iwDsc#{&+pwg4_Ta%u=F-CXo{rW)>3}hE+kW05p)Z-2T z$o1^~MYu)@I*W0TIU0>@0L<ebn5)AzwTP_Heb&+1Qr_SgE6?9vPGUFi@2;FU!4U3& z+l&vdJY>!u^}lKl(If~qiGfV1q$IBrbJSN6xvJT}YyADk2E^ms7=N`_dZ6Nu+kZP7 z<~vW)MjS6%xybPMB}T^tBm~=3>HYFx>F}`&b4zqXT4|$whrA_YF*wRaa@#YKS0)_9 zq!tJfKzNscJZPnf2wGMaTq8ZOaSF})IxwK$yud8KarK{@*-Bn@gKK%if&195+8`cK zEcCW(5VcA=dlFIDcah-mE$(Ya#z*)(dkKh?l*gF~`IcPQmOT-%?7)WDeyEFy2ki%_ z*~y<|^ZWHr#+&z9MeTzWkC}!=0C@$){y%T;qu+H%uv=MEFRvM*L+0M#hY-LEE9i=f zJ>JB$(%m8@5^Z5Ip`u1_v5ote`DB>F!g;eZ8h^K5tOd-MI&YsG_g`aT{?JK+(Bs8n zh{|mhRAANb)=?{6|3^3Qo8$tW5^#ZRMaU0y2rCn9*Dkux@<=jP%|1Jbh<n=!95Nq~ z?YZ2$<o$3h_=p+b+rUoZvWAr5;u}L#%y8VNGByDBIkux9ye?fayy@@t^)+@U`@!SC zD6CV4(oRP|;IE8aJZDaIpd18=eEur}OZFpzr5sD6NTa`Z%zDgMPic^M_X5e?c_ZX> zwXa57Ii8+%GLYR8zw;v@+I5m9w`6Y!$vC8feJ(nrS`MYn@&`?<w&)W-w;#{aZ(5KD zi;!N(%!EVV_>J5(SyO&(A2Vl}d@`&^>^fkHV~8~;+kbXl3c*iqsN~^3hLC(5j>&TZ za}#hLJc{xP;!BGU8$Y3~P7QN*q%->P{kXZ`-^uhiJ>{FP?W$a<e-U{=K8*dd@+R%} zXy=g9sYU7d>?tMkhD<3_pS?6Wx3?@xu5Oe?nsOc>EaOqw&M~YNI1iL;eRJX-UcDFG z=K3T{p^*K?Fn+&)i5L@eZ1dzLu=?TxuMn#xaDqv~O*&C5Ve3aXb+ydH_1eWUX*Zba z>|NN4ffr#C5ZnU`Zz>L_PUDlhhlnwyrwWO4ybSk|eGWr3A?cn%33c9NPQez$#j#pj zV-h|gFZ!Pj%Xj#rt1y=DEYaiHOXZvQ$GMu<ci(Nj9ug4PtM5dZ;A<fzRY(I#!|AS{ z7nBw=;?`pyBlO5y?mT;9;wvg!>)@%{T2Vhe-@QLx@)9obWNug}^{glSXghu=z>P2P z>>A3n0q>et-83kOC>8*ZCljC4%jDS;cUc+Pn0nAfWl83?wcUM3;L!w1oRDDcuRgmc zIqPhlGnQ{aLx!z%sW<V*=NrDC&&5OgtJS|gTgSgpWisefp=n?PR6~N>nK|I*^4Izf z{2e}D+{dp~f)!RD_LHX{3f~VdVxMsgEWL9#U2B@wyHcNC)D-va>RR7rYFKXJ7$4K! z`$Qh4xECdx(qJ)doC49u`Ut#vQE9~hUw?->PvDU&^a9(d6YD3yXHP|qCDOJmN40z7 z)*DRa37ekrJ}^LbN$kGm?jm6JNh)02?$?72!<*@dN;ovPWjgDXsOtH_gQ?pbRxB@~ zlKDwOt*S$F;M~ZP=FXcckr~A<gs6WVra_!yG7z=K11<^Sdt>aTtru9|a>owi#T|MN zTx<44vSLpQdZm4mzcQ;bEC=7vxW1u+umN=GwY_ONlbBedcYRddDU<D%{)5T_O)GV9 zSe7%P<Q%1zcTH-~w+zN63&yv3MP)R+oFL5jS6YMn>XfPhy8mM1@($6OU?ezC>>`J$ z&Uh<iJafmkix0gLHHums8F$@x8_uAHd&Z~5=<1FuOqt$(*j(4L7NU`H9AqcE%Kq%q z3=;nf4!Abt^0~~r`1Zw`i@$LgsH)<M{4oa)!%dDfCAW`Y=rl67y7QB!VD`6s^82q3 z)Ad5NbvpWHi%Mpw*jq!C?l1ZoD_bvz-#s$_HkBP6!S=g&mwwAFZw@~);uVjq1`h9r z&U|P3*-o>7Z{23$v6V_@(i?{}lUO~jE1W1Y*+0=^d20LQ94ryVJ8zJWy?0+Y{qRb^ zXiJg4o}G?)SRa^bXnHQ8BMV7`gxJuhDcdopDc|V14NBFrUx<x#7`s%zLBh32NW(5r z7)3I)4RY`qjL2s0tdyxLU(~+5tO@A9y#0E;b|heb!y|s)rN3^wKUSt>8rt2y&}*x` z2k<+JR!#uje-ra!5_QG$QE|Tuez>Wn*c90fb#Xqp`#Q<TCjWT!8OHc5W6de)eVN#> zYg^pj`f5q3;_AA(GqQ$Z=epWNz_u35CSg2#I(Pk^2W@ZF1=-8cN6Q{N?W4NpLD$n6 zWgqGprL2<Wck#|{Doj1Bb-M~SJ#nIIQZMD;yPH3qt9#X4L6nY<o=R(L*H<sGcl*;= ziBu%t1AAt4z4pq=tF#K=wlEjuOr!$gQemVHq%gc%Se2Ajf7Xi-w`!_-MMuPr>yX8E z@g*iImp#Mxh;H9~#}jh6I<w56jQjM}oXJRE4XVyyOUAH={AD+e7u>(*MG3n))Hs?- z#9^%1DkQn7+#j%#xW-VdDy?@w6kLsbkWBb6j5sk6MVhH^_+LjGO7`2P1NnoEwT|)H z*=6p&vypLzkQcx!R<+KfJ{o`EsOG#y`gmD&_1jkHr$Yegw~f@FUT=)o`{{XqM?m~O zzb=Q%H9vQ>uAH!I<>BZY!Ub-Q>5!5hz~~<JHEztugB!7Krd!|7Y~Hbd$Qy_g-{)%J zP<yn_nb;3p6b5geS!9(l<7ib22NF6`IPh^=V8(x83jcY&LPH{QLQYqm5k~2y^JCm) zgH_j^+Fm&XE){j%6djw6IgwteH&50-d}yMKrMhoiTVh~bTRc_}l13(c1&nHa8~#a7 z9CEf5t9X977L(IjCiRrn9}p)94mI5DzJ3bLw<~+j+^)nON&cAb_T2|{R@gGFItLPf ziBMw<Gtr`XtXRZC{aMt)1isYejh(UCK)JCSGo<SEN@?F))onB;a?$PF1nc#&j!eW& zga4K;I5fzIW-9-awt@TH0}20Z;V}zKT2+5ki;g~>H1063u~Z0Lpai%VA+m=~Fsa1V zO+!onwymBb?DB5&Pns{T{~2^)?Kkund-wyFYT__6$EtxJLb+Bp1_pBWH4XQdVM&7< z<L^Hzg>%9Nt`7uCxDS~n!zZ=j%a8_H;UYn>A;VweEJu=M8<xF6V9l@FBRztbeWoW@ zr7H}=&!>)J0$48}Zeq{EYvTPow1YZ1Byw*&kx)ZNX%d7Ou@cXOajcE0*YH5`Y2q&* zG?VRdRLUM;{|&*ZRWC*gn_~J9265>#Cdz+?wA|9X8qmBRv(I%L2BmXIt}Z(}3t|6a zx^I0SX(SYg7}6+}yPhZv1~WWZCe}NTedH4vN>At6V^FPBw625EjB3@6;Fxi#&%>ZL z#BEAJG6w{>z(`^a?gF96QM$BpBd;6K<y<mfjFB{iagY@F-Nk!7S!gfcI{VA8u~Y=V zzLfD(Ss2m)E^g{vx2^I}V{ICKrl%Pg`tvV%_F{1uZ`3abjjFO7O;;a7>gYr6gRokq zDAD81*zK&%PHj;&jyqdLQDZ&$t)J}<yJw}7+%o(epwGnko>JxJwdf-<Lgcq1RD2m9 zV%DEjiJm}<m`d0_d@D>8^sDRmylH4|xslj}*K)pT^waaqb3d8+>Z`{FzT+UJ&pFMH z5BhupYHQJ&Ol8Q>%glo@7`fiA$0y&=Cw|oVx&W1<%_!)TfaZViN$Nr&)vH7Ir?Fw{ z%LY4oih6Xnw}7tPLA(<OToIg@xT`;l#d-nIa--2dqjBp_W(pOVbU`2^ierMz2xbl~ zAD!?YXWBV+i)3CsDWc#GF<P<|<CM?gWir>U(9|6m-(I8T5KYDQRF1O{0g32m>MHJJ zh3lMQ{lXA?u4}s8#WR_upj%z8Y*+)#0mK-Q|9jadx4=s9&W>?{Mr_^8t<@+vp%ucR zl=9xu{)~Xndmg=Zf)=sif`BS84%@bb$vc<q>-8Zz%lX!Nb{pBn<oq;?ckxMIlno?k z-)Z~lucU7ODaWdXG1ZII+Dgm#6k)}D-Af8BkEC}19UF*aGx#TzzRG#4AIQLvGG^ec zrh3w&Po=e0{Z@fNic&5O#iU3MT{;sYYxi<jJ#9n1WnF7>Ae*h!uU@qH4PmNxGPBdb z0_bbdoD7YPO$O01FrXr$SlIa!QB`P}ncsx!Jztz@mXv+zU<h5NnX1%BIBoU@e29tf zOf+Eq$_Ps*DVKADZD3HUUSV28a26J&;BQNeHZhS>*O(IGg-iZ~%0~iCf+Ytf-`+6O zW>1(d*HZ<`Yc1V<BUR$W!0Z%j_-hYFL~3gIAH~7~O#&#frA<xan~3FfbxX^xc%yQb zN3V8aNN7o$rgj}Cb-6zq#GJnF$<)%)vN(rSZ;Sd?hIQldSo!|nmk<+~RAzhBXz1rl zk9~#!D;xcu)W<=5fk%@-YBYe7B0OeD$^Y`&nLL(hlCS_Z81WGj9(plVx7sq5+9IT+ zq>Fd1U=7s|pPGE`roEmIchYL4rHTNgJVn^%9je7EzZDe~^?knt?&i+wwE0U}4P&oh z6?p~JVB~7?RaY#kXY;}_Jc$#jGXA6h(iJzE%$@G37<Hr&2Y9in`byrw!IuLf0$=A| z5e>P=V+9FD(QrS>Am5%D26fAf+)tH{;LU`YgoHTt_I8(QWn?P%D~cR_0Ns$FWV<2W zaRimD^iaIYdzf)ahjmu#d4F6UM2sY`jg>pUIX}p5sK)Ve85sbp+)H<?zJ=ir%$iM% zOXL<Uj<LuXqE_Njs@U_bY8{xD>?wNK6a<{ge8JJ{B3d+DBd!Z#yC$?xr~IBp8vSpu zj($Rqbgg5D6D}lQ-|xj3OZ*ZgzMP^-0uu_KK0MH~>i9&nax0tJ5^-0*fl5kCOPS=8 zcPlo(J8u3t?aax|4bl#JWSzdl&GA7-@FxV$#;3A$<;F?3Ubh$221!m=8bv4+<eA|# z`SGJZxrvUQ*I<vV<g@<YF{W)m3+oHSQ>&NhMo0*TOlHZ>UuG|<dfDQ0&>iXIKNfV& z>X-|p(gQah^yN&i)_T*0|GZ?bzLNQ#Z(Z!`a7f(H-8y(;HqOZ1Bk0A_=|fo61AiNb zKq=aZV8WOJIAcg3+%$81Xs81DqBxZZ|1#|Vi|Ck7`AM+LHL20w&x)u7nbV{qe-P!< z!n~*kD=gbNnOxDH|4q44t1VJvxtq`{Ly%GrYppvvQh)wSX}DIQ1~sNr(?992x{>(3 z8hytjTH#PtmM$C8^A#S!AG%%76e&FAwAd-G(I&Hf|2kL0^CnUvc!6w8Yo~8sDF3~( z)*@gZtUfEn6cb#qUCAOd^D59N6DbGPNIC7Ude(RHI7+M#uBiTt%|?@q1>m<-6)d}B zcWB)pBLHT>rt$XZdHi65VyobO=~^4+$$Z93!p@>i9avN$2V;~bXsk@SmMq@6_ed8U z_U_F;ZD0vDZRr{z+|r~~+1Iuu&?R#pKu3Nsh5o@xd14%5joJQoopno^A-|HIOpdOb z4EpAYA6$DJUR{MLC;n!vLEt|)H)8~zo<S4QpsMjg#<M7U?Z#`Q{&HLV>WbKQv%^&i zR=}zHy{f6rC3^fh*{~bYtyFToS{e*xO<7lgsD)c^=j`!0${L3AY7lPR7fZ<8Tzq=K zTbf4r@7KJR-Q@zk<T?&6jEM+CCm|rZw0iD-cFDP8J0M2<R1h-bN(;&ABX>u`ZA0G) zJEiG=)?dp17Y+njssEd<&et{3Zz9$xYU8b{B7?Ki;NXz`0FI?bG^`)8K0+rWS}&Ac z$0XEdXK_AmW$MidPcbuEr-V;o(DM?Bb_%Q?A&b^PxRfJWafbo7f6E6|GURtbWCk9B zMvfgRv3^B$W8|i!;R|v{LWNDkGkXx-umHSlFXO3)V1j5ELaaSGqiVte+{=K!m8`LM z<pSb`o6g6Ivnvsil=L^a!B9qWpeVhLXZS4yrr`PwpvgPu6iqV?*e3yk|6+&Av5-(p z{kz40i7a3$G)~w9Xg&Ebg_#!Y7P>LX1rxUgNe3rlg&&7);G*cWTjHU^)H%T&ZbT_! zG<9Kg86Xl$EozEC))ldT*5U#2jcg_!!Ljgop*b)znu31~n4og$q=`nu8YZoihN<G_ zS^Z<wP?f+ZOfyd+{8y~9p@fj&Yj?)!`4(jhbUQdqGY@bWAtdQqOjgUuoEd2Of7-qg zVlfm5L#=!yL@4jZq|DGAH;N7gg85Gvb!{6g;~TzBkJ3H5`5ZHE63`3nm}~v%BiM)c z2|B2!aI>z{HOJ=$6BO=#wN#$@9z25<Pp;!i5)5w!*Zw|rpaU1EPJzUkq8a8)LX9%@ z^kLVffJk*&4Cr?U>jfhlp#GEhv;$4+iQ;Q#_s29*J+h();KK3w?QltLBUcUja$B5x z;lg=*5%SOymh5kO!=q>(g?0~?I8-vYBtPbH;B!36^)Fo_0bH@a%OGF^5)UX&u1G*& zQ&T5MFgy^Q-vPH#@mmasmD6AdJdjij(pyrgOWr6OOy}iP<6<C<36MX?Zz?*}9FqK% zjZ^nSt=->=D{N~x8a@xMJ==mP{lCFYt;5`|)Gb)bf)QM;V0A#1v7)S1BWo=31-TsS zhEtM&@UJ%a4<&<wpWh#EQ6pRMa~4UciE<{GQu{b*!W|}M%#me!gkeqjVM9p#F7Zg< z><{AU#TAk8W~NfKE%f_T70QDU{UC(zJzpFG;LT{gI){)@F!~1Hi*bSzHN;bt|D!^I zMjsF=<P6ybzjmqQ&e~6Y2LgzW2dH84TU$B}lv<8HH?XBMHGsrECa;N8l9Bb%q8}z5 zUZ1GY`s=2G6Y(r*Qd5@$;gl><PeXpkLL?NvTbz)SBlx>4$Se@10{$a%jF>x>zhKRd zN9x^0qnalmL9u?W%Z-N^{4sYz8y!1Yay`I1zX4!li-ClAofEKn+&lTn0s{q2o~0y0 zO65<E?!08zZ*(MSNhg;nD>263R`dxJu<AWSNh>;0iCYwb0S%J5I-V|UK$!A+bNloE gTSYc`z#9(Z*;`{~)PK$}F*}^RtTMPt+9c?I06Y?l{Qv*} literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/ic_splash.png b/app/src/main/res/drawable-xxhdpi/ic_splash.png deleted file mode 100644 index e69473a5f94797493315fae9187242a0941968ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19270 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 F{{ckr)g1r; diff --git a/app/src/main/res/drawable-xxhdpi/ic_splash_logo.png b/app/src/main/res/drawable-xxhdpi/ic_splash_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..bf1b5df506eb437189f248ef695e3523f5e1dc00 GIT binary patch literal 24774 zcmeEt^;cBi_r8d94ke9@bcY~~!hm!M14G9U(jlEvGk|o7(uxv;3`2u-3zAY&($Xbe zpX+O__YdFy;mcaHSnJ+%&OK+JeRe$iIWam~FGvXK3GdyzN200%(Ytr=zR|xQJ}&U2 z#qQl4@Q=V<1?F|{9_!P8KP*wBynuW69^F%gJlFTj-kB!|(x14HJFw><FcD93!M6h0 zCPQFdQ6q$|)XqxoSSV;^Z0M|Ufq_$Ip10GsYx`uQC64bi+e)5du6zo8s+sUG4BU$L zbmxup@m;pGZ%P(CWzf@pea<Uy|I4f8LHPPmj`U#aS@sq4huK|R5b#IWI~1%6fk5DV zxO`yXFGASzzsGN};*dyWpCz#o@DhS+)AsMB2rV`Z@HV-f77e^a68D5D{p%|9|GWOb zVlo2za)F}0FZKN)%MVSpU?9!+3Tq;KJ)42NQXxC4Wxpqm>p!~;b!}?gbTJdKN1v%f zsFHr{`gjeK!}L@0SFgP6Wp~;(8bfI2H8msV%x{P^!x<vzKw_3{V7;Wy<fU?si|EfD zm%bhsLM?l`>HCx&;#<#AtZy4khdvvKg7t{8X_EWT^>e;iv`l=i43gDkU;F~Do#KqF zq*sP}0+Xfilo08;c)+>u%S$#6OZWBjbW5#>7s#xd-jYVB*a0m(mPOw_9r{8~{hiIN zP)yE1&}}WQGZ8`oOd(dJnSPB#XGH=p*1AplZ~f?obeTCsxGPKvPTmY&D_8JumH6~R z<d9VI>nW)uW?6}f2^i37q)e|fcwO1UQ!;CYBTsG05!!?V_l7C`Bt$&!lx`1VEYpJv zw@e7^ldqUFKY+AbwSkY8US`qv3Mu`3>-NXGD6W{A*a!~0%r04ydlO4J9HWrA2zN;K zYV12|3sZuQ!i(J)XIaUWCg}4fK@2lb(osmPxU^4rr5<t?C@oNT;^GLn%oL78Z1m{? zE)RHoW>qxPNo>P2*^w6ASN&H~KlSgkZgB$0I>-GfJ!rkkzpv5D8I-DCKHSg&m6Sj# zoc*yM&MGEt3Rx!qWK4K_D_5}P*<uXIU@J8_K0$XA9K#8Tjo6rE^<$oi<#?4Ki(`VC zF=BaEad6<M=#3!mAjR*yb(A2_t*61Sge`SVB^l|)C9hvVa1Tfy3#?`Hr(j{zbZ3X0 zF7j#Va~5*JKI4^N%(YVq5*txbGTvt^l;9dIGp>S76dKvI6&739#3I=$mC20NFT!>B zge-OS|9F*suEOF1sd6lSDec}nq!I(xKpRZ!p23W|^cbc{?o#_JO1{5xz^a6eO{1i- zZ?Z-LWyECzSNW^DowTtB^a%l<5|=fa$NP=Drv%n(qi-(k&Q}5fpGy)p0wpigR&!Yc zO`hQLf-$tX{DchHG&M2pu}D6xCjvR${RdQpxO|Su!>~7Jo`N9ItJEd?%4Tew2&}mK zfXeNScTx`%vVk4hen}77vG6+*VbffANQiK3-ua;usX@8}M<<Rn(w#4#0edvM0sCRU z;SDZKLdG17OUlQ+w{F8o3{?SksOyGNoXvvRh^A-h85pd%wmrdD>-`9qk9Q1#t%Poz z+qw!zauNE~vbGPIS@M&<h^8f->vLCvP>B`V|27X!3*(EW=8OBy<^wLQw-g&FG-}7( z%PXbs1ZLnI<2b2|cx=OX)>MNIFA};TZogn8Wdo;l+z4bI%e7EVwuKdO-Bc76?R05D z*wQucaa6ixTuMNSA0ZwqX0z7EF2y2Mq&okyDr$upGV&S`j&foICl=cv5Vkr=flMzN zi^pQZmfQ+=P7ZQqPzdBRIGVWkkWcZ%9jSu_O!eK9hDczDzSq&4vQ^Q?MK6hXjW~L$ z9>gHiJU<SsWe;cSlb|fK(r%}Q9HV)`VB5iQZ9Om!I^0&lx&0aBQ?>17;b?ZIEwD=* zEADWOhoNgm!SduF?u67u%>>0rj>60Yy01v&&yC&8?*4s_Zo&*z2}Zi(6R~o@;7h6f zRhv|9Szqr6W0$<qXrFLqR)fG{?3dZ7BAEw+5m@Th#D<e;si_}j_p`G{f1R}iU*&7( z$w3$SS3jcB<TyA{zi=8Fw*T%o%qeZzFyK*IwWUyXreBVYk5>z&r>92=+jv%!r)Ooo zI+<4haq;ksbxi%LY3Lgm7*{Y<Rps_AF{Z_6gkz~ITz*p4CET+=2`+d~K-uF|@SPGB zZ5-^YL%h1?G9I3BZrl=t<J&+Fv<|~k7m*`@%&e$k6{?AaTtDD9if0LpnefF^wd{^1 ztIn^n?)HS%4aT#o1ICZSs$LIKtfTos9Ova{jmpcfk7D?ZtMQ3w_?EBvkFEPsXt6Wc zXul3>>z94j%84~`&1!GZhx1tPO&$*qcXvb)!6rmlqWM&XEmgyozRy9>?}crmX;5Qh zW2hGCzAiO&^_qM!-#t@YelM%O6mo26_M!9hV{0_nK-eK`41U_5LWB)v6gJJ8%JE%j zw^aImj9cEz5*jX8dp&(<CPHlF(cx~ZWqow{Qv1g`BQJ(Z_{H|=ti6ZGw`*DqTSpi* zC!i(xhBo{ctC}jrctcsDh;o{~F-RODOVr+TTF3R`UUZY`kagKU(yz+oYO@#7;x5{m zu8L%aZcl}FyDMdIE?_S=KU$z<;~&irsF71s@aPJowjq7d6MWAV{WDdZTepUy^Ud*k zb6*1#B6Vm^zE5ztK)w%3NqHC0QAN1&Rxwg|6;Lfap<xm2=`KuFRW<8#0ei)tB9+96 zv?6njVu^vOT7rN#+Jr6=9Ci>w-~MU-O8Zsg*%KnOZ|5%2yoKV(Go)Vy@{Cw@6ZeKJ zFcuq%wr>09FfAW5#C+dx$75-GOZU_y_$hgm^WNM;_hH%4wS?4h{9G7qAhD5dj}P%W z>w22|?z6&!m>Lo#X}pvKhsBXRdzu~^1pY@i@y_(QF35bMym`O75*6zqGsQl;R!F8+ z<1Iq28`u&m!0=Z2_2kcW;k7S!$4M^6_C3n=hsDuhRz)@3KoH>$)($SfF!f*=6|JVe ze9%d)`xhxnTv5MFD9)Zv_AojDgp1-D*)ZE(`{d&<Yzk6hQOroI&(?bDjuev05HanK zTZ-ipmoVjGKb(1zm$UFO5o^FQ;ERty#AD&n*f;-Pb_HsF+fd<I?kc-FPk}r{;FEOu z8y?x@@fMz2=J9cB`ZQ##m$y(BMp5%c{8@u)F{ZuyBmM(e4$E?LZ^HiAl8zNsWw<T* z&0oV>cv6~?iTm33L{tj{a(S;XPGJ34lqYQ6Q<4)F%n8BfHNtfV%&f3!zq$rGM?P=h z8AboIZx1Cm&3H1mWf}T`I1jWul7GEEm=!TNs8P0$3+6_i75ZtX=<khB4YFekTPnHA znTYhM4_?s9-%|W*P=Y*T+ptk(&xyLf;z0_1@VB6y{d4gB*zNHzWOBFXk3SW8NQA41 z7ZnxNA9Td&8X5IXDKqaJxjw>0300ajU1#w5GkkoJD1LKHK95#cSFes~XJ==pa0Yd& z2Lv?wbSN7eH&QguO_rM=`co^?EY(#wZ{KY0drHPND1tK`PC3b6RMCB16|?H_dl}7p zXc+9eC$+l1?r0%18*7{jSSTEULs?Gy>dn%cWm%quvVqKsBul40`{E>fYWgs0ln}b0 zc&>|1jV1Kkm_Fs~Lw@5=!F>l2(O}k&*z@-ywz02HZFF@(0^bh6Uk$l3kIe)&9Lx42 zRfH|0+L!vs6(epm>Xv9cHgbF&EHIQTe1HMznrra7SW<|l2!#*66UMHa6X~Qf_;<J! zuE4KWn@qKG4QN?$QRJIWBnwWZ@wMcl8qN<p!_MZs1Zf0Jx!Na_wz^mtFnIi0ewkx{ zze(MuRt|HaSI9pjuu>F{nfIPz(hE&Oo=gu(Z97Nv#?tB1QS@d@oWj``s+OD8^|HDb zjFPQzcpm^3!iehFbKDu-jog~JJh4!__|%;hCTc&l`pG+%SD4lO$wk@;aaYxl6vBY7 z!JRG#A01B37HlouncfAzAu`e@?P4<rzVOt8*xaL=`j;xTh&8pkROWVGFcmHo9S$6S z=LbTAR18kfG0+OTp=%}twyIiT>Sea%U7G8-QFqD^N9KU!+?F&eBgzs75ZJpRclNrH zmuph|W*Wbm{}jg2eN{1Do~G(8mVnxVX9Kf@H13E$kynOK;5OS_Dc9O2%?{<v7G=!| z$f3X1FRPIfq;MmFBl@tFf8xr1B%hVSnc$)iPbiydL9vq%I%@|gw<fW-kSQptS5$CY z?G+Dfxp^=uzi2$segu(#RYo0f5{s9<`dKs8Mg=&4gWnl2aMppq_t%4C@|4^v#75;G zx=(P|I5_GCFzfja%-`LW?AQ~`JoKW8y8?~B)v5Aq@<~KSW0m2c%(Ehld^K?ksj)e$ zQ)gmqj54A>VZPP%la(2<TDCdPI72H|IXg{BMj?N518;fmhQNg35*gjXOm5i-_M+D} zRmtIPRruH=nRwHW=cAKZU;!2}FXttnsPKU7X}+3X=+5PV0<BfI;h6&sQ(Mvn{D261 za0E0TadL9*F>p`%+th<6kT%AQvxgj=f!X($?cwCK==USNnQlprAGz}VhDQO<nzF2j z<e~?1zA~nj!!CcLvG-jKMlLpOjtP{rnqW@O7JD+eQ`%1IlCn>qp6vDdeOp}l3C`7} zeK6F1RKR)EoINMd>NgAmh0Y|>d)NB=(CWTxxxM6t+u8NFoOvXCtX8}C*WULmqcVIg zF}Oklyx=8j)C?{|hEm5JquIK7pbWI=YmevZspQlsKM>RG%yBHrx;u8w!%Ueoci-EQ z5*x}(i++9SxMb=z!iK?MR%#1~9tw!eEPx5~-o*h<JGOqe-LGY;M04}fo)f1nYy$Zu z=e-Jaa-`mcugnlGHY_jy)OA<_7>tlmUfQHBY^}sR-sa@H%(5i>5l5X@2R|%cVtr)> z^QJRWZ~IGVv>qj~5i{cp@#O02^Be>^$p1Q84Y|zy^yyRAMCRc$8JwuR0xTmr%guph zQ-Su+I!Vhj44k<vB2-3%6vB)-HG+qtO1-~owwG(|XUNn8fa6fK8gWN2?Eey<7QL+g zpji0N*Qk=0$+0h!`QBf=nuQ;`X3fT%arKhbdIrT=2iZx7d;T=`45f?dm8-F$k=MR~ zwTu>bChHC^7_MXB{j;>PQm3J#m<ESyi4oA$Ebi|Ye-hxn;k8WS^$aa|gs_Ee-gz<O zzJO8lup0^2f@ZsKIns5H`T6<R6PsM;r8IJbYzJ8~74()pB^!bg$kfR|TVFCoOm%hY zOG9^JVkatGA`WA3UYrvI6r^%B&dLaXkMG&viyn9_Zqj*@<E%=%zZdg#TX`w-B$&T) zv5;Lbk<(8nZW>cSP&VAY-2UvjNmGU*TjlFme(GViRm+qgUf~rMNJ3$F!%1G~=3ZRg z)=&rj)4Q*Pc*FTc;_k>1ge`W49IG4Z!3PD_@86fXXG@!=7Z?(M4L>J)?Tr6Ihzl+` z!hBaM&m_8y=dKroR8v!1KB^BI{?H?&<>LllBcv%a<e*NJd^8e`zcPi_rv|BS><p1g zaf$iS0U{=ZbxiCLf76$~ztPZS9Gs~xXuj`HNK|Gdh09m?2=GdONzg@0cQXj_$VZ3# z?^(;fl*=-gN|TUH<@7j0$vwSRrb^#vMC6rAspIkiQ9p%r9c4c|ooYR&Rhl?AliVBb zU#tTz*daT6v2{)_D&H$nHN3tNojgJrw=c(Ovt>C^;uavvZBpH-nv&Rgj0)eMyfzaL zXqY`dctn`DR%QeQH9*=UC29%kS0X0Ss?M8Jkcc(wqlj*jUMXq>y)#~ndqJS<2eJ1Z zIP1b#<2X?ST7dd(m92dgGj-?`pdu7CRm6E;fAl=_6-lHi9D%hYSxo?_OA4)}`it7~ zGR{>MDoj^s;xj4pQl{t+TbBp!tc3Av!yMK6ZDZ;grqfv};D>B~PsnsrqWC;MeAv4B zz4prrWe36;K9a3OLEEiQVpT*orkQ>yrbV)D>-%D$Ki(Tm<?%Bi!)-Q)O#x&l_CxCK z<{#HH{is25OeFUSonO%@@!Qu`7wozWe8J)cw)bfecrmM9m>*s(F>dZ6ihWy~dtqOk zs@%2bOH^#d;)>Zbm^rHTaN;I-!To>HoKGJxRz>k09v7X=SJvCH^-Sh<DaLUL4TPME zSb}teUOn&We9Ov<L*Q5MD#TpQFz865>y^O-jL=5U*)C3=oOmnV{IH;3G2>w6G8O&F z?!o7Y%IDn4WCNs>#$e0MZE$4+S2CQmkvFI#`9d+nK}V{rg(bIy?)#b#k{*U>vr7M` zQxJ;MXXUlJJW+hw5o1rj8GGT{{j@zoKgRr_Vk&#UH`EGF(TQs65q#%BMF8useK2R5 zS%Opkd{0Z}y6-z*gLuIa*1%F9EopuppxF@39gl}s2%2t%jQWuLCQ5TFvA90Z$Ewg` zOAo&!6+M4%L^a7vSvW!A`x=y;#1P6pLJz|>5YGl<{jY(w#e`%{e3e3<XT9|AtY6~? zSB)VmO83dsF%(cV)sxBl!^wTskhUWd-BJV~xoRmq^K!|Y2|i3p$YmPSfR2>q<}Mvl z#k$PtY&ofE%#&5U+Jk%o)$53hd9MVuD&fi4qW-rekvB?Wv(@p{#(fk$joKX;%1+_0 zEktAndO1b0%m7A1<y#nAGi6rj5>2fLjpYX=P7-%{i78I!r|H|3a7%y3<!j#P5h4(e zLWUpwjX5cHc97Y!DoSE^6)lt_sW7x(df%8U16NT6!Vg<Q7M==??_1O`JuNLQ9c^h& z``0Q>oU*b^Gc&O0-LcV+ALK(WYJ-b;%kIzZg|%Wofpab*S3;YcE>66Q(x)%lr5r{F zcboIpTiuTRO<T7=Tql$-Kj0DHJ6dF}YdZ9uBdIJ|3hcE>SK%(7yq{j5!|B&hvwLFB zp#a55gIX(g%Sh-J^6K%lW@Bj1aFPjPhSw*ceoFv!S*Q`2QeC~SZdFU=etEhZAs2l4 z;G5Q*Hgr<Q)&i4O(EQP7(cVG??0Dw#=~sBfuPMKKnV&fyZ~jfa*=w$@rt<gq=a;hv za@AVbdHRFKxjAos(_G%(R8C&>pncVk`R^97cI!ZVv`Sv^-c-QeG<T{{DNaX6XZm2# zrsqio6;A1Q@+@8R1@W|ujB^)%D=XH|8d(&X_CU7&&g+Gqs6ghpT~u?SXPe$}jPBfh z8c;VGc81=NZ$tKXGD;rF{&}_3KS(6%(R4!;oG|13E!3No20H`XC11L^`Ks^xcSmnm z3Q&p5;c^{)?qZ{NZUfwDYTeOmtk(6%c(iD@uLzEMkTS0%<c~WXwN4?q4(15Ax3zUz zl$DQ*Su$0QL@GR9Pl#!-wk~XypnDc6aJb0!kaw_CPt1}!uIfAcG?im}B*99}RvP}x zY+5bIC|jxNGO?OR?Wc3=B6Y&=!<~8pmYZ>^A-wIMlgNYzpZ+f)C-5Z!b!+PCCeu`B z2wD^b>zZB<t$7YX{in)k(Vwy3aRTk-5RSj9xjm$7J|K(5z|Q<eXmTJVSk|$2=J#sI zR;$n~wr*=AYip)(jxEy6kuo5HGTuH0SCKdGF$eAt;FeGK0b;r_2npxG<<oLce5_j; zuvIeCH#k_mBligGWit|+B>=#jMiZQ0tXWV?6wVQA$o?($jBn*RYCvuUvE%ss1Z8o@ z&Kz`r<#NlV6hD?XrG^8zhL7^Y%x{~e_rGED8isTMu#?_*AVIacxvZ#8_2S}5+d~u? z117GFmcpP6NIOe#063jGCL{>RqLCNJ8<p>EWpMcbFeDZv9Al<mj=@A5FJDk3*TkHP zER(4nBG~DaH&ypaargw1DY307u7EgN|JI)ZbU|^f{!lQ)<O(~Lcyt)ZkWpJ-^|$yG z0B2R<*UmOg#U68X4y3TK8gOABbtYDo1s*i?<9zznDsg@&u27KBNX0|vPCV7-)QzEF zth2deLxS3_ziGRFzG}3My*v;m5LZ$qHiW>7m!|H0@aZ67m=kBH)&}o3owd5Oq2D~a zGe?uLJeWm4N9R4gUpvG-_KmbKr*pS%IK@(3V>cvoz&|fmn@=~~MTl_2LWux?(C8d* z?|v`*4X%1NL5^}hxISAqb9bAG|8=+4QO-}|Oc|l3BH_kH(L?&8!@tvNe*-z|v|?5e z&dLk^KGbR5RtN>s>EzM50cc={z9KrDCigv}eBFTGcj@`hmQ$>QUx;6}r{mg6%hOg4 zzVqxVGAn8CTA{=+0HPGZ!sUwqdh0%^w|de1W1Ya@N2$?4t7+@t%NfUz*~aoF-PAg~ z^gCE|q^Q>OD<?ta-tCb4CIOy<=F-t9Bv;c>teQQDC%DmG2H7I`Pb&4QHcPcJNoyC5 z#dfdSRa+V5GGEmlMq(~G>b$q>s57UWXCg52Kf2pd47%54oVteYkL)UP@L@7dLNcYf zs>Ne$zBM!kZ$(FA+pi4ifMq#Wd}Hw551I@(QDfnF9av_j={ozZG^)qn^wO58qJjKX zXd`Y+aA4P}*tg}_vZN0m23FXgr~xBE+Qu^bW*)bH=6Zfj-6LlRp>pvSY)$-So7Zk; zoY1KK^n#e^GP0E8P3g>9OF?P+?B}@vI;llj>QgQ<ri_e?WmMIWGGMb3^M23&@s!;7 zU~3amq}E13qHL&&=KehOMVlq)`tZfCBXS6&Qa^8hti@4&KJxPZ!>uE-{Pp7>&xiU6 z$*bQ-@&_7=G|C1uqzKANmkvA5H+sL5xlm)4Zhwg}h~U9e|0Z;%28>q+#ImN<S;$X% zP5uuZ<!0Z$=WnXnuZcq3H!OW`I;m$+rl>_DV%{QJI)Q4vJu#QLyEbK3Y4`76^VE9U z86B;V9>%T~_f!QK%4dLI^q>v<>>n7EyxO&Tva%oY=KGYKviHIQO*8@aaQ~6How|DT zibbo!R-~@3KgPQFpo2(I88ED5Uuw%e0K3WW{Y9<KxcsOjx3aC^IauT)VAqTNZYcG? z9TGSalGRCamK}Ny+nTx3k@ZHjBEO4n=va-YnF@UIw5KSgK>OiZMfy!X0%e(9FqFCP zBr6qjACVcyD<T~{qYF8mz3F8i1aAy0C>V2gp4}VfAx;=rtIo2LR<ybd>lVd-oSB*$ z(H*xaay9-4JeDS46#p@?Wv#@aM!(sSqFRc0H}3Y>^+l81Jn?*tl9Cdw7*AvB7PWB4 zny0J&CPB%FLmG+l<JVJWzV8CAVvs>anhc0rhTC}8&?YPu?NNsGfR3~;+$9cLTd(xC zNMPxU)K*v8dx{3Rm0q7kL`7%9o=AKr0hN-Y>mgbXASbc*BoxW9jn}ON5*Mk65mx(R zn&PdKgaZ<*0lVXE4hs_>M(M91#Ob&QzFQCj)tcM@tQ}MTYFuJJ7Wp&%=NIWq!3!cr zGIPAZfG^QHYbMQ}AB7zzGFW;~xwZ2>KX|aJ>sNAU&<=k@d7~^<kpRvTBZ?<knS(^- zZ@*P{Kbj3y*2{AZ$j9KA66xwUI)2xF<o4b9X9kq6)*iyZ=t#|LL}87?tMT%S2w(@i zUk`4@J!g>(JB8f@(Y$rdPF-tCsxF4FX^INKV@hb36OA1~K##32ZC=PYV3vm|NR(2w zwZv{`;ON?x@Q+eM*XF{t=5N>1oGq=}2A!usj$Uq!qs~G40vCbTnU<4N^n>UT7*m*< z_YGuLF?3jAj`J?n+hGm5It;VwV_ud)L5tMCxmXDY;;1*ISfdWAt-zQ@EbX~4SHpNx zqh?1&g=(AORyoLFraa_ZT^CEua-s>LMonSN40eX6)5C7UyA&|^zLx)T!0V>1Iq?m+ zOH*J0>v3gI;znz8xlXA=2Vn+IOiTtNGaL9w;-bQ^VC7ZtUqWb@Bn(|J275bycgeLZ zD{j^CVDBV@+k5Q&3^vV%Wz_R0581)s#IEWDiIw<8Fl+foPJOYQ)S|N=zpjpq8E+hY zA%Xn7PF!Q-4aFfuv}m>t8WJm7(de96K!;+I#CA?*?`P{e9G5uGRIVi^SIoXoPyZ3j zLW{s>|JTwICk|QMkTxFhad9`(Pl1}Av*8L_!*iNxIXut++HKBeyiK0HujQGEW%4BQ zMcQY{yI3R_8msjthNgNBkb1mglyt6n)O*Z|)qcCM&H0P3)bAR?y9xHJEKg#Q#ojP7 z?L#8{g{}0uQiGS~@$(fypi}eJ`&az*yqi8z-Gf+hfabt$EAfaxx=wo918rfm0%P|L zf>ZzXIO*iIfarHy%k!N82&gchCMBq*{Eoz?+SZ$1!5~!<HnBF*XHm<&BikRd_on2@ z4FV|lELneqKwQ+-cEjGZHav5i_-)Z#I>l?e*xD!uv?GMZrE%v1RTS3j-&zo=Z&*`_ z$_kDzT6KzoHx&_USL&5+6GP}zE^KHVAj>vFDAFi}156l?56iWB{$V(qPu5|^dHQ%L z18B3+S&LMRq|k9)+jUs6(11V+B-b8pJYubhuqZBd!#DAvDqo1&!cej<x)~eOOE>Zk zrC|;Dghj0Wj|;HWXNh+v<bDg(qa3<SQRWXxU!ly~7x<j1%WvgS&EIvS!i?HuMFAic z9S&5r8gDbnjw{S(t~;SiTV_`Cf_IvvNH6sATgti4HsMfk;fOcO#6u?0v6|?QxvG1& zR!(<MuR0nn5_lc}z`uR=Z)RNKb!}jp+rjORT6NZ>HT((->A$+gDzs=r(f8>&mc*mF zcj9DUCe=eoLAvLSiCY^M&EdY7CQgUlMe+dZIBLF{EHTUYR7(bpDEl&UP*lZm{mbBW z3o&TLHv|3+T>HMWA1#q@N<6^~yhb$b7lsf>@}`HKMXSz)1m{5X&0;h&y3ML1L&&ll z1n73Ln?*)p3=%wgJgA|4LU=n-7T`jcb0DWRJ~ln3YhXuWBm-9Lstf@_9*LnrXPVNv zOYn#)_iksS8!%tJLZo$L*qS>Wt)xi%kE#HEd>@+mMpkBm*N@jIH{biRTC}6lEq9(N zi6ZaV4h5uOLd4k`st~G%JULMU*%w=iQI|qXn=iF`i$5qwc`we)?5uw+g_P~z<Nc?+ zeYCrJvn!Z8(*(-339ea-Xjkke<=3q;ozjok3AusdxhV%H1jwc!J&t)}q`Qxa4S%-| z^DmKGWeZtGAwyX~p#GTgr$4*pjA+`Jfo4b6)Ma#}pdJFw21-yeRc&kQ%MWqv$O|LR zyoZ;M;_!{4qN0MHGjNZ__5-vG01kd)M?A&K1{O(qx7xDvbbtAP?8Wt-_d(?I`h&Y3 zPYX%}ehd<+aB{KZ{i7otZF8YjUP>JcRO{yMG>g&9tXGz>d%b5d$hS2cRn7bh7R5ku z*19bgTOgGZoLi&-fupvL96R?Cow`e76e9tK2dkR*r|NT}l7yd0dv8AyJBk>z=~-!r zPu3@KfszkHo`@cNEAipp6>{duY!wdM{DPfT9^M^BU0D4jp_l?hr&(=N|69<e=Ghv1 zsWBz<t!m%E2HMc-+2?)Qwwixa?GRcWd;V*x#qG>VeIv3-z{;53a8?I|ow4k9DG1Vi zeZo8%7dY+rxxzBb1?issVD=fnI^i11bcy!*M?~Qg$rdbQ#^vkw$YKP83#Ua*+Lon& zd4I}YY@kSj^}ZVA5e6QKNd9}YfG9&3etH;U*e?}6^q1Gp3#sF=Qvoa*SNv1s?mL6@ z1nTbQB!k(6iue6MnKt3Z0Et}9OiC+`;#;b2^f5A@BWkVCc=7%N%eY;)VFK{=p*fqO zuvt4Ne3&bPP#H#4PGY_7&wJ7!e+}Ra0@GU_ESC=&Pnu|wBZyNA_}vmKfU?VaJ7dl- zPDt=vi`3)^IVdZtiPh)=!RK+IX;5M;=5!sCkl`=OltBFQ=|g))4lp>j>gOP_3$`&4 zEbAoZoyjEA9sh2RV+O$iH9*UWtrA#K7K<)}Dr6j_ZfTt#sR(LF<_>0RTJJb2L!zZF zmpIZk_MRD-V>!Eb?tPtV`SO<e?cYQDLPe;>o_pav2$JHCb3qWS@oLdUe7c&z*tK>0 zWl|XDfYzA8<i1{Fp-@3alfKAj0wdBF%Ao|}o%)`h$|k`Nb>0GA+iLOK#Pr>wfqSMw z+q%!=f)=eS*B8w+nD0}&ZS9;Hg~9t@|9EV$z0M6_wqP#gP#}OUA9*?bTIsZrJ%oD_ zto!h7?4=>IqVeg_NH+c3dAXqAnU%iKE$p9ZEDt@@t`Mz5x%t5l@66neO*vZfrhOk= z*)@kXr`{!epK}RPjp=%38KBm-)K(i!)V)^te6xAY>;UTF3!mU9sg~B9pUegJfXjKP z+hXOzcCJ!Ul@XaPSYzfFF>G0!+G3||f%o>!O`Uw)Wr|u0KK#|G752#&7V|!eq4Ldq zgQ~q^ozLynB_^T(D@xZ$t!}^f6tSS>?eA@a1|ZLvS!R>Jk|DI-(xmdIG#2=nCvG~i zZ19-7+hALIDD&={?5$JiVv$F8SP^<>$GL3(eryWh56{<Y4Nu%B*o>k;7{`Hxm4lVI z%D`1O-P_xM7H7CBn30Ye)8#4cM(x{)y=LmlX<k1?osm1_jn6IR)B24xeMm3w8MS{O zg}h<h1#CPIGP-uQ(lyx}bkgVf7FgEC2i})PKVm5X=#CJG+%$8O9yBens+&S9U8M<! zS{V>`A}lBD)Io3hDAdMe&3?s`!m_*x0HyQc&YX>57u|jJGEei_r&z`9W8KQdF9Fm5 zzSF`I7$SM};u@EIxMg4kk!Bd8=UL^x3Ib;FnQ=d|g7mEGoYGWAie``sT|Xk4{D3q# zXP+{<kOf#^sr&hzxpMn~#nSn&a+wDzul8s<l68S75pB-58SBq(Hu^>24c<$tN@y_} zh2r}srTfB_^YX+>^6;1e$Jm56$wRq%j)e#yWDk0!DjENVtC3Z`eiecj^tu|)PT#X3 z$HA&i&&U{vP*M*Q_9Ujs!>pMwUAE~?t%{>a6Wyb}`$NOvwJs4jK<&6$%c(p!dJ3&7 z3<DT$3d^n(Vap&)mrJ5-BmR(8UH<Y(;>G<G3a!5?Q@P4~iZs=@MZ1+pD!y}I3$eI( z<(NJxndjWkW0Tm|?U@>O7u|3CXtaV_qF%6O86PF326yN>D?)iF+(Thf>koaOH_F)4 zdzLVQF{FoyRT`}7*QPm{i4mDMED6`w`^CHxZ6A|01}LMKDFF=E!n5$PoZJ}6jAQvL z+K2zZIEuxj$1nTF*6sQ42=PLnP}-6;4_(0Ea^j0gRIPwL5dg&{`Y366OEW`2mTh|a zT3QJczF0~zvv#Rc@EEJku@^MI58f>nZq+3E(I%DDvlGBdT%~DPwqr{SnEdZW#r%_i z9?PTEJ{pXS3lr(b^C>U)zhh0hH#2rEeQdIIEpIT9fKAFC8zP2TS+@a99KUtTtjF+} zZ7tM~&e6PEP*I&6manR$g>wp2uTEer8bz>k%PjIw^<vIgtVN^vTtX(dSym24HjA%& zd4t+j)w1OKM-}4{`mAN2L^)d!07DDdg;RoOc0@35+jOqbKi-T?mqhw^Zu}O0DH=Av zllkGVyf6tq@!mv;iOL|MkN=LM3Oz@|hbQouJSQTukAL6e=}6s@{@iHtyO#u6C507g z)8HWf8~0(c1|z0xcp}eD>2Sm%f9vZPfJVdycI%U>Yn0vN(_U+*c!0~NWNYtLU>}=c zmpZ4(jOj9*2+b&beK72?yy$jVTu^^Vq9%esN%QDQvhd;)8^taw3{&xwC`QIcp&Btf z`Zr5-X(YMPKn8wvUQmzEn6OF&t5Vl!j@8r<`Zv}02rh4h44P^}vV!ZB#e%J^*0vuP zFe*Gde3;_)FRSRFI7RiSf3vlD`A^|X7k?;S{C-s&;?6wRot>vNYOk*S>M>(KHD<3^ zMbY^6FwYZj?yP_9$2^gGf<O<g>l=1`l1BO(LBWkT3cBg9d%_-dB+Ia>N0!m0bC1rk zcaMHMb^sWhg-P`v9z5cWL^Y1_WWPHkPe^P8ojA3uVJYfXH3Wv2C}hxby!E6WsIE6e za<S!B;ZG32YKKbx`0Xm8PrRz>G1V6^6Q8B??z)fbpIh5=TJ!Ko>Go!<c0IhVSbkR< zd;r5^+{J22Daj)50bv&x8$Zq?(P-396Hc(#aGAvB=Iqk+^?kkD*X1<zfG1m)b2PuW z$EmFOVi#NRUbn4GSf7psXPS)~g2|7g-!?W$>?2QUXXNK@px#kXSwe}?a{h4^xK$GR z4R^k7ND;9eGG^CTDp&&9U0g2+_<2$sx+%*H09hg?Ou3q#OP^2W^9Ri<=4()_yj22N zD-E=-MS<N@)7GxL6v*c)sbYT;&6J8j#m>1D3zq+#)jh4&`g5HJ`}6+l3B@qOWI!K9 zqOLo+*wZ_bnuphfd-2l#)5!%8vF%I_eAtTi>$g2b!&UgIayzS9qstGisqkTe$_vpp zi7hkEZtS*sZ&McnX-kIZu}oUc%cJ>RST~2o3!(Z|uHW)Hqv6F&r#zdAljn{r*ck(B ztFTB2oM{1o{~}Sp#&{S*cKBBluSpUr<|lW&cg~OF+{YTfj2;S3b<RtcPb3xXW*TOE zbZuL6U%Zo9q=wUiFm|=Gk9V_CRK5z;rAGfrjP>yPv8y2uJZ66)3Q@U#bcGIGZZ77R zS*=rde$}sXJ6`kW+a4X8*0t^jR&`?ON%@2OTiUt!d}cqe-x9M%6WQjT%Qb$MwQykh z&lI`gsCOr^3zQAskm7WPMtuzRubjC?MYhN$o%S@V-25h(jwW%I1+<aSw77Ly!1A(L zrmv6OdbtV3&!{}*Uf3ikih}}BTkPbui)dN{#f*B?`OKN_lk2;J<#>Z1=0~4ca^C#) z9=?AQSOXaEv&=>NK5*yU_}6FO?LK{(s9A~I0XT$!(mxp~X2dwEm%9I{4Q&@YJ(H;P zajKe6^IJgHB8Y+&CsDorXx*+Zoh7Zn^fcCiHl9h2Di&@=FdJaJ6p+A4tlvE>5A^tr z33NYiMCcg$p*?)PwO&o{ecI-Hba+WnjzE2(xnI`0g!O`-@Raz#FjeOGfh`dXR->xi zT>n`vLPsUdk^$KVk-0mM{jFPZ6K^*~6ZRD`&))%&wbXv55S&9JwBzb0Fz)(gUM;Zj zM~Kg?RUJ;F`L%2KpO&IU?7wTDgPG;qZ2ao_eXsK6m2-Trx-MUd-}N5JDOU}2eMu~5 zPTvoWqRex9{zZNGd2kDnSe{GxyxkOis!zZvsmpfhJr}D#JsWFH{3pe&cmC78vb~DA z_W{}&kz+3klj(rfyY3TsU%zu$e7BxPKCmNkmNIfK*J$;$A?K+8PN;k?8$0;J##wV~ zT=e!!fO2jH;52}p+BzYG=Bp)drK19Zmo|=`%C#TX_>-JD$*-hEn@#W48P>>|o^RH* znSZrWNe1OCv{q&!bl${jvTx5B=c@kscS>1b39lM)!Nr;v$K>S_S1QUOyBYIb&8tJT z8*qM`ZQR(osZ-BgIXDq)wVhP~@DWX{&iNPaIZ@F>ALRCzEo2FrW=Wcw%o)W0hML|j zbzF)qg00rYWDdB%T7fl-Lixm<QMl23L+!Dw<NMBF>Yv-eXk%hY8dBIoUb8VVjD795 z26b%OBpENtovJy>TdUk^eonKQly&e41i(BsTdQJzS~`j7_bheToz0@n`0Lys#p-vu zTNrf)jWP(Zk&%KZbX8;uIzAf)ZNd5pzoc}Nfkjl{)Wv`FF@68(-*WjMKWuVE=pR<z z0xupiDUr9%tZ_2`S-XV-k@E+SqERCX8NoX$%&(~`_1OwpmsKb*r!!k`1FR(b0Sv6j zJP$GY<eo4bhXq5yd5heqCoHb6e)5M&w74bp4ZxDQ;?^h@-ilgdJEJwR!R)f@Y4fIz zNgg)u#_XRSM|Um^w?D<jsrGg<ACb1pZ%RF#uP4~<nIrT62L!N|)D;wvLGyVid12*- z7%ACHCuVmzQgnXvR<@X}7#^Id^W&i*K)Hsn9ztW^;}J)rY89Yg<jo==dA8oj4zb!> zwogc#`BcOw0$5RPK+9*Kj1FwmyFO$4V=`f4m<s}>HDwx^CT}(n5l<{!+oG;`q87;r zQ<!|HYM?CJ-E1eXHz<xb@K-v!Z)a{nQcZJR#zPA_;Ds5x^&@GN5smAWqbtm8k`?gw zo!Toc*iSn(7io-f_;dCWULm$B*=VXY9=h=1U-qa(Wxqhqx~#}#)bCiHlAfI!FW_qt zpJ0RWn@+KE{ks3rFlTN#bW9)feaCgDiou7bVABJc1Q>{sekNiVe-x^#n)J`%Z^0xv z7d|opk)JBQQXD_e4k8))6(%!d(t|34-JkO*QPa>E1Bp!96DHCX_kuec@1|q5?4y&H z#D?&CDz@djEnG+6?WWs26PB5{Gxw$MU7js}<OZSb%i+V%dAKaw3jeq}8Sveyfp}rh zGS#CC&Vr}%&GKAjj<|Soze+R7j$-Aeq&F2fva7QXv=L@d$O`_TL2E2Z<@N1+OP%`= zO<M-|N7m+%vjuJyCfRqr;z~a(w(ypy*qnSTqUib8`Y16zY>XS%WgHTC{{kf@9wI7h z6cvU-FJ;ti^1<KBwF{XrF2^qPZ~3h%p^ltM^n!&VGKCAyuf?<UeB=S|zc6w*=&^|+ zb#E+d+3?@WKTo}6D8{9Zeisx=Qga*Ed*(OW=Nc&LqzJ<Kt=b%W^sxp2-1)VH2-`FT zc-u3OGx&-)9mWp#mJPfYEhj?F6p+{Ddrv98*jUr|taqaCr*utIa7S_ws}oF5_`9>W z@*XMsx{24nt<bB`_H>hCQC&-#5ME)+KK+tc*sHW-uQWOl8c1;acJ!Bs!~)m2%)i(s zgN;tE{!^C&HE_Wss%sYWXylXIgaTC0k(2nmTaxzg2O_^D9et+7_heJD70c@%Wor-~ zPD_3K!F`uf1&rI2JbvyEEPKM(wHDzKbcGTgPx-JZ&j+Op6rgtlFMj`R5`3=bh{x<m zB?gq1CC<+&7;~=P*iYECx<3HC@c1t2(QgN=|75k#cJ>TQB`Rs+c<`3?77;h%@2<^E zOJ#uA2nmbO=6fC-^CdJ*lT6w*H4<eIQ#4v?UJhOAvjL)SE34%HqVF$c8E&uj9>dws z)Y|FlRxR7QoSCJl4A!=5J1?fDJY*{JS$Cd9asmAbe=aYbYB6(_3)!?8|6uK?^(bMC z%?S8#$L3pwKmmYCvX~34R+AmuucF!w4@KRVW`49^IWw336xNVn;mKk3YOrpnf9iDq zRqBtf4yXQiQhn#;TG2LRNn+>r5kg1nRmo$#@pxED6SqLOk-0=23usB5IT{E5#X3H0 zahB&$BZc>UQ=C13J$;C$=uU33(p?W2k4Am{;?w;OCfP^Z-x5G&X1ncUxxc?r@cEB> zXO?fSj?GY#fooZ}>@Hzp<1l1cotji#6qirnT!ZSx2@u4%9!H^k`ges+PpgChTt_C7 zt5l1M>G@JKk?!@9vUb=Z(TjBwSR(swCutxxS?(kEf4Z`~8L<{4Zbt}{9M|qemLUp* z)udZ~1AP76@a<NX&WmB+6U!(dalBBNWFWvh(CPp&%RILRFlvQD1N06-?hq~zl|^`p zc(l7bPTo^lBGT0L-igrcYYhdJo-vJHWyk4!EP6POK%G$}{675jE?cHXIsN0$*Z;Jg z#!I%N_K;5@mN_`3X_b|?*^q~0L5wgMaq_$JnJ#-Yw(tC*h+6A)iw7OuBDw8RQq8z| zRAA~U!0}0jA@I8~^P3dTh-z9im+_X1L-wkGRi9&KcGz(R!&|Sf66wA7lnh*6QODY~ zB5sbMIN24S6#9O}sLlOyl_vWn^iIsu1un=}cz#g(>VPRBl^q_R`<hUo-iKW36WigR z{9>u|$;|2FHWPp-aYP{I7==39MI6AF&C?15GVoGG#=|54zoM`V<N4Chb|!&9Va?=t z%<wCYINiH~>Ap5_o<+=)wZx|ghK}5iC(%Sq{KSXt&yp^^=`uT%c%SyFyNeJwa-UkP zD($;u;oh4wq^Yj-kvm>Z$4Z}y0Ty@@i|Jczx6l&Vw@)Erku*^XlMw_>2e~)oWX1RZ z<XbtzrJL>d>&X+k!Z?q<t!Zx1hDFAk!|}^wq5NXr_jR~9UKt;2cj~o^bp_!!VV*MY z4zOG5lx(p!EIp7yL#OXwH`$aH14CtH(FF8R5n%_;RxaT+4bO3QJ%O*i-Ht8`@fVTe z@QTJ(GCa&|I_O-?$iJ5ULZd=&BKWK!sb-{w<*w#oK4Z<HT&V<v)}GktIk`QBh-LDq zp45!YF`9ffNzB24Q{!9XQ(Rk*TxzAM!{8T{8zp2*#^1~X8QsuFWG@^eQD(KCgO&R| zb+r`C2DmHate_~kX)V)m=<lW;i`R<KOjjoNZUb3iJ7>cd9V+jpyA#&f_0Uohybewo z9MXU4oL<}xzLFcPS{v}u0T!0qrI6$-u13WY5r{3Tjag~ag^0nu|D;6{WWH`cCzu~8 zd3oQ$CAQSYVpn-#p2)*`QFqrW+^yNNC8=f<8jf(DUFz`IB;^^^Fb)496q&^-jQ%I+ zxquj^Gl2scpC<~F#h_R9OAlp7n;HJw=UwS&rqED4gxtbs*@PdQ?;fxu41zE`^J3?j zyLhND^~sNFB_3*`czm^v4iWDn!~*_0l++~;zFLO0mF3MG+{oQs=p{#^ZiA(MXHNMj zP9`PDh;WrUswdj)59HaLwHk`cXuy|L_L5E{6Mlnc#pyUI>y%4sqJJ==CCJK1aBxfo z5QQ7<uf*s6vg8-?93@Q@Ja!)tn|E)g73k9#_5Ho#GJTuq>k+gl+-x@?b6re<A+0Yv zz^}EUOgQX|6|OQw3uIbKBl%vr;~p$pykN$JgutXY%+kVFwS1UWs0^$n+{g14dnzkr zh#t-c-A{;R-DcnEu~r!kU^P<n#{XBZ>Hs$4jPF@rXOum$T9?`Q_(&BmC;H{<i8Q9( zv%A{|f#&@#_#6wkAATstT_{d6r!DLHGW!$^I==w;Gi+(}W%1EtV|pjKRH`o`QA(|K zOF1XvGFMo?WSS2CKKGgPd&Lt?w*0^+wxy$J5xl>&R?J%-&bj<#-}<XsA4T~?bC0_) zcGpc~!3XLk9R$G5pV>yS;jN}HYZZ;4JiiPk>C>6Y04LcN!O|E0=}h9jvH`xTU2O~E zZ)G22C46Nh{Pc%+X0Kxsk-75cvYEt6Ig-Laagv6yd&S$t{hooHT%$z48SYM$5*z0z zr<1!|lem!zl@lPAfycZ$^{;Idz47D}9ZIA4Mgx{&8h;pV$hFyMir85U#x(;lv`W=> zx?tsve3|ac5K|)lmhIgVS`2h@zthWmR_6`90qH#`P$D!pD(B)~`=tl@)B@mtl^3IA zI*lvO6#W#!l;RBtV0hbQ2g8l=)5~&&Kb^|-9{O^TqXE`l&07FuRk5WWq6j)0q+e~V zf{|$)d~hnV?h9z%3;bqYr`T;cQ7w9GQmF9n9%<an>7f1j?L<ZO(z83ELc6|SdZ7>Q z%I9O}U2R`*q+Q7vS^+Kr$+!G_3g>()*H^cumF<}XfOQxY;JW>E>AiFGExElfYN;As zPX9|sUq2GKu>j~YvY6jm;$XHHYQ4C%k4=hKN{eYJ^<8Qe``|HR_9|)xxVyvw+`ket z5v$hXJ0Aq1U^@ddpZn70cl0KCCS_5nlhN3~8WHo<ewB8jEhsPJ&3fCm6mk<W;PO<l z!^zq7!8B*_^gb-Tun3R_A#8v0CJf-y=`2A%pD3V#s$dtCq@0U;$x{*n7g!t8Lp8Zc zl7_r2#-aXDd-A3uS&DUA2jM7VmL2!4Q4uO@oK9rKQ*FEsIfFXSHyZqMc?>=RoXwPc zCA~W5Q1=@WrC(y;uzHsT2LBN9=iR%<RU1C>^4KmGi`O9|JHFTZcyhBgPUkaTqS~}h zK6(76i+@8d7v!)iNaf&b?(Cnh(c$c@TCX|5A`NEy>sB`_PC73`6o|xcskyWX`q#OY zxL@|G$zSOc`~RhX-6um3Rk7f-rfAf_Y^1|xS&nPD`M64~s0c&~qRGTkH^dIidA6Z% zd1;%w58MZqXgnrw39ycbRvs~tIx{EyB!H=wFpb=us*l)T`jbfOWGBI`)K07QSpg5> zzzg15Z}Gqr+M~(;^z9IHl?zaU3EoPJ#+qnCN+~<vSjb&)`!v^S27VUbPkOJ7)Dwn# zH%TxkvgAes<!zZB25!lT-oIGtZ)Y(EifI~+o${sx%dMO@%+pr_yf6q=#y1>>!`(SS zT{H9Y?u1E&G#=J6oBbi$%LDz_k{fAuO&WiBt0maKTo&uJQ%oLcbhLGtANZd<eRg}> zHWib^9!=8i&I-~^I(3^y2;N@MCG0w94>CzGmQZ6Z=MHSLk7nbHQO2+!Kk`d`mbGFE zw8UsLj;_gpe?<}fZ;<YT@28nookSK(S7)_OzSd6oyv(IQSU)b3bTcyX%lAJ<1LaCx zChw8y>WE~~$&Ww7p+d-Fm&I>rW)m9MQx?*{1dq*mqEMgGPXG9J(q;$DDm~x*SbW3k zOaa^h@j|op0OzuAU^W_sDk!)aJ7{m47JVbO_@wo#g&-*zg>G3kL$=XPodMV4q92FX zxauNLG)lmpq>YZuEGD73=|ON<T3V!Jx*~~MtwWdsR-8RWEqKS@NImaB<MkN{tP>aO zct7rlhB6rzv(#4OHEFf~C9v9lWXnBYft8oLMmG9pMeXl5p)Ps5c!w`GuHQpKctL20 ze=;x*-_Dw67c9Ii@2uL1YjT(a9*7Gj{0;FJ6X*XGTXA=#*~zy5d7#6uga#wR8Q(P` zZ&rFzM~LV~;HPK*CXM1T`kfWYPdTvmmL*j6-1kv5Q4G=;eN`0{Bxld`-E_@Zf`BpM zClM@1WK8&)C3W-!mFn*hnMln?IXwUzU@GaNub!yut1s@Zb1ZNPJx(~u<qruUW%z?G zgSH$U@ip7=VP_DyGee1vj!?nTgdjR~V!V*UWo738(F)f0|C}TfW-MAl=*TTKNv_Lk zT8<=;9&z7PfD?hQ8RkS$+lGEx@h4d9E;KifGk#@+H5tdn<Q7{lc#Ai?xER<ueHnO- zx+{XUl^O9e#3P|Vu(7+To;MJem5Rv7d1B<g;`ia>JG`^_v!}ObH(qZTLU0*|x!5p~ zit>!zTcPE>E%5>o9m)O*87tTAv_5CrBitXWmIO&592x)P0*F2Ihh~cW7pF=y(iO5i zZ+!6Kak>hx(Vp01{_STxtfu+9Si=QGaF^w@o%zR}1aP5Um;3M1(9n1nULP^ibUK;@ z02JTV`(^brf->3T`QOqL8Zx8rq-2Drk6djyP}Vh%Qbb<gym!-etHQf34cxrpa+3sg z4?J~q={+9Lc;wdY>Oxd)d0)HNbAQ-;xmA{TAIBqDf3G(%uC~JMB7{Da*>88|9eTM= zm&8!vIgm${>b*je2hgu)MPeaaQveQ9=cU<UqD~G!>p{AS53esd2xhj_gMGfbxcGbI ztIdeI?2iC>I+HgkUs5J24W)+s5A6TQmAYvp+>d)oXVA!1_{;t=uMt0a{El)WGt+{g zuc}h;_|kJ0fJhe|86z(q@-c?%vzjUO`RXRgd5B9gjkrt=qZ_TRJe;KYq_?l-<c0A3 z2Gmugbc;UH9H3YNA<%O+C$pJhh7uCI+E1tB@c_ojadx3@QhB?}R4h<2N(7B>S3F5# zFEx0)|Bc)X_Y8Rv=ddJc<is`|U987r>CvB^p)^J`Ah)Cc(^o61=@a;XL~b_n6xU4< z)UDk9Il^y0xkAS?AN<=r|2u1$nP*^j$TltUt^ak#y(;%My^t=|?oCls5za7`VKyoQ z)O%kqY;(g_TfwbkGxVA0*F$EIQYOCsT_9YRP@Lr`i-uVO0{H8IL<Z#OndY;mpXWFJ z?=tK7T@(4S*03`i?Lpzk==%ddNEj2s(<OZB#mUNwDz<1k9)kMU{QODeg8dn8gXcY0 z-6T;iAMR!X7DTsy`)1^vZDf3P3z2s?Z4${gdpE~RvLP!>V3YTbYRVnQB|Px_<x{G* zFk1y;BYxznbNZ)&o_wupTZg5xqndQxg#d8u&jeG>+`9=il>dpe-?sc4#rXHEPJLpJ z567n}UgUXvQS;y{H*=bo*D%QYO{#<dYP`me)~%ufIjj^GbJ2MoJdSlc1b)FMlR-b7 z7vevO;?lOvL#XJczET7o4BD-_$)U(H{1Fp#B$U5CkPVlJnoiqVl4X1M8c7ThR~Tqk z8`UdC98t~{SmO*3mPnW;=aSAH{)#hkmf&gO$@S;V)lNjdC+~d2n>!!A5z<T;SjRZ} z^)G~Hv6PBFBsx4DWmT6QH(=fhZFI+Rs&hbhZB)l9MxxcENDV&OmsQ`*IQ;y-*3R-F ziZ*QfOLs_@ARvOkQc?;i(jp;9EG)4gumVe`G)Oln-6*24bV@I+l*H1l<dOnQ!#m#Z z^ZW<TxBW1C?anoGoilTs$MKt)U2s4O7!n3F9}m6llqR|xIOtdNr2IlXUV0Ic19p65 zF5G6d#9GSoEY__^PMq9`cQX5<8CTy+^n>}GO?LUufnXl&ZZPFDIYvO%MXx&iTsp(g z+0SJ-tf$fO#v-1E=vVCh3dd_TW}!UprA-MZo8#qO$zIBd2!1A`xy`LcPNm}G*$@Tz zoGeq-`U=EWD~kT)nMe9S6=KYRcI*g0gAN;8#aGmvwqtjUS4CGYSQSq%AFx^Kl~|p~ zIf1?i<_P&WDulL@XbLT@xf&NfY)t-FO~haX_il`%tw!Mm<3;eU$p&}~oOTkpQ%+J{ ziXD4&uTXwcXzqRAm%tDwLk5X#QAXf;$Xu<23Cp{I(+C9|k2N-!5vPWY+^Zdwwbd7Z zbUq-dfBr;8qeOOV?_n9Xo8Rb|SqrgNqO3Gp?>nG#g{dDoTs&GTD5)OijrC@qCgl|H z-DYmwPAMI=w{m)Y*NLGVX7mLF*xoJa1%k?;+#C-yvLqQu{C#SDR0@u;8-<l8O841h zUWKLI*5kO{p3!If{>%#Hwhu*q(Ao_bFmGddT+^Fx8hy@ysXky1C5Mp0I!NzHdF61P zj-OB&ei}~wwQ9Il&&B5FSA~LVD{-{8k<~bj^wbMeUWD<LhW=Ar5+6MxGHmywZ=&3> z`T6^~hI7LvODK<lUD4-lqflVD!LQ>XGTPUo@j@4D^qBev?<_oRA;sBHoy|n_RAL_x zVl#!tTdeGq@jZnU?GmuIz%jNj_Xwl~sE2@sW|04VSZGIr3y<-7P4+WZUE(CEW97O1 ztNM^NAk{iURr*+Tbm1$3itqg6?`R8!Lwykp!9<Dy%jNw@!9SZQe%Yf9r-L2yHdNL7 zKEQ{jS78-Zf)0%k>irXVJ8`^1I+?pX98^SYP=zZ}5}hLEL)^6J_oCE+mA}o6>()z{ z<%&FV!cbo)hH7#8efvm%PkC9NEN7oE$cWpDB143Ds$GHtFJN9fV`~2EH<kz8z)*xp z&}6y9-p~RjK1ywKycHdmpAgW<9Civ8KVYW*<}kn*aX5`UIfJ3t+d-B^i78_O^dIt? z=oqih``+e_X?>fLk(x@T7koL?9<u6ISsU=rLP8ScP9mwwqSE%AcI-*P?K7ut>^JRt zpJqTEDR^UG?%w>QrRPf&61J4<D)?@NXy>QE<oZ*T%*app(`3(YPo;jwtsmv;0Vd7i zxGvGv?Sh{K0u~ET3@VTcTR}y%!rN=Qh^YJBGXj?E20)}kQIc<W{`scMc$jl*V+nfh z+IdP~_Su((iexVbkwR~vJPa`I^kjOSN@#35G876@SNl+T!RDPt6i#1j>tdx%+Wf-s zp?4TxmSIE7s4G*&U=q9~5ETN!f?M+nl|#nnSBDF222Kq}<x{nRvA!lA@fHc1RyO7V zt{|uOMksW<_gO83*UCdpt9z3*!s3tqUtt&8hcT2?odAO(Yi@%MLJx$|uX`?v)t~(k zv4X=bfEYJ<>j=;YMBW}=e+8G?9o6IAIEne(x@H$7Xj?s4+DKWxCLoyg+TVGQ#bC@5 z81A*M+cgrm1Z`d14_J0H#Y{=nD;>1n%|vLAU)l!vA6=5PIILd0?mI>iG~`5yt49Cr ztALasCcf72Oed$)VyLhU({2U<$uh^vJl_#ow1qLwpD{F&De04UiiOX>J6k!%rs}GG z*9QsK(>D=QasIkW5AKEInV(Ocre9B$odrO@)uV!Wkqu&1romDByB|J?Y@w>sj~l8| zi48kL2vX%{`dqu-S1NRj9U?kGxq$)YE2kN*#!lq^*mZ;E7T@;lmy*k+1G(LRIzzEU z$;IsdcQ4>-&5*Uyafs6aGfSyz7miFaq(Fhm9;{4ooK#J?G&!$uk<@bu37#_}uc$d? zyF$Bg{D8=b8jqYDg^XwIe3TpwVEcJ9$MOEM@4jdqUNw70^d6)2x4QRH?lMQ}Rc{x~ z=yuD<-O{z=RyvP!f1GV`3_o95krVWKi-a8Fe9>;#2?0kv9?dPN>B+6>rNJS~P1GOs zq!^MrnLub{i1F~B?wb6isK417%6D4&-C58duxaP;HA#&?l`^NJ^WFJ$?M*t)O8-13 zMs*6lqAFzt#WuD9u72bblz#?5^0<%k?9NWXo%93!^SSG80lE3fid!+etXiiZgb3eF z(}~o(RNL6XOo@YfveDZMQJOt);d1NI`cuEFTr&L>55jP6Kx=J-yZ2cKN|SBHTMe+w z6@rJu7|rgZQoDNqo{w7_L0&@<ZmQa^mq1ixOQ|NB=cD6Nf`?QKlY2kS6C3y5{3Vm1 z!5`fB=iexS=c>xcg>T?g@oXjWy3%5*{o9Gzp-1H$(KQuJZ_hui^|A)quH6`#9@hnf z`^0d_*d8EsYD*ysYi*Xu+g(<^g%#4RQ>9-lS6MF3Cf+Q`x-v=*myui^XRjp8{A?;1 zDt{?Jae+dMdd!^ey}{?M_M-aAh383wcCKF$K9q(r%S33yne3@k92&?Jl0d0<`BPuL z_GE*y8wH107kCY+soN$1URcz_shpT&&iJng4jpNJ0nEY5CDGw9^s;WrQMz~-2$HnI zd1G(UTgDw+RAeKqGyxl~kKr#X@48sj1@%~TGDJQiovOGcwY9a?2}E95XH}jjQ2~#} zT*#&Uk4f>dM?|0IjIKwokpW1A&b;4|2Z>prEk`_?qZr#;RHDc5pVuOLO`J&Mb4cym zJC5!Csp50AM7)?*KJX9S|K<ce@$I!JeE8X$zmR{Di2ul~^Cl)Fa$msTnaZ7go_0a? zL~(;tt}ZXC@Y}t1(u&rdZmh%F>?eG3FawEEJkD0Sv%Ta+-e_E3b^@SBWqVA{@I8E( zVv}V#I0h`Dw;ih@76Si6Pl%uSz55PM*5>bSJ&i`Dy0cH<{b1fQUfvdKj4%NF?<Exl z3C}0F!|@o~{i!*GPQ^*loe}0DRa*aFtJPxvCsPl4DS#OAriCCr-qZ{f5a6&X3r3K( zmJDdY`Y`5iFmCprZXiEe$3)I%b(pS>baVm*bq9*`7=EJ-v7bt+4SdZ4Xq&+d)fah- z^oEO~<T<{ct2*pKVOh}^)yD_-kW7`!fbCCt9|(A<*>;8=rc3Sjq&pdh)zD?-4fO1J z9Tna{;ESS^iU9#O6C4qPPIF%L-oA&Nh}&`nUm@VGQbNI??+?C-&r1dsGejAWqXOro zH@#eipsYACC6y0E0v1)hrU4|GjJ+1$MPTWv3JXsbSXmDiFiVBA%LR%Rz?EIp;iMwP zyNvG%@ND$5g1rNtw*~gg%oc^$B}yF6=QeJi!rxw(@rj7;Z$}H1PcV!(NDoj^b#~&! z02yD4o2z#K_9D5_v5RWoQ4zIm$_J^LJGjg}n;mf(%ijxM63$q<<Y4Q9#!%UsPOmV= zBN?looNh*z1_nMM%nqPQ*pVE}K9><RX?(Tq5PN4plJUg)M-YK_|12>q9Y2c;EXrYj zxZ2bIlZE9}6F^2>Ni^39Pla>or5URF<xQ2f5CE2A)@uLH;Vt|8qPKPL`S=d>wD2Oh zF`-CN+RK$ydu?kpKQXx>g<vxl_S%3FQuz1<!iOe3U4wIA>W1Rd*=oZ=T1vWZf33Va zF`#`alKg6i`G!@VJ%VxywrC%5a1!pCSGi)*lZeLr(bLFDiHpVgCaVzA5nvebzeDEW zuzi5N{>*FN|5v}hUE`7_c;NEr#wiEKY0d*?sBtx-<iO4_T3DodxJT4;(-q7>VRZKi z&ob{+b_j?0aOwk;W#ix1KrmhAWv!fx^-K@}wwp8x2sz&~o_0-HIT+@a)-j8lF#E>j zx^?ed@}s3A2Frhi341T?*H|CsY*m)%q3+43ktIQA>f`<g#q{}qb3?BY_OUI0Tpt%h zS2GAv+c@@YLHa;G@L^=41bjHVQQMC<x*OG1=e^w?k=W4s(@CsBU(p~!E9&fga6Hjp zNc)VKV8et!{9oSYqjU3W=NJyzP85AA5r-e>k<C1!6U-}6`W4xC`;@;Y#JWebGs#17 z(uh%7<a|ANGd;WiR3%YKAbe{asEq{K(9T6eO%a$&wJ)T*DU9l=cc6w$8*LaS#!29? zleN#e-%I*eCnx6f-ra+v3`J)<$>M=fE@7vv$%59(%3rdqcV%|`(fD|&@aju5A<*3> zAe;KOwR%ueI0pH~%Yp)s(deLF*~Dyxf=t!D+Pe`XK&Qo&y6`{5NFhVjsXlEg6=d1! zG%_lFAHa{iM++tc@GHOF9Nm_h>XsMM)sFp7Bn0jnUb}*P^0GVeB=8IEB;3|DJmF4v zea!*HLeKDCI5k>OR4Rsc`QhTzpJm-gWa_Vs^p_N*s||pnA&Qfxg^4)|OhvtUgl}1% z@)dF@h|1Ua2dmMn%n=2=u5Qv|26#*YJ-z7=EiKBuCJbdPyWH${bBHD4DBiB+qFom; zW3<aCf@G^6mcG1i;_(~gzKhCrLeZeqLrcE9Z5aEb)?sS^EhYXj5dhl)##4Id7DdPU z2}B5vPWh`Yl?#PLCrs+w+TMQ!sxtmp$#A6RJ^90PhEDL__rU1uF9BAI|APfA5ElK5 zN~P$fRgAC<m;}nQv}z1_!`W|j;9t1v=}Az=7|B_g9=s+J%1Zt*N%ow^4XIRVTxI$A zy}q{=uuHx}jVq(QL2F$A@8#~>jTbe~qccP-TCf0P$~zn!-Tx&=!W$9rkdm!zyem8+ zMbW_KRxABUD+i(VVJn*9PKnZoUuy$~m1_!C(%)MFoSY^A+Uh~fQ2PTJ=vk4%4SR7s zMuHxX&+NDFYS_NBYQL2_rDA=1Hq!-2#nq+0_U3fy#CnCIUr%FF_`9+J^o=2)A(Hn6 zp+mcpID3=#Q|vwo%9Ha%3*V^+AWU_6Gv+aVt;c5ci#LtxtdyZk8LpEQM(-oOtfsZ^ zC6q5bj=FmxThh`ZTUHeERU>MDr;%MEdw!9S5cy!*TTf_lnTOx3@F!1a8iZC<Kp;k6 zIOfdnHO0-f4FRx+r(~)Iltw@@b<NOvdG)0)WY7CQde?_Dem=el+?20sqG~<!|J`%+ z<hrRbRpP?v2V`YY0<E0x&zlEnJG<AAAsK1F$+(%Kj<{%3@udVbaeBqcNS&?5EyL^4 zhmW6so0^0A)3mI-=pQmI_8%FT`&l6O?jvY(WO%piO$TX^zTk;BE~FmY;@6cfVxyte zHBxAt`X5S+-pi@Hq_^cXUW$^ao+chiQ{CigA7NjyAD0Br_?=hefti%J+F?ysO8mPU zJ^b^-!zu|y0GVRk!Owt#N74k`?s9ba;bk&j28Qi(ROngsq}}KXltv))G&aM37(NF2 zb;qR!i=5KtZ8$#$phkZ!!+z*C?!o?N2<9?d$Pp>sY)ea5PViT0{EJh=gg57D5*A_H zK#+bZ;I8vPng6c_bJbmq#<8(vhSP=FI<R3#W_UsGfRS8bV(Y)^<<?La2T*E|mPs?` zlyUV%b@@}NlOeE52ES1v^Zh+G9cf)2D>ORwQ@%5a=WamQ{_|uC))>O5|GopLPOkeg zqi%zNwS9KRJ;17X;)!_FHsDLA-$!+@$vso)Lyt>{l&p+arZdHU7C*k8VVVA*i_<O- z)Kz^bG<e@jHtu?u>Ropd64FYFgJ(e9sKTjp>@Kq*`Wc&tB%r0jgbAh{DS}PVlc`5) z+(uPC^jzhHEZLX9c1edcA08!*-I8k4Ree86v>sPT00I%4kiGL6+W78~++V9vB8!+F z>s<5G?~8=juF&bzPuJx`wD~Ois?B&KBNx`IDtqC(C*PkgUwh|TqYvLtSDjeUam@99 zim~deC+Dorva|oKv~SS-BUw9_FM5n{f!Im&M;Q?p)wS3i<EsFbu93yLb2F;en>DZ2 zvcsFMR*u~!n^U}Yhtv5u@WBbr9(=z%?O>=Wi@Cg?+-&t1Y!iYaT@(bB4pvtw+5F-> zqHz#l<ySNY=`<(no7I!aG{}bjt>*BKO*R5%?jP~!a|Kfyz&m<rg}d8Cjt(cz(od%= zvx<7L)9iW0%IfN5*~s-Mqib8=o2gRa(SQc)%lkE0xnXpJko=jBpj8UnT%^;~BJswe z)H{vjjE}&ePXQ3r=EIwSafC=xH%;w!ir3`?xsitl{dC*P$n?dUlS|>xp01=p8_Be8 z5)M3rO&h#^sW}ze9}m98z)=oBZ}6to$+D|Nz~#6DE{pAt{rf%N%?kMS&&BU3>1mYv z7p!uVBY-~V;cp?t<zLC21xeOAi5+|8FFhmQiT_co)?9_wLcI$60dXGde`}7ouo6>G zKrD|wx2adT&HhAOsi}CT)Wp%}K^oP$Mr-Uh%i;|c7q>6F=Ry`S#=TT1vj0Lab??up zJU{H@CkP1(dy#iAd}v!Jf<}Lo{Kl41k<1egBCEfqm6==sXi6p24$RZnlOTXK=KMXo zW@aUaPqwb_FK#IJQ7Cd1FV7OwN9*Ez$|{SiMt?5I#uT9#nnW989$=5<eNJaD(N}Mq zFzuJFy|>c2&CiH+ct_4tj+V7ilc<?aMM)!J%4)(z)lv*PktI}rB(Fk@_>Cg4Ex~t7 zi$zV6qElTgo2w9x4Kk?-#Xy>05x>mBV2MhpU{eg+PJy}8c|=9i;?jEy-v`h8)RDwZ zp?1CemoIHwZo@ARzq9)&9W^g*xWuRJbl-pz3a<{P{QO@i7ryZgG^mIL0E#XTwum0y zA^2w3a62X{W>8Iu2&7!9$n11h=KuW*MhBz{|ARx$UT9nAQtObr=Uws8$edt(?=kZm z(MPoRwmIE|WUBL0;pt{<zLSWrs61q<BnJ=@k)k^TDL%SNIuqq^O0A|d&AeZ~?^Gn} zo4=07%i>URd0PA_@vpQvlQJ8Z_@X;-&<V6PJa2Dz7qnx{4DWUvewe0HAD1>IPE#$y zb5tt0n^rEy>ax}7ni16o;x_)3a!8+kMkrPwfKr}MG1webj};QTr(e5Do_RPMo$<nQ zPW+miH<x!lc6>`V!)@PfUoMX-RI30id&;>o=N539?RAS)f8)CsxL#%Iy}?ltCS`V$ z*;q(dx>_P<P-*;1|3l;a#q8!&rrJN<AK;zvws&&bvL}Nk2Gy&Qu<K@yu!g0kJ%KND zh8Q0>x?zDG(D=V%ay(R}I!67E7k4Y0Z+2^O(YxxC?MvPd5!ZIgCOXLuQ!BM2Kv=WH zjz$r)^Y+<2E9?Yg8~w1~NwF<K$wCU!w>gm9=>{9Ivbe|L7x!^ppuEdA@5B5YeS+h( zE2lWykWAqD`TIa26$9xz>`_P)-nPJln+0dg=`%9lK(nK=SB3jgrH&Akosqs~s!0)E z&AZhZ;fSy`ft9G@XIUORn1zP&2&sy8rp4P4%_U-<=;FGHv-M`q$|uWyg6XDge$TG2 zs5-~ZuZF9*F<qBlo$Ucfmfn}^rEMhY^c&@=EfUjrgV9MPncdfsZpwa;{>|6L&p5Q6 z-CiF|Y_zd!W&5nJ1fKCFouC%lBV+=bX!dSS7+1P38~ni^`PuK*BJ3-HhiJt;fzUp$ zzds&PQS!ujG4_JHUylTA-Ev_*T{d)GLn|VDZ?8POH`WDKTA>xbtJIz6O^c%L)1txX zf|5+ZP-;snIm5vSLRhZQ)JZ%y^SV6DLy)4i!ncMxDD^wsIi5{?wyKtB@7M%1TbmJ2 zYN>@k$u@DK)v~$c=fc4jB-CAirFSA9PV310Anxq_y`PFo9{R<J-0@xK5l`hh9|gM^ z7>ff+oGbawbnzTEWYjcdVuj;uvN29fDz^;o%ykwO2lXu@OLGC<8;8JF85JnKN8bhg z47ZebY>s_^i!6xQMDx>w<JgYvJ4pl`<lXuSB*@%5Mj*D}#_h+!XhmQP#mG_|YKR<9 zHAp(Bk%hQVoLpXCb9Ih$Lp_iZ6h>=^2k?|YY$~L$T8>ujAo!E=pO+weLil_Mib_QN z3@aUa==<T5DPwtf@;KPBg^==g=6k^s@(-(p!l<8`Ueth?zA+gN2syF~1xvirmoOsb zM8*gPjYc^oR7{)<r&f424#Ft(F4{Ad`=mj!KUIvs(-`9MRuUpz3{s`Yal-dqP4@+h zpUp8#LqoZB^gqOKhH|9cuz?8qhM}ehUzQt*k$1k8yf7JRvJoPKiPVp`q*!2+s+6U< zJX&cZ7Sjf;amYJ`f9K7t+GQhQaeBbMiBc|suOEYsC$zVHHVTE|E%=j>`e-Yj&`O&D z>U=2#2}38tN@US^VA_~{J7_Qsj0%CE_(L1Wan^gGAp|rKf)~Z@eM`&2A8!OfPpXsl zXx*LPTHqT5lXu|N3Y8n1A~88H**!Aw4GP9GjM9)cI96~pX|Vp28Y9q5dfh5#aF4sB zK)FrMi8zRT08MAOcjpgIaE~G|JDLS+^MXO2X0+ylF}aMIxG}1FXe&-i8<r3v>5rVA zlsuKvi4KZE3Dz=++V?A^^_m=c!zbNx>0U`Y5xH97#&ExIVl@-VBcOZB?Ld@Sv)Yf( zpqjc~BSZ|&r=EL=WNYpi#AkT)vVgvUV&t7q2Qi62ye8~$y2P$JeNmduxPysUp!yDk zE$bI9p%x@5r-O_2k#R={lUcC@Zp;o#LEW}DQGUegV*~rnXh{-5<COBHsH&3?UW&m{ zGoQ!sp~nX9&taocz}hIL2fG=|r%AqnWK<N|<Hl$e1)u59Maajj+M(;{45Vb=u0Mx~ zN^P;^G8r!&fI-aN1t*QV9z$}$gIOJxdt)V&>Y3>35`sZX8Re82ejjDnr~oiOb_mWV z+c?sZV0j;H*eKMN%;n-G;`z)M9r}jb@{}8q&1b<q_aec3y7M<sMt$<64ohd2syc)X znF{=oGCFhjS-1vF^sTLpJ&OtDqp+2kta9C+b{0LjAU?yVr1H&-a>R^!=*=twKLumQ z#1q`}wg_Fe)+>x6I1*jJLbY|)V)<3HVLGw?s5+|vGUGc9SB~N#+u`|zO1LqWMc|$y z73V0S^aT~t64r-b$iKX9xmUTYQ%FWx_g(nQpf;+H8gf8_Ri3iEm|=~HHFdMLd#Qm! z;4{d65g)H>6mCO$ii*z->3^#gTl<PH{UDei12`{PpfQ~>>`|O`DTE^pNcHE<_zdn= zOVLx7zu|qViLd8p=Nyn~yQB{{b2~!V)k@9CR%5vBR3;qX*pIjn|Dweu^ARfZ)BIg} zZU{~IU6=IK=utjW2^B;v$kbSpsbScnka-RS@Sz92Z}xW*if!cya0q^LR_0U3rBwbR z2E0ylso4we-m>CvY@ev*2Gsi#h24R41hZ@eYDyUX{E|v_<~2gO8MP-7^40cMeayXX zYh{V-!LkT0*`@}|`hIqqRK7hf8R%Zk2X;P?yxG5xkAew6i5VTZpneS)4#?_3B?u%& z3qbxeNCZJazzGVHxB0)`jMqhm1bA_P-oJMQ{2%@SEzZze+~ZhL&(1C5EMR=l3uP^( Jas^n({{w0zL%{$5 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/ic_splash_logo.png b/app/src/main/res/drawable-xxxhdpi/ic_splash_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..8473615db499d8b48833bd23f004ace166ff50bc GIT binary patch literal 34484 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable/ic_splash.xml b/app/src/main/res/drawable/ic_splash.xml index 476cb4e42a..18456786db 100644 --- a/app/src/main/res/drawable/ic_splash.xml +++ b/app/src/main/res/drawable/ic_splash.xml @@ -5,7 +5,7 @@ <item android:drawable="@color/splash_background" /> <item - android:drawable="@drawable/ic_manager" + android:drawable="@drawable/ic_splash_logo" android:gravity="center"/> </layer-list> \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 040404c7ff..6d9f7b7333 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <resources> - <style name="SplashTheme" parent="Theme.MaterialComponents.NoActionBar"> + <style name="SplashTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar"> <item name="android:windowBackground">@drawable/ic_splash</item> <item name="android:windowTranslucentStatus">true</item> <item name="android:windowTranslucentNavigation">true</item> From 735a91606c3e33006c3374f5b0bbcd5d5eecb63e Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 27 Jun 2021 14:26:03 +0400 Subject: [PATCH 014/118] updated proguard rules --- app/proguard-rules.pro | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 172f088481..c9fae9e0dd 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -12,8 +12,13 @@ # public *; #} --keep class com.vanced.manager.core.App --keep class com.crowdin.platform.* { *; } +-keep class com.vanced.manager.network.model.AppDto { + *; +} + +-keep class com.vanced.manager.network.model.JsonDto { + *; +} # Uncomment this to preserve the line number information for # debugging stack traces. From a9cfa224687d3cb27248dbf15d5d0c29e48c2e48 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 27 Jun 2021 19:55:42 +0400 Subject: [PATCH 015/118] more refactor --- .../domain/model/NotificationPrefModel.kt | 6 ++ .../manager/network/model/AppDtoMapper.kt | 8 +- .../com/vanced/manager/ui/MainActivity.kt | 3 +- .../button/ManagerThemedTextButton.kt | 4 +- .../ui/components/dialog/ManagerDialog.kt | 22 ----- .../components/layout/ManagerSwipeRefresh.kt | 28 ++++++ .../preference/CheckboxDialogPreference.kt | 17 ++-- .../preference/CheckboxPreference.kt | 36 +------ .../components/preference/DialogPreference.kt | 56 ----------- .../ui/components/preference/Preference.kt | 35 ------- .../preference/RadiobuttonDialogPreference.kt | 28 +++--- .../ui/components/text/AppVersionText.kt | 9 +- .../ui/components/text/CategoryTitleText.kt | 4 +- .../manager/ui/components/text/ManagerText.kt | 17 ---- .../ui/components/text/ToolbarTitleText.kt | 4 +- .../vanced/manager/ui/layouts/AboutLayout.kt | 33 +++---- .../vanced/manager/ui/layouts/HomeLayout.kt | 75 +++++--------- .../manager/ui/layouts/SettingsLayout.kt | 99 ++++--------------- .../ui/preferences/ManagerPreference.kt | 6 +- .../holder/PreferenceDefaultValueHolder.kt | 10 +- .../ui/preferences/holder/PreferenceHolder.kt | 15 ++- .../lifecycle => resources}/ManagerString.kt | 2 +- .../ui/widgets/button/ManagerCancelButton.kt | 21 ++++ .../ui/widgets/button/ManagerCloseButton.kt | 21 ++++ .../widgets/button/ManagerDownloadButton.kt | 21 ++++ .../ui/widgets/button/ManagerSaveButton.kt | 25 +++++ .../manager/ui/widgets/home/apps/AppsItem.kt | 27 +++++ .../widgets/home/apps/card/AppActionCard.kt | 22 +++-- .../home/apps/dialog/AppChangelogDialog.kt | 10 +- .../home/download/AppDownloadDialogButtons.kt | 18 +--- .../CheckboxInstallationOption.kt | 5 +- .../RadiobuttonInstallationOption.kt | 5 +- .../home/socialmedia/SocialMediaItem.kt | 17 ++++ .../ui/widgets/home/sponsors/SponsorsItem.kt | 17 ++++ .../ui/widgets/layout/CategoryLayout.kt | 5 +- .../widgets/layout/SettingsCategoryLayout.kt | 21 ++++ .../ui/widgets/settings/AccentColorItem.kt | 10 +- .../ui/widgets/settings/ClearFilesItem.kt | 17 ++++ .../ui/widgets/settings/CustomTabsItem.kt | 16 +++ .../ui/widgets/settings/ManagerVariantItem.kt | 28 ++++++ .../ui/widgets/settings/NotificationsItem.kt | 22 +++++ .../manager/ui/widgets/settings/ThemeItem.kt | 32 ++++-- .../vanced/manager/util/AppNotifications.kt | 21 ++++ app/src/main/res/values/strings.xml | 2 +- 44 files changed, 480 insertions(+), 420 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/domain/model/NotificationPrefModel.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/layout/ManagerSwipeRefresh.kt rename app/src/main/java/com/vanced/manager/ui/{components/lifecycle => resources}/ManagerString.kt (89%) create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerCancelButton.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerCloseButton.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerDownloadButton.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerSaveButton.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/home/apps/AppsItem.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/home/socialmedia/SocialMediaItem.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/home/sponsors/SponsorsItem.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/layout/SettingsCategoryLayout.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/settings/ClearFilesItem.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/settings/CustomTabsItem.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/settings/ManagerVariantItem.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/settings/NotificationsItem.kt create mode 100644 app/src/main/java/com/vanced/manager/util/AppNotifications.kt diff --git a/app/src/main/java/com/vanced/manager/domain/model/NotificationPrefModel.kt b/app/src/main/java/com/vanced/manager/domain/model/NotificationPrefModel.kt new file mode 100644 index 0000000000..eb975d7896 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/domain/model/NotificationPrefModel.kt @@ -0,0 +1,6 @@ +package com.vanced.manager.domain.model + +data class NotificationPrefModel( + val app: String, + val prefKey: String +) diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt index 201bb98857..ec65d012c8 100644 --- a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt +++ b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt @@ -78,7 +78,7 @@ class AppDtoMapper( when (app.name) { VANCED_NAME -> listOf( RadiobuttonInstallationOption( - title = R.string.app_installation_options_theme, + titleId = R.string.app_installation_options_theme, preference = vancedThemePref, buttons = app.versions?.map { RadioButtonPreference( @@ -88,7 +88,7 @@ class AppDtoMapper( } ?: emptyList() ), RadiobuttonInstallationOption( - title = R.string.app_installation_options_version, + titleId = R.string.app_installation_options_version, preference = vancedVersionPref, buttons = app.versions?.map { RadioButtonPreference( @@ -98,7 +98,7 @@ class AppDtoMapper( } ?: emptyList() ), CheckboxInstallationOption( - title = R.string.app_installation_options_language, + titleId = R.string.app_installation_options_language, preference = vancedLanguagesPref, buttons = app.versions?.map { CheckboxPreference( @@ -110,7 +110,7 @@ class AppDtoMapper( ) MUSIC_NAME -> listOf( RadiobuttonInstallationOption( - title = R.string.app_installation_options_version, + titleId = R.string.app_installation_options_version, preference = musicVersionPref, buttons = app.versions?.map { RadioButtonPreference( diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index d8d0b04a93..b7f5a41115 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -23,6 +23,7 @@ import com.vanced.manager.ui.components.color.managerAnimatedColor import com.vanced.manager.ui.components.color.managerSurfaceColor import com.vanced.manager.ui.components.color.managerTextColor import com.vanced.manager.ui.components.menu.ManagerDropdownMenuItem +import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.screens.Screen import com.vanced.manager.ui.theme.ManagerTheme import com.vanced.manager.ui.theme.isDark @@ -90,7 +91,7 @@ class MainActivity : AppCompatActivity() { val currentScreenRoute = navController.currentBackStackEntryAsState().value?.destination?.route TopAppBar( title = { - ToolbarTitleText(screens.find { it.route == currentScreenRoute }?.displayName) + ToolbarTitleText(managerString(stringId = screens.find { it.route == currentScreenRoute }?.displayName)) }, backgroundColor = managerAnimatedColor(color = MaterialTheme.colors.surface), actions = { diff --git a/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedTextButton.kt b/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedTextButton.kt index e230c38ab4..4c9a220b3d 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedTextButton.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedTextButton.kt @@ -13,7 +13,7 @@ import com.vanced.manager.ui.preferences.holder.managerAccentColorPref fun ManagerThemedTextButton( modifier: Modifier = Modifier, backgroundColor: Color = managerAccentColor(), - @StringRes stringId: Int, + text: String, onClick: () -> Unit ) { ManagerThemedButton( @@ -21,6 +21,6 @@ fun ManagerThemedTextButton( backgroundColor = backgroundColor, onClick = onClick ) { - ManagerText(stringId = stringId) + ManagerText(text = text) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/dialog/ManagerDialog.kt b/app/src/main/java/com/vanced/manager/ui/components/dialog/ManagerDialog.kt index 15989a39d6..a39fd0de94 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/dialog/ManagerDialog.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/dialog/ManagerDialog.kt @@ -1,6 +1,5 @@ package com.vanced.manager.ui.components.dialog -import androidx.annotation.StringRes import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope @@ -15,27 +14,6 @@ import com.vanced.manager.ui.components.card.ManagerCard import com.vanced.manager.ui.components.text.ManagerText import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal -@Composable -fun ManagerDialog( - @StringRes titleId: Int, - onDismissRequest: () -> Unit, - buttons: @Composable ColumnScope.() -> Unit, - content: @Composable ColumnScope.() -> Unit, -) { - ManagerDialog( - title = { - ManagerText( - modifier = Modifier.align(Alignment.CenterHorizontally), - stringId = titleId, - textStyle = MaterialTheme.typography.h2 - ) - }, - onDismissRequest = onDismissRequest, - buttons = buttons, - content = content - ) -} - @Composable fun ManagerDialog( title: String, diff --git a/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerSwipeRefresh.kt b/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerSwipeRefresh.kt new file mode 100644 index 0000000000..2c06b9ccc1 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerSwipeRefresh.kt @@ -0,0 +1,28 @@ +package com.vanced.manager.ui.components.layout + +import androidx.compose.runtime.Composable +import com.google.accompanist.swiperefresh.SwipeRefresh +import com.google.accompanist.swiperefresh.SwipeRefreshIndicator +import com.google.accompanist.swiperefresh.SwipeRefreshState +import com.vanced.manager.ui.components.color.managerAccentColor + +@Composable +fun ManagerSwipeRefresh( + refreshState: SwipeRefreshState, + onRefresh: () -> Unit, + content: @Composable () -> Unit +) { + SwipeRefresh( + state = refreshState, + onRefresh = onRefresh, + indicator = { state, trigger -> + SwipeRefreshIndicator( + state = state, + refreshTriggerDistance = trigger, + scale = true, + contentColor = managerAccentColor() + ) + }, + content = content + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxDialogPreference.kt index 4eae73920e..1158c8dca1 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxDialogPreference.kt @@ -1,6 +1,5 @@ package com.vanced.manager.ui.components.preference -import androidx.annotation.StringRes import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -9,6 +8,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.toMutableStateList import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource import com.vanced.manager.R import com.vanced.manager.ui.components.button.ManagerThemedTextButton import com.vanced.manager.ui.components.list.CheckboxItem @@ -18,27 +18,28 @@ import kotlinx.coroutines.launch @Composable fun CheckboxDialogPreference( - @StringRes preferenceTitle: Int, - @StringRes preferenceDescription: Int? = null, + preferenceTitle: String, + preferenceDescriptionConverter: (values: List<String>) -> String = { it.joinToString(separator = ", ") }, preference: ManagerPreference<Set<String>>, trailing: @Composable () -> Unit = {}, buttons: List<CheckboxPreference>, onSave: (checkedButtons: List<String>) -> Unit = {} ) { - val selectedButtons = remember { preference.value.value.toMutableStateList() } + var pref by preference + val selectedButtons = remember { pref.toMutableStateList() } val coroutineScope = rememberCoroutineScope() DialogPreference( - preferenceTitleId = preferenceTitle, - preferenceDescriptionId = preferenceDescription, + preferenceTitle = preferenceTitle, + preferenceDescription = preferenceDescriptionConverter(selectedButtons), trailing = trailing, buttons = { isShown -> ManagerThemedTextButton( - stringId = R.string.dialog_button_save, + text = stringResource(id = R.string.dialog_button_save), modifier = Modifier.fillMaxWidth(), onClick = { coroutineScope.launch { isShown.value = false - preference.save(selectedButtons.toSet()) + pref = selectedButtons.toSet() onSave(selectedButtons) } } diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxPreference.kt b/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxPreference.kt index 0ca0ce8fd3..2537692f77 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxPreference.kt @@ -1,42 +1,11 @@ package com.vanced.manager.ui.components.preference -import androidx.annotation.StringRes import androidx.compose.runtime.Composable import androidx.compose.runtime.rememberCoroutineScope import com.vanced.manager.ui.components.checkbox.ManagerCheckbox import com.vanced.manager.ui.preferences.ManagerPreference import kotlinx.coroutines.launch -@Composable -fun CheckboxPreference( - @StringRes preferenceTitle: Int, - @StringRes preferenceDescription: Int? = null, - preference: ManagerPreference<Boolean>, - onCheckedChange: (isChecked: Boolean) -> Unit = {} -) { - val isChecked by preference - val coroutineScope = rememberCoroutineScope() - - val onClick: () -> Unit = { - coroutineScope.launch { - preference.save(!isChecked) - onCheckedChange(isChecked) - } - } - - Preference( - preferenceTitleId = preferenceTitle, - preferenceDescriptionId = preferenceDescription, - onClick = onClick, - trailing = { - ManagerCheckbox( - isChecked = isChecked, - onCheckedChange = { onClick() } - ) - } - ) -} - @Composable fun CheckboxPreference( preferenceTitle: String, @@ -44,16 +13,15 @@ fun CheckboxPreference( preference: ManagerPreference<Boolean>, onCheckedChange: (isChecked: Boolean) -> Unit = {} ) { - val isChecked by preference + var isChecked by preference val coroutineScope = rememberCoroutineScope() val onClick: () -> Unit = { coroutineScope.launch { - preference.save(!isChecked) + isChecked = !isChecked onCheckedChange(isChecked) } } - Preference( preferenceTitle = preferenceTitle, preferenceDescription = preferenceDescription, diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/DialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/components/preference/DialogPreference.kt index 8d2fadea6b..873b8ecc35 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/preference/DialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/preference/DialogPreference.kt @@ -8,62 +8,6 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import com.vanced.manager.ui.components.dialog.ManagerDialog -@Composable -fun DialogPreference( - @StringRes preferenceTitleId: Int, - @StringRes preferenceDescriptionId: Int? = null, - trailing: @Composable () -> Unit = {}, - buttons: @Composable ColumnScope.(isShown: MutableState<Boolean>) -> Unit, - content: @Composable ColumnScope.() -> Unit -) { - val isShown = remember { mutableStateOf(false) } - Preference( - preferenceTitleId = preferenceTitleId, - preferenceDescriptionId = preferenceDescriptionId, - trailing = trailing - ) { - isShown.value = true - } - if (isShown.value) { - ManagerDialog( - titleId = preferenceTitleId, - onDismissRequest = { - isShown.value = false - }, - buttons = { buttons(isShown) }, - content = content - ) - } -} - -@Composable -fun DialogPreference( - @StringRes preferenceTitleId: Int, - preferenceDescription: String? = null, - trailing: @Composable () -> Unit = {}, - buttons: @Composable ColumnScope.(isShown: MutableState<Boolean>) -> Unit, - content: @Composable ColumnScope.() -> Unit -) { - val isShown = remember { mutableStateOf(false) } - Preference( - preferenceTitleId = preferenceTitleId, - preferenceDescription = preferenceDescription, - trailing = trailing - ) { - isShown.value = true - } - if (isShown.value) { - ManagerDialog( - titleId = preferenceTitleId, - onDismissRequest = { - isShown.value = false - }, - buttons = { buttons(isShown) }, - content = content - ) - } -} - @Composable fun DialogPreference( preferenceTitle: String, diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/Preference.kt b/app/src/main/java/com/vanced/manager/ui/components/preference/Preference.kt index 7bb82ff178..f50aecbfa6 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/preference/Preference.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/preference/Preference.kt @@ -1,6 +1,5 @@ package com.vanced.manager.ui.components.preference -import androidx.annotation.StringRes import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.padding import androidx.compose.material.LocalContentColor @@ -14,40 +13,6 @@ import com.vanced.manager.ui.components.list.ManagerListItem import com.vanced.manager.ui.components.text.ManagerText import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal -@Composable -fun Preference( - @StringRes preferenceTitleId: Int, - @StringRes preferenceDescriptionId: Int? = null, - trailing: @Composable () -> Unit = {}, - onClick: () -> Unit -) { - Preference( - preferenceTitle = { ManagerText(stringId = preferenceTitleId) }, - preferenceDescription = if (preferenceDescriptionId != null) {{ - ManagerText(stringId = preferenceDescriptionId) - }} else null, - trailing = trailing, - onClick = onClick - ) -} - -@Composable -fun Preference( - @StringRes preferenceTitleId: Int, - preferenceDescription: String? = null, - trailing: @Composable () -> Unit = {}, - onClick: () -> Unit -) { - Preference( - preferenceTitle = { ManagerText(stringId = preferenceTitleId) }, - preferenceDescription = if (preferenceDescription != null) {{ - ManagerText(text = preferenceDescription) - }} else null, - trailing = trailing, - onClick = onClick - ) -} - @Composable fun Preference( preferenceTitle: String, diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt index 7018348e4e..8b9bc858e8 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt @@ -1,23 +1,21 @@ package com.vanced.manager.ui.components.preference -import androidx.annotation.StringRes -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import com.vanced.manager.R -import com.vanced.manager.ui.components.button.ManagerThemedTextButton import com.vanced.manager.ui.components.list.RadiobuttonItem import com.vanced.manager.ui.preferences.ManagerPreference import com.vanced.manager.ui.preferences.RadioButtonPreference +import com.vanced.manager.ui.widgets.button.ManagerSaveButton import kotlinx.coroutines.launch @Composable fun RadiobuttonDialogPreference( - @StringRes preferenceTitle: Int, + preferenceTitle: String, + preferenceDescriptionConverter: (value: String) -> String = { it }, preference: ManagerPreference<String>, trailing: @Composable () -> Unit = {}, buttons: List<RadioButtonPreference>, @@ -26,21 +24,17 @@ fun RadiobuttonDialogPreference( val coroutineScope = rememberCoroutineScope() var currentSelection by remember { mutableStateOf(preference.value.value) } DialogPreference( - preferenceTitleId = preferenceTitle, - preferenceDescription = currentSelection, + preferenceTitle = preferenceTitle, + preferenceDescription = preferenceDescriptionConverter(currentSelection), trailing = trailing, buttons = { isShown -> - ManagerThemedTextButton( - stringId = R.string.dialog_button_save, - modifier = Modifier.fillMaxWidth(), - onClick = { - coroutineScope.launch { - isShown.value = false - preference.save(currentSelection) - onSave(currentSelection) - } + ManagerSaveButton { + coroutineScope.launch { + isShown.value = false + preference.save(currentSelection) + onSave(currentSelection) } - ) + } } ) { LazyColumn( diff --git a/app/src/main/java/com/vanced/manager/ui/components/text/AppVersionText.kt b/app/src/main/java/com/vanced/manager/ui/components/text/AppVersionText.kt index ad0604c319..51832a1497 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/text/AppVersionText.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/text/AppVersionText.kt @@ -1,19 +1,14 @@ package com.vanced.manager.ui.components.text -import androidx.annotation.StringRes import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable -import com.vanced.manager.R -import com.vanced.manager.ui.components.lifecycle.managerString @Composable fun AppVersionText( - @StringRes stringId: Int, - version: String? + text: String ) { ManagerText( - version ?: managerString(stringId = R.string.app_content_unavailable), - stringId = stringId, + text = text, textStyle = MaterialTheme.typography.body2, ) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/text/CategoryTitleText.kt b/app/src/main/java/com/vanced/manager/ui/components/text/CategoryTitleText.kt index 283764aba0..43d17a7316 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/text/CategoryTitleText.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/text/CategoryTitleText.kt @@ -10,11 +10,11 @@ import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal @Composable fun CategoryTitleText( - @StringRes stringId: Int + text: String ) { ManagerText( modifier = Modifier.padding(start = defaultContentPaddingHorizontal), - stringId = stringId, + text = text, textStyle = MaterialTheme.typography.h2, color = managerAnimatedColor(MaterialTheme.colors.onSurface) ) diff --git a/app/src/main/java/com/vanced/manager/ui/components/text/ManagerText.kt b/app/src/main/java/com/vanced/manager/ui/components/text/ManagerText.kt index 09eb4844f0..7b6255813e 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/text/ManagerText.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/text/ManagerText.kt @@ -6,23 +6,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.TextStyle -import com.vanced.manager.ui.components.lifecycle.managerString - -@Composable -fun ManagerText( - vararg formatArgs: Any, - modifier: Modifier = Modifier, - color: Color = Color.Unspecified, - textStyle: TextStyle = LocalTextStyle.current, - stringId: Int?, -) { - ManagerText( - modifier = modifier, - color = color, - textStyle = textStyle, - text = managerString(stringId, *formatArgs), - ) -} @Composable fun ManagerText( diff --git a/app/src/main/java/com/vanced/manager/ui/components/text/ToolbarTitleText.kt b/app/src/main/java/com/vanced/manager/ui/components/text/ToolbarTitleText.kt index 916ece22e4..9c1d7b717a 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/text/ToolbarTitleText.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/text/ToolbarTitleText.kt @@ -6,10 +6,10 @@ import com.vanced.manager.ui.components.color.managerAnimatedColor @Composable fun ToolbarTitleText( - stringId: Int? + text: String ) { ManagerText( - stringId = stringId, + text = text, textStyle = MaterialTheme.typography.h1, color = managerAnimatedColor(MaterialTheme.colors.onSurface) ) diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/AboutLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/AboutLayout.kt index 01866bf0fe..4b55d8f975 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/AboutLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/layouts/AboutLayout.kt @@ -3,16 +3,15 @@ package com.vanced.manager.ui.layouts import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp @@ -22,7 +21,7 @@ import com.vanced.manager.ui.components.card.ManagerLinkCard import com.vanced.manager.ui.components.card.ManagerThemedCard import com.vanced.manager.ui.components.layout.ManagerScrollableColumn import com.vanced.manager.ui.components.layout.ScrollableItemRow -import com.vanced.manager.ui.components.lifecycle.managerString +import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.components.list.ManagerListItem import com.vanced.manager.ui.components.text.ManagerText import com.vanced.manager.ui.widgets.layout.CategoryLayout @@ -126,7 +125,7 @@ fun AboutLayout() { AboutManagerCard() credits.fastForEach { credit -> CategoryLayout( - categoryNameId = credit.nameId, + categoryName = managerString(stringId = credit.nameId), categoryNameSpacing = 4.dp ) { Column { @@ -149,7 +148,11 @@ fun AboutLayout() { } } } - CategoryLayout(categoryNameId = R.string.about_category_sources) { + CategoryLayout( + categoryName = managerString( + stringId = R.string.about_category_sources + ), + ) { ScrollableItemRow(items = sources) { source -> ManagerLinkCard( title = managerString(source.nameId), @@ -165,25 +168,14 @@ fun AboutLayout() { fun AboutManagerCard() { ManagerThemedCard { Column( - modifier = Modifier -// .clip(managerShape()) -// .background( -// Brush.horizontalGradient( -// colors = listOf( -// vancedBlue, -// vancedRed -// ) -// ) -// ) + modifier = Modifier, + horizontalAlignment = Alignment.CenterHorizontally ) { Text( - text = "Vanced Manager", - textAlign = TextAlign.Center, + text = managerString(stringId = R.string.app_name), modifier = Modifier - .fillMaxWidth() .padding(top = 8.dp), fontSize = 30.sp, - color = Color.White ) Text( text = buildAnnotatedString { @@ -193,12 +185,9 @@ fun AboutManagerCard() { } append("d") }, - textAlign = TextAlign.Center, modifier = Modifier - .fillMaxWidth() .padding(bottom = 8.dp), fontSize = 16.sp, - color = Color.White ) } } diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt index d41ee2b719..dd14beab4c 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt @@ -1,31 +1,21 @@ package com.vanced.manager.ui.layouts -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState -import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.compose.ui.util.fastForEach -import com.google.accompanist.swiperefresh.SwipeRefresh -import com.google.accompanist.swiperefresh.SwipeRefreshIndicator import com.google.accompanist.swiperefresh.rememberSwipeRefreshState import com.vanced.manager.R -import com.vanced.manager.domain.model.App -import com.vanced.manager.ui.components.card.ManagerLinkCard -import com.vanced.manager.ui.components.color.managerAccentColor import com.vanced.manager.ui.components.layout.ManagerScrollableColumn -import com.vanced.manager.ui.components.layout.ScrollableItemRow -import com.vanced.manager.ui.preferences.holder.managerAccentColorPref +import com.vanced.manager.ui.components.layout.ManagerSwipeRefresh +import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.utils.defaultContentPaddingVertical import com.vanced.manager.ui.viewmodel.HomeViewModel -import com.vanced.manager.ui.widgets.home.apps.card.AppCard +import com.vanced.manager.ui.widgets.home.apps.HomeAppsItem +import com.vanced.manager.ui.widgets.home.socialmedia.HomeSocialMediaItem +import com.vanced.manager.ui.widgets.home.sponsors.HomeSponsorsItem import com.vanced.manager.ui.widgets.layout.CategoryLayout -import com.vanced.manager.util.socialMedia -import com.vanced.manager.util.sponsors import org.koin.androidx.compose.getViewModel @Composable @@ -34,52 +24,35 @@ fun HomeLayout() { val viewModel: HomeViewModel = getViewModel() val isFetching by viewModel.isFetching.observeAsState(false) val refreshState = rememberSwipeRefreshState(isRefreshing = isFetching) - SwipeRefresh( - state = refreshState, - onRefresh = { viewModel.fetch() }, - indicator = { state, trigger -> - SwipeRefreshIndicator( - state = state, - refreshTriggerDistance = trigger, - scale = true, - contentColor = managerAccentColor() - ) - } + ManagerSwipeRefresh( + refreshState = refreshState, + onRefresh = { viewModel.fetch() } ) { ManagerScrollableColumn( contentPaddingVertical = defaultContentPaddingVertical, itemSpacing = 18.dp ) { CategoryLayout( - categoryNameId = R.string.home_category_apps, + categoryName = managerString( + stringId = R.string.home_category_apps + ), contentPaddingHorizontal = 0.dp ) { - Column( - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - viewModel.apps.fastForEach { app -> - val observedApp by app.observeAsState(initial = App()) - AppCard(observedApp, isFetching) - } - } + HomeAppsItem(viewModel, isFetching) } - CategoryLayout(categoryNameId = R.string.home_category_support_us) { - ScrollableItemRow(items = sponsors) { sponsor -> - ManagerLinkCard( - icon = sponsor.icon, - title = sponsor.title, - link = sponsor.link - ) - } + CategoryLayout( + categoryName = managerString( + stringId = R.string.home_category_support_us + ) + ) { + HomeSponsorsItem() } - CategoryLayout(categoryNameId = R.string.home_category_social_media) { - ScrollableItemRow(items = socialMedia) { socialMedia -> - ManagerLinkCard( - icon = socialMedia.icon, - title = socialMedia.title, - link = socialMedia.link - ) - } + CategoryLayout( + categoryName = managerString( + stringId = R.string.home_category_social_media + ) + ) { + HomeSocialMediaItem() } } } diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt index f51f24d18c..43b6456d4b 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt @@ -1,41 +1,14 @@ package com.vanced.manager.ui.layouts -import androidx.compose.foundation.layout.Column import androidx.compose.runtime.* +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.vanced.manager.R import com.vanced.manager.ui.components.layout.ManagerScrollableColumn -import com.vanced.manager.ui.components.preference.CheckboxPreference -import com.vanced.manager.ui.components.preference.Preference -import com.vanced.manager.ui.components.preference.RadiobuttonDialogPreference -import com.vanced.manager.ui.preferences.RadioButtonPreference -import com.vanced.manager.ui.preferences.holder.managerVariantPref -import com.vanced.manager.ui.preferences.holder.useCustomTabsPref -import com.vanced.manager.ui.preferences.managerBooleanPreference +import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.utils.defaultContentPaddingVertical -import com.vanced.manager.ui.widgets.layout.CategoryLayout -import com.vanced.manager.ui.widgets.settings.SettingsAccentColorItem -import com.vanced.manager.ui.widgets.settings.ThemeSettingsItem - -data class NotificationPrefModel( - val app: String, - val prefKey: String -) - -private val notificationApps = arrayOf( - NotificationPrefModel( - app = "YouTube Vanced", - prefKey = "vanced" - ), - NotificationPrefModel( - app = "YouTube Music Vanced", - prefKey = "music" - ), - NotificationPrefModel( - app = "Vanced microG", - prefKey = "microg" - ) -) +import com.vanced.manager.ui.widgets.layout.SettingsCategoryLayout +import com.vanced.manager.ui.widgets.settings.* @Composable fun SettingsLayout() { @@ -43,59 +16,23 @@ fun SettingsLayout() { contentPaddingVertical = defaultContentPaddingVertical, itemSpacing = 12.dp ) { - CategoryLayout( - categoryNameId = R.string.settings_category_behaviour, - contentPaddingHorizontal = 0.dp, - categoryNameSpacing = 4.dp + SettingsCategoryLayout( + categoryName = managerString( + stringId = R.string.settings_category_behaviour + ) ) { - Column { - CheckboxPreference( - preferenceTitle = R.string.settings_preference_use_custom_tabs_title, - preferenceDescription = R.string.settings_preference_use_custom_tabs_summary, - preference = useCustomTabsPref - ) - notificationApps.forEach { - with(it) { - CheckboxPreference( - preferenceTitle = "$app Push Notifications", - preferenceDescription = "Receive push notifications when an update for $app is released", - preference = managerBooleanPreference( - key = "${prefKey}_notifications", - defaultValue = true - ) - ) - } - } - RadiobuttonDialogPreference( - preferenceTitle = R.string.settings_preference_variant_title, - preference = managerVariantPref, - buttons = listOf( - RadioButtonPreference( - title = "nonroot", - key = "nonroot" - ), - RadioButtonPreference( - title = "root", - key = "root" - ), - ) - ) - Preference( - preferenceTitleId = R.string.settings_preference_clear_files_title, - preferenceDescriptionId = null, - onClick = {} - ) - } + SettingsCustomTabsItem() + SettingsNotificationsItem() + SettingsManagerVariantItem() + } - CategoryLayout( - categoryNameId = R.string.settings_category_appearance, - contentPaddingHorizontal = 0.dp, - categoryNameSpacing = 4.dp + SettingsCategoryLayout( + categoryName = managerString( + stringId = R.string.settings_category_appearance + ) ) { - Column { - SettingsAccentColorItem() - ThemeSettingsItem() - } + SettingsAccentColorItem() + ThemeSettingsItem() } } diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/ManagerPreference.kt b/app/src/main/java/com/vanced/manager/ui/preferences/ManagerPreference.kt index 44807d7a73..0d3e216aff 100644 --- a/app/src/main/java/com/vanced/manager/ui/preferences/ManagerPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/preferences/ManagerPreference.kt @@ -27,6 +27,10 @@ class ManagerPreference<T>( operator fun getValue(thisRef: Any?, property: KProperty<*>) = value.value + operator fun setValue(thisRef: Any?, property: KProperty<*>, newValue: T) { + save(newValue) + } + fun save(newValue: T) { _value.value = newValue sharedPreferences.edit { @@ -34,7 +38,7 @@ class ManagerPreference<T>( } } - //It's Chewsday innit - © Bri'ish ppl + //It's Chewsday innit init { _value.value = getter(sharedPreferences) } diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceDefaultValueHolder.kt b/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceDefaultValueHolder.kt index ef48dd0d54..9844a3c33d 100644 --- a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceDefaultValueHolder.kt +++ b/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceDefaultValueHolder.kt @@ -2,5 +2,11 @@ package com.vanced.manager.ui.preferences.holder const val MANAGER_VARIANT_DEFAULT_VALUE = "nonroot" -const val VANCED_ENABLED_DEFAULT_VALUE = true -const val MUSIC_ENABLED_DEFAULT_VALUE = true \ No newline at end of file +const val MANAGER_THEME_DEFAULT_VALUE = "System Default" + +const val VANCED_THEME_DEFAULT_VALUE = "Dark" +val VANCED_LANGUAGE_DEFAULT_VALUE = setOf("en") + +const val APP_VERSION_DEFAULT_VALUE = "latest" + +const val APP_ENABLED_DEFAULT_VALUE = true \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceHolder.kt b/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceHolder.kt index 6f719e6e40..4f89a6374d 100644 --- a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceHolder.kt +++ b/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceHolder.kt @@ -7,17 +7,16 @@ import com.vanced.manager.ui.preferences.managerStringSetPreference import com.vanced.manager.ui.theme.defAccentColor val useCustomTabsPref = managerBooleanPreference(USE_CUSTOM_TABS_KEY) - val managerVariantPref = managerStringPreference(MANAGER_VARIANT_KEY, MANAGER_VARIANT_DEFAULT_VALUE) -val managerThemePref = managerStringPreference(MANAGER_THEME_KEY, "System Default") +val managerThemePref = managerStringPreference(MANAGER_THEME_KEY, MANAGER_THEME_DEFAULT_VALUE) val managerAccentColorPref = managerLongPreference(MANAGER_ACCENT_COLOR_KEY, defAccentColor) -val vancedThemePref = managerStringPreference(APP_VANCED_THEME_KEY, "Dark") -val vancedVersionPref = managerStringPreference(APP_VANCED_VERSION_KEY, "latest") -val vancedLanguagesPref = managerStringSetPreference(APP_VANCED_LANGUAGE_KEY, setOf("en")) +val vancedThemePref = managerStringPreference(APP_VANCED_THEME_KEY, VANCED_THEME_DEFAULT_VALUE) +val vancedVersionPref = managerStringPreference(APP_VANCED_VERSION_KEY, APP_VERSION_DEFAULT_VALUE) +val vancedLanguagesPref = managerStringSetPreference(APP_VANCED_LANGUAGE_KEY, VANCED_LANGUAGE_DEFAULT_VALUE) -val musicVersionPref = managerStringPreference(APP_MUSIC_VERSION_KEY, "latest") +val musicVersionPref = managerStringPreference(APP_MUSIC_VERSION_KEY, APP_VERSION_DEFAULT_VALUE) -val vancedEnabled = managerBooleanPreference(VANCED_ENABLED_KEY, VANCED_ENABLED_DEFAULT_VALUE) -val musicEnabled = managerBooleanPreference(MUSIC_ENABLED_KEY, MUSIC_ENABLED_DEFAULT_VALUE) \ No newline at end of file +val vancedEnabled = managerBooleanPreference(VANCED_ENABLED_KEY, APP_ENABLED_DEFAULT_VALUE) +val musicEnabled = managerBooleanPreference(MUSIC_ENABLED_KEY, APP_ENABLED_DEFAULT_VALUE) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/lifecycle/ManagerString.kt b/app/src/main/java/com/vanced/manager/ui/resources/ManagerString.kt similarity index 89% rename from app/src/main/java/com/vanced/manager/ui/components/lifecycle/ManagerString.kt rename to app/src/main/java/com/vanced/manager/ui/resources/ManagerString.kt index 3af1af083d..04a35744d3 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/lifecycle/ManagerString.kt +++ b/app/src/main/java/com/vanced/manager/ui/resources/ManagerString.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.lifecycle +package com.vanced.manager.ui.resources import androidx.annotation.StringRes import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerCancelButton.kt b/app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerCancelButton.kt new file mode 100644 index 0000000000..47a658727e --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerCancelButton.kt @@ -0,0 +1,21 @@ +package com.vanced.manager.ui.widgets.button + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.vanced.manager.R +import com.vanced.manager.ui.components.button.ManagerThemedTextButton +import com.vanced.manager.ui.resources.managerString + +@Composable +fun ManagerCancelButton( + onClick: () -> Unit +) { + ManagerThemedTextButton( + modifier = Modifier.fillMaxWidth(), + text = managerString( + stringId = R.string.dialog_button_cancel + ), + onClick = onClick + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerCloseButton.kt b/app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerCloseButton.kt new file mode 100644 index 0000000000..524600a6df --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerCloseButton.kt @@ -0,0 +1,21 @@ +package com.vanced.manager.ui.widgets.button + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.vanced.manager.R +import com.vanced.manager.ui.components.button.ManagerThemedTextButton +import com.vanced.manager.ui.resources.managerString + +@Composable +fun ManagerCloseButton( + onClick: () -> Unit +) { + ManagerThemedTextButton( + modifier = Modifier.fillMaxWidth(), + text = managerString( + stringId = R.string.dialog_button_close + ), + onClick = onClick + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerDownloadButton.kt b/app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerDownloadButton.kt new file mode 100644 index 0000000000..8dba17b406 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerDownloadButton.kt @@ -0,0 +1,21 @@ +package com.vanced.manager.ui.widgets.button + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.vanced.manager.R +import com.vanced.manager.ui.components.button.ManagerThemedTextButton +import com.vanced.manager.ui.resources.managerString + +@Composable +fun ManagerDownloadButton( + onClick: () -> Unit +) { + ManagerThemedTextButton( + modifier = Modifier.fillMaxWidth(), + text = managerString( + stringId = R.string.app_download_dialog_confirm + ), + onClick = onClick + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerSaveButton.kt b/app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerSaveButton.kt new file mode 100644 index 0000000000..8e7d3c63d2 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerSaveButton.kt @@ -0,0 +1,25 @@ +package com.vanced.manager.ui.widgets.button + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import com.vanced.manager.R +import com.vanced.manager.ui.components.button.ManagerThemedTextButton +import com.vanced.manager.ui.components.color.managerAccentColor +import com.vanced.manager.ui.resources.managerString + +@Composable +fun ManagerSaveButton( + backgroundColor: Color = managerAccentColor(), + onClick: () -> Unit +) { + ManagerThemedTextButton( + modifier = Modifier.fillMaxWidth(), + text = managerString( + stringId = R.string.dialog_button_save + ), + backgroundColor = backgroundColor, + onClick = onClick + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/AppsItem.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/AppsItem.kt new file mode 100644 index 0000000000..98a461fac6 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/AppsItem.kt @@ -0,0 +1,27 @@ +package com.vanced.manager.ui.widgets.home.apps + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.ui.unit.dp +import androidx.compose.ui.util.fastForEach +import com.vanced.manager.domain.model.App +import com.vanced.manager.ui.viewmodel.HomeViewModel +import com.vanced.manager.ui.widgets.home.apps.card.AppCard + +@Composable +fun HomeAppsItem( + viewModel: HomeViewModel, + isFetching: Boolean +) { + Column( + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + viewModel.apps.fastForEach { app -> + val observedApp by app.observeAsState(initial = App()) + AppCard(observedApp, isFetching) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt index 3d46ffd975..203c67ab23 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt @@ -10,10 +10,10 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.vanced.manager.R import com.vanced.manager.ui.components.button.IconButton -import com.vanced.manager.ui.components.color.ThemedCardContentColorProvider import com.vanced.manager.ui.components.text.ManagerText import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal import com.vanced.manager.ui.components.text.AppVersionText @@ -37,14 +37,24 @@ fun AppActionCard( .wrapContentWidth(Alignment.Start), verticalArrangement = Arrangement.spacedBy(4.dp) ) { - ManagerText(stringId = R.string.app_versions) + ManagerText( + text = stringResource(id = R.string.app_versions) + ) AppVersionText( - stringId = R.string.app_version_latest, - version = appRemoteVersion + text = stringResource( + id = R.string.app_version_latest, + appRemoteVersion ?: stringResource( + id = R.string.app_content_unavailable + ) + ) ) AppVersionText( - stringId = R.string.app_version_installed, - version = appInstalledVersion + text = stringResource( + id = R.string.app_version_installed, + appInstalledVersion ?: stringResource( + id = R.string.app_content_unavailable + ) + ) ) } Row( diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppChangelogDialog.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppChangelogDialog.kt index 5836b88995..845a61b9ad 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppChangelogDialog.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppChangelogDialog.kt @@ -1,6 +1,5 @@ package com.vanced.manager.ui.widgets.home.apps.dialog -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable @@ -8,10 +7,10 @@ import androidx.compose.runtime.MutableState import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.vanced.manager.R -import com.vanced.manager.ui.components.button.ManagerThemedTextButton import com.vanced.manager.ui.components.dialog.ManagerDialog -import com.vanced.manager.ui.components.lifecycle.managerString +import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.components.text.ManagerText +import com.vanced.manager.ui.widgets.button.ManagerCloseButton @Composable fun AppChangelogDialog( @@ -24,10 +23,7 @@ fun AppChangelogDialog( title = managerString(R.string.app_info_title, appName), onDismissRequest = { showDialog.value = false }, buttons = { - ManagerThemedTextButton( - modifier = Modifier.fillMaxWidth(), - stringId = R.string.dialog_button_close - ) { + ManagerCloseButton { showDialog.value = false } } diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogButtons.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogButtons.kt index 9ea86aa2a0..35aa46eeeb 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogButtons.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogButtons.kt @@ -1,11 +1,9 @@ package com.vanced.manager.ui.widgets.home.download -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState -import androidx.compose.ui.Modifier -import com.vanced.manager.R -import com.vanced.manager.ui.components.button.ManagerThemedTextButton +import com.vanced.manager.ui.widgets.button.ManagerCancelButton +import com.vanced.manager.ui.widgets.button.ManagerDownloadButton @Composable fun AppDownloadDialogButtons( @@ -14,15 +12,7 @@ fun AppDownloadDialogButtons( onCancelClick: () -> Unit, ) { when (showProgress.value) { - true -> ManagerThemedTextButton( - stringId = R.string.dialog_button_cancel, - modifier = Modifier.fillMaxWidth(), - onClick = onCancelClick - ) - false -> ManagerThemedTextButton( - stringId = R.string.app_download_dialog_confirm, - modifier = Modifier.fillMaxWidth(), - onClick = onDownloadClick - ) + true -> ManagerCancelButton(onClick = onCancelClick) + false -> ManagerDownloadButton(onClick = onDownloadClick) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/CheckboxInstallationOption.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/CheckboxInstallationOption.kt index f3c7e80c93..c299784192 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/CheckboxInstallationOption.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/CheckboxInstallationOption.kt @@ -1,18 +1,19 @@ package com.vanced.manager.ui.widgets.home.installation import androidx.annotation.StringRes +import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.components.preference.CheckboxDialogPreference import com.vanced.manager.ui.preferences.CheckboxPreference import com.vanced.manager.ui.preferences.ManagerPreference data class CheckboxInstallationOption( - @StringRes val title: Int, + @StringRes val titleId: Int, val preference: ManagerPreference<Set<String>>, val buttons: List<CheckboxPreference> ) : InstallationOption( item = { CheckboxDialogPreference( - preferenceTitle = title, + preferenceTitle = managerString(stringId = titleId), preference = preference, buttons = buttons ) diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/RadiobuttonInstallationOption.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/RadiobuttonInstallationOption.kt index ceb4260bac..be03278057 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/RadiobuttonInstallationOption.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/RadiobuttonInstallationOption.kt @@ -4,15 +4,16 @@ import androidx.annotation.StringRes import com.vanced.manager.ui.components.preference.RadiobuttonDialogPreference import com.vanced.manager.ui.preferences.ManagerPreference import com.vanced.manager.ui.preferences.RadioButtonPreference +import com.vanced.manager.ui.resources.managerString data class RadiobuttonInstallationOption( - @StringRes val title: Int, + @StringRes val titleId: Int, val preference: ManagerPreference<String>, val buttons: List<RadioButtonPreference> ) : InstallationOption( item = { RadiobuttonDialogPreference( - preferenceTitle = title, + preferenceTitle = managerString(stringId = titleId), preference = preference, buttons = buttons ) diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/socialmedia/SocialMediaItem.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/socialmedia/SocialMediaItem.kt new file mode 100644 index 0000000000..4fa6ed78bc --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/socialmedia/SocialMediaItem.kt @@ -0,0 +1,17 @@ +package com.vanced.manager.ui.widgets.home.socialmedia + +import androidx.compose.runtime.Composable +import com.vanced.manager.ui.components.card.ManagerLinkCard +import com.vanced.manager.ui.components.layout.ScrollableItemRow +import com.vanced.manager.util.socialMedia + +@Composable +fun HomeSocialMediaItem() { + ScrollableItemRow(items = socialMedia) { socialMedia -> + ManagerLinkCard( + icon = socialMedia.icon, + title = socialMedia.title, + link = socialMedia.link + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/sponsors/SponsorsItem.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/sponsors/SponsorsItem.kt new file mode 100644 index 0000000000..0cc4aa3a0f --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/sponsors/SponsorsItem.kt @@ -0,0 +1,17 @@ +package com.vanced.manager.ui.widgets.home.sponsors + +import androidx.compose.runtime.Composable +import com.vanced.manager.ui.components.card.ManagerLinkCard +import com.vanced.manager.ui.components.layout.ScrollableItemRow +import com.vanced.manager.util.sponsors + +@Composable +fun HomeSponsorsItem() { + ScrollableItemRow(items = sponsors) { sponsor -> + ManagerLinkCard( + icon = sponsor.icon, + title = sponsor.title, + link = sponsor.link + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/layout/CategoryLayout.kt b/app/src/main/java/com/vanced/manager/ui/widgets/layout/CategoryLayout.kt index 75edce1bd9..b6ed6aaef8 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/layout/CategoryLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/layout/CategoryLayout.kt @@ -1,6 +1,5 @@ package com.vanced.manager.ui.widgets.layout -import androidx.annotation.StringRes import androidx.compose.foundation.layout.* import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -11,7 +10,7 @@ import com.vanced.manager.ui.components.text.CategoryTitleText @Composable fun CategoryLayout( - @StringRes categoryNameId: Int, + categoryName: String, contentPaddingHorizontal: Dp = defaultContentPaddingHorizontal, categoryNameSpacing: Dp = defaultContentPaddingVertical, content: @Composable () -> Unit, @@ -20,7 +19,7 @@ fun CategoryLayout( modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(categoryNameSpacing), ) { - CategoryTitleText(stringId = categoryNameId) + CategoryTitleText(text = categoryName) Box( modifier = Modifier.padding(horizontal = contentPaddingHorizontal) ) { diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/layout/SettingsCategoryLayout.kt b/app/src/main/java/com/vanced/manager/ui/widgets/layout/SettingsCategoryLayout.kt new file mode 100644 index 0000000000..69a9d9fdff --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/layout/SettingsCategoryLayout.kt @@ -0,0 +1,21 @@ +package com.vanced.manager.ui.widgets.layout + +import androidx.compose.foundation.layout.Column +import androidx.compose.runtime.Composable +import androidx.compose.ui.unit.dp + +@Composable +fun SettingsCategoryLayout( + categoryName: String, + content: @Composable () -> Unit +) { + CategoryLayout( + categoryName = categoryName, + contentPaddingHorizontal = 0.dp, + categoryNameSpacing = 4.dp + ) { + Column { + content() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/settings/AccentColorItem.kt b/app/src/main/java/com/vanced/manager/ui/widgets/settings/AccentColorItem.kt index 30a8dfaa0e..8dfc334339 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/settings/AccentColorItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/settings/AccentColorItem.kt @@ -3,20 +3,22 @@ package com.vanced.manager.ui.widgets.settings import androidx.compose.runtime.* import androidx.compose.ui.graphics.Color import com.vanced.manager.R -import com.vanced.manager.ui.components.button.ManagerThemedTextButton import com.vanced.manager.ui.components.color.ManagerColorPicker import com.vanced.manager.ui.components.preference.DialogPreference +import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.preferences.holder.managerAccentColorPref +import com.vanced.manager.ui.widgets.button.ManagerSaveButton @Composable fun SettingsAccentColorItem() { var localAccentColor by remember { mutableStateOf(managerAccentColorPref.value.value) } DialogPreference( - preferenceTitleId = R.string.settings_preference_accent_color_title, + preferenceTitle = managerString( + stringId = R.string.settings_preference_accent_color_title + ), preferenceDescription = "#" + Integer.toHexString(localAccentColor.toInt()), buttons = { isShown -> - ManagerThemedTextButton( - stringId = R.string.dialog_button_save, + ManagerSaveButton( backgroundColor = Color(localAccentColor) ) { isShown.value = false diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/settings/ClearFilesItem.kt b/app/src/main/java/com/vanced/manager/ui/widgets/settings/ClearFilesItem.kt new file mode 100644 index 0000000000..0c1163e849 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/settings/ClearFilesItem.kt @@ -0,0 +1,17 @@ +package com.vanced.manager.ui.widgets.settings + +import androidx.compose.runtime.Composable +import com.vanced.manager.R +import com.vanced.manager.ui.components.preference.Preference +import com.vanced.manager.ui.resources.managerString + +@Composable +fun SettingsClearFilesItem() { + Preference( + preferenceTitle = managerString( + stringId = R.string.settings_preference_clear_files_title + ), + preferenceDescription = null, + onClick = {} + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/settings/CustomTabsItem.kt b/app/src/main/java/com/vanced/manager/ui/widgets/settings/CustomTabsItem.kt new file mode 100644 index 0000000000..1408bbf1c5 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/settings/CustomTabsItem.kt @@ -0,0 +1,16 @@ +package com.vanced.manager.ui.widgets.settings + +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import com.vanced.manager.R +import com.vanced.manager.ui.components.preference.CheckboxPreference +import com.vanced.manager.ui.preferences.holder.useCustomTabsPref + +@Composable +fun SettingsCustomTabsItem() { + CheckboxPreference( + preferenceTitle = stringResource(id = R.string.settings_preference_use_custom_tabs_title), + preferenceDescription = stringResource(id = R.string.settings_preference_use_custom_tabs_summary), + preference = useCustomTabsPref + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/settings/ManagerVariantItem.kt b/app/src/main/java/com/vanced/manager/ui/widgets/settings/ManagerVariantItem.kt new file mode 100644 index 0000000000..a37e86f824 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/settings/ManagerVariantItem.kt @@ -0,0 +1,28 @@ +package com.vanced.manager.ui.widgets.settings + +import androidx.compose.runtime.Composable +import com.vanced.manager.R +import com.vanced.manager.ui.components.preference.RadiobuttonDialogPreference +import com.vanced.manager.ui.preferences.RadioButtonPreference +import com.vanced.manager.ui.preferences.holder.managerVariantPref +import com.vanced.manager.ui.resources.managerString + +@Composable +fun SettingsManagerVariantItem() { + RadiobuttonDialogPreference( + preferenceTitle = managerString( + stringId = R.string.settings_preference_variant_title + ), + preference = managerVariantPref, + buttons = listOf( + RadioButtonPreference( + title = "nonroot", + key = "nonroot" + ), + RadioButtonPreference( + title = "root", + key = "root" + ), + ) + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/settings/NotificationsItem.kt b/app/src/main/java/com/vanced/manager/ui/widgets/settings/NotificationsItem.kt new file mode 100644 index 0000000000..5391a6fa0d --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widgets/settings/NotificationsItem.kt @@ -0,0 +1,22 @@ +package com.vanced.manager.ui.widgets.settings + +import androidx.compose.runtime.Composable +import com.vanced.manager.ui.components.preference.CheckboxPreference +import com.vanced.manager.ui.preferences.managerBooleanPreference +import com.vanced.manager.util.notificationApps + +@Composable +fun SettingsNotificationsItem() { + notificationApps.forEach { + with(it) { + CheckboxPreference( + preferenceTitle = "$app Push Notifications", + preferenceDescription = "Receive push notifications when an update for $app is released", + preference = managerBooleanPreference( + key = "${prefKey}_notifications", + defaultValue = true + ) + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/settings/ThemeItem.kt b/app/src/main/java/com/vanced/manager/ui/widgets/settings/ThemeItem.kt index 3ede43286d..da5a58a971 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/settings/ThemeItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/settings/ThemeItem.kt @@ -5,25 +5,41 @@ import com.vanced.manager.R import com.vanced.manager.ui.components.preference.RadiobuttonDialogPreference import com.vanced.manager.ui.preferences.RadioButtonPreference import com.vanced.manager.ui.preferences.holder.managerThemePref +import com.vanced.manager.ui.resources.managerString @Composable fun ThemeSettingsItem() { + val lightTheme = managerString(stringId = R.string.settings_preference_theme_light) + val darkTheme = managerString(stringId = R.string.settings_preference_theme_dark) + val sysDefTheme = managerString(stringId = R.string.settings_option_system_default) + + val lightKey = "Light" + val darkKey = "Dark" + val sysDefKey = "System Default" + RadiobuttonDialogPreference( - preferenceTitle = R.string.settings_preference_theme_title, + preferenceTitle = managerString(stringId = R.string.settings_preference_theme_title), preference = managerThemePref, buttons = listOf( RadioButtonPreference( - title = "Light Theme", - key = "Light" + title = lightTheme, + key = lightKey ), RadioButtonPreference( - title = "Dark Theme", - key = "Dark" + title = darkTheme, + key = darkKey ), RadioButtonPreference( - title = "System Default", - key = "System Default" + title = sysDefTheme, + key = sysDefKey ) - ) + ), + preferenceDescriptionConverter = { + when (it) { + lightKey -> lightTheme + darkKey -> darkTheme + else -> sysDefTheme + } + } ) } diff --git a/app/src/main/java/com/vanced/manager/util/AppNotifications.kt b/app/src/main/java/com/vanced/manager/util/AppNotifications.kt new file mode 100644 index 0000000000..c3737f2910 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/util/AppNotifications.kt @@ -0,0 +1,21 @@ +package com.vanced.manager.util + +import com.vanced.manager.domain.model.NotificationPrefModel +import com.vanced.manager.network.util.MICROG_NAME +import com.vanced.manager.network.util.MUSIC_NAME +import com.vanced.manager.network.util.VANCED_NAME + +val notificationApps = arrayOf( + NotificationPrefModel( + app = VANCED_NAME, + prefKey = "vanced" + ), + NotificationPrefModel( + app = MUSIC_NAME, + prefKey = "music" + ), + NotificationPrefModel( + app = MICROG_NAME, + prefKey = "microg" + ) +) \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 924686fd58..38a4d1c2f6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -23,7 +23,7 @@ <!-- Settings Page--> <string name="settings_category_appearance">Appearance</string> - <string name="settings_category_behaviour">Behavior</string> + <string name="settings_category_behaviour">Behaviour</string> <string name="settings_option_system_default">System Default</string> <string name="settings_preference_accent_color_title">Accent Color</string> <string name="settings_preference_clear_files_title">Clear downloaded files</string> From 30f45b9b1bfd3a9038a76677ae439659b40e997d Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 27 Jun 2021 19:57:47 +0400 Subject: [PATCH 016/118] fixed sponsor links --- .../main/java/com/vanced/manager/network/util/Constants.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/network/util/Constants.kt b/app/src/main/java/com/vanced/manager/network/util/Constants.kt index 8837825e0d..7e791feb3e 100644 --- a/app/src/main/java/com/vanced/manager/network/util/Constants.kt +++ b/app/src/main/java/com/vanced/manager/network/util/Constants.kt @@ -7,8 +7,8 @@ const val VANCED_NAME = "YouTube Vanced" const val MUSIC_NAME = "YouTube Vanced Music" const val MICROG_NAME = "Vanced microG" -const val BRAVE = "" -const val ADGUARD = "" +const val BRAVE = "https://vancedapp.com/brave" +const val ADGUARD = "https://adguard.com/?aid=31141&source=manager" const val INSTAGRAM = "https://instagram.com/vanced.youtube" const val YOUTUBE = "https://youtube.com/c/YouTubeVanced" From 896a32adde4ce67a847c52c36273a983047c603f Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 28 Jun 2021 11:50:24 +0400 Subject: [PATCH 017/118] Fixed installation options --- .../components/layout/ManagerButtonColumn.kt | 20 ++++++ .../widgets/home/apps/card/AppActionCard.kt | 4 +- .../ui/widgets/home/apps/card/AppCard.kt | 66 ++++++++++++------- 3 files changed, 65 insertions(+), 25 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/ui/components/layout/ManagerButtonColumn.kt diff --git a/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerButtonColumn.kt b/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerButtonColumn.kt new file mode 100644 index 0000000000..b59739bdb1 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerButtonColumn.kt @@ -0,0 +1,20 @@ +package com.vanced.manager.ui.components.layout + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.vanced.manager.ui.utils.defaultContentPaddingVertical + +@Composable +fun ManagerButtonColumn( + modifier: Modifier = Modifier, + content: @Composable ColumnScope.() -> Unit +) { + Column( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(defaultContentPaddingVertical), + content = content + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt index 203c67ab23..0f62cb0c32 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt @@ -28,7 +28,9 @@ fun AppActionCard( hasInstallationOptions: Boolean ) { Row( - modifier = Modifier.padding(horizontal = defaultContentPaddingHorizontal, vertical = 12.dp), + modifier = Modifier.padding( + horizontal = defaultContentPaddingHorizontal + ), verticalAlignment = Alignment.CenterVertically ) { Column( diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt index 0e8cea4840..08ae6b8076 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt @@ -4,14 +4,19 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import com.google.accompanist.glide.rememberGlidePainter import com.vanced.manager.domain.model.App -import com.vanced.manager.ui.components.button.ManagerThemedButton import com.vanced.manager.ui.components.card.ManagerThemedCard +import com.vanced.manager.ui.components.layout.ManagerButtonColumn +import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal +import com.vanced.manager.ui.utils.defaultContentPaddingVertical +import com.vanced.manager.ui.widgets.button.ManagerCancelButton +import com.vanced.manager.ui.widgets.button.ManagerDownloadButton import com.vanced.manager.ui.widgets.home.apps.dialog.AppChangelogDialog import com.vanced.manager.ui.widgets.home.apps.dialog.AppDownloadDialog @@ -30,33 +35,46 @@ fun AppCard( ) val hasInstallationOption = app.installationOptions != null - ManagerThemedCard { - Column { - AppInfoCard( - appName = app.name ?: "", - icon = icon, - fetching = fetching - ) - AppActionCard( - appInstalledVersion = app.installedVersion, - appRemoteVersion = app.remoteVersion, - showDownloadDialog = showDownloadDialog, - showAppInfo = showAppInfo, - showInstallationOptions = showInstallationOptions, - hasInstallationOptions = hasInstallationOption - ) - if (hasInstallationOption) { - AnimatedVisibility( - modifier = Modifier.fillMaxWidth(), - visible = showInstallationOptions.value + Column { + ManagerThemedCard { + Column { + AppInfoCard( + appName = app.name ?: "", + icon = icon, + fetching = fetching + ) + Column( + modifier = Modifier.padding(vertical = defaultContentPaddingVertical) ) { + AppActionCard( + appInstalledVersion = app.installedVersion, + appRemoteVersion = app.remoteVersion, + showDownloadDialog = showDownloadDialog, + showAppInfo = showAppInfo, + showInstallationOptions = showInstallationOptions, + hasInstallationOptions = hasInstallationOption + ) + } + } + } + if (hasInstallationOption) { + AnimatedVisibility( + modifier = Modifier.fillMaxWidth(), + visible = showInstallationOptions.value + ) { + Column { app.installationOptions?.forEach { it.item() } - ManagerThemedButton(onClick = { - showDownloadDialog.value = true - }) { - + ManagerButtonColumn( + modifier = Modifier.padding(horizontal = defaultContentPaddingHorizontal) + ) { + ManagerDownloadButton { + showDownloadDialog.value = true + } + ManagerCancelButton { + showInstallationOptions.value = false + } } } } From 822778f7e9d29fb8e1956e55d181ad3104c4095f Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 28 Jun 2021 12:10:19 +0400 Subject: [PATCH 018/118] installation option layout adjustments --- .../components/modifier/ManagerClickable.kt | 27 +++++++++++++++++++ .../ManagerPlaceholder.kt | 2 +- .../ui/components/preference/Preference.kt | 3 ++- .../ui/widgets/home/apps/card/AppCard.kt | 21 +++++++++++---- .../ui/widgets/home/apps/card/AppInfoCard.kt | 2 +- 5 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/ui/components/modifier/ManagerClickable.kt rename app/src/main/java/com/vanced/manager/ui/components/{placeholder => modifier}/ManagerPlaceholder.kt (89%) diff --git a/app/src/main/java/com/vanced/manager/ui/components/modifier/ManagerClickable.kt b/app/src/main/java/com/vanced/manager/ui/components/modifier/ManagerClickable.kt new file mode 100644 index 0000000000..e4ccbc7e78 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/modifier/ManagerClickable.kt @@ -0,0 +1,27 @@ +package com.vanced.manager.ui.components.modifier + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.material.MaterialTheme +import androidx.compose.material.ripple.rememberRipple +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.composed +import androidx.compose.ui.draw.clip + +fun Modifier.managerClickable( + onClick: () -> Unit +) = composed { + val ripple = rememberRipple() + val interactionSource = remember { MutableInteractionSource() } + + return@composed then( + clip(MaterialTheme.shapes.medium) + ).then( + clickable( + interactionSource = interactionSource, + onClick = onClick, + indication = ripple + ) + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/placeholder/ManagerPlaceholder.kt b/app/src/main/java/com/vanced/manager/ui/components/modifier/ManagerPlaceholder.kt similarity index 89% rename from app/src/main/java/com/vanced/manager/ui/components/placeholder/ManagerPlaceholder.kt rename to app/src/main/java/com/vanced/manager/ui/components/modifier/ManagerPlaceholder.kt index 93f47a3bfc..b15e229b3e 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/placeholder/ManagerPlaceholder.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/modifier/ManagerPlaceholder.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.placeholder +package com.vanced.manager.ui.components.modifier import androidx.compose.ui.Modifier import androidx.compose.ui.composed diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/Preference.kt b/app/src/main/java/com/vanced/manager/ui/components/preference/Preference.kt index f50aecbfa6..d0f298f719 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/preference/Preference.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/preference/Preference.kt @@ -10,6 +10,7 @@ import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier import com.vanced.manager.ui.components.color.managerAnimatedColor import com.vanced.manager.ui.components.list.ManagerListItem +import com.vanced.manager.ui.components.modifier.managerClickable import com.vanced.manager.ui.components.text.ManagerText import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal @@ -40,7 +41,7 @@ fun Preference( val color = managerAnimatedColor(color = MaterialTheme.colors.onSurface) ManagerListItem( modifier = Modifier - .clickable(onClick = onClick) + .managerClickable(onClick = onClick) .padding(horizontal = defaultContentPaddingHorizontal), title = { CompositionLocalProvider( diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt index 08ae6b8076..ffc013aa85 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt @@ -1,7 +1,7 @@ package com.vanced.manager.ui.widgets.home.apps.card -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.* +import androidx.compose.animation.core.tween import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding @@ -9,6 +9,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp import com.google.accompanist.glide.rememberGlidePainter import com.vanced.manager.domain.model.App import com.vanced.manager.ui.components.card.ManagerThemedCard @@ -60,14 +61,24 @@ fun AppCard( if (hasInstallationOption) { AnimatedVisibility( modifier = Modifier.fillMaxWidth(), - visible = showInstallationOptions.value + visible = showInstallationOptions.value, + enter = expandVertically( + animationSpec = tween(400) + ), + exit = shrinkVertically( + animationSpec = tween(400) + ) ) { - Column { + Column( + modifier = Modifier.padding(vertical = 4.dp) + ) { app.installationOptions?.forEach { it.item() } ManagerButtonColumn( - modifier = Modifier.padding(horizontal = defaultContentPaddingHorizontal) + modifier = Modifier + .padding(horizontal = defaultContentPaddingHorizontal) + .padding(top = defaultContentPaddingVertical) ) { ManagerDownloadButton { showDownloadDialog.value = true diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppInfoCard.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppInfoCard.kt index eb757ae559..1a5cdbf962 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppInfoCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppInfoCard.kt @@ -11,7 +11,7 @@ import com.google.accompanist.imageloading.ImageLoadState import com.google.accompanist.imageloading.LoadPainter import com.vanced.manager.ui.components.card.ManagerCard import com.vanced.manager.ui.components.list.ManagerListItem -import com.vanced.manager.ui.components.placeholder.managerPlaceholder +import com.vanced.manager.ui.components.modifier.managerPlaceholder import com.vanced.manager.ui.components.text.ManagerText import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal From bc69bd4a9dfe74db48e555cfcee20bf23cd6a20f Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 28 Jun 2021 16:22:12 +0400 Subject: [PATCH 019/118] more refactor --- .../manager/network/model/AppDtoMapper.kt | 3 +- .../com/vanced/manager/ui/MainActivity.kt | 2 +- .../components/button/ManagerThemedButton.kt | 1 - .../button/ManagerThemedTextButton.kt | 3 - .../ui/components/card/ManagerItemCard.kt | 2 - .../ui/components/checkbox/ManagerCheckbox.kt | 3 - .../components/color/ColorContentProvider.kt | 3 - .../ui/components/color/ColorPicker.kt | 4 -- .../ui/components/color/ManagerColors.kt | 1 - .../ui/components/list/CheckboxItem.kt | 2 - .../ui/components/list/RadiobuttonItem.kt | 2 - .../components/preference/DialogPreference.kt | 1 - .../ui/components/preference/Preference.kt | 1 - .../ManagerProgressIndicator.kt | 22 +++++++ .../ui/components/text/CategoryTitleText.kt | 1 - .../vanced/manager/ui/layouts/AboutLayout.kt | 2 +- .../vanced/manager/ui/layouts/LogLayout.kt | 7 +- .../manager/ui/layouts/SettingsLayout.kt | 3 +- .../java/com/vanced/manager/ui/theme/Color.kt | 2 - .../widgets/home/apps/card/AppActionCard.kt | 43 +++++++----- .../ui/widgets/home/apps/card/AppCard.kt | 65 ++++++++++++------- .../home/apps/dialog/AppChangelogDialog.kt | 31 ++++----- .../home/apps/dialog/AppDownloadDialog.kt | 50 +++++--------- .../home/download/AppDownloadDialogButtons.kt | 18 ----- .../download/AppDownloadDialogProgress.kt | 48 +++++++------- .../CheckboxInstallationOption.kt | 2 +- .../ui/widgets/layout/CategoryLayout.kt | 2 +- .../ui/widgets/settings/AccentColorItem.kt | 2 +- 28 files changed, 152 insertions(+), 174 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/ui/components/progressindicator/ManagerProgressIndicator.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogButtons.kt diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt index ec65d012c8..059900041f 100644 --- a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt +++ b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt @@ -12,7 +12,8 @@ import com.vanced.manager.downloader.impl.VancedDownloader import com.vanced.manager.network.util.MICROG_NAME import com.vanced.manager.network.util.MUSIC_NAME import com.vanced.manager.network.util.VANCED_NAME -import com.vanced.manager.ui.preferences.* +import com.vanced.manager.ui.preferences.CheckboxPreference +import com.vanced.manager.ui.preferences.RadioButtonPreference import com.vanced.manager.ui.preferences.holder.musicVersionPref import com.vanced.manager.ui.preferences.holder.vancedLanguagesPref import com.vanced.manager.ui.preferences.holder.vancedThemePref diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index b7f5a41115..e6b0c47b8b 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -23,11 +23,11 @@ import com.vanced.manager.ui.components.color.managerAnimatedColor import com.vanced.manager.ui.components.color.managerSurfaceColor import com.vanced.manager.ui.components.color.managerTextColor import com.vanced.manager.ui.components.menu.ManagerDropdownMenuItem +import com.vanced.manager.ui.components.text.ToolbarTitleText import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.screens.Screen import com.vanced.manager.ui.theme.ManagerTheme import com.vanced.manager.ui.theme.isDark -import com.vanced.manager.ui.components.text.ToolbarTitleText class MainActivity : AppCompatActivity() { diff --git a/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedButton.kt b/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedButton.kt index fb2bea852f..4894d3c146 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedButton.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedButton.kt @@ -11,7 +11,6 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.luminance import androidx.compose.ui.unit.dp import com.vanced.manager.ui.components.color.managerAccentColor -import com.vanced.manager.ui.preferences.holder.managerAccentColorPref @Composable fun ManagerThemedButton( diff --git a/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedTextButton.kt b/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedTextButton.kt index 4c9a220b3d..d2524b2564 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedTextButton.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedTextButton.kt @@ -1,13 +1,10 @@ package com.vanced.manager.ui.components.button -import androidx.annotation.StringRes -import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import com.vanced.manager.ui.components.color.managerAccentColor import com.vanced.manager.ui.components.text.ManagerText -import com.vanced.manager.ui.preferences.holder.managerAccentColorPref @Composable fun ManagerThemedTextButton( diff --git a/app/src/main/java/com/vanced/manager/ui/components/card/ManagerItemCard.kt b/app/src/main/java/com/vanced/manager/ui/components/card/ManagerItemCard.kt index 93d96b846f..ed6ae8976b 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/card/ManagerItemCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/card/ManagerItemCard.kt @@ -10,14 +10,12 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.vanced.manager.ui.components.color.ThemedItemContentColorProvider import com.vanced.manager.ui.components.color.managerAccentColor -import com.vanced.manager.ui.preferences.holder.managerAccentColorPref private val cardModifier = Modifier.sizeIn( minHeight = 95.dp, diff --git a/app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt b/app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt index 60d758c598..43d1b68941 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt @@ -7,21 +7,18 @@ import androidx.compose.animation.core.updateTransition import androidx.compose.foundation.layout.requiredSize import androidx.compose.foundation.layout.size import androidx.compose.material.Icon -import androidx.compose.material.MaterialTheme import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.Close import androidx.compose.material.icons.rounded.Done import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import com.vanced.manager.ui.components.card.ManagerCard import com.vanced.manager.ui.components.color.contentColorForColor import com.vanced.manager.ui.components.color.managerAccentColor import com.vanced.manager.ui.components.color.managerAnimatedColor import com.vanced.manager.ui.components.color.managerThemedCardColor -import com.vanced.manager.ui.preferences.holder.managerAccentColorPref @SuppressLint("UnusedTransitionTargetStateParameter") @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/components/color/ColorContentProvider.kt b/app/src/main/java/com/vanced/manager/ui/components/color/ColorContentProvider.kt index 857913836c..2b7022cc56 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/color/ColorContentProvider.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/color/ColorContentProvider.kt @@ -1,11 +1,8 @@ package com.vanced.manager.ui.components.color import androidx.compose.material.LocalContentColor -import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.ui.graphics.Color -import com.vanced.manager.ui.preferences.holder.managerAccentColorPref @Composable fun ThemedItemContentColorProvider( diff --git a/app/src/main/java/com/vanced/manager/ui/components/color/ColorPicker.kt b/app/src/main/java/com/vanced/manager/ui/components/color/ColorPicker.kt index 268097c04a..2eb04d9001 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/color/ColorPicker.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/color/ColorPicker.kt @@ -2,17 +2,13 @@ package com.vanced.manager.ui.components.color import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.wrapContentHeight -import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import com.skydoves.colorpickerview.ColorEnvelope import com.skydoves.orchestra.colorpicker.ColorPicker -import com.vanced.manager.ui.preferences.holder.managerAccentColorPref @Composable fun ManagerColorPicker( diff --git a/app/src/main/java/com/vanced/manager/ui/components/color/ManagerColors.kt b/app/src/main/java/com/vanced/manager/ui/components/color/ManagerColors.kt index 4a38e1d503..cbaa460763 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/color/ManagerColors.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/color/ManagerColors.kt @@ -4,7 +4,6 @@ import androidx.compose.animation.animateColorAsState import androidx.compose.animation.core.tween import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.luminance import com.vanced.manager.ui.preferences.holder.managerAccentColorPref diff --git a/app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt b/app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt index 6312715e3c..19d238d125 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt @@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material.Checkbox import androidx.compose.material.CheckboxDefaults -import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -16,7 +15,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.vanced.manager.ui.components.color.managerAccentColor import com.vanced.manager.ui.components.color.managerTextColor -import com.vanced.manager.ui.preferences.holder.managerAccentColorPref @Composable fun CheckboxItem( diff --git a/app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt b/app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt index 8db2b0e350..f8246bcd74 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt @@ -4,7 +4,6 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.material.MaterialTheme import androidx.compose.material.RadioButton import androidx.compose.material.RadioButtonDefaults import androidx.compose.material.Text @@ -16,7 +15,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.vanced.manager.ui.components.color.managerAccentColor import com.vanced.manager.ui.components.color.managerTextColor -import com.vanced.manager.ui.preferences.holder.managerAccentColorPref @Composable fun <T> RadiobuttonItem( diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/DialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/components/preference/DialogPreference.kt index 873b8ecc35..c9c2502110 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/preference/DialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/preference/DialogPreference.kt @@ -1,6 +1,5 @@ package com.vanced.manager.ui.components.preference -import androidx.annotation.StringRes import androidx.compose.foundation.layout.ColumnScope import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/Preference.kt b/app/src/main/java/com/vanced/manager/ui/components/preference/Preference.kt index d0f298f719..4d3e84e920 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/preference/Preference.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/preference/Preference.kt @@ -1,6 +1,5 @@ package com.vanced.manager.ui.components.preference -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.padding import androidx.compose.material.LocalContentColor import androidx.compose.material.LocalTextStyle diff --git a/app/src/main/java/com/vanced/manager/ui/components/progressindicator/ManagerProgressIndicator.kt b/app/src/main/java/com/vanced/manager/ui/components/progressindicator/ManagerProgressIndicator.kt new file mode 100644 index 0000000000..f6c80a2ac7 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/progressindicator/ManagerProgressIndicator.kt @@ -0,0 +1,22 @@ +package com.vanced.manager.ui.components.progressindicator + +import androidx.compose.material.LinearProgressIndicator +import androidx.compose.runtime.Composable +import com.vanced.manager.ui.components.color.managerAccentColor + +@Composable +fun ManagerProgressIndicator() { + LinearProgressIndicator( + color = managerAccentColor() + ) +} + +@Composable +fun ManagerProgressIndicator( + progress: Float +) { + LinearProgressIndicator( + color = managerAccentColor(), + progress = progress + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/text/CategoryTitleText.kt b/app/src/main/java/com/vanced/manager/ui/components/text/CategoryTitleText.kt index 43d17a7316..e5c7710b24 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/text/CategoryTitleText.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/text/CategoryTitleText.kt @@ -1,6 +1,5 @@ package com.vanced.manager.ui.components.text -import androidx.annotation.StringRes import androidx.compose.foundation.layout.padding import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/AboutLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/AboutLayout.kt index 4b55d8f975..ac3a27bae4 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/AboutLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/layouts/AboutLayout.kt @@ -21,9 +21,9 @@ import com.vanced.manager.ui.components.card.ManagerLinkCard import com.vanced.manager.ui.components.card.ManagerThemedCard import com.vanced.manager.ui.components.layout.ManagerScrollableColumn import com.vanced.manager.ui.components.layout.ScrollableItemRow -import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.components.list.ManagerListItem import com.vanced.manager.ui.components.text.ManagerText +import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.widgets.layout.CategoryLayout data class Person( diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt index 81189fee3a..fbb8483aa6 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt @@ -2,16 +2,17 @@ package com.vanced.manager.ui.layouts import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.lazy.items -import androidx.compose.material.* +import androidx.compose.material.FloatingActionButton +import androidx.compose.material.Icon +import androidx.compose.material.Scaffold +import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Share import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import com.vanced.manager.ui.components.color.managerAccentColor import com.vanced.manager.ui.components.color.managerSurfaceColor import com.vanced.manager.ui.components.layout.ManagerLazyColumn -import com.vanced.manager.ui.preferences.holder.managerAccentColorPref import com.vanced.manager.util.logs @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt index 43b6456d4b..b2c8a3fd16 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt @@ -1,7 +1,6 @@ package com.vanced.manager.ui.layouts -import androidx.compose.runtime.* -import androidx.compose.ui.res.stringResource +import androidx.compose.runtime.Composable import androidx.compose.ui.unit.dp import com.vanced.manager.R import com.vanced.manager.ui.components.layout.ManagerScrollableColumn diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Color.kt b/app/src/main/java/com/vanced/manager/ui/theme/Color.kt index 3bb279fc4a..8df8e3748e 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Color.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Color.kt @@ -1,8 +1,6 @@ package com.vanced.manager.ui.theme import androidx.compose.ui.graphics.Color -import com.vanced.manager.ui.components.color.managerAccentColor -import com.vanced.manager.ui.preferences.holder.managerAccentColorPref val primaryColor = Color(defAccentColor) val primaryColorVariant = primaryColor.copy(alpha = 0.25f) diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt index 0f62cb0c32..73278eec74 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt @@ -7,25 +7,24 @@ import androidx.compose.material.icons.rounded.DeleteForever import androidx.compose.material.icons.rounded.Download import androidx.compose.material.icons.rounded.Launch import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.vanced.manager.R import com.vanced.manager.ui.components.button.IconButton +import com.vanced.manager.ui.components.text.AppVersionText import com.vanced.manager.ui.components.text.ManagerText import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal -import com.vanced.manager.ui.components.text.AppVersionText @Composable fun AppActionCard( appRemoteVersion: String?, appInstalledVersion: String?, - showDownloadDialog: MutableState<Boolean>, - showAppInfo: MutableState<Boolean>, - showInstallationOptions: MutableState<Boolean>, - hasInstallationOptions: Boolean + onInfoClick: () -> Unit, + onUninstallClick: () -> Unit, + onLaunchClick: () -> Unit, + onDownloadClick: () -> Unit, ) { Row( modifier = Modifier.padding( @@ -65,18 +64,26 @@ fun AppActionCard( .padding(start = 4.dp) .wrapContentWidth(Alignment.End) ) { - IconButton(icon = Icons.Outlined.Info, contentDescription = "App Info") { - showAppInfo.value = true - } - IconButton(icon = Icons.Rounded.DeleteForever, contentDescription = "Uninstall") {} - IconButton(icon = Icons.Rounded.Launch, contentDescription = "Launch") {} - IconButton(icon = Icons.Rounded.Download, contentDescription = "Install") { - if (hasInstallationOptions) { - showInstallationOptions.value = true - } else { - showDownloadDialog.value = true - } - } + IconButton( + icon = Icons.Outlined.Info, + contentDescription = "App Info", + onClick = onInfoClick + ) + IconButton( + icon = Icons.Rounded.DeleteForever, + contentDescription = "Uninstall", + onClick = onUninstallClick + ) + IconButton( + icon = Icons.Rounded.Launch, + contentDescription = "Launch", + onClick = onLaunchClick + ) + IconButton( + icon = Icons.Rounded.Download, + contentDescription = "Install", + onClick = onDownloadClick + ) } } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt index ffc013aa85..334dc1a8cc 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt @@ -1,14 +1,16 @@ package com.vanced.manager.ui.widgets.home.apps.card -import androidx.compose.animation.* +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.core.tween +import androidx.compose.animation.expandVertically +import androidx.compose.animation.shrinkVertically import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember +import androidx.compose.runtime.* import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp import com.google.accompanist.glide.rememberGlidePainter import com.vanced.manager.domain.model.App @@ -27,14 +29,21 @@ fun AppCard( app: App, fetching: Boolean ) { - val showDownloadDialog = remember { mutableStateOf(false) } - val showAppInfo = remember { mutableStateOf(false) } - val showInstallationOptions = remember { mutableStateOf(false) } + var showDownloadDialog by remember { mutableStateOf(false) } + var showAppInfoDialog by remember { mutableStateOf(false) } + var showInstallationOptions by remember { mutableStateOf(false) } + val icon = rememberGlidePainter( request = app.iconUrl ?: "", fadeIn = true ) - val hasInstallationOption = app.installationOptions != null + + val hasInstallationOptions = app.installationOptions != null + val animationSpec = tween<IntSize>(400) + + fun download() { + + } Column { ManagerThemedCard { @@ -50,23 +59,31 @@ fun AppCard( AppActionCard( appInstalledVersion = app.installedVersion, appRemoteVersion = app.remoteVersion, - showDownloadDialog = showDownloadDialog, - showAppInfo = showAppInfo, - showInstallationOptions = showInstallationOptions, - hasInstallationOptions = hasInstallationOption + onDownloadClick = { + if (hasInstallationOptions) { + showInstallationOptions = true + } else { + showDownloadDialog = true + } + }, + onInfoClick = { + showAppInfoDialog = true + }, + onLaunchClick = {}, + onUninstallClick = {} ) } } } - if (hasInstallationOption) { + if (hasInstallationOptions) { AnimatedVisibility( modifier = Modifier.fillMaxWidth(), - visible = showInstallationOptions.value, + visible = showInstallationOptions, enter = expandVertically( - animationSpec = tween(400) + animationSpec = animationSpec ), exit = shrinkVertically( - animationSpec = tween(400) + animationSpec = animationSpec ) ) { Column( @@ -81,10 +98,10 @@ fun AppCard( .padding(top = defaultContentPaddingVertical) ) { ManagerDownloadButton { - showDownloadDialog.value = true + showDownloadDialog = true } ManagerCancelButton { - showInstallationOptions.value = false + showInstallationOptions = false } } } @@ -92,19 +109,23 @@ fun AppCard( } } - if (app.name != null && app.downloader != null) { + if (app.name != null && app.downloader != null && showDownloadDialog) { AppDownloadDialog( app = app.name, downloader = app.downloader, - showDialog = showDownloadDialog + onCancelClick = { + showDownloadDialog = false + } ) } - if (app.name != null && app.changelog != null) { + if (app.name != null && app.changelog != null && showAppInfoDialog) { AppChangelogDialog( appName = app.name, changelog = app.changelog, - showDialog = showAppInfo + onDismissRequest = { + showAppInfoDialog = false + } ) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppChangelogDialog.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppChangelogDialog.kt index 845a61b9ad..fff490475c 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppChangelogDialog.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppChangelogDialog.kt @@ -3,36 +3,31 @@ package com.vanced.manager.ui.widgets.home.apps.dialog import androidx.compose.foundation.layout.padding import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.vanced.manager.R import com.vanced.manager.ui.components.dialog.ManagerDialog -import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.components.text.ManagerText +import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.widgets.button.ManagerCloseButton @Composable fun AppChangelogDialog( appName: String, changelog: String, - showDialog: MutableState<Boolean> + onDismissRequest: () -> Unit, ) { - if (showDialog.value) { - ManagerDialog( - title = managerString(R.string.app_info_title, appName), - onDismissRequest = { showDialog.value = false }, - buttons = { - ManagerCloseButton { - showDialog.value = false - } - } - ) { - ManagerText( - modifier = Modifier.padding(top = 4.dp), - text = changelog, - textStyle = MaterialTheme.typography.subtitle1 - ) + ManagerDialog( + title = managerString(R.string.app_info_title, appName), + onDismissRequest = onDismissRequest, + buttons = { + ManagerCloseButton(onClick = onDismissRequest) } + ) { + ManagerText( + modifier = Modifier.padding(top = 4.dp), + text = changelog, + textStyle = MaterialTheme.typography.subtitle1 + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppDownloadDialog.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppDownloadDialog.kt index 905e9f91e9..e0913a6ea7 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppDownloadDialog.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppDownloadDialog.kt @@ -1,53 +1,33 @@ package com.vanced.manager.ui.widgets.home.apps.dialog -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import com.vanced.manager.downloader.base.BaseDownloader import com.vanced.manager.ui.components.dialog.ManagerDialog -import com.vanced.manager.ui.widgets.home.download.AppDownloadDialogButtons +import com.vanced.manager.ui.widgets.button.ManagerCancelButton import com.vanced.manager.ui.widgets.home.download.AppDownloadDialogProgress -import kotlinx.coroutines.launch @Composable fun AppDownloadDialog( app: String, downloader: BaseDownloader, - showDialog: MutableState<Boolean> + onCancelClick: () -> Unit, ) { - val coroutineScope = rememberCoroutineScope() - val rememberProgress = remember { downloader.downloadProgress } val rememberFile = remember { downloader.downloadFile } val rememberInstalling = remember { downloader.installing } - val showProgress = remember { mutableStateOf(false) } - - if (showDialog.value) { - ManagerDialog( - title = app, - onDismissRequest = { showDialog.value = false }, - buttons = { - AppDownloadDialogButtons( - showProgress = showProgress, - onDownloadClick = { - coroutineScope.launch { - showProgress.value = true - downloader.download() - } - }, - onCancelClick = { - downloader.cancelDownload() - showDialog.value = false - showProgress.value = false - } - ) - } - ) { - AppDownloadDialogProgress( - progress = rememberProgress, - file = rememberFile, - showProgress = showProgress.value, - installing = rememberInstalling - ) + ManagerDialog( + title = app, + onDismissRequest = {}, + buttons = { + ManagerCancelButton(onClick = onCancelClick) } + ) { + AppDownloadDialogProgress( + progress = rememberProgress, + file = rememberFile, + installing = rememberInstalling + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogButtons.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogButtons.kt deleted file mode 100644 index 35aa46eeeb..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogButtons.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.vanced.manager.ui.widgets.home.download - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState -import com.vanced.manager.ui.widgets.button.ManagerCancelButton -import com.vanced.manager.ui.widgets.button.ManagerDownloadButton - -@Composable -fun AppDownloadDialogButtons( - showProgress: MutableState<Boolean>, - onDownloadClick: () -> Unit, - onCancelClick: () -> Unit, -) { - when (showProgress.value) { - true -> ManagerCancelButton(onClick = onCancelClick) - false -> ManagerDownloadButton(onClick = onDownloadClick) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt index 3e4b17b5d6..06a2087097 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt @@ -2,43 +2,39 @@ package com.vanced.manager.ui.widgets.home.download import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.wrapContentWidth -import androidx.compose.material.LinearProgressIndicator import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import com.vanced.manager.ui.components.color.managerAccentColor -import com.vanced.manager.ui.preferences.holder.managerAccentColorPref +import com.vanced.manager.R +import com.vanced.manager.ui.components.progressindicator.ManagerProgressIndicator +import com.vanced.manager.ui.resources.managerString @Composable fun AppDownloadDialogProgress( progress: Float, file: String, - showProgress: Boolean, installing: Boolean ) { - if (showProgress) { - when (installing) { - true -> LinearProgressIndicator(color = managerAccentColor()) - false -> LinearProgressIndicator( - progress = progress, - color = managerAccentColor() - ) - } - Row { - Text( - modifier = Modifier - .weight(1f) - .wrapContentWidth(Alignment.Start), - text = "Downloading $file" - ) - Text( - modifier = Modifier - .weight(1f) - .wrapContentWidth(Alignment.End), - text = "$progress" + when (installing) { + true -> ManagerProgressIndicator() + false -> ManagerProgressIndicator(progress = progress) + } + Row { + Text( + modifier = Modifier + .weight(1f) + .wrapContentWidth(Alignment.Start), + text = managerString( + stringId = R.string.app_download_dialog_downloading_file, + file ) - } + ) + Text( + modifier = Modifier + .weight(1f) + .wrapContentWidth(Alignment.End), + text = "%$progress" + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/CheckboxInstallationOption.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/CheckboxInstallationOption.kt index c299784192..34b8ec1f60 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/CheckboxInstallationOption.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/CheckboxInstallationOption.kt @@ -1,10 +1,10 @@ package com.vanced.manager.ui.widgets.home.installation import androidx.annotation.StringRes -import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.components.preference.CheckboxDialogPreference import com.vanced.manager.ui.preferences.CheckboxPreference import com.vanced.manager.ui.preferences.ManagerPreference +import com.vanced.manager.ui.resources.managerString data class CheckboxInstallationOption( @StringRes val titleId: Int, diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/layout/CategoryLayout.kt b/app/src/main/java/com/vanced/manager/ui/widgets/layout/CategoryLayout.kt index b6ed6aaef8..e0fbb7ed39 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/layout/CategoryLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/layout/CategoryLayout.kt @@ -4,9 +4,9 @@ import androidx.compose.foundation.layout.* import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.Dp +import com.vanced.manager.ui.components.text.CategoryTitleText import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal import com.vanced.manager.ui.utils.defaultContentPaddingVertical -import com.vanced.manager.ui.components.text.CategoryTitleText @Composable fun CategoryLayout( diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/settings/AccentColorItem.kt b/app/src/main/java/com/vanced/manager/ui/widgets/settings/AccentColorItem.kt index 8dfc334339..c0706d1ecd 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/settings/AccentColorItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/settings/AccentColorItem.kt @@ -5,8 +5,8 @@ import androidx.compose.ui.graphics.Color import com.vanced.manager.R import com.vanced.manager.ui.components.color.ManagerColorPicker import com.vanced.manager.ui.components.preference.DialogPreference -import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.preferences.holder.managerAccentColorPref +import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.widgets.button.ManagerSaveButton @Composable From 3a0cbc6174e54e4a5dd19cc3b6008329c9c9d146 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 28 Jun 2021 16:35:47 +0400 Subject: [PATCH 020/118] dialog adjustments --- .../manager/network/model/AppDtoMapper.kt | 9 +++--- .../preference/CheckboxDialogPreference.kt | 7 +++-- .../preference/RadiobuttonDialogPreference.kt | 3 +- .../manager/ui/widgets/settings/ThemeItem.kt | 29 +++++-------------- 4 files changed, 18 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt index 059900041f..5a68803ea5 100644 --- a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt +++ b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt @@ -21,6 +21,7 @@ import com.vanced.manager.ui.preferences.holder.vancedVersionPref import com.vanced.manager.ui.widgets.home.installation.CheckboxInstallationOption import com.vanced.manager.ui.widgets.home.installation.InstallationOption import com.vanced.manager.ui.widgets.home.installation.RadiobuttonInstallationOption +import java.util.* class AppDtoMapper( private val packageInformationDataSource: PackageInformationDataSource, @@ -81,10 +82,10 @@ class AppDtoMapper( RadiobuttonInstallationOption( titleId = R.string.app_installation_options_theme, preference = vancedThemePref, - buttons = app.versions?.map { + buttons = app.versions?.map { version -> RadioButtonPreference( - title = it, - key = it + title = version.replaceFirstChar { it.titlecase(Locale.getDefault()) }, + key = version ) } ?: emptyList() ), @@ -103,7 +104,7 @@ class AppDtoMapper( preference = vancedLanguagesPref, buttons = app.versions?.map { CheckboxPreference( - title = it, + title = Locale(it).displayName, key = it ) } ?: emptyList() diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxDialogPreference.kt index 1158c8dca1..cdd82b7fbe 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxDialogPreference.kt @@ -19,7 +19,6 @@ import kotlinx.coroutines.launch @Composable fun CheckboxDialogPreference( preferenceTitle: String, - preferenceDescriptionConverter: (values: List<String>) -> String = { it.joinToString(separator = ", ") }, preference: ManagerPreference<Set<String>>, trailing: @Composable () -> Unit = {}, buttons: List<CheckboxPreference>, @@ -30,7 +29,11 @@ fun CheckboxDialogPreference( val coroutineScope = rememberCoroutineScope() DialogPreference( preferenceTitle = preferenceTitle, - preferenceDescription = preferenceDescriptionConverter(selectedButtons), + preferenceDescription = buttons.filter { button -> + selectedButtons.any { selectedButton -> + button.key == selectedButton + } + }.joinToString(separator = ", ") { it.title }, trailing = trailing, buttons = { isShown -> ManagerThemedTextButton( diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt index 8b9bc858e8..c38ff0cdc9 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt @@ -15,7 +15,6 @@ import kotlinx.coroutines.launch @Composable fun RadiobuttonDialogPreference( preferenceTitle: String, - preferenceDescriptionConverter: (value: String) -> String = { it }, preference: ManagerPreference<String>, trailing: @Composable () -> Unit = {}, buttons: List<RadioButtonPreference>, @@ -25,7 +24,7 @@ fun RadiobuttonDialogPreference( var currentSelection by remember { mutableStateOf(preference.value.value) } DialogPreference( preferenceTitle = preferenceTitle, - preferenceDescription = preferenceDescriptionConverter(currentSelection), + preferenceDescription = buttons.find { it.key == currentSelection }?.title, trailing = trailing, buttons = { isShown -> ManagerSaveButton { diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/settings/ThemeItem.kt b/app/src/main/java/com/vanced/manager/ui/widgets/settings/ThemeItem.kt index da5a58a971..d0dccda88d 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/settings/ThemeItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/settings/ThemeItem.kt @@ -9,37 +9,22 @@ import com.vanced.manager.ui.resources.managerString @Composable fun ThemeSettingsItem() { - val lightTheme = managerString(stringId = R.string.settings_preference_theme_light) - val darkTheme = managerString(stringId = R.string.settings_preference_theme_dark) - val sysDefTheme = managerString(stringId = R.string.settings_option_system_default) - - val lightKey = "Light" - val darkKey = "Dark" - val sysDefKey = "System Default" - RadiobuttonDialogPreference( preferenceTitle = managerString(stringId = R.string.settings_preference_theme_title), preference = managerThemePref, buttons = listOf( RadioButtonPreference( - title = lightTheme, - key = lightKey + title = managerString(stringId = R.string.settings_preference_theme_light), + key = "Light" ), RadioButtonPreference( - title = darkTheme, - key = darkKey + title = managerString(stringId = R.string.settings_preference_theme_dark), + key = "Dark" ), RadioButtonPreference( - title = sysDefTheme, - key = sysDefKey + title = managerString(stringId = R.string.settings_option_system_default), + key = "System Default" ) - ), - preferenceDescriptionConverter = { - when (it) { - lightKey -> lightTheme - darkKey -> darkTheme - else -> sysDefTheme - } - } + ) ) } From 3b179f690cf43fafa67c3407c7a69f478f753215 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 28 Jun 2021 17:08:41 +0400 Subject: [PATCH 021/118] fixed installation options --- .../main/java/com/vanced/manager/network/model/AppDto.kt | 8 ++++---- .../java/com/vanced/manager/network/model/AppDtoMapper.kt | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDto.kt b/app/src/main/java/com/vanced/manager/network/model/AppDto.kt index 0487ce328f..bb6b00c143 100644 --- a/app/src/main/java/com/vanced/manager/network/model/AppDto.kt +++ b/app/src/main/java/com/vanced/manager/network/model/AppDto.kt @@ -6,12 +6,12 @@ data class AppDto( @SerializedName("name") val name: String? = null, @SerializedName("version") val version: String? = null, @SerializedName("versionCode") val versionCode: Int? = null, - @SerializedName("changelog") val changelog: String? = null, + @SerializedName("versions") val versions: List<String>? = null, + @SerializedName("themes") val themes: List<String>? = null, + @SerializedName("langs") val languages: List<String>? = null, @SerializedName("package_name") val packageName: String? = null, @SerializedName("package_name_root") val packageNameRoot: String? = null, + @SerializedName("changelog") val changelog: String? = null, @SerializedName("icon_url") val iconUrl: String? = null, @SerializedName("url") val url: String? = null, - @SerializedName("versions") val versions: List<String>? = null, - @SerializedName("themes") val themes: List<String>? = null, - @SerializedName("languages") val languages: List<String>? = null ) diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt index 5a68803ea5..b3b7e7fca8 100644 --- a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt +++ b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt @@ -82,7 +82,7 @@ class AppDtoMapper( RadiobuttonInstallationOption( titleId = R.string.app_installation_options_theme, preference = vancedThemePref, - buttons = app.versions?.map { version -> + buttons = app.themes?.map { version -> RadioButtonPreference( title = version.replaceFirstChar { it.titlecase(Locale.getDefault()) }, key = version @@ -102,7 +102,7 @@ class AppDtoMapper( CheckboxInstallationOption( titleId = R.string.app_installation_options_language, preference = vancedLanguagesPref, - buttons = app.versions?.map { + buttons = app.languages?.map { CheckboxPreference( title = Locale(it).displayName, key = it From 6b447788e0c06e18bb4a3c60af9cd6b10a603e91 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 28 Jun 2021 17:50:23 +0400 Subject: [PATCH 022/118] migrated to custom checkbox and radiobutton --- .../components/animation/SpringAnimation.kt | 26 ++++++++++++++ .../ui/components/checkbox/ManagerCheckbox.kt | 31 ++++------------ .../ui/components/list/CheckboxItem.kt | 36 ++++++++----------- .../ui/components/list/RadiobuttonItem.kt | 27 +++++++------- .../preference/CheckboxDialogPreference.kt | 6 ++-- .../preference/CheckboxPreference.kt | 4 ++- .../preference/RadiobuttonDialogPreference.kt | 2 +- .../radiobutton/ManagerRadiobutton.kt | 33 +++++++++++++++++ 8 files changed, 100 insertions(+), 65 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/ui/components/animation/SpringAnimation.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/components/radiobutton/ManagerRadiobutton.kt diff --git a/app/src/main/java/com/vanced/manager/ui/components/animation/SpringAnimation.kt b/app/src/main/java/com/vanced/manager/ui/components/animation/SpringAnimation.kt new file mode 100644 index 0000000000..1b43cd5cb5 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/animation/SpringAnimation.kt @@ -0,0 +1,26 @@ +package com.vanced.manager.ui.components.animation + +import android.annotation.SuppressLint +import androidx.compose.animation.core.Transition +import androidx.compose.animation.core.animateDp +import androidx.compose.animation.core.keyframes +import androidx.compose.runtime.Composable +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp + +@SuppressLint("UnusedTransitionTargetStateParameter") +@Composable +fun <T> Transition<T>.springAnimation( + initialValue: Dp, + label: String +) = animateDp( + transitionSpec = { + keyframes { + durationMillis = 250 + initialValue - 8.dp at 50 + initialValue + 8.dp at 150 + initialValue at 250 + } + }, + label = label +) { initialValue } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt b/app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt index 43d1b68941..e6baa83d70 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt @@ -1,8 +1,6 @@ package com.vanced.manager.ui.components.checkbox import android.annotation.SuppressLint -import androidx.compose.animation.core.animateDp -import androidx.compose.animation.core.keyframes import androidx.compose.animation.core.updateTransition import androidx.compose.foundation.layout.requiredSize import androidx.compose.foundation.layout.size @@ -13,7 +11,8 @@ import androidx.compose.material.icons.rounded.Done import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.Dp +import com.vanced.manager.ui.components.animation.springAnimation import com.vanced.manager.ui.components.card.ManagerCard import com.vanced.manager.ui.components.color.contentColorForColor import com.vanced.manager.ui.components.color.managerAccentColor @@ -23,33 +22,15 @@ import com.vanced.manager.ui.components.color.managerThemedCardColor @SuppressLint("UnusedTransitionTargetStateParameter") @Composable fun ManagerCheckbox( + size: Dp, isChecked: Boolean, onCheckedChange: (isChecked: Boolean) -> Unit ) { val accentColor = managerAccentColor() + val iconInitialSize = size / 1.6f val transition = updateTransition(targetState = isChecked, label = "Checked") - val cardSize by transition.animateDp( - transitionSpec = { - keyframes { - durationMillis = 250 - 32.dp at 50 - 48.dp at 150 - 40.dp at 250 - } - }, - label = "Checkbox size" - ) { 40.dp } - val iconSize by transition.animateDp( - transitionSpec = { - keyframes { - durationMillis = 250 - 18.dp at 50 - 30.dp at 150 - 24.dp at 250 - } - }, - label = "Icon size" - ) { 24.dp } + val cardSize by transition.springAnimation(initialValue = size, label = "Checkbox Size") + val iconSize by transition.springAnimation(initialValue = iconInitialSize, label = "Icon size") val cardColor = managerAnimatedColor(if (isChecked) accentColor else managerThemedCardColor()) val iconTint = managerAnimatedColor(if (isChecked) contentColorForColor(cardColor) else accentColor) diff --git a/app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt b/app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt index 19d238d125..f18e67e277 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt @@ -1,20 +1,15 @@ package com.vanced.manager.ui.components.list -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.material.Checkbox -import androidx.compose.material.CheckboxDefaults +import androidx.compose.foundation.layout.* import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.vanced.manager.ui.components.color.managerAccentColor +import com.vanced.manager.ui.components.checkbox.ManagerCheckbox import com.vanced.manager.ui.components.color.managerTextColor +import com.vanced.manager.ui.components.modifier.managerClickable @Composable fun CheckboxItem( @@ -22,27 +17,26 @@ fun CheckboxItem( isChecked: Boolean, onCheck: (Boolean) -> Unit = {} ) { - fun toggle() { - onCheck(isChecked) - } + val toggle = { onCheck(!isChecked) } Row( modifier = Modifier .fillMaxWidth() - .clickable { toggle() } + .managerClickable(onClick = toggle) .padding(horizontal = 8.dp, vertical = 6.dp), verticalAlignment = Alignment.CenterVertically ) { - Checkbox( - checked = isChecked, - onCheckedChange = { + Box( + modifier = Modifier.size(30.dp), + contentAlignment = Alignment.Center + ) { + ManagerCheckbox( + size = 24.dp, + isChecked = isChecked + ) { toggle() - }, - colors = CheckboxDefaults.colors( - checkedColor = managerAccentColor(), - uncheckedColor = Color.LightGray - ) - ) + } + } Text( modifier = Modifier.padding(start = 12.dp), text = text, diff --git a/app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt b/app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt index f8246bcd74..9e96c68728 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt @@ -1,26 +1,21 @@ package com.vanced.manager.ui.components.list import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.material.RadioButton -import androidx.compose.material.RadioButtonDefaults +import androidx.compose.foundation.layout.* import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.vanced.manager.ui.components.color.managerAccentColor import com.vanced.manager.ui.components.color.managerTextColor +import com.vanced.manager.ui.components.radiobutton.ManagerRadiobutton @Composable fun <T> RadiobuttonItem( text: String, tag: T, - selected: Boolean, + isSelected: Boolean, onSelect: (tag: T) -> Unit ) { val onClick = { @@ -34,14 +29,16 @@ fun <T> RadiobuttonItem( .padding(horizontal = 8.dp, vertical = 6.dp), verticalAlignment = Alignment.CenterVertically ) { - RadioButton( - selected = selected, - onClick = onClick, - colors = RadioButtonDefaults.colors( - selectedColor = managerAccentColor(), - unselectedColor = Color.LightGray + Box( + modifier = Modifier.size(30.dp), + contentAlignment = Alignment.Center + ) { + ManagerRadiobutton( + size = 24.dp, + isSelected = isSelected, + onClick = onClick ) - ) + } Text( modifier = Modifier.padding(start = 12.dp), text = text, diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxDialogPreference.kt index cdd82b7fbe..f78a07d7c5 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxDialogPreference.kt @@ -1,6 +1,7 @@ package com.vanced.manager.ui.components.preference import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.runtime.Composable @@ -9,6 +10,7 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.toMutableStateList import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp import com.vanced.manager.R import com.vanced.manager.ui.components.button.ManagerThemedTextButton import com.vanced.manager.ui.components.list.CheckboxItem @@ -33,7 +35,7 @@ fun CheckboxDialogPreference( selectedButtons.any { selectedButton -> button.key == selectedButton } - }.joinToString(separator = ", ") { it.title }, + }.sortedBy { it.title }.joinToString(separator = ", ") { it.title }, trailing = trailing, buttons = { isShown -> ManagerThemedTextButton( @@ -50,7 +52,7 @@ fun CheckboxDialogPreference( } ) { LazyColumn( - modifier = Modifier + modifier = Modifier.heightIn(max = 400.dp) ) { items(buttons) { button -> val (title, key) = button diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxPreference.kt b/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxPreference.kt index 2537692f77..8770319bbb 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxPreference.kt @@ -2,6 +2,7 @@ package com.vanced.manager.ui.components.preference import androidx.compose.runtime.Composable import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.unit.dp import com.vanced.manager.ui.components.checkbox.ManagerCheckbox import com.vanced.manager.ui.preferences.ManagerPreference import kotlinx.coroutines.launch @@ -29,7 +30,8 @@ fun CheckboxPreference( trailing = { ManagerCheckbox( isChecked = isChecked, - onCheckedChange = { onClick() } + onCheckedChange = { onClick() }, + size = 40.dp ) } ) diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt index c38ff0cdc9..b87fc2beba 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt @@ -44,7 +44,7 @@ fun RadiobuttonDialogPreference( RadiobuttonItem( text = title, tag = key, - selected = currentSelection == key, + isSelected = currentSelection == key, onSelect = { currentSelection = it } diff --git a/app/src/main/java/com/vanced/manager/ui/components/radiobutton/ManagerRadiobutton.kt b/app/src/main/java/com/vanced/manager/ui/components/radiobutton/ManagerRadiobutton.kt new file mode 100644 index 0000000000..e55b2753b0 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/components/radiobutton/ManagerRadiobutton.kt @@ -0,0 +1,33 @@ +package com.vanced.manager.ui.components.radiobutton + +import android.annotation.SuppressLint +import androidx.compose.animation.core.updateTransition +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.Dp +import com.vanced.manager.ui.components.animation.springAnimation +import com.vanced.manager.ui.components.card.ManagerCard +import com.vanced.manager.ui.components.color.managerAccentColor +import com.vanced.manager.ui.components.color.managerAnimatedColor +import com.vanced.manager.ui.components.color.managerThemedCardColor + +@SuppressLint("UnusedTransitionTargetStateParameter") +@Composable +fun ManagerRadiobutton( + size: Dp, + isSelected: Boolean, + onClick: () -> Unit +) { + val accentColor = managerAccentColor() + val transition = updateTransition(targetState = isSelected, label = "Selected") + val cardSize by transition.springAnimation(initialValue = size, label = "Radiobutton Size") + val cardColor = managerAnimatedColor(if (isSelected) accentColor else managerThemedCardColor()) + ManagerCard( + modifier = Modifier.size(cardSize), + onClick = onClick, + backgroundColor = cardColor, + content = {} + ) +} \ No newline at end of file From b76b67414eb871cd4a5e366e7e22cbd0fb90d3f7 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 28 Jun 2021 18:44:19 +0400 Subject: [PATCH 023/118] text improvements --- .../manager/ui/components/dialog/ManagerDialog.kt | 11 +++++------ .../vanced/manager/ui/components/text/ManagerText.kt | 5 ++++- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/components/dialog/ManagerDialog.kt b/app/src/main/java/com/vanced/manager/ui/components/dialog/ManagerDialog.kt index a39fd0de94..06ace4057e 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/dialog/ManagerDialog.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/dialog/ManagerDialog.kt @@ -1,13 +1,10 @@ package com.vanced.manager.ui.components.dialog -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.* import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import com.vanced.manager.ui.components.card.ManagerCard @@ -24,8 +21,10 @@ fun ManagerDialog( ManagerDialog( title = { ManagerText( - modifier = Modifier.align(Alignment.CenterHorizontally), + modifier = Modifier + .fillMaxWidth(), textStyle = MaterialTheme.typography.h2, + textAlign = TextAlign.Center, text = title ) }, diff --git a/app/src/main/java/com/vanced/manager/ui/components/text/ManagerText.kt b/app/src/main/java/com/vanced/manager/ui/components/text/ManagerText.kt index 7b6255813e..79df124033 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/text/ManagerText.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/text/ManagerText.kt @@ -6,18 +6,21 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.style.TextAlign @Composable fun ManagerText( modifier: Modifier = Modifier, color: Color = Color.Unspecified, textStyle: TextStyle = LocalTextStyle.current, + textAlign: TextAlign? = null, text: String, ) { Text( modifier = modifier, text = text, color = color, - style = textStyle + style = textStyle, + textAlign = textAlign ) } \ No newline at end of file From aa3234a83c25ff4294a830276e6d941840c85d83 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 28 Jun 2021 19:22:55 +0400 Subject: [PATCH 024/118] progressbar adjustments --- .../ManagerProgressIndicator.kt | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/vanced/manager/ui/components/progressindicator/ManagerProgressIndicator.kt b/app/src/main/java/com/vanced/manager/ui/components/progressindicator/ManagerProgressIndicator.kt index f6c80a2ac7..667168377f 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/progressindicator/ManagerProgressIndicator.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/progressindicator/ManagerProgressIndicator.kt @@ -1,12 +1,30 @@ package com.vanced.manager.ui.components.progressindicator +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.LinearProgressIndicator +import androidx.compose.material.MaterialTheme +import androidx.compose.material.ProgressIndicatorDefaults import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.composed +import androidx.compose.ui.draw.clip import com.vanced.manager.ui.components.color.managerAccentColor +private val progressBarModifier = Modifier.composed { + then( + fillMaxWidth() + ).then( + clip(MaterialTheme.shapes.medium) + ) +} + + @Composable fun ManagerProgressIndicator() { LinearProgressIndicator( + modifier = progressBarModifier, color = managerAccentColor() ) } @@ -15,8 +33,13 @@ fun ManagerProgressIndicator() { fun ManagerProgressIndicator( progress: Float ) { + val animatedProgress by animateFloatAsState( + targetValue = progress, + animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec + ) LinearProgressIndicator( + modifier = progressBarModifier, color = managerAccentColor(), - progress = progress + progress = animatedProgress ) } \ No newline at end of file From 493b6d3963b1ea2ed7a521c64dc8aa839c49c321 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 28 Jun 2021 19:28:36 +0400 Subject: [PATCH 025/118] T H I C C progressbar --- .../components/progressindicator/ManagerProgressIndicator.kt | 5 ++++- .../ui/widgets/home/download/AppDownloadDialogProgress.kt | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/components/progressindicator/ManagerProgressIndicator.kt b/app/src/main/java/com/vanced/manager/ui/components/progressindicator/ManagerProgressIndicator.kt index 667168377f..f3a492c6dd 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/progressindicator/ManagerProgressIndicator.kt +++ b/app/src/main/java/com/vanced/manager/ui/components/progressindicator/ManagerProgressIndicator.kt @@ -2,6 +2,7 @@ package com.vanced.manager.ui.components.progressindicator import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.material.LinearProgressIndicator import androidx.compose.material.MaterialTheme import androidx.compose.material.ProgressIndicatorDefaults @@ -10,17 +11,19 @@ import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.composed import androidx.compose.ui.draw.clip +import androidx.compose.ui.unit.dp import com.vanced.manager.ui.components.color.managerAccentColor private val progressBarModifier = Modifier.composed { then( + height(5.dp) + ).then( fillMaxWidth() ).then( clip(MaterialTheme.shapes.medium) ) } - @Composable fun ManagerProgressIndicator() { LinearProgressIndicator( diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt index 06a2087097..1d59576014 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt @@ -1,9 +1,11 @@ package com.vanced.manager.ui.widgets.home.download +import androidx.compose.animation.core.animateIntAsState import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.wrapContentWidth 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 com.vanced.manager.R @@ -20,6 +22,7 @@ fun AppDownloadDialogProgress( true -> ManagerProgressIndicator() false -> ManagerProgressIndicator(progress = progress) } + val animatedProgress by animateIntAsState(targetValue = progress.toInt()) Row { Text( modifier = Modifier @@ -34,7 +37,7 @@ fun AppDownloadDialogProgress( modifier = Modifier .weight(1f) .wrapContentWidth(Alignment.End), - text = "%$progress" + text = "%$animatedProgress" ) } } \ No newline at end of file From 0a50882412dcd71c7f40f68e2dc824a01a388292 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 12 Jul 2021 18:00:23 +0400 Subject: [PATCH 026/118] installer adjustments --- app/build.gradle.kts | 2 +- app/src/main/AndroidManifest.xml | 14 ++ .../com/vanced/manager/ManagerApplication.kt | 1 + .../com/vanced/manager/di/DownloaderModule.kt | 20 ++- .../com/vanced/manager/di/InstallerModuke.kt | 20 ++- .../com/vanced/manager/di/MapperModule.kt | 6 +- .../com/vanced/manager/domain/model/App.kt | 4 +- .../manager/downloader/api/VancedAPI.kt | 2 +- .../manager/downloader/base/AppDownloader.kt | 167 ++++++++++++++++++ .../manager/downloader/base/BaseDownloader.kt | 106 ----------- .../downloader/impl/MicrogDownloader.kt | 10 +- .../downloader/impl/MusicDownloader.kt | 10 +- .../downloader/impl/VancedDownloader.kt | 158 +++++++++++------ .../vanced/manager/installer/AppInstaller.kt | 34 ---- .../manager/installer/MicrogInstaller.kt | 26 +++ .../manager/installer/MusicInstaller.kt | 24 +++ .../manager/installer/VancedInstaller.kt | 26 +++ .../manager/installer/base/AppInstaller.kt | 36 ++++ .../manager/network/model/AppDtoMapper.kt | 17 +- .../vanced/manager/ui/layouts/HomeLayout.kt | 2 +- .../holder/PreferenceDefaultValueHolder.kt | 2 +- .../manager/ui/widgets/home/apps/AppsItem.kt | 5 +- .../ui/widgets/home/apps/card/AppCard.kt | 40 +++-- .../ui/widgets/home/apps/card/AppInfoCard.kt | 7 +- .../home/apps/dialog/AppDownloadDialog.kt | 15 +- .../download/AppDownloadDialogProgress.kt | 8 +- .../main/java/com/vanced/manager/util/Arch.kt | 9 + 27 files changed, 492 insertions(+), 279 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/downloader/base/AppDownloader.kt delete mode 100644 app/src/main/java/com/vanced/manager/downloader/base/BaseDownloader.kt delete mode 100644 app/src/main/java/com/vanced/manager/installer/AppInstaller.kt create mode 100644 app/src/main/java/com/vanced/manager/installer/MicrogInstaller.kt create mode 100644 app/src/main/java/com/vanced/manager/installer/MusicInstaller.kt create mode 100644 app/src/main/java/com/vanced/manager/installer/VancedInstaller.kt create mode 100644 app/src/main/java/com/vanced/manager/installer/base/AppInstaller.kt create mode 100644 app/src/main/java/com/vanced/manager/util/Arch.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index cd0e62f81e..e85ee124fb 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -120,7 +120,7 @@ dependencies { implementation("com.squareup.retrofit2:retrofit:$retrofitVersion") implementation("com.squareup.retrofit2:converter-gson:$retrofitVersion") - implementation("com.github.x1nto:apkhelper:1.1.0") + implementation("com.github.x1nto:apkhelper:1.1.2") testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.2") diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d65962c97e..e40a04468d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,6 +3,18 @@ package="com.vanced.manager"> <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" /> + <uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" /> + + <queries> + <package android:name="com.vanced.android.youtube" /> + <package android:name="com.google.android.youtube" /> + <package android:name="com.vanced.android.apps.youtube.music" /> + <package android:name="com.google.android.apps.youtube.music" /> + <package android:name="com.mgoogle.android.gms" /> + <package android:name="com.vanced.faq" /> + <package android:name="com.android.vending" /> + </queries> <application android:name=".ManagerApplication" @@ -29,6 +41,8 @@ android:theme="@style/Theme.MaterialComponents.NoActionBar" android:label="@string/app_name"/> + <service android:name="com.xinto.apkhelper.services.PackageManagerService" /> + </application> </manifest> \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ManagerApplication.kt b/app/src/main/java/com/vanced/manager/ManagerApplication.kt index 3568efa821..eb39aee21f 100644 --- a/app/src/main/java/com/vanced/manager/ManagerApplication.kt +++ b/app/src/main/java/com/vanced/manager/ManagerApplication.kt @@ -16,6 +16,7 @@ class ManagerApplication : Application() { modules( apiModule, downloaderModule, + installerModule, mapperModule, networkModule, packageManagerModule, diff --git a/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt b/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt index 4b22504e3b..2edefb070e 100644 --- a/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt +++ b/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt @@ -2,16 +2,28 @@ package com.vanced.manager.di import com.vanced.manager.downloader.api.VancedAPI import com.vanced.manager.downloader.impl.VancedDownloader +import com.vanced.manager.installer.VancedInstaller import org.koin.dsl.module val downloaderModule = module { fun provideVancedDownloader( vancedAPI: VancedAPI, - ): VancedDownloader = VancedDownloader(vancedAPI) + vancedInstaller: VancedInstaller + ): VancedDownloader = VancedDownloader(vancedAPI, vancedInstaller) - single { - provideVancedDownloader(get()) - } + fun provideMusicDownloader( + vancedAPI: VancedAPI, + vancedInstaller: VancedInstaller + ): VancedDownloader = VancedDownloader(vancedAPI, vancedInstaller) + + fun provideMicrogDownloader( + vancedAPI: VancedAPI, + vancedInstaller: VancedInstaller + ): VancedDownloader = VancedDownloader(vancedAPI, vancedInstaller) + + single { provideVancedDownloader(get(), get()) } + single { provideMusicDownloader(get(), get()) } + single { provideMicrogDownloader(get(), get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt b/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt index a512419e3c..1c5c899393 100644 --- a/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt +++ b/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt @@ -1,15 +1,19 @@ package com.vanced.manager.di -import android.content.Context -import com.vanced.manager.installer.AppInstaller -import com.vanced.manager.ui.viewmodel.HomeViewModel +import com.vanced.manager.installer.MicrogInstaller +import com.vanced.manager.installer.MusicInstaller +import com.vanced.manager.installer.VancedInstaller import org.koin.dsl.module val installerModule = module { - fun provideAppInstaller( - context: Context, - homeViewModel: HomeViewModel - ) = AppInstaller(context, homeViewModel) - single { provideAppInstaller(get(), get()) } + fun provideVancedInstaller() = VancedInstaller() + + fun provideMusicInstaller() = MusicInstaller() + + fun provideMicrogInstaller() = MicrogInstaller() + + single { provideVancedInstaller() } + single { provideMusicInstaller() } + single { provideMicrogInstaller() } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/MapperModule.kt b/app/src/main/java/com/vanced/manager/di/MapperModule.kt index c1a97ea882..0295702c79 100644 --- a/app/src/main/java/com/vanced/manager/di/MapperModule.kt +++ b/app/src/main/java/com/vanced/manager/di/MapperModule.kt @@ -10,10 +10,8 @@ val mapperModule = module { fun provideAppMapper( packageInformationDataSource: PackageInformationDataSource, - vancedDownloader: VancedDownloader, ): AppDtoMapper = AppDtoMapper( - packageInformationDataSource = packageInformationDataSource, - vancedDownloader = vancedDownloader + packageInformationDataSource = packageInformationDataSource ) fun provideJsonMapper( @@ -22,7 +20,7 @@ val mapperModule = module { appDtoMapper = appDtoMapper ) - single { provideAppMapper(get(), get()) } + single { provideAppMapper(get()) } single { provideJsonMapper(get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/domain/model/App.kt b/app/src/main/java/com/vanced/manager/domain/model/App.kt index 494d4cb4db..4ce076b7f1 100644 --- a/app/src/main/java/com/vanced/manager/domain/model/App.kt +++ b/app/src/main/java/com/vanced/manager/domain/model/App.kt @@ -1,6 +1,6 @@ package com.vanced.manager.domain.model -import com.vanced.manager.downloader.base.BaseDownloader +import com.vanced.manager.downloader.base.AppDownloader import com.vanced.manager.ui.widgets.home.installation.InstallationOption data class App( @@ -21,6 +21,6 @@ data class App( val versions: List<String>? = null, val themes: List<String>? = null, val languages: List<String>? = null, - val downloader: BaseDownloader? = null, + val downloader: AppDownloader? = null, val installationOptions: List<InstallationOption>? = null ) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt b/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt index 939349c29d..73edb3161f 100644 --- a/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt +++ b/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt @@ -8,7 +8,7 @@ import retrofit2.http.Streaming interface VancedAPI { - @GET("apks/{version}/{variant}/{type}/{apkName}.apk") + @GET("apks/v{version}/{variant}/{type}/{apkName}") @Streaming fun getApk( @Path("version") version: String, diff --git a/app/src/main/java/com/vanced/manager/downloader/base/AppDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/base/AppDownloader.kt new file mode 100644 index 0000000000..7e16961ba0 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/downloader/base/AppDownloader.kt @@ -0,0 +1,167 @@ +package com.vanced.manager.downloader.base + +import android.content.Context +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import com.vanced.manager.domain.model.App +import com.vanced.manager.installer.base.AppInstaller +import com.vanced.manager.ui.viewmodel.HomeViewModel +import com.vanced.manager.util.log +import okhttp3.ResponseBody +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject +import retrofit2.Call +import retrofit2.awaitResponse +import java.io.File +import java.io.FileOutputStream +import java.io.IOException + +abstract class AppDownloader( + val appName: String, + val appInstaller: AppInstaller +) : KoinComponent { + + data class File( + val call: Call<ResponseBody>, + val fileName: String + ) + + var downloadProgress by mutableStateOf(0f) + private set + + var downloadFile by mutableStateOf("") + private set + + var installing by mutableStateOf(false) + var error by mutableStateOf(false) + + val showDownloadScreen = mutableStateOf(false) + + private var canceled = false + + private lateinit var call: Call<ResponseBody> + + private val tag = this::class.simpleName!! + + private fun resetValues() { + showDownloadScreen.value = false + downloadProgress = 0f + downloadFile = "" + installing = false + error = false + canceled = false + } + + val context: Context by inject() + + abstract suspend fun download( + app: App, + viewModel: HomeViewModel + ) + + private fun install(viewModel: HomeViewModel) { + installing = true + appInstaller.install { + viewModel.fetch() + resetValues() + } + } + + suspend fun downloadFile( + file: File, + viewModel: HomeViewModel, + folderStructure: String, + onError: (error: String) -> Unit = {}, + ) { + downloadFiles( + files = listOf(file), + viewModel = viewModel, + folderStructure = folderStructure, + onError = onError + ) + } + + suspend fun downloadFiles( + files: List<File>, + viewModel: HomeViewModel, + folderStructure: String, + onError: (error: String) -> Unit = {}, + ) { + showDownloadScreen.value = true + fun error(errorBody: String) { + error = true + onError(errorBody) + log(tag, errorBody) + } + try { + for (file in files) { + if (canceled) { + break + } + + val fileName = file.fileName + downloadFile = fileName + this.call = file.call + val response = call.awaitResponse() + if (response.isSuccessful) { + val body = response.body() + if (body != null) { + if (!writeFile(body, fileName, folderStructure)) { + error("Failed to write file data") + } + } + } else { + val error = response.errorBody()?.toString() + if (error != null) { + error(error) + } + } + } + } catch (e: Exception) { + error(e.stackTraceToString()) + } + + if (canceled) { + resetValues() + return + } + + install(viewModel) + } + + fun cancelDownload() { + canceled = true + call.cancel() + } + + private fun writeFile( + body: ResponseBody, + fileName: String, + folderStructure: String + ): Boolean { + val folder = File("${context.getExternalFilesDir(appName)?.path}/$folderStructure") + folder.mkdirs() + val file = File("${folder.path}/$fileName") + val inputStream = body.byteStream() + val outputStream = FileOutputStream(file) + return try { + val totalBytes = body.contentLength() + val fileReader = ByteArray(4096) + var downloadedBytes = 0L + var read: Int + while (inputStream.read(fileReader).also { read = it } != -1) { + outputStream.write(fileReader, 0, read) + downloadedBytes += read + downloadProgress = (downloadedBytes * 100 / totalBytes).toFloat() + } + true + } catch (e: IOException) { + false + } finally { + inputStream.close() + outputStream.close() + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/base/BaseDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/base/BaseDownloader.kt deleted file mode 100644 index 2454e119bd..0000000000 --- a/app/src/main/java/com/vanced/manager/downloader/base/BaseDownloader.kt +++ /dev/null @@ -1,106 +0,0 @@ -package com.vanced.manager.downloader.base - -import android.content.Context -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import com.vanced.manager.installer.AppInstaller -import com.vanced.manager.util.log -import okhttp3.ResponseBody -import org.koin.core.component.KoinComponent -import org.koin.core.component.inject -import retrofit2.Call -import retrofit2.awaitResponse -import java.io.File -import java.io.FileOutputStream -import java.io.IOException - -abstract class BaseDownloader( - val appName: String -) : KoinComponent { - - var downloadProgress by mutableStateOf(0f) - private set - - var downloadFile by mutableStateOf("") - private set - - var installing by mutableStateOf(false) - - private lateinit var call: Call<ResponseBody> - - private val tag = this::class.simpleName!! - - val context: Context by inject() - val appInstaller: AppInstaller by inject() - - abstract suspend fun download() - - suspend fun downloadFile( - call: Call<ResponseBody>, - folderStructure: String, - fileName: String, - onError: (error: String) -> Unit = {}, - onComplete: suspend () -> Unit = {}, - ) { - fun error(errorBody: String) { - downloadFile = "Error downloading $fileName" - onError(errorBody) - log(tag, errorBody) - } - try { - this.call = call - val response = call.awaitResponse() - if (response.isSuccessful) { - val body = response.body() - if (body != null) { - if (writeFile(body, fileName, folderStructure)) { - onComplete() - } - } - } else { - val error = response.errorBody()?.toString() - if (error != null) { - error(error) - } - } - } catch (e: Exception) { - error(e.stackTraceToString()) - } - downloadProgress = 0f - } - - fun cancelDownload() { - call.cancel() - } - - private fun writeFile( - body: ResponseBody, - fileName: String, - folderStructure: String - ): Boolean { - val file = File("${context.getExternalFilesDir(appName)?.path}/$folderStructure/$fileName") - val inputStream = body.byteStream() - val outputStream = FileOutputStream(file) - return try { - val totalBytes = body.contentLength() - val fileReader = ByteArray(4096) - var downloadedBytes = 0L - var read: Int - while (inputStream.read(fileReader).also { read = it } != -1) { - outputStream.write(fileReader, 0, read) - downloadedBytes += read - downloadProgress = (downloadedBytes * 100 / totalBytes).toFloat() - } - true - } catch (e: IOException) { - false - } finally { - inputStream.close() - outputStream.close() - } - } - - - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt index c0f30e2e56..1a478f5eb1 100644 --- a/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt @@ -1,11 +1,13 @@ package com.vanced.manager.downloader.impl -import com.vanced.manager.downloader.base.BaseDownloader +import com.vanced.manager.domain.model.App +import com.vanced.manager.downloader.base.AppDownloader +import com.vanced.manager.ui.viewmodel.HomeViewModel -object MicrogDownloader : BaseDownloader("") { - - override suspend fun download() { +class MicrogDownloader : AppDownloader("") { + override suspend fun download(app: App, viewModel: HomeViewModel) { + TODO("Not yet implemented") } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt index b2fe2aba34..def60b4d2f 100644 --- a/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt @@ -1,11 +1,13 @@ package com.vanced.manager.downloader.impl -import com.vanced.manager.downloader.base.BaseDownloader +import com.vanced.manager.domain.model.App +import com.vanced.manager.downloader.base.AppDownloader +import com.vanced.manager.ui.viewmodel.HomeViewModel -object MusicDownloader : BaseDownloader("") { - - override suspend fun download() { +class MusicDownloader : AppDownloader("") { + override suspend fun download(app: App, viewModel: HomeViewModel) { + TODO("Not yet implemented") } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt index bb00e24da7..86db664227 100644 --- a/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt @@ -1,73 +1,119 @@ package com.vanced.manager.downloader.impl +import com.vanced.manager.domain.model.App import com.vanced.manager.downloader.api.VancedAPI -import com.vanced.manager.downloader.base.BaseDownloader +import com.vanced.manager.downloader.base.AppDownloader +import com.vanced.manager.installer.VancedInstaller +import com.vanced.manager.ui.preferences.holder.managerVariantPref +import com.vanced.manager.ui.preferences.holder.vancedLanguagesPref +import com.vanced.manager.ui.preferences.holder.vancedThemePref +import com.vanced.manager.ui.preferences.holder.vancedVersionPref +import com.vanced.manager.ui.viewmodel.HomeViewModel +import com.vanced.manager.util.arch +import com.vanced.manager.util.log class VancedDownloader( private val vancedAPI: VancedAPI, -) : BaseDownloader( - appName = "vanced" + vancedInstaller: VancedInstaller +) : AppDownloader( + appName = "vanced", + appInstaller = vancedInstaller ) { - private lateinit var version: String - private lateinit var variant: String + private val theme by vancedThemePref + private val version by vancedVersionPref + private val variant by managerVariantPref + private val languages by vancedLanguagesPref - private lateinit var folderStructure: String - - override suspend fun download() { - version = "v16.16.38" - variant = "nonroot" - folderStructure = "$appName/$version/$variant" - downloadTheme() - } - - private suspend fun downloadTheme() { - downloadVancedApk( - type = "Theme", - apkName = "black.apk" - ) { - downloadArch() - } - } - - private suspend fun downloadArch() { - downloadVancedApk( - type = "Arch", - apkName = "split_config.x86.apk" - ) { - downloadLanguage() - } - } - - private suspend fun downloadLanguage() { - downloadVancedApk( - type = "Language", - apkName = "split_config.en.apk" - ) { - appInstaller.installVanced(version) + override suspend fun download(app: App, viewModel: HomeViewModel) { + val files = listOf( + getFile( + type = "Theme", + apkName = "$theme.apk" + ), + getFile( + type = "Arch", + apkName = "split_config.$arch.apk" + ) + ) + languages.map { language -> + getFile("Language", "split_config.$language.apk") } + downloadFiles( + files = files, + viewModel, + folderStructure = "$version/$variant", + onError = { + log("error", it) + } + ) } - private suspend fun downloadVancedApk( + private fun getFile( type: String, apkName: String, - onDownload: suspend () -> Unit, - ) { - downloadFile( - vancedAPI.getApk( - version = version, - variant = variant, - type = type, - apkName = apkName - ), - folderStructure = folderStructure, - fileName = apkName, - onError = { + ) = File( + call = vancedAPI.getApk( + version = version, + variant = variant, + type = type, + apkName = apkName + ), + fileName = apkName + ) - } - ) { - onDownload() - } - } +// private suspend fun downloadTheme() { +// val theme by vancedThemePref +// downloadVancedApk( +// type = "Theme", +// apkName = "$theme.apk" +// ) { +// downloadArch() +// } +// } +// +// private suspend fun downloadArch() { +// downloadVancedApk( +// type = "Arch", +// apkName = "split_config.x86.apk" +// ) { +// downloadLanguage() +// } +// } +// +// private suspend fun downloadLanguage() { +// val languages by vancedLanguagesPref +// languages.forEach { language -> +// downloadVancedApk( +// type = "Language", +// apkName = "split_config.$language.apk" +// ) {} +// } +// install() +// } +// +// +// +// +// private suspend fun downloadVancedApk( +// type: String, +// apkName: String, +// onDownload: suspend () -> Unit, +// ) { +// downloadFile( +// vancedAPI.getApk( +// version = version, +// variant = variant, +// type = type, +// apkName = apkName +// ), +// folderStructure = "$version/$variant", +// fileName = apkName, +// onError = { +// log("error", it) +// } +// ) { +// onDownload() +// } +// } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/installer/AppInstaller.kt b/app/src/main/java/com/vanced/manager/installer/AppInstaller.kt deleted file mode 100644 index d93f718ed1..0000000000 --- a/app/src/main/java/com/vanced/manager/installer/AppInstaller.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.vanced.manager.installer - -import android.content.Context -import com.vanced.manager.ui.viewmodel.HomeViewModel -import com.xinto.apkhelper.installSplitApks -import com.xinto.apkhelper.statusCallback -import com.xinto.apkhelper.statusCallbackBuilder - -class AppInstaller( - private val context: Context, - private val viewModel: HomeViewModel -) { - - fun installVanced(version: String) { - installSplitApks(context.getExternalFilesDir("vanced/$version")!!.path, context) - } - - fun installMusic() { - - } - - fun installMicrog() { - - } - - init { - statusCallback = statusCallbackBuilder( - onAction = { - viewModel.fetch() - } - ) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/installer/MicrogInstaller.kt b/app/src/main/java/com/vanced/manager/installer/MicrogInstaller.kt new file mode 100644 index 0000000000..21a5ad73f7 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/installer/MicrogInstaller.kt @@ -0,0 +1,26 @@ +package com.vanced.manager.installer + +import androidx.compose.runtime.MutableState +import com.vanced.manager.installer.base.AppInstaller +import com.vanced.manager.ui.preferences.holder.managerVariantPref +import com.vanced.manager.ui.preferences.holder.vancedVersionPref +import com.vanced.manager.ui.viewmodel.HomeViewModel +import com.xinto.apkhelper.installSplitApks + +class MicrogInstaller : AppInstaller() { + + override fun install( + onDone: () -> Unit + ) { + super.install(onDone) + + val version by vancedVersionPref + val variant by managerVariantPref + + installSplitApks( + apksPath = context.getExternalFilesDir("vanced/$version/$variant")!!.path, + context = context + ) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/installer/MusicInstaller.kt b/app/src/main/java/com/vanced/manager/installer/MusicInstaller.kt new file mode 100644 index 0000000000..1264dea5e9 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/installer/MusicInstaller.kt @@ -0,0 +1,24 @@ +package com.vanced.manager.installer + +import com.vanced.manager.installer.base.AppInstaller +import com.vanced.manager.ui.preferences.holder.managerVariantPref +import com.vanced.manager.ui.preferences.holder.vancedVersionPref +import com.xinto.apkhelper.installSplitApks + +class MusicInstaller : AppInstaller() { + + override fun install( + onDone: () -> Unit + ) { + super.install(onDone) + + val version by vancedVersionPref + val variant by managerVariantPref + + installSplitApks( + apksPath = context.getExternalFilesDir("vanced/$version/$variant")!!.path, + context = context + ) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/installer/VancedInstaller.kt b/app/src/main/java/com/vanced/manager/installer/VancedInstaller.kt new file mode 100644 index 0000000000..7217fa3639 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/installer/VancedInstaller.kt @@ -0,0 +1,26 @@ +package com.vanced.manager.installer + +import androidx.compose.runtime.MutableState +import com.vanced.manager.installer.base.AppInstaller +import com.vanced.manager.ui.preferences.holder.managerVariantPref +import com.vanced.manager.ui.preferences.holder.vancedVersionPref +import com.vanced.manager.ui.viewmodel.HomeViewModel +import com.xinto.apkhelper.installSplitApks + +class VancedInstaller : AppInstaller() { + + override fun install( + onDone: () -> Unit + ) { + super.install(onDone) + + val version by vancedVersionPref + val variant by managerVariantPref + + installSplitApks( + apksPath = context.getExternalFilesDir("vanced/$version/$variant")!!.path, + context = context + ) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/installer/base/AppInstaller.kt b/app/src/main/java/com/vanced/manager/installer/base/AppInstaller.kt new file mode 100644 index 0000000000..3c1d2c9cb5 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/installer/base/AppInstaller.kt @@ -0,0 +1,36 @@ +package com.vanced.manager.installer.base + +import android.content.Context +import androidx.annotation.CallSuper +import com.vanced.manager.util.log +import com.xinto.apkhelper.statusCallback +import com.xinto.apkhelper.statusCallbackBuilder +import org.koin.core.component.KoinComponent +import org.koin.core.component.inject + +open class AppInstaller : KoinComponent { + + val context: Context by inject() + + @CallSuper + open fun install( + onDone: () -> Unit + ) { + setStatusCallback(onDone = onDone) + } + + private fun setStatusCallback( + onDone: () -> Unit + ) { + statusCallback = statusCallbackBuilder( + onInstall = { _, _ -> + onDone() + }, + onInstallFailed = { error, _, _ -> + onDone() + log("install", error) + } + ) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt index b3b7e7fca8..8e6e52df19 100644 --- a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt +++ b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt @@ -5,11 +5,6 @@ import com.vanced.manager.domain.datasource.PackageInformationDataSource import com.vanced.manager.domain.model.App import com.vanced.manager.domain.model.AppStatus import com.vanced.manager.domain.util.EntityMapper -import com.vanced.manager.downloader.base.BaseDownloader -import com.vanced.manager.downloader.impl.MicrogDownloader -import com.vanced.manager.downloader.impl.MusicDownloader -import com.vanced.manager.downloader.impl.VancedDownloader -import com.vanced.manager.network.util.MICROG_NAME import com.vanced.manager.network.util.MUSIC_NAME import com.vanced.manager.network.util.VANCED_NAME import com.vanced.manager.ui.preferences.CheckboxPreference @@ -24,8 +19,7 @@ import com.vanced.manager.ui.widgets.home.installation.RadiobuttonInstallationOp import java.util.* class AppDtoMapper( - private val packageInformationDataSource: PackageInformationDataSource, - private val vancedDownloader: VancedDownloader + private val packageInformationDataSource: PackageInformationDataSource ) : EntityMapper<AppDto, App> { override suspend fun mapToModel(entity: AppDto): App = @@ -52,7 +46,6 @@ class AppDtoMapper( versions = versions, themes = themes, languages = languages, - downloader = getDownloader(name), installationOptions = getInstallationOptions(entity) ) } @@ -68,14 +61,6 @@ class AppDtoMapper( AppStatus.Install } - private fun getDownloader(app: String?): BaseDownloader? = - when (app) { - VANCED_NAME -> vancedDownloader - MUSIC_NAME -> MusicDownloader - MICROG_NAME -> MicrogDownloader - else -> null - } - private fun getInstallationOptions(app: AppDto): List<InstallationOption>? = when (app.name) { VANCED_NAME -> listOf( diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt index dd14beab4c..189d5a2cad 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt @@ -38,7 +38,7 @@ fun HomeLayout() { ), contentPaddingHorizontal = 0.dp ) { - HomeAppsItem(viewModel, isFetching) + HomeAppsItem(viewModel) } CategoryLayout( categoryName = managerString( diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceDefaultValueHolder.kt b/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceDefaultValueHolder.kt index 9844a3c33d..2eb280d65e 100644 --- a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceDefaultValueHolder.kt +++ b/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceDefaultValueHolder.kt @@ -4,7 +4,7 @@ const val MANAGER_VARIANT_DEFAULT_VALUE = "nonroot" const val MANAGER_THEME_DEFAULT_VALUE = "System Default" -const val VANCED_THEME_DEFAULT_VALUE = "Dark" +const val VANCED_THEME_DEFAULT_VALUE = "dark" val VANCED_LANGUAGE_DEFAULT_VALUE = setOf("en") const val APP_VERSION_DEFAULT_VALUE = "latest" diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/AppsItem.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/AppsItem.kt index 98a461fac6..3e0f57d4f1 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/AppsItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/AppsItem.kt @@ -13,15 +13,14 @@ import com.vanced.manager.ui.widgets.home.apps.card.AppCard @Composable fun HomeAppsItem( - viewModel: HomeViewModel, - isFetching: Boolean + viewModel: HomeViewModel ) { Column( verticalArrangement = Arrangement.spacedBy(8.dp) ) { viewModel.apps.fastForEach { app -> val observedApp by app.observeAsState(initial = App()) - AppCard(observedApp, isFetching) + AppCard(observedApp, viewModel) } } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt index 334dc1a8cc..417686e184 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt @@ -1,14 +1,12 @@ package com.vanced.manager.ui.widgets.home.apps.card -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.* import androidx.compose.animation.core.tween -import androidx.compose.animation.expandVertically -import androidx.compose.animation.shrinkVertically import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.runtime.* +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp @@ -18,21 +16,25 @@ import com.vanced.manager.ui.components.card.ManagerThemedCard import com.vanced.manager.ui.components.layout.ManagerButtonColumn import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal import com.vanced.manager.ui.utils.defaultContentPaddingVertical +import com.vanced.manager.ui.viewmodel.HomeViewModel import com.vanced.manager.ui.widgets.button.ManagerCancelButton import com.vanced.manager.ui.widgets.button.ManagerDownloadButton import com.vanced.manager.ui.widgets.home.apps.dialog.AppChangelogDialog import com.vanced.manager.ui.widgets.home.apps.dialog.AppDownloadDialog +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch @OptIn(ExperimentalAnimationApi::class) @Composable fun AppCard( app: App, - fetching: Boolean + viewModel: HomeViewModel ) { - var showDownloadDialog by remember { mutableStateOf(false) } - var showAppInfoDialog by remember { mutableStateOf(false) } + var showAppInfoDialog by rememberSaveable { mutableStateOf(false) } var showInstallationOptions by remember { mutableStateOf(false) } + val coroutineScope = rememberCoroutineScope { Dispatchers.IO } + val icon = rememberGlidePainter( request = app.iconUrl ?: "", fadeIn = true @@ -41,17 +43,21 @@ fun AppCard( val hasInstallationOptions = app.installationOptions != null val animationSpec = tween<IntSize>(400) - fun download() { + val downloader = app.downloader + val download: () -> Unit = { + showInstallationOptions = false + coroutineScope.launch { + downloader!!.download(app, viewModel) + } } Column { ManagerThemedCard { Column { AppInfoCard( - appName = app.name ?: "", + appName = app.name, icon = icon, - fetching = fetching ) Column( modifier = Modifier.padding(vertical = defaultContentPaddingVertical) @@ -63,7 +69,7 @@ fun AppCard( if (hasInstallationOptions) { showInstallationOptions = true } else { - showDownloadDialog = true + download() } }, onInfoClick = { @@ -97,9 +103,9 @@ fun AppCard( .padding(horizontal = defaultContentPaddingHorizontal) .padding(top = defaultContentPaddingVertical) ) { - ManagerDownloadButton { - showDownloadDialog = true - } + ManagerDownloadButton( + onClick = download + ) ManagerCancelButton { showInstallationOptions = false } @@ -109,12 +115,12 @@ fun AppCard( } } - if (app.name != null && app.downloader != null && showDownloadDialog) { + if (app.name != null && downloader != null && downloader.showDownloadScreen.value) { AppDownloadDialog( app = app.name, - downloader = app.downloader, + downloader = downloader, onCancelClick = { - showDownloadDialog = false + downloader.cancelDownload() } ) } diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppInfoCard.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppInfoCard.kt index 1a5cdbf962..6dafdb8516 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppInfoCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppInfoCard.kt @@ -17,9 +17,8 @@ import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal @Composable fun AppInfoCard( - appName: String, + appName: String?, icon: LoadPainter<Any>, - fetching: Boolean ) { ManagerCard { ManagerListItem( @@ -29,8 +28,8 @@ fun AppInfoCard( ), title = { ManagerText( - modifier = Modifier.managerPlaceholder(fetching), - text = appName, + modifier = Modifier.managerPlaceholder(appName == null), + text = appName ?: "", textStyle = MaterialTheme.typography.h5 ) }, diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppDownloadDialog.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppDownloadDialog.kt index e0913a6ea7..fca9fdf9d9 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppDownloadDialog.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppDownloadDialog.kt @@ -1,8 +1,7 @@ package com.vanced.manager.ui.widgets.home.apps.dialog import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import com.vanced.manager.downloader.base.BaseDownloader +import com.vanced.manager.downloader.base.AppDownloader import com.vanced.manager.ui.components.dialog.ManagerDialog import com.vanced.manager.ui.widgets.button.ManagerCancelButton import com.vanced.manager.ui.widgets.home.download.AppDownloadDialogProgress @@ -10,13 +9,9 @@ import com.vanced.manager.ui.widgets.home.download.AppDownloadDialogProgress @Composable fun AppDownloadDialog( app: String, - downloader: BaseDownloader, + downloader: AppDownloader, onCancelClick: () -> Unit, ) { - val rememberProgress = remember { downloader.downloadProgress } - val rememberFile = remember { downloader.downloadFile } - val rememberInstalling = remember { downloader.installing } - ManagerDialog( title = app, onDismissRequest = {}, @@ -25,9 +20,9 @@ fun AppDownloadDialog( } ) { AppDownloadDialogProgress( - progress = rememberProgress, - file = rememberFile, - installing = rememberInstalling + progress = downloader.downloadProgress, + file = downloader.downloadFile, + installing = downloader.installing ) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt index 1d59576014..4f968934b9 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt +++ b/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt @@ -2,12 +2,14 @@ package com.vanced.manager.ui.widgets.home.download import androidx.compose.animation.core.animateIntAsState import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentWidth 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.unit.dp import com.vanced.manager.R import com.vanced.manager.ui.components.progressindicator.ManagerProgressIndicator import com.vanced.manager.ui.resources.managerString @@ -20,7 +22,7 @@ fun AppDownloadDialogProgress( ) { when (installing) { true -> ManagerProgressIndicator() - false -> ManagerProgressIndicator(progress = progress) + false -> ManagerProgressIndicator(progress = progress / 100f) } val animatedProgress by animateIntAsState(targetValue = progress.toInt()) Row { @@ -35,9 +37,9 @@ fun AppDownloadDialogProgress( ) Text( modifier = Modifier - .weight(1f) + .padding(start = 4.dp) .wrapContentWidth(Alignment.End), - text = "%$animatedProgress" + text = "$animatedProgress%" ) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/util/Arch.kt b/app/src/main/java/com/vanced/manager/util/Arch.kt new file mode 100644 index 0000000000..5724ba8afc --- /dev/null +++ b/app/src/main/java/com/vanced/manager/util/Arch.kt @@ -0,0 +1,9 @@ +package com.vanced.manager.util + +import android.os.Build + +val arch = when { + Build.SUPPORTED_ABIS.contains("x86") -> "x86" + Build.SUPPORTED_ABIS.contains("arm64-v8a") -> "arm64_v8a" + else -> "armeabi_v7a" +} \ No newline at end of file From 0468882c1c2fd695e9a89bc30b388c73dc31042d Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 12 Jul 2021 18:04:43 +0400 Subject: [PATCH 027/118] updated deps --- app/build.gradle.kts | 12 ++++++------ build.gradle.kts | 2 +- buildSrc/src/main/java/Dependencies.kt | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e85ee124fb..bdcc28ea4d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -85,9 +85,9 @@ val languages: String get() { dependencies { implementation(kotlin("reflect")) - implementation("androidx.core:core-ktx:1.5.0") + implementation("androidx.core:core-ktx:1.6.0") implementation("androidx.appcompat:appcompat:1.3.0") - implementation("com.google.android.material:material:1.3.0") + implementation("com.google.android.material:material:1.4.0") implementation("androidx.browser:browser:1.3.0") implementation("androidx.compose.compiler:compiler:$composeVersion") @@ -103,9 +103,9 @@ dependencies { implementation("androidx.preference:preference-ktx:1.1.1") - implementation("androidx.activity:activity-compose:1.3.0-beta02") + implementation("androidx.activity:activity-compose:1.3.0-rc01") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-alpha02") - implementation("androidx.navigation:navigation-compose:2.4.0-alpha03") + implementation("androidx.navigation:navigation-compose:2.4.0-alpha04") implementation("com.google.accompanist:accompanist-glide:$accompanistVersion") implementation("com.google.accompanist:accompanist-swiperefresh:$accompanistVersion") @@ -123,6 +123,6 @@ dependencies { implementation("com.github.x1nto:apkhelper:1.1.2") testImplementation("junit:junit:4.13.2") - androidTestImplementation("androidx.test.ext:junit:1.1.2") - androidTestImplementation("androidx.test.espresso:espresso-core:3.3.0") + androidTestImplementation("androidx.test.ext:junit:1.1.3") + androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0") } diff --git a/build.gradle.kts b/build.gradle.kts index ac8f89b525..e356cb87ab 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,7 +5,7 @@ buildscript { } dependencies { - classpath("com.android.tools.build:gradle:7.0.0-beta04") + classpath("com.android.tools.build:gradle:7.0.0-beta05") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${Config.kotlinVersion}") } } diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index 8b868f465a..4cf499ad9f 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -1,7 +1,7 @@ object Dependencies { const val accompanistVersion = "0.12.0" - const val composeVersion = "1.0.0-beta09" + const val composeVersion = "1.0.0-rc01" const val koinVersion = "3.1.0" const val retrofitVersion = "2.9.0" const val orchestraVersion = "1.0.7" From 95cc22d522ca2e1551677cf28aa1ae189321f4d8 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 12 Jul 2021 20:22:41 +0400 Subject: [PATCH 028/118] small refactor --- app/src/main/AndroidManifest.xml | 2 +- .../com/vanced/manager/di/DownloaderModule.kt | 20 ++-- .../com/vanced/manager/domain/model/App.kt | 2 +- .../downloader/impl/MicrogDownloader.kt | 8 +- .../downloader/impl/MusicDownloader.kt | 9 +- .../downloader/impl/VancedDownloader.kt | 8 +- .../manager/installer/MicrogInstaller.kt | 6 +- .../manager/installer/MusicInstaller.kt | 4 +- .../manager/installer/VancedInstaller.kt | 6 +- .../manager/network/model/AppDtoMapper.kt | 18 ++-- .../preferences/CheckboxPreference.kt | 2 +- .../{ui => }/preferences/ManagerPreference.kt | 99 ++++++++----------- .../preferences/RadioButtonPreference.kt | 2 +- .../holder/PreferenceDefaultValueHolder.kt | 2 +- .../preferences/holder/PreferenceHolder.kt | 10 +- .../preferences/holder/PreferenceKeyHolder.kt | 2 +- .../com/vanced/manager/ui/MainActivity.kt | 18 ++-- .../manager/{ => ui}/SplashScreenActivity.kt | 3 +- .../animation/SpringAnimation.kt | 2 +- .../button/ManagerIconButton.kt | 2 +- .../button/ManagerThemedButton.kt | 4 +- .../button/ManagerThemedTextButton.kt | 6 +- .../card/ManagerCard.kt | 2 +- .../card/ManagerItemCard.kt | 6 +- .../card/ManagerLinkCard.kt | 4 +- .../card/ManagerThemedCard.kt | 4 +- .../checkbox/ManagerCheckbox.kt | 23 +++-- .../color/ColorContentProvider.kt | 2 +- .../color/ColorPicker.kt | 2 +- .../color/ManagerColors.kt | 19 ++-- .../dialog/ManagerDialog.kt | 8 +- .../layout/ManagerButtonColumn.kt | 4 +- .../layout/ManagerLazyColumn.kt | 2 +- .../layout/ManagerScrollableColumn.kt | 4 +- .../layout/ManagerSurface.kt | 4 +- .../layout/ManagerSwipeRefresh.kt | 4 +- .../layout/ScrollableItemRow.kt | 2 +- .../list/CheckboxItem.kt | 10 +- .../list/ManagerListItem.kt | 2 +- .../list/RadiobuttonItem.kt | 12 +-- .../menu/ManagerDropdownMenuItem.kt | 4 +- .../modifier/ManagerClickable.kt | 2 +- .../modifier/ManagerPlaceholder.kt | 2 +- .../preference/CheckboxDialogPreference.kt | 10 +- .../preference/CheckboxPreference.kt | 6 +- .../preference/DialogPreference.kt | 4 +- .../preference/Preference.kt | 12 +-- .../preference/RadiobuttonDialogPreference.kt | 10 +- .../ManagerProgressIndicator.kt | 4 +- .../radiobutton/ManagerRadiobutton.kt | 16 +-- .../text/AppVersionText.kt | 2 +- .../text/CategoryTitleText.kt | 6 +- .../text/ManagerText.kt | 2 +- .../text/ToolbarTitleText.kt | 4 +- .../ui/{layouts => screens}/AboutLayout.kt | 14 +-- .../ui/{layouts => screens}/HomeLayout.kt | 16 +-- .../ui/{layouts => screens}/LogLayout.kt | 8 +- .../ui/{layouts => screens}/SettingsLayout.kt | 11 +-- .../java/com/vanced/manager/ui/theme/Color.kt | 8 +- .../java/com/vanced/manager/ui/theme/Theme.kt | 5 +- .../manager/ui/{utils => util}/Const.kt | 2 +- .../manager/ui/{screens => util}/Screen.kt | 8 +- .../manager/ui/viewmodel/HomeViewModel.kt | 6 +- .../button/ManagerCancelButton.kt | 4 +- .../button/ManagerCloseButton.kt | 4 +- .../button/ManagerDownloadButton.kt | 4 +- .../button/ManagerSaveButton.kt | 6 +- .../layout/CategoryLayout.kt | 8 +- .../layout/SettingsCategoryLayout.kt | 2 +- .../screens}/home/apps/AppsItem.kt | 4 +- .../screens/home/apps/card/AppActionCard.kt | 94 ++++++++++++++++++ .../screens}/home/apps/card/AppCard.kt | 20 ++-- .../screens}/home/apps/card/AppInfoCard.kt | 12 +-- .../home/apps/dialog/AppChangelogDialog.kt | 8 +- .../home/apps/dialog/AppDownloadDialog.kt | 8 +- .../download/AppDownloadDialogProgress.kt | 4 +- .../CheckboxInstallationOption.kt | 8 +- .../home/installation/InstallationOption.kt | 2 +- .../RadiobuttonInstallationOption.kt | 8 +- .../home/socialmedia/SocialMediaItem.kt | 6 +- .../screens}/home/sponsors/SponsorsItem.kt | 6 +- .../screens}/settings/AccentColorItem.kt | 10 +- .../screens}/settings/ClearFilesItem.kt | 4 +- .../screens}/settings/CustomTabsItem.kt | 6 +- .../screens}/settings/ManagerVariantItem.kt | 8 +- .../screens}/settings/NotificationsItem.kt | 6 +- .../screens}/settings/ThemeItem.kt | 8 +- .../widgets/home/apps/card/AppActionCard.kt | 89 ----------------- 88 files changed, 428 insertions(+), 422 deletions(-) rename app/src/main/java/com/vanced/manager/{ui => }/preferences/CheckboxPreference.kt (65%) rename app/src/main/java/com/vanced/manager/{ui => }/preferences/ManagerPreference.kt (62%) rename app/src/main/java/com/vanced/manager/{ui => }/preferences/RadioButtonPreference.kt (65%) rename app/src/main/java/com/vanced/manager/{ui => }/preferences/holder/PreferenceDefaultValueHolder.kt (85%) rename app/src/main/java/com/vanced/manager/{ui => }/preferences/holder/PreferenceHolder.kt (76%) rename app/src/main/java/com/vanced/manager/{ui => }/preferences/holder/PreferenceKeyHolder.kt (91%) rename app/src/main/java/com/vanced/manager/{ => ui}/SplashScreenActivity.kt (83%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/animation/SpringAnimation.kt (93%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/button/ManagerIconButton.kt (96%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/button/ManagerThemedButton.kt (90%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/button/ManagerThemedTextButton.kt (73%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/card/ManagerCard.kt (96%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/card/ManagerItemCard.kt (91%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/card/ManagerLinkCard.kt (88%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/card/ManagerThemedCard.kt (88%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/checkbox/ManagerCheckbox.kt (70%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/color/ColorContentProvider.kt (94%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/color/ColorPicker.kt (94%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/color/ManagerColors.kt (73%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/dialog/ManagerDialog.kt (86%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/layout/ManagerButtonColumn.kt (82%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/layout/ManagerLazyColumn.kt (92%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/layout/ManagerScrollableColumn.kt (90%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/layout/ManagerSurface.kt (76%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/layout/ManagerSwipeRefresh.kt (86%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/layout/ScrollableItemRow.kt (93%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/list/CheckboxItem.kt (77%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/list/ManagerListItem.kt (97%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/list/RadiobuttonItem.kt (78%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/menu/ManagerDropdownMenuItem.kt (79%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/modifier/ManagerClickable.kt (93%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/modifier/ManagerPlaceholder.kt (90%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/preference/CheckboxDialogPreference.kt (88%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/preference/CheckboxPreference.kt (84%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/preference/DialogPreference.kt (89%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/preference/Preference.kt (83%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/preference/RadiobuttonDialogPreference.kt (84%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/progressindicator/ManagerProgressIndicator.kt (91%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/radiobutton/ManagerRadiobutton.kt (63%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/text/AppVersionText.kt (84%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/text/CategoryTitleText.kt (72%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/text/ManagerText.kt (93%) rename app/src/main/java/com/vanced/manager/ui/{components => component}/text/ToolbarTitleText.kt (73%) rename app/src/main/java/com/vanced/manager/ui/{layouts => screens}/AboutLayout.kt (92%) rename app/src/main/java/com/vanced/manager/ui/{layouts => screens}/HomeLayout.kt (76%) rename app/src/main/java/com/vanced/manager/ui/{layouts => screens}/LogLayout.kt (82%) rename app/src/main/java/com/vanced/manager/ui/{layouts => screens}/SettingsLayout.kt (74%) rename app/src/main/java/com/vanced/manager/ui/{utils => util}/Const.kt (77%) rename app/src/main/java/com/vanced/manager/ui/{screens => util}/Screen.kt (83%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget}/button/ManagerCancelButton.kt (80%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget}/button/ManagerCloseButton.kt (80%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget}/button/ManagerDownloadButton.kt (80%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget}/button/ManagerSaveButton.kt (77%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget}/layout/CategoryLayout.kt (74%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget}/layout/SettingsCategoryLayout.kt (90%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget/screens}/home/apps/AppsItem.kt (85%) create mode 100644 app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppActionCard.kt rename app/src/main/java/com/vanced/manager/ui/{widgets => widget/screens}/home/apps/card/AppCard.kt (86%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget/screens}/home/apps/card/AppInfoCard.kt (78%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget/screens}/home/apps/dialog/AppChangelogDialog.kt (77%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget/screens}/home/apps/dialog/AppDownloadDialog.kt (68%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget/screens}/home/download/AppDownloadDialogProgress.kt (90%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget/screens}/home/installation/CheckboxInstallationOption.kt (65%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget/screens}/home/installation/InstallationOption.kt (64%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget/screens}/home/installation/RadiobuttonInstallationOption.kt (65%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget/screens}/home/socialmedia/SocialMediaItem.kt (64%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget/screens}/home/sponsors/SponsorsItem.kt (63%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget/screens}/settings/AccentColorItem.kt (73%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget/screens}/settings/ClearFilesItem.kt (76%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget/screens}/settings/CustomTabsItem.kt (70%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget/screens}/settings/ManagerVariantItem.kt (71%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget/screens}/settings/NotificationsItem.kt (75%) rename app/src/main/java/com/vanced/manager/ui/{widgets => widget/screens}/settings/ThemeItem.kt (77%) delete mode 100644 app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e40a04468d..f2f746742f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -25,7 +25,7 @@ android:supportsRtl="true"> <activity - android:name=".SplashScreenActivity" + android:name=".ui.SplashScreenActivity" android:exported="true" android:label="@string/app_name" android:theme="@style/SplashTheme"> diff --git a/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt b/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt index 2edefb070e..0dcc6af546 100644 --- a/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt +++ b/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt @@ -1,7 +1,11 @@ package com.vanced.manager.di import com.vanced.manager.downloader.api.VancedAPI +import com.vanced.manager.downloader.impl.MicrogDownloader +import com.vanced.manager.downloader.impl.MusicDownloader import com.vanced.manager.downloader.impl.VancedDownloader +import com.vanced.manager.installer.MicrogInstaller +import com.vanced.manager.installer.MusicInstaller import com.vanced.manager.installer.VancedInstaller import org.koin.dsl.module @@ -10,20 +14,18 @@ val downloaderModule = module { fun provideVancedDownloader( vancedAPI: VancedAPI, vancedInstaller: VancedInstaller - ): VancedDownloader = VancedDownloader(vancedAPI, vancedInstaller) + ) = VancedDownloader(vancedAPI, vancedInstaller) fun provideMusicDownloader( - vancedAPI: VancedAPI, - vancedInstaller: VancedInstaller - ): VancedDownloader = VancedDownloader(vancedAPI, vancedInstaller) + musicInstaller: MusicInstaller + ) = MusicDownloader(musicInstaller) fun provideMicrogDownloader( - vancedAPI: VancedAPI, - vancedInstaller: VancedInstaller - ): VancedDownloader = VancedDownloader(vancedAPI, vancedInstaller) + microgInstaller: MicrogInstaller + ) = MicrogDownloader(microgInstaller) single { provideVancedDownloader(get(), get()) } - single { provideMusicDownloader(get(), get()) } - single { provideMicrogDownloader(get(), get()) } + single { provideMusicDownloader(get()) } + single { provideMicrogDownloader(get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/domain/model/App.kt b/app/src/main/java/com/vanced/manager/domain/model/App.kt index 4ce076b7f1..e762624ae6 100644 --- a/app/src/main/java/com/vanced/manager/domain/model/App.kt +++ b/app/src/main/java/com/vanced/manager/domain/model/App.kt @@ -1,7 +1,7 @@ package com.vanced.manager.domain.model import com.vanced.manager.downloader.base.AppDownloader -import com.vanced.manager.ui.widgets.home.installation.InstallationOption +import com.vanced.manager.ui.widget.screens.home.installation.InstallationOption data class App( val name: String? = null, diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt index 1a478f5eb1..34430e106c 100644 --- a/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt @@ -2,9 +2,15 @@ package com.vanced.manager.downloader.impl import com.vanced.manager.domain.model.App import com.vanced.manager.downloader.base.AppDownloader +import com.vanced.manager.installer.MicrogInstaller import com.vanced.manager.ui.viewmodel.HomeViewModel -class MicrogDownloader : AppDownloader("") { +class MicrogDownloader( + microgInstaller: MicrogInstaller +) : AppDownloader( + appName = "microg", + appInstaller = microgInstaller +) { override suspend fun download(app: App, viewModel: HomeViewModel) { TODO("Not yet implemented") diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt index def60b4d2f..c9a3e4b9bc 100644 --- a/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt @@ -2,9 +2,16 @@ package com.vanced.manager.downloader.impl import com.vanced.manager.domain.model.App import com.vanced.manager.downloader.base.AppDownloader +import com.vanced.manager.installer.MusicInstaller +import com.vanced.manager.installer.VancedInstaller import com.vanced.manager.ui.viewmodel.HomeViewModel -class MusicDownloader : AppDownloader("") { +class MusicDownloader( + musicInstaller: MusicInstaller +) : AppDownloader( + appName = "music", + appInstaller = musicInstaller +) { override suspend fun download(app: App, viewModel: HomeViewModel) { TODO("Not yet implemented") diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt index 86db664227..dd71a68afc 100644 --- a/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt @@ -4,10 +4,10 @@ import com.vanced.manager.domain.model.App import com.vanced.manager.downloader.api.VancedAPI import com.vanced.manager.downloader.base.AppDownloader import com.vanced.manager.installer.VancedInstaller -import com.vanced.manager.ui.preferences.holder.managerVariantPref -import com.vanced.manager.ui.preferences.holder.vancedLanguagesPref -import com.vanced.manager.ui.preferences.holder.vancedThemePref -import com.vanced.manager.ui.preferences.holder.vancedVersionPref +import com.vanced.manager.preferences.holder.managerVariantPref +import com.vanced.manager.preferences.holder.vancedLanguagesPref +import com.vanced.manager.preferences.holder.vancedThemePref +import com.vanced.manager.preferences.holder.vancedVersionPref import com.vanced.manager.ui.viewmodel.HomeViewModel import com.vanced.manager.util.arch import com.vanced.manager.util.log diff --git a/app/src/main/java/com/vanced/manager/installer/MicrogInstaller.kt b/app/src/main/java/com/vanced/manager/installer/MicrogInstaller.kt index 21a5ad73f7..6ca994e275 100644 --- a/app/src/main/java/com/vanced/manager/installer/MicrogInstaller.kt +++ b/app/src/main/java/com/vanced/manager/installer/MicrogInstaller.kt @@ -1,10 +1,8 @@ package com.vanced.manager.installer -import androidx.compose.runtime.MutableState import com.vanced.manager.installer.base.AppInstaller -import com.vanced.manager.ui.preferences.holder.managerVariantPref -import com.vanced.manager.ui.preferences.holder.vancedVersionPref -import com.vanced.manager.ui.viewmodel.HomeViewModel +import com.vanced.manager.preferences.holder.managerVariantPref +import com.vanced.manager.preferences.holder.vancedVersionPref import com.xinto.apkhelper.installSplitApks class MicrogInstaller : AppInstaller() { diff --git a/app/src/main/java/com/vanced/manager/installer/MusicInstaller.kt b/app/src/main/java/com/vanced/manager/installer/MusicInstaller.kt index 1264dea5e9..d934206410 100644 --- a/app/src/main/java/com/vanced/manager/installer/MusicInstaller.kt +++ b/app/src/main/java/com/vanced/manager/installer/MusicInstaller.kt @@ -1,8 +1,8 @@ package com.vanced.manager.installer import com.vanced.manager.installer.base.AppInstaller -import com.vanced.manager.ui.preferences.holder.managerVariantPref -import com.vanced.manager.ui.preferences.holder.vancedVersionPref +import com.vanced.manager.preferences.holder.managerVariantPref +import com.vanced.manager.preferences.holder.vancedVersionPref import com.xinto.apkhelper.installSplitApks class MusicInstaller : AppInstaller() { diff --git a/app/src/main/java/com/vanced/manager/installer/VancedInstaller.kt b/app/src/main/java/com/vanced/manager/installer/VancedInstaller.kt index 7217fa3639..eaf5db4069 100644 --- a/app/src/main/java/com/vanced/manager/installer/VancedInstaller.kt +++ b/app/src/main/java/com/vanced/manager/installer/VancedInstaller.kt @@ -1,10 +1,8 @@ package com.vanced.manager.installer -import androidx.compose.runtime.MutableState import com.vanced.manager.installer.base.AppInstaller -import com.vanced.manager.ui.preferences.holder.managerVariantPref -import com.vanced.manager.ui.preferences.holder.vancedVersionPref -import com.vanced.manager.ui.viewmodel.HomeViewModel +import com.vanced.manager.preferences.holder.managerVariantPref +import com.vanced.manager.preferences.holder.vancedVersionPref import com.xinto.apkhelper.installSplitApks class VancedInstaller : AppInstaller() { diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt index 8e6e52df19..0685cd666a 100644 --- a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt +++ b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt @@ -7,15 +7,15 @@ import com.vanced.manager.domain.model.AppStatus import com.vanced.manager.domain.util.EntityMapper import com.vanced.manager.network.util.MUSIC_NAME import com.vanced.manager.network.util.VANCED_NAME -import com.vanced.manager.ui.preferences.CheckboxPreference -import com.vanced.manager.ui.preferences.RadioButtonPreference -import com.vanced.manager.ui.preferences.holder.musicVersionPref -import com.vanced.manager.ui.preferences.holder.vancedLanguagesPref -import com.vanced.manager.ui.preferences.holder.vancedThemePref -import com.vanced.manager.ui.preferences.holder.vancedVersionPref -import com.vanced.manager.ui.widgets.home.installation.CheckboxInstallationOption -import com.vanced.manager.ui.widgets.home.installation.InstallationOption -import com.vanced.manager.ui.widgets.home.installation.RadiobuttonInstallationOption +import com.vanced.manager.preferences.CheckboxPreference +import com.vanced.manager.preferences.RadioButtonPreference +import com.vanced.manager.preferences.holder.musicVersionPref +import com.vanced.manager.preferences.holder.vancedLanguagesPref +import com.vanced.manager.preferences.holder.vancedThemePref +import com.vanced.manager.preferences.holder.vancedVersionPref +import com.vanced.manager.ui.widget.screens.home.installation.CheckboxInstallationOption +import com.vanced.manager.ui.widget.screens.home.installation.InstallationOption +import com.vanced.manager.ui.widget.screens.home.installation.RadiobuttonInstallationOption import java.util.* class AppDtoMapper( diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/CheckboxPreference.kt b/app/src/main/java/com/vanced/manager/preferences/CheckboxPreference.kt similarity index 65% rename from app/src/main/java/com/vanced/manager/ui/preferences/CheckboxPreference.kt rename to app/src/main/java/com/vanced/manager/preferences/CheckboxPreference.kt index 630c3342d6..f966ec98d8 100644 --- a/app/src/main/java/com/vanced/manager/ui/preferences/CheckboxPreference.kt +++ b/app/src/main/java/com/vanced/manager/preferences/CheckboxPreference.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.preferences +package com.vanced.manager.preferences data class CheckboxPreference( val title: String, diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/ManagerPreference.kt b/app/src/main/java/com/vanced/manager/preferences/ManagerPreference.kt similarity index 62% rename from app/src/main/java/com/vanced/manager/ui/preferences/ManagerPreference.kt rename to app/src/main/java/com/vanced/manager/preferences/ManagerPreference.kt index 0d3e216aff..c79028eb0e 100644 --- a/app/src/main/java/com/vanced/manager/ui/preferences/ManagerPreference.kt +++ b/app/src/main/java/com/vanced/manager/preferences/ManagerPreference.kt @@ -1,55 +1,18 @@ -package com.vanced.manager.ui.preferences +package com.vanced.manager.preferences import android.content.SharedPreferences -import androidx.compose.runtime.Composable import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember import androidx.core.content.edit import org.koin.core.component.KoinComponent import org.koin.core.component.inject import kotlin.reflect.KProperty -class ManagerPreference<T>( - private val key: String, - private val defaultValue: T, - private val getter: (SharedPreferences) -> T, - private val setter: (SharedPreferences.Editor, key: String, newValue: T) -> Unit -) : KoinComponent { - - private val sharedPreferences: SharedPreferences by inject() - - private val _value = mutableStateOf(defaultValue) - val value: State<T> = _value - - @Composable - fun rememberValue() = remember { value } - - operator fun getValue(thisRef: Any?, property: KProperty<*>) = value.value - - operator fun setValue(thisRef: Any?, property: KProperty<*>, newValue: T) { - save(newValue) - } - - fun save(newValue: T) { - _value.value = newValue - sharedPreferences.edit { - setter(this, key, newValue) - } - } - - //It's Chewsday innit - init { - _value.value = getter(sharedPreferences) - } - -} - fun <T> managerPreference( key: String, defaultValue: T, - getter: (SharedPreferences) -> T, - setter: (SharedPreferences.Editor, key: String, newValue: T) -> Unit + getter: SharedPreferences.(key: String, defaultValue: T) -> T?, + setter: SharedPreferences.Editor.(key: String, newValue: T) -> Unit ) = ManagerPreference(key, defaultValue, getter, setter) fun managerStringPreference( @@ -58,9 +21,7 @@ fun managerStringPreference( ) = managerPreference( key = key, defaultValue = defaultValue, - getter = { sharedPreferences -> - SharedPreferences::getString.invoke(sharedPreferences, key, defaultValue) ?: defaultValue - }, + getter = SharedPreferences::getString, setter = SharedPreferences.Editor::putString ) @@ -70,21 +31,17 @@ fun managerStringSetPreference( ) = managerPreference( key = key, defaultValue = defaultValue, - getter = { sharedPreferences -> - SharedPreferences::getStringSet.invoke(sharedPreferences, key, defaultValue) ?: defaultValue - }, + getter = SharedPreferences::getStringSet, setter = SharedPreferences.Editor::putStringSet ) fun managerBooleanPreference( key: String, defaultValue: Boolean = false -) =managerPreference( +) = managerPreference( key = key, defaultValue = defaultValue, - getter = { sharedPreferences -> - SharedPreferences::getBoolean.invoke(sharedPreferences, key, defaultValue) - }, + getter = SharedPreferences::getBoolean, setter = SharedPreferences.Editor::putBoolean ) @@ -94,9 +51,7 @@ fun managerIntPreference( ) = managerPreference( key = key, defaultValue = defaultValue, - getter = { sharedPreferences -> - SharedPreferences::getInt.invoke(sharedPreferences, key, defaultValue) - }, + getter = SharedPreferences::getInt, setter = SharedPreferences.Editor::putInt ) @@ -106,8 +61,38 @@ fun managerLongPreference( ) = managerPreference( key = key, defaultValue = defaultValue, - getter = { sharedPreferences -> - SharedPreferences::getLong.invoke(sharedPreferences, key, defaultValue) - }, + getter = SharedPreferences::getLong, setter = SharedPreferences.Editor::putLong -) \ No newline at end of file +) + +class ManagerPreference<T>( + private val key: String, + private val defaultValue: T, + private val getter: SharedPreferences.(key: String, defaultValue: T) -> T?, + private val setter: SharedPreferences.Editor.(key: String, newValue: T) -> Unit +) : KoinComponent { + + private val sharedPreferences: SharedPreferences by inject() + + private val _value = mutableStateOf(defaultValue) + val value: State<T> = _value + + operator fun getValue(thisRef: Any?, property: KProperty<*>) = value.value + + operator fun setValue(thisRef: Any?, property: KProperty<*>, newValue: T) { + save(newValue) + } + + fun save(newValue: T) { + _value.value = newValue + sharedPreferences.edit { + setter(key, newValue) + } + } + + //It's Chewsday innit + init { + _value.value = sharedPreferences.getter(key, defaultValue) ?: defaultValue + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/RadioButtonPreference.kt b/app/src/main/java/com/vanced/manager/preferences/RadioButtonPreference.kt similarity index 65% rename from app/src/main/java/com/vanced/manager/ui/preferences/RadioButtonPreference.kt rename to app/src/main/java/com/vanced/manager/preferences/RadioButtonPreference.kt index ab797fbc3e..bdf36b4fb7 100644 --- a/app/src/main/java/com/vanced/manager/ui/preferences/RadioButtonPreference.kt +++ b/app/src/main/java/com/vanced/manager/preferences/RadioButtonPreference.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.preferences +package com.vanced.manager.preferences data class RadioButtonPreference( val title: String, diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceDefaultValueHolder.kt b/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceDefaultValueHolder.kt similarity index 85% rename from app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceDefaultValueHolder.kt rename to app/src/main/java/com/vanced/manager/preferences/holder/PreferenceDefaultValueHolder.kt index 2eb280d65e..cb209aa519 100644 --- a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceDefaultValueHolder.kt +++ b/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceDefaultValueHolder.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.preferences.holder +package com.vanced.manager.preferences.holder const val MANAGER_VARIANT_DEFAULT_VALUE = "nonroot" diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceHolder.kt b/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceHolder.kt similarity index 76% rename from app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceHolder.kt rename to app/src/main/java/com/vanced/manager/preferences/holder/PreferenceHolder.kt index 4f89a6374d..0b8061722d 100644 --- a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceHolder.kt +++ b/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceHolder.kt @@ -1,9 +1,9 @@ -package com.vanced.manager.ui.preferences.holder +package com.vanced.manager.preferences.holder -import com.vanced.manager.ui.preferences.managerBooleanPreference -import com.vanced.manager.ui.preferences.managerLongPreference -import com.vanced.manager.ui.preferences.managerStringPreference -import com.vanced.manager.ui.preferences.managerStringSetPreference +import com.vanced.manager.preferences.managerBooleanPreference +import com.vanced.manager.preferences.managerLongPreference +import com.vanced.manager.preferences.managerStringPreference +import com.vanced.manager.preferences.managerStringSetPreference import com.vanced.manager.ui.theme.defAccentColor val useCustomTabsPref = managerBooleanPreference(USE_CUSTOM_TABS_KEY) diff --git a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceKeyHolder.kt b/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceKeyHolder.kt similarity index 91% rename from app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceKeyHolder.kt rename to app/src/main/java/com/vanced/manager/preferences/holder/PreferenceKeyHolder.kt index 34f941eb09..c24886805e 100644 --- a/app/src/main/java/com/vanced/manager/ui/preferences/holder/PreferenceKeyHolder.kt +++ b/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceKeyHolder.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.preferences.holder +package com.vanced.manager.preferences.holder const val USE_CUSTOM_TABS_KEY = "use_custom_tabs" const val MANAGER_VARIANT_KEY = "manager_variant" diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index e6b0c47b8b..b656e90bd6 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -1,8 +1,8 @@ package com.vanced.manager.ui import android.os.Bundle +import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.appcompat.app.AppCompatActivity import androidx.compose.foundation.background import androidx.compose.material.* import androidx.compose.material.icons.Icons @@ -19,17 +19,17 @@ import androidx.navigation.compose.composable import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import com.google.accompanist.systemuicontroller.rememberSystemUiController -import com.vanced.manager.ui.components.color.managerAnimatedColor -import com.vanced.manager.ui.components.color.managerSurfaceColor -import com.vanced.manager.ui.components.color.managerTextColor -import com.vanced.manager.ui.components.menu.ManagerDropdownMenuItem -import com.vanced.manager.ui.components.text.ToolbarTitleText +import com.vanced.manager.ui.component.color.managerAnimatedColor +import com.vanced.manager.ui.component.color.managerSurfaceColor +import com.vanced.manager.ui.component.color.managerTextColor +import com.vanced.manager.ui.component.menu.ManagerDropdownMenuItem +import com.vanced.manager.ui.component.text.ToolbarTitleText import com.vanced.manager.ui.resources.managerString -import com.vanced.manager.ui.screens.Screen +import com.vanced.manager.ui.util.Screen import com.vanced.manager.ui.theme.ManagerTheme import com.vanced.manager.ui.theme.isDark -class MainActivity : AppCompatActivity() { +class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -128,7 +128,7 @@ class MainActivity : AppCompatActivity() { } } }, - navigationIcon = if (currentScreenRoute != Screen.Home.route) { { + navigationIcon = if (currentScreenRoute != Screen.Home.route) {{ IconButton(onClick = { navController.popBackStack() }) { diff --git a/app/src/main/java/com/vanced/manager/SplashScreenActivity.kt b/app/src/main/java/com/vanced/manager/ui/SplashScreenActivity.kt similarity index 83% rename from app/src/main/java/com/vanced/manager/SplashScreenActivity.kt rename to app/src/main/java/com/vanced/manager/ui/SplashScreenActivity.kt index 92f2f02398..aeb2ecf771 100644 --- a/app/src/main/java/com/vanced/manager/SplashScreenActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/SplashScreenActivity.kt @@ -1,9 +1,8 @@ -package com.vanced.manager +package com.vanced.manager.ui import android.content.Intent import android.os.Bundle import androidx.activity.ComponentActivity -import com.vanced.manager.ui.MainActivity class SplashScreenActivity : ComponentActivity() { diff --git a/app/src/main/java/com/vanced/manager/ui/components/animation/SpringAnimation.kt b/app/src/main/java/com/vanced/manager/ui/component/animation/SpringAnimation.kt similarity index 93% rename from app/src/main/java/com/vanced/manager/ui/components/animation/SpringAnimation.kt rename to app/src/main/java/com/vanced/manager/ui/component/animation/SpringAnimation.kt index 1b43cd5cb5..6bad604461 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/animation/SpringAnimation.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/animation/SpringAnimation.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.animation +package com.vanced.manager.ui.component.animation import android.annotation.SuppressLint import androidx.compose.animation.core.Transition diff --git a/app/src/main/java/com/vanced/manager/ui/components/button/ManagerIconButton.kt b/app/src/main/java/com/vanced/manager/ui/component/button/ManagerIconButton.kt similarity index 96% rename from app/src/main/java/com/vanced/manager/ui/components/button/ManagerIconButton.kt rename to app/src/main/java/com/vanced/manager/ui/component/button/ManagerIconButton.kt index 11baf94b37..dee1b46f0c 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/button/ManagerIconButton.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/button/ManagerIconButton.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.button +package com.vanced.manager.ui.component.button import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource diff --git a/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedButton.kt b/app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedButton.kt similarity index 90% rename from app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedButton.kt rename to app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedButton.kt index 4894d3c146..0eeae708d7 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedButton.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedButton.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.button +package com.vanced.manager.ui.component.button import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.fillMaxWidth @@ -10,7 +10,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.luminance import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.components.color.managerAccentColor +import com.vanced.manager.ui.component.color.managerAccentColor @Composable fun ManagerThemedButton( diff --git a/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedTextButton.kt b/app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedTextButton.kt similarity index 73% rename from app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedTextButton.kt rename to app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedTextButton.kt index d2524b2564..ad46c351ef 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/button/ManagerThemedTextButton.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedTextButton.kt @@ -1,10 +1,10 @@ -package com.vanced.manager.ui.components.button +package com.vanced.manager.ui.component.button import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import com.vanced.manager.ui.components.color.managerAccentColor -import com.vanced.manager.ui.components.text.ManagerText +import com.vanced.manager.ui.component.color.managerAccentColor +import com.vanced.manager.ui.component.text.ManagerText @Composable fun ManagerThemedTextButton( diff --git a/app/src/main/java/com/vanced/manager/ui/components/card/ManagerCard.kt b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerCard.kt similarity index 96% rename from app/src/main/java/com/vanced/manager/ui/components/card/ManagerCard.kt rename to app/src/main/java/com/vanced/manager/ui/component/card/ManagerCard.kt index 81787834fe..49c9a88ae2 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/card/ManagerCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerCard.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.card +package com.vanced.manager.ui.component.card import androidx.compose.material.Card import androidx.compose.material.ExperimentalMaterialApi diff --git a/app/src/main/java/com/vanced/manager/ui/components/card/ManagerItemCard.kt b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerItemCard.kt similarity index 91% rename from app/src/main/java/com/vanced/manager/ui/components/card/ManagerItemCard.kt rename to app/src/main/java/com/vanced/manager/ui/component/card/ManagerItemCard.kt index ed6ae8976b..6cddd8b1ae 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/card/ManagerItemCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerItemCard.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.card +package com.vanced.manager.ui.component.card import androidx.annotation.DrawableRes import androidx.compose.foundation.Canvas @@ -14,8 +14,8 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.vanced.manager.ui.components.color.ThemedItemContentColorProvider -import com.vanced.manager.ui.components.color.managerAccentColor +import com.vanced.manager.ui.component.color.ThemedItemContentColorProvider +import com.vanced.manager.ui.component.color.managerAccentColor private val cardModifier = Modifier.sizeIn( minHeight = 95.dp, diff --git a/app/src/main/java/com/vanced/manager/ui/components/card/ManagerLinkCard.kt b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerLinkCard.kt similarity index 88% rename from app/src/main/java/com/vanced/manager/ui/components/card/ManagerLinkCard.kt rename to app/src/main/java/com/vanced/manager/ui/component/card/ManagerLinkCard.kt index 76179210d1..4cc2a5e43a 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/card/ManagerLinkCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerLinkCard.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.card +package com.vanced.manager.ui.component.card import android.content.Intent import android.net.Uri @@ -7,7 +7,7 @@ import androidx.browser.customtabs.CustomTabsIntent import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext -import com.vanced.manager.ui.preferences.holder.useCustomTabsPref +import com.vanced.manager.preferences.holder.useCustomTabsPref @Composable fun ManagerLinkCard( diff --git a/app/src/main/java/com/vanced/manager/ui/components/card/ManagerThemedCard.kt b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerThemedCard.kt similarity index 88% rename from app/src/main/java/com/vanced/manager/ui/components/card/ManagerThemedCard.kt rename to app/src/main/java/com/vanced/manager/ui/component/card/ManagerThemedCard.kt index bc75156861..c02e1c17f5 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/card/ManagerThemedCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerThemedCard.kt @@ -1,10 +1,10 @@ -package com.vanced.manager.ui.components.card +package com.vanced.manager.ui.component.card import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Shape -import com.vanced.manager.ui.components.color.managerThemedCardColor +import com.vanced.manager.ui.component.color.managerThemedCardColor @Composable fun ManagerThemedCard( diff --git a/app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt b/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt similarity index 70% rename from app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt rename to app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt index e6baa83d70..f9dd90fc54 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/checkbox/ManagerCheckbox.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt @@ -1,41 +1,44 @@ -package com.vanced.manager.ui.components.checkbox +package com.vanced.manager.ui.component.checkbox import android.annotation.SuppressLint import androidx.compose.animation.core.updateTransition import androidx.compose.foundation.layout.requiredSize import androidx.compose.foundation.layout.size import androidx.compose.material.Icon +import androidx.compose.material.MaterialTheme import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.Close import androidx.compose.material.icons.rounded.Done import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Shape import androidx.compose.ui.unit.Dp -import com.vanced.manager.ui.components.animation.springAnimation -import com.vanced.manager.ui.components.card.ManagerCard -import com.vanced.manager.ui.components.color.contentColorForColor -import com.vanced.manager.ui.components.color.managerAccentColor -import com.vanced.manager.ui.components.color.managerAnimatedColor -import com.vanced.manager.ui.components.color.managerThemedCardColor +import com.vanced.manager.ui.component.animation.springAnimation +import com.vanced.manager.ui.component.card.ManagerCard +import com.vanced.manager.ui.component.color.contentColorForColor +import com.vanced.manager.ui.component.color.managerAccentColor +import com.vanced.manager.ui.component.color.managerAnimatedColor +import com.vanced.manager.ui.component.color.managerThemedCardColor @SuppressLint("UnusedTransitionTargetStateParameter") @Composable fun ManagerCheckbox( size: Dp, isChecked: Boolean, + shape: Shape = MaterialTheme.shapes.medium, onCheckedChange: (isChecked: Boolean) -> Unit ) { val accentColor = managerAccentColor() - val iconInitialSize = size / 1.6f val transition = updateTransition(targetState = isChecked, label = "Checked") val cardSize by transition.springAnimation(initialValue = size, label = "Checkbox Size") - val iconSize by transition.springAnimation(initialValue = iconInitialSize, label = "Icon size") + val iconSize = cardSize / 1.6f val cardColor = managerAnimatedColor(if (isChecked) accentColor else managerThemedCardColor()) val iconTint = managerAnimatedColor(if (isChecked) contentColorForColor(cardColor) else accentColor) - + ManagerCard( modifier = Modifier.size(cardSize), + shape = shape, onClick = { onCheckedChange(!isChecked) }, backgroundColor = cardColor ) { diff --git a/app/src/main/java/com/vanced/manager/ui/components/color/ColorContentProvider.kt b/app/src/main/java/com/vanced/manager/ui/component/color/ColorContentProvider.kt similarity index 94% rename from app/src/main/java/com/vanced/manager/ui/components/color/ColorContentProvider.kt rename to app/src/main/java/com/vanced/manager/ui/component/color/ColorContentProvider.kt index 2b7022cc56..00511baf30 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/color/ColorContentProvider.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/color/ColorContentProvider.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.color +package com.vanced.manager.ui.component.color import androidx.compose.material.LocalContentColor import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/vanced/manager/ui/components/color/ColorPicker.kt b/app/src/main/java/com/vanced/manager/ui/component/color/ColorPicker.kt similarity index 94% rename from app/src/main/java/com/vanced/manager/ui/components/color/ColorPicker.kt rename to app/src/main/java/com/vanced/manager/ui/component/color/ColorPicker.kt index 2eb04d9001..be52927483 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/color/ColorPicker.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/color/ColorPicker.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.color +package com.vanced.manager.ui.component.color import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height diff --git a/app/src/main/java/com/vanced/manager/ui/components/color/ManagerColors.kt b/app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt similarity index 73% rename from app/src/main/java/com/vanced/manager/ui/components/color/ManagerColors.kt rename to app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt index cbaa460763..6a60bbde95 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/color/ManagerColors.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt @@ -1,12 +1,13 @@ -package com.vanced.manager.ui.components.color +package com.vanced.manager.ui.component.color import androidx.compose.animation.animateColorAsState import androidx.compose.animation.core.tween import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.luminance -import com.vanced.manager.ui.preferences.holder.managerAccentColorPref +import com.vanced.manager.preferences.holder.managerAccentColorPref @Composable fun contentColorForColor(color: Color) = @@ -18,11 +19,11 @@ fun contentColorForColor(color: Color) = @Composable fun managerAccentColor(): Color { val accentColor by managerAccentColorPref - return Color(accentColor) + return remember { Color(accentColor) } } @Composable -fun managerThemedCardColor() = managerAccentColor().copy(alpha = 0.2f) +fun managerThemedCardColor() = managerAccentColor().copy(alpha = 0.27f) @Composable fun managerTextColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.onSurface) @@ -33,9 +34,7 @@ fun managerSurfaceColor(): Color = managerAnimatedColor(color = MaterialTheme.co @Composable fun managerAnimatedColor( color: Color -): Color { - return animateColorAsState( - targetValue = color, - animationSpec = tween(500) - ).value -} \ No newline at end of file +): Color = animateColorAsState( + targetValue = color, + animationSpec = tween(500) +).value \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/components/dialog/ManagerDialog.kt b/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt similarity index 86% rename from app/src/main/java/com/vanced/manager/ui/components/dialog/ManagerDialog.kt rename to app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt index 06ace4057e..12b7fa1a97 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/dialog/ManagerDialog.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.dialog +package com.vanced.manager.ui.component.dialog import androidx.compose.foundation.layout.* import androidx.compose.material.MaterialTheme @@ -7,9 +7,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog -import com.vanced.manager.ui.components.card.ManagerCard -import com.vanced.manager.ui.components.text.ManagerText -import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal +import com.vanced.manager.ui.component.card.ManagerCard +import com.vanced.manager.ui.component.text.ManagerText +import com.vanced.manager.ui.util.defaultContentPaddingHorizontal @Composable fun ManagerDialog( diff --git a/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerButtonColumn.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerButtonColumn.kt similarity index 82% rename from app/src/main/java/com/vanced/manager/ui/components/layout/ManagerButtonColumn.kt rename to app/src/main/java/com/vanced/manager/ui/component/layout/ManagerButtonColumn.kt index b59739bdb1..4ef62a2505 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerButtonColumn.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerButtonColumn.kt @@ -1,11 +1,11 @@ -package com.vanced.manager.ui.components.layout +package com.vanced.manager.ui.component.layout import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import com.vanced.manager.ui.utils.defaultContentPaddingVertical +import com.vanced.manager.ui.util.defaultContentPaddingVertical @Composable fun ManagerButtonColumn( diff --git a/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerLazyColumn.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt similarity index 92% rename from app/src/main/java/com/vanced/manager/ui/components/layout/ManagerLazyColumn.kt rename to app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt index 681314b6c7..339ee39feb 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerLazyColumn.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.layout +package com.vanced.manager.ui.component.layout import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.PaddingValues diff --git a/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerScrollableColumn.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrollableColumn.kt similarity index 90% rename from app/src/main/java/com/vanced/manager/ui/components/layout/ManagerScrollableColumn.kt rename to app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrollableColumn.kt index 40eb440b70..aec175e29e 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerScrollableColumn.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrollableColumn.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.layout +package com.vanced.manager.ui.component.layout import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -11,7 +11,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.utils.defaultContentPaddingVertical +import com.vanced.manager.ui.util.defaultContentPaddingVertical @Composable fun ManagerScrollableColumn( diff --git a/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerSurface.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSurface.kt similarity index 76% rename from app/src/main/java/com/vanced/manager/ui/components/layout/ManagerSurface.kt rename to app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSurface.kt index f2a6c7a055..1823d721d2 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerSurface.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSurface.kt @@ -1,10 +1,10 @@ -package com.vanced.manager.ui.components.layout +package com.vanced.manager.ui.component.layout import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import com.vanced.manager.ui.components.color.managerSurfaceColor +import com.vanced.manager.ui.component.color.managerSurfaceColor @Composable fun ManagerSurface( diff --git a/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerSwipeRefresh.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSwipeRefresh.kt similarity index 86% rename from app/src/main/java/com/vanced/manager/ui/components/layout/ManagerSwipeRefresh.kt rename to app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSwipeRefresh.kt index 2c06b9ccc1..c1234cc454 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/layout/ManagerSwipeRefresh.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSwipeRefresh.kt @@ -1,10 +1,10 @@ -package com.vanced.manager.ui.components.layout +package com.vanced.manager.ui.component.layout import androidx.compose.runtime.Composable import com.google.accompanist.swiperefresh.SwipeRefresh import com.google.accompanist.swiperefresh.SwipeRefreshIndicator import com.google.accompanist.swiperefresh.SwipeRefreshState -import com.vanced.manager.ui.components.color.managerAccentColor +import com.vanced.manager.ui.component.color.managerAccentColor @Composable fun ManagerSwipeRefresh( diff --git a/app/src/main/java/com/vanced/manager/ui/components/layout/ScrollableItemRow.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ScrollableItemRow.kt similarity index 93% rename from app/src/main/java/com/vanced/manager/ui/components/layout/ScrollableItemRow.kt rename to app/src/main/java/com/vanced/manager/ui/component/layout/ScrollableItemRow.kt index 0b33fffea9..7de9d56291 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/layout/ScrollableItemRow.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ScrollableItemRow.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.layout +package com.vanced.manager.ui.component.layout import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.fillMaxWidth diff --git a/app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt b/app/src/main/java/com/vanced/manager/ui/component/list/CheckboxItem.kt similarity index 77% rename from app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt rename to app/src/main/java/com/vanced/manager/ui/component/list/CheckboxItem.kt index f18e67e277..ef2ffe812f 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/list/CheckboxItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/list/CheckboxItem.kt @@ -1,15 +1,16 @@ -package com.vanced.manager.ui.components.list +package com.vanced.manager.ui.component.list import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.vanced.manager.ui.components.checkbox.ManagerCheckbox -import com.vanced.manager.ui.components.color.managerTextColor -import com.vanced.manager.ui.components.modifier.managerClickable +import com.vanced.manager.ui.component.checkbox.ManagerCheckbox +import com.vanced.manager.ui.component.color.managerTextColor +import com.vanced.manager.ui.component.modifier.managerClickable @Composable fun CheckboxItem( @@ -32,6 +33,7 @@ fun CheckboxItem( ) { ManagerCheckbox( size = 24.dp, + shape = CircleShape, isChecked = isChecked ) { toggle() diff --git a/app/src/main/java/com/vanced/manager/ui/components/list/ManagerListItem.kt b/app/src/main/java/com/vanced/manager/ui/component/list/ManagerListItem.kt similarity index 97% rename from app/src/main/java/com/vanced/manager/ui/components/list/ManagerListItem.kt rename to app/src/main/java/com/vanced/manager/ui/component/list/ManagerListItem.kt index 63560220e7..6bacb6ae7c 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/list/ManagerListItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/list/ManagerListItem.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.list +package com.vanced.manager.ui.component.list import androidx.compose.foundation.layout.* import androidx.compose.material.ContentAlpha diff --git a/app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt b/app/src/main/java/com/vanced/manager/ui/component/list/RadiobuttonItem.kt similarity index 78% rename from app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt rename to app/src/main/java/com/vanced/manager/ui/component/list/RadiobuttonItem.kt index 9e96c68728..8d2af13f78 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/list/RadiobuttonItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/list/RadiobuttonItem.kt @@ -1,15 +1,16 @@ -package com.vanced.manager.ui.components.list +package com.vanced.manager.ui.component.list import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.vanced.manager.ui.components.color.managerTextColor -import com.vanced.manager.ui.components.radiobutton.ManagerRadiobutton +import com.vanced.manager.ui.component.color.managerTextColor +import com.vanced.manager.ui.component.radiobutton.ManagerRadiobutton @Composable fun <T> RadiobuttonItem( @@ -18,9 +19,7 @@ fun <T> RadiobuttonItem( isSelected: Boolean, onSelect: (tag: T) -> Unit ) { - val onClick = { - onSelect(tag) - } + val onClick = { onSelect(tag) } Row( modifier = Modifier @@ -35,6 +34,7 @@ fun <T> RadiobuttonItem( ) { ManagerRadiobutton( size = 24.dp, + shape = CircleShape, isSelected = isSelected, onClick = onClick ) diff --git a/app/src/main/java/com/vanced/manager/ui/components/menu/ManagerDropdownMenuItem.kt b/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenuItem.kt similarity index 79% rename from app/src/main/java/com/vanced/manager/ui/components/menu/ManagerDropdownMenuItem.kt rename to app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenuItem.kt index d1277a6670..8e75fe6a1e 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/menu/ManagerDropdownMenuItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenuItem.kt @@ -1,9 +1,9 @@ -package com.vanced.manager.ui.components.menu +package com.vanced.manager.ui.component.menu import androidx.compose.material.DropdownMenuItem import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable -import com.vanced.manager.ui.components.text.ManagerText +import com.vanced.manager.ui.component.text.ManagerText @Composable fun ManagerDropdownMenuItem( diff --git a/app/src/main/java/com/vanced/manager/ui/components/modifier/ManagerClickable.kt b/app/src/main/java/com/vanced/manager/ui/component/modifier/ManagerClickable.kt similarity index 93% rename from app/src/main/java/com/vanced/manager/ui/components/modifier/ManagerClickable.kt rename to app/src/main/java/com/vanced/manager/ui/component/modifier/ManagerClickable.kt index e4ccbc7e78..f834c53473 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/modifier/ManagerClickable.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/modifier/ManagerClickable.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.modifier +package com.vanced.manager.ui.component.modifier import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource diff --git a/app/src/main/java/com/vanced/manager/ui/components/modifier/ManagerPlaceholder.kt b/app/src/main/java/com/vanced/manager/ui/component/modifier/ManagerPlaceholder.kt similarity index 90% rename from app/src/main/java/com/vanced/manager/ui/components/modifier/ManagerPlaceholder.kt rename to app/src/main/java/com/vanced/manager/ui/component/modifier/ManagerPlaceholder.kt index b15e229b3e..6e45eb7422 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/modifier/ManagerPlaceholder.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/modifier/ManagerPlaceholder.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.modifier +package com.vanced.manager.ui.component.modifier import androidx.compose.ui.Modifier import androidx.compose.ui.composed diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt similarity index 88% rename from app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxDialogPreference.kt rename to app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt index f78a07d7c5..fb10eb920f 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.preference +package com.vanced.manager.ui.component.preference import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.heightIn @@ -12,10 +12,10 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.vanced.manager.R -import com.vanced.manager.ui.components.button.ManagerThemedTextButton -import com.vanced.manager.ui.components.list.CheckboxItem -import com.vanced.manager.ui.preferences.CheckboxPreference -import com.vanced.manager.ui.preferences.ManagerPreference +import com.vanced.manager.preferences.CheckboxPreference +import com.vanced.manager.preferences.ManagerPreference +import com.vanced.manager.ui.component.button.ManagerThemedTextButton +import com.vanced.manager.ui.component.list.CheckboxItem import kotlinx.coroutines.launch @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt similarity index 84% rename from app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxPreference.kt rename to app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt index 8770319bbb..e65be4c9b0 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/preference/CheckboxPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt @@ -1,10 +1,10 @@ -package com.vanced.manager.ui.components.preference +package com.vanced.manager.ui.component.preference import androidx.compose.runtime.Composable import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.components.checkbox.ManagerCheckbox -import com.vanced.manager.ui.preferences.ManagerPreference +import com.vanced.manager.ui.component.checkbox.ManagerCheckbox +import com.vanced.manager.preferences.ManagerPreference import kotlinx.coroutines.launch @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/DialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/DialogPreference.kt similarity index 89% rename from app/src/main/java/com/vanced/manager/ui/components/preference/DialogPreference.kt rename to app/src/main/java/com/vanced/manager/ui/component/preference/DialogPreference.kt index c9c2502110..0e26a0db6b 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/preference/DialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/DialogPreference.kt @@ -1,11 +1,11 @@ -package com.vanced.manager.ui.components.preference +package com.vanced.manager.ui.component.preference import androidx.compose.foundation.layout.ColumnScope import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import com.vanced.manager.ui.components.dialog.ManagerDialog +import com.vanced.manager.ui.component.dialog.ManagerDialog @Composable fun DialogPreference( diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/Preference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt similarity index 83% rename from app/src/main/java/com/vanced/manager/ui/components/preference/Preference.kt rename to app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt index 4d3e84e920..e128956ef5 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/preference/Preference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.preference +package com.vanced.manager.ui.component.preference import androidx.compose.foundation.layout.padding import androidx.compose.material.LocalContentColor @@ -7,11 +7,11 @@ import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier -import com.vanced.manager.ui.components.color.managerAnimatedColor -import com.vanced.manager.ui.components.list.ManagerListItem -import com.vanced.manager.ui.components.modifier.managerClickable -import com.vanced.manager.ui.components.text.ManagerText -import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal +import com.vanced.manager.ui.component.color.managerAnimatedColor +import com.vanced.manager.ui.component.list.ManagerListItem +import com.vanced.manager.ui.component.modifier.managerClickable +import com.vanced.manager.ui.component.text.ManagerText +import com.vanced.manager.ui.util.defaultContentPaddingHorizontal @Composable fun Preference( diff --git a/app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt similarity index 84% rename from app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt rename to app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt index b87fc2beba..c64e2a2730 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/preference/RadiobuttonDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.preference +package com.vanced.manager.ui.component.preference import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.lazy.LazyColumn @@ -6,10 +6,10 @@ import androidx.compose.foundation.lazy.items import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.components.list.RadiobuttonItem -import com.vanced.manager.ui.preferences.ManagerPreference -import com.vanced.manager.ui.preferences.RadioButtonPreference -import com.vanced.manager.ui.widgets.button.ManagerSaveButton +import com.vanced.manager.ui.component.list.RadiobuttonItem +import com.vanced.manager.preferences.ManagerPreference +import com.vanced.manager.preferences.RadioButtonPreference +import com.vanced.manager.ui.widget.button.ManagerSaveButton import kotlinx.coroutines.launch @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/components/progressindicator/ManagerProgressIndicator.kt b/app/src/main/java/com/vanced/manager/ui/component/progressindicator/ManagerProgressIndicator.kt similarity index 91% rename from app/src/main/java/com/vanced/manager/ui/components/progressindicator/ManagerProgressIndicator.kt rename to app/src/main/java/com/vanced/manager/ui/component/progressindicator/ManagerProgressIndicator.kt index f3a492c6dd..2aa10cfc0f 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/progressindicator/ManagerProgressIndicator.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/progressindicator/ManagerProgressIndicator.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.progressindicator +package com.vanced.manager.ui.component.progressindicator import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.layout.fillMaxWidth @@ -12,7 +12,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.composed import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.components.color.managerAccentColor +import com.vanced.manager.ui.component.color.managerAccentColor private val progressBarModifier = Modifier.composed { then( diff --git a/app/src/main/java/com/vanced/manager/ui/components/radiobutton/ManagerRadiobutton.kt b/app/src/main/java/com/vanced/manager/ui/component/radiobutton/ManagerRadiobutton.kt similarity index 63% rename from app/src/main/java/com/vanced/manager/ui/components/radiobutton/ManagerRadiobutton.kt rename to app/src/main/java/com/vanced/manager/ui/component/radiobutton/ManagerRadiobutton.kt index e55b2753b0..40417488fb 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/radiobutton/ManagerRadiobutton.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/radiobutton/ManagerRadiobutton.kt @@ -1,23 +1,26 @@ -package com.vanced.manager.ui.components.radiobutton +package com.vanced.manager.ui.component.radiobutton import android.annotation.SuppressLint import androidx.compose.animation.core.updateTransition import androidx.compose.foundation.layout.size +import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Shape import androidx.compose.ui.unit.Dp -import com.vanced.manager.ui.components.animation.springAnimation -import com.vanced.manager.ui.components.card.ManagerCard -import com.vanced.manager.ui.components.color.managerAccentColor -import com.vanced.manager.ui.components.color.managerAnimatedColor -import com.vanced.manager.ui.components.color.managerThemedCardColor +import com.vanced.manager.ui.component.animation.springAnimation +import com.vanced.manager.ui.component.card.ManagerCard +import com.vanced.manager.ui.component.color.managerAccentColor +import com.vanced.manager.ui.component.color.managerAnimatedColor +import com.vanced.manager.ui.component.color.managerThemedCardColor @SuppressLint("UnusedTransitionTargetStateParameter") @Composable fun ManagerRadiobutton( size: Dp, isSelected: Boolean, + shape: Shape = MaterialTheme.shapes.medium, onClick: () -> Unit ) { val accentColor = managerAccentColor() @@ -27,6 +30,7 @@ fun ManagerRadiobutton( ManagerCard( modifier = Modifier.size(cardSize), onClick = onClick, + shape = shape, backgroundColor = cardColor, content = {} ) diff --git a/app/src/main/java/com/vanced/manager/ui/components/text/AppVersionText.kt b/app/src/main/java/com/vanced/manager/ui/component/text/AppVersionText.kt similarity index 84% rename from app/src/main/java/com/vanced/manager/ui/components/text/AppVersionText.kt rename to app/src/main/java/com/vanced/manager/ui/component/text/AppVersionText.kt index 51832a1497..fe1277d89d 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/text/AppVersionText.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/text/AppVersionText.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.text +package com.vanced.manager.ui.component.text import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/vanced/manager/ui/components/text/CategoryTitleText.kt b/app/src/main/java/com/vanced/manager/ui/component/text/CategoryTitleText.kt similarity index 72% rename from app/src/main/java/com/vanced/manager/ui/components/text/CategoryTitleText.kt rename to app/src/main/java/com/vanced/manager/ui/component/text/CategoryTitleText.kt index e5c7710b24..ff0bbe9e6f 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/text/CategoryTitleText.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/text/CategoryTitleText.kt @@ -1,11 +1,11 @@ -package com.vanced.manager.ui.components.text +package com.vanced.manager.ui.component.text import androidx.compose.foundation.layout.padding import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import com.vanced.manager.ui.components.color.managerAnimatedColor -import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal +import com.vanced.manager.ui.component.color.managerAnimatedColor +import com.vanced.manager.ui.util.defaultContentPaddingHorizontal @Composable fun CategoryTitleText( diff --git a/app/src/main/java/com/vanced/manager/ui/components/text/ManagerText.kt b/app/src/main/java/com/vanced/manager/ui/component/text/ManagerText.kt similarity index 93% rename from app/src/main/java/com/vanced/manager/ui/components/text/ManagerText.kt rename to app/src/main/java/com/vanced/manager/ui/component/text/ManagerText.kt index 79df124033..9a94ab8742 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/text/ManagerText.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/text/ManagerText.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.components.text +package com.vanced.manager.ui.component.text import androidx.compose.material.LocalTextStyle import androidx.compose.material.Text diff --git a/app/src/main/java/com/vanced/manager/ui/components/text/ToolbarTitleText.kt b/app/src/main/java/com/vanced/manager/ui/component/text/ToolbarTitleText.kt similarity index 73% rename from app/src/main/java/com/vanced/manager/ui/components/text/ToolbarTitleText.kt rename to app/src/main/java/com/vanced/manager/ui/component/text/ToolbarTitleText.kt index 9c1d7b717a..cad4646d81 100644 --- a/app/src/main/java/com/vanced/manager/ui/components/text/ToolbarTitleText.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/text/ToolbarTitleText.kt @@ -1,8 +1,8 @@ -package com.vanced.manager.ui.components.text +package com.vanced.manager.ui.component.text import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable -import com.vanced.manager.ui.components.color.managerAnimatedColor +import com.vanced.manager.ui.component.color.managerAnimatedColor @Composable fun ToolbarTitleText( diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/AboutLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt similarity index 92% rename from app/src/main/java/com/vanced/manager/ui/layouts/AboutLayout.kt rename to app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt index ac3a27bae4..a4067d9f19 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/AboutLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt @@ -17,14 +17,14 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.util.fastForEach import com.vanced.manager.R -import com.vanced.manager.ui.components.card.ManagerLinkCard -import com.vanced.manager.ui.components.card.ManagerThemedCard -import com.vanced.manager.ui.components.layout.ManagerScrollableColumn -import com.vanced.manager.ui.components.layout.ScrollableItemRow -import com.vanced.manager.ui.components.list.ManagerListItem -import com.vanced.manager.ui.components.text.ManagerText +import com.vanced.manager.ui.component.card.ManagerLinkCard +import com.vanced.manager.ui.component.card.ManagerThemedCard +import com.vanced.manager.ui.component.layout.ManagerScrollableColumn +import com.vanced.manager.ui.component.layout.ScrollableItemRow +import com.vanced.manager.ui.component.list.ManagerListItem +import com.vanced.manager.ui.component.text.ManagerText import com.vanced.manager.ui.resources.managerString -import com.vanced.manager.ui.widgets.layout.CategoryLayout +import com.vanced.manager.ui.widget.layout.CategoryLayout data class Person( val name: String, diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt similarity index 76% rename from app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt rename to app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt index 189d5a2cad..fabcf5a567 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/HomeLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.layouts +package com.vanced.manager.ui.screens import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -7,15 +7,15 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.google.accompanist.swiperefresh.rememberSwipeRefreshState import com.vanced.manager.R -import com.vanced.manager.ui.components.layout.ManagerScrollableColumn -import com.vanced.manager.ui.components.layout.ManagerSwipeRefresh +import com.vanced.manager.ui.component.layout.ManagerScrollableColumn +import com.vanced.manager.ui.component.layout.ManagerSwipeRefresh import com.vanced.manager.ui.resources.managerString -import com.vanced.manager.ui.utils.defaultContentPaddingVertical +import com.vanced.manager.ui.util.defaultContentPaddingVertical import com.vanced.manager.ui.viewmodel.HomeViewModel -import com.vanced.manager.ui.widgets.home.apps.HomeAppsItem -import com.vanced.manager.ui.widgets.home.socialmedia.HomeSocialMediaItem -import com.vanced.manager.ui.widgets.home.sponsors.HomeSponsorsItem -import com.vanced.manager.ui.widgets.layout.CategoryLayout +import com.vanced.manager.ui.widget.screens.home.apps.HomeAppsItem +import com.vanced.manager.ui.widget.screens.home.socialmedia.HomeSocialMediaItem +import com.vanced.manager.ui.widget.screens.home.sponsors.HomeSponsorsItem +import com.vanced.manager.ui.widget.layout.CategoryLayout import org.koin.androidx.compose.getViewModel @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/LogLayout.kt similarity index 82% rename from app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt rename to app/src/main/java/com/vanced/manager/ui/screens/LogLayout.kt index fbb8483aa6..ebaa7abc97 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/LogLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/LogLayout.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.layouts +package com.vanced.manager.ui.screens import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.lazy.items @@ -10,9 +10,9 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Share import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import com.vanced.manager.ui.components.color.managerAccentColor -import com.vanced.manager.ui.components.color.managerSurfaceColor -import com.vanced.manager.ui.components.layout.ManagerLazyColumn +import com.vanced.manager.ui.component.color.managerAccentColor +import com.vanced.manager.ui.component.color.managerSurfaceColor +import com.vanced.manager.ui.component.layout.ManagerLazyColumn import com.vanced.manager.util.logs @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt similarity index 74% rename from app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt rename to app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt index b2c8a3fd16..923713099a 100644 --- a/app/src/main/java/com/vanced/manager/ui/layouts/SettingsLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt @@ -1,13 +1,13 @@ -package com.vanced.manager.ui.layouts +package com.vanced.manager.ui.screens import androidx.compose.runtime.Composable import androidx.compose.ui.unit.dp import com.vanced.manager.R -import com.vanced.manager.ui.components.layout.ManagerScrollableColumn +import com.vanced.manager.ui.component.layout.ManagerScrollableColumn import com.vanced.manager.ui.resources.managerString -import com.vanced.manager.ui.utils.defaultContentPaddingVertical -import com.vanced.manager.ui.widgets.layout.SettingsCategoryLayout -import com.vanced.manager.ui.widgets.settings.* +import com.vanced.manager.ui.util.defaultContentPaddingVertical +import com.vanced.manager.ui.widget.layout.SettingsCategoryLayout +import com.vanced.manager.ui.widget.screens.settings.* @Composable fun SettingsLayout() { @@ -23,7 +23,6 @@ fun SettingsLayout() { SettingsCustomTabsItem() SettingsNotificationsItem() SettingsManagerVariantItem() - } SettingsCategoryLayout( categoryName = managerString( diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Color.kt b/app/src/main/java/com/vanced/manager/ui/theme/Color.kt index 8df8e3748e..03a4b67a59 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Color.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Color.kt @@ -5,10 +5,8 @@ import androidx.compose.ui.graphics.Color val primaryColor = Color(defAccentColor) val primaryColorVariant = primaryColor.copy(alpha = 0.25f) +val darkSurface = Color.Black val darkOnSurface = Color(0xFFD5D5D5) -val lightOnSurface = Color.Black -val lightSurface = Color(0xFFE5E5E5) - -val vancedBlue = Color(0xFF2E73FF) -val vancedRed = Color(0xFFFF0032) \ No newline at end of file +val lightSurface = Color.White +val lightOnSurface = Color.Black \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt index 30f1da9b02..3005ccaf9a 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt @@ -5,13 +5,14 @@ import androidx.compose.material.MaterialTheme import androidx.compose.material.darkColors import androidx.compose.material.lightColors import androidx.compose.runtime.Composable -import com.vanced.manager.ui.preferences.holder.managerThemePref +import com.vanced.manager.preferences.holder.managerThemePref const val defAccentColor = 0xFF0477E1 private val DarkColorPalette = darkColors( primary = primaryColor, primaryVariant = primaryColorVariant, + surface = darkSurface, onSurface = darkOnSurface ) @@ -19,7 +20,7 @@ private val LightColorPalette = lightColors( primary = primaryColor, primaryVariant = primaryColorVariant, surface = lightSurface, - onSurface = lightOnSurface + onSurface = lightOnSurface, ) @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/utils/Const.kt b/app/src/main/java/com/vanced/manager/ui/util/Const.kt similarity index 77% rename from app/src/main/java/com/vanced/manager/ui/utils/Const.kt rename to app/src/main/java/com/vanced/manager/ui/util/Const.kt index 75cd4d68b0..256682442e 100644 --- a/app/src/main/java/com/vanced/manager/ui/utils/Const.kt +++ b/app/src/main/java/com/vanced/manager/ui/util/Const.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.utils +package com.vanced.manager.ui.util import androidx.compose.ui.unit.dp diff --git a/app/src/main/java/com/vanced/manager/ui/screens/Screen.kt b/app/src/main/java/com/vanced/manager/ui/util/Screen.kt similarity index 83% rename from app/src/main/java/com/vanced/manager/ui/screens/Screen.kt rename to app/src/main/java/com/vanced/manager/ui/util/Screen.kt index 0b6bfbd6ca..deba3f941a 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/Screen.kt +++ b/app/src/main/java/com/vanced/manager/ui/util/Screen.kt @@ -1,12 +1,12 @@ -package com.vanced.manager.ui.screens +package com.vanced.manager.ui.util import androidx.annotation.StringRes import androidx.compose.runtime.Composable import com.vanced.manager.R import com.vanced.manager.ui.layouts.AboutLayout -import com.vanced.manager.ui.layouts.HomeLayout -import com.vanced.manager.ui.layouts.LogLayout -import com.vanced.manager.ui.layouts.SettingsLayout +import com.vanced.manager.ui.screens.HomeLayout +import com.vanced.manager.ui.screens.LogLayout +import com.vanced.manager.ui.screens.SettingsLayout sealed class Screen( val route: String, diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt index 1d5b9885a8..d935367861 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt @@ -9,9 +9,9 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.vanced.manager.domain.model.App import com.vanced.manager.repository.JsonRepository -import com.vanced.manager.ui.preferences.holder.managerVariantPref -import com.vanced.manager.ui.preferences.holder.musicEnabled -import com.vanced.manager.ui.preferences.holder.vancedEnabled +import com.vanced.manager.preferences.holder.managerVariantPref +import com.vanced.manager.preferences.holder.musicEnabled +import com.vanced.manager.preferences.holder.vancedEnabled import kotlinx.coroutines.launch class HomeViewModel( diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerCancelButton.kt b/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerCancelButton.kt similarity index 80% rename from app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerCancelButton.kt rename to app/src/main/java/com/vanced/manager/ui/widget/button/ManagerCancelButton.kt index 47a658727e..3115b51f98 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerCancelButton.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerCancelButton.kt @@ -1,10 +1,10 @@ -package com.vanced.manager.ui.widgets.button +package com.vanced.manager.ui.widget.button import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import com.vanced.manager.R -import com.vanced.manager.ui.components.button.ManagerThemedTextButton +import com.vanced.manager.ui.component.button.ManagerThemedTextButton import com.vanced.manager.ui.resources.managerString @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerCloseButton.kt b/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerCloseButton.kt similarity index 80% rename from app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerCloseButton.kt rename to app/src/main/java/com/vanced/manager/ui/widget/button/ManagerCloseButton.kt index 524600a6df..5e292ac700 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerCloseButton.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerCloseButton.kt @@ -1,10 +1,10 @@ -package com.vanced.manager.ui.widgets.button +package com.vanced.manager.ui.widget.button import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import com.vanced.manager.R -import com.vanced.manager.ui.components.button.ManagerThemedTextButton +import com.vanced.manager.ui.component.button.ManagerThemedTextButton import com.vanced.manager.ui.resources.managerString @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerDownloadButton.kt b/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerDownloadButton.kt similarity index 80% rename from app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerDownloadButton.kt rename to app/src/main/java/com/vanced/manager/ui/widget/button/ManagerDownloadButton.kt index 8dba17b406..ba3766c61f 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerDownloadButton.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerDownloadButton.kt @@ -1,10 +1,10 @@ -package com.vanced.manager.ui.widgets.button +package com.vanced.manager.ui.widget.button import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import com.vanced.manager.R -import com.vanced.manager.ui.components.button.ManagerThemedTextButton +import com.vanced.manager.ui.component.button.ManagerThemedTextButton import com.vanced.manager.ui.resources.managerString @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerSaveButton.kt b/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerSaveButton.kt similarity index 77% rename from app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerSaveButton.kt rename to app/src/main/java/com/vanced/manager/ui/widget/button/ManagerSaveButton.kt index 8e7d3c63d2..34bb326f8e 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/button/ManagerSaveButton.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerSaveButton.kt @@ -1,12 +1,12 @@ -package com.vanced.manager.ui.widgets.button +package com.vanced.manager.ui.widget.button import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import com.vanced.manager.R -import com.vanced.manager.ui.components.button.ManagerThemedTextButton -import com.vanced.manager.ui.components.color.managerAccentColor +import com.vanced.manager.ui.component.button.ManagerThemedTextButton +import com.vanced.manager.ui.component.color.managerAccentColor import com.vanced.manager.ui.resources.managerString @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/layout/CategoryLayout.kt b/app/src/main/java/com/vanced/manager/ui/widget/layout/CategoryLayout.kt similarity index 74% rename from app/src/main/java/com/vanced/manager/ui/widgets/layout/CategoryLayout.kt rename to app/src/main/java/com/vanced/manager/ui/widget/layout/CategoryLayout.kt index e0fbb7ed39..b3ee9ab2b1 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/layout/CategoryLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/layout/CategoryLayout.kt @@ -1,12 +1,12 @@ -package com.vanced.manager.ui.widgets.layout +package com.vanced.manager.ui.widget.layout import androidx.compose.foundation.layout.* import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.Dp -import com.vanced.manager.ui.components.text.CategoryTitleText -import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal -import com.vanced.manager.ui.utils.defaultContentPaddingVertical +import com.vanced.manager.ui.component.text.CategoryTitleText +import com.vanced.manager.ui.util.defaultContentPaddingHorizontal +import com.vanced.manager.ui.util.defaultContentPaddingVertical @Composable fun CategoryLayout( diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/layout/SettingsCategoryLayout.kt b/app/src/main/java/com/vanced/manager/ui/widget/layout/SettingsCategoryLayout.kt similarity index 90% rename from app/src/main/java/com/vanced/manager/ui/widgets/layout/SettingsCategoryLayout.kt rename to app/src/main/java/com/vanced/manager/ui/widget/layout/SettingsCategoryLayout.kt index 69a9d9fdff..411c2c025f 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/layout/SettingsCategoryLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/layout/SettingsCategoryLayout.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.widgets.layout +package com.vanced.manager.ui.widget.layout import androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/AppsItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/AppsItem.kt similarity index 85% rename from app/src/main/java/com/vanced/manager/ui/widgets/home/apps/AppsItem.kt rename to app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/AppsItem.kt index 3e0f57d4f1..3e8fb35fca 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/AppsItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/AppsItem.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.widgets.home.apps +package com.vanced.manager.ui.widget.screens.home.apps import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -9,7 +9,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEach import com.vanced.manager.domain.model.App import com.vanced.manager.ui.viewmodel.HomeViewModel -import com.vanced.manager.ui.widgets.home.apps.card.AppCard +import com.vanced.manager.ui.widget.screens.home.apps.card.AppCard @Composable fun HomeAppsItem( diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppActionCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppActionCard.kt new file mode 100644 index 0000000000..015a09c8ab --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppActionCard.kt @@ -0,0 +1,94 @@ +package com.vanced.manager.ui.widget.screens.home.apps.card + +import androidx.compose.foundation.layout.* +import androidx.compose.material.LocalContentColor +import androidx.compose.material.MaterialTheme +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Info +import androidx.compose.material.icons.rounded.DeleteForever +import androidx.compose.material.icons.rounded.Download +import androidx.compose.material.icons.rounded.Launch +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.vanced.manager.R +import com.vanced.manager.ui.component.button.IconButton +import com.vanced.manager.ui.component.text.AppVersionText +import com.vanced.manager.ui.component.text.ManagerText +import com.vanced.manager.ui.util.defaultContentPaddingHorizontal + +@Composable +fun AppActionCard( + appRemoteVersion: String?, + appInstalledVersion: String?, + onInfoClick: () -> Unit, + onUninstallClick: () -> Unit, + onLaunchClick: () -> Unit, + onDownloadClick: () -> Unit, +) { + CompositionLocalProvider(LocalContentColor provides MaterialTheme.colors.onSurface) { + Row( + modifier = Modifier.padding( + horizontal = defaultContentPaddingHorizontal + ), + verticalAlignment = Alignment.CenterVertically + ) { + Column( + modifier = Modifier + .weight(1f) + .wrapContentWidth(Alignment.Start), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + ManagerText( + text = stringResource(id = R.string.app_versions) + ) + AppVersionText( + text = stringResource( + id = R.string.app_version_latest, + appRemoteVersion ?: stringResource( + id = R.string.app_content_unavailable + ) + ) + ) + AppVersionText( + text = stringResource( + id = R.string.app_version_installed, + appInstalledVersion ?: stringResource( + id = R.string.app_content_unavailable + ) + ) + ) + } + Row( + modifier = Modifier + .weight(1f) + .padding(start = 4.dp) + .wrapContentWidth(Alignment.End) + ) { + IconButton( + icon = Icons.Outlined.Info, + contentDescription = "App Info", + onClick = onInfoClick + ) + IconButton( + icon = Icons.Rounded.DeleteForever, + contentDescription = "Uninstall", + onClick = onUninstallClick + ) + IconButton( + icon = Icons.Rounded.Launch, + contentDescription = "Launch", + onClick = onLaunchClick + ) + IconButton( + icon = Icons.Rounded.Download, + contentDescription = "Install", + onClick = onDownloadClick + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppCard.kt similarity index 86% rename from app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt rename to app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppCard.kt index 417686e184..139b73ae05 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppCard.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.widgets.home.apps.card +package com.vanced.manager.ui.widget.screens.home.apps.card import androidx.compose.animation.* import androidx.compose.animation.core.tween @@ -12,15 +12,15 @@ import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp import com.google.accompanist.glide.rememberGlidePainter import com.vanced.manager.domain.model.App -import com.vanced.manager.ui.components.card.ManagerThemedCard -import com.vanced.manager.ui.components.layout.ManagerButtonColumn -import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal -import com.vanced.manager.ui.utils.defaultContentPaddingVertical +import com.vanced.manager.ui.component.card.ManagerThemedCard +import com.vanced.manager.ui.component.layout.ManagerButtonColumn +import com.vanced.manager.ui.util.defaultContentPaddingHorizontal +import com.vanced.manager.ui.util.defaultContentPaddingVertical import com.vanced.manager.ui.viewmodel.HomeViewModel -import com.vanced.manager.ui.widgets.button.ManagerCancelButton -import com.vanced.manager.ui.widgets.button.ManagerDownloadButton -import com.vanced.manager.ui.widgets.home.apps.dialog.AppChangelogDialog -import com.vanced.manager.ui.widgets.home.apps.dialog.AppDownloadDialog +import com.vanced.manager.ui.widget.button.ManagerCancelButton +import com.vanced.manager.ui.widget.button.ManagerDownloadButton +import com.vanced.manager.ui.widget.screens.home.apps.dialog.AppChangelogDialog +import com.vanced.manager.ui.widget.screens.home.apps.dialog.AppDownloadDialog import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -31,7 +31,7 @@ fun AppCard( viewModel: HomeViewModel ) { var showAppInfoDialog by rememberSaveable { mutableStateOf(false) } - var showInstallationOptions by remember { mutableStateOf(false) } + var showInstallationOptions by rememberSaveable { mutableStateOf(false) } val coroutineScope = rememberCoroutineScope { Dispatchers.IO } diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppInfoCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppInfoCard.kt similarity index 78% rename from app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppInfoCard.kt rename to app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppInfoCard.kt index 6dafdb8516..2b8405c6fa 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppInfoCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppInfoCard.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.widgets.home.apps.card +package com.vanced.manager.ui.widget.screens.home.apps.card import androidx.compose.foundation.Image import androidx.compose.foundation.layout.padding @@ -9,11 +9,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.google.accompanist.imageloading.ImageLoadState import com.google.accompanist.imageloading.LoadPainter -import com.vanced.manager.ui.components.card.ManagerCard -import com.vanced.manager.ui.components.list.ManagerListItem -import com.vanced.manager.ui.components.modifier.managerPlaceholder -import com.vanced.manager.ui.components.text.ManagerText -import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal +import com.vanced.manager.ui.component.card.ManagerCard +import com.vanced.manager.ui.component.list.ManagerListItem +import com.vanced.manager.ui.component.modifier.managerPlaceholder +import com.vanced.manager.ui.component.text.ManagerText +import com.vanced.manager.ui.util.defaultContentPaddingHorizontal @Composable fun AppInfoCard( diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppChangelogDialog.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/dialog/AppChangelogDialog.kt similarity index 77% rename from app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppChangelogDialog.kt rename to app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/dialog/AppChangelogDialog.kt index fff490475c..aeaec0b02a 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppChangelogDialog.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/dialog/AppChangelogDialog.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.widgets.home.apps.dialog +package com.vanced.manager.ui.widget.screens.home.apps.dialog import androidx.compose.foundation.layout.padding import androidx.compose.material.MaterialTheme @@ -6,10 +6,10 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.vanced.manager.R -import com.vanced.manager.ui.components.dialog.ManagerDialog -import com.vanced.manager.ui.components.text.ManagerText +import com.vanced.manager.ui.component.dialog.ManagerDialog +import com.vanced.manager.ui.component.text.ManagerText import com.vanced.manager.ui.resources.managerString -import com.vanced.manager.ui.widgets.button.ManagerCloseButton +import com.vanced.manager.ui.widget.button.ManagerCloseButton @Composable fun AppChangelogDialog( diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppDownloadDialog.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/dialog/AppDownloadDialog.kt similarity index 68% rename from app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppDownloadDialog.kt rename to app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/dialog/AppDownloadDialog.kt index fca9fdf9d9..e96c866820 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/dialog/AppDownloadDialog.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/dialog/AppDownloadDialog.kt @@ -1,10 +1,10 @@ -package com.vanced.manager.ui.widgets.home.apps.dialog +package com.vanced.manager.ui.widget.screens.home.apps.dialog import androidx.compose.runtime.Composable import com.vanced.manager.downloader.base.AppDownloader -import com.vanced.manager.ui.components.dialog.ManagerDialog -import com.vanced.manager.ui.widgets.button.ManagerCancelButton -import com.vanced.manager.ui.widgets.home.download.AppDownloadDialogProgress +import com.vanced.manager.ui.component.dialog.ManagerDialog +import com.vanced.manager.ui.widget.button.ManagerCancelButton +import com.vanced.manager.ui.widget.screens.home.download.AppDownloadDialogProgress @Composable fun AppDownloadDialog( diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/download/AppDownloadDialogProgress.kt similarity index 90% rename from app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt rename to app/src/main/java/com/vanced/manager/ui/widget/screens/home/download/AppDownloadDialogProgress.kt index 4f968934b9..dd7636cd5f 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/download/AppDownloadDialogProgress.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/download/AppDownloadDialogProgress.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.widgets.home.download +package com.vanced.manager.ui.widget.screens.home.download import androidx.compose.animation.core.animateIntAsState import androidx.compose.foundation.layout.Row @@ -11,7 +11,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.vanced.manager.R -import com.vanced.manager.ui.components.progressindicator.ManagerProgressIndicator +import com.vanced.manager.ui.component.progressindicator.ManagerProgressIndicator import com.vanced.manager.ui.resources.managerString @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/CheckboxInstallationOption.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/CheckboxInstallationOption.kt similarity index 65% rename from app/src/main/java/com/vanced/manager/ui/widgets/home/installation/CheckboxInstallationOption.kt rename to app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/CheckboxInstallationOption.kt index 34b8ec1f60..d76a4b0b1e 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/CheckboxInstallationOption.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/CheckboxInstallationOption.kt @@ -1,9 +1,9 @@ -package com.vanced.manager.ui.widgets.home.installation +package com.vanced.manager.ui.widget.screens.home.installation import androidx.annotation.StringRes -import com.vanced.manager.ui.components.preference.CheckboxDialogPreference -import com.vanced.manager.ui.preferences.CheckboxPreference -import com.vanced.manager.ui.preferences.ManagerPreference +import com.vanced.manager.ui.component.preference.CheckboxDialogPreference +import com.vanced.manager.preferences.CheckboxPreference +import com.vanced.manager.preferences.ManagerPreference import com.vanced.manager.ui.resources.managerString data class CheckboxInstallationOption( diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/InstallationOption.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/InstallationOption.kt similarity index 64% rename from app/src/main/java/com/vanced/manager/ui/widgets/home/installation/InstallationOption.kt rename to app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/InstallationOption.kt index 5c3601ffe2..1a3a6fa119 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/InstallationOption.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/InstallationOption.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.widgets.home.installation +package com.vanced.manager.ui.widget.screens.home.installation import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/RadiobuttonInstallationOption.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/RadiobuttonInstallationOption.kt similarity index 65% rename from app/src/main/java/com/vanced/manager/ui/widgets/home/installation/RadiobuttonInstallationOption.kt rename to app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/RadiobuttonInstallationOption.kt index be03278057..36b60e1c30 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/installation/RadiobuttonInstallationOption.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/RadiobuttonInstallationOption.kt @@ -1,9 +1,9 @@ -package com.vanced.manager.ui.widgets.home.installation +package com.vanced.manager.ui.widget.screens.home.installation import androidx.annotation.StringRes -import com.vanced.manager.ui.components.preference.RadiobuttonDialogPreference -import com.vanced.manager.ui.preferences.ManagerPreference -import com.vanced.manager.ui.preferences.RadioButtonPreference +import com.vanced.manager.ui.component.preference.RadiobuttonDialogPreference +import com.vanced.manager.preferences.ManagerPreference +import com.vanced.manager.preferences.RadioButtonPreference import com.vanced.manager.ui.resources.managerString data class RadiobuttonInstallationOption( diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/socialmedia/SocialMediaItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/socialmedia/SocialMediaItem.kt similarity index 64% rename from app/src/main/java/com/vanced/manager/ui/widgets/home/socialmedia/SocialMediaItem.kt rename to app/src/main/java/com/vanced/manager/ui/widget/screens/home/socialmedia/SocialMediaItem.kt index 4fa6ed78bc..3b96427c1e 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/socialmedia/SocialMediaItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/socialmedia/SocialMediaItem.kt @@ -1,8 +1,8 @@ -package com.vanced.manager.ui.widgets.home.socialmedia +package com.vanced.manager.ui.widget.screens.home.socialmedia import androidx.compose.runtime.Composable -import com.vanced.manager.ui.components.card.ManagerLinkCard -import com.vanced.manager.ui.components.layout.ScrollableItemRow +import com.vanced.manager.ui.component.card.ManagerLinkCard +import com.vanced.manager.ui.component.layout.ScrollableItemRow import com.vanced.manager.util.socialMedia @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/sponsors/SponsorsItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/sponsors/SponsorsItem.kt similarity index 63% rename from app/src/main/java/com/vanced/manager/ui/widgets/home/sponsors/SponsorsItem.kt rename to app/src/main/java/com/vanced/manager/ui/widget/screens/home/sponsors/SponsorsItem.kt index 0cc4aa3a0f..45332625e3 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/sponsors/SponsorsItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/sponsors/SponsorsItem.kt @@ -1,8 +1,8 @@ -package com.vanced.manager.ui.widgets.home.sponsors +package com.vanced.manager.ui.widget.screens.home.sponsors import androidx.compose.runtime.Composable -import com.vanced.manager.ui.components.card.ManagerLinkCard -import com.vanced.manager.ui.components.layout.ScrollableItemRow +import com.vanced.manager.ui.component.card.ManagerLinkCard +import com.vanced.manager.ui.component.layout.ScrollableItemRow import com.vanced.manager.util.sponsors @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/settings/AccentColorItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt similarity index 73% rename from app/src/main/java/com/vanced/manager/ui/widgets/settings/AccentColorItem.kt rename to app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt index c0706d1ecd..3d4cd1bcd6 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/settings/AccentColorItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt @@ -1,13 +1,13 @@ -package com.vanced.manager.ui.widgets.settings +package com.vanced.manager.ui.widget.screens.settings import androidx.compose.runtime.* import androidx.compose.ui.graphics.Color import com.vanced.manager.R -import com.vanced.manager.ui.components.color.ManagerColorPicker -import com.vanced.manager.ui.components.preference.DialogPreference -import com.vanced.manager.ui.preferences.holder.managerAccentColorPref +import com.vanced.manager.ui.component.color.ManagerColorPicker +import com.vanced.manager.ui.component.preference.DialogPreference +import com.vanced.manager.preferences.holder.managerAccentColorPref import com.vanced.manager.ui.resources.managerString -import com.vanced.manager.ui.widgets.button.ManagerSaveButton +import com.vanced.manager.ui.widget.button.ManagerSaveButton @Composable fun SettingsAccentColorItem() { diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/settings/ClearFilesItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ClearFilesItem.kt similarity index 76% rename from app/src/main/java/com/vanced/manager/ui/widgets/settings/ClearFilesItem.kt rename to app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ClearFilesItem.kt index 0c1163e849..57cb4ed4bc 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/settings/ClearFilesItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ClearFilesItem.kt @@ -1,8 +1,8 @@ -package com.vanced.manager.ui.widgets.settings +package com.vanced.manager.ui.widget.screens.settings import androidx.compose.runtime.Composable import com.vanced.manager.R -import com.vanced.manager.ui.components.preference.Preference +import com.vanced.manager.ui.component.preference.Preference import com.vanced.manager.ui.resources.managerString @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/settings/CustomTabsItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/CustomTabsItem.kt similarity index 70% rename from app/src/main/java/com/vanced/manager/ui/widgets/settings/CustomTabsItem.kt rename to app/src/main/java/com/vanced/manager/ui/widget/screens/settings/CustomTabsItem.kt index 1408bbf1c5..10e57d780f 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/settings/CustomTabsItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/CustomTabsItem.kt @@ -1,10 +1,10 @@ -package com.vanced.manager.ui.widgets.settings +package com.vanced.manager.ui.widget.screens.settings import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import com.vanced.manager.R -import com.vanced.manager.ui.components.preference.CheckboxPreference -import com.vanced.manager.ui.preferences.holder.useCustomTabsPref +import com.vanced.manager.ui.component.preference.CheckboxPreference +import com.vanced.manager.preferences.holder.useCustomTabsPref @Composable fun SettingsCustomTabsItem() { diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/settings/ManagerVariantItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt similarity index 71% rename from app/src/main/java/com/vanced/manager/ui/widgets/settings/ManagerVariantItem.kt rename to app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt index a37e86f824..3b3c811f6e 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/settings/ManagerVariantItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt @@ -1,10 +1,10 @@ -package com.vanced.manager.ui.widgets.settings +package com.vanced.manager.ui.widget.screens.settings import androidx.compose.runtime.Composable import com.vanced.manager.R -import com.vanced.manager.ui.components.preference.RadiobuttonDialogPreference -import com.vanced.manager.ui.preferences.RadioButtonPreference -import com.vanced.manager.ui.preferences.holder.managerVariantPref +import com.vanced.manager.ui.component.preference.RadiobuttonDialogPreference +import com.vanced.manager.preferences.RadioButtonPreference +import com.vanced.manager.preferences.holder.managerVariantPref import com.vanced.manager.ui.resources.managerString @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/settings/NotificationsItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/NotificationsItem.kt similarity index 75% rename from app/src/main/java/com/vanced/manager/ui/widgets/settings/NotificationsItem.kt rename to app/src/main/java/com/vanced/manager/ui/widget/screens/settings/NotificationsItem.kt index 5391a6fa0d..b79d33813a 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/settings/NotificationsItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/NotificationsItem.kt @@ -1,8 +1,8 @@ -package com.vanced.manager.ui.widgets.settings +package com.vanced.manager.ui.widget.screens.settings import androidx.compose.runtime.Composable -import com.vanced.manager.ui.components.preference.CheckboxPreference -import com.vanced.manager.ui.preferences.managerBooleanPreference +import com.vanced.manager.ui.component.preference.CheckboxPreference +import com.vanced.manager.preferences.managerBooleanPreference import com.vanced.manager.util.notificationApps @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/settings/ThemeItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt similarity index 77% rename from app/src/main/java/com/vanced/manager/ui/widgets/settings/ThemeItem.kt rename to app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt index d0dccda88d..ffadf0d244 100644 --- a/app/src/main/java/com/vanced/manager/ui/widgets/settings/ThemeItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt @@ -1,10 +1,10 @@ -package com.vanced.manager.ui.widgets.settings +package com.vanced.manager.ui.widget.screens.settings import androidx.compose.runtime.Composable import com.vanced.manager.R -import com.vanced.manager.ui.components.preference.RadiobuttonDialogPreference -import com.vanced.manager.ui.preferences.RadioButtonPreference -import com.vanced.manager.ui.preferences.holder.managerThemePref +import com.vanced.manager.ui.component.preference.RadiobuttonDialogPreference +import com.vanced.manager.preferences.RadioButtonPreference +import com.vanced.manager.preferences.holder.managerThemePref import com.vanced.manager.ui.resources.managerString @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt b/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt deleted file mode 100644 index 73278eec74..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widgets/home/apps/card/AppActionCard.kt +++ /dev/null @@ -1,89 +0,0 @@ -package com.vanced.manager.ui.widgets.home.apps.card - -import androidx.compose.foundation.layout.* -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Info -import androidx.compose.material.icons.rounded.DeleteForever -import androidx.compose.material.icons.rounded.Download -import androidx.compose.material.icons.rounded.Launch -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.vanced.manager.R -import com.vanced.manager.ui.components.button.IconButton -import com.vanced.manager.ui.components.text.AppVersionText -import com.vanced.manager.ui.components.text.ManagerText -import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal - -@Composable -fun AppActionCard( - appRemoteVersion: String?, - appInstalledVersion: String?, - onInfoClick: () -> Unit, - onUninstallClick: () -> Unit, - onLaunchClick: () -> Unit, - onDownloadClick: () -> Unit, -) { - Row( - modifier = Modifier.padding( - horizontal = defaultContentPaddingHorizontal - ), - verticalAlignment = Alignment.CenterVertically - ) { - Column( - modifier = Modifier - .weight(1f) - .wrapContentWidth(Alignment.Start), - verticalArrangement = Arrangement.spacedBy(4.dp) - ) { - ManagerText( - text = stringResource(id = R.string.app_versions) - ) - AppVersionText( - text = stringResource( - id = R.string.app_version_latest, - appRemoteVersion ?: stringResource( - id = R.string.app_content_unavailable - ) - ) - ) - AppVersionText( - text = stringResource( - id = R.string.app_version_installed, - appInstalledVersion ?: stringResource( - id = R.string.app_content_unavailable - ) - ) - ) - } - Row( - modifier = Modifier - .weight(1f) - .padding(start = 4.dp) - .wrapContentWidth(Alignment.End) - ) { - IconButton( - icon = Icons.Outlined.Info, - contentDescription = "App Info", - onClick = onInfoClick - ) - IconButton( - icon = Icons.Rounded.DeleteForever, - contentDescription = "Uninstall", - onClick = onUninstallClick - ) - IconButton( - icon = Icons.Rounded.Launch, - contentDescription = "Launch", - onClick = onLaunchClick - ) - IconButton( - icon = Icons.Rounded.Download, - contentDescription = "Install", - onClick = onDownloadClick - ) - } - } -} \ No newline at end of file From c443d0f61e06d8a473f9b2542c2c58ee05cdedd7 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 12 Jul 2021 20:33:46 +0400 Subject: [PATCH 029/118] installer fixes --- .../manager/network/model/AppDtoMapper.kt | 18 +++++++++++++++++- .../ManagerProgressIndicator.kt | 10 +++------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt index 0685cd666a..f0f2102c97 100644 --- a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt +++ b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt @@ -5,6 +5,11 @@ import com.vanced.manager.domain.datasource.PackageInformationDataSource import com.vanced.manager.domain.model.App import com.vanced.manager.domain.model.AppStatus import com.vanced.manager.domain.util.EntityMapper +import com.vanced.manager.downloader.base.AppDownloader +import com.vanced.manager.downloader.impl.MicrogDownloader +import com.vanced.manager.downloader.impl.MusicDownloader +import com.vanced.manager.downloader.impl.VancedDownloader +import com.vanced.manager.network.util.MICROG_NAME import com.vanced.manager.network.util.MUSIC_NAME import com.vanced.manager.network.util.VANCED_NAME import com.vanced.manager.preferences.CheckboxPreference @@ -16,11 +21,13 @@ import com.vanced.manager.preferences.holder.vancedVersionPref import com.vanced.manager.ui.widget.screens.home.installation.CheckboxInstallationOption import com.vanced.manager.ui.widget.screens.home.installation.InstallationOption import com.vanced.manager.ui.widget.screens.home.installation.RadiobuttonInstallationOption +import org.koin.core.component.KoinComponent +import org.koin.core.component.get import java.util.* class AppDtoMapper( private val packageInformationDataSource: PackageInformationDataSource -) : EntityMapper<AppDto, App> { +) : EntityMapper<AppDto, App>, KoinComponent { override suspend fun mapToModel(entity: AppDto): App = with (entity) { @@ -46,6 +53,7 @@ class AppDtoMapper( versions = versions, themes = themes, languages = languages, + downloader = getDownloader(name), installationOptions = getInstallationOptions(entity) ) } @@ -109,4 +117,12 @@ class AppDtoMapper( ) else -> null } + + private fun getDownloader(app: String?): AppDownloader? = + when (app) { + VANCED_NAME -> get<VancedDownloader>() + MUSIC_NAME -> get<MusicDownloader>() + MICROG_NAME -> get<MicrogDownloader>() + else -> null + } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/progressindicator/ManagerProgressIndicator.kt b/app/src/main/java/com/vanced/manager/ui/component/progressindicator/ManagerProgressIndicator.kt index 2aa10cfc0f..74e53e6bf5 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/progressindicator/ManagerProgressIndicator.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/progressindicator/ManagerProgressIndicator.kt @@ -15,13 +15,9 @@ import androidx.compose.ui.unit.dp import com.vanced.manager.ui.component.color.managerAccentColor private val progressBarModifier = Modifier.composed { - then( - height(5.dp) - ).then( - fillMaxWidth() - ).then( - clip(MaterialTheme.shapes.medium) - ) + then(height(5.dp)) + .then(fillMaxWidth()) + .then(clip(MaterialTheme.shapes.medium)) } @Composable From e54ecb466c7b221f8c4749c800a12fa603656229 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Fri, 16 Jul 2021 00:45:52 +0400 Subject: [PATCH 030/118] dep updates --- app/build.gradle.kts | 5 +++-- .../ui/widget/screens/home/apps/card/AppCard.kt | 7 +++---- .../widget/screens/home/apps/card/AppInfoCard.kt | 15 +++++++++------ buildSrc/src/main/java/Dependencies.kt | 6 +++--- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index bdcc28ea4d..c4de82ec3d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -103,15 +103,16 @@ dependencies { implementation("androidx.preference:preference-ktx:1.1.1") - implementation("androidx.activity:activity-compose:1.3.0-rc01") + implementation("androidx.activity:activity-compose:1.3.0-rc02") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-alpha02") implementation("androidx.navigation:navigation-compose:2.4.0-alpha04") - implementation("com.google.accompanist:accompanist-glide:$accompanistVersion") implementation("com.google.accompanist:accompanist-swiperefresh:$accompanistVersion") implementation("com.google.accompanist:accompanist-systemuicontroller:$accompanistVersion") implementation("com.google.accompanist:accompanist-placeholder-material:$accompanistVersion") + implementation("io.coil-kt:coil-compose:1.3.0") + implementation("com.github.skydoves:orchestra-colorpicker:$orchestraVersion") implementation("io.insert-koin:koin-android:$koinVersion") diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppCard.kt index 139b73ae05..c7f09657be 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppCard.kt @@ -10,7 +10,7 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp -import com.google.accompanist.glide.rememberGlidePainter +import coil.compose.rememberImagePainter import com.vanced.manager.domain.model.App import com.vanced.manager.ui.component.card.ManagerThemedCard import com.vanced.manager.ui.component.layout.ManagerButtonColumn @@ -35,9 +35,8 @@ fun AppCard( val coroutineScope = rememberCoroutineScope { Dispatchers.IO } - val icon = rememberGlidePainter( - request = app.iconUrl ?: "", - fadeIn = true + val icon = rememberImagePainter( + data = app.iconUrl ) val hasInstallationOptions = app.installationOptions != null diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppInfoCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppInfoCard.kt index 2b8405c6fa..2cb4bd8f68 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppInfoCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppInfoCard.kt @@ -1,24 +1,27 @@ package com.vanced.manager.ui.widget.screens.home.apps.card import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import com.google.accompanist.imageloading.ImageLoadState -import com.google.accompanist.imageloading.LoadPainter +import coil.annotation.ExperimentalCoilApi +import coil.compose.ImagePainter import com.vanced.manager.ui.component.card.ManagerCard import com.vanced.manager.ui.component.list.ManagerListItem import com.vanced.manager.ui.component.modifier.managerPlaceholder import com.vanced.manager.ui.component.text.ManagerText import com.vanced.manager.ui.util.defaultContentPaddingHorizontal +@OptIn(ExperimentalCoilApi::class) @Composable fun AppInfoCard( appName: String?, - icon: LoadPainter<Any>, + icon: ImagePainter, ) { ManagerCard { ManagerListItem( @@ -35,11 +38,11 @@ fun AppInfoCard( }, icon = { Image( + modifier = Modifier + .size(48.dp) + .managerPlaceholder(icon.state is ImagePainter.State.Loading), painter = icon, contentDescription = "", - modifier = Modifier - .size(48.dp, 48.dp) - .managerPlaceholder(icon.loadState is ImageLoadState.Loading) ) } ) diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt index 4cf499ad9f..6e08a53544 100644 --- a/buildSrc/src/main/java/Dependencies.kt +++ b/buildSrc/src/main/java/Dependencies.kt @@ -1,8 +1,8 @@ object Dependencies { - const val accompanistVersion = "0.12.0" - const val composeVersion = "1.0.0-rc01" - const val koinVersion = "3.1.0" + const val accompanistVersion = "0.14.0" + const val composeVersion = "1.0.0-rc02" + const val koinVersion = "3.1.2" const val retrofitVersion = "2.9.0" const val orchestraVersion = "1.0.7" From 83167e4fc06d7e3be4c2e51f85c9f718aa20b4eb Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Fri, 16 Jul 2021 00:47:33 +0400 Subject: [PATCH 031/118] cleanup --- app/src/main/java/com/vanced/manager/di/MapperModule.kt | 1 - .../com/vanced/manager/downloader/impl/MusicDownloader.kt | 1 - app/src/main/java/com/vanced/manager/ui/MainActivity.kt | 2 +- .../manager/ui/component/preference/CheckboxPreference.kt | 2 +- .../ui/component/preference/RadiobuttonDialogPreference.kt | 2 +- .../main/java/com/vanced/manager/ui/screens/HomeLayout.kt | 2 +- .../java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt | 2 +- .../manager/ui/widget/screens/home/apps/card/AppCard.kt | 5 ++++- .../manager/ui/widget/screens/home/apps/card/AppInfoCard.kt | 2 -- .../screens/home/installation/CheckboxInstallationOption.kt | 2 +- .../home/installation/RadiobuttonInstallationOption.kt | 2 +- .../manager/ui/widget/screens/settings/AccentColorItem.kt | 2 +- .../manager/ui/widget/screens/settings/CustomTabsItem.kt | 2 +- .../manager/ui/widget/screens/settings/ManagerVariantItem.kt | 2 +- .../manager/ui/widget/screens/settings/NotificationsItem.kt | 2 +- .../vanced/manager/ui/widget/screens/settings/ThemeItem.kt | 2 +- 16 files changed, 16 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/di/MapperModule.kt b/app/src/main/java/com/vanced/manager/di/MapperModule.kt index 0295702c79..72aad51bb8 100644 --- a/app/src/main/java/com/vanced/manager/di/MapperModule.kt +++ b/app/src/main/java/com/vanced/manager/di/MapperModule.kt @@ -1,7 +1,6 @@ package com.vanced.manager.di import com.vanced.manager.domain.datasource.PackageInformationDataSource -import com.vanced.manager.downloader.impl.VancedDownloader import com.vanced.manager.network.model.AppDtoMapper import com.vanced.manager.network.model.JsonDtoMapper import org.koin.dsl.module diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt index c9a3e4b9bc..24e66a3aa7 100644 --- a/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt @@ -3,7 +3,6 @@ package com.vanced.manager.downloader.impl import com.vanced.manager.domain.model.App import com.vanced.manager.downloader.base.AppDownloader import com.vanced.manager.installer.MusicInstaller -import com.vanced.manager.installer.VancedInstaller import com.vanced.manager.ui.viewmodel.HomeViewModel class MusicDownloader( diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index b656e90bd6..54a755b8c4 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -25,9 +25,9 @@ import com.vanced.manager.ui.component.color.managerTextColor import com.vanced.manager.ui.component.menu.ManagerDropdownMenuItem import com.vanced.manager.ui.component.text.ToolbarTitleText import com.vanced.manager.ui.resources.managerString -import com.vanced.manager.ui.util.Screen import com.vanced.manager.ui.theme.ManagerTheme import com.vanced.manager.ui.theme.isDark +import com.vanced.manager.ui.util.Screen class MainActivity : ComponentActivity() { diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt index e65be4c9b0..d08608e0c1 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt @@ -3,8 +3,8 @@ package com.vanced.manager.ui.component.preference import androidx.compose.runtime.Composable import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.component.checkbox.ManagerCheckbox import com.vanced.manager.preferences.ManagerPreference +import com.vanced.manager.ui.component.checkbox.ManagerCheckbox import kotlinx.coroutines.launch @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt index c64e2a2730..ea7da32ca7 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt @@ -6,9 +6,9 @@ import androidx.compose.foundation.lazy.items import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.component.list.RadiobuttonItem import com.vanced.manager.preferences.ManagerPreference import com.vanced.manager.preferences.RadioButtonPreference +import com.vanced.manager.ui.component.list.RadiobuttonItem import com.vanced.manager.ui.widget.button.ManagerSaveButton import kotlinx.coroutines.launch diff --git a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt index fabcf5a567..6831066756 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt @@ -12,10 +12,10 @@ import com.vanced.manager.ui.component.layout.ManagerSwipeRefresh import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.util.defaultContentPaddingVertical import com.vanced.manager.ui.viewmodel.HomeViewModel +import com.vanced.manager.ui.widget.layout.CategoryLayout import com.vanced.manager.ui.widget.screens.home.apps.HomeAppsItem import com.vanced.manager.ui.widget.screens.home.socialmedia.HomeSocialMediaItem import com.vanced.manager.ui.widget.screens.home.sponsors.HomeSponsorsItem -import com.vanced.manager.ui.widget.layout.CategoryLayout import org.koin.androidx.compose.getViewModel @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt index d935367861..43192e589d 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt @@ -8,10 +8,10 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.vanced.manager.domain.model.App -import com.vanced.manager.repository.JsonRepository import com.vanced.manager.preferences.holder.managerVariantPref import com.vanced.manager.preferences.holder.musicEnabled import com.vanced.manager.preferences.holder.vancedEnabled +import com.vanced.manager.repository.JsonRepository import kotlinx.coroutines.launch class HomeViewModel( diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppCard.kt index c7f09657be..1333437a92 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppCard.kt @@ -1,7 +1,10 @@ package com.vanced.manager.ui.widget.screens.home.apps.card -import androidx.compose.animation.* +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.core.tween +import androidx.compose.animation.expandVertically +import androidx.compose.animation.shrinkVertically import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppInfoCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppInfoCard.kt index 2cb4bd8f68..f765ed094a 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppInfoCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppInfoCard.kt @@ -1,8 +1,6 @@ package com.vanced.manager.ui.widget.screens.home.apps.card import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.material.MaterialTheme diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/CheckboxInstallationOption.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/CheckboxInstallationOption.kt index d76a4b0b1e..bc7d703aaa 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/CheckboxInstallationOption.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/CheckboxInstallationOption.kt @@ -1,9 +1,9 @@ package com.vanced.manager.ui.widget.screens.home.installation import androidx.annotation.StringRes -import com.vanced.manager.ui.component.preference.CheckboxDialogPreference import com.vanced.manager.preferences.CheckboxPreference import com.vanced.manager.preferences.ManagerPreference +import com.vanced.manager.ui.component.preference.CheckboxDialogPreference import com.vanced.manager.ui.resources.managerString data class CheckboxInstallationOption( diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/RadiobuttonInstallationOption.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/RadiobuttonInstallationOption.kt index 36b60e1c30..58bd616667 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/RadiobuttonInstallationOption.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/RadiobuttonInstallationOption.kt @@ -1,9 +1,9 @@ package com.vanced.manager.ui.widget.screens.home.installation import androidx.annotation.StringRes -import com.vanced.manager.ui.component.preference.RadiobuttonDialogPreference import com.vanced.manager.preferences.ManagerPreference import com.vanced.manager.preferences.RadioButtonPreference +import com.vanced.manager.ui.component.preference.RadiobuttonDialogPreference import com.vanced.manager.ui.resources.managerString data class RadiobuttonInstallationOption( diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt index 3d4cd1bcd6..3eb1933d6a 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt @@ -3,9 +3,9 @@ package com.vanced.manager.ui.widget.screens.settings import androidx.compose.runtime.* import androidx.compose.ui.graphics.Color import com.vanced.manager.R +import com.vanced.manager.preferences.holder.managerAccentColorPref import com.vanced.manager.ui.component.color.ManagerColorPicker import com.vanced.manager.ui.component.preference.DialogPreference -import com.vanced.manager.preferences.holder.managerAccentColorPref import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.widget.button.ManagerSaveButton diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/CustomTabsItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/CustomTabsItem.kt index 10e57d780f..8cc6d31ab1 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/CustomTabsItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/CustomTabsItem.kt @@ -3,8 +3,8 @@ package com.vanced.manager.ui.widget.screens.settings import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import com.vanced.manager.R -import com.vanced.manager.ui.component.preference.CheckboxPreference import com.vanced.manager.preferences.holder.useCustomTabsPref +import com.vanced.manager.ui.component.preference.CheckboxPreference @Composable fun SettingsCustomTabsItem() { diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt index 3b3c811f6e..bf5cc30dcb 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt @@ -2,9 +2,9 @@ package com.vanced.manager.ui.widget.screens.settings import androidx.compose.runtime.Composable import com.vanced.manager.R -import com.vanced.manager.ui.component.preference.RadiobuttonDialogPreference import com.vanced.manager.preferences.RadioButtonPreference import com.vanced.manager.preferences.holder.managerVariantPref +import com.vanced.manager.ui.component.preference.RadiobuttonDialogPreference import com.vanced.manager.ui.resources.managerString @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/NotificationsItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/NotificationsItem.kt index b79d33813a..86f11ae440 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/NotificationsItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/NotificationsItem.kt @@ -1,8 +1,8 @@ package com.vanced.manager.ui.widget.screens.settings import androidx.compose.runtime.Composable -import com.vanced.manager.ui.component.preference.CheckboxPreference import com.vanced.manager.preferences.managerBooleanPreference +import com.vanced.manager.ui.component.preference.CheckboxPreference import com.vanced.manager.util.notificationApps @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt index ffadf0d244..c77ec5146e 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt @@ -2,9 +2,9 @@ package com.vanced.manager.ui.widget.screens.settings import androidx.compose.runtime.Composable import com.vanced.manager.R -import com.vanced.manager.ui.component.preference.RadiobuttonDialogPreference import com.vanced.manager.preferences.RadioButtonPreference import com.vanced.manager.preferences.holder.managerThemePref +import com.vanced.manager.ui.component.preference.RadiobuttonDialogPreference import com.vanced.manager.ui.resources.managerString @Composable From 41bb2db71ca057dc56ac69496cdf8c42052a904b Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Fri, 16 Jul 2021 00:58:23 +0400 Subject: [PATCH 032/118] adjusted about screen --- .../manager/ui/component/text/ManagerText.kt | 18 +++++++++++ .../vanced/manager/ui/screens/AboutLayout.kt | 32 ++++++++++--------- .../java/com/vanced/manager/ui/util/Screen.kt | 2 +- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/component/text/ManagerText.kt b/app/src/main/java/com/vanced/manager/ui/component/text/ManagerText.kt index 9a94ab8742..188676f177 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/text/ManagerText.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/text/ManagerText.kt @@ -5,6 +5,7 @@ import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.TextAlign @@ -23,4 +24,21 @@ fun ManagerText( style = textStyle, textAlign = textAlign ) +} + +@Composable +fun ManagerText( + modifier: Modifier = Modifier, + color: Color = Color.Unspecified, + textStyle: TextStyle = LocalTextStyle.current, + textAlign: TextAlign? = null, + text: AnnotatedString, +) { + Text( + modifier = modifier, + text = text, + color = color, + style = textStyle, + textAlign = textAlign + ) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt index a4067d9f19..8ac5454a10 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt @@ -1,11 +1,12 @@ -package com.vanced.manager.ui.layouts +package com.vanced.manager.ui.screens import androidx.annotation.DrawableRes import androidx.annotation.StringRes +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -14,7 +15,6 @@ import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import androidx.compose.ui.util.fastForEach import com.vanced.manager.R import com.vanced.manager.ui.component.card.ManagerLinkCard @@ -24,6 +24,7 @@ import com.vanced.manager.ui.component.layout.ScrollableItemRow import com.vanced.manager.ui.component.list.ManagerListItem import com.vanced.manager.ui.component.text.ManagerText import com.vanced.manager.ui.resources.managerString +import com.vanced.manager.ui.util.defaultContentPaddingVertical import com.vanced.manager.ui.widget.layout.CategoryLayout data class Person( @@ -166,18 +167,21 @@ fun AboutLayout() { @Composable fun AboutManagerCard() { - ManagerThemedCard { + ManagerThemedCard( + modifier = Modifier.fillMaxWidth() + ) { Column( - modifier = Modifier, - horizontalAlignment = Alignment.CenterHorizontally + modifier = Modifier.padding(vertical = defaultContentPaddingVertical), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(4.dp) ) { - Text( - text = managerString(stringId = R.string.app_name), - modifier = Modifier - .padding(top = 8.dp), - fontSize = 30.sp, + ManagerText( + modifier = Modifier, + text = managerString(R.string.app_name), + textStyle = MaterialTheme.typography.h1 ) - Text( + ManagerText( + modifier = Modifier, text = buildAnnotatedString { append("Re") withStyle(style = SpanStyle(Color(0xFFBBB529))) { @@ -185,9 +189,7 @@ fun AboutManagerCard() { } append("d") }, - modifier = Modifier - .padding(bottom = 8.dp), - fontSize = 16.sp, + textStyle = MaterialTheme.typography.h5 ) } } diff --git a/app/src/main/java/com/vanced/manager/ui/util/Screen.kt b/app/src/main/java/com/vanced/manager/ui/util/Screen.kt index deba3f941a..ca716056ff 100644 --- a/app/src/main/java/com/vanced/manager/ui/util/Screen.kt +++ b/app/src/main/java/com/vanced/manager/ui/util/Screen.kt @@ -3,7 +3,7 @@ package com.vanced.manager.ui.util import androidx.annotation.StringRes import androidx.compose.runtime.Composable import com.vanced.manager.R -import com.vanced.manager.ui.layouts.AboutLayout +import com.vanced.manager.ui.screens.AboutLayout import com.vanced.manager.ui.screens.HomeLayout import com.vanced.manager.ui.screens.LogLayout import com.vanced.manager.ui.screens.SettingsLayout From 5726e4e0ad46b097eca68b4ed3ca76c9b752982a Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Fri, 16 Jul 2021 01:08:11 +0400 Subject: [PATCH 033/118] fixed live accent color --- .../vanced/manager/ui/component/checkbox/ManagerCheckbox.kt | 6 +++--- .../com/vanced/manager/ui/component/color/ManagerColors.kt | 3 +-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt b/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt index f9dd90fc54..f793ea0ad8 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt @@ -20,6 +20,7 @@ import com.vanced.manager.ui.component.color.contentColorForColor import com.vanced.manager.ui.component.color.managerAccentColor import com.vanced.manager.ui.component.color.managerAnimatedColor import com.vanced.manager.ui.component.color.managerThemedCardColor +import com.vanced.manager.util.log @SuppressLint("UnusedTransitionTargetStateParameter") @Composable @@ -29,12 +30,11 @@ fun ManagerCheckbox( shape: Shape = MaterialTheme.shapes.medium, onCheckedChange: (isChecked: Boolean) -> Unit ) { - val accentColor = managerAccentColor() val transition = updateTransition(targetState = isChecked, label = "Checked") val cardSize by transition.springAnimation(initialValue = size, label = "Checkbox Size") val iconSize = cardSize / 1.6f - val cardColor = managerAnimatedColor(if (isChecked) accentColor else managerThemedCardColor()) - val iconTint = managerAnimatedColor(if (isChecked) contentColorForColor(cardColor) else accentColor) + val cardColor = managerAnimatedColor(if (isChecked) managerAccentColor() else managerThemedCardColor()) + val iconTint = managerAnimatedColor(if (isChecked) contentColorForColor(cardColor) else managerAccentColor()) ManagerCard( modifier = Modifier.size(cardSize), diff --git a/app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt b/app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt index 6a60bbde95..f2762ad147 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt @@ -4,7 +4,6 @@ import androidx.compose.animation.animateColorAsState import androidx.compose.animation.core.tween import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.luminance import com.vanced.manager.preferences.holder.managerAccentColorPref @@ -19,7 +18,7 @@ fun contentColorForColor(color: Color) = @Composable fun managerAccentColor(): Color { val accentColor by managerAccentColorPref - return remember { Color(accentColor) } + return Color(accentColor) } @Composable From 1351bc91f0745cd1a5dbe430c6f4732ae01c11fb Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 20 Jul 2021 15:15:56 +0400 Subject: [PATCH 034/118] implemented own navigator --- .../com/vanced/manager/ui/MainActivity.kt | 59 +++++++++---------- .../manager/ui/navigation/ManagerNavigator.kt | 30 ++++++++++ .../ui/navigation/NavigationController.kt | 42 +++++++++++++ 3 files changed, 100 insertions(+), 31 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/ui/navigation/ManagerNavigator.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/navigation/NavigationController.kt diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index 54a755b8c4..6684d44198 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -2,6 +2,7 @@ package com.vanced.manager.ui import android.os.Bundle import androidx.activity.ComponentActivity +import androidx.activity.compose.BackHandler import androidx.activity.compose.setContent import androidx.compose.foundation.background import androidx.compose.material.* @@ -12,18 +13,15 @@ import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import androidx.compose.ui.util.fastForEach -import androidx.navigation.NavController -import androidx.navigation.compose.NavHost -import androidx.navigation.compose.composable -import androidx.navigation.compose.currentBackStackEntryAsState -import androidx.navigation.compose.rememberNavController import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.vanced.manager.ui.component.color.managerAnimatedColor import com.vanced.manager.ui.component.color.managerSurfaceColor import com.vanced.manager.ui.component.color.managerTextColor import com.vanced.manager.ui.component.menu.ManagerDropdownMenuItem import com.vanced.manager.ui.component.text.ToolbarTitleText +import com.vanced.manager.ui.navigation.ManagerNavigator +import com.vanced.manager.ui.navigation.NavigationController +import com.vanced.manager.ui.navigation.rememberNavigationController import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.theme.ManagerTheme import com.vanced.manager.ui.theme.isDark @@ -42,11 +40,13 @@ class MainActivity : ComponentActivity() { @Composable fun MainActivityLayout() { - val isMenuExpanded = remember { mutableStateOf(false) } val systemUiController = rememberSystemUiController() val surfaceColor = managerSurfaceColor() val isDark = isDark() - val navController = rememberNavController() + + val navController = rememberNavigationController<Screen>( + initialScreen = Screen.Home + ) val screens = listOf( Screen.Home, @@ -59,36 +59,37 @@ class MainActivity : ComponentActivity() { systemUiController.setSystemBarsColor(surfaceColor, !isDark) } + BackHandler { + if (!navController.pop()) { + finish() + } + } + Scaffold( topBar = { MainToolbar( navController = navController, screens = screens, - isMenuExpanded = isMenuExpanded ) }, - backgroundColor = managerSurfaceColor() + backgroundColor = surfaceColor ) { - NavHost( - navController = navController, - startDestination = Screen.Home.route + ManagerNavigator( + navigationController = navController ) { - screens.fastForEach { screen -> - composable(screen.route) { - screen.content() - } - } + it.last().content() } } } @Composable fun MainToolbar( - navController: NavController, + navController: NavigationController<Screen>, screens: List<Screen>, - isMenuExpanded: MutableState<Boolean> ) { - val currentScreenRoute = navController.currentBackStackEntryAsState().value?.destination?.route + var isMenuExpanded by remember { mutableStateOf(false) } + + val currentScreenRoute = navController.screens.last().route TopAppBar( title = { ToolbarTitleText(managerString(stringId = screens.find { it.route == currentScreenRoute }?.displayName)) @@ -97,7 +98,7 @@ class MainActivity : ComponentActivity() { actions = { if (currentScreenRoute == Screen.Home.route) { IconButton( - onClick = { isMenuExpanded.value = !isMenuExpanded.value } + onClick = { isMenuExpanded= !isMenuExpanded } ) { Icon( imageVector = Icons.Default.MoreVert, @@ -107,9 +108,9 @@ class MainActivity : ComponentActivity() { } DropdownMenu( - expanded = isMenuExpanded.value, + expanded = isMenuExpanded, onDismissRequest = { - isMenuExpanded.value = false + isMenuExpanded = false }, modifier = Modifier.background(MaterialTheme.colors.surface) ) { @@ -117,12 +118,8 @@ class MainActivity : ComponentActivity() { ManagerDropdownMenuItem( title = stringResource(id = it.displayName) ) { - isMenuExpanded.value = !isMenuExpanded.value - navController.navigate(it.route) { - popUpTo(Screen.Home.route) { - saveState = true - } - } + isMenuExpanded = !isMenuExpanded + navController.push(it) } } } @@ -130,7 +127,7 @@ class MainActivity : ComponentActivity() { }, navigationIcon = if (currentScreenRoute != Screen.Home.route) {{ IconButton(onClick = { - navController.popBackStack() + navController.pop() }) { Icon( imageVector = Icons.Default.ArrowBackIos, diff --git a/app/src/main/java/com/vanced/manager/ui/navigation/ManagerNavigator.kt b/app/src/main/java/com/vanced/manager/ui/navigation/ManagerNavigator.kt new file mode 100644 index 0000000000..45cb5c0211 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/navigation/ManagerNavigator.kt @@ -0,0 +1,30 @@ +package com.vanced.manager.ui.navigation + +import androidx.compose.animation.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember + +@OptIn(ExperimentalAnimationApi::class) +@Composable +fun <T> ManagerNavigator( + navigationController: NavigationController<T>, + content: @Composable (targetContent: List<T>) -> Unit +) { + val screens = remember { navigationController.screens } + + //TODO Animation is not working for some weird reasons + AnimatedContent( + transitionSpec = { + if (targetState.size > initialState.size) { + slideIntoContainer(AnimatedContentScope.SlideDirection.Start) with + slideOutOfContainer(AnimatedContentScope.SlideDirection.End) + } else { + slideIntoContainer(AnimatedContentScope.SlideDirection.End) with + slideOutOfContainer(AnimatedContentScope.SlideDirection.Start) + } + }, + targetState = screens + ) { targetContents -> + content(targetContents) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/navigation/NavigationController.kt b/app/src/main/java/com/vanced/manager/ui/navigation/NavigationController.kt new file mode 100644 index 0000000000..c34eb9e24c --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/navigation/NavigationController.kt @@ -0,0 +1,42 @@ +package com.vanced.manager.ui.navigation + +import androidx.compose.runtime.* +import androidx.compose.runtime.snapshots.SnapshotStateList + +@Composable +fun <T> rememberNavigationController( + initialScreen: T +) = remember { + NavigationControllerImpl(initialScreen) +} + +interface NavigationController<T> { + + val screens: SnapshotStateList<T> + + fun push(item: T) + + fun pop(): Boolean + +} + +class NavigationControllerImpl<T>( + initialScreen: T +) : NavigationController<T> { + + override val screens: SnapshotStateList<T> = + mutableStateListOf(initialScreen) + + override fun push(item: T) { + screens.add(item) + } + + override fun pop(): Boolean { + if (screens.size > 1) { + screens.removeLast() + return true + } + return false + } + +} \ No newline at end of file From ba2b5a9150d1ea9084888a204f0931043ecc0e65 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 20 Jul 2021 15:26:57 +0400 Subject: [PATCH 035/118] removed navigation library --- app/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c4de82ec3d..4b15179a08 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -105,13 +105,13 @@ dependencies { implementation("androidx.activity:activity-compose:1.3.0-rc02") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-alpha02") - implementation("androidx.navigation:navigation-compose:2.4.0-alpha04") + implementation("androidx.lifecycle:lifecycle-viewmodel-compose:1.0.0-alpha07") implementation("com.google.accompanist:accompanist-swiperefresh:$accompanistVersion") implementation("com.google.accompanist:accompanist-systemuicontroller:$accompanistVersion") implementation("com.google.accompanist:accompanist-placeholder-material:$accompanistVersion") - implementation("io.coil-kt:coil-compose:1.3.0") + implementation("io.coil-kt:coil-compose:1.3.0") implementation("com.github.skydoves:orchestra-colorpicker:$orchestraVersion") From b97fb17ee6c9832ed1b1b59b70b4f6d109893faa Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 20 Jul 2021 15:28:22 +0400 Subject: [PATCH 036/118] fixed splash activity --- app/src/main/java/com/vanced/manager/ui/SplashScreenActivity.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/com/vanced/manager/ui/SplashScreenActivity.kt b/app/src/main/java/com/vanced/manager/ui/SplashScreenActivity.kt index aeb2ecf771..c2697d5c3d 100644 --- a/app/src/main/java/com/vanced/manager/ui/SplashScreenActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/SplashScreenActivity.kt @@ -12,6 +12,7 @@ class SplashScreenActivity : ComponentActivity() { startActivity( Intent(this, MainActivity::class.java) ) + finish() } } \ No newline at end of file From 65c99cc8c3d9b4ba8ad1c8a5ef4a24f25da4a81b Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 20 Jul 2021 23:22:04 +0400 Subject: [PATCH 037/118] updated to rc1 --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index e356cb87ab..839d218e5d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,7 +5,7 @@ buildscript { } dependencies { - classpath("com.android.tools.build:gradle:7.0.0-beta05") + classpath("com.android.tools.build:gradle:7.0.0-rc01") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${Config.kotlinVersion}") } } From f3c132885cb5c760e6b5c9ecdc38b0dd144f6a6f Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 25 Jul 2021 20:35:12 +0400 Subject: [PATCH 038/118] added music and microg downloaders --- .../java/com/vanced/manager/di/APIModule.kt | 23 ++++++- .../com/vanced/manager/di/DownloaderModule.kt | 27 ++++---- .../com/vanced/manager/di/InstallerModuke.kt | 6 +- .../com/vanced/manager/di/MapperModule.kt | 1 - .../com/vanced/manager/di/NetworkModule.kt | 1 + .../com/vanced/manager/di/RepositoryModule.kt | 1 - .../com/vanced/manager/di/ServiceModule.kt | 1 - .../manager/downloader/api/MicrogAPI.kt | 16 +++++ .../vanced/manager/downloader/api/MusicAPI.kt | 18 +++++ .../manager/downloader/api/VancedAPI.kt | 2 +- .../manager/downloader/base/AppDownloader.kt | 1 + .../downloader/impl/MicrogDownloader.kt | 20 ++++-- .../downloader/impl/MusicDownloader.kt | 28 ++++++-- .../downloader/impl/VancedDownloader.kt | 66 ++----------------- .../installer/{ => impl}/MicrogInstaller.kt | 10 ++- .../installer/{ => impl}/MusicInstaller.kt | 12 ++-- .../installer/{ => impl}/VancedInstaller.kt | 2 +- .../java/com/vanced/manager/ui/util/Const.kt | 13 +++- 18 files changed, 146 insertions(+), 102 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/downloader/api/MicrogAPI.kt create mode 100644 app/src/main/java/com/vanced/manager/downloader/api/MusicAPI.kt rename app/src/main/java/com/vanced/manager/installer/{ => impl}/MicrogInstaller.kt (63%) rename app/src/main/java/com/vanced/manager/installer/{ => impl}/MusicInstaller.kt (53%) rename app/src/main/java/com/vanced/manager/installer/{ => impl}/VancedInstaller.kt (93%) diff --git a/app/src/main/java/com/vanced/manager/di/APIModule.kt b/app/src/main/java/com/vanced/manager/di/APIModule.kt index f40d6dbf51..db8ef30f0f 100644 --- a/app/src/main/java/com/vanced/manager/di/APIModule.kt +++ b/app/src/main/java/com/vanced/manager/di/APIModule.kt @@ -1,5 +1,7 @@ package com.vanced.manager.di +import com.vanced.manager.downloader.api.MicrogAPI +import com.vanced.manager.downloader.api.MusicAPI import com.vanced.manager.downloader.api.VancedAPI import com.vanced.manager.network.util.BASE import okhttp3.OkHttpClient @@ -10,12 +12,29 @@ val apiModule = module { fun provideVancedAPI( okHttpClient: OkHttpClient - ): VancedAPI = Retrofit.Builder() + ) = Retrofit.Builder() .baseUrl(BASE) .client(okHttpClient) .build() .create(VancedAPI::class.java) - single { provideVancedAPI(get()) } + fun provideMusicAPI( + okHttpClient: OkHttpClient + )= Retrofit.Builder() + .baseUrl(BASE) + .client(okHttpClient) + .build() + .create(MusicAPI::class.java) + fun provideMicrogAPI( + okHttpClient: OkHttpClient + ) = Retrofit.Builder() + .baseUrl("https://github.com/YTVanced/VancedMicroG/") + .client(okHttpClient) + .build() + .create(MicrogAPI::class.java) + + single { provideVancedAPI(get()) } + single { provideMusicAPI(get()) } + single { provideMicrogAPI(get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt b/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt index 0dcc6af546..3f64a5e294 100644 --- a/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt +++ b/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt @@ -1,31 +1,34 @@ package com.vanced.manager.di +import com.vanced.manager.downloader.api.MicrogAPI +import com.vanced.manager.downloader.api.MusicAPI import com.vanced.manager.downloader.api.VancedAPI import com.vanced.manager.downloader.impl.MicrogDownloader import com.vanced.manager.downloader.impl.MusicDownloader import com.vanced.manager.downloader.impl.VancedDownloader -import com.vanced.manager.installer.MicrogInstaller -import com.vanced.manager.installer.MusicInstaller -import com.vanced.manager.installer.VancedInstaller +import com.vanced.manager.installer.impl.MicrogInstaller +import com.vanced.manager.installer.impl.MusicInstaller +import com.vanced.manager.installer.impl.VancedInstaller import org.koin.dsl.module val downloaderModule = module { fun provideVancedDownloader( + vancedInstaller: VancedInstaller, vancedAPI: VancedAPI, - vancedInstaller: VancedInstaller - ) = VancedDownloader(vancedAPI, vancedInstaller) + ) = VancedDownloader(vancedInstaller, vancedAPI) fun provideMusicDownloader( - musicInstaller: MusicInstaller - ) = MusicDownloader(musicInstaller) + musicInstaller: MusicInstaller, + musicAPI: MusicAPI, + ) = MusicDownloader(musicInstaller, musicAPI) fun provideMicrogDownloader( - microgInstaller: MicrogInstaller - ) = MicrogDownloader(microgInstaller) + microgInstaller: MicrogInstaller, + microgAPI: MicrogAPI, + ) = MicrogDownloader(microgInstaller, microgAPI) single { provideVancedDownloader(get(), get()) } - single { provideMusicDownloader(get()) } - single { provideMicrogDownloader(get()) } - + single { provideMusicDownloader(get(), get()) } + single { provideMicrogDownloader(get(), get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt b/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt index 1c5c899393..109c57f167 100644 --- a/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt +++ b/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt @@ -1,8 +1,8 @@ package com.vanced.manager.di -import com.vanced.manager.installer.MicrogInstaller -import com.vanced.manager.installer.MusicInstaller -import com.vanced.manager.installer.VancedInstaller +import com.vanced.manager.installer.impl.MicrogInstaller +import com.vanced.manager.installer.impl.MusicInstaller +import com.vanced.manager.installer.impl.VancedInstaller import org.koin.dsl.module val installerModule = module { diff --git a/app/src/main/java/com/vanced/manager/di/MapperModule.kt b/app/src/main/java/com/vanced/manager/di/MapperModule.kt index 72aad51bb8..c789da0848 100644 --- a/app/src/main/java/com/vanced/manager/di/MapperModule.kt +++ b/app/src/main/java/com/vanced/manager/di/MapperModule.kt @@ -21,5 +21,4 @@ val mapperModule = module { single { provideAppMapper(get()) } single { provideJsonMapper(get()) } - } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/NetworkModule.kt b/app/src/main/java/com/vanced/manager/di/NetworkModule.kt index 83d42ce241..94a10c829f 100644 --- a/app/src/main/java/com/vanced/manager/di/NetworkModule.kt +++ b/app/src/main/java/com/vanced/manager/di/NetworkModule.kt @@ -4,6 +4,7 @@ import okhttp3.OkHttpClient import org.koin.dsl.module val networkModule = module { + fun provideOkHttpClient(): OkHttpClient { return OkHttpClient() } diff --git a/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt b/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt index 0eb7b01c67..ec4773f834 100644 --- a/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt +++ b/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt @@ -17,5 +17,4 @@ val repositoryModule = module { ) single { provideJsonRepository(get(), get()) } - } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/ServiceModule.kt b/app/src/main/java/com/vanced/manager/di/ServiceModule.kt index 44c12581eb..743a82aa27 100644 --- a/app/src/main/java/com/vanced/manager/di/ServiceModule.kt +++ b/app/src/main/java/com/vanced/manager/di/ServiceModule.kt @@ -19,5 +19,4 @@ val serviceModule = module { .create(JsonService::class.java) single { provideRetrofitService(get()) } - } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/api/MicrogAPI.kt b/app/src/main/java/com/vanced/manager/downloader/api/MicrogAPI.kt new file mode 100644 index 0000000000..20f7a48473 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/downloader/api/MicrogAPI.kt @@ -0,0 +1,16 @@ +package com.vanced.manager.downloader.api + +import okhttp3.ResponseBody +import retrofit2.Call +import retrofit2.http.GET +import retrofit2.http.Path +import retrofit2.http.Streaming +import retrofit2.http.Url + +interface MicrogAPI { + + @GET("releases/latest/download/microg.apk") + @Streaming + fun getFile() : Call<ResponseBody> + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/api/MusicAPI.kt b/app/src/main/java/com/vanced/manager/downloader/api/MusicAPI.kt new file mode 100644 index 0000000000..1e738903a2 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/downloader/api/MusicAPI.kt @@ -0,0 +1,18 @@ +package com.vanced.manager.downloader.api + +import okhttp3.ResponseBody +import retrofit2.Call +import retrofit2.http.GET +import retrofit2.http.Path +import retrofit2.http.Streaming + +interface MusicAPI { + + @GET("music/v{version}/{variant}.apk") + @Streaming + fun getFiles( + @Path("version") version: String, + @Path("variant") variant: String, + ) : Call<ResponseBody> + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt b/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt index 73edb3161f..cc2eccc659 100644 --- a/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt +++ b/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt @@ -10,7 +10,7 @@ interface VancedAPI { @GET("apks/v{version}/{variant}/{type}/{apkName}") @Streaming - fun getApk( + fun getFiles( @Path("version") version: String, @Path("variant") variant: String, @Path("type") type: String, diff --git a/app/src/main/java/com/vanced/manager/downloader/base/AppDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/base/AppDownloader.kt index 7e16961ba0..632ff53d14 100644 --- a/app/src/main/java/com/vanced/manager/downloader/base/AppDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/base/AppDownloader.kt @@ -17,6 +17,7 @@ import java.io.File import java.io.FileOutputStream import java.io.IOException +//TODO remove showDownloadScreen and viewModel references abstract class AppDownloader( val appName: String, val appInstaller: AppInstaller diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt index 34430e106c..5a6b1e58a4 100644 --- a/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt @@ -1,19 +1,31 @@ package com.vanced.manager.downloader.impl import com.vanced.manager.domain.model.App +import com.vanced.manager.downloader.api.MicrogAPI import com.vanced.manager.downloader.base.AppDownloader -import com.vanced.manager.installer.MicrogInstaller +import com.vanced.manager.installer.impl.MicrogInstaller import com.vanced.manager.ui.viewmodel.HomeViewModel class MicrogDownloader( - microgInstaller: MicrogInstaller + microgInstaller: MicrogInstaller, + private val microgAPI: MicrogAPI, ) : AppDownloader( appName = "microg", appInstaller = microgInstaller ) { - override suspend fun download(app: App, viewModel: HomeViewModel) { - TODO("Not yet implemented") + override suspend fun download( + app: App, + viewModel: HomeViewModel + ) { + downloadFile( + file = File( + call = microgAPI.getFile(), + fileName = "microg.apk" + ), + viewModel = viewModel, + folderStructure = "" + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt index 24e66a3aa7..73374b760d 100644 --- a/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt @@ -1,19 +1,39 @@ package com.vanced.manager.downloader.impl import com.vanced.manager.domain.model.App +import com.vanced.manager.downloader.api.MusicAPI import com.vanced.manager.downloader.base.AppDownloader -import com.vanced.manager.installer.MusicInstaller +import com.vanced.manager.installer.impl.MusicInstaller +import com.vanced.manager.preferences.holder.managerVariantPref +import com.vanced.manager.preferences.holder.musicVersionPref import com.vanced.manager.ui.viewmodel.HomeViewModel class MusicDownloader( - musicInstaller: MusicInstaller + musicInstaller: MusicInstaller, + private val musicAPI: MusicAPI, ) : AppDownloader( appName = "music", appInstaller = musicInstaller ) { - override suspend fun download(app: App, viewModel: HomeViewModel) { - TODO("Not yet implemented") + private val version by musicVersionPref + private val variant by managerVariantPref + + override suspend fun download( + app: App, + viewModel: HomeViewModel + ) { + downloadFile( + file = File( + call = musicAPI.getFiles( + version = version, + variant = variant, + ), + fileName = "music.apk" + ), + viewModel = viewModel, + folderStructure = "$version/$variant" + ) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt index dd71a68afc..f4cfb59415 100644 --- a/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt @@ -3,7 +3,7 @@ package com.vanced.manager.downloader.impl import com.vanced.manager.domain.model.App import com.vanced.manager.downloader.api.VancedAPI import com.vanced.manager.downloader.base.AppDownloader -import com.vanced.manager.installer.VancedInstaller +import com.vanced.manager.installer.impl.VancedInstaller import com.vanced.manager.preferences.holder.managerVariantPref import com.vanced.manager.preferences.holder.vancedLanguagesPref import com.vanced.manager.preferences.holder.vancedThemePref @@ -13,8 +13,8 @@ import com.vanced.manager.util.arch import com.vanced.manager.util.log class VancedDownloader( + vancedInstaller: VancedInstaller, private val vancedAPI: VancedAPI, - vancedInstaller: VancedInstaller ) : AppDownloader( appName = "vanced", appInstaller = vancedInstaller @@ -25,7 +25,10 @@ class VancedDownloader( private val variant by managerVariantPref private val languages by vancedLanguagesPref - override suspend fun download(app: App, viewModel: HomeViewModel) { + override suspend fun download( + app: App, + viewModel: HomeViewModel + ) { val files = listOf( getFile( type = "Theme", @@ -52,7 +55,7 @@ class VancedDownloader( type: String, apkName: String, ) = File( - call = vancedAPI.getApk( + call = vancedAPI.getFiles( version = version, variant = variant, type = type, @@ -61,59 +64,4 @@ class VancedDownloader( fileName = apkName ) -// private suspend fun downloadTheme() { -// val theme by vancedThemePref -// downloadVancedApk( -// type = "Theme", -// apkName = "$theme.apk" -// ) { -// downloadArch() -// } -// } -// -// private suspend fun downloadArch() { -// downloadVancedApk( -// type = "Arch", -// apkName = "split_config.x86.apk" -// ) { -// downloadLanguage() -// } -// } -// -// private suspend fun downloadLanguage() { -// val languages by vancedLanguagesPref -// languages.forEach { language -> -// downloadVancedApk( -// type = "Language", -// apkName = "split_config.$language.apk" -// ) {} -// } -// install() -// } -// -// -// -// -// private suspend fun downloadVancedApk( -// type: String, -// apkName: String, -// onDownload: suspend () -> Unit, -// ) { -// downloadFile( -// vancedAPI.getApk( -// version = version, -// variant = variant, -// type = type, -// apkName = apkName -// ), -// folderStructure = "$version/$variant", -// fileName = apkName, -// onError = { -// log("error", it) -// } -// ) { -// onDownload() -// } -// } - } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/installer/MicrogInstaller.kt b/app/src/main/java/com/vanced/manager/installer/impl/MicrogInstaller.kt similarity index 63% rename from app/src/main/java/com/vanced/manager/installer/MicrogInstaller.kt rename to app/src/main/java/com/vanced/manager/installer/impl/MicrogInstaller.kt index 6ca994e275..7654665dde 100644 --- a/app/src/main/java/com/vanced/manager/installer/MicrogInstaller.kt +++ b/app/src/main/java/com/vanced/manager/installer/impl/MicrogInstaller.kt @@ -1,8 +1,9 @@ -package com.vanced.manager.installer +package com.vanced.manager.installer.impl import com.vanced.manager.installer.base.AppInstaller import com.vanced.manager.preferences.holder.managerVariantPref import com.vanced.manager.preferences.holder.vancedVersionPref +import com.xinto.apkhelper.installApk import com.xinto.apkhelper.installSplitApks class MicrogInstaller : AppInstaller() { @@ -12,11 +13,8 @@ class MicrogInstaller : AppInstaller() { ) { super.install(onDone) - val version by vancedVersionPref - val variant by managerVariantPref - - installSplitApks( - apksPath = context.getExternalFilesDir("vanced/$version/$variant")!!.path, + installApk( + apkPath = context.getExternalFilesDir("microg/microg.apk")!!.path, context = context ) } diff --git a/app/src/main/java/com/vanced/manager/installer/MusicInstaller.kt b/app/src/main/java/com/vanced/manager/installer/impl/MusicInstaller.kt similarity index 53% rename from app/src/main/java/com/vanced/manager/installer/MusicInstaller.kt rename to app/src/main/java/com/vanced/manager/installer/impl/MusicInstaller.kt index d934206410..3b7d1d2892 100644 --- a/app/src/main/java/com/vanced/manager/installer/MusicInstaller.kt +++ b/app/src/main/java/com/vanced/manager/installer/impl/MusicInstaller.kt @@ -1,9 +1,9 @@ -package com.vanced.manager.installer +package com.vanced.manager.installer.impl import com.vanced.manager.installer.base.AppInstaller import com.vanced.manager.preferences.holder.managerVariantPref -import com.vanced.manager.preferences.holder.vancedVersionPref -import com.xinto.apkhelper.installSplitApks +import com.vanced.manager.preferences.holder.musicVersionPref +import com.xinto.apkhelper.installApk class MusicInstaller : AppInstaller() { @@ -12,11 +12,11 @@ class MusicInstaller : AppInstaller() { ) { super.install(onDone) - val version by vancedVersionPref + val version by musicVersionPref val variant by managerVariantPref - installSplitApks( - apksPath = context.getExternalFilesDir("vanced/$version/$variant")!!.path, + installApk( + apkPath = context.getExternalFilesDir("music/$version/$variant/music.apk")!!.path, context = context ) } diff --git a/app/src/main/java/com/vanced/manager/installer/VancedInstaller.kt b/app/src/main/java/com/vanced/manager/installer/impl/VancedInstaller.kt similarity index 93% rename from app/src/main/java/com/vanced/manager/installer/VancedInstaller.kt rename to app/src/main/java/com/vanced/manager/installer/impl/VancedInstaller.kt index eaf5db4069..699f342773 100644 --- a/app/src/main/java/com/vanced/manager/installer/VancedInstaller.kt +++ b/app/src/main/java/com/vanced/manager/installer/impl/VancedInstaller.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.installer +package com.vanced.manager.installer.impl import com.vanced.manager.installer.base.AppInstaller import com.vanced.manager.preferences.holder.managerVariantPref diff --git a/app/src/main/java/com/vanced/manager/ui/util/Const.kt b/app/src/main/java/com/vanced/manager/ui/util/Const.kt index 256682442e..8ae7364882 100644 --- a/app/src/main/java/com/vanced/manager/ui/util/Const.kt +++ b/app/src/main/java/com/vanced/manager/ui/util/Const.kt @@ -3,4 +3,15 @@ package com.vanced.manager.ui.util import androidx.compose.ui.unit.dp val defaultContentPaddingHorizontal = 16.dp -val defaultContentPaddingVertical = 12.dp \ No newline at end of file +val defaultContentPaddingVertical = 12.dp + +fun test(anotherFun: () -> Int) = anotherFun() + 5 +fun test(anotherNum: Int) = anotherNum + 5 + +fun test2() { + test { + print("haha jonathan you are banging my number") + return@test 0 + } + test(0) +} \ No newline at end of file From 9a3e02f82c5623ef6eb7144698de401bfeae6f9d Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 27 Jul 2021 15:03:48 +0400 Subject: [PATCH 039/118] improved radiobutton and checkbox preference dialogs --- .../ui/component/preference/CheckboxDialogPreference.kt | 2 +- .../manager/ui/component/preference/DialogPreference.kt | 2 ++ .../component/preference/RadiobuttonDialogPreference.kt | 9 +++++---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt index fb10eb920f..0b1e384e45 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt @@ -32,7 +32,7 @@ fun CheckboxDialogPreference( DialogPreference( preferenceTitle = preferenceTitle, preferenceDescription = buttons.filter { button -> - selectedButtons.any { selectedButton -> + pref.any { selectedButton -> button.key == selectedButton } }.sortedBy { it.title }.joinToString(separator = ", ") { it.title }, diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/DialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/DialogPreference.kt index 0e26a0db6b..62039323b2 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/DialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/DialogPreference.kt @@ -11,6 +11,7 @@ import com.vanced.manager.ui.component.dialog.ManagerDialog fun DialogPreference( preferenceTitle: String, preferenceDescription: String? = null, + onDismissRequest: () -> Unit = {}, trailing: @Composable () -> Unit = {}, buttons: @Composable ColumnScope.(isShown: MutableState<Boolean>) -> Unit, content: @Composable ColumnScope.() -> Unit @@ -27,6 +28,7 @@ fun DialogPreference( ManagerDialog( title = preferenceTitle, onDismissRequest = { + onDismissRequest() isShown.value = false }, buttons = { buttons(isShown) }, diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt index ea7da32ca7..af12f99890 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt @@ -20,21 +20,22 @@ fun RadiobuttonDialogPreference( buttons: List<RadioButtonPreference>, onSave: (newPref: String?) -> Unit = {} ) { + var pref by preference + var currentSelection by remember { mutableStateOf(pref) } val coroutineScope = rememberCoroutineScope() - var currentSelection by remember { mutableStateOf(preference.value.value) } DialogPreference( preferenceTitle = preferenceTitle, - preferenceDescription = buttons.find { it.key == currentSelection }?.title, + preferenceDescription = buttons.find { it.key == pref }?.title, trailing = trailing, buttons = { isShown -> ManagerSaveButton { coroutineScope.launch { isShown.value = false - preference.save(currentSelection) + pref = currentSelection onSave(currentSelection) } } - } + }, ) { LazyColumn( modifier = Modifier.heightIn(max = 400.dp) From 7dfc3cbe591f0cdd68babea3659535045ab7955d Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 27 Jul 2021 15:04:59 +0400 Subject: [PATCH 040/118] Added a reset button widget --- .../ui/widget/button/ManagerResetButton.kt | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 app/src/main/java/com/vanced/manager/ui/widget/button/ManagerResetButton.kt diff --git a/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerResetButton.kt b/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerResetButton.kt new file mode 100644 index 0000000000..0aee26929b --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerResetButton.kt @@ -0,0 +1,21 @@ +package com.vanced.manager.ui.widget.button + +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.vanced.manager.R +import com.vanced.manager.ui.component.button.ManagerThemedTextButton +import com.vanced.manager.ui.resources.managerString + +@Composable +fun ManagerResetButton( + onClick: () -> Unit +) { + ManagerThemedTextButton( + modifier = Modifier.fillMaxWidth(), + text = managerString( + stringId = R.string.dialog_button_reset + ), + onClick = onClick + ) +} \ No newline at end of file From f277e2628cb5643d674215821869e463c0f220b0 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 27 Jul 2021 15:12:43 +0400 Subject: [PATCH 041/118] Added a reset button to accent color picker --- .../vanced/manager/ui/widget/button/ManagerResetButton.kt | 4 ++++ .../manager/ui/widget/screens/settings/AccentColorItem.kt | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerResetButton.kt b/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerResetButton.kt index 0aee26929b..2e77dd3e2e 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerResetButton.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerResetButton.kt @@ -3,12 +3,15 @@ package com.vanced.manager.ui.widget.button import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import com.vanced.manager.R import com.vanced.manager.ui.component.button.ManagerThemedTextButton +import com.vanced.manager.ui.component.color.managerAccentColor import com.vanced.manager.ui.resources.managerString @Composable fun ManagerResetButton( + backgroundColor: Color = managerAccentColor(), onClick: () -> Unit ) { ManagerThemedTextButton( @@ -16,6 +19,7 @@ fun ManagerResetButton( text = managerString( stringId = R.string.dialog_button_reset ), + backgroundColor = backgroundColor, onClick = onClick ) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt index 3eb1933d6a..570f5113cf 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt @@ -7,6 +7,8 @@ import com.vanced.manager.preferences.holder.managerAccentColorPref import com.vanced.manager.ui.component.color.ManagerColorPicker import com.vanced.manager.ui.component.preference.DialogPreference import com.vanced.manager.ui.resources.managerString +import com.vanced.manager.ui.theme.defAccentColor +import com.vanced.manager.ui.widget.button.ManagerResetButton import com.vanced.manager.ui.widget.button.ManagerSaveButton @Composable @@ -18,6 +20,12 @@ fun SettingsAccentColorItem() { ), preferenceDescription = "#" + Integer.toHexString(localAccentColor.toInt()), buttons = { isShown -> + ManagerResetButton( + backgroundColor = Color(localAccentColor) + ) { + isShown.value = false + managerAccentColorPref.save(defAccentColor) + } ManagerSaveButton( backgroundColor = Color(localAccentColor) ) { From 0e7f2ce59e49223845301b307f0c20e2195b7649 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 27 Jul 2021 15:16:29 +0400 Subject: [PATCH 042/118] Added a modifier builder for better syntax --- .../manager/ui/component/modifier/ModifierBuilder.kt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 app/src/main/java/com/vanced/manager/ui/component/modifier/ModifierBuilder.kt diff --git a/app/src/main/java/com/vanced/manager/ui/component/modifier/ModifierBuilder.kt b/app/src/main/java/com/vanced/manager/ui/component/modifier/ModifierBuilder.kt new file mode 100644 index 0000000000..6892891f2f --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/component/modifier/ModifierBuilder.kt @@ -0,0 +1,7 @@ +package com.vanced.manager.ui.component.modifier + +import androidx.compose.ui.Modifier + +fun modifierBuilder( + block: Modifier.() -> Unit +) = Modifier.block() \ No newline at end of file From dac2ec5b70c565c84ddc4763ca9eda9d395e0050 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Fri, 20 Aug 2021 11:30:34 +0400 Subject: [PATCH 043/118] updated buildscript --- app/build.gradle.kts | 20 +++++++++----------- build.gradle.kts | 4 ++-- buildSrc/.gitignore | 1 - buildSrc/build.gradle.kts | 9 --------- buildSrc/src/main/java/Config.kt | 5 ----- buildSrc/src/main/java/Dependencies.kt | 9 --------- 6 files changed, 11 insertions(+), 37 deletions(-) delete mode 100644 buildSrc/.gitignore delete mode 100644 buildSrc/build.gradle.kts delete mode 100644 buildSrc/src/main/java/Config.kt delete mode 100644 buildSrc/src/main/java/Dependencies.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4b15179a08..552fbda336 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,9 +1,3 @@ -import Dependencies.accompanistVersion -import Dependencies.composeVersion -import Dependencies.koinVersion -import Dependencies.orchestraVersion -import Dependencies.retrofitVersion - plugins { id("com.android.application") kotlin("android") @@ -54,7 +48,7 @@ android { } composeOptions { - kotlinCompilerExtensionVersion = composeVersion + kotlinCompilerExtensionVersion = "1.0.1" } } @@ -86,10 +80,11 @@ dependencies { implementation(kotlin("reflect")) implementation("androidx.core:core-ktx:1.6.0") - implementation("androidx.appcompat:appcompat:1.3.0") + implementation("androidx.appcompat:appcompat:1.3.1") implementation("com.google.android.material:material:1.4.0") implementation("androidx.browser:browser:1.3.0") + val composeVersion = "1.0.1" implementation("androidx.compose.compiler:compiler:$composeVersion") implementation("androidx.compose.foundation:foundation:$composeVersion") implementation("androidx.compose.material:material-icons-core:$composeVersion") @@ -103,21 +98,24 @@ dependencies { implementation("androidx.preference:preference-ktx:1.1.1") - implementation("androidx.activity:activity-compose:1.3.0-rc02") - implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-alpha02") + implementation("androidx.activity:activity-compose:1.3.1") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-alpha03") implementation("androidx.lifecycle:lifecycle-viewmodel-compose:1.0.0-alpha07") + val accompanistVersion = "0.14.0" implementation("com.google.accompanist:accompanist-swiperefresh:$accompanistVersion") implementation("com.google.accompanist:accompanist-systemuicontroller:$accompanistVersion") implementation("com.google.accompanist:accompanist-placeholder-material:$accompanistVersion") implementation("io.coil-kt:coil-compose:1.3.0") - implementation("com.github.skydoves:orchestra-colorpicker:$orchestraVersion") + implementation("com.github.skydoves:orchestra-colorpicker:1.0.7") + val koinVersion = "3.1.2" implementation("io.insert-koin:koin-android:$koinVersion") implementation("io.insert-koin:koin-androidx-compose:$koinVersion") + val retrofitVersion = "2.9.0" implementation("com.squareup.retrofit2:retrofit:$retrofitVersion") implementation("com.squareup.retrofit2:converter-gson:$retrofitVersion") diff --git a/build.gradle.kts b/build.gradle.kts index 839d218e5d..9c57a4fe31 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,8 +5,8 @@ buildscript { } dependencies { - classpath("com.android.tools.build:gradle:7.0.0-rc01") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${Config.kotlinVersion}") + classpath("com.android.tools.build:gradle:7.0.1") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.10") } } diff --git a/buildSrc/.gitignore b/buildSrc/.gitignore deleted file mode 100644 index d16386367f..0000000000 --- a/buildSrc/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build/ \ No newline at end of file diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts deleted file mode 100644 index 051fc6281d..0000000000 --- a/buildSrc/build.gradle.kts +++ /dev/null @@ -1,9 +0,0 @@ -plugins { - `kotlin-dsl` -} - -repositories { - google() - jcenter() - maven(url = "https://jitpack.io") -} \ No newline at end of file diff --git a/buildSrc/src/main/java/Config.kt b/buildSrc/src/main/java/Config.kt deleted file mode 100644 index c376c1b48d..0000000000 --- a/buildSrc/src/main/java/Config.kt +++ /dev/null @@ -1,5 +0,0 @@ -object Config { - - const val kotlinVersion = "1.5.10" - -} \ No newline at end of file diff --git a/buildSrc/src/main/java/Dependencies.kt b/buildSrc/src/main/java/Dependencies.kt deleted file mode 100644 index 6e08a53544..0000000000 --- a/buildSrc/src/main/java/Dependencies.kt +++ /dev/null @@ -1,9 +0,0 @@ -object Dependencies { - - const val accompanistVersion = "0.14.0" - const val composeVersion = "1.0.0-rc02" - const val koinVersion = "3.1.2" - const val retrofitVersion = "2.9.0" - const val orchestraVersion = "1.0.7" - -} \ No newline at end of file From b7ab53c7b69ce60d693ecf2ae6bcdf2381fc12a5 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Fri, 20 Aug 2021 11:32:09 +0400 Subject: [PATCH 044/118] target android 12 --- app/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 552fbda336..7fcf99ea49 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -4,11 +4,11 @@ plugins { } android { - compileSdk = 30 + compileSdk = 31 defaultConfig { minSdk = 21 - targetSdk = 30 + targetSdk = 31 applicationId = "com.vanced.manager" From 146e864c27ab986893efc18e07a5676de79660b1 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Fri, 20 Aug 2021 11:32:34 +0400 Subject: [PATCH 045/118] updated accompanist --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 7fcf99ea49..d4ada0b365 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -102,7 +102,7 @@ dependencies { implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-alpha03") implementation("androidx.lifecycle:lifecycle-viewmodel-compose:1.0.0-alpha07") - val accompanistVersion = "0.14.0" + val accompanistVersion = "0.17.0" implementation("com.google.accompanist:accompanist-swiperefresh:$accompanistVersion") implementation("com.google.accompanist:accompanist-systemuicontroller:$accompanistVersion") implementation("com.google.accompanist:accompanist-placeholder-material:$accompanistVersion") From 407773342101ccfa83be4070bc6f55cd25c0f3e8 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Fri, 20 Aug 2021 11:38:11 +0400 Subject: [PATCH 046/118] updated kotlin --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 9c57a4fe31..49c69926e0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ buildscript { dependencies { classpath("com.android.tools.build:gradle:7.0.1") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.10") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21") } } From c289a70d9a47e0f0093efce782e78226b8a029fa Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Fri, 20 Aug 2021 11:52:55 +0400 Subject: [PATCH 047/118] use saveable state holder --- .../main/java/com/vanced/manager/ui/MainActivity.kt | 2 +- .../vanced/manager/ui/navigation/ManagerNavigator.kt | 12 +++++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index 6684d44198..a6325be5ab 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -77,7 +77,7 @@ class MainActivity : ComponentActivity() { ManagerNavigator( navigationController = navController ) { - it.last().content() + it.content() } } } diff --git a/app/src/main/java/com/vanced/manager/ui/navigation/ManagerNavigator.kt b/app/src/main/java/com/vanced/manager/ui/navigation/ManagerNavigator.kt index 45cb5c0211..37aaa916c4 100644 --- a/app/src/main/java/com/vanced/manager/ui/navigation/ManagerNavigator.kt +++ b/app/src/main/java/com/vanced/manager/ui/navigation/ManagerNavigator.kt @@ -3,13 +3,16 @@ package com.vanced.manager.ui.navigation import androidx.compose.animation.* import androidx.compose.runtime.Composable import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveableStateHolder +import com.vanced.manager.ui.util.Screen @OptIn(ExperimentalAnimationApi::class) @Composable -fun <T> ManagerNavigator( +fun <T : Screen> ManagerNavigator( navigationController: NavigationController<T>, - content: @Composable (targetContent: List<T>) -> Unit + content: @Composable (targetContent: T) -> Unit ) { + val saveableStateHolder = rememberSaveableStateHolder() val screens = remember { navigationController.screens } //TODO Animation is not working for some weird reasons @@ -25,6 +28,9 @@ fun <T> ManagerNavigator( }, targetState = screens ) { targetContents -> - content(targetContents) + val targetContent = targetContents.last() + saveableStateHolder.SaveableStateProvider(key = targetContent.route) { + content(targetContent) + } } } \ No newline at end of file From 54f947cc952d2e503fa7584395c0f1edfe8442ff Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Fri, 20 Aug 2021 12:17:47 +0400 Subject: [PATCH 048/118] switched to accompanist navigation --- app/build.gradle.kts | 3 +- .../com/vanced/manager/ui/MainActivity.kt | 62 ++++++++++++------- 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index d4ada0b365..315c578d56 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -103,9 +103,10 @@ dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-compose:1.0.0-alpha07") val accompanistVersion = "0.17.0" + implementation("com.google.accompanist:accompanist-navigation-animation:$accompanistVersion") + implementation("com.google.accompanist:accompanist-placeholder-material:$accompanistVersion") implementation("com.google.accompanist:accompanist-swiperefresh:$accompanistVersion") implementation("com.google.accompanist:accompanist-systemuicontroller:$accompanistVersion") - implementation("com.google.accompanist:accompanist-placeholder-material:$accompanistVersion") implementation("io.coil-kt:coil-compose:1.3.0") diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index a6325be5ab..ae0e29354a 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -2,8 +2,11 @@ package com.vanced.manager.ui import android.os.Bundle import androidx.activity.ComponentActivity -import androidx.activity.compose.BackHandler import androidx.activity.compose.setContent +import androidx.compose.animation.AnimatedContentScope +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut import androidx.compose.foundation.background import androidx.compose.material.* import androidx.compose.material.icons.Icons @@ -13,15 +16,18 @@ import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import androidx.compose.ui.util.fastForEach +import androidx.navigation.NavHostController +import androidx.navigation.compose.currentBackStackEntryAsState +import com.google.accompanist.navigation.animation.AnimatedNavHost +import com.google.accompanist.navigation.animation.composable +import com.google.accompanist.navigation.animation.rememberAnimatedNavController import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.vanced.manager.ui.component.color.managerAnimatedColor import com.vanced.manager.ui.component.color.managerSurfaceColor import com.vanced.manager.ui.component.color.managerTextColor import com.vanced.manager.ui.component.menu.ManagerDropdownMenuItem import com.vanced.manager.ui.component.text.ToolbarTitleText -import com.vanced.manager.ui.navigation.ManagerNavigator -import com.vanced.manager.ui.navigation.NavigationController -import com.vanced.manager.ui.navigation.rememberNavigationController import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.theme.ManagerTheme import com.vanced.manager.ui.theme.isDark @@ -38,15 +44,14 @@ class MainActivity : ComponentActivity() { } } + @OptIn(ExperimentalAnimationApi::class) @Composable fun MainActivityLayout() { val systemUiController = rememberSystemUiController() val surfaceColor = managerSurfaceColor() val isDark = isDark() - val navController = rememberNavigationController<Screen>( - initialScreen = Screen.Home - ) + val navController = rememberAnimatedNavController() val screens = listOf( Screen.Home, @@ -59,12 +64,6 @@ class MainActivity : ComponentActivity() { systemUiController.setSystemBarsColor(surfaceColor, !isDark) } - BackHandler { - if (!navController.pop()) { - finish() - } - } - Scaffold( topBar = { MainToolbar( @@ -74,22 +73,41 @@ class MainActivity : ComponentActivity() { }, backgroundColor = surfaceColor ) { - ManagerNavigator( - navigationController = navController + AnimatedNavHost( + navController = navController, + startDestination = "home", ) { - it.content() + screens.fastForEach { screen -> + composable( + route = screen.route, + enterTransition = { _, _ -> + slideIntoContainer(AnimatedContentScope.SlideDirection.Start) + fadeIn() + }, + exitTransition = { _, _ -> + slideOutOfContainer(AnimatedContentScope.SlideDirection.End) + fadeOut() + }, + popEnterTransition = { _, _ -> + slideIntoContainer(AnimatedContentScope.SlideDirection.End) + fadeIn() + }, + popExitTransition = { _, _ -> + slideOutOfContainer(AnimatedContentScope.SlideDirection.Start) + fadeOut() + } + ) { + screen.content() + } + } } } } @Composable fun MainToolbar( - navController: NavigationController<Screen>, + navController: NavHostController, screens: List<Screen>, ) { var isMenuExpanded by remember { mutableStateOf(false) } - val currentScreenRoute = navController.screens.last().route + val currentScreenRoute = navController.currentBackStackEntryAsState().value?.destination?.route TopAppBar( title = { ToolbarTitleText(managerString(stringId = screens.find { it.route == currentScreenRoute }?.displayName)) @@ -114,12 +132,12 @@ class MainActivity : ComponentActivity() { }, modifier = Modifier.background(MaterialTheme.colors.surface) ) { - screens.filter { it.route != currentScreenRoute }.forEach { + screens.filter { it.route != currentScreenRoute }.forEach { screen -> ManagerDropdownMenuItem( - title = stringResource(id = it.displayName) + title = stringResource(id = screen.displayName) ) { isMenuExpanded = !isMenuExpanded - navController.push(it) + navController.navigate(screen.route) } } } @@ -127,7 +145,7 @@ class MainActivity : ComponentActivity() { }, navigationIcon = if (currentScreenRoute != Screen.Home.route) {{ IconButton(onClick = { - navController.pop() + navController.popBackStack() }) { Icon( imageVector = Icons.Default.ArrowBackIos, From c7bc496bd3014a30d5c72cf4e1bdfa814ba6d097 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Fri, 20 Aug 2021 12:23:56 +0400 Subject: [PATCH 049/118] switched livedata to stateflow --- .../manager/downloader/api/MicrogAPI.kt | 2 -- .../manager/installer/impl/MicrogInstaller.kt | 3 --- .../ui/component/checkbox/ManagerCheckbox.kt | 1 - .../manager/ui/navigation/ManagerNavigator.kt | 5 ++++- .../ui/navigation/NavigationController.kt | 4 +++- .../vanced/manager/ui/screens/HomeLayout.kt | 4 ++-- .../manager/ui/viewmodel/HomeViewModel.kt | 21 ++++++++++--------- .../ui/widget/screens/home/apps/AppsItem.kt | 5 ++--- 8 files changed, 22 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/downloader/api/MicrogAPI.kt b/app/src/main/java/com/vanced/manager/downloader/api/MicrogAPI.kt index 20f7a48473..597448015e 100644 --- a/app/src/main/java/com/vanced/manager/downloader/api/MicrogAPI.kt +++ b/app/src/main/java/com/vanced/manager/downloader/api/MicrogAPI.kt @@ -3,9 +3,7 @@ package com.vanced.manager.downloader.api import okhttp3.ResponseBody import retrofit2.Call import retrofit2.http.GET -import retrofit2.http.Path import retrofit2.http.Streaming -import retrofit2.http.Url interface MicrogAPI { diff --git a/app/src/main/java/com/vanced/manager/installer/impl/MicrogInstaller.kt b/app/src/main/java/com/vanced/manager/installer/impl/MicrogInstaller.kt index 7654665dde..b756275ca4 100644 --- a/app/src/main/java/com/vanced/manager/installer/impl/MicrogInstaller.kt +++ b/app/src/main/java/com/vanced/manager/installer/impl/MicrogInstaller.kt @@ -1,10 +1,7 @@ package com.vanced.manager.installer.impl import com.vanced.manager.installer.base.AppInstaller -import com.vanced.manager.preferences.holder.managerVariantPref -import com.vanced.manager.preferences.holder.vancedVersionPref import com.xinto.apkhelper.installApk -import com.xinto.apkhelper.installSplitApks class MicrogInstaller : AppInstaller() { diff --git a/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt b/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt index f793ea0ad8..ab10f15e6d 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt @@ -20,7 +20,6 @@ import com.vanced.manager.ui.component.color.contentColorForColor import com.vanced.manager.ui.component.color.managerAccentColor import com.vanced.manager.ui.component.color.managerAnimatedColor import com.vanced.manager.ui.component.color.managerThemedCardColor -import com.vanced.manager.util.log @SuppressLint("UnusedTransitionTargetStateParameter") @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/navigation/ManagerNavigator.kt b/app/src/main/java/com/vanced/manager/ui/navigation/ManagerNavigator.kt index 37aaa916c4..baed2e916e 100644 --- a/app/src/main/java/com/vanced/manager/ui/navigation/ManagerNavigator.kt +++ b/app/src/main/java/com/vanced/manager/ui/navigation/ManagerNavigator.kt @@ -1,6 +1,9 @@ package com.vanced.manager.ui.navigation -import androidx.compose.animation.* +import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.AnimatedContentScope +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.with import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveableStateHolder diff --git a/app/src/main/java/com/vanced/manager/ui/navigation/NavigationController.kt b/app/src/main/java/com/vanced/manager/ui/navigation/NavigationController.kt index c34eb9e24c..5694ab745e 100644 --- a/app/src/main/java/com/vanced/manager/ui/navigation/NavigationController.kt +++ b/app/src/main/java/com/vanced/manager/ui/navigation/NavigationController.kt @@ -1,6 +1,8 @@ package com.vanced.manager.ui.navigation -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.remember import androidx.compose.runtime.snapshots.SnapshotStateList @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt index 6831066756..24ba315d9c 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt @@ -1,8 +1,8 @@ package com.vanced.manager.ui.screens import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.google.accompanist.swiperefresh.rememberSwipeRefreshState @@ -22,7 +22,7 @@ import org.koin.androidx.compose.getViewModel @Preview fun HomeLayout() { val viewModel: HomeViewModel = getViewModel() - val isFetching by viewModel.isFetching.observeAsState(false) + val isFetching by viewModel.isFetching.collectAsState() val refreshState = rememberSwipeRefreshState(isRefreshing = isFetching) ManagerSwipeRefresh( refreshState = refreshState, diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt index 43192e589d..f4737bb8f5 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt @@ -3,8 +3,6 @@ package com.vanced.manager.ui.viewmodel import android.content.Context import android.util.Log import androidx.compose.runtime.* -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.vanced.manager.domain.model.App @@ -12,6 +10,9 @@ import com.vanced.manager.preferences.holder.managerVariantPref import com.vanced.manager.preferences.holder.musicEnabled import com.vanced.manager.preferences.holder.vancedEnabled import com.vanced.manager.repository.JsonRepository +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch class HomeViewModel( @@ -19,18 +20,18 @@ class HomeViewModel( private val repository: JsonRepository ) : ViewModel() { - private val vanced = MutableLiveData<App>() - private val music = MutableLiveData<App>() - private val microg = MutableLiveData<App>() - private var manager = MutableLiveData<App>() + private val vanced = MutableStateFlow(App()) + private val music = MutableStateFlow(App()) + private val microg = MutableStateFlow(App()) + private var manager = MutableStateFlow(App()) - private val _isFetching = MutableLiveData<Boolean>() - val isFetching: LiveData<Boolean> = _isFetching + private val _isFetching = MutableStateFlow(false) + val isFetching: StateFlow<Boolean> = _isFetching - val apps = mutableListOf<LiveData<App>>() + val apps = mutableListOf<StateFlow<App>>() fun fetch() { - viewModelScope.launch { + viewModelScope.launch(Dispatchers.IO) { _isFetching.value = true try { with(repository.fetch()) { diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/AppsItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/AppsItem.kt index 3e8fb35fca..8aa1571b64 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/AppsItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/AppsItem.kt @@ -3,11 +3,10 @@ package com.vanced.manager.ui.widget.screens.home.apps import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEach -import com.vanced.manager.domain.model.App import com.vanced.manager.ui.viewmodel.HomeViewModel import com.vanced.manager.ui.widget.screens.home.apps.card.AppCard @@ -19,7 +18,7 @@ fun HomeAppsItem( verticalArrangement = Arrangement.spacedBy(8.dp) ) { viewModel.apps.fastForEach { app -> - val observedApp by app.observeAsState(initial = App()) + val observedApp by app.collectAsState() AppCard(observedApp, viewModel) } } From 35121cc67f18d8b5599690ca9731e62b1091948b Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Fri, 20 Aug 2021 12:24:47 +0400 Subject: [PATCH 050/118] renamed HomeViewModel --- .../main/java/com/vanced/manager/di/ViewModelModule.kt | 4 ++-- .../vanced/manager/downloader/base/AppDownloader.kt | 10 +++++----- .../vanced/manager/downloader/impl/MicrogDownloader.kt | 4 ++-- .../vanced/manager/downloader/impl/MusicDownloader.kt | 4 ++-- .../vanced/manager/downloader/impl/VancedDownloader.kt | 4 ++-- .../java/com/vanced/manager/ui/screens/HomeLayout.kt | 4 ++-- .../viewmodel/{HomeViewModel.kt => MainViewModel.kt} | 10 +++++----- .../manager/ui/widget/screens/home/apps/AppsItem.kt | 4 ++-- .../ui/widget/screens/home/apps/card/AppCard.kt | 4 ++-- 9 files changed, 24 insertions(+), 24 deletions(-) rename app/src/main/java/com/vanced/manager/ui/viewmodel/{HomeViewModel.kt => MainViewModel.kt} (86%) diff --git a/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt index 849857f789..8ebadbbf02 100644 --- a/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt +++ b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt @@ -1,9 +1,9 @@ package com.vanced.manager.di -import com.vanced.manager.ui.viewmodel.HomeViewModel +import com.vanced.manager.ui.viewmodel.MainViewModel import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.dsl.module val viewModelModule = module { - viewModel { HomeViewModel(get(), get()) } + viewModel { MainViewModel(get(), get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/base/AppDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/base/AppDownloader.kt index 632ff53d14..03b7433de4 100644 --- a/app/src/main/java/com/vanced/manager/downloader/base/AppDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/base/AppDownloader.kt @@ -6,7 +6,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import com.vanced.manager.domain.model.App import com.vanced.manager.installer.base.AppInstaller -import com.vanced.manager.ui.viewmodel.HomeViewModel +import com.vanced.manager.ui.viewmodel.MainViewModel import com.vanced.manager.util.log import okhttp3.ResponseBody import org.koin.core.component.KoinComponent @@ -58,10 +58,10 @@ abstract class AppDownloader( abstract suspend fun download( app: App, - viewModel: HomeViewModel + viewModel: MainViewModel ) - private fun install(viewModel: HomeViewModel) { + private fun install(viewModel: MainViewModel) { installing = true appInstaller.install { viewModel.fetch() @@ -71,7 +71,7 @@ abstract class AppDownloader( suspend fun downloadFile( file: File, - viewModel: HomeViewModel, + viewModel: MainViewModel, folderStructure: String, onError: (error: String) -> Unit = {}, ) { @@ -85,7 +85,7 @@ abstract class AppDownloader( suspend fun downloadFiles( files: List<File>, - viewModel: HomeViewModel, + viewModel: MainViewModel, folderStructure: String, onError: (error: String) -> Unit = {}, ) { diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt index 5a6b1e58a4..0dc5ef007b 100644 --- a/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt @@ -4,7 +4,7 @@ import com.vanced.manager.domain.model.App import com.vanced.manager.downloader.api.MicrogAPI import com.vanced.manager.downloader.base.AppDownloader import com.vanced.manager.installer.impl.MicrogInstaller -import com.vanced.manager.ui.viewmodel.HomeViewModel +import com.vanced.manager.ui.viewmodel.MainViewModel class MicrogDownloader( microgInstaller: MicrogInstaller, @@ -16,7 +16,7 @@ class MicrogDownloader( override suspend fun download( app: App, - viewModel: HomeViewModel + viewModel: MainViewModel ) { downloadFile( file = File( diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt index 73374b760d..35b6448d2c 100644 --- a/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt @@ -6,7 +6,7 @@ import com.vanced.manager.downloader.base.AppDownloader import com.vanced.manager.installer.impl.MusicInstaller import com.vanced.manager.preferences.holder.managerVariantPref import com.vanced.manager.preferences.holder.musicVersionPref -import com.vanced.manager.ui.viewmodel.HomeViewModel +import com.vanced.manager.ui.viewmodel.MainViewModel class MusicDownloader( musicInstaller: MusicInstaller, @@ -21,7 +21,7 @@ class MusicDownloader( override suspend fun download( app: App, - viewModel: HomeViewModel + viewModel: MainViewModel ) { downloadFile( file = File( diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt index f4cfb59415..e02989de7f 100644 --- a/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt @@ -8,7 +8,7 @@ import com.vanced.manager.preferences.holder.managerVariantPref import com.vanced.manager.preferences.holder.vancedLanguagesPref import com.vanced.manager.preferences.holder.vancedThemePref import com.vanced.manager.preferences.holder.vancedVersionPref -import com.vanced.manager.ui.viewmodel.HomeViewModel +import com.vanced.manager.ui.viewmodel.MainViewModel import com.vanced.manager.util.arch import com.vanced.manager.util.log @@ -27,7 +27,7 @@ class VancedDownloader( override suspend fun download( app: App, - viewModel: HomeViewModel + viewModel: MainViewModel ) { val files = listOf( getFile( diff --git a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt index 24ba315d9c..ab8eedd312 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt @@ -11,7 +11,7 @@ import com.vanced.manager.ui.component.layout.ManagerScrollableColumn import com.vanced.manager.ui.component.layout.ManagerSwipeRefresh import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.util.defaultContentPaddingVertical -import com.vanced.manager.ui.viewmodel.HomeViewModel +import com.vanced.manager.ui.viewmodel.MainViewModel import com.vanced.manager.ui.widget.layout.CategoryLayout import com.vanced.manager.ui.widget.screens.home.apps.HomeAppsItem import com.vanced.manager.ui.widget.screens.home.socialmedia.HomeSocialMediaItem @@ -21,7 +21,7 @@ import org.koin.androidx.compose.getViewModel @Composable @Preview fun HomeLayout() { - val viewModel: HomeViewModel = getViewModel() + val viewModel: MainViewModel = getViewModel() val isFetching by viewModel.isFetching.collectAsState() val refreshState = rememberSwipeRefreshState(isRefreshing = isFetching) ManagerSwipeRefresh( diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt similarity index 86% rename from app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt rename to app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt index f4737bb8f5..94289fc4b5 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/HomeViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt @@ -15,7 +15,7 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch -class HomeViewModel( +class MainViewModel( context: Context, private val repository: JsonRepository ) : ViewModel() { @@ -23,7 +23,7 @@ class HomeViewModel( private val vanced = MutableStateFlow(App()) private val music = MutableStateFlow(App()) private val microg = MutableStateFlow(App()) - private var manager = MutableStateFlow(App()) + private val manager = MutableStateFlow(App()) private val _isFetching = MutableStateFlow(false) val isFetching: StateFlow<Boolean> = _isFetching @@ -35,9 +35,9 @@ class HomeViewModel( _isFetching.value = true try { with(repository.fetch()) { - this@HomeViewModel.vanced.value = vanced - this@HomeViewModel.music.value = music - this@HomeViewModel.microg.value = microg + this@MainViewModel.vanced.value = vanced + this@MainViewModel.music.value = music + this@MainViewModel.microg.value = microg } } catch (e: Exception) { Log.d("HomeViewModel", "failed to fetch: $e") diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/AppsItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/AppsItem.kt index 8aa1571b64..b5c7980ae4 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/AppsItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/AppsItem.kt @@ -7,12 +7,12 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEach -import com.vanced.manager.ui.viewmodel.HomeViewModel +import com.vanced.manager.ui.viewmodel.MainViewModel import com.vanced.manager.ui.widget.screens.home.apps.card.AppCard @Composable fun HomeAppsItem( - viewModel: HomeViewModel + viewModel: MainViewModel ) { Column( verticalArrangement = Arrangement.spacedBy(8.dp) diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppCard.kt index 1333437a92..b3a775b65c 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppCard.kt @@ -19,7 +19,7 @@ import com.vanced.manager.ui.component.card.ManagerThemedCard import com.vanced.manager.ui.component.layout.ManagerButtonColumn import com.vanced.manager.ui.util.defaultContentPaddingHorizontal import com.vanced.manager.ui.util.defaultContentPaddingVertical -import com.vanced.manager.ui.viewmodel.HomeViewModel +import com.vanced.manager.ui.viewmodel.MainViewModel import com.vanced.manager.ui.widget.button.ManagerCancelButton import com.vanced.manager.ui.widget.button.ManagerDownloadButton import com.vanced.manager.ui.widget.screens.home.apps.dialog.AppChangelogDialog @@ -31,7 +31,7 @@ import kotlinx.coroutines.launch @Composable fun AppCard( app: App, - viewModel: HomeViewModel + viewModel: MainViewModel ) { var showAppInfoDialog by rememberSaveable { mutableStateOf(false) } var showInstallationOptions by rememberSaveable { mutableStateOf(false) } From 459677ad7be61573b53968815dc619b9f4471920 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Fri, 20 Aug 2021 12:26:12 +0400 Subject: [PATCH 051/118] removed context parameter from MainViewModel --- app/src/main/java/com/vanced/manager/di/ViewModelModule.kt | 2 +- .../main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt index 8ebadbbf02..c561df6a03 100644 --- a/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt +++ b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt @@ -5,5 +5,5 @@ import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.dsl.module val viewModelModule = module { - viewModel { MainViewModel(get(), get()) } + viewModel { MainViewModel(get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt index 94289fc4b5..569de47400 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt @@ -1,6 +1,5 @@ package com.vanced.manager.ui.viewmodel -import android.content.Context import android.util.Log import androidx.compose.runtime.* import androidx.lifecycle.ViewModel @@ -16,7 +15,6 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch class MainViewModel( - context: Context, private val repository: JsonRepository ) : ViewModel() { From 02a3bd87b31db2248e9b5d78c1053076983f29c9 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Fri, 20 Aug 2021 12:28:33 +0400 Subject: [PATCH 052/118] adjusted dropdown manu item text style --- .../vanced/manager/ui/component/menu/ManagerDropdownMenuItem.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenuItem.kt b/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenuItem.kt index 8e75fe6a1e..632b9edadd 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenuItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenuItem.kt @@ -15,7 +15,7 @@ fun ManagerDropdownMenuItem( ) { ManagerText( text = title, - textStyle = MaterialTheme.typography.body1 + textStyle = MaterialTheme.typography.h6 ) } } \ No newline at end of file From f4f89119220540ac158f5a018309992939acf730 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 24 Aug 2021 12:23:26 +0400 Subject: [PATCH 053/118] improved version selector --- .../com/vanced/manager/di/MapperModule.kt | 9 ++------- .../downloader/impl/MusicDownloader.kt | 9 +++++++-- .../downloader/impl/VancedDownloader.kt | 20 +++++++++++++++---- .../manager/network/model/AppDtoMapper.kt | 19 +++++++++++++----- .../java/com/vanced/manager/util/AppHelper.kt | 13 ++++++++++++ 5 files changed, 52 insertions(+), 18 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/util/AppHelper.kt diff --git a/app/src/main/java/com/vanced/manager/di/MapperModule.kt b/app/src/main/java/com/vanced/manager/di/MapperModule.kt index c789da0848..c55cc79b09 100644 --- a/app/src/main/java/com/vanced/manager/di/MapperModule.kt +++ b/app/src/main/java/com/vanced/manager/di/MapperModule.kt @@ -1,17 +1,12 @@ package com.vanced.manager.di -import com.vanced.manager.domain.datasource.PackageInformationDataSource import com.vanced.manager.network.model.AppDtoMapper import com.vanced.manager.network.model.JsonDtoMapper import org.koin.dsl.module val mapperModule = module { - fun provideAppMapper( - packageInformationDataSource: PackageInformationDataSource, - ): AppDtoMapper = AppDtoMapper( - packageInformationDataSource = packageInformationDataSource - ) + fun provideAppMapper(): AppDtoMapper = AppDtoMapper() fun provideJsonMapper( appDtoMapper: AppDtoMapper @@ -19,6 +14,6 @@ val mapperModule = module { appDtoMapper = appDtoMapper ) - single { provideAppMapper(get()) } + single { provideAppMapper() } single { provideJsonMapper(get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt index 35b6448d2c..9fbcb16cdb 100644 --- a/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt @@ -7,6 +7,7 @@ import com.vanced.manager.installer.impl.MusicInstaller import com.vanced.manager.preferences.holder.managerVariantPref import com.vanced.manager.preferences.holder.musicVersionPref import com.vanced.manager.ui.viewmodel.MainViewModel +import com.vanced.manager.util.getLatestOrProvidedAppVersion class MusicDownloader( musicInstaller: MusicInstaller, @@ -23,16 +24,20 @@ class MusicDownloader( app: App, viewModel: MainViewModel ) { + val correctVersion = getLatestOrProvidedAppVersion( + version = version, + app = app + ) downloadFile( file = File( call = musicAPI.getFiles( - version = version, + version = correctVersion, variant = variant, ), fileName = "music.apk" ), viewModel = viewModel, - folderStructure = "$version/$variant" + folderStructure = "$correctVersion/$variant" ) } diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt index e02989de7f..7e11980881 100644 --- a/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt @@ -10,6 +10,7 @@ import com.vanced.manager.preferences.holder.vancedThemePref import com.vanced.manager.preferences.holder.vancedVersionPref import com.vanced.manager.ui.viewmodel.MainViewModel import com.vanced.manager.util.arch +import com.vanced.manager.util.getLatestOrProvidedAppVersion import com.vanced.manager.util.log class VancedDownloader( @@ -29,22 +30,32 @@ class VancedDownloader( app: App, viewModel: MainViewModel ) { + val correctVersion = getLatestOrProvidedAppVersion( + version = version, + app = app + ) val files = listOf( getFile( type = "Theme", - apkName = "$theme.apk" + apkName = "$theme.apk", + version = correctVersion ), getFile( type = "Arch", - apkName = "split_config.$arch.apk" + apkName = "split_config.$arch.apk", + version = correctVersion ) ) + languages.map { language -> - getFile("Language", "split_config.$language.apk") + getFile( + type = "Language", + apkName = "split_config.$language.apk", + version = correctVersion + ) } downloadFiles( files = files, viewModel, - folderStructure = "$version/$variant", + folderStructure = "$correctVersion/$variant", onError = { log("error", it) } @@ -54,6 +65,7 @@ class VancedDownloader( private fun getFile( type: String, apkName: String, + version: String, ) = File( call = vancedAPI.getFiles( version = version, diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt index f0f2102c97..6c105ac405 100644 --- a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt +++ b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt @@ -1,5 +1,6 @@ package com.vanced.manager.network.model +import android.content.Context import com.vanced.manager.R import com.vanced.manager.domain.datasource.PackageInformationDataSource import com.vanced.manager.domain.model.App @@ -23,11 +24,19 @@ import com.vanced.manager.ui.widget.screens.home.installation.InstallationOption import com.vanced.manager.ui.widget.screens.home.installation.RadiobuttonInstallationOption import org.koin.core.component.KoinComponent import org.koin.core.component.get +import org.koin.core.component.inject import java.util.* -class AppDtoMapper( - private val packageInformationDataSource: PackageInformationDataSource -) : EntityMapper<AppDto, App>, KoinComponent { +class AppDtoMapper : EntityMapper<AppDto, App>, KoinComponent { + + private val packageInformationDataSource: PackageInformationDataSource by inject() + private val context: Context by inject() + + private val latestVersionRadioButton = + RadioButtonPreference( + title = context.getString(R.string.app_version_dialog_option_latest), + key = "latest" + ) override suspend fun mapToModel(entity: AppDto): App = with (entity) { @@ -90,7 +99,7 @@ class AppDtoMapper( title = it, key = it ) - } ?: emptyList() + }?.plus(latestVersionRadioButton)?.reversed() ?: emptyList() ), CheckboxInstallationOption( titleId = R.string.app_installation_options_language, @@ -112,7 +121,7 @@ class AppDtoMapper( title = it, key = it ) - } ?: emptyList() + }?.plus(latestVersionRadioButton)?.reversed() ?: emptyList() ), ) else -> null diff --git a/app/src/main/java/com/vanced/manager/util/AppHelper.kt b/app/src/main/java/com/vanced/manager/util/AppHelper.kt new file mode 100644 index 0000000000..bd7abb3c69 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/util/AppHelper.kt @@ -0,0 +1,13 @@ +package com.vanced.manager.util + +import com.vanced.manager.domain.model.App + +fun getLatestOrProvidedAppVersion( + version: String, + app: App +): String { + if (version == "latest") { + return app.versions?.last() ?: version + } + return version +} \ No newline at end of file From 6ca18c43eb0ec0286938b20fca83e5a9a3836914 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 24 Aug 2021 12:42:53 +0400 Subject: [PATCH 054/118] separated animations from checkbox and radiobutton --- .../{SpringAnimation.kt => JumpAnimation.kt} | 2 +- .../ui/component/checkbox/ManagerCheckbox.kt | 39 ++++++++++--------- .../manager/ui/component/list/CheckboxItem.kt | 3 +- .../ui/component/list/RadiobuttonItem.kt | 3 +- .../preference/CheckboxPreference.kt | 4 +- .../radiobutton/ManagerRadiobutton.kt | 11 +----- .../checkbox/ManagerAnimatedCheckbox.kt | 35 +++++++++++++++++ .../radiobutton/ManagerAnimatedRadiobutton.kt | 35 +++++++++++++++++ 8 files changed, 100 insertions(+), 32 deletions(-) rename app/src/main/java/com/vanced/manager/ui/component/animation/{SpringAnimation.kt => JumpAnimation.kt} (94%) create mode 100644 app/src/main/java/com/vanced/manager/ui/widget/checkbox/ManagerAnimatedCheckbox.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widget/radiobutton/ManagerAnimatedRadiobutton.kt diff --git a/app/src/main/java/com/vanced/manager/ui/component/animation/SpringAnimation.kt b/app/src/main/java/com/vanced/manager/ui/component/animation/JumpAnimation.kt similarity index 94% rename from app/src/main/java/com/vanced/manager/ui/component/animation/SpringAnimation.kt rename to app/src/main/java/com/vanced/manager/ui/component/animation/JumpAnimation.kt index 6bad604461..4bf21c2453 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/animation/SpringAnimation.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/animation/JumpAnimation.kt @@ -10,7 +10,7 @@ import androidx.compose.ui.unit.dp @SuppressLint("UnusedTransitionTargetStateParameter") @Composable -fun <T> Transition<T>.springAnimation( +fun <T> Transition<T>.jumpAnimation( initialValue: Dp, label: String ) = animateDp( diff --git a/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt b/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt index ab10f15e6d..8dbc857040 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt @@ -1,20 +1,17 @@ package com.vanced.manager.ui.component.checkbox import android.annotation.SuppressLint -import androidx.compose.animation.core.updateTransition -import androidx.compose.foundation.layout.requiredSize -import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.requiredSizeIn import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.Close import androidx.compose.material.icons.rounded.Done import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.unit.Dp -import com.vanced.manager.ui.component.animation.springAnimation import com.vanced.manager.ui.component.card.ManagerCard import com.vanced.manager.ui.component.color.contentColorForColor import com.vanced.manager.ui.component.color.managerAccentColor @@ -24,28 +21,34 @@ import com.vanced.manager.ui.component.color.managerThemedCardColor @SuppressLint("UnusedTransitionTargetStateParameter") @Composable fun ManagerCheckbox( - size: Dp, + modifier: Modifier, isChecked: Boolean, shape: Shape = MaterialTheme.shapes.medium, onCheckedChange: (isChecked: Boolean) -> Unit ) { - val transition = updateTransition(targetState = isChecked, label = "Checked") - val cardSize by transition.springAnimation(initialValue = size, label = "Checkbox Size") - val iconSize = cardSize / 1.6f val cardColor = managerAnimatedColor(if (isChecked) managerAccentColor() else managerThemedCardColor()) val iconTint = managerAnimatedColor(if (isChecked) contentColorForColor(cardColor) else managerAccentColor()) - + ManagerCard( - modifier = Modifier.size(cardSize), + modifier = modifier, shape = shape, onClick = { onCheckedChange(!isChecked) }, backgroundColor = cardColor ) { - Icon( - modifier = Modifier.requiredSize(iconSize), - imageVector = if (isChecked) Icons.Rounded.Done else Icons.Rounded.Close, - tint = iconTint, - contentDescription = null - ) + BoxWithConstraints { + Icon( + modifier = Modifier + .requiredSizeIn( + minWidth = minWidth / 1.6f, + minHeight = minHeight / 1.6f, + maxWidth = maxWidth / 1.6f, + maxHeight = maxHeight / 1.6f, + ) + .align(Alignment.Center), + imageVector = if (isChecked) Icons.Rounded.Done else Icons.Rounded.Close, + tint = iconTint, + contentDescription = null + ) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/list/CheckboxItem.kt b/app/src/main/java/com/vanced/manager/ui/component/list/CheckboxItem.kt index ef2ffe812f..bbc75e30be 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/list/CheckboxItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/list/CheckboxItem.kt @@ -11,6 +11,7 @@ import androidx.compose.ui.unit.sp import com.vanced.manager.ui.component.checkbox.ManagerCheckbox import com.vanced.manager.ui.component.color.managerTextColor import com.vanced.manager.ui.component.modifier.managerClickable +import com.vanced.manager.ui.widget.checkbox.ManagerAnimatedCheckbox @Composable fun CheckboxItem( @@ -31,7 +32,7 @@ fun CheckboxItem( modifier = Modifier.size(30.dp), contentAlignment = Alignment.Center ) { - ManagerCheckbox( + ManagerAnimatedCheckbox( size = 24.dp, shape = CircleShape, isChecked = isChecked diff --git a/app/src/main/java/com/vanced/manager/ui/component/list/RadiobuttonItem.kt b/app/src/main/java/com/vanced/manager/ui/component/list/RadiobuttonItem.kt index 8d2af13f78..ef4c2f1a6c 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/list/RadiobuttonItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/list/RadiobuttonItem.kt @@ -11,6 +11,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.vanced.manager.ui.component.color.managerTextColor import com.vanced.manager.ui.component.radiobutton.ManagerRadiobutton +import com.vanced.manager.ui.widget.radiobutton.ManagerAnimatedRadiobutton @Composable fun <T> RadiobuttonItem( @@ -32,7 +33,7 @@ fun <T> RadiobuttonItem( modifier = Modifier.size(30.dp), contentAlignment = Alignment.Center ) { - ManagerRadiobutton( + ManagerAnimatedRadiobutton( size = 24.dp, shape = CircleShape, isSelected = isSelected, diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt index d08608e0c1..abe2a15616 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt @@ -4,7 +4,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.unit.dp import com.vanced.manager.preferences.ManagerPreference -import com.vanced.manager.ui.component.checkbox.ManagerCheckbox +import com.vanced.manager.ui.widget.checkbox.ManagerAnimatedCheckbox import kotlinx.coroutines.launch @Composable @@ -28,7 +28,7 @@ fun CheckboxPreference( preferenceDescription = preferenceDescription, onClick = onClick, trailing = { - ManagerCheckbox( + ManagerAnimatedCheckbox( isChecked = isChecked, onCheckedChange = { onClick() }, size = 40.dp diff --git a/app/src/main/java/com/vanced/manager/ui/component/radiobutton/ManagerRadiobutton.kt b/app/src/main/java/com/vanced/manager/ui/component/radiobutton/ManagerRadiobutton.kt index 40417488fb..2a7190394b 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/radiobutton/ManagerRadiobutton.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/radiobutton/ManagerRadiobutton.kt @@ -1,15 +1,10 @@ package com.vanced.manager.ui.component.radiobutton import android.annotation.SuppressLint -import androidx.compose.animation.core.updateTransition -import androidx.compose.foundation.layout.size import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.unit.Dp -import com.vanced.manager.ui.component.animation.springAnimation import com.vanced.manager.ui.component.card.ManagerCard import com.vanced.manager.ui.component.color.managerAccentColor import com.vanced.manager.ui.component.color.managerAnimatedColor @@ -18,17 +13,15 @@ import com.vanced.manager.ui.component.color.managerThemedCardColor @SuppressLint("UnusedTransitionTargetStateParameter") @Composable fun ManagerRadiobutton( - size: Dp, + modifier: Modifier, isSelected: Boolean, shape: Shape = MaterialTheme.shapes.medium, onClick: () -> Unit ) { val accentColor = managerAccentColor() - val transition = updateTransition(targetState = isSelected, label = "Selected") - val cardSize by transition.springAnimation(initialValue = size, label = "Radiobutton Size") val cardColor = managerAnimatedColor(if (isSelected) accentColor else managerThemedCardColor()) ManagerCard( - modifier = Modifier.size(cardSize), + modifier = modifier, onClick = onClick, shape = shape, backgroundColor = cardColor, diff --git a/app/src/main/java/com/vanced/manager/ui/widget/checkbox/ManagerAnimatedCheckbox.kt b/app/src/main/java/com/vanced/manager/ui/widget/checkbox/ManagerAnimatedCheckbox.kt new file mode 100644 index 0000000000..82d93be5d1 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widget/checkbox/ManagerAnimatedCheckbox.kt @@ -0,0 +1,35 @@ +package com.vanced.manager.ui.widget.checkbox + +import androidx.compose.animation.core.updateTransition +import androidx.compose.foundation.layout.size +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.unit.Dp +import com.vanced.manager.ui.component.animation.jumpAnimation +import com.vanced.manager.ui.component.checkbox.ManagerCheckbox + +@Composable +fun ManagerAnimatedCheckbox( + size: Dp, + isChecked: Boolean, + shape: Shape = MaterialTheme.shapes.medium, + onCheckedChange: (isChecked: Boolean) -> Unit, +) { + val transition = updateTransition( + targetState = isChecked, + label = "Checkbox Animation" + ) + val animatedSize by transition.jumpAnimation( + initialValue = size, + label = "Checkbox Size" + ) + ManagerCheckbox( + modifier = Modifier.size(animatedSize), + isChecked = isChecked, + shape = shape, + onCheckedChange = onCheckedChange + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/radiobutton/ManagerAnimatedRadiobutton.kt b/app/src/main/java/com/vanced/manager/ui/widget/radiobutton/ManagerAnimatedRadiobutton.kt new file mode 100644 index 0000000000..b3fb64c071 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widget/radiobutton/ManagerAnimatedRadiobutton.kt @@ -0,0 +1,35 @@ +package com.vanced.manager.ui.widget.radiobutton + +import androidx.compose.animation.core.updateTransition +import androidx.compose.foundation.layout.size +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.unit.Dp +import com.vanced.manager.ui.component.animation.jumpAnimation +import com.vanced.manager.ui.component.radiobutton.ManagerRadiobutton + +@Composable +fun ManagerAnimatedRadiobutton( + size: Dp, + isSelected: Boolean, + shape: Shape = MaterialTheme.shapes.medium, + onClick: () -> Unit +) { + val transition = updateTransition( + targetState = isSelected, + label = "Radiobutton Animation" + ) + val animatedSize by transition.jumpAnimation( + initialValue = size, + label = "Checkbox Size" + ) + ManagerRadiobutton( + modifier = Modifier.size(animatedSize), + isSelected = isSelected, + shape = shape, + onClick = onClick + ) +} \ No newline at end of file From 9067811a6aadbb5f22c9b7deb928880f84d9a740 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 24 Aug 2021 12:53:29 +0400 Subject: [PATCH 055/118] improved UI of link cards --- .../com/vanced/manager/ui/component/card/ManagerItemCard.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerItemCard.kt b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerItemCard.kt index 6cddd8b1ae..245b7311c1 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerItemCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerItemCard.kt @@ -54,10 +54,11 @@ private fun ManagerItemCardContent( @DrawableRes icon: Int? = null, ) { val accentColor = managerAccentColor() + val circleOffset = 32.dp.value Canvas(modifier = Modifier.requiredSize(72.dp)) { drawCircle( color = accentColor, - center = Offset(32f,32f) + center = Offset(circleOffset, circleOffset) ) } Box( From a2a4057ac64ca9fbdabe3ff6a4e3e344c7a60e03 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 24 Aug 2021 13:27:06 +0400 Subject: [PATCH 056/118] moved checkbox and radiobutton list items to widget namespace --- .../list/ManagerSelectableListItem.kt | 2 ++ .../list/CheckboxItem.kt | 27 +++++++---------- .../list/RadiobuttonItem.kt | 29 ++++++++----------- 3 files changed, 25 insertions(+), 33 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/ui/component/list/ManagerSelectableListItem.kt rename app/src/main/java/com/vanced/manager/ui/{component => widget}/list/CheckboxItem.kt (68%) rename app/src/main/java/com/vanced/manager/ui/{component => widget}/list/RadiobuttonItem.kt (69%) diff --git a/app/src/main/java/com/vanced/manager/ui/component/list/ManagerSelectableListItem.kt b/app/src/main/java/com/vanced/manager/ui/component/list/ManagerSelectableListItem.kt new file mode 100644 index 0000000000..ea1435fbe3 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/component/list/ManagerSelectableListItem.kt @@ -0,0 +1,2 @@ +package com.vanced.manager.ui.component.list + diff --git a/app/src/main/java/com/vanced/manager/ui/component/list/CheckboxItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt similarity index 68% rename from app/src/main/java/com/vanced/manager/ui/component/list/CheckboxItem.kt rename to app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt index bbc75e30be..8555395296 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/list/CheckboxItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt @@ -21,17 +21,18 @@ fun CheckboxItem( ) { val toggle = { onCheck(!isChecked) } - Row( + ManagerSelectableListItem( modifier = Modifier .fillMaxWidth() - .managerClickable(onClick = toggle) - .padding(horizontal = 8.dp, vertical = 6.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Box( - modifier = Modifier.size(30.dp), - contentAlignment = Alignment.Center - ) { + .managerClickable(onClick = toggle), + title = { + Text( + text = text, + color = managerTextColor(), + fontSize = 18.sp + ) + }, + trailing = { ManagerAnimatedCheckbox( size = 24.dp, shape = CircleShape, @@ -40,11 +41,5 @@ fun CheckboxItem( toggle() } } - Text( - modifier = Modifier.padding(start = 12.dp), - text = text, - color = managerTextColor(), - fontSize = 18.sp - ) - } + ) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/list/RadiobuttonItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt similarity index 69% rename from app/src/main/java/com/vanced/manager/ui/component/list/RadiobuttonItem.kt rename to app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt index ef4c2f1a6c..24b0ad94e6 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/list/RadiobuttonItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt @@ -10,6 +10,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.vanced.manager.ui.component.color.managerTextColor +import com.vanced.manager.ui.component.modifier.managerClickable import com.vanced.manager.ui.component.radiobutton.ManagerRadiobutton import com.vanced.manager.ui.widget.radiobutton.ManagerAnimatedRadiobutton @@ -21,18 +22,18 @@ fun <T> RadiobuttonItem( onSelect: (tag: T) -> Unit ) { val onClick = { onSelect(tag) } - - Row( + ManagerSelectableListItem( modifier = Modifier .fillMaxWidth() - .clickable(onClick = onClick) - .padding(horizontal = 8.dp, vertical = 6.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Box( - modifier = Modifier.size(30.dp), - contentAlignment = Alignment.Center - ) { + .managerClickable(onClick = onClick), + title = { + Text( + text = text, + color = managerTextColor(), + fontSize = 18.sp + ) + }, + trailing = { ManagerAnimatedRadiobutton( size = 24.dp, shape = CircleShape, @@ -40,11 +41,5 @@ fun <T> RadiobuttonItem( onClick = onClick ) } - Text( - modifier = Modifier.padding(start = 12.dp), - text = text, - color = managerTextColor(), - fontSize = 18.sp - ) - } + ) } \ No newline at end of file From c84807d723bfe6798cfecdc23854e50eaba935a7 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 24 Aug 2021 13:27:28 +0400 Subject: [PATCH 057/118] UI adjustments --- .../ui/component/dialog/ManagerDialog.kt | 3 +- .../list/ManagerSelectableListItem.kt | 37 +++++++++++++++++++ .../preference/CheckboxDialogPreference.kt | 2 +- .../preference/RadiobuttonDialogPreference.kt | 2 +- .../java/com/vanced/manager/ui/theme/Type.kt | 4 ++ .../manager/ui/widget/list/CheckboxItem.kt | 5 +-- .../manager/ui/widget/list/RadiobuttonItem.kt | 6 +-- .../home/apps/dialog/AppDownloadDialog.kt | 13 +++++++ 8 files changed, 62 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt b/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt index 12b7fa1a97..78e63c5234 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt @@ -10,6 +10,7 @@ import androidx.compose.ui.window.Dialog import com.vanced.manager.ui.component.card.ManagerCard import com.vanced.manager.ui.component.text.ManagerText import com.vanced.manager.ui.util.defaultContentPaddingHorizontal +import com.vanced.manager.ui.util.defaultContentPaddingVertical @Composable fun ManagerDialog( @@ -47,7 +48,7 @@ fun ManagerDialog( ManagerCard { Column( modifier = Modifier.padding(defaultContentPaddingHorizontal), - verticalArrangement = Arrangement.spacedBy(8.dp) + verticalArrangement = Arrangement.spacedBy(defaultContentPaddingVertical) ) { title() content() diff --git a/app/src/main/java/com/vanced/manager/ui/component/list/ManagerSelectableListItem.kt b/app/src/main/java/com/vanced/manager/ui/component/list/ManagerSelectableListItem.kt index ea1435fbe3..f7b6f6fb50 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/list/ManagerSelectableListItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/list/ManagerSelectableListItem.kt @@ -1,2 +1,39 @@ package com.vanced.manager.ui.component.list +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +@Composable +fun ManagerSelectableListItem( + modifier: Modifier = Modifier, + title: @Composable () -> Unit, + trailing: @Composable (() -> Unit) +) { + Row( + modifier = modifier + .padding(vertical = 8.dp, horizontal = 6.dp) + ) { + Box( + modifier = Modifier + .weight(1f) + .padding(horizontal = 6.dp) + .align(Alignment.CenterVertically), + ) { + title() + } + Box( + modifier = Modifier + .size(30.dp) + .align(Alignment.CenterVertically), + contentAlignment = Alignment.Center, + ) { + trailing() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt index 0b1e384e45..203e357d90 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt @@ -15,7 +15,7 @@ import com.vanced.manager.R import com.vanced.manager.preferences.CheckboxPreference import com.vanced.manager.preferences.ManagerPreference import com.vanced.manager.ui.component.button.ManagerThemedTextButton -import com.vanced.manager.ui.component.list.CheckboxItem +import com.vanced.manager.ui.widget.list.CheckboxItem import kotlinx.coroutines.launch @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt index af12f99890..26bdac64da 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt @@ -8,7 +8,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.vanced.manager.preferences.ManagerPreference import com.vanced.manager.preferences.RadioButtonPreference -import com.vanced.manager.ui.component.list.RadiobuttonItem +import com.vanced.manager.ui.widget.list.RadiobuttonItem import com.vanced.manager.ui.widget.button.ManagerSaveButton import kotlinx.coroutines.launch diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Type.kt b/app/src/main/java/com/vanced/manager/ui/theme/Type.kt index b271cc387a..741a260083 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Type.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Type.kt @@ -47,6 +47,10 @@ val typography = Typography( fontWeight = FontWeight.Normal, fontSize = 12.sp, ), + subtitle2 = TextStyle( + fontWeight = FontWeight.Normal, + fontSize = 14.sp + ), button = TextStyle( fontSize = 14.sp, fontWeight = FontWeight.Medium diff --git a/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt index 8555395296..0cb2d33db3 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt @@ -1,15 +1,14 @@ -package com.vanced.manager.ui.component.list +package com.vanced.manager.ui.widget.list import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.vanced.manager.ui.component.checkbox.ManagerCheckbox import com.vanced.manager.ui.component.color.managerTextColor +import com.vanced.manager.ui.component.list.ManagerSelectableListItem import com.vanced.manager.ui.component.modifier.managerClickable import com.vanced.manager.ui.widget.checkbox.ManagerAnimatedCheckbox diff --git a/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt index 24b0ad94e6..e7e02f9abc 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt @@ -1,17 +1,15 @@ -package com.vanced.manager.ui.component.list +package com.vanced.manager.ui.widget.list -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.Text import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.vanced.manager.ui.component.color.managerTextColor +import com.vanced.manager.ui.component.list.ManagerSelectableListItem import com.vanced.manager.ui.component.modifier.managerClickable -import com.vanced.manager.ui.component.radiobutton.ManagerRadiobutton import com.vanced.manager.ui.widget.radiobutton.ManagerAnimatedRadiobutton @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/dialog/AppDownloadDialog.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/dialog/AppDownloadDialog.kt index e96c866820..4b6a0b8091 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/dialog/AppDownloadDialog.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/dialog/AppDownloadDialog.kt @@ -1,8 +1,15 @@ package com.vanced.manager.ui.widget.screens.home.apps.dialog +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import com.vanced.manager.R import com.vanced.manager.downloader.base.AppDownloader import com.vanced.manager.ui.component.dialog.ManagerDialog +import com.vanced.manager.ui.component.text.ManagerText import com.vanced.manager.ui.widget.button.ManagerCancelButton import com.vanced.manager.ui.widget.screens.home.download.AppDownloadDialogProgress @@ -19,6 +26,12 @@ fun AppDownloadDialog( ManagerCancelButton(onClick = onCancelClick) } ) { + ManagerText( + modifier = Modifier.fillMaxWidth(), + text = stringResource(id = R.string.app_download_dialog_subtitle), + textStyle = MaterialTheme.typography.subtitle2, + textAlign = TextAlign.Center + ) AppDownloadDialogProgress( progress = downloader.downloadProgress, file = downloader.downloadFile, From 6170da7f35a5e1a3654f859214c78a97e7a3b665 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 24 Aug 2021 13:38:11 +0400 Subject: [PATCH 058/118] changed home page title to Vanced Manager --- app/src/main/java/com/vanced/manager/ui/util/Screen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/vanced/manager/ui/util/Screen.kt b/app/src/main/java/com/vanced/manager/ui/util/Screen.kt index ca716056ff..769139ace8 100644 --- a/app/src/main/java/com/vanced/manager/ui/util/Screen.kt +++ b/app/src/main/java/com/vanced/manager/ui/util/Screen.kt @@ -16,7 +16,7 @@ sealed class Screen( object Home : Screen( route = "home", - displayName = R.string.toolbar_home, + displayName = R.string.app_name, content = { HomeLayout() } From 656f7e5d7bed9f9d21b27832295ae5703c00d50d Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Fri, 24 Sep 2021 19:27:56 +0400 Subject: [PATCH 059/118] update deps --- app/build.gradle.kts | 22 ++++++++++++---------- build.gradle.kts | 4 ++-- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 315c578d56..9c68ddfd03 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -43,19 +43,19 @@ android { // To inline the bytecode built with JVM target 1.8 into // bytecode that is being built with JVM target 1.6. (e.g. navArgs) compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 } composeOptions { - kotlinCompilerExtensionVersion = "1.0.1" + kotlinCompilerExtensionVersion = "1.1.0-alpha04" } } tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> { kotlinOptions { - jvmTarget = "1.8" + jvmTarget = "11" freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn" } } @@ -84,7 +84,7 @@ dependencies { implementation("com.google.android.material:material:1.4.0") implementation("androidx.browser:browser:1.3.0") - val composeVersion = "1.0.1" + val composeVersion = "1.1.0-alpha04" implementation("androidx.compose.compiler:compiler:$composeVersion") implementation("androidx.compose.foundation:foundation:$composeVersion") implementation("androidx.compose.material:material-icons-core:$composeVersion") @@ -99,18 +99,20 @@ dependencies { implementation("androidx.preference:preference-ktx:1.1.1") implementation("androidx.activity:activity-compose:1.3.1") - implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-alpha03") - implementation("androidx.lifecycle:lifecycle-viewmodel-compose:1.0.0-alpha07") - val accompanistVersion = "0.17.0" + val lifecycleVersion = "2.4.0-beta01" + implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleVersion") + implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycleVersion") + + val accompanistVersion = "0.18.0" implementation("com.google.accompanist:accompanist-navigation-animation:$accompanistVersion") implementation("com.google.accompanist:accompanist-placeholder-material:$accompanistVersion") implementation("com.google.accompanist:accompanist-swiperefresh:$accompanistVersion") implementation("com.google.accompanist:accompanist-systemuicontroller:$accompanistVersion") - implementation("io.coil-kt:coil-compose:1.3.0") + implementation("io.coil-kt:coil-compose:1.3.2") - implementation("com.github.skydoves:orchestra-colorpicker:1.0.7") + implementation("com.github.skydoves:orchestra-colorpicker:1.1.0") val koinVersion = "3.1.2" implementation("io.insert-koin:koin-android:$koinVersion") diff --git a/build.gradle.kts b/build.gradle.kts index 49c69926e0..3e18cd8912 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,8 +5,8 @@ buildscript { } dependencies { - classpath("com.android.tools.build:gradle:7.0.1") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.21") + classpath("com.android.tools.build:gradle:7.0.2") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.30") } } From e26bb6069860233ba3cad440323126d8c3b14d76 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sat, 25 Sep 2021 13:32:08 +0400 Subject: [PATCH 060/118] fancy adjustments --- .../java/com/vanced/manager/di/APIModule.kt | 2 +- .../manager/domain/util/EntityMapper.kt | 2 +- .../manager/downloader/api/MicrogAPI.kt | 2 +- .../vanced/manager/downloader/api/MusicAPI.kt | 2 +- .../manager/downloader/api/VancedAPI.kt | 2 +- .../com/vanced/manager/ext/RetrofitKotlin.kt | 2 +- .../manager/network/model/AppDtoMapper.kt | 8 +- .../manager/network/model/JsonDtoMapper.kt | 2 +- .../preferences/holder/PreferenceHolder.kt | 3 +- .../com/vanced/manager/ui/MainActivity.kt | 120 +++++++++++------- .../component/button/ManagerThemedButton.kt | 8 +- .../ui/component/checkbox/ManagerCheckbox.kt | 6 +- .../ui/component/dialog/ManagerDialog.kt | 3 +- .../ui/component/layout/ManagerScrim.kt | 32 +++++ .../ui/component/preference/Preference.kt | 24 ++-- .../preference/RadiobuttonDialogPreference.kt | 2 +- .../manager/ui/navigation/ManagerNavigator.kt | 4 +- .../checkbox/ManagerAnimatedCheckbox.kt | 4 +- .../manager/ui/widget/list/CheckboxItem.kt | 2 +- .../manager/ui/widget/list/RadiobuttonItem.kt | 2 +- .../main/java/com/vanced/manager/util/Log.kt | 10 +- 21 files changed, 157 insertions(+), 85 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrim.kt diff --git a/app/src/main/java/com/vanced/manager/di/APIModule.kt b/app/src/main/java/com/vanced/manager/di/APIModule.kt index db8ef30f0f..49b4b89bad 100644 --- a/app/src/main/java/com/vanced/manager/di/APIModule.kt +++ b/app/src/main/java/com/vanced/manager/di/APIModule.kt @@ -20,7 +20,7 @@ val apiModule = module { fun provideMusicAPI( okHttpClient: OkHttpClient - )= Retrofit.Builder() + ) = Retrofit.Builder() .baseUrl(BASE) .client(okHttpClient) .build() diff --git a/app/src/main/java/com/vanced/manager/domain/util/EntityMapper.kt b/app/src/main/java/com/vanced/manager/domain/util/EntityMapper.kt index 6ec1d4773a..e7d847e6b9 100644 --- a/app/src/main/java/com/vanced/manager/domain/util/EntityMapper.kt +++ b/app/src/main/java/com/vanced/manager/domain/util/EntityMapper.kt @@ -1,6 +1,6 @@ package com.vanced.manager.domain.util -interface EntityMapper <T, Model> { +interface EntityMapper<T, Model> { suspend fun mapToModel(entity: T): Model diff --git a/app/src/main/java/com/vanced/manager/downloader/api/MicrogAPI.kt b/app/src/main/java/com/vanced/manager/downloader/api/MicrogAPI.kt index 597448015e..e379b85ce0 100644 --- a/app/src/main/java/com/vanced/manager/downloader/api/MicrogAPI.kt +++ b/app/src/main/java/com/vanced/manager/downloader/api/MicrogAPI.kt @@ -9,6 +9,6 @@ interface MicrogAPI { @GET("releases/latest/download/microg.apk") @Streaming - fun getFile() : Call<ResponseBody> + fun getFile(): Call<ResponseBody> } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/api/MusicAPI.kt b/app/src/main/java/com/vanced/manager/downloader/api/MusicAPI.kt index 1e738903a2..9eece8b5c8 100644 --- a/app/src/main/java/com/vanced/manager/downloader/api/MusicAPI.kt +++ b/app/src/main/java/com/vanced/manager/downloader/api/MusicAPI.kt @@ -13,6 +13,6 @@ interface MusicAPI { fun getFiles( @Path("version") version: String, @Path("variant") variant: String, - ) : Call<ResponseBody> + ): Call<ResponseBody> } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt b/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt index cc2eccc659..27ae1e3096 100644 --- a/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt +++ b/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt @@ -15,6 +15,6 @@ interface VancedAPI { @Path("variant") variant: String, @Path("type") type: String, @Path("apkName") apkName: String, - ) : Call<ResponseBody> + ): Call<ResponseBody> } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ext/RetrofitKotlin.kt b/app/src/main/java/com/vanced/manager/ext/RetrofitKotlin.kt index ff47605aa8..bf15a4764c 100644 --- a/app/src/main/java/com/vanced/manager/ext/RetrofitKotlin.kt +++ b/app/src/main/java/com/vanced/manager/ext/RetrofitKotlin.kt @@ -4,7 +4,7 @@ import retrofit2.Call import retrofit2.Callback import retrofit2.Response -fun <T: Any> Call<T>.enqueue( +fun <T : Any> Call<T>.enqueue( onResponse: (call: Call<T>, response: Response<T>) -> Unit, onFailure: (call: Call<T>, t: Throwable) -> Unit ) { diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt index 6c105ac405..712b6ae661 100644 --- a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt +++ b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt @@ -39,11 +39,13 @@ class AppDtoMapper : EntityMapper<AppDto, App>, KoinComponent { ) override suspend fun mapToModel(entity: AppDto): App = - with (entity) { + with(entity) { val localVersionCode = packageInformationDataSource.getVersionCode(packageName ?: "") - val localVersionCodeRoot = packageInformationDataSource.getVersionCode(packageNameRoot ?: "") + val localVersionCodeRoot = + packageInformationDataSource.getVersionCode(packageNameRoot ?: "") val localVersionName = packageInformationDataSource.getVersionName(packageName ?: "") - val localVersionNameRoot = packageInformationDataSource.getVersionName(packageNameRoot ?: "") + val localVersionNameRoot = + packageInformationDataSource.getVersionName(packageNameRoot ?: "") App( name = name, remoteVersion = version, diff --git a/app/src/main/java/com/vanced/manager/network/model/JsonDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/JsonDtoMapper.kt index 5bfada0c54..7d94416402 100644 --- a/app/src/main/java/com/vanced/manager/network/model/JsonDtoMapper.kt +++ b/app/src/main/java/com/vanced/manager/network/model/JsonDtoMapper.kt @@ -8,7 +8,7 @@ class JsonDtoMapper( ) : EntityMapper<JsonDto, Json> { override suspend fun mapToModel(entity: JsonDto): Json = - with (entity) { + with(entity) { Json( isMicrogBroken = isMicrogBroken, manager = appDtoMapper.mapToModel(manager), diff --git a/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceHolder.kt b/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceHolder.kt index 0b8061722d..38ddf03608 100644 --- a/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceHolder.kt +++ b/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceHolder.kt @@ -14,7 +14,8 @@ val managerAccentColorPref = managerLongPreference(MANAGER_ACCENT_COLOR_KEY, def val vancedThemePref = managerStringPreference(APP_VANCED_THEME_KEY, VANCED_THEME_DEFAULT_VALUE) val vancedVersionPref = managerStringPreference(APP_VANCED_VERSION_KEY, APP_VERSION_DEFAULT_VALUE) -val vancedLanguagesPref = managerStringSetPreference(APP_VANCED_LANGUAGE_KEY, VANCED_LANGUAGE_DEFAULT_VALUE) +val vancedLanguagesPref = + managerStringSetPreference(APP_VANCED_LANGUAGE_KEY, VANCED_LANGUAGE_DEFAULT_VALUE) val musicVersionPref = managerStringPreference(APP_MUSIC_VERSION_KEY, APP_VERSION_DEFAULT_VALUE) diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index ae0e29354a..5d3903705b 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -5,15 +5,19 @@ import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.animation.AnimatedContentScope import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.core.animateDpAsState import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box import androidx.compose.material.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBackIos import androidx.compose.material.icons.filled.MoreVert import androidx.compose.runtime.* import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.blur +import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEach @@ -26,6 +30,7 @@ import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.vanced.manager.ui.component.color.managerAnimatedColor import com.vanced.manager.ui.component.color.managerSurfaceColor import com.vanced.manager.ui.component.color.managerTextColor +import com.vanced.manager.ui.component.layout.ManagerScrim import com.vanced.manager.ui.component.menu.ManagerDropdownMenuItem import com.vanced.manager.ui.component.text.ToolbarTitleText import com.vanced.manager.ui.resources.managerString @@ -47,6 +52,14 @@ class MainActivity : ComponentActivity() { @OptIn(ExperimentalAnimationApi::class) @Composable fun MainActivityLayout() { + val isMenuExpanded = remember { mutableStateOf(false) } + + var shouldBlur by remember { mutableStateOf(false) } + + LocalView.current.viewTreeObserver.addOnWindowFocusChangeListener { hasFocus -> + shouldBlur = !hasFocus + } + val systemUiController = rememberSystemUiController() val surfaceColor = managerSurfaceColor() val isDark = isDark() @@ -63,40 +76,50 @@ class MainActivity : ComponentActivity() { SideEffect { systemUiController.setSystemBarsColor(surfaceColor, !isDark) } + + val animatedBlurRadius by animateDpAsState( + targetValue = if (shouldBlur) 5.dp else 0.dp + ) - Scaffold( - topBar = { - MainToolbar( - navController = navController, - screens = screens, - ) - }, - backgroundColor = surfaceColor + Box( + modifier = Modifier.blur(animatedBlurRadius) ) { - AnimatedNavHost( - navController = navController, - startDestination = "home", + Scaffold( + topBar = { + MainToolbar( + navController = navController, + screens = screens, + isMenuExpanded = isMenuExpanded + ) + }, + backgroundColor = surfaceColor ) { - screens.fastForEach { screen -> - composable( - route = screen.route, - enterTransition = { _, _ -> - slideIntoContainer(AnimatedContentScope.SlideDirection.Start) + fadeIn() - }, - exitTransition = { _, _ -> - slideOutOfContainer(AnimatedContentScope.SlideDirection.End) + fadeOut() - }, - popEnterTransition = { _, _ -> - slideIntoContainer(AnimatedContentScope.SlideDirection.End) + fadeIn() - }, - popExitTransition = { _, _ -> - slideOutOfContainer(AnimatedContentScope.SlideDirection.Start) + fadeOut() + AnimatedNavHost( + navController = navController, + startDestination = Screen.Home.route, + enterTransition = { _, _ -> + slideIntoContainer(AnimatedContentScope.SlideDirection.Start) + fadeIn() + }, + exitTransition = { _, _ -> + slideOutOfContainer(AnimatedContentScope.SlideDirection.End) + fadeOut() + }, + popEnterTransition = { _, _ -> + slideIntoContainer(AnimatedContentScope.SlideDirection.End) + fadeIn() + }, + popExitTransition = { _, _ -> + slideOutOfContainer(AnimatedContentScope.SlideDirection.Start) + fadeOut() + } + ) { + screens.fastForEach { screen -> + composable( + route = screen.route, + ) { + screen.content() } - ) { - screen.content() } } } + ManagerScrim(show = isMenuExpanded.value) } } @@ -104,19 +127,24 @@ class MainActivity : ComponentActivity() { fun MainToolbar( navController: NavHostController, screens: List<Screen>, + isMenuExpanded: MutableState<Boolean> ) { - var isMenuExpanded by remember { mutableStateOf(false) } + val currentScreenRoute = + navController.currentBackStackEntryAsState().value?.destination?.route - val currentScreenRoute = navController.currentBackStackEntryAsState().value?.destination?.route TopAppBar( title = { - ToolbarTitleText(managerString(stringId = screens.find { it.route == currentScreenRoute }?.displayName)) + ToolbarTitleText( + text = managerString( + stringId = screens.find { it.route == currentScreenRoute }?.displayName + ) + ) }, backgroundColor = managerAnimatedColor(color = MaterialTheme.colors.surface), actions = { if (currentScreenRoute == Screen.Home.route) { IconButton( - onClick = { isMenuExpanded= !isMenuExpanded } + onClick = { isMenuExpanded.value = true } ) { Icon( imageVector = Icons.Default.MoreVert, @@ -126,34 +154,36 @@ class MainActivity : ComponentActivity() { } DropdownMenu( - expanded = isMenuExpanded, + expanded = isMenuExpanded.value, onDismissRequest = { - isMenuExpanded = false + isMenuExpanded.value = false }, - modifier = Modifier.background(MaterialTheme.colors.surface) + modifier = Modifier.background(MaterialTheme.colors.surface), ) { screens.filter { it.route != currentScreenRoute }.forEach { screen -> ManagerDropdownMenuItem( title = stringResource(id = screen.displayName) ) { - isMenuExpanded = !isMenuExpanded + isMenuExpanded.value = false navController.navigate(screen.route) } } } } }, - navigationIcon = if (currentScreenRoute != Screen.Home.route) {{ - IconButton(onClick = { - navController.popBackStack() - }) { - Icon( - imageVector = Icons.Default.ArrowBackIos, - contentDescription = null, - tint = managerTextColor() - ) + navigationIcon = if (currentScreenRoute != Screen.Home.route) { + { + IconButton(onClick = { + navController.popBackStack() + }) { + Icon( + imageVector = Icons.Default.ArrowBackIos, + contentDescription = null, + tint = managerTextColor() + ) + } } - }} else null, + } else null, elevation = 0.dp ) } diff --git a/app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedButton.kt b/app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedButton.kt index 0eeae708d7..8edc51abc1 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedButton.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedButton.kt @@ -26,10 +26,10 @@ fun ManagerThemedButton( colors = ButtonDefaults.buttonColors( backgroundColor = backgroundColor, contentColor = - if (backgroundColor.luminance() > 0.7) - Color.Black - else - Color.White + if (backgroundColor.luminance() > 0.7) + Color.Black + else + Color.White ), elevation = ButtonDefaults.elevation(0.dp, 0.dp, 0.dp) ) { diff --git a/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt b/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt index 8dbc857040..65d2de6564 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt @@ -26,8 +26,10 @@ fun ManagerCheckbox( shape: Shape = MaterialTheme.shapes.medium, onCheckedChange: (isChecked: Boolean) -> Unit ) { - val cardColor = managerAnimatedColor(if (isChecked) managerAccentColor() else managerThemedCardColor()) - val iconTint = managerAnimatedColor(if (isChecked) contentColorForColor(cardColor) else managerAccentColor()) + val cardColor = + managerAnimatedColor(if (isChecked) managerAccentColor() else managerThemedCardColor()) + val iconTint = + managerAnimatedColor(if (isChecked) contentColorForColor(cardColor) else managerAccentColor()) ManagerCard( modifier = modifier, diff --git a/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt b/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt index 78e63c5234..bf9174ad14 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt @@ -5,7 +5,6 @@ import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import com.vanced.manager.ui.component.card.ManagerCard import com.vanced.manager.ui.component.text.ManagerText @@ -55,6 +54,6 @@ fun ManagerDialog( buttons() } } - } + }, ) } diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrim.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrim.kt new file mode 100644 index 0000000000..a7b55ce649 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrim.kt @@ -0,0 +1,32 @@ +package com.vanced.manager.ui.component.layout + +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.animation.core.tween +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier + +@Composable +fun ManagerScrim( + show: Boolean +) { + val scrimAlpha by animateFloatAsState( + targetValue = if (show) 1f else 0f, + animationSpec = tween() + ) + + val scrimColor = MaterialTheme.colors.onSurface.copy(alpha = 0.32f) + + Canvas( + Modifier + .fillMaxSize() + ) { + drawRect( + color = scrimColor, + alpha = scrimAlpha + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt index e128956ef5..04013eeeaa 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt @@ -22,9 +22,11 @@ fun Preference( ) { Preference( preferenceTitle = { ManagerText(text = preferenceTitle) }, - preferenceDescription = if (preferenceDescription != null) {{ - ManagerText(text = preferenceDescription) - }} else null, + preferenceDescription = if (preferenceDescription != null) { + { + ManagerText(text = preferenceDescription) + } + } else null, trailing = trailing, onClick = onClick ) @@ -50,14 +52,16 @@ fun Preference( preferenceTitle() } }, - description = if (preferenceDescription != null) {{ - CompositionLocalProvider( - LocalContentColor provides color, - LocalTextStyle provides MaterialTheme.typography.subtitle1 - ) { - preferenceDescription() + description = if (preferenceDescription != null) { + { + CompositionLocalProvider( + LocalContentColor provides color, + LocalTextStyle provides MaterialTheme.typography.subtitle1 + ) { + preferenceDescription() + } } - }} else null, + } else null, trailing = trailing, ) } diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt index 26bdac64da..a2d666c15d 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt @@ -8,8 +8,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.vanced.manager.preferences.ManagerPreference import com.vanced.manager.preferences.RadioButtonPreference -import com.vanced.manager.ui.widget.list.RadiobuttonItem import com.vanced.manager.ui.widget.button.ManagerSaveButton +import com.vanced.manager.ui.widget.list.RadiobuttonItem import kotlinx.coroutines.launch @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/navigation/ManagerNavigator.kt b/app/src/main/java/com/vanced/manager/ui/navigation/ManagerNavigator.kt index baed2e916e..d9f88cc813 100644 --- a/app/src/main/java/com/vanced/manager/ui/navigation/ManagerNavigator.kt +++ b/app/src/main/java/com/vanced/manager/ui/navigation/ManagerNavigator.kt @@ -23,10 +23,10 @@ fun <T : Screen> ManagerNavigator( transitionSpec = { if (targetState.size > initialState.size) { slideIntoContainer(AnimatedContentScope.SlideDirection.Start) with - slideOutOfContainer(AnimatedContentScope.SlideDirection.End) + slideOutOfContainer(AnimatedContentScope.SlideDirection.End) } else { slideIntoContainer(AnimatedContentScope.SlideDirection.End) with - slideOutOfContainer(AnimatedContentScope.SlideDirection.Start) + slideOutOfContainer(AnimatedContentScope.SlideDirection.Start) } }, targetState = screens diff --git a/app/src/main/java/com/vanced/manager/ui/widget/checkbox/ManagerAnimatedCheckbox.kt b/app/src/main/java/com/vanced/manager/ui/widget/checkbox/ManagerAnimatedCheckbox.kt index 82d93be5d1..4385dc5178 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/checkbox/ManagerAnimatedCheckbox.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/checkbox/ManagerAnimatedCheckbox.kt @@ -19,7 +19,7 @@ fun ManagerAnimatedCheckbox( onCheckedChange: (isChecked: Boolean) -> Unit, ) { val transition = updateTransition( - targetState = isChecked, + targetState = isChecked, label = "Checkbox Animation" ) val animatedSize by transition.jumpAnimation( @@ -28,7 +28,7 @@ fun ManagerAnimatedCheckbox( ) ManagerCheckbox( modifier = Modifier.size(animatedSize), - isChecked = isChecked, + isChecked = isChecked, shape = shape, onCheckedChange = onCheckedChange ) diff --git a/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt index 0cb2d33db3..dc3206d76e 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt @@ -1,6 +1,6 @@ package com.vanced.manager.ui.widget.list -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.Text import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt index e7e02f9abc..5846aee935 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt @@ -1,6 +1,6 @@ package com.vanced.manager.ui.widget.list -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.Text import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/vanced/manager/util/Log.kt b/app/src/main/java/com/vanced/manager/util/Log.kt index 33646a3663..e2e06318de 100644 --- a/app/src/main/java/com/vanced/manager/util/Log.kt +++ b/app/src/main/java/com/vanced/manager/util/Log.kt @@ -19,10 +19,12 @@ fun log(tag: String, message: String) { logs.add( LogContent( body = buildAnnotatedString { - withStyle(SpanStyle( - color = Color(0xFF2E73FF), - fontWeight = FontWeight.Bold - )) { + withStyle( + SpanStyle( + color = Color(0xFF2E73FF), + fontWeight = FontWeight.Bold + ) + ) { append("$tag:") } append("") From 93fde6bda6e2da9a24827603baaf50daa320880d Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sat, 25 Sep 2021 14:12:17 +0400 Subject: [PATCH 061/118] scrimming --- .../com/vanced/manager/ui/MainActivity.kt | 26 +++++++++---------- .../ui/component/layout/ManagerScrim.kt | 20 +++++++++++++- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index 5d3903705b..c9a86ef0b3 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -6,8 +6,6 @@ import androidx.activity.compose.setContent import androidx.compose.animation.AnimatedContentScope import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.core.animateDpAsState -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.material.* @@ -26,7 +24,6 @@ import androidx.navigation.compose.currentBackStackEntryAsState import com.google.accompanist.navigation.animation.AnimatedNavHost import com.google.accompanist.navigation.animation.composable import com.google.accompanist.navigation.animation.rememberAnimatedNavController -import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.vanced.manager.ui.component.color.managerAnimatedColor import com.vanced.manager.ui.component.color.managerSurfaceColor import com.vanced.manager.ui.component.color.managerTextColor @@ -35,7 +32,6 @@ import com.vanced.manager.ui.component.menu.ManagerDropdownMenuItem import com.vanced.manager.ui.component.text.ToolbarTitleText import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.theme.ManagerTheme -import com.vanced.manager.ui.theme.isDark import com.vanced.manager.ui.util.Screen class MainActivity : ComponentActivity() { @@ -60,9 +56,7 @@ class MainActivity : ComponentActivity() { shouldBlur = !hasFocus } - val systemUiController = rememberSystemUiController() val surfaceColor = managerSurfaceColor() - val isDark = isDark() val navController = rememberAnimatedNavController() @@ -72,10 +66,6 @@ class MainActivity : ComponentActivity() { Screen.About, Screen.Logs ) - - SideEffect { - systemUiController.setSystemBarsColor(surfaceColor, !isDark) - } val animatedBlurRadius by animateDpAsState( targetValue = if (shouldBlur) 5.dp else 0.dp @@ -98,16 +88,24 @@ class MainActivity : ComponentActivity() { navController = navController, startDestination = Screen.Home.route, enterTransition = { _, _ -> - slideIntoContainer(AnimatedContentScope.SlideDirection.Start) + fadeIn() + slideIntoContainer( + towards = AnimatedContentScope.SlideDirection.Start + ) }, exitTransition = { _, _ -> - slideOutOfContainer(AnimatedContentScope.SlideDirection.End) + fadeOut() + slideOutOfContainer( + towards = AnimatedContentScope.SlideDirection.End + ) }, popEnterTransition = { _, _ -> - slideIntoContainer(AnimatedContentScope.SlideDirection.End) + fadeIn() + slideIntoContainer( + towards = AnimatedContentScope.SlideDirection.End + ) }, popExitTransition = { _, _ -> - slideOutOfContainer(AnimatedContentScope.SlideDirection.Start) + fadeOut() + slideOutOfContainer( + towards = AnimatedContentScope.SlideDirection.Start + ) } ) { screens.fastForEach { screen -> diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrim.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrim.kt index a7b55ce649..3318d3f6ec 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrim.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrim.kt @@ -6,19 +6,37 @@ import androidx.compose.foundation.Canvas import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import com.google.accompanist.systemuicontroller.rememberSystemUiController +import com.vanced.manager.ui.theme.isDark @Composable fun ManagerScrim( show: Boolean ) { + val systemUiController = rememberSystemUiController() + + val scrimColor = Color.Black.copy(alpha = 0.5f) + val surfaceColor = MaterialTheme.colors.surface + + val isDark = isDark() + val scrimAlpha by animateFloatAsState( targetValue = if (show) 1f else 0f, animationSpec = tween() ) - val scrimColor = MaterialTheme.colors.onSurface.copy(alpha = 0.32f) + SideEffect { + //TODO fix colors in navigation bars + if (show) { + systemUiController.setSystemBarsColor(scrimColor, false) + } else { + systemUiController.setSystemBarsColor(surfaceColor, !isDark) + } + } Canvas( Modifier From b800bf5f4dd54b5115b22812aac73c51e6d4f296 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 17 Oct 2021 11:30:15 +0400 Subject: [PATCH 062/118] updated deps --- app/build.gradle.kts | 10 +++++----- build.gradle.kts | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9c68ddfd03..870ffb1639 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -48,7 +48,7 @@ android { } composeOptions { - kotlinCompilerExtensionVersion = "1.1.0-alpha04" + kotlinCompilerExtensionVersion = "1.1.0-alpha06" } } @@ -56,7 +56,7 @@ android { tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> { kotlinOptions { jvmTarget = "11" - freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn" + freeCompilerArgs = freeCompilerArgs + "-Xopt-in=kotlin.RequiresOptIn" } } @@ -84,7 +84,7 @@ dependencies { implementation("com.google.android.material:material:1.4.0") implementation("androidx.browser:browser:1.3.0") - val composeVersion = "1.1.0-alpha04" + val composeVersion = "1.1.0-alpha06" implementation("androidx.compose.compiler:compiler:$composeVersion") implementation("androidx.compose.foundation:foundation:$composeVersion") implementation("androidx.compose.material:material-icons-core:$composeVersion") @@ -104,13 +104,13 @@ dependencies { implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleVersion") implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycleVersion") - val accompanistVersion = "0.18.0" + val accompanistVersion = "0.20.0" implementation("com.google.accompanist:accompanist-navigation-animation:$accompanistVersion") implementation("com.google.accompanist:accompanist-placeholder-material:$accompanistVersion") implementation("com.google.accompanist:accompanist-swiperefresh:$accompanistVersion") implementation("com.google.accompanist:accompanist-systemuicontroller:$accompanistVersion") - implementation("io.coil-kt:coil-compose:1.3.2") + implementation("io.coil-kt:coil-compose:1.4.0") implementation("com.github.skydoves:orchestra-colorpicker:1.1.0") diff --git a/build.gradle.kts b/build.gradle.kts index 3e18cd8912..a291249dea 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,7 +5,7 @@ buildscript { } dependencies { - classpath("com.android.tools.build:gradle:7.0.2") + classpath("com.android.tools.build:gradle:7.0.3") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.30") } } From 4075bd154f1dcbb98857da4083a41b0e1f768a74 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 17 Oct 2021 13:09:29 +0400 Subject: [PATCH 063/118] remove blur and scrimming --- .../com/vanced/manager/ui/MainActivity.kt | 97 ++++++++----------- build.gradle.kts | 2 +- 2 files changed, 40 insertions(+), 59 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index c9a86ef0b3..cce3d45b27 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -5,17 +5,16 @@ import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.compose.animation.AnimatedContentScope import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.animation.core.animateDpAsState import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box import androidx.compose.material.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBackIos import androidx.compose.material.icons.filled.MoreVert -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.blur -import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastForEach @@ -27,7 +26,6 @@ import com.google.accompanist.navigation.animation.rememberAnimatedNavController import com.vanced.manager.ui.component.color.managerAnimatedColor import com.vanced.manager.ui.component.color.managerSurfaceColor import com.vanced.manager.ui.component.color.managerTextColor -import com.vanced.manager.ui.component.layout.ManagerScrim import com.vanced.manager.ui.component.menu.ManagerDropdownMenuItem import com.vanced.manager.ui.component.text.ToolbarTitleText import com.vanced.manager.ui.resources.managerString @@ -50,14 +48,7 @@ class MainActivity : ComponentActivity() { fun MainActivityLayout() { val isMenuExpanded = remember { mutableStateOf(false) } - var shouldBlur by remember { mutableStateOf(false) } - - LocalView.current.viewTreeObserver.addOnWindowFocusChangeListener { hasFocus -> - shouldBlur = !hasFocus - } - val surfaceColor = managerSurfaceColor() - val navController = rememberAnimatedNavController() val screens = listOf( @@ -66,58 +57,48 @@ class MainActivity : ComponentActivity() { Screen.About, Screen.Logs ) - - val animatedBlurRadius by animateDpAsState( - targetValue = if (shouldBlur) 5.dp else 0.dp - ) - - Box( - modifier = Modifier.blur(animatedBlurRadius) + Scaffold( + topBar = { + MainToolbar( + navController = navController, + screens = screens, + isMenuExpanded = isMenuExpanded + ) + }, + backgroundColor = surfaceColor ) { - Scaffold( - topBar = { - MainToolbar( - navController = navController, - screens = screens, - isMenuExpanded = isMenuExpanded + AnimatedNavHost( + navController = navController, + startDestination = Screen.Home.route, + enterTransition = { _, _ -> + slideIntoContainer( + towards = AnimatedContentScope.SlideDirection.Start ) }, - backgroundColor = surfaceColor + exitTransition = { _, _ -> + slideOutOfContainer( + towards = AnimatedContentScope.SlideDirection.End + ) + }, + popEnterTransition = { _, _ -> + slideIntoContainer( + towards = AnimatedContentScope.SlideDirection.End + ) + }, + popExitTransition = { _, _ -> + slideOutOfContainer( + towards = AnimatedContentScope.SlideDirection.Start + ) + } ) { - AnimatedNavHost( - navController = navController, - startDestination = Screen.Home.route, - enterTransition = { _, _ -> - slideIntoContainer( - towards = AnimatedContentScope.SlideDirection.Start - ) - }, - exitTransition = { _, _ -> - slideOutOfContainer( - towards = AnimatedContentScope.SlideDirection.End - ) - }, - popEnterTransition = { _, _ -> - slideIntoContainer( - towards = AnimatedContentScope.SlideDirection.End - ) - }, - popExitTransition = { _, _ -> - slideOutOfContainer( - towards = AnimatedContentScope.SlideDirection.Start - ) - } - ) { - screens.fastForEach { screen -> - composable( - route = screen.route, - ) { - screen.content() - } + screens.fastForEach { screen -> + composable( + route = screen.route, + ) { + screen.content() } } } - ManagerScrim(show = isMenuExpanded.value) } } diff --git a/build.gradle.kts b/build.gradle.kts index a291249dea..54564af2e4 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ buildscript { dependencies { classpath("com.android.tools.build:gradle:7.0.3") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.30") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31") } } From 9d3529e8a5546a565f3e8875d6f733d1a892ff6f Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 31 Oct 2021 12:52:51 +0400 Subject: [PATCH 064/118] refactor --- app/build.gradle.kts | 2 +- .../{ => core}/downloader/api/MicrogAPI.kt | 2 +- .../{ => core}/downloader/api/MusicAPI.kt | 2 +- .../{ => core}/downloader/api/VancedAPI.kt | 2 +- .../core/downloader/base/AppDownloader.kt | 85 ++++++++ .../core/downloader/impl/MicrogDownloader.kt | 53 +++++ .../core/downloader/impl/MusicDownloader.kt | 64 ++++++ .../core/downloader/impl/VancedDownloader.kt | 92 +++++++++ .../core/downloader/util/DownloadStatus.kt | 16 ++ .../{ => core}/installer/base/AppInstaller.kt | 4 +- .../installer/impl/MicrogInstaller.kt | 4 +- .../installer/impl/MusicInstaller.kt | 8 +- .../installer/impl/VancedInstaller.kt | 8 +- .../preferences/CheckboxPreference.kt | 2 +- .../preferences/ManagerPreference.kt | 2 +- .../preferences/RadioButtonPreference.kt | 2 +- .../holder/PreferenceDefaultValueHolder.kt | 2 +- .../preferences/holder/PreferenceHolder.kt | 10 +- .../preferences/holder/PreferenceKeyHolder.kt | 2 +- .../com/vanced/manager/core/util/AppHelper.kt | 11 + .../{ => core}/util/AppNotifications.kt | 2 +- .../vanced/manager/{ => core}/util/Arch.kt | 2 +- .../vanced/manager/core/util/DownloadLog.kt | 9 + .../com/vanced/manager/{ => core}/util/Log.kt | 2 +- .../manager/{ => core}/util/SocialLinks.kt | 2 +- .../vanced/manager/{ => core}/util/Variant.kt | 2 +- .../java/com/vanced/manager/di/APIModule.kt | 6 +- .../com/vanced/manager/di/DownloaderModule.kt | 34 ++-- .../com/vanced/manager/di/InstallerModuke.kt | 6 +- .../com/vanced/manager/di/MapperModule.kt | 9 +- .../com/vanced/manager/domain/model/App.kt | 40 ++-- .../domain/model/InstallationOption.kt | 34 ++++ .../vanced/manager/domain/pkg/PkgManager.kt | 3 + .../manager/downloader/base/AppDownloader.kt | 168 ---------------- .../downloader/impl/MicrogDownloader.kt | 31 --- .../downloader/impl/MusicDownloader.kt | 44 ---- .../downloader/impl/VancedDownloader.kt | 79 -------- .../com/vanced/manager/ext/RetrofitKotlin.kt | 24 --- .../vanced/manager/network/model/AppDto.kt | 16 +- .../manager/network/model/AppDtoMapper.kt | 135 +++++++------ .../com/vanced/manager/ui/MainActivity.kt | 61 ++++-- .../ui/component/button/ManagerIconButton.kt | 2 +- .../ui/component/card/ManagerLinkCard.kt | 2 +- .../ui/component/color/ManagerColors.kt | 2 +- .../ui/component/dialog/ManagerDialog.kt | 8 +- .../component/layout/ManagerButtonColumn.kt | 4 +- .../ui/component/layout/ManagerLazyColumn.kt | 2 + .../layout/ManagerScrollableColumn.kt | 7 +- .../preference/CheckboxDialogPreference.kt | 4 +- .../preference/CheckboxPreference.kt | 2 +- .../ui/component/preference/Preference.kt | 4 +- .../preference/RadiobuttonDialogPreference.kt | 4 +- .../ui/component/text/AppVersionText.kt | 5 +- .../ui/component/text/CategoryTitleText.kt | 4 +- .../manager/ui/component/text/ManagerText.kt | 4 +- .../vanced/manager/ui/screens/AboutLayout.kt | 4 +- .../vanced/manager/ui/screens/HomeLayout.kt | 145 ++++++++++--- .../ui/screens/InstallPreferencesScreen.kt | 104 ++++++++++ .../manager/ui/screens/InstallScreen.kt | 190 ++++++++++++++++++ .../vanced/manager/ui/screens/LogLayout.kt | 2 +- .../manager/ui/screens/SettingsLayout.kt | 4 +- .../java/com/vanced/manager/ui/theme/Theme.kt | 2 +- .../java/com/vanced/manager/ui/util/Const.kt | 15 +- .../java/com/vanced/manager/ui/util/Screen.kt | 45 ++--- .../manager/ui/viewmodel/MainViewModel.kt | 61 +++--- .../vanced/manager/ui/widget/app/AppCard.kt | 91 +++++++++ .../ui/widget/app/AppCardPlaceholder.kt | 57 ++++++ .../manager/ui/widget/app/BaseAppCard.kt | 69 +++++++ .../ui/widget/layout/CategoryLayout.kt | 8 +- .../manager/ui/widget/list/CheckboxItem.kt | 7 +- .../manager/ui/widget/list/RadiobuttonItem.kt | 4 +- .../ui/widget/screens/home/apps/AppsItem.kt | 25 --- .../screens/home/apps/card/AppActionCard.kt | 94 --------- .../widget/screens/home/apps/card/AppCard.kt | 139 ------------- .../screens/home/apps/card/AppInfoCard.kt | 48 ----- .../home/apps/dialog/AppChangelogDialog.kt | 33 --- .../home/apps/dialog/AppDownloadDialog.kt | 41 ---- .../download/AppDownloadDialogProgress.kt | 45 ----- .../CheckboxInstallationOption.kt | 21 -- .../home/installation/InstallationOption.kt | 7 - .../RadiobuttonInstallationOption.kt | 21 -- .../home/socialmedia/SocialMediaItem.kt | 17 -- .../screens/home/sponsors/SponsorsItem.kt | 17 -- .../screens/settings/AccentColorItem.kt | 2 +- .../widget/screens/settings/CustomTabsItem.kt | 2 +- .../screens/settings/ManagerVariantItem.kt | 4 +- .../screens/settings/NotificationsItem.kt | 4 +- .../ui/widget/screens/settings/ThemeItem.kt | 4 +- .../java/com/vanced/manager/util/AppHelper.kt | 13 -- app/src/main/res/values/strings.xml | 2 + build.gradle.kts | 3 +- 91 files changed, 1302 insertions(+), 1184 deletions(-) rename app/src/main/java/com/vanced/manager/{ => core}/downloader/api/MicrogAPI.kt (83%) rename app/src/main/java/com/vanced/manager/{ => core}/downloader/api/MusicAPI.kt (88%) rename app/src/main/java/com/vanced/manager/{ => core}/downloader/api/VancedAPI.kt (90%) create mode 100644 app/src/main/java/com/vanced/manager/core/downloader/base/AppDownloader.kt create mode 100644 app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt create mode 100644 app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt create mode 100644 app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt create mode 100644 app/src/main/java/com/vanced/manager/core/downloader/util/DownloadStatus.kt rename app/src/main/java/com/vanced/manager/{ => core}/installer/base/AppInstaller.kt (89%) rename app/src/main/java/com/vanced/manager/{ => core}/installer/impl/MicrogInstaller.kt (75%) rename app/src/main/java/com/vanced/manager/{ => core}/installer/impl/MusicInstaller.kt (63%) rename app/src/main/java/com/vanced/manager/{ => core}/installer/impl/VancedInstaller.kt (63%) rename app/src/main/java/com/vanced/manager/{ => core}/preferences/CheckboxPreference.kt (63%) rename app/src/main/java/com/vanced/manager/{ => core}/preferences/ManagerPreference.kt (98%) rename app/src/main/java/com/vanced/manager/{ => core}/preferences/RadioButtonPreference.kt (64%) rename app/src/main/java/com/vanced/manager/{ => core}/preferences/holder/PreferenceDefaultValueHolder.kt (85%) rename app/src/main/java/com/vanced/manager/{ => core}/preferences/holder/PreferenceHolder.kt (75%) rename app/src/main/java/com/vanced/manager/{ => core}/preferences/holder/PreferenceKeyHolder.kt (91%) create mode 100644 app/src/main/java/com/vanced/manager/core/util/AppHelper.kt rename app/src/main/java/com/vanced/manager/{ => core}/util/AppNotifications.kt (93%) rename app/src/main/java/com/vanced/manager/{ => core}/util/Arch.kt (83%) create mode 100644 app/src/main/java/com/vanced/manager/core/util/DownloadLog.kt rename app/src/main/java/com/vanced/manager/{ => core}/util/Log.kt (96%) rename app/src/main/java/com/vanced/manager/{ => core}/util/SocialLinks.kt (97%) rename app/src/main/java/com/vanced/manager/{ => core}/util/Variant.kt (53%) create mode 100644 app/src/main/java/com/vanced/manager/domain/model/InstallationOption.kt delete mode 100644 app/src/main/java/com/vanced/manager/downloader/base/AppDownloader.kt delete mode 100644 app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt delete mode 100644 app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt delete mode 100644 app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt delete mode 100644 app/src/main/java/com/vanced/manager/ext/RetrofitKotlin.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widget/app/AppCard.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widget/app/AppCardPlaceholder.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widget/app/BaseAppCard.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/AppsItem.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppActionCard.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppCard.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppInfoCard.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/dialog/AppChangelogDialog.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/dialog/AppDownloadDialog.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/screens/home/download/AppDownloadDialogProgress.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/CheckboxInstallationOption.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/InstallationOption.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/RadiobuttonInstallationOption.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/screens/home/socialmedia/SocialMediaItem.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/screens/home/sponsors/SponsorsItem.kt delete mode 100644 app/src/main/java/com/vanced/manager/util/AppHelper.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 870ffb1639..f16a92b465 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,6 +1,7 @@ plugins { id("com.android.application") kotlin("android") + id("kotlin-parcelize") } android { @@ -78,7 +79,6 @@ val languages: String get() { dependencies { implementation(kotlin("reflect")) - implementation("androidx.core:core-ktx:1.6.0") implementation("androidx.appcompat:appcompat:1.3.1") implementation("com.google.android.material:material:1.4.0") diff --git a/app/src/main/java/com/vanced/manager/downloader/api/MicrogAPI.kt b/app/src/main/java/com/vanced/manager/core/downloader/api/MicrogAPI.kt similarity index 83% rename from app/src/main/java/com/vanced/manager/downloader/api/MicrogAPI.kt rename to app/src/main/java/com/vanced/manager/core/downloader/api/MicrogAPI.kt index e379b85ce0..14c99d626c 100644 --- a/app/src/main/java/com/vanced/manager/downloader/api/MicrogAPI.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/api/MicrogAPI.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.downloader.api +package com.vanced.manager.core.downloader.api import okhttp3.ResponseBody import retrofit2.Call diff --git a/app/src/main/java/com/vanced/manager/downloader/api/MusicAPI.kt b/app/src/main/java/com/vanced/manager/core/downloader/api/MusicAPI.kt similarity index 88% rename from app/src/main/java/com/vanced/manager/downloader/api/MusicAPI.kt rename to app/src/main/java/com/vanced/manager/core/downloader/api/MusicAPI.kt index 9eece8b5c8..0eaec89f7d 100644 --- a/app/src/main/java/com/vanced/manager/downloader/api/MusicAPI.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/api/MusicAPI.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.downloader.api +package com.vanced.manager.core.downloader.api import okhttp3.ResponseBody import retrofit2.Call diff --git a/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt b/app/src/main/java/com/vanced/manager/core/downloader/api/VancedAPI.kt similarity index 90% rename from app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt rename to app/src/main/java/com/vanced/manager/core/downloader/api/VancedAPI.kt index 27ae1e3096..1e44b2681a 100644 --- a/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/api/VancedAPI.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.downloader.api +package com.vanced.manager.core.downloader.api import okhttp3.ResponseBody import retrofit2.Call diff --git a/app/src/main/java/com/vanced/manager/core/downloader/base/AppDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/base/AppDownloader.kt new file mode 100644 index 0000000000..4628b30b63 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/downloader/base/AppDownloader.kt @@ -0,0 +1,85 @@ +package com.vanced.manager.core.downloader.base + +import com.vanced.manager.core.downloader.util.DownloadStatus +import okhttp3.ResponseBody +import retrofit2.Call +import retrofit2.awaitResponse +import java.io.FileOutputStream + +typealias DownloadCall = Call<ResponseBody> + +abstract class AppDownloader { + + data class DownloadFile( + val fileName: String, + val call: DownloadCall, + ) + + private lateinit var call: DownloadCall + + abstract suspend fun download( + appVersions: List<String>, + onStatus: (DownloadStatus) -> Unit + ) + + abstract fun getSavedFilePath(): String + + suspend fun downloadFiles( + downloadFiles: Array<DownloadFile>, + onFile: (String) -> Unit, + onProgress: (Float) -> Unit, + onError: (error: String, fileName: String) -> Unit, + onSuccess: () -> Unit + ) { + for (downloadFile in downloadFiles) { + try { + this.call = downloadFile.call + + onFile(downloadFile.fileName) + + val response = call.awaitResponse() + if (response.isSuccessful) { + val body = response.body() + if (body != null) { + writeFile(body, downloadFile.fileName) { progress -> + onProgress(progress) + } + } + continue + } + + val error = response.errorBody()?.toString() + if (error != null) { + onError(error, downloadFile.fileName) + return + } + } catch (e: Exception) { + onError(e.stackTraceToString(), downloadFile.fileName) + return + } + } + + onSuccess() + } + + private inline fun writeFile( + body: ResponseBody, + fileName: String, + onProgress: (Float) -> Unit + ) { + val inputStream = body.byteStream() + val outputStream = FileOutputStream(getSavedFilePath() + "/$fileName") + val totalBytes = body.contentLength() + val fileReader = ByteArray(4096) + var downloadedBytes = 0L + var read: Int + while (inputStream.read(fileReader).also { read = it } != -1) { + outputStream.write(fileReader, 0, read) + downloadedBytes += read + onProgress((downloadedBytes * 100 / totalBytes).toFloat()) + } + inputStream.close() + outputStream.close() + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt new file mode 100644 index 0000000000..7d017e4074 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt @@ -0,0 +1,53 @@ +package com.vanced.manager.core.downloader.impl + +import android.content.Context +import com.vanced.manager.core.downloader.api.MicrogAPI +import com.vanced.manager.core.downloader.base.AppDownloader +import com.vanced.manager.core.downloader.util.DownloadStatus +import java.io.File + +class MicrogDownloader( + private val microgAPI: MicrogAPI, + private val context: Context, +) : AppDownloader() { + + override suspend fun download( + appVersions: List<String>, + onStatus: (DownloadStatus) -> Unit + ) { + downloadFiles( + downloadFiles = arrayOf( + DownloadFile( + call = microgAPI.getFile(), + fileName = "microg.apk" + ) + ), + onProgress = { progress -> + onStatus(DownloadStatus.Progress(progress)) + }, + onFile = { fileName -> + onStatus(DownloadStatus.File(fileName)) + }, + onSuccess = { + onStatus(DownloadStatus.StartInstall) + }, + onError = { error, fileName -> + onStatus(DownloadStatus.Error( + displayError = "Failed to download $fileName", + stacktrace = error + )) + } + ) + } + + override fun getSavedFilePath(): String { + val directory = + File(context.getExternalFilesDir("microg")!!.path) + + if (!directory.exists()) + directory.mkdirs() + + return directory.path + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt new file mode 100644 index 0000000000..20fdb1e8db --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt @@ -0,0 +1,64 @@ +package com.vanced.manager.core.downloader.impl + +import android.content.Context +import com.vanced.manager.core.downloader.api.MusicAPI +import com.vanced.manager.core.downloader.base.AppDownloader +import com.vanced.manager.core.downloader.util.DownloadStatus +import com.vanced.manager.core.preferences.holder.managerVariantPref +import com.vanced.manager.core.preferences.holder.musicVersionPref +import com.vanced.manager.core.util.getLatestOrProvidedAppVersion +import java.io.File + +class MusicDownloader( + private val musicAPI: MusicAPI, + private val context: Context, +) : AppDownloader() { + + private val version by musicVersionPref + private val variant by managerVariantPref + + private lateinit var correctVersion: String + + override suspend fun download( + appVersions: List<String>, + onStatus: (DownloadStatus) -> Unit + ) { + correctVersion = getLatestOrProvidedAppVersion(version, appVersions) + + downloadFiles( + downloadFiles = arrayOf(DownloadFile( + call = musicAPI.getFiles( + version = correctVersion, + variant = variant, + ), + fileName = "music.apk" + )), + onProgress = { progress -> + onStatus(DownloadStatus.Progress(progress)) + }, + onFile = { fileName -> + onStatus(DownloadStatus.File(fileName)) + }, + onSuccess = { + onStatus(DownloadStatus.StartInstall) + }, + onError = { error, fileName -> + onStatus(DownloadStatus.Error( + displayError = "Failed to download $fileName", + stacktrace = error + )) + } + ) + } + + override fun getSavedFilePath(): String { + val directory = + File(context.getExternalFilesDir("vancedmusic")!!.path + "$correctVersion/$variant") + + if (!directory.exists()) + directory.mkdirs() + + return directory.path + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt new file mode 100644 index 0000000000..dacad5937a --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt @@ -0,0 +1,92 @@ +package com.vanced.manager.core.downloader.impl + +import android.content.Context +import com.vanced.manager.core.downloader.api.VancedAPI +import com.vanced.manager.core.downloader.base.AppDownloader +import com.vanced.manager.core.downloader.util.DownloadStatus +import com.vanced.manager.core.preferences.holder.managerVariantPref +import com.vanced.manager.core.preferences.holder.vancedLanguagesPref +import com.vanced.manager.core.preferences.holder.vancedThemePref +import com.vanced.manager.core.preferences.holder.vancedVersionPref +import com.vanced.manager.core.util.arch +import com.vanced.manager.core.util.getLatestOrProvidedAppVersion +import java.io.File + +class VancedDownloader( + private val vancedAPI: VancedAPI, + private val context: Context, +) : AppDownloader() { + + private val theme by vancedThemePref + private val version by vancedVersionPref + private val variant by managerVariantPref + private val languages by vancedLanguagesPref + + private lateinit var correctVersion: String + + override suspend fun download( + appVersions: List<String>, + onStatus: (DownloadStatus) -> Unit + ) { + correctVersion = getLatestOrProvidedAppVersion(version, appVersions) + + val files = arrayOf( + getFile( + type = "Theme", + apkName = "$theme.apk", + ), + getFile( + type = "Arch", + apkName = "split_config.$arch.apk", + ) + ) + languages.map { language -> + getFile( + type = "Language", + apkName = "split_config.$language.apk", + ) + } + + downloadFiles( + downloadFiles = files, + onProgress = { progress -> + onStatus(DownloadStatus.Progress(progress)) + }, + onFile = { fileName -> + onStatus(DownloadStatus.File(fileName)) + }, + onSuccess = { + onStatus(DownloadStatus.StartInstall) + }, + onError = { error, fileName -> + onStatus(DownloadStatus.Error( + displayError = "Failed to download $fileName", + stacktrace = error + )) + } + ) + } + + override fun getSavedFilePath(): String { + val directory = + File(context.getExternalFilesDir("vanced")!!.path + "$correctVersion/$variant") + + if (!directory.exists()) + directory.mkdirs() + + return directory.path + } + + private fun getFile( + type: String, + apkName: String, + ) = DownloadFile( + call = vancedAPI.getFiles( + version = correctVersion, + variant = variant, + type = type, + apkName = apkName + ), + fileName = apkName + ) + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadStatus.kt b/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadStatus.kt new file mode 100644 index 0000000000..ee01c5d02c --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadStatus.kt @@ -0,0 +1,16 @@ +package com.vanced.manager.core.downloader.util + +sealed class DownloadStatus { + + object StartInstall : DownloadStatus() + + data class File(val fileName: String) : DownloadStatus() + + data class Progress(val progress: Float) : DownloadStatus() + + data class Error( + val displayError: String, + val stacktrace: String, + ) : DownloadStatus() + +} diff --git a/app/src/main/java/com/vanced/manager/installer/base/AppInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/base/AppInstaller.kt similarity index 89% rename from app/src/main/java/com/vanced/manager/installer/base/AppInstaller.kt rename to app/src/main/java/com/vanced/manager/core/installer/base/AppInstaller.kt index 3c1d2c9cb5..21ed798478 100644 --- a/app/src/main/java/com/vanced/manager/installer/base/AppInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/base/AppInstaller.kt @@ -1,8 +1,8 @@ -package com.vanced.manager.installer.base +package com.vanced.manager.core.installer.base import android.content.Context import androidx.annotation.CallSuper -import com.vanced.manager.util.log +import com.vanced.manager.core.util.log import com.xinto.apkhelper.statusCallback import com.xinto.apkhelper.statusCallbackBuilder import org.koin.core.component.KoinComponent diff --git a/app/src/main/java/com/vanced/manager/installer/impl/MicrogInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt similarity index 75% rename from app/src/main/java/com/vanced/manager/installer/impl/MicrogInstaller.kt rename to app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt index b756275ca4..fc3f4ad638 100644 --- a/app/src/main/java/com/vanced/manager/installer/impl/MicrogInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt @@ -1,6 +1,6 @@ -package com.vanced.manager.installer.impl +package com.vanced.manager.core.installer.impl -import com.vanced.manager.installer.base.AppInstaller +import com.vanced.manager.core.installer.base.AppInstaller import com.xinto.apkhelper.installApk class MicrogInstaller : AppInstaller() { diff --git a/app/src/main/java/com/vanced/manager/installer/impl/MusicInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt similarity index 63% rename from app/src/main/java/com/vanced/manager/installer/impl/MusicInstaller.kt rename to app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt index 3b7d1d2892..5da7a7db2b 100644 --- a/app/src/main/java/com/vanced/manager/installer/impl/MusicInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt @@ -1,8 +1,8 @@ -package com.vanced.manager.installer.impl +package com.vanced.manager.core.installer.impl -import com.vanced.manager.installer.base.AppInstaller -import com.vanced.manager.preferences.holder.managerVariantPref -import com.vanced.manager.preferences.holder.musicVersionPref +import com.vanced.manager.core.installer.base.AppInstaller +import com.vanced.manager.core.preferences.holder.managerVariantPref +import com.vanced.manager.core.preferences.holder.musicVersionPref import com.xinto.apkhelper.installApk class MusicInstaller : AppInstaller() { diff --git a/app/src/main/java/com/vanced/manager/installer/impl/VancedInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt similarity index 63% rename from app/src/main/java/com/vanced/manager/installer/impl/VancedInstaller.kt rename to app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt index 699f342773..56cf82a5d3 100644 --- a/app/src/main/java/com/vanced/manager/installer/impl/VancedInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt @@ -1,8 +1,8 @@ -package com.vanced.manager.installer.impl +package com.vanced.manager.core.installer.impl -import com.vanced.manager.installer.base.AppInstaller -import com.vanced.manager.preferences.holder.managerVariantPref -import com.vanced.manager.preferences.holder.vancedVersionPref +import com.vanced.manager.core.installer.base.AppInstaller +import com.vanced.manager.core.preferences.holder.managerVariantPref +import com.vanced.manager.core.preferences.holder.vancedVersionPref import com.xinto.apkhelper.installSplitApks class VancedInstaller : AppInstaller() { diff --git a/app/src/main/java/com/vanced/manager/preferences/CheckboxPreference.kt b/app/src/main/java/com/vanced/manager/core/preferences/CheckboxPreference.kt similarity index 63% rename from app/src/main/java/com/vanced/manager/preferences/CheckboxPreference.kt rename to app/src/main/java/com/vanced/manager/core/preferences/CheckboxPreference.kt index f966ec98d8..ceb47e2fb5 100644 --- a/app/src/main/java/com/vanced/manager/preferences/CheckboxPreference.kt +++ b/app/src/main/java/com/vanced/manager/core/preferences/CheckboxPreference.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.preferences +package com.vanced.manager.core.preferences data class CheckboxPreference( val title: String, diff --git a/app/src/main/java/com/vanced/manager/preferences/ManagerPreference.kt b/app/src/main/java/com/vanced/manager/core/preferences/ManagerPreference.kt similarity index 98% rename from app/src/main/java/com/vanced/manager/preferences/ManagerPreference.kt rename to app/src/main/java/com/vanced/manager/core/preferences/ManagerPreference.kt index c79028eb0e..162a72f1c2 100644 --- a/app/src/main/java/com/vanced/manager/preferences/ManagerPreference.kt +++ b/app/src/main/java/com/vanced/manager/core/preferences/ManagerPreference.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.preferences +package com.vanced.manager.core.preferences import android.content.SharedPreferences import androidx.compose.runtime.State diff --git a/app/src/main/java/com/vanced/manager/preferences/RadioButtonPreference.kt b/app/src/main/java/com/vanced/manager/core/preferences/RadioButtonPreference.kt similarity index 64% rename from app/src/main/java/com/vanced/manager/preferences/RadioButtonPreference.kt rename to app/src/main/java/com/vanced/manager/core/preferences/RadioButtonPreference.kt index bdf36b4fb7..491b4fbf41 100644 --- a/app/src/main/java/com/vanced/manager/preferences/RadioButtonPreference.kt +++ b/app/src/main/java/com/vanced/manager/core/preferences/RadioButtonPreference.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.preferences +package com.vanced.manager.core.preferences data class RadioButtonPreference( val title: String, diff --git a/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceDefaultValueHolder.kt b/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceDefaultValueHolder.kt similarity index 85% rename from app/src/main/java/com/vanced/manager/preferences/holder/PreferenceDefaultValueHolder.kt rename to app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceDefaultValueHolder.kt index cb209aa519..9972b2d009 100644 --- a/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceDefaultValueHolder.kt +++ b/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceDefaultValueHolder.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.preferences.holder +package com.vanced.manager.core.preferences.holder const val MANAGER_VARIANT_DEFAULT_VALUE = "nonroot" diff --git a/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceHolder.kt b/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceHolder.kt similarity index 75% rename from app/src/main/java/com/vanced/manager/preferences/holder/PreferenceHolder.kt rename to app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceHolder.kt index 38ddf03608..e537e2eee3 100644 --- a/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceHolder.kt +++ b/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceHolder.kt @@ -1,9 +1,9 @@ -package com.vanced.manager.preferences.holder +package com.vanced.manager.core.preferences.holder -import com.vanced.manager.preferences.managerBooleanPreference -import com.vanced.manager.preferences.managerLongPreference -import com.vanced.manager.preferences.managerStringPreference -import com.vanced.manager.preferences.managerStringSetPreference +import com.vanced.manager.core.preferences.managerBooleanPreference +import com.vanced.manager.core.preferences.managerLongPreference +import com.vanced.manager.core.preferences.managerStringPreference +import com.vanced.manager.core.preferences.managerStringSetPreference import com.vanced.manager.ui.theme.defAccentColor val useCustomTabsPref = managerBooleanPreference(USE_CUSTOM_TABS_KEY) diff --git a/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceKeyHolder.kt b/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceKeyHolder.kt similarity index 91% rename from app/src/main/java/com/vanced/manager/preferences/holder/PreferenceKeyHolder.kt rename to app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceKeyHolder.kt index c24886805e..42dbbc6472 100644 --- a/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceKeyHolder.kt +++ b/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceKeyHolder.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.preferences.holder +package com.vanced.manager.core.preferences.holder const val USE_CUSTOM_TABS_KEY = "use_custom_tabs" const val MANAGER_VARIANT_KEY = "manager_variant" diff --git a/app/src/main/java/com/vanced/manager/core/util/AppHelper.kt b/app/src/main/java/com/vanced/manager/core/util/AppHelper.kt new file mode 100644 index 0000000000..bbb46a782b --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/util/AppHelper.kt @@ -0,0 +1,11 @@ +package com.vanced.manager.core.util + +fun getLatestOrProvidedAppVersion( + version: String, + appVersions: List<String> +): String { + if (appVersions.contains(version)) + return version + + return appVersions.last() +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/util/AppNotifications.kt b/app/src/main/java/com/vanced/manager/core/util/AppNotifications.kt similarity index 93% rename from app/src/main/java/com/vanced/manager/util/AppNotifications.kt rename to app/src/main/java/com/vanced/manager/core/util/AppNotifications.kt index c3737f2910..221bf3db1f 100644 --- a/app/src/main/java/com/vanced/manager/util/AppNotifications.kt +++ b/app/src/main/java/com/vanced/manager/core/util/AppNotifications.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.util +package com.vanced.manager.core.util import com.vanced.manager.domain.model.NotificationPrefModel import com.vanced.manager.network.util.MICROG_NAME diff --git a/app/src/main/java/com/vanced/manager/util/Arch.kt b/app/src/main/java/com/vanced/manager/core/util/Arch.kt similarity index 83% rename from app/src/main/java/com/vanced/manager/util/Arch.kt rename to app/src/main/java/com/vanced/manager/core/util/Arch.kt index 5724ba8afc..4c2247f50b 100644 --- a/app/src/main/java/com/vanced/manager/util/Arch.kt +++ b/app/src/main/java/com/vanced/manager/core/util/Arch.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.util +package com.vanced.manager.core.util import android.os.Build diff --git a/app/src/main/java/com/vanced/manager/core/util/DownloadLog.kt b/app/src/main/java/com/vanced/manager/core/util/DownloadLog.kt new file mode 100644 index 0000000000..fdfa563ac9 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/util/DownloadLog.kt @@ -0,0 +1,9 @@ +package com.vanced.manager.core.util + +sealed class Message { + data class Success(val message: String) : Message() + data class Warning(val message: String) : Message() + data class Error(val message: String) : Message() +} + +val downloadLogs = mutableListOf<Message>() \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/util/Log.kt b/app/src/main/java/com/vanced/manager/core/util/Log.kt similarity index 96% rename from app/src/main/java/com/vanced/manager/util/Log.kt rename to app/src/main/java/com/vanced/manager/core/util/Log.kt index e2e06318de..5476699fff 100644 --- a/app/src/main/java/com/vanced/manager/util/Log.kt +++ b/app/src/main/java/com/vanced/manager/core/util/Log.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.util +package com.vanced.manager.core.util import android.util.Log import androidx.compose.ui.graphics.Color diff --git a/app/src/main/java/com/vanced/manager/util/SocialLinks.kt b/app/src/main/java/com/vanced/manager/core/util/SocialLinks.kt similarity index 97% rename from app/src/main/java/com/vanced/manager/util/SocialLinks.kt rename to app/src/main/java/com/vanced/manager/core/util/SocialLinks.kt index bea816310c..06cbd82a6b 100644 --- a/app/src/main/java/com/vanced/manager/util/SocialLinks.kt +++ b/app/src/main/java/com/vanced/manager/core/util/SocialLinks.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.util +package com.vanced.manager.core.util import com.vanced.manager.R import com.vanced.manager.domain.model.Link diff --git a/app/src/main/java/com/vanced/manager/util/Variant.kt b/app/src/main/java/com/vanced/manager/core/util/Variant.kt similarity index 53% rename from app/src/main/java/com/vanced/manager/util/Variant.kt rename to app/src/main/java/com/vanced/manager/core/util/Variant.kt index 326d183c53..850f40cf9b 100644 --- a/app/src/main/java/com/vanced/manager/util/Variant.kt +++ b/app/src/main/java/com/vanced/manager/core/util/Variant.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.util +package com.vanced.manager.core.util enum class Variant { diff --git a/app/src/main/java/com/vanced/manager/di/APIModule.kt b/app/src/main/java/com/vanced/manager/di/APIModule.kt index 49b4b89bad..04477c78c8 100644 --- a/app/src/main/java/com/vanced/manager/di/APIModule.kt +++ b/app/src/main/java/com/vanced/manager/di/APIModule.kt @@ -1,8 +1,8 @@ package com.vanced.manager.di -import com.vanced.manager.downloader.api.MicrogAPI -import com.vanced.manager.downloader.api.MusicAPI -import com.vanced.manager.downloader.api.VancedAPI +import com.vanced.manager.core.downloader.api.MicrogAPI +import com.vanced.manager.core.downloader.api.MusicAPI +import com.vanced.manager.core.downloader.api.VancedAPI import com.vanced.manager.network.util.BASE import okhttp3.OkHttpClient import org.koin.dsl.module diff --git a/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt b/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt index 3f64a5e294..050c6c330f 100644 --- a/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt +++ b/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt @@ -1,34 +1,32 @@ package com.vanced.manager.di -import com.vanced.manager.downloader.api.MicrogAPI -import com.vanced.manager.downloader.api.MusicAPI -import com.vanced.manager.downloader.api.VancedAPI -import com.vanced.manager.downloader.impl.MicrogDownloader -import com.vanced.manager.downloader.impl.MusicDownloader -import com.vanced.manager.downloader.impl.VancedDownloader -import com.vanced.manager.installer.impl.MicrogInstaller -import com.vanced.manager.installer.impl.MusicInstaller -import com.vanced.manager.installer.impl.VancedInstaller +import android.content.Context +import com.vanced.manager.core.downloader.api.MicrogAPI +import com.vanced.manager.core.downloader.api.MusicAPI +import com.vanced.manager.core.downloader.api.VancedAPI +import com.vanced.manager.core.downloader.impl.MicrogDownloader +import com.vanced.manager.core.downloader.impl.MusicDownloader +import com.vanced.manager.core.downloader.impl.VancedDownloader import org.koin.dsl.module val downloaderModule = module { fun provideVancedDownloader( - vancedInstaller: VancedInstaller, vancedAPI: VancedAPI, - ) = VancedDownloader(vancedInstaller, vancedAPI) + context: Context, + ) = VancedDownloader(vancedAPI, context) fun provideMusicDownloader( - musicInstaller: MusicInstaller, musicAPI: MusicAPI, - ) = MusicDownloader(musicInstaller, musicAPI) + context: Context, + ) = MusicDownloader(musicAPI, context) fun provideMicrogDownloader( - microgInstaller: MicrogInstaller, microgAPI: MicrogAPI, - ) = MicrogDownloader(microgInstaller, microgAPI) + context: Context, + ) = MicrogDownloader(microgAPI, context) - single { provideVancedDownloader(get(), get()) } - single { provideMusicDownloader(get(), get()) } - single { provideMicrogDownloader(get(), get()) } + factory { provideVancedDownloader(get(), get()) } + factory { provideMusicDownloader(get(), get()) } + factory { provideMicrogDownloader(get(), get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt b/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt index 109c57f167..907e3cdf3c 100644 --- a/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt +++ b/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt @@ -1,8 +1,8 @@ package com.vanced.manager.di -import com.vanced.manager.installer.impl.MicrogInstaller -import com.vanced.manager.installer.impl.MusicInstaller -import com.vanced.manager.installer.impl.VancedInstaller +import com.vanced.manager.core.installer.impl.MicrogInstaller +import com.vanced.manager.core.installer.impl.MusicInstaller +import com.vanced.manager.core.installer.impl.VancedInstaller import org.koin.dsl.module val installerModule = module { diff --git a/app/src/main/java/com/vanced/manager/di/MapperModule.kt b/app/src/main/java/com/vanced/manager/di/MapperModule.kt index c55cc79b09..2c0560bdaf 100644 --- a/app/src/main/java/com/vanced/manager/di/MapperModule.kt +++ b/app/src/main/java/com/vanced/manager/di/MapperModule.kt @@ -1,12 +1,17 @@ package com.vanced.manager.di +import android.content.Context +import com.vanced.manager.domain.datasource.PackageInformationDataSource import com.vanced.manager.network.model.AppDtoMapper import com.vanced.manager.network.model.JsonDtoMapper import org.koin.dsl.module val mapperModule = module { - fun provideAppMapper(): AppDtoMapper = AppDtoMapper() + fun provideAppMapper( + packageInformationDataSource: PackageInformationDataSource, + context: Context, + ) = AppDtoMapper(packageInformationDataSource, context) fun provideJsonMapper( appDtoMapper: AppDtoMapper @@ -14,6 +19,6 @@ val mapperModule = module { appDtoMapper = appDtoMapper ) - single { provideAppMapper() } + single { provideAppMapper(get(), get()) } single { provideJsonMapper(get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/domain/model/App.kt b/app/src/main/java/com/vanced/manager/domain/model/App.kt index e762624ae6..a93d7dc0ef 100644 --- a/app/src/main/java/com/vanced/manager/domain/model/App.kt +++ b/app/src/main/java/com/vanced/manager/domain/model/App.kt @@ -1,26 +1,22 @@ package com.vanced.manager.domain.model -import com.vanced.manager.downloader.base.AppDownloader -import com.vanced.manager.ui.widget.screens.home.installation.InstallationOption - data class App( - val name: String? = null, - val remoteVersion: String? = null, - val remoteVersionCode: Int? = null, - val installedVersion: String? = null, - val installedVersionCode: Int? = null, - val installedVersionRoot: String? = null, - val installedVersionCodeRoot: Int? = null, - val iconUrl: String? = "", - val appStatus: AppStatus = AppStatus.Install, - val appStatusRoot: AppStatus = AppStatus.Install, - val packageName: String? = null, - val packageNameRoot: String? = null, - val changelog: String? = null, - val url: String? = null, - val versions: List<String>? = null, - val themes: List<String>? = null, - val languages: List<String>? = null, - val downloader: AppDownloader? = null, - val installationOptions: List<InstallationOption>? = null + val name: String, + val remoteVersion: String, + val remoteVersionCode: Int, + val installedVersion: String?, + val installedVersionCode: Int?, + val installedVersionRoot: String?, + val installedVersionCodeRoot: Int?, + val iconUrl: String?, + val appStatus: AppStatus, + val appStatusRoot: AppStatus, + val packageName: String, + val packageNameRoot: String?, + val changelog: String, + val url: String?, + val versions: List<String>?, + val themes: List<String>?, + val languages: List<String>?, + val installationOptions: List<InstallationOption>? ) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/domain/model/InstallationOption.kt b/app/src/main/java/com/vanced/manager/domain/model/InstallationOption.kt new file mode 100644 index 0000000000..c5bfd46d26 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/domain/model/InstallationOption.kt @@ -0,0 +1,34 @@ +package com.vanced.manager.domain.model + +import android.os.Parcelable +import androidx.annotation.StringRes +import kotlinx.parcelize.Parcelize + +sealed class InstallationOption( + @StringRes val itemTitleId: Int, +) : Parcelable { + + @Parcelize + data class MultiSelect( + @StringRes val titleId: Int, + val items: List<InstallationOptionItem>, + val getOption: () -> Set<String>, + val addOption: (String) -> Unit, + val removeOption: (String) -> Unit + ) : InstallationOption(titleId) + + @Parcelize + data class SingleSelect( + @StringRes val titleId: Int, + val items: List<InstallationOptionItem>, + val getOption: () -> String, + val setOption: (String) -> Unit, + ) : InstallationOption(titleId) + +} + +@Parcelize +data class InstallationOptionItem( + val displayText: String, + val key: String, +) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/domain/pkg/PkgManager.kt b/app/src/main/java/com/vanced/manager/domain/pkg/PkgManager.kt index 076a48c676..3e01ad1b67 100644 --- a/app/src/main/java/com/vanced/manager/domain/pkg/PkgManager.kt +++ b/app/src/main/java/com/vanced/manager/domain/pkg/PkgManager.kt @@ -1,5 +1,6 @@ package com.vanced.manager.domain.pkg +import android.annotation.SuppressLint import android.content.pm.PackageManager import android.os.Build @@ -21,6 +22,7 @@ class PkgManagerImpl( const val MAJOR_IGNORE = 0xFFFFFFFF } + @SuppressLint("WrongConstant") @Suppress("DEPRECATION") @Throws(PackageManager.NameNotFoundException::class) override suspend fun getVersionCode(packageName: String): Int { @@ -37,6 +39,7 @@ class PkgManagerImpl( } } + @SuppressLint("WrongConstant") @Throws(PackageManager.NameNotFoundException::class) override suspend fun getVersionName(packageName: String): String = packageManager.getPackageInfo(packageName, PACKAGE_FLAG_ALL_OFF) diff --git a/app/src/main/java/com/vanced/manager/downloader/base/AppDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/base/AppDownloader.kt deleted file mode 100644 index 03b7433de4..0000000000 --- a/app/src/main/java/com/vanced/manager/downloader/base/AppDownloader.kt +++ /dev/null @@ -1,168 +0,0 @@ -package com.vanced.manager.downloader.base - -import android.content.Context -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import com.vanced.manager.domain.model.App -import com.vanced.manager.installer.base.AppInstaller -import com.vanced.manager.ui.viewmodel.MainViewModel -import com.vanced.manager.util.log -import okhttp3.ResponseBody -import org.koin.core.component.KoinComponent -import org.koin.core.component.inject -import retrofit2.Call -import retrofit2.awaitResponse -import java.io.File -import java.io.FileOutputStream -import java.io.IOException - -//TODO remove showDownloadScreen and viewModel references -abstract class AppDownloader( - val appName: String, - val appInstaller: AppInstaller -) : KoinComponent { - - data class File( - val call: Call<ResponseBody>, - val fileName: String - ) - - var downloadProgress by mutableStateOf(0f) - private set - - var downloadFile by mutableStateOf("") - private set - - var installing by mutableStateOf(false) - var error by mutableStateOf(false) - - val showDownloadScreen = mutableStateOf(false) - - private var canceled = false - - private lateinit var call: Call<ResponseBody> - - private val tag = this::class.simpleName!! - - private fun resetValues() { - showDownloadScreen.value = false - downloadProgress = 0f - downloadFile = "" - installing = false - error = false - canceled = false - } - - val context: Context by inject() - - abstract suspend fun download( - app: App, - viewModel: MainViewModel - ) - - private fun install(viewModel: MainViewModel) { - installing = true - appInstaller.install { - viewModel.fetch() - resetValues() - } - } - - suspend fun downloadFile( - file: File, - viewModel: MainViewModel, - folderStructure: String, - onError: (error: String) -> Unit = {}, - ) { - downloadFiles( - files = listOf(file), - viewModel = viewModel, - folderStructure = folderStructure, - onError = onError - ) - } - - suspend fun downloadFiles( - files: List<File>, - viewModel: MainViewModel, - folderStructure: String, - onError: (error: String) -> Unit = {}, - ) { - showDownloadScreen.value = true - fun error(errorBody: String) { - error = true - onError(errorBody) - log(tag, errorBody) - } - try { - for (file in files) { - if (canceled) { - break - } - - val fileName = file.fileName - downloadFile = fileName - this.call = file.call - val response = call.awaitResponse() - if (response.isSuccessful) { - val body = response.body() - if (body != null) { - if (!writeFile(body, fileName, folderStructure)) { - error("Failed to write file data") - } - } - } else { - val error = response.errorBody()?.toString() - if (error != null) { - error(error) - } - } - } - } catch (e: Exception) { - error(e.stackTraceToString()) - } - - if (canceled) { - resetValues() - return - } - - install(viewModel) - } - - fun cancelDownload() { - canceled = true - call.cancel() - } - - private fun writeFile( - body: ResponseBody, - fileName: String, - folderStructure: String - ): Boolean { - val folder = File("${context.getExternalFilesDir(appName)?.path}/$folderStructure") - folder.mkdirs() - val file = File("${folder.path}/$fileName") - val inputStream = body.byteStream() - val outputStream = FileOutputStream(file) - return try { - val totalBytes = body.contentLength() - val fileReader = ByteArray(4096) - var downloadedBytes = 0L - var read: Int - while (inputStream.read(fileReader).also { read = it } != -1) { - outputStream.write(fileReader, 0, read) - downloadedBytes += read - downloadProgress = (downloadedBytes * 100 / totalBytes).toFloat() - } - true - } catch (e: IOException) { - false - } finally { - inputStream.close() - outputStream.close() - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt deleted file mode 100644 index 0dc5ef007b..0000000000 --- a/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.vanced.manager.downloader.impl - -import com.vanced.manager.domain.model.App -import com.vanced.manager.downloader.api.MicrogAPI -import com.vanced.manager.downloader.base.AppDownloader -import com.vanced.manager.installer.impl.MicrogInstaller -import com.vanced.manager.ui.viewmodel.MainViewModel - -class MicrogDownloader( - microgInstaller: MicrogInstaller, - private val microgAPI: MicrogAPI, -) : AppDownloader( - appName = "microg", - appInstaller = microgInstaller -) { - - override suspend fun download( - app: App, - viewModel: MainViewModel - ) { - downloadFile( - file = File( - call = microgAPI.getFile(), - fileName = "microg.apk" - ), - viewModel = viewModel, - folderStructure = "" - ) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt deleted file mode 100644 index 9fbcb16cdb..0000000000 --- a/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.vanced.manager.downloader.impl - -import com.vanced.manager.domain.model.App -import com.vanced.manager.downloader.api.MusicAPI -import com.vanced.manager.downloader.base.AppDownloader -import com.vanced.manager.installer.impl.MusicInstaller -import com.vanced.manager.preferences.holder.managerVariantPref -import com.vanced.manager.preferences.holder.musicVersionPref -import com.vanced.manager.ui.viewmodel.MainViewModel -import com.vanced.manager.util.getLatestOrProvidedAppVersion - -class MusicDownloader( - musicInstaller: MusicInstaller, - private val musicAPI: MusicAPI, -) : AppDownloader( - appName = "music", - appInstaller = musicInstaller -) { - - private val version by musicVersionPref - private val variant by managerVariantPref - - override suspend fun download( - app: App, - viewModel: MainViewModel - ) { - val correctVersion = getLatestOrProvidedAppVersion( - version = version, - app = app - ) - downloadFile( - file = File( - call = musicAPI.getFiles( - version = correctVersion, - variant = variant, - ), - fileName = "music.apk" - ), - viewModel = viewModel, - folderStructure = "$correctVersion/$variant" - ) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt deleted file mode 100644 index 7e11980881..0000000000 --- a/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt +++ /dev/null @@ -1,79 +0,0 @@ -package com.vanced.manager.downloader.impl - -import com.vanced.manager.domain.model.App -import com.vanced.manager.downloader.api.VancedAPI -import com.vanced.manager.downloader.base.AppDownloader -import com.vanced.manager.installer.impl.VancedInstaller -import com.vanced.manager.preferences.holder.managerVariantPref -import com.vanced.manager.preferences.holder.vancedLanguagesPref -import com.vanced.manager.preferences.holder.vancedThemePref -import com.vanced.manager.preferences.holder.vancedVersionPref -import com.vanced.manager.ui.viewmodel.MainViewModel -import com.vanced.manager.util.arch -import com.vanced.manager.util.getLatestOrProvidedAppVersion -import com.vanced.manager.util.log - -class VancedDownloader( - vancedInstaller: VancedInstaller, - private val vancedAPI: VancedAPI, -) : AppDownloader( - appName = "vanced", - appInstaller = vancedInstaller -) { - - private val theme by vancedThemePref - private val version by vancedVersionPref - private val variant by managerVariantPref - private val languages by vancedLanguagesPref - - override suspend fun download( - app: App, - viewModel: MainViewModel - ) { - val correctVersion = getLatestOrProvidedAppVersion( - version = version, - app = app - ) - val files = listOf( - getFile( - type = "Theme", - apkName = "$theme.apk", - version = correctVersion - ), - getFile( - type = "Arch", - apkName = "split_config.$arch.apk", - version = correctVersion - ) - ) + languages.map { language -> - getFile( - type = "Language", - apkName = "split_config.$language.apk", - version = correctVersion - ) - } - downloadFiles( - files = files, - viewModel, - folderStructure = "$correctVersion/$variant", - onError = { - log("error", it) - } - ) - } - - private fun getFile( - type: String, - apkName: String, - version: String, - ) = File( - call = vancedAPI.getFiles( - version = version, - variant = variant, - type = type, - apkName = apkName - ), - fileName = apkName - ) - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ext/RetrofitKotlin.kt b/app/src/main/java/com/vanced/manager/ext/RetrofitKotlin.kt deleted file mode 100644 index bf15a4764c..0000000000 --- a/app/src/main/java/com/vanced/manager/ext/RetrofitKotlin.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.vanced.manager.ext - -import retrofit2.Call -import retrofit2.Callback -import retrofit2.Response - -fun <T : Any> Call<T>.enqueue( - onResponse: (call: Call<T>, response: Response<T>) -> Unit, - onFailure: (call: Call<T>, t: Throwable) -> Unit -) { - enqueue(object : Callback<T> { - - override fun onResponse( - call: Call<T>, - response: Response<T> - ) = onResponse(call, response) - - override fun onFailure( - call: Call<T>, - t: Throwable - ) = onFailure(call, t) - - }) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDto.kt b/app/src/main/java/com/vanced/manager/network/model/AppDto.kt index bb6b00c143..ed5042121e 100644 --- a/app/src/main/java/com/vanced/manager/network/model/AppDto.kt +++ b/app/src/main/java/com/vanced/manager/network/model/AppDto.kt @@ -3,15 +3,15 @@ package com.vanced.manager.network.model import com.google.gson.annotations.SerializedName data class AppDto( - @SerializedName("name") val name: String? = null, - @SerializedName("version") val version: String? = null, - @SerializedName("versionCode") val versionCode: Int? = null, + @SerializedName("name") val name: String, + @SerializedName("version") val version: String, + @SerializedName("versionCode") val versionCode: Int, + @SerializedName("changelog") val changelog: String, + @SerializedName("icon_url") val iconUrl: String? = null, + @SerializedName("package_name") val packageName: String, + @SerializedName("package_name_root") val packageNameRoot: String? = null, + @SerializedName("url") val url: String? = null, @SerializedName("versions") val versions: List<String>? = null, @SerializedName("themes") val themes: List<String>? = null, @SerializedName("langs") val languages: List<String>? = null, - @SerializedName("package_name") val packageName: String? = null, - @SerializedName("package_name_root") val packageNameRoot: String? = null, - @SerializedName("changelog") val changelog: String? = null, - @SerializedName("icon_url") val iconUrl: String? = null, - @SerializedName("url") val url: String? = null, ) diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt index 712b6ae661..bf3f1520b8 100644 --- a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt +++ b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt @@ -2,48 +2,37 @@ package com.vanced.manager.network.model import android.content.Context import com.vanced.manager.R +import com.vanced.manager.core.preferences.holder.musicVersionPref +import com.vanced.manager.core.preferences.holder.vancedLanguagesPref +import com.vanced.manager.core.preferences.holder.vancedThemePref +import com.vanced.manager.core.preferences.holder.vancedVersionPref import com.vanced.manager.domain.datasource.PackageInformationDataSource import com.vanced.manager.domain.model.App import com.vanced.manager.domain.model.AppStatus +import com.vanced.manager.domain.model.InstallationOption +import com.vanced.manager.domain.model.InstallationOptionItem import com.vanced.manager.domain.util.EntityMapper -import com.vanced.manager.downloader.base.AppDownloader -import com.vanced.manager.downloader.impl.MicrogDownloader -import com.vanced.manager.downloader.impl.MusicDownloader -import com.vanced.manager.downloader.impl.VancedDownloader -import com.vanced.manager.network.util.MICROG_NAME import com.vanced.manager.network.util.MUSIC_NAME import com.vanced.manager.network.util.VANCED_NAME -import com.vanced.manager.preferences.CheckboxPreference -import com.vanced.manager.preferences.RadioButtonPreference -import com.vanced.manager.preferences.holder.musicVersionPref -import com.vanced.manager.preferences.holder.vancedLanguagesPref -import com.vanced.manager.preferences.holder.vancedThemePref -import com.vanced.manager.preferences.holder.vancedVersionPref -import com.vanced.manager.ui.widget.screens.home.installation.CheckboxInstallationOption -import com.vanced.manager.ui.widget.screens.home.installation.InstallationOption -import com.vanced.manager.ui.widget.screens.home.installation.RadiobuttonInstallationOption -import org.koin.core.component.KoinComponent -import org.koin.core.component.get -import org.koin.core.component.inject import java.util.* -class AppDtoMapper : EntityMapper<AppDto, App>, KoinComponent { - - private val packageInformationDataSource: PackageInformationDataSource by inject() - private val context: Context by inject() +class AppDtoMapper( + private val packageInformationDataSource: PackageInformationDataSource, + context: Context +) : EntityMapper<AppDto, App> { private val latestVersionRadioButton = - RadioButtonPreference( - title = context.getString(R.string.app_version_dialog_option_latest), + InstallationOptionItem( + displayText = context.getString(R.string.app_version_dialog_option_latest), key = "latest" ) override suspend fun mapToModel(entity: AppDto): App = with(entity) { - val localVersionCode = packageInformationDataSource.getVersionCode(packageName ?: "") + val localVersionCode = packageInformationDataSource.getVersionCode(packageName) val localVersionCodeRoot = packageInformationDataSource.getVersionCode(packageNameRoot ?: "") - val localVersionName = packageInformationDataSource.getVersionName(packageName ?: "") + val localVersionName = packageInformationDataSource.getVersionName(packageName) val localVersionNameRoot = packageInformationDataSource.getVersionName(packageNameRoot ?: "") App( @@ -64,12 +53,11 @@ class AppDtoMapper : EntityMapper<AppDto, App>, KoinComponent { versions = versions, themes = themes, languages = languages, - downloader = getDownloader(name), - installationOptions = getInstallationOptions(entity) + installationOptions = getInstallationOptions(name, themes, versions, languages) ) } - private fun compareVersionCodes(remote: Int?, local: Int?): AppStatus = + private fun compareVersionCodes(remote: Int?, local: Int?) = if (local != null && remote != null) { when { remote > local -> AppStatus.Update @@ -80,60 +68,73 @@ class AppDtoMapper : EntityMapper<AppDto, App>, KoinComponent { AppStatus.Install } - private fun getInstallationOptions(app: AppDto): List<InstallationOption>? = - when (app.name) { + private fun getInstallationOptions( + appName: String, + appThemes: List<String>?, + appVersions: List<String>?, + appLanguages: List<String>?, + ) = when (appName) { VANCED_NAME -> listOf( - RadiobuttonInstallationOption( + InstallationOption.SingleSelect( titleId = R.string.app_installation_options_theme, - preference = vancedThemePref, - buttons = app.themes?.map { version -> - RadioButtonPreference( - title = version.replaceFirstChar { it.titlecase(Locale.getDefault()) }, - key = version + getOption = { vancedThemePref.value.value }, + setOption = { + vancedThemePref.save(it) + }, + items = appThemes?.map { theme -> + InstallationOptionItem( + displayText = theme.replaceFirstChar { + it.titlecase(Locale.getDefault()) + }, + key = theme ) - } ?: emptyList() + } ?: emptyList(), ), - RadiobuttonInstallationOption( + InstallationOption.SingleSelect( titleId = R.string.app_installation_options_version, - preference = vancedVersionPref, - buttons = app.versions?.map { - RadioButtonPreference( - title = it, - key = it + getOption = { vancedVersionPref.value.value }, + setOption = { + vancedVersionPref.save(it) + }, + items = appVersions?.map { version -> + InstallationOptionItem( + displayText = version, + key = version ) - }?.plus(latestVersionRadioButton)?.reversed() ?: emptyList() + }?.plus(latestVersionRadioButton)?.reversed() ?: emptyList(), ), - CheckboxInstallationOption( + InstallationOption.MultiSelect( titleId = R.string.app_installation_options_language, - preference = vancedLanguagesPref, - buttons = app.languages?.map { - CheckboxPreference( - title = Locale(it).displayName, - key = it + getOption = { vancedLanguagesPref.value.value }, + addOption = { + vancedLanguagesPref.save(vancedLanguagesPref.value.value + it) + }, + removeOption = { + vancedLanguagesPref.save(vancedLanguagesPref.value.value - it) + }, + items = appLanguages?.map { version -> + InstallationOptionItem( + displayText = version, + key = version ) - } ?: emptyList() + }?.plus(latestVersionRadioButton)?.reversed() ?: emptyList(), ), ) MUSIC_NAME -> listOf( - RadiobuttonInstallationOption( + InstallationOption.SingleSelect( titleId = R.string.app_installation_options_version, - preference = musicVersionPref, - buttons = app.versions?.map { - RadioButtonPreference( - title = it, - key = it + getOption = { musicVersionPref.value.value }, + setOption = { + musicVersionPref.save(it) + }, + items = appVersions?.map { version -> + InstallationOptionItem( + displayText = version, + key = version ) - }?.plus(latestVersionRadioButton)?.reversed() ?: emptyList() - ), + } ?: emptyList(), + ) ) else -> null } - - private fun getDownloader(app: String?): AppDownloader? = - when (app) { - VANCED_NAME -> get<VancedDownloader>() - MUSIC_NAME -> get<MusicDownloader>() - MICROG_NAME -> get<MicrogDownloader>() - else -> null - } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index cce3d45b27..181b58decf 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -10,26 +10,25 @@ import androidx.compose.material.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBackIos import androidx.compose.material.icons.filled.MoreVert -import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember +import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import androidx.compose.ui.util.fastForEach import androidx.navigation.NavHostController import androidx.navigation.compose.currentBackStackEntryAsState import com.google.accompanist.navigation.animation.AnimatedNavHost import com.google.accompanist.navigation.animation.composable import com.google.accompanist.navigation.animation.rememberAnimatedNavController +import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.vanced.manager.ui.component.color.managerAnimatedColor import com.vanced.manager.ui.component.color.managerSurfaceColor import com.vanced.manager.ui.component.color.managerTextColor import com.vanced.manager.ui.component.menu.ManagerDropdownMenuItem import com.vanced.manager.ui.component.text.ToolbarTitleText import com.vanced.manager.ui.resources.managerString +import com.vanced.manager.ui.screens.* import com.vanced.manager.ui.theme.ManagerTheme +import com.vanced.manager.ui.theme.isDark import com.vanced.manager.ui.util.Screen class MainActivity : ComponentActivity() { @@ -49,19 +48,23 @@ class MainActivity : ComponentActivity() { val isMenuExpanded = remember { mutableStateOf(false) } val surfaceColor = managerSurfaceColor() + + val isDark = isDark() + val navController = rememberAnimatedNavController() + val systemUiController = rememberSystemUiController() + + SideEffect { + systemUiController.setSystemBarsColor( + color = surfaceColor, + darkIcons = !isDark + ) + } - val screens = listOf( - Screen.Home, - Screen.Settings, - Screen.About, - Screen.Logs - ) Scaffold( topBar = { MainToolbar( navController = navController, - screens = screens, isMenuExpanded = isMenuExpanded ) }, @@ -91,12 +94,29 @@ class MainActivity : ComponentActivity() { ) } ) { - screens.fastForEach { screen -> - composable( - route = screen.route, - ) { - screen.content() - } + composable(Screen.Home.route) { + HomeLayout(navController) + } + composable(Screen.Settings.route) { + SettingsLayout() + } + composable(Screen.About.route) { + AboutLayout() + } + composable(Screen.InstallPreferences.route) { + val arguments = navController.previousBackStackEntry?.arguments + + InstallPreferencesScreen( + installationOptions = arguments?.getParcelableArrayList("app")!! + ) + } + composable(Screen.Install.route,) { + val arguments = navController.previousBackStackEntry?.arguments + + InstallScreen( + appName = arguments?.getString("appName")!!, + appVersions = arguments.getParcelableArrayList("appVersions")!! + ) } } } @@ -105,7 +125,6 @@ class MainActivity : ComponentActivity() { @Composable fun MainToolbar( navController: NavHostController, - screens: List<Screen>, isMenuExpanded: MutableState<Boolean> ) { val currentScreenRoute = @@ -115,7 +134,7 @@ class MainActivity : ComponentActivity() { title = { ToolbarTitleText( text = managerString( - stringId = screens.find { it.route == currentScreenRoute }?.displayName + stringId = Screen.values().find { it.route == currentScreenRoute }?.displayName ) ) }, @@ -139,7 +158,7 @@ class MainActivity : ComponentActivity() { }, modifier = Modifier.background(MaterialTheme.colors.surface), ) { - screens.filter { it.route != currentScreenRoute }.forEach { screen -> + for (screen in Screen.values()) { ManagerDropdownMenuItem( title = stringResource(id = screen.displayName) ) { diff --git a/app/src/main/java/com/vanced/manager/ui/component/button/ManagerIconButton.kt b/app/src/main/java/com/vanced/manager/ui/component/button/ManagerIconButton.kt index dee1b46f0c..27a808e352 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/button/ManagerIconButton.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/button/ManagerIconButton.kt @@ -28,7 +28,7 @@ fun IconButton( onClick = onClick, role = Role.Button, interactionSource = interactionSource, - indication = rememberRipple(bounded = false, radius = 18.dp) + indication = rememberRipple(radius = buttonSize / 2) ) .size(buttonSize), contentAlignment = Alignment.Center diff --git a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerLinkCard.kt b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerLinkCard.kt index 4cc2a5e43a..3acd2e9be7 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerLinkCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerLinkCard.kt @@ -7,7 +7,7 @@ import androidx.browser.customtabs.CustomTabsIntent import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext -import com.vanced.manager.preferences.holder.useCustomTabsPref +import com.vanced.manager.core.preferences.holder.useCustomTabsPref @Composable fun ManagerLinkCard( diff --git a/app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt b/app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt index f2762ad147..081f83e620 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt @@ -6,7 +6,7 @@ import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.luminance -import com.vanced.manager.preferences.holder.managerAccentColorPref +import com.vanced.manager.core.preferences.holder.managerAccentColorPref @Composable fun contentColorForColor(color: Color) = diff --git a/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt b/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt index bf9174ad14..1dbd8b4ba4 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt @@ -8,8 +8,8 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.window.Dialog import com.vanced.manager.ui.component.card.ManagerCard import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.util.defaultContentPaddingHorizontal -import com.vanced.manager.ui.util.defaultContentPaddingVertical +import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal +import com.vanced.manager.ui.util.DefaultContentPaddingVertical @Composable fun ManagerDialog( @@ -46,8 +46,8 @@ fun ManagerDialog( content = { ManagerCard { Column( - modifier = Modifier.padding(defaultContentPaddingHorizontal), - verticalArrangement = Arrangement.spacedBy(defaultContentPaddingVertical) + modifier = Modifier.padding(DefaultContentPaddingHorizontal), + verticalArrangement = Arrangement.spacedBy(DefaultContentPaddingVertical) ) { title() content() diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerButtonColumn.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerButtonColumn.kt index 4ef62a2505..48e1f840b1 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerButtonColumn.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerButtonColumn.kt @@ -5,7 +5,7 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import com.vanced.manager.ui.util.defaultContentPaddingVertical +import com.vanced.manager.ui.util.DefaultContentPaddingVertical @Composable fun ManagerButtonColumn( @@ -14,7 +14,7 @@ fun ManagerButtonColumn( ) { Column( modifier = modifier, - verticalArrangement = Arrangement.spacedBy(defaultContentPaddingVertical), + verticalArrangement = Arrangement.spacedBy(DefaultContentPaddingVertical), content = content ) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt index 339ee39feb..0c77f78c15 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt @@ -5,11 +5,13 @@ import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp @Composable fun ManagerLazyColumn( + modifier: Modifier = Modifier, itemSpacing: Dp = 0.dp, content: LazyListScope.() -> Unit ) { diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrollableColumn.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrollableColumn.kt index aec175e29e..be7f89c028 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrollableColumn.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrollableColumn.kt @@ -11,17 +11,18 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.util.defaultContentPaddingVertical +import com.vanced.manager.ui.util.DefaultContentPaddingVertical @Composable fun ManagerScrollableColumn( - contentPaddingVertical: Dp = defaultContentPaddingVertical, + modifier: Modifier = Modifier, + contentPaddingVertical: Dp = DefaultContentPaddingVertical, itemSpacing: Dp = 0.dp, content: @Composable ColumnScope.() -> Unit ) { val scrollState = rememberScrollState() Column( - modifier = Modifier + modifier = modifier .verticalScroll(scrollState) .padding(vertical = contentPaddingVertical), horizontalAlignment = Alignment.CenterHorizontally, diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt index 203e357d90..c58dbd1ddc 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt @@ -12,8 +12,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.vanced.manager.R -import com.vanced.manager.preferences.CheckboxPreference -import com.vanced.manager.preferences.ManagerPreference +import com.vanced.manager.core.preferences.CheckboxPreference +import com.vanced.manager.core.preferences.ManagerPreference import com.vanced.manager.ui.component.button.ManagerThemedTextButton import com.vanced.manager.ui.widget.list.CheckboxItem import kotlinx.coroutines.launch diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt index abe2a15616..b4533436aa 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt @@ -3,7 +3,7 @@ package com.vanced.manager.ui.component.preference import androidx.compose.runtime.Composable import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.unit.dp -import com.vanced.manager.preferences.ManagerPreference +import com.vanced.manager.core.preferences.ManagerPreference import com.vanced.manager.ui.widget.checkbox.ManagerAnimatedCheckbox import kotlinx.coroutines.launch diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt index 04013eeeaa..bad3c9cd0f 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt @@ -11,7 +11,7 @@ import com.vanced.manager.ui.component.color.managerAnimatedColor import com.vanced.manager.ui.component.list.ManagerListItem import com.vanced.manager.ui.component.modifier.managerClickable import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.util.defaultContentPaddingHorizontal +import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal @Composable fun Preference( @@ -43,7 +43,7 @@ fun Preference( ManagerListItem( modifier = Modifier .managerClickable(onClick = onClick) - .padding(horizontal = defaultContentPaddingHorizontal), + .padding(horizontal = DefaultContentPaddingHorizontal), title = { CompositionLocalProvider( LocalContentColor provides color, diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt index a2d666c15d..ceffad7799 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt @@ -6,8 +6,8 @@ import androidx.compose.foundation.lazy.items import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import com.vanced.manager.preferences.ManagerPreference -import com.vanced.manager.preferences.RadioButtonPreference +import com.vanced.manager.core.preferences.ManagerPreference +import com.vanced.manager.core.preferences.RadioButtonPreference import com.vanced.manager.ui.widget.button.ManagerSaveButton import com.vanced.manager.ui.widget.list.RadiobuttonItem import kotlinx.coroutines.launch diff --git a/app/src/main/java/com/vanced/manager/ui/component/text/AppVersionText.kt b/app/src/main/java/com/vanced/manager/ui/component/text/AppVersionText.kt index fe1277d89d..ab25f2c41d 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/text/AppVersionText.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/text/AppVersionText.kt @@ -2,12 +2,15 @@ package com.vanced.manager.ui.component.text import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier @Composable fun AppVersionText( - text: String + text: String, + modifier: Modifier = Modifier, ) { ManagerText( + modifier = modifier, text = text, textStyle = MaterialTheme.typography.body2, ) diff --git a/app/src/main/java/com/vanced/manager/ui/component/text/CategoryTitleText.kt b/app/src/main/java/com/vanced/manager/ui/component/text/CategoryTitleText.kt index ff0bbe9e6f..5684a59f12 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/text/CategoryTitleText.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/text/CategoryTitleText.kt @@ -5,14 +5,14 @@ import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import com.vanced.manager.ui.component.color.managerAnimatedColor -import com.vanced.manager.ui.util.defaultContentPaddingHorizontal +import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal @Composable fun CategoryTitleText( text: String ) { ManagerText( - modifier = Modifier.padding(start = defaultContentPaddingHorizontal), + modifier = Modifier.padding(start = DefaultContentPaddingHorizontal), text = text, textStyle = MaterialTheme.typography.h2, color = managerAnimatedColor(MaterialTheme.colors.onSurface) diff --git a/app/src/main/java/com/vanced/manager/ui/component/text/ManagerText.kt b/app/src/main/java/com/vanced/manager/ui/component/text/ManagerText.kt index 188676f177..25870bd20f 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/text/ManagerText.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/text/ManagerText.kt @@ -11,11 +11,11 @@ import androidx.compose.ui.text.style.TextAlign @Composable fun ManagerText( + text: String, modifier: Modifier = Modifier, color: Color = Color.Unspecified, textStyle: TextStyle = LocalTextStyle.current, textAlign: TextAlign? = null, - text: String, ) { Text( modifier = modifier, @@ -28,11 +28,11 @@ fun ManagerText( @Composable fun ManagerText( + text: AnnotatedString, modifier: Modifier = Modifier, color: Color = Color.Unspecified, textStyle: TextStyle = LocalTextStyle.current, textAlign: TextAlign? = null, - text: AnnotatedString, ) { Text( modifier = modifier, diff --git a/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt index 8ac5454a10..8ac9440680 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt @@ -24,7 +24,7 @@ import com.vanced.manager.ui.component.layout.ScrollableItemRow import com.vanced.manager.ui.component.list.ManagerListItem import com.vanced.manager.ui.component.text.ManagerText import com.vanced.manager.ui.resources.managerString -import com.vanced.manager.ui.util.defaultContentPaddingVertical +import com.vanced.manager.ui.util.DefaultContentPaddingVertical import com.vanced.manager.ui.widget.layout.CategoryLayout data class Person( @@ -171,7 +171,7 @@ fun AboutManagerCard() { modifier = Modifier.fillMaxWidth() ) { Column( - modifier = Modifier.padding(vertical = defaultContentPaddingVertical), + modifier = Modifier.padding(vertical = DefaultContentPaddingVertical), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(4.dp) ) { diff --git a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt index ab8eedd312..6664027267 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt @@ -1,58 +1,145 @@ package com.vanced.manager.ui.screens -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.animation.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.* +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import androidx.navigation.NavController +import coil.compose.rememberImagePainter +import coil.request.CachePolicy import com.google.accompanist.swiperefresh.rememberSwipeRefreshState import com.vanced.manager.R +import com.vanced.manager.core.util.socialMedia +import com.vanced.manager.core.util.sponsors +import com.vanced.manager.ui.component.card.ManagerLinkCard +import com.vanced.manager.ui.component.dialog.ManagerDialog import com.vanced.manager.ui.component.layout.ManagerScrollableColumn import com.vanced.manager.ui.component.layout.ManagerSwipeRefresh +import com.vanced.manager.ui.component.layout.ScrollableItemRow +import com.vanced.manager.ui.component.text.ManagerText import com.vanced.manager.ui.resources.managerString -import com.vanced.manager.ui.util.defaultContentPaddingVertical +import com.vanced.manager.ui.util.DefaultContentPaddingVertical +import com.vanced.manager.ui.util.Screen import com.vanced.manager.ui.viewmodel.MainViewModel +import com.vanced.manager.ui.widget.app.AppCard +import com.vanced.manager.ui.widget.app.AppCardPlaceholder +import com.vanced.manager.ui.widget.button.ManagerCloseButton import com.vanced.manager.ui.widget.layout.CategoryLayout -import com.vanced.manager.ui.widget.screens.home.apps.HomeAppsItem -import com.vanced.manager.ui.widget.screens.home.socialmedia.HomeSocialMediaItem -import com.vanced.manager.ui.widget.screens.home.sponsors.HomeSponsorsItem import org.koin.androidx.compose.getViewModel +@ExperimentalAnimationApi @Composable -@Preview -fun HomeLayout() { +fun HomeLayout( + navController: NavController +) { val viewModel: MainViewModel = getViewModel() - val isFetching by viewModel.isFetching.collectAsState() - val refreshState = rememberSwipeRefreshState(isRefreshing = isFetching) + val appState by viewModel.appState.collectAsState() + + val refreshState = rememberSwipeRefreshState(isRefreshing = appState is MainViewModel.AppState.Fetching) ManagerSwipeRefresh( refreshState = refreshState, onRefresh = { viewModel.fetch() } ) { ManagerScrollableColumn( - contentPaddingVertical = defaultContentPaddingVertical, + contentPaddingVertical = DefaultContentPaddingVertical, itemSpacing = 18.dp ) { CategoryLayout( - categoryName = managerString( - stringId = R.string.home_category_apps - ), + categoryName = managerString(R.string.home_category_apps), contentPaddingHorizontal = 0.dp ) { - HomeAppsItem(viewModel) + AnimatedContent( + targetState = appState, + transitionSpec = { + scaleIn(initialScale = 0.9f) + fadeIn() with + scaleOut(targetScale = 0.9f) + fadeOut() + } + ) { animatedAppState -> + Column( + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + when (animatedAppState) { + is MainViewModel.AppState.Success -> { + for (app in animatedAppState.apps) { + val appIcon = rememberImagePainter(app.iconUrl) { + diskCachePolicy(CachePolicy.ENABLED) + } + + var showAppInfoDialog by rememberSaveable { mutableStateOf(false) } + + AppCard( + appName = app.name, + appIcon = appIcon, + appInstalledVersion = app.installedVersion, + appRemoteVersion = app.remoteVersion, + onDownloadClick = { + if (app.installationOptions != null) { + navController.navigate(Screen.InstallPreferences.route) + } else { + navController.navigate(Screen.Install.route) + } + + }, + onUninstallClick = { /*TODO*/ }, + onLaunchClick = { /*TODO*/ }, + onInfoClick = { + showAppInfoDialog = true + } + ) + + if (showAppInfoDialog) { + ManagerDialog( + title = managerString(R.string.app_info_title, app.name), + onDismissRequest = { showAppInfoDialog = false }, + buttons = { + ManagerCloseButton(onClick = { + showAppInfoDialog = false + }) + } + ) { + ManagerText( + modifier = Modifier.padding(top = 4.dp), + text = app.changelog, + textStyle = MaterialTheme.typography.subtitle1 + ) + } + } + } + } + is MainViewModel.AppState.Fetching -> { + for (i in 0 until animatedAppState.placeholderAppsCount) { + AppCardPlaceholder() + } + } + is MainViewModel.AppState.Error -> { + + } + } + } + } } - CategoryLayout( - categoryName = managerString( - stringId = R.string.home_category_support_us - ) - ) { - HomeSponsorsItem() + CategoryLayout(managerString(R.string.home_category_support_us)) { + ScrollableItemRow(items = sponsors) { sponsor -> + ManagerLinkCard( + icon = sponsor.icon, + title = sponsor.title, + link = sponsor.link + ) + } } - CategoryLayout( - categoryName = managerString( - stringId = R.string.home_category_social_media - ) - ) { - HomeSocialMediaItem() + CategoryLayout( managerString(R.string.home_category_social_media)) { + ScrollableItemRow(items = socialMedia) { socialMedia -> + ManagerLinkCard( + icon = socialMedia.icon, + title = socialMedia.title, + link = socialMedia.link + ) + } } } } diff --git a/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt b/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt new file mode 100644 index 0000000000..5fa3e27e50 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt @@ -0,0 +1,104 @@ +package com.vanced.manager.ui.screens + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.sizeIn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.Scaffold +import androidx.compose.runtime.* +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.compose.ui.util.fastForEachIndexed +import com.vanced.manager.domain.model.InstallationOption +import com.vanced.manager.ui.component.card.ManagerCard +import com.vanced.manager.ui.component.layout.ManagerLazyColumn +import com.vanced.manager.ui.component.layout.ManagerScrollableColumn +import com.vanced.manager.ui.component.text.ManagerText +import com.vanced.manager.ui.resources.managerString +import com.vanced.manager.ui.widget.list.CheckboxItem +import com.vanced.manager.ui.widget.list.RadiobuttonItem + +@Composable +fun InstallPreferencesScreen( + installationOptions: List<InstallationOption> +) { + var selectedOptionIndex by rememberSaveable { mutableStateOf(0) } + + Scaffold( + floatingActionButton = { + + } + ) { paddingValues -> + ManagerScrollableColumn( + modifier = Modifier.padding(paddingValues) + ) { + installationOptions.fastForEachIndexed { index, installationOption -> + ManagerCard(onClick = { + selectedOptionIndex = index + }) { + Column { + ManagerText( + text = managerString(installationOption.itemTitleId), + textStyle = TextStyle( + fontSize = 20.sp, + fontWeight = FontWeight.SemiBold + ) + ) + AnimatedVisibility( + visible = index == selectedOptionIndex + ) { + ManagerLazyColumn( + modifier = Modifier.sizeIn( + minHeight = 400.dp, + maxHeight = 400.dp + ) + ) { + when (installationOption) { + is InstallationOption.MultiSelect -> { + items(installationOption.items) { item -> + val preference = installationOption.getOption() + CheckboxItem( + modifier = Modifier.fillMaxWidth(), + text = item.displayText, + isChecked = preference.contains(item.key), + onCheck = { + if (it) { + installationOption.addOption(item.key) + } else { + installationOption.removeOption(item.key) + } + } + ) + } + } + is InstallationOption.SingleSelect -> { + items(installationOption.items) { item -> + val preference = installationOption.getOption() + RadiobuttonItem( + modifier = Modifier.fillMaxWidth(), + text = item.displayText, + isSelected = preference == item.key, + onSelect = { + installationOption.setOption(item.key) + }, + tag = item.key + ) + } + } + } + } + } + } + } + } + } + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt b/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt new file mode 100644 index 0000000000..5e7eb3790b --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt @@ -0,0 +1,190 @@ +package com.vanced.manager.ui.screens + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.items +import androidx.compose.material.FloatingActionButton +import androidx.compose.material.Icon +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Scaffold +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.ArrowDropDown +import androidx.compose.runtime.* +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.rotate +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.withStyle +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.vanced.manager.core.downloader.impl.MicrogDownloader +import com.vanced.manager.core.downloader.impl.MusicDownloader +import com.vanced.manager.core.downloader.impl.VancedDownloader +import com.vanced.manager.core.downloader.util.DownloadStatus +import com.vanced.manager.core.installer.impl.MicrogInstaller +import com.vanced.manager.core.installer.impl.MusicInstaller +import com.vanced.manager.core.installer.impl.VancedInstaller +import com.vanced.manager.network.util.MICROG_NAME +import com.vanced.manager.network.util.MUSIC_NAME +import com.vanced.manager.network.util.VANCED_NAME +import com.vanced.manager.ui.component.layout.ManagerLazyColumn +import com.vanced.manager.ui.component.modifier.managerClickable +import com.vanced.manager.ui.component.progressindicator.ManagerProgressIndicator +import com.vanced.manager.ui.component.text.ManagerText +import com.vanced.manager.ui.viewmodel.MainViewModel +import org.koin.androidx.compose.get +import org.koin.androidx.compose.getViewModel + +sealed class Log { + data class Info(val infoText: String) : Log() + data class Success(val successText: String) : Log() + data class Error( + val displayText: String, + val stacktrace: String, + ) : Log() +} + +@Composable +fun InstallScreen( + appName: String, + appVersions: List<String> +) { + val logs = rememberSaveable { mutableStateListOf<Log>() } + + var progress by rememberSaveable { mutableStateOf(0f) } + var installing by rememberSaveable { mutableStateOf(false) } + + val viewModel: MainViewModel = getViewModel() + + val downloader = when (appName) { + VANCED_NAME -> get<VancedDownloader>() + MUSIC_NAME -> get<MusicDownloader>() + MICROG_NAME -> get<MicrogDownloader>() + else -> throw IllegalArgumentException("$appName is not a valid app") + } + + val installer = when (appName) { + VANCED_NAME -> get<VancedInstaller>() + MUSIC_NAME -> get<MusicInstaller>() + MICROG_NAME -> get<MicrogInstaller>() + else -> throw IllegalArgumentException("$appName is not a valid app") + } + + //FIXME this is absolutely bad, must move to WorkManager + LaunchedEffect(true) { + downloader.download(appVersions) { status -> + when (status) { + is DownloadStatus.File -> logs.add(Log.Info("Downloading ${status.fileName}")) + is DownloadStatus.Error -> logs.add(Log.Error( + displayText = status.displayError, + stacktrace = status.stacktrace + )) + is DownloadStatus.Progress -> progress = status.progress + is DownloadStatus.StartInstall -> { + installing = true + installer.install { + viewModel.fetch() + } + } + } + } + } + + Scaffold( + topBar = { + if (installing) { + ManagerProgressIndicator() + } else { + ManagerProgressIndicator(progress) + } + }, + floatingActionButton = { + FloatingActionButton(onClick = { /*TODO*/ }) { + + } + } + ) { paddingValues -> + ManagerLazyColumn( + modifier = Modifier.padding(paddingValues) + ) { + items(logs) { log -> + when (log) { + is Log.Success -> { + ManagerText( + text = log.successText, + textStyle = TextStyle( + fontWeight = FontWeight.Bold, + fontSize = 14.sp, + color = Color.Green + ), + ) + } + is Log.Info -> { + ManagerText( + text = log.infoText, + textStyle = TextStyle( + fontWeight = FontWeight.SemiBold, + fontSize = 14.sp, + color = Color.Green + ), + ) + } + is Log.Error -> { + var visible by remember { mutableStateOf(false) } + val iconRotation by animateFloatAsState(if (visible) 0f else 90f) + Row( + modifier = Modifier.managerClickable { + visible = !visible + }, + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + Icon( + modifier = Modifier.rotate(iconRotation), + imageVector = Icons.Rounded.ArrowDropDown, + contentDescription = "expand", + ) + Column( + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + ManagerText( + text = buildAnnotatedString { + withStyle(SpanStyle(color = MaterialTheme.colors.error)) { + append(log.displayText) + append(": ") + } + withStyle(SpanStyle(color = MaterialTheme.colors.error.copy(alpha = 0.7f))) { + append(log.stacktrace) + } + }, + textStyle = TextStyle( + fontWeight = FontWeight.Bold, + fontSize = 14.sp, + color = Color.Green + ), + ) + AnimatedVisibility(visible) { + ManagerText( + text = log.stacktrace, + textStyle = TextStyle( + fontWeight = FontWeight.Bold, + fontSize = 14.sp, + color = Color.Green + ), + ) + } + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/screens/LogLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/LogLayout.kt index ebaa7abc97..5632b6bde0 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/LogLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/LogLayout.kt @@ -13,7 +13,7 @@ import androidx.compose.ui.Modifier import com.vanced.manager.ui.component.color.managerAccentColor import com.vanced.manager.ui.component.color.managerSurfaceColor import com.vanced.manager.ui.component.layout.ManagerLazyColumn -import com.vanced.manager.util.logs +import com.vanced.manager.core.util.logs @Composable fun LogLayout() { diff --git a/app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt index 923713099a..7ee69359ff 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt @@ -5,14 +5,14 @@ import androidx.compose.ui.unit.dp import com.vanced.manager.R import com.vanced.manager.ui.component.layout.ManagerScrollableColumn import com.vanced.manager.ui.resources.managerString -import com.vanced.manager.ui.util.defaultContentPaddingVertical +import com.vanced.manager.ui.util.DefaultContentPaddingVertical import com.vanced.manager.ui.widget.layout.SettingsCategoryLayout import com.vanced.manager.ui.widget.screens.settings.* @Composable fun SettingsLayout() { ManagerScrollableColumn( - contentPaddingVertical = defaultContentPaddingVertical, + contentPaddingVertical = DefaultContentPaddingVertical, itemSpacing = 12.dp ) { SettingsCategoryLayout( diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt index 3005ccaf9a..226f435d92 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt @@ -5,7 +5,7 @@ import androidx.compose.material.MaterialTheme import androidx.compose.material.darkColors import androidx.compose.material.lightColors import androidx.compose.runtime.Composable -import com.vanced.manager.preferences.holder.managerThemePref +import com.vanced.manager.core.preferences.holder.managerThemePref const val defAccentColor = 0xFF0477E1 diff --git a/app/src/main/java/com/vanced/manager/ui/util/Const.kt b/app/src/main/java/com/vanced/manager/ui/util/Const.kt index 8ae7364882..abd4c2d659 100644 --- a/app/src/main/java/com/vanced/manager/ui/util/Const.kt +++ b/app/src/main/java/com/vanced/manager/ui/util/Const.kt @@ -2,16 +2,5 @@ package com.vanced.manager.ui.util import androidx.compose.ui.unit.dp -val defaultContentPaddingHorizontal = 16.dp -val defaultContentPaddingVertical = 12.dp - -fun test(anotherFun: () -> Int) = anotherFun() + 5 -fun test(anotherNum: Int) = anotherNum + 5 - -fun test2() { - test { - print("haha jonathan you are banging my number") - return@test 0 - } - test(0) -} \ No newline at end of file +val DefaultContentPaddingHorizontal = 16.dp +val DefaultContentPaddingVertical = 12.dp \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/util/Screen.kt b/app/src/main/java/com/vanced/manager/ui/util/Screen.kt index 769139ace8..573fe61bbe 100644 --- a/app/src/main/java/com/vanced/manager/ui/util/Screen.kt +++ b/app/src/main/java/com/vanced/manager/ui/util/Screen.kt @@ -8,41 +8,32 @@ import com.vanced.manager.ui.screens.HomeLayout import com.vanced.manager.ui.screens.LogLayout import com.vanced.manager.ui.screens.SettingsLayout -sealed class Screen( +enum class Screen( val route: String, @StringRes val displayName: Int, - val content: @Composable () -> Unit ) { - - object Home : Screen( + Home( route = "home", - displayName = R.string.app_name, - content = { - HomeLayout() - } - ) - - object Settings : Screen( + displayName = R.string.app_name + ), + Settings( route = "settings", displayName = R.string.toolbar_settings, - content = { - SettingsLayout() - } - ) - - object About : Screen( + ), + About( route = "about", displayName = R.string.toolbar_about, - content = { - AboutLayout() - } - ) - - object Logs : Screen( + ), + Logs( route = "logs", displayName = R.string.toolbar_logs, - content = { - LogLayout() - } - ) + ), + InstallPreferences( + route = "installpreferences", + displayName = R.string.toolbar_installation_preferences + ), + Install( + route = "install", + displayName = R.string.toolbar_install + ), } diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt index 569de47400..992186fd87 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt @@ -1,13 +1,12 @@ package com.vanced.manager.ui.viewmodel import android.util.Log -import androidx.compose.runtime.* import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.vanced.manager.domain.model.App -import com.vanced.manager.preferences.holder.managerVariantPref -import com.vanced.manager.preferences.holder.musicEnabled -import com.vanced.manager.preferences.holder.vancedEnabled +import com.vanced.manager.core.preferences.holder.managerVariantPref +import com.vanced.manager.core.preferences.holder.musicEnabled +import com.vanced.manager.core.preferences.holder.vancedEnabled import com.vanced.manager.repository.JsonRepository import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow @@ -18,40 +17,54 @@ class MainViewModel( private val repository: JsonRepository ) : ViewModel() { - private val vanced = MutableStateFlow(App()) - private val music = MutableStateFlow(App()) - private val microg = MutableStateFlow(App()) - private val manager = MutableStateFlow(App()) + sealed class AppState { - private val _isFetching = MutableStateFlow(false) - val isFetching: StateFlow<Boolean> = _isFetching + data class Fetching(val placeholderAppsCount: Int) : AppState() - val apps = mutableListOf<StateFlow<App>>() + data class Success(val apps: List<App>) : AppState() + + data class Error(val error: String) : AppState() + + } + + private val _appState = MutableStateFlow<AppState>(AppState.Fetching(3)) + val appState: StateFlow<AppState> = _appState fun fetch() { viewModelScope.launch(Dispatchers.IO) { - _isFetching.value = true + val vancedEnabled = vancedEnabled.value.value + val musicEnabled = musicEnabled.value.value + val isNonroot = managerVariantPref.value.value == "nonroot" + + var appsCount = 0 + + if (vancedEnabled) appsCount++ + if (musicEnabled) appsCount++ + if (isNonroot) appsCount++ + + _appState.value = AppState.Fetching(appsCount) + try { with(repository.fetch()) { - this@MainViewModel.vanced.value = vanced - this@MainViewModel.music.value = music - this@MainViewModel.microg.value = microg + val apps = mutableListOf<App>() + + apps.apply { + if (vancedEnabled) add(vanced) + if (musicEnabled) add(music) + if (isNonroot) add(microg) + } + + _appState.value = AppState.Success(apps) } } catch (e: Exception) { - Log.d("HomeViewModel", "failed to fetch: $e") + val error = "failed to fetch: \n${e.stackTraceToString()}" + _appState.value = AppState.Error(error) + Log.d("MainViewModel", error) } - - _isFetching.value = false } } init { - apps.apply { - if (vancedEnabled.value.value) add(vanced) - if (musicEnabled.value.value) add(music) - if (managerVariantPref.value.value == "nonroot") add(microg) - } - fetch() } diff --git a/app/src/main/java/com/vanced/manager/ui/widget/app/AppCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/app/AppCard.kt new file mode 100644 index 0000000000..3b77e17f11 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widget/app/AppCard.kt @@ -0,0 +1,91 @@ +package com.vanced.manager.ui.widget.app + +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.size +import androidx.compose.material.MaterialTheme +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Info +import androidx.compose.material.icons.rounded.DeleteForever +import androidx.compose.material.icons.rounded.Download +import androidx.compose.material.icons.rounded.Launch +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import coil.compose.ImagePainter +import com.vanced.manager.R +import com.vanced.manager.ui.component.button.IconButton +import com.vanced.manager.ui.component.text.AppVersionText +import com.vanced.manager.ui.component.text.ManagerText + +@OptIn(ExperimentalAnimationApi::class) +@Composable +fun AppCard( + appName: String, + appIcon: ImagePainter, + appInstalledVersion: String?, + appRemoteVersion: String?, + onDownloadClick: () -> Unit, + onUninstallClick: () -> Unit, + onLaunchClick: () -> Unit, + onInfoClick: () -> Unit, +) { + BaseAppCard( + appTitle = { + ManagerText( + modifier = Modifier.fillMaxSize(), + text = appName, + textStyle = MaterialTheme.typography.h5 + ) + }, + appIcon = { + Image( + modifier = Modifier.size(48.dp), + painter = appIcon, + contentDescription = "App Icon", + ) + }, + appVersionsColumn = { + AppVersionText( + text = stringResource( + id = R.string.app_version_latest, + appRemoteVersion ?: stringResource( + id = R.string.app_content_unavailable + ) + ) + ) + AppVersionText( + text = stringResource( + id = R.string.app_version_installed, + appInstalledVersion ?: stringResource( + id = R.string.app_content_unavailable + ) + ) + ) + }, + appActionsRow = { + IconButton( + icon = Icons.Outlined.Info, + contentDescription = "App Info", + onClick = onInfoClick + ) + IconButton( + icon = Icons.Rounded.DeleteForever, + contentDescription = "Uninstall", + onClick = onUninstallClick + ) + IconButton( + icon = Icons.Rounded.Launch, + contentDescription = "Launch", + onClick = onLaunchClick + ) + IconButton( + icon = Icons.Rounded.Download, + contentDescription = "Install", + onClick = onDownloadClick + ) + } + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/app/AppCardPlaceholder.kt b/app/src/main/java/com/vanced/manager/ui/widget/app/AppCardPlaceholder.kt new file mode 100644 index 0000000000..3a6e67d6e2 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widget/app/AppCardPlaceholder.kt @@ -0,0 +1,57 @@ +package com.vanced.manager.ui.widget.app + +import androidx.compose.foundation.layout.* +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.unit.dp +import com.vanced.manager.ui.component.modifier.managerPlaceholder +import com.vanced.manager.ui.component.text.AppVersionText +import com.vanced.manager.ui.component.text.ManagerText + +@Composable +fun AppCardPlaceholder() { + BaseAppCard( + appTitle = { + ManagerText( + modifier = Modifier + .clip(MaterialTheme.shapes.medium) + .managerPlaceholder(true), + text = " ".repeat(40), + textStyle = MaterialTheme.typography.h5 + ) + }, + appIcon = { + Box( + Modifier + .clip(MaterialTheme.shapes.medium) + .managerPlaceholder(true) + .size(48.dp) + ) + }, + appVersionsColumn = { + AppVersionText( + modifier = Modifier + .managerPlaceholder(true) + .clip(MaterialTheme.shapes.small), + text = " ".repeat(30) + ) + AppVersionText( + modifier = Modifier + .managerPlaceholder(true) + .clip(MaterialTheme.shapes.small), + text = " ".repeat(30) + ) + }, + appActionsRow = { + Box( + Modifier + .clip(MaterialTheme.shapes.medium) + .fillMaxWidth(0.8f) + .height(36.dp) + .managerPlaceholder(true) + ) + } + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/app/BaseAppCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/app/BaseAppCard.kt new file mode 100644 index 0000000000..c85789ff15 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widget/app/BaseAppCard.kt @@ -0,0 +1,69 @@ +package com.vanced.manager.ui.widget.app + +import androidx.compose.foundation.layout.* +import androidx.compose.material.LocalContentColor +import androidx.compose.material.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import com.vanced.manager.R +import com.vanced.manager.ui.component.card.ManagerCard +import com.vanced.manager.ui.component.card.ManagerThemedCard +import com.vanced.manager.ui.component.list.ManagerListItem +import com.vanced.manager.ui.component.text.ManagerText +import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal +import com.vanced.manager.ui.util.DefaultContentPaddingVertical + +@Composable +fun BaseAppCard( + appTitle: @Composable () -> Unit, + appIcon: @Composable () -> Unit, + appVersionsColumn: @Composable ColumnScope.() -> Unit, + appActionsRow: @Composable RowScope.() -> Unit, +) { + ManagerThemedCard { + Column { + ManagerCard { + ManagerListItem( + modifier = Modifier.padding( + horizontal = DefaultContentPaddingHorizontal, + vertical = DefaultContentPaddingVertical + ), + title = appTitle, + icon = appIcon + ) + } + CompositionLocalProvider( + LocalContentColor provides MaterialTheme.colors.onSurface + ) { + Row( + modifier = Modifier.padding( + horizontal = DefaultContentPaddingHorizontal, + vertical = 8.dp + ), + verticalAlignment = Alignment.CenterVertically, + ) { + Column( + modifier = Modifier + .weight(1f) + .wrapContentWidth(Alignment.Start), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + ManagerText(stringResource(id = R.string.app_versions)) + appVersionsColumn() + } + Row( + modifier = Modifier + .weight(1f) + .padding(start = 4.dp) + .wrapContentWidth(Alignment.End), + content = appActionsRow + ) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/layout/CategoryLayout.kt b/app/src/main/java/com/vanced/manager/ui/widget/layout/CategoryLayout.kt index b3ee9ab2b1..f314532c52 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/layout/CategoryLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/layout/CategoryLayout.kt @@ -5,14 +5,14 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.Dp import com.vanced.manager.ui.component.text.CategoryTitleText -import com.vanced.manager.ui.util.defaultContentPaddingHorizontal -import com.vanced.manager.ui.util.defaultContentPaddingVertical +import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal +import com.vanced.manager.ui.util.DefaultContentPaddingVertical @Composable fun CategoryLayout( categoryName: String, - contentPaddingHorizontal: Dp = defaultContentPaddingHorizontal, - categoryNameSpacing: Dp = defaultContentPaddingVertical, + contentPaddingHorizontal: Dp = DefaultContentPaddingHorizontal, + categoryNameSpacing: Dp = DefaultContentPaddingVertical, content: @Composable () -> Unit, ) { Column( diff --git a/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt index dc3206d76e..cb2c60375f 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt @@ -1,6 +1,5 @@ package com.vanced.manager.ui.widget.list -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.Text import androidx.compose.runtime.Composable @@ -16,13 +15,13 @@ import com.vanced.manager.ui.widget.checkbox.ManagerAnimatedCheckbox fun CheckboxItem( text: String, isChecked: Boolean, - onCheck: (Boolean) -> Unit = {} + onCheck: (Boolean) -> Unit, + modifier: Modifier = Modifier, ) { val toggle = { onCheck(!isChecked) } ManagerSelectableListItem( - modifier = Modifier - .fillMaxWidth() + modifier = modifier .managerClickable(onClick = toggle), title = { Text( diff --git a/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt index 5846aee935..afdc156325 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt @@ -17,12 +17,12 @@ fun <T> RadiobuttonItem( text: String, tag: T, isSelected: Boolean, - onSelect: (tag: T) -> Unit + onSelect: (tag: T) -> Unit, + modifier: Modifier = Modifier ) { val onClick = { onSelect(tag) } ManagerSelectableListItem( modifier = Modifier - .fillMaxWidth() .managerClickable(onClick = onClick), title = { Text( diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/AppsItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/AppsItem.kt deleted file mode 100644 index b5c7980ae4..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/AppsItem.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.vanced.manager.ui.widget.screens.home.apps - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.ui.unit.dp -import androidx.compose.ui.util.fastForEach -import com.vanced.manager.ui.viewmodel.MainViewModel -import com.vanced.manager.ui.widget.screens.home.apps.card.AppCard - -@Composable -fun HomeAppsItem( - viewModel: MainViewModel -) { - Column( - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - viewModel.apps.fastForEach { app -> - val observedApp by app.collectAsState() - AppCard(observedApp, viewModel) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppActionCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppActionCard.kt deleted file mode 100644 index 015a09c8ab..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppActionCard.kt +++ /dev/null @@ -1,94 +0,0 @@ -package com.vanced.manager.ui.widget.screens.home.apps.card - -import androidx.compose.foundation.layout.* -import androidx.compose.material.LocalContentColor -import androidx.compose.material.MaterialTheme -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Info -import androidx.compose.material.icons.rounded.DeleteForever -import androidx.compose.material.icons.rounded.Download -import androidx.compose.material.icons.rounded.Launch -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import com.vanced.manager.R -import com.vanced.manager.ui.component.button.IconButton -import com.vanced.manager.ui.component.text.AppVersionText -import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.util.defaultContentPaddingHorizontal - -@Composable -fun AppActionCard( - appRemoteVersion: String?, - appInstalledVersion: String?, - onInfoClick: () -> Unit, - onUninstallClick: () -> Unit, - onLaunchClick: () -> Unit, - onDownloadClick: () -> Unit, -) { - CompositionLocalProvider(LocalContentColor provides MaterialTheme.colors.onSurface) { - Row( - modifier = Modifier.padding( - horizontal = defaultContentPaddingHorizontal - ), - verticalAlignment = Alignment.CenterVertically - ) { - Column( - modifier = Modifier - .weight(1f) - .wrapContentWidth(Alignment.Start), - verticalArrangement = Arrangement.spacedBy(4.dp) - ) { - ManagerText( - text = stringResource(id = R.string.app_versions) - ) - AppVersionText( - text = stringResource( - id = R.string.app_version_latest, - appRemoteVersion ?: stringResource( - id = R.string.app_content_unavailable - ) - ) - ) - AppVersionText( - text = stringResource( - id = R.string.app_version_installed, - appInstalledVersion ?: stringResource( - id = R.string.app_content_unavailable - ) - ) - ) - } - Row( - modifier = Modifier - .weight(1f) - .padding(start = 4.dp) - .wrapContentWidth(Alignment.End) - ) { - IconButton( - icon = Icons.Outlined.Info, - contentDescription = "App Info", - onClick = onInfoClick - ) - IconButton( - icon = Icons.Rounded.DeleteForever, - contentDescription = "Uninstall", - onClick = onUninstallClick - ) - IconButton( - icon = Icons.Rounded.Launch, - contentDescription = "Launch", - onClick = onLaunchClick - ) - IconButton( - icon = Icons.Rounded.Download, - contentDescription = "Install", - onClick = onDownloadClick - ) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppCard.kt deleted file mode 100644 index b3a775b65c..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppCard.kt +++ /dev/null @@ -1,139 +0,0 @@ -package com.vanced.manager.ui.widget.screens.home.apps.card - -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.animation.core.tween -import androidx.compose.animation.expandVertically -import androidx.compose.animation.shrinkVertically -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.runtime.* -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.IntSize -import androidx.compose.ui.unit.dp -import coil.compose.rememberImagePainter -import com.vanced.manager.domain.model.App -import com.vanced.manager.ui.component.card.ManagerThemedCard -import com.vanced.manager.ui.component.layout.ManagerButtonColumn -import com.vanced.manager.ui.util.defaultContentPaddingHorizontal -import com.vanced.manager.ui.util.defaultContentPaddingVertical -import com.vanced.manager.ui.viewmodel.MainViewModel -import com.vanced.manager.ui.widget.button.ManagerCancelButton -import com.vanced.manager.ui.widget.button.ManagerDownloadButton -import com.vanced.manager.ui.widget.screens.home.apps.dialog.AppChangelogDialog -import com.vanced.manager.ui.widget.screens.home.apps.dialog.AppDownloadDialog -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch - -@OptIn(ExperimentalAnimationApi::class) -@Composable -fun AppCard( - app: App, - viewModel: MainViewModel -) { - var showAppInfoDialog by rememberSaveable { mutableStateOf(false) } - var showInstallationOptions by rememberSaveable { mutableStateOf(false) } - - val coroutineScope = rememberCoroutineScope { Dispatchers.IO } - - val icon = rememberImagePainter( - data = app.iconUrl - ) - - val hasInstallationOptions = app.installationOptions != null - val animationSpec = tween<IntSize>(400) - - val downloader = app.downloader - - val download: () -> Unit = { - showInstallationOptions = false - coroutineScope.launch { - downloader!!.download(app, viewModel) - } - } - - Column { - ManagerThemedCard { - Column { - AppInfoCard( - appName = app.name, - icon = icon, - ) - Column( - modifier = Modifier.padding(vertical = defaultContentPaddingVertical) - ) { - AppActionCard( - appInstalledVersion = app.installedVersion, - appRemoteVersion = app.remoteVersion, - onDownloadClick = { - if (hasInstallationOptions) { - showInstallationOptions = true - } else { - download() - } - }, - onInfoClick = { - showAppInfoDialog = true - }, - onLaunchClick = {}, - onUninstallClick = {} - ) - } - } - } - if (hasInstallationOptions) { - AnimatedVisibility( - modifier = Modifier.fillMaxWidth(), - visible = showInstallationOptions, - enter = expandVertically( - animationSpec = animationSpec - ), - exit = shrinkVertically( - animationSpec = animationSpec - ) - ) { - Column( - modifier = Modifier.padding(vertical = 4.dp) - ) { - app.installationOptions?.forEach { - it.item() - } - ManagerButtonColumn( - modifier = Modifier - .padding(horizontal = defaultContentPaddingHorizontal) - .padding(top = defaultContentPaddingVertical) - ) { - ManagerDownloadButton( - onClick = download - ) - ManagerCancelButton { - showInstallationOptions = false - } - } - } - } - } - } - - if (app.name != null && downloader != null && downloader.showDownloadScreen.value) { - AppDownloadDialog( - app = app.name, - downloader = downloader, - onCancelClick = { - downloader.cancelDownload() - } - ) - } - - if (app.name != null && app.changelog != null && showAppInfoDialog) { - AppChangelogDialog( - appName = app.name, - changelog = app.changelog, - onDismissRequest = { - showAppInfoDialog = false - } - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppInfoCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppInfoCard.kt deleted file mode 100644 index f765ed094a..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/card/AppInfoCard.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.vanced.manager.ui.widget.screens.home.apps.card - -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import coil.annotation.ExperimentalCoilApi -import coil.compose.ImagePainter -import com.vanced.manager.ui.component.card.ManagerCard -import com.vanced.manager.ui.component.list.ManagerListItem -import com.vanced.manager.ui.component.modifier.managerPlaceholder -import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.util.defaultContentPaddingHorizontal - -@OptIn(ExperimentalCoilApi::class) -@Composable -fun AppInfoCard( - appName: String?, - icon: ImagePainter, -) { - ManagerCard { - ManagerListItem( - modifier = Modifier.padding( - horizontal = defaultContentPaddingHorizontal, - vertical = 12.dp - ), - title = { - ManagerText( - modifier = Modifier.managerPlaceholder(appName == null), - text = appName ?: "", - textStyle = MaterialTheme.typography.h5 - ) - }, - icon = { - Image( - modifier = Modifier - .size(48.dp) - .managerPlaceholder(icon.state is ImagePainter.State.Loading), - painter = icon, - contentDescription = "", - ) - } - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/dialog/AppChangelogDialog.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/dialog/AppChangelogDialog.kt deleted file mode 100644 index aeaec0b02a..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/dialog/AppChangelogDialog.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.vanced.manager.ui.widget.screens.home.apps.dialog - -import androidx.compose.foundation.layout.padding -import androidx.compose.material.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.vanced.manager.R -import com.vanced.manager.ui.component.dialog.ManagerDialog -import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.resources.managerString -import com.vanced.manager.ui.widget.button.ManagerCloseButton - -@Composable -fun AppChangelogDialog( - appName: String, - changelog: String, - onDismissRequest: () -> Unit, -) { - ManagerDialog( - title = managerString(R.string.app_info_title, appName), - onDismissRequest = onDismissRequest, - buttons = { - ManagerCloseButton(onClick = onDismissRequest) - } - ) { - ManagerText( - modifier = Modifier.padding(top = 4.dp), - text = changelog, - textStyle = MaterialTheme.typography.subtitle1 - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/dialog/AppDownloadDialog.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/dialog/AppDownloadDialog.kt deleted file mode 100644 index 4b6a0b8091..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/apps/dialog/AppDownloadDialog.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.vanced.manager.ui.widget.screens.home.apps.dialog - -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.material.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import com.vanced.manager.R -import com.vanced.manager.downloader.base.AppDownloader -import com.vanced.manager.ui.component.dialog.ManagerDialog -import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.widget.button.ManagerCancelButton -import com.vanced.manager.ui.widget.screens.home.download.AppDownloadDialogProgress - -@Composable -fun AppDownloadDialog( - app: String, - downloader: AppDownloader, - onCancelClick: () -> Unit, -) { - ManagerDialog( - title = app, - onDismissRequest = {}, - buttons = { - ManagerCancelButton(onClick = onCancelClick) - } - ) { - ManagerText( - modifier = Modifier.fillMaxWidth(), - text = stringResource(id = R.string.app_download_dialog_subtitle), - textStyle = MaterialTheme.typography.subtitle2, - textAlign = TextAlign.Center - ) - AppDownloadDialogProgress( - progress = downloader.downloadProgress, - file = downloader.downloadFile, - installing = downloader.installing - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/download/AppDownloadDialogProgress.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/download/AppDownloadDialogProgress.kt deleted file mode 100644 index dd7636cd5f..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/download/AppDownloadDialogProgress.kt +++ /dev/null @@ -1,45 +0,0 @@ -package com.vanced.manager.ui.widget.screens.home.download - -import androidx.compose.animation.core.animateIntAsState -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.wrapContentWidth -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.unit.dp -import com.vanced.manager.R -import com.vanced.manager.ui.component.progressindicator.ManagerProgressIndicator -import com.vanced.manager.ui.resources.managerString - -@Composable -fun AppDownloadDialogProgress( - progress: Float, - file: String, - installing: Boolean -) { - when (installing) { - true -> ManagerProgressIndicator() - false -> ManagerProgressIndicator(progress = progress / 100f) - } - val animatedProgress by animateIntAsState(targetValue = progress.toInt()) - Row { - Text( - modifier = Modifier - .weight(1f) - .wrapContentWidth(Alignment.Start), - text = managerString( - stringId = R.string.app_download_dialog_downloading_file, - file - ) - ) - Text( - modifier = Modifier - .padding(start = 4.dp) - .wrapContentWidth(Alignment.End), - text = "$animatedProgress%" - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/CheckboxInstallationOption.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/CheckboxInstallationOption.kt deleted file mode 100644 index bc7d703aaa..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/CheckboxInstallationOption.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.vanced.manager.ui.widget.screens.home.installation - -import androidx.annotation.StringRes -import com.vanced.manager.preferences.CheckboxPreference -import com.vanced.manager.preferences.ManagerPreference -import com.vanced.manager.ui.component.preference.CheckboxDialogPreference -import com.vanced.manager.ui.resources.managerString - -data class CheckboxInstallationOption( - @StringRes val titleId: Int, - val preference: ManagerPreference<Set<String>>, - val buttons: List<CheckboxPreference> -) : InstallationOption( - item = { - CheckboxDialogPreference( - preferenceTitle = managerString(stringId = titleId), - preference = preference, - buttons = buttons - ) - } -) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/InstallationOption.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/InstallationOption.kt deleted file mode 100644 index 1a3a6fa119..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/InstallationOption.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.vanced.manager.ui.widget.screens.home.installation - -import androidx.compose.runtime.Composable - -open class InstallationOption( - val item: @Composable () -> Unit -) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/RadiobuttonInstallationOption.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/RadiobuttonInstallationOption.kt deleted file mode 100644 index 58bd616667..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/installation/RadiobuttonInstallationOption.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.vanced.manager.ui.widget.screens.home.installation - -import androidx.annotation.StringRes -import com.vanced.manager.preferences.ManagerPreference -import com.vanced.manager.preferences.RadioButtonPreference -import com.vanced.manager.ui.component.preference.RadiobuttonDialogPreference -import com.vanced.manager.ui.resources.managerString - -data class RadiobuttonInstallationOption( - @StringRes val titleId: Int, - val preference: ManagerPreference<String>, - val buttons: List<RadioButtonPreference> -) : InstallationOption( - item = { - RadiobuttonDialogPreference( - preferenceTitle = managerString(stringId = titleId), - preference = preference, - buttons = buttons - ) - } -) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/socialmedia/SocialMediaItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/socialmedia/SocialMediaItem.kt deleted file mode 100644 index 3b96427c1e..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/socialmedia/SocialMediaItem.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.vanced.manager.ui.widget.screens.home.socialmedia - -import androidx.compose.runtime.Composable -import com.vanced.manager.ui.component.card.ManagerLinkCard -import com.vanced.manager.ui.component.layout.ScrollableItemRow -import com.vanced.manager.util.socialMedia - -@Composable -fun HomeSocialMediaItem() { - ScrollableItemRow(items = socialMedia) { socialMedia -> - ManagerLinkCard( - icon = socialMedia.icon, - title = socialMedia.title, - link = socialMedia.link - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/sponsors/SponsorsItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/home/sponsors/SponsorsItem.kt deleted file mode 100644 index 45332625e3..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/home/sponsors/SponsorsItem.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.vanced.manager.ui.widget.screens.home.sponsors - -import androidx.compose.runtime.Composable -import com.vanced.manager.ui.component.card.ManagerLinkCard -import com.vanced.manager.ui.component.layout.ScrollableItemRow -import com.vanced.manager.util.sponsors - -@Composable -fun HomeSponsorsItem() { - ScrollableItemRow(items = sponsors) { sponsor -> - ManagerLinkCard( - icon = sponsor.icon, - title = sponsor.title, - link = sponsor.link - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt index 570f5113cf..d93c27576c 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt @@ -3,7 +3,7 @@ package com.vanced.manager.ui.widget.screens.settings import androidx.compose.runtime.* import androidx.compose.ui.graphics.Color import com.vanced.manager.R -import com.vanced.manager.preferences.holder.managerAccentColorPref +import com.vanced.manager.core.preferences.holder.managerAccentColorPref import com.vanced.manager.ui.component.color.ManagerColorPicker import com.vanced.manager.ui.component.preference.DialogPreference import com.vanced.manager.ui.resources.managerString diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/CustomTabsItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/CustomTabsItem.kt index 8cc6d31ab1..db01f79166 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/CustomTabsItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/CustomTabsItem.kt @@ -3,7 +3,7 @@ package com.vanced.manager.ui.widget.screens.settings import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import com.vanced.manager.R -import com.vanced.manager.preferences.holder.useCustomTabsPref +import com.vanced.manager.core.preferences.holder.useCustomTabsPref import com.vanced.manager.ui.component.preference.CheckboxPreference @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt index bf5cc30dcb..a0121c150e 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt @@ -2,8 +2,8 @@ package com.vanced.manager.ui.widget.screens.settings import androidx.compose.runtime.Composable import com.vanced.manager.R -import com.vanced.manager.preferences.RadioButtonPreference -import com.vanced.manager.preferences.holder.managerVariantPref +import com.vanced.manager.core.preferences.RadioButtonPreference +import com.vanced.manager.core.preferences.holder.managerVariantPref import com.vanced.manager.ui.component.preference.RadiobuttonDialogPreference import com.vanced.manager.ui.resources.managerString diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/NotificationsItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/NotificationsItem.kt index 86f11ae440..342ff63ae1 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/NotificationsItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/NotificationsItem.kt @@ -1,9 +1,9 @@ package com.vanced.manager.ui.widget.screens.settings import androidx.compose.runtime.Composable -import com.vanced.manager.preferences.managerBooleanPreference +import com.vanced.manager.core.preferences.managerBooleanPreference +import com.vanced.manager.core.util.notificationApps import com.vanced.manager.ui.component.preference.CheckboxPreference -import com.vanced.manager.util.notificationApps @Composable fun SettingsNotificationsItem() { diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt index c77ec5146e..11038023f1 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt @@ -2,8 +2,8 @@ package com.vanced.manager.ui.widget.screens.settings import androidx.compose.runtime.Composable import com.vanced.manager.R -import com.vanced.manager.preferences.RadioButtonPreference -import com.vanced.manager.preferences.holder.managerThemePref +import com.vanced.manager.core.preferences.RadioButtonPreference +import com.vanced.manager.core.preferences.holder.managerThemePref import com.vanced.manager.ui.component.preference.RadiobuttonDialogPreference import com.vanced.manager.ui.resources.managerString diff --git a/app/src/main/java/com/vanced/manager/util/AppHelper.kt b/app/src/main/java/com/vanced/manager/util/AppHelper.kt deleted file mode 100644 index bd7abb3c69..0000000000 --- a/app/src/main/java/com/vanced/manager/util/AppHelper.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.vanced.manager.util - -import com.vanced.manager.domain.model.App - -fun getLatestOrProvidedAppVersion( - version: String, - app: App -): String { - if (version == "latest") { - return app.versions?.last() ?: version - } - return version -} \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 38a4d1c2f6..fe9274372b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -71,6 +71,8 @@ <string name="toolbar_home">Manager</string> <string name="toolbar_logs">Logs</string> <string name="toolbar_settings">Settings</string> + <string name="toolbar_install">Install</string> + <string name="toolbar_installation_preferences">Installation Preferences</string> <string name="toolbar_update_manager">Update Manager</string> <!-- App Card --> diff --git a/build.gradle.kts b/build.gradle.kts index 54564af2e4..a057b51296 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,9 +4,10 @@ buildscript { mavenCentral() } + val kotlinVersion = "1.5.31" dependencies { classpath("com.android.tools.build:gradle:7.0.3") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.31") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") } } From f7d0afc3b64c51544f9fd8e2ca577766a9c1df81 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Wed, 3 Nov 2021 00:35:12 +0400 Subject: [PATCH 065/118] implement proper installation --- app/build.gradle.kts | 8 +- app/src/main/AndroidManifest.xml | 2 + .../core/downloader/base/AppDownloader.kt | 6 +- .../core/downloader/impl/MicrogDownloader.kt | 3 +- .../core/downloader/impl/MusicDownloader.kt | 10 +- .../core/downloader/impl/VancedDownloader.kt | 10 +- .../core/installer/base/AppInstaller.kt | 33 +- .../core/installer/impl/MicrogInstaller.kt | 20 +- .../core/installer/impl/MusicInstaller.kt | 21 +- .../core/installer/impl/VancedInstaller.kt | 27 +- .../installer/service/AppInstallService.kt | 44 +++ .../vanced/manager/core/installer/util/PM.kt | 73 +++++ .../com/vanced/manager/core/util/AppHelper.kt | 5 +- .../com/vanced/manager/di/InstallerModuke.kt | 19 +- .../com/vanced/manager/di/ViewModelModule.kt | 2 + .../domain/model/InstallationOption.kt | 2 +- .../manager/network/model/AppDtoMapper.kt | 23 +- .../com/vanced/manager/ui/MainActivity.kt | 291 +++++++++--------- .../ui/component/layout/ManagerLazyColumn.kt | 5 +- .../vanced/manager/ui/screens/HomeLayout.kt | 14 +- .../ui/screens/InstallPreferencesScreen.kt | 62 ++-- .../manager/ui/screens/InstallScreen.kt | 181 +++++------ .../java/com/vanced/manager/ui/util/Screen.kt | 37 ++- .../manager/ui/viewmodel/InstallViewModel.kt | 131 ++++++++ .../manager/ui/viewmodel/MainViewModel.kt | 3 + 25 files changed, 645 insertions(+), 387 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/core/installer/service/AppInstallService.kt create mode 100644 app/src/main/java/com/vanced/manager/core/installer/util/PM.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f16a92b465..f5328a761e 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -79,12 +79,12 @@ val languages: String get() { dependencies { implementation(kotlin("reflect")) - implementation("androidx.core:core-ktx:1.6.0") + implementation("androidx.core:core-ktx:1.7.0") implementation("androidx.appcompat:appcompat:1.3.1") implementation("com.google.android.material:material:1.4.0") implementation("androidx.browser:browser:1.3.0") - val composeVersion = "1.1.0-alpha06" + val composeVersion = "1.1.0-beta01" implementation("androidx.compose.compiler:compiler:$composeVersion") implementation("androidx.compose.foundation:foundation:$composeVersion") implementation("androidx.compose.material:material-icons-core:$composeVersion") @@ -96,9 +96,11 @@ dependencies { implementation("androidx.compose.ui:ui-util:$composeVersion") implementation("androidx.compose.ui:ui:$composeVersion") + implementation("com.github.zsoltk:compose-router:0.28.0") + implementation("androidx.preference:preference-ktx:1.1.1") - implementation("androidx.activity:activity-compose:1.3.1") + implementation("androidx.activity:activity-compose:1.4.0") val lifecycleVersion = "2.4.0-beta01" implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleVersion") diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f2f746742f..d23988b9c8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -43,6 +43,8 @@ <service android:name="com.xinto.apkhelper.services.PackageManagerService" /> + <service android:name=".core.installer.service.AppInstallService" /> + </application> </manifest> \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/downloader/base/AppDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/base/AppDownloader.kt index 4628b30b63..7901506f23 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/base/AppDownloader.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/base/AppDownloader.kt @@ -18,7 +18,7 @@ abstract class AppDownloader { private lateinit var call: DownloadCall abstract suspend fun download( - appVersions: List<String>, + appVersions: List<String>?, onStatus: (DownloadStatus) -> Unit ) @@ -41,9 +41,7 @@ abstract class AppDownloader { if (response.isSuccessful) { val body = response.body() if (body != null) { - writeFile(body, downloadFile.fileName) { progress -> - onProgress(progress) - } + writeFile(body, downloadFile.fileName, onProgress) } continue } diff --git a/app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt index 7d017e4074..daf1933f1a 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt @@ -1,6 +1,7 @@ package com.vanced.manager.core.downloader.impl import android.content.Context +import android.util.Log import com.vanced.manager.core.downloader.api.MicrogAPI import com.vanced.manager.core.downloader.base.AppDownloader import com.vanced.manager.core.downloader.util.DownloadStatus @@ -12,7 +13,7 @@ class MicrogDownloader( ) : AppDownloader() { override suspend fun download( - appVersions: List<String>, + appVersions: List<String>?, onStatus: (DownloadStatus) -> Unit ) { downloadFiles( diff --git a/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt index 20fdb1e8db..c317480234 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt @@ -17,18 +17,18 @@ class MusicDownloader( private val version by musicVersionPref private val variant by managerVariantPref - private lateinit var correctVersion: String + private lateinit var absoluteVersion: String override suspend fun download( - appVersions: List<String>, + appVersions: List<String>?, onStatus: (DownloadStatus) -> Unit ) { - correctVersion = getLatestOrProvidedAppVersion(version, appVersions) + absoluteVersion = getLatestOrProvidedAppVersion(version, appVersions) downloadFiles( downloadFiles = arrayOf(DownloadFile( call = musicAPI.getFiles( - version = correctVersion, + version = absoluteVersion, variant = variant, ), fileName = "music.apk" @@ -53,7 +53,7 @@ class MusicDownloader( override fun getSavedFilePath(): String { val directory = - File(context.getExternalFilesDir("vancedmusic")!!.path + "$correctVersion/$variant") + File(context.getExternalFilesDir("vancedmusic")!!.path + "$absoluteVersion/$variant") if (!directory.exists()) directory.mkdirs() diff --git a/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt index dacad5937a..6cfcb69e56 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt @@ -22,13 +22,13 @@ class VancedDownloader( private val variant by managerVariantPref private val languages by vancedLanguagesPref - private lateinit var correctVersion: String + private lateinit var absoluteVersion: String override suspend fun download( - appVersions: List<String>, + appVersions: List<String>?, onStatus: (DownloadStatus) -> Unit ) { - correctVersion = getLatestOrProvidedAppVersion(version, appVersions) + absoluteVersion = getLatestOrProvidedAppVersion(version, appVersions) val files = arrayOf( getFile( @@ -68,7 +68,7 @@ class VancedDownloader( override fun getSavedFilePath(): String { val directory = - File(context.getExternalFilesDir("vanced")!!.path + "$correctVersion/$variant") + File(context.getExternalFilesDir("vanced")!!.path + "/$absoluteVersion/$variant") if (!directory.exists()) directory.mkdirs() @@ -81,7 +81,7 @@ class VancedDownloader( apkName: String, ) = DownloadFile( call = vancedAPI.getFiles( - version = correctVersion, + version = absoluteVersion, variant = variant, type = type, apkName = apkName diff --git a/app/src/main/java/com/vanced/manager/core/installer/base/AppInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/base/AppInstaller.kt index 21ed798478..24d029944d 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/base/AppInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/base/AppInstaller.kt @@ -1,36 +1,7 @@ package com.vanced.manager.core.installer.base -import android.content.Context -import androidx.annotation.CallSuper -import com.vanced.manager.core.util.log -import com.xinto.apkhelper.statusCallback -import com.xinto.apkhelper.statusCallbackBuilder -import org.koin.core.component.KoinComponent -import org.koin.core.component.inject +abstract class AppInstaller { -open class AppInstaller : KoinComponent { - - val context: Context by inject() - - @CallSuper - open fun install( - onDone: () -> Unit - ) { - setStatusCallback(onDone = onDone) - } - - private fun setStatusCallback( - onDone: () -> Unit - ) { - statusCallback = statusCallbackBuilder( - onInstall = { _, _ -> - onDone() - }, - onInstallFailed = { error, _, _ -> - onDone() - log("install", error) - } - ) - } + abstract fun install(appVersions: List<String>?) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt index fc3f4ad638..766a9b2dcd 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt @@ -1,19 +1,17 @@ package com.vanced.manager.core.installer.impl +import android.content.Context import com.vanced.manager.core.installer.base.AppInstaller -import com.xinto.apkhelper.installApk +import com.vanced.manager.core.installer.util.installApp +import java.io.File -class MicrogInstaller : AppInstaller() { +class MicrogInstaller( + private val context: Context +) : AppInstaller() { - override fun install( - onDone: () -> Unit - ) { - super.install(onDone) - - installApk( - apkPath = context.getExternalFilesDir("microg/microg.apk")!!.path, - context = context - ) + override fun install(appVersions: List<String>?) { + val musicApk = File(context.getExternalFilesDir("microg/microg.apk")!!.path) + installApp(musicApk, context) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt index 5da7a7db2b..d19e64621e 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt @@ -1,24 +1,23 @@ package com.vanced.manager.core.installer.impl +import android.content.Context import com.vanced.manager.core.installer.base.AppInstaller +import com.vanced.manager.core.installer.util.installApp import com.vanced.manager.core.preferences.holder.managerVariantPref import com.vanced.manager.core.preferences.holder.musicVersionPref -import com.xinto.apkhelper.installApk +import java.io.File -class MusicInstaller : AppInstaller() { - - override fun install( - onDone: () -> Unit - ) { - super.install(onDone) +class MusicInstaller( + private val context: Context +) : AppInstaller() { + override fun install(appVersions: List<String>?) { val version by musicVersionPref val variant by managerVariantPref - installApk( - apkPath = context.getExternalFilesDir("music/$version/$variant/music.apk")!!.path, - context = context - ) + val musicApk = File(context.getExternalFilesDir("music/$version/$variant/music.apk")!!.path) + + installApp(musicApk, context) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt index 56cf82a5d3..7e6f3b24d2 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt @@ -1,24 +1,29 @@ package com.vanced.manager.core.installer.impl +import android.content.Context import com.vanced.manager.core.installer.base.AppInstaller +import com.vanced.manager.core.installer.util.installSplitApp import com.vanced.manager.core.preferences.holder.managerVariantPref import com.vanced.manager.core.preferences.holder.vancedVersionPref -import com.xinto.apkhelper.installSplitApks +import com.vanced.manager.core.util.getLatestOrProvidedAppVersion -class VancedInstaller : AppInstaller() { - - override fun install( - onDone: () -> Unit - ) { - super.install(onDone) +class VancedInstaller( + private val context: Context +) : AppInstaller() { + override fun install(appVersions: List<String>?) { val version by vancedVersionPref val variant by managerVariantPref - installSplitApks( - apksPath = context.getExternalFilesDir("vanced/$version/$variant")!!.path, - context = context - ) + val absoluteVersion = getLatestOrProvidedAppVersion(version, appVersions) + + val apks = context + .getExternalFilesDir("vanced/$absoluteVersion/$variant")!! + .listFiles { file -> + file.extension == "apk" + } + + installSplitApp(apks!!, context) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/installer/service/AppInstallService.kt b/app/src/main/java/com/vanced/manager/core/installer/service/AppInstallService.kt new file mode 100644 index 0000000000..bef5867c7f --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/installer/service/AppInstallService.kt @@ -0,0 +1,44 @@ +package com.vanced.manager.core.installer.service + +import android.app.Service +import android.content.Intent +import android.content.pm.PackageInstaller +import android.os.IBinder + +class AppInstallService : Service() { + + override fun onStartCommand( + intent: Intent, + flags: Int, + startId: Int + ): Int { + when (val status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -999)) { + PackageInstaller.STATUS_PENDING_USER_ACTION -> { + startActivity( + intent.getParcelableExtra<Intent>(Intent.EXTRA_INTENT).apply { + this?.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + ) + } + else -> { + sendBroadcast(Intent().apply { + action = APP_INSTALL_STATUS + putExtra(EXTRA_INSTALL_STATUS, status) + putExtra(EXTRA_INSTALL_EXTRA, intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE)) + }) + } + } + stopSelf() + return START_NOT_STICKY + } + + override fun onBind(intent: Intent?): IBinder? = null + + companion object { + const val APP_INSTALL_STATUS = "APP_INSTALL_STATUS" + + const val EXTRA_INSTALL_STATUS = "EXTRA_INSTALL_STATUS" + const val EXTRA_INSTALL_EXTRA = "EXTRA_INSTALL_EXTRA" + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/installer/util/PM.kt b/app/src/main/java/com/vanced/manager/core/installer/util/PM.kt new file mode 100644 index 0000000000..8bb1f08a12 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/installer/util/PM.kt @@ -0,0 +1,73 @@ +package com.vanced.manager.core.installer.util + +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.content.pm.PackageInstaller +import android.content.pm.PackageManager +import android.os.Build +import com.vanced.manager.core.installer.service.AppInstallService +import java.io.File +import java.io.FileInputStream + +private const val byteArraySize = 1024 * 1024 // Because 1,048,576 is not readable + +fun installApp(apk: File, context: Context) { + val packageInstaller = context.packageManager.packageInstaller + val session = + packageInstaller.openSession(packageInstaller.createSession(sessionParams)) + writeApkToSession(apk, session) + session.commit(getIntentSender(context)) + session.close() +} + +fun installSplitApp(apks: Array<File>, context: Context) { + val packageInstaller = context.packageManager.packageInstaller + val session = + packageInstaller.openSession(packageInstaller.createSession(sessionParams)) + for (apk in apks) { + writeApkToSession(apk, session) + } + session.commit(getIntentSender(context)) + session.close() +} + +private val intentFlags + get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) + PendingIntent.FLAG_MUTABLE + else + 0 + +private val sessionParams + get() = PackageInstaller.SessionParams( + PackageInstaller.SessionParams.MODE_FULL_INSTALL + ).apply { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + setInstallReason(PackageManager.INSTALL_REASON_USER) + } + } + +private fun getIntentSender(context: Context) = + PendingIntent.getService( + context, + 0, + Intent(context, AppInstallService::class.java), + intentFlags + ).intentSender + +private fun writeApkToSession( + apk: File, + session: PackageInstaller.Session +) { + val inputStream = FileInputStream(apk) + val outputStream = session.openWrite(apk.name, 0, apk.length()) + val buffer = ByteArray(byteArraySize) + var length: Int + while (inputStream.read(buffer).also { length = it } > 0) { + outputStream.write(buffer, 0, length) + } + session.fsync(outputStream) + inputStream.close() + outputStream.flush() + outputStream.close() +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/util/AppHelper.kt b/app/src/main/java/com/vanced/manager/core/util/AppHelper.kt index bbb46a782b..cfcdd85692 100644 --- a/app/src/main/java/com/vanced/manager/core/util/AppHelper.kt +++ b/app/src/main/java/com/vanced/manager/core/util/AppHelper.kt @@ -2,8 +2,11 @@ package com.vanced.manager.core.util fun getLatestOrProvidedAppVersion( version: String, - appVersions: List<String> + appVersions: List<String>? ): String { + if (appVersions == null) + return version + if (appVersions.contains(version)) return version diff --git a/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt b/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt index 907e3cdf3c..7c90797c1c 100644 --- a/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt +++ b/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt @@ -1,5 +1,6 @@ package com.vanced.manager.di +import android.content.Context import com.vanced.manager.core.installer.impl.MicrogInstaller import com.vanced.manager.core.installer.impl.MusicInstaller import com.vanced.manager.core.installer.impl.VancedInstaller @@ -7,13 +8,19 @@ import org.koin.dsl.module val installerModule = module { - fun provideVancedInstaller() = VancedInstaller() + fun provideVancedInstaller( + context: Context + ) = VancedInstaller(context) - fun provideMusicInstaller() = MusicInstaller() + fun provideMusicInstaller( + context: Context + ) = MusicInstaller(context) - fun provideMicrogInstaller() = MicrogInstaller() + fun provideMicrogInstaller( + context: Context + ) = MicrogInstaller(context) - single { provideVancedInstaller() } - single { provideMusicInstaller() } - single { provideMicrogInstaller() } + single { provideVancedInstaller(get()) } + single { provideMusicInstaller(get()) } + single { provideMicrogInstaller(get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt index c561df6a03..4aebd1216a 100644 --- a/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt +++ b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt @@ -1,9 +1,11 @@ package com.vanced.manager.di +import com.vanced.manager.ui.viewmodel.InstallViewModel import com.vanced.manager.ui.viewmodel.MainViewModel import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.dsl.module val viewModelModule = module { viewModel { MainViewModel(get()) } + viewModel { InstallViewModel(get(), get(), get(), get(), get(), get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/domain/model/InstallationOption.kt b/app/src/main/java/com/vanced/manager/domain/model/InstallationOption.kt index c5bfd46d26..c79cd4e2be 100644 --- a/app/src/main/java/com/vanced/manager/domain/model/InstallationOption.kt +++ b/app/src/main/java/com/vanced/manager/domain/model/InstallationOption.kt @@ -29,6 +29,6 @@ sealed class InstallationOption( @Parcelize data class InstallationOptionItem( - val displayText: String, val key: String, + val displayText: (key: String) -> String, ) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt index bf3f1520b8..6ef95e005b 100644 --- a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt +++ b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt @@ -23,7 +23,7 @@ class AppDtoMapper( private val latestVersionRadioButton = InstallationOptionItem( - displayText = context.getString(R.string.app_version_dialog_option_latest), + displayText = { context.getString(R.string.app_version_dialog_option_latest) }, key = "latest" ) @@ -83,8 +83,10 @@ class AppDtoMapper( }, items = appThemes?.map { theme -> InstallationOptionItem( - displayText = theme.replaceFirstChar { - it.titlecase(Locale.getDefault()) + displayText = { + theme.replaceFirstChar { + it.titlecase(Locale.getDefault()) + } }, key = theme ) @@ -98,7 +100,7 @@ class AppDtoMapper( }, items = appVersions?.map { version -> InstallationOptionItem( - displayText = version, + displayText = { "v$version" }, key = version ) }?.plus(latestVersionRadioButton)?.reversed() ?: emptyList(), @@ -112,12 +114,15 @@ class AppDtoMapper( removeOption = { vancedLanguagesPref.save(vancedLanguagesPref.value.value - it) }, - items = appLanguages?.map { version -> + items = appLanguages?.map { language -> InstallationOptionItem( - displayText = version, - key = version + displayText = { + val locale = Locale(it) + locale.getDisplayName(locale) + }, + key = language ) - }?.plus(latestVersionRadioButton)?.reversed() ?: emptyList(), + } ?: emptyList(), ), ) MUSIC_NAME -> listOf( @@ -129,7 +134,7 @@ class AppDtoMapper( }, items = appVersions?.map { version -> InstallationOptionItem( - displayText = version, + displayText = { version }, key = version ) } ?: emptyList(), diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index 181b58decf..098e37e072 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -1,9 +1,12 @@ package com.vanced.manager.ui +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.compose.animation.AnimatedContentScope import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.background import androidx.compose.material.* @@ -14,12 +17,11 @@ import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import androidx.navigation.NavHostController -import androidx.navigation.compose.currentBackStackEntryAsState -import com.google.accompanist.navigation.animation.AnimatedNavHost -import com.google.accompanist.navigation.animation.composable -import com.google.accompanist.navigation.animation.rememberAnimatedNavController +import com.github.zsoltk.compose.backpress.BackPressHandler +import com.github.zsoltk.compose.backpress.LocalBackPressHandler +import com.github.zsoltk.compose.router.Router import com.google.accompanist.systemuicontroller.rememberSystemUiController +import com.vanced.manager.core.installer.service.AppInstallService import com.vanced.manager.ui.component.color.managerAnimatedColor import com.vanced.manager.ui.component.color.managerSurfaceColor import com.vanced.manager.ui.component.color.managerTextColor @@ -30,160 +32,173 @@ import com.vanced.manager.ui.screens.* import com.vanced.manager.ui.theme.ManagerTheme import com.vanced.manager.ui.theme.isDark import com.vanced.manager.ui.util.Screen +import com.vanced.manager.ui.viewmodel.InstallViewModel +import org.koin.android.ext.android.inject class MainActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setContent { - ManagerTheme { - MainActivityLayout() - } + private val installViewModel: InstallViewModel by inject() + + private val backPressHandler = BackPressHandler() + + private val installBroadcastReceiver = object : BroadcastReceiver() { + + override fun onReceive(context: Context?, intent: Intent?) { + if (intent?.action != AppInstallService.APP_INSTALL_STATUS) return + + installViewModel.postInstallStatus( + pmStatus = intent.getIntExtra(AppInstallService.EXTRA_INSTALL_STATUS, -999), + extra = intent.getStringExtra(AppInstallService.EXTRA_INSTALL_EXTRA)!!, + ) } } @OptIn(ExperimentalAnimationApi::class) - @Composable - fun MainActivityLayout() { - val isMenuExpanded = remember { mutableStateOf(false) } - - val surfaceColor = managerSurfaceColor() + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + ManagerTheme { + var isMenuExpanded by remember { mutableStateOf(false) } + var currentScreen by remember { mutableStateOf<Screen>(Screen.Home) } - val isDark = isDark() + val surfaceColor = managerSurfaceColor() - val navController = rememberAnimatedNavController() - val systemUiController = rememberSystemUiController() + val isDark = isDark() - SideEffect { - systemUiController.setSystemBarsColor( - color = surfaceColor, - darkIcons = !isDark - ) - } + val systemUiController = rememberSystemUiController() - Scaffold( - topBar = { - MainToolbar( - navController = navController, - isMenuExpanded = isMenuExpanded - ) - }, - backgroundColor = surfaceColor - ) { - AnimatedNavHost( - navController = navController, - startDestination = Screen.Home.route, - enterTransition = { _, _ -> - slideIntoContainer( - towards = AnimatedContentScope.SlideDirection.Start - ) - }, - exitTransition = { _, _ -> - slideOutOfContainer( - towards = AnimatedContentScope.SlideDirection.End + SideEffect { + systemUiController.setSystemBarsColor( + color = surfaceColor, + darkIcons = !isDark ) - }, - popEnterTransition = { _, _ -> - slideIntoContainer( - towards = AnimatedContentScope.SlideDirection.End - ) - }, - popExitTransition = { _, _ -> - slideOutOfContainer( - towards = AnimatedContentScope.SlideDirection.Start - ) - } - ) { - composable(Screen.Home.route) { - HomeLayout(navController) - } - composable(Screen.Settings.route) { - SettingsLayout() - } - composable(Screen.About.route) { - AboutLayout() } - composable(Screen.InstallPreferences.route) { - val arguments = navController.previousBackStackEntry?.arguments - InstallPreferencesScreen( - installationOptions = arguments?.getParcelableArrayList("app")!! - ) - } - composable(Screen.Install.route,) { - val arguments = navController.previousBackStackEntry?.arguments + CompositionLocalProvider( + LocalBackPressHandler provides backPressHandler + ) { + Router<Screen>("VancedManager", Screen.Home) { backStack -> + val screen = backStack.last() + currentScreen = screen - InstallScreen( - appName = arguments?.getString("appName")!!, - appVersions = arguments.getParcelableArrayList("appVersions")!! - ) - } - } - } - } + Scaffold( + topBar = { + TopAppBar( + title = { + ToolbarTitleText( + text = managerString( + stringId = currentScreen.displayName + ) + ) + }, + backgroundColor = managerAnimatedColor(color = MaterialTheme.colors.surface), + actions = { + if (currentScreen is Screen.Home) { + IconButton( + onClick = { isMenuExpanded = true } + ) { + Icon( + imageVector = Icons.Default.MoreVert, + contentDescription = null, + tint = managerTextColor() + ) + } - @Composable - fun MainToolbar( - navController: NavHostController, - isMenuExpanded: MutableState<Boolean> - ) { - val currentScreenRoute = - navController.currentBackStackEntryAsState().value?.destination?.route - - TopAppBar( - title = { - ToolbarTitleText( - text = managerString( - stringId = Screen.values().find { it.route == currentScreenRoute }?.displayName - ) - ) - }, - backgroundColor = managerAnimatedColor(color = MaterialTheme.colors.surface), - actions = { - if (currentScreenRoute == Screen.Home.route) { - IconButton( - onClick = { isMenuExpanded.value = true } - ) { - Icon( - imageVector = Icons.Default.MoreVert, - contentDescription = null, - tint = managerTextColor() - ) - } + DropdownMenu( + expanded = isMenuExpanded, + onDismissRequest = { + isMenuExpanded = false + }, + modifier = Modifier.background(MaterialTheme.colors.surface), + ) { + ManagerDropdownMenuItem( + title = stringResource(id = Screen.Settings.displayName) + ) { + isMenuExpanded = false + backStack.push(Screen.Settings) + } + } + } + }, + navigationIcon = if (currentScreen !is Screen.Home) { + { + IconButton(onClick = { + backStack.pop() + }) { + Icon( + imageVector = Icons.Default.ArrowBackIos, + contentDescription = null, + tint = managerTextColor() + ) + } + } + } else null, + elevation = 0.dp + ) + }, + backgroundColor = surfaceColor + ) { + when (screen) { + is Screen.Home -> { + HomeLayout( + onAppInstallPress = { appName, appVersions, installationOptions -> + if (installationOptions != null) { + backStack.push(Screen.InstallPreferences(appName, appVersions, installationOptions)) + } else { + backStack.push(Screen.Install(appName, appVersions)) + } + } + ) + } + is Screen.Settings -> { + SettingsLayout() + } + is Screen.About -> { + AboutLayout() + } + is Screen.Logs -> { - DropdownMenu( - expanded = isMenuExpanded.value, - onDismissRequest = { - isMenuExpanded.value = false - }, - modifier = Modifier.background(MaterialTheme.colors.surface), - ) { - for (screen in Screen.values()) { - ManagerDropdownMenuItem( - title = stringResource(id = screen.displayName) - ) { - isMenuExpanded.value = false - navController.navigate(screen.route) + } + is Screen.InstallPreferences -> { + InstallPreferencesScreen( + installationOptions = screen.appInstallationOptions, + onDoneClick = { + backStack.push(Screen.Install(screen.appName, screen.appVersions)) + } + ) + } + is Screen.Install -> { + InstallScreen(screen.appName, screen.appVersions) + } } } } } - }, - navigationIcon = if (currentScreenRoute != Screen.Home.route) { - { - IconButton(onClick = { - navController.popBackStack() - }) { - Icon( - imageVector = Icons.Default.ArrowBackIos, - contentDescription = null, - tint = managerTextColor() - ) - } - } - } else null, - elevation = 0.dp + } + } + } + + override fun onBackPressed() { + if (!backPressHandler.handle()) + super.onBackPressed() + } + + override fun onStart() { + super.onStart() + + registerReceiver( + installBroadcastReceiver, + IntentFilter().apply { + addAction(AppInstallService.APP_INSTALL_STATUS) + } ) } + override fun onStop() { + super.onStop() + + unregisterReceiver(installBroadcastReceiver) + } + + } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt index 0c77f78c15..49fa25d74b 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt @@ -8,15 +8,18 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal @Composable fun ManagerLazyColumn( modifier: Modifier = Modifier, itemSpacing: Dp = 0.dp, + contentPadding: PaddingValues = PaddingValues(12.dp), content: LazyListScope.() -> Unit ) { LazyColumn( - contentPadding = PaddingValues(12.dp), + modifier = modifier, + contentPadding = contentPadding, verticalArrangement = Arrangement.spacedBy(itemSpacing), content = content ) diff --git a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt index 6664027267..647c1d650f 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt @@ -16,6 +16,7 @@ import com.google.accompanist.swiperefresh.rememberSwipeRefreshState import com.vanced.manager.R import com.vanced.manager.core.util.socialMedia import com.vanced.manager.core.util.sponsors +import com.vanced.manager.domain.model.InstallationOption import com.vanced.manager.ui.component.card.ManagerLinkCard import com.vanced.manager.ui.component.dialog.ManagerDialog import com.vanced.manager.ui.component.layout.ManagerScrollableColumn @@ -35,7 +36,11 @@ import org.koin.androidx.compose.getViewModel @ExperimentalAnimationApi @Composable fun HomeLayout( - navController: NavController + onAppInstallPress: ( + appName: String, + appVersions: List<String>?, + installationOptions: List<InstallationOption>? + ) -> Unit ) { val viewModel: MainViewModel = getViewModel() val appState by viewModel.appState.collectAsState() @@ -78,12 +83,7 @@ fun HomeLayout( appInstalledVersion = app.installedVersion, appRemoteVersion = app.remoteVersion, onDownloadClick = { - if (app.installationOptions != null) { - navController.navigate(Screen.InstallPreferences.route) - } else { - navController.navigate(Screen.Install.route) - } - + onAppInstallPress(app.name, app.versions, app.installationOptions) }, onUninstallClick = { /*TODO*/ }, onLaunchClick = { /*TODO*/ }, diff --git a/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt b/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt index 5fa3e27e50..8f9dc94e04 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt @@ -5,67 +5,93 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.sizeIn -import androidx.compose.foundation.lazy.items +import androidx.compose.material.FloatingActionButton +import androidx.compose.material.Icon import androidx.compose.material.Scaffold -import androidx.compose.runtime.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.Done +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import androidx.compose.ui.util.fastForEach import androidx.compose.ui.util.fastForEachIndexed import com.vanced.manager.domain.model.InstallationOption -import com.vanced.manager.ui.component.card.ManagerCard -import com.vanced.manager.ui.component.layout.ManagerLazyColumn +import com.vanced.manager.ui.component.card.ManagerClickableThemedCard import com.vanced.manager.ui.component.layout.ManagerScrollableColumn import com.vanced.manager.ui.component.text.ManagerText import com.vanced.manager.ui.resources.managerString +import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal +import com.vanced.manager.ui.util.DefaultContentPaddingVertical import com.vanced.manager.ui.widget.list.CheckboxItem import com.vanced.manager.ui.widget.list.RadiobuttonItem @Composable fun InstallPreferencesScreen( - installationOptions: List<InstallationOption> + installationOptions: List<InstallationOption>, + onDoneClick: () -> Unit ) { var selectedOptionIndex by rememberSaveable { mutableStateOf(0) } Scaffold( floatingActionButton = { - + FloatingActionButton( + onClick = onDoneClick + ) { + Icon( + imageVector = Icons.Rounded.Done, + contentDescription = "Done" + ) + } } ) { paddingValues -> ManagerScrollableColumn( - modifier = Modifier.padding(paddingValues) + modifier = Modifier.padding(paddingValues), + itemSpacing = DefaultContentPaddingVertical ) { installationOptions.fastForEachIndexed { index, installationOption -> - ManagerCard(onClick = { - selectedOptionIndex = index - }) { - Column { + ManagerClickableThemedCard( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = DefaultContentPaddingHorizontal), + onClick = { + selectedOptionIndex = index + } + ) { + Column( + modifier = Modifier.padding(12.dp) + ) { ManagerText( + modifier = Modifier.fillMaxWidth(), text = managerString(installationOption.itemTitleId), textStyle = TextStyle( fontSize = 20.sp, fontWeight = FontWeight.SemiBold - ) + ), + textAlign = TextAlign.Center ) AnimatedVisibility( visible = index == selectedOptionIndex ) { - ManagerLazyColumn( + ManagerScrollableColumn( modifier = Modifier.sizeIn( - minHeight = 400.dp, maxHeight = 400.dp ) ) { when (installationOption) { is InstallationOption.MultiSelect -> { - items(installationOption.items) { item -> + installationOption.items.fastForEach { item -> val preference = installationOption.getOption() CheckboxItem( modifier = Modifier.fillMaxWidth(), - text = item.displayText, + text = item.displayText(item.key), isChecked = preference.contains(item.key), onCheck = { if (it) { @@ -78,11 +104,11 @@ fun InstallPreferencesScreen( } } is InstallationOption.SingleSelect -> { - items(installationOption.items) { item -> + installationOption.items.fastForEach { item -> val preference = installationOption.getOption() RadiobuttonItem( modifier = Modifier.fillMaxWidth(), - text = item.displayText, + text = item.displayText(item.key), isSelected = preference == item.key, onSelect = { installationOption.setOption(item.key) diff --git a/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt b/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt index 5e7eb3790b..ea605e4c82 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt @@ -2,19 +2,16 @@ package com.vanced.manager.ui.screens import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.items -import androidx.compose.material.FloatingActionButton import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme import androidx.compose.material.Scaffold import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.ArrowDropDown import androidx.compose.runtime.* -import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate import androidx.compose.ui.graphics.Color @@ -25,161 +22,123 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import com.vanced.manager.core.downloader.impl.MicrogDownloader -import com.vanced.manager.core.downloader.impl.MusicDownloader -import com.vanced.manager.core.downloader.impl.VancedDownloader -import com.vanced.manager.core.downloader.util.DownloadStatus -import com.vanced.manager.core.installer.impl.MicrogInstaller -import com.vanced.manager.core.installer.impl.MusicInstaller -import com.vanced.manager.core.installer.impl.VancedInstaller -import com.vanced.manager.network.util.MICROG_NAME -import com.vanced.manager.network.util.MUSIC_NAME -import com.vanced.manager.network.util.VANCED_NAME import com.vanced.manager.ui.component.layout.ManagerLazyColumn import com.vanced.manager.ui.component.modifier.managerClickable import com.vanced.manager.ui.component.progressindicator.ManagerProgressIndicator import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.viewmodel.MainViewModel -import org.koin.androidx.compose.get +import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal +import com.vanced.manager.ui.util.DefaultContentPaddingVertical +import com.vanced.manager.ui.viewmodel.InstallViewModel import org.koin.androidx.compose.getViewModel -sealed class Log { - data class Info(val infoText: String) : Log() - data class Success(val successText: String) : Log() - data class Error( - val displayText: String, - val stacktrace: String, - ) : Log() -} - +@OptIn(ExperimentalFoundationApi::class) @Composable fun InstallScreen( appName: String, - appVersions: List<String> + appVersions: List<String>? ) { - val logs = rememberSaveable { mutableStateListOf<Log>() } - - var progress by rememberSaveable { mutableStateOf(0f) } - var installing by rememberSaveable { mutableStateOf(false) } - - val viewModel: MainViewModel = getViewModel() - - val downloader = when (appName) { - VANCED_NAME -> get<VancedDownloader>() - MUSIC_NAME -> get<MusicDownloader>() - MICROG_NAME -> get<MicrogDownloader>() - else -> throw IllegalArgumentException("$appName is not a valid app") - } - - val installer = when (appName) { - VANCED_NAME -> get<VancedInstaller>() - MUSIC_NAME -> get<MusicInstaller>() - MICROG_NAME -> get<MicrogInstaller>() - else -> throw IllegalArgumentException("$appName is not a valid app") - } + val viewModel: InstallViewModel = getViewModel() - //FIXME this is absolutely bad, must move to WorkManager - LaunchedEffect(true) { - downloader.download(appVersions) { status -> - when (status) { - is DownloadStatus.File -> logs.add(Log.Info("Downloading ${status.fileName}")) - is DownloadStatus.Error -> logs.add(Log.Error( - displayText = status.displayError, - stacktrace = status.stacktrace - )) - is DownloadStatus.Progress -> progress = status.progress - is DownloadStatus.StartInstall -> { - installing = true - installer.install { - viewModel.fetch() - } - } - } - } - } + viewModel.startAppProcess(appName, appVersions) Scaffold( - topBar = { - if (installing) { - ManagerProgressIndicator() - } else { - ManagerProgressIndicator(progress) - } - }, floatingActionButton = { - FloatingActionButton(onClick = { /*TODO*/ }) { - } } ) { paddingValues -> ManagerLazyColumn( - modifier = Modifier.padding(paddingValues) + modifier = Modifier + .fillMaxWidth() + .padding(paddingValues), + contentPadding = PaddingValues(0.dp), ) { - items(logs) { log -> + stickyHeader { + when (val status = viewModel.status) { + is InstallViewModel.Status.Progress -> { + ManagerProgressIndicator(status.progress) + } + is InstallViewModel.Status.Installing -> { + ManagerProgressIndicator() + } + else -> {} + } + } + + item { + Spacer(Modifier.height(DefaultContentPaddingVertical)) + } + + items(viewModel.logs) { log -> when (log) { - is Log.Success -> { + is InstallViewModel.Log.Success -> { ManagerText( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = DefaultContentPaddingHorizontal), text = log.successText, textStyle = TextStyle( fontWeight = FontWeight.Bold, fontSize = 14.sp, - color = Color.Green + color = Color.Blue ), ) } - is Log.Info -> { + is InstallViewModel.Log.Info -> { ManagerText( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = DefaultContentPaddingHorizontal), text = log.infoText, textStyle = TextStyle( fontWeight = FontWeight.SemiBold, fontSize = 14.sp, - color = Color.Green + color = Color.Black ), ) } - is Log.Error -> { + is InstallViewModel.Log.Error -> { var visible by remember { mutableStateOf(false) } - val iconRotation by animateFloatAsState(if (visible) 0f else 90f) - Row( - modifier = Modifier.managerClickable { - visible = !visible - }, - horizontalArrangement = Arrangement.spacedBy(8.dp) + val iconRotation by animateFloatAsState(if (visible) -90f else 0f) + Column( + modifier = Modifier + .fillMaxWidth() + .managerClickable { + visible = !visible + } + .padding(horizontal = DefaultContentPaddingHorizontal), ) { - Icon( - modifier = Modifier.rotate(iconRotation), - imageVector = Icons.Rounded.ArrowDropDown, - contentDescription = "expand", - ) - Column( - verticalArrangement = Arrangement.spacedBy(4.dp) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically ) { ManagerText( text = buildAnnotatedString { withStyle(SpanStyle(color = MaterialTheme.colors.error)) { append(log.displayText) - append(": ") - } - withStyle(SpanStyle(color = MaterialTheme.colors.error.copy(alpha = 0.7f))) { - append(log.stacktrace) } }, textStyle = TextStyle( fontWeight = FontWeight.Bold, fontSize = 14.sp, - color = Color.Green ), ) - AnimatedVisibility(visible) { - ManagerText( - text = log.stacktrace, - textStyle = TextStyle( - fontWeight = FontWeight.Bold, - fontSize = 14.sp, - color = Color.Green - ), - ) - } + Icon( + modifier = Modifier.rotate(iconRotation), + imageVector = Icons.Rounded.ArrowDropDown, + contentDescription = "expand", + tint = MaterialTheme.colors.error + ) + } + AnimatedVisibility(visible) { + ManagerText( + text = log.stacktrace, + textStyle = TextStyle( + fontWeight = FontWeight.Bold, + fontSize = 14.sp, + color = MaterialTheme.colors.error.copy(alpha = 0.7f) + ), + ) } } } diff --git a/app/src/main/java/com/vanced/manager/ui/util/Screen.kt b/app/src/main/java/com/vanced/manager/ui/util/Screen.kt index 573fe61bbe..216b3effc0 100644 --- a/app/src/main/java/com/vanced/manager/ui/util/Screen.kt +++ b/app/src/main/java/com/vanced/manager/ui/util/Screen.kt @@ -3,37 +3,48 @@ package com.vanced.manager.ui.util import androidx.annotation.StringRes import androidx.compose.runtime.Composable import com.vanced.manager.R +import com.vanced.manager.domain.model.InstallationOption import com.vanced.manager.ui.screens.AboutLayout import com.vanced.manager.ui.screens.HomeLayout import com.vanced.manager.ui.screens.LogLayout import com.vanced.manager.ui.screens.SettingsLayout -enum class Screen( +sealed class Screen( val route: String, @StringRes val displayName: Int, ) { - Home( + object Home : Screen( route = "home", displayName = R.string.app_name - ), - Settings( + ) + + object Settings: Screen( route = "settings", displayName = R.string.toolbar_settings, - ), - About( + ) + + object About: Screen( route = "about", displayName = R.string.toolbar_about, - ), - Logs( + ) + object Logs : Screen( route = "logs", displayName = R.string.toolbar_logs, - ), - InstallPreferences( + ) + data class InstallPreferences( + val appName: String, + val appVersions: List<String>?, + val appInstallationOptions: List<InstallationOption> + ) : Screen( route = "installpreferences", displayName = R.string.toolbar_installation_preferences - ), - Install( + ) + + data class Install( + val appName: String, + val appVersions: List<String>? + ) : Screen( route = "install", displayName = R.string.toolbar_install - ), + ) } diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt new file mode 100644 index 0000000000..fa08a6b72f --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt @@ -0,0 +1,131 @@ +package com.vanced.manager.ui.viewmodel + +import android.content.pm.PackageInstaller +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.vanced.manager.core.downloader.impl.MicrogDownloader +import com.vanced.manager.core.downloader.impl.MusicDownloader +import com.vanced.manager.core.downloader.impl.VancedDownloader +import com.vanced.manager.core.downloader.util.DownloadStatus +import com.vanced.manager.core.installer.impl.MicrogInstaller +import com.vanced.manager.core.installer.impl.MusicInstaller +import com.vanced.manager.core.installer.impl.VancedInstaller +import com.vanced.manager.network.util.MICROG_NAME +import com.vanced.manager.network.util.MUSIC_NAME +import com.vanced.manager.network.util.VANCED_NAME +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch + +class InstallViewModel( + private val vancedDownloader: VancedDownloader, + private val musicDownloader: MusicDownloader, + private val microgDownloader: MicrogDownloader, + + private val vancedInstaller: VancedInstaller, + private val musicInstaller: MusicInstaller, + private val microgInstaller: MicrogInstaller, +) : ViewModel() { + + sealed class Log { + data class Info(val infoText: String) : Log() + data class Success(val successText: String) : Log() + data class Error( + val displayText: String, + val stacktrace: String, + ) : Log() + } + + sealed class Status { + object Idle : Status() + object Installing : Status() + object Installed : Status() + object Failure : Status() + data class Progress(val progress: Float) : Status() + } + + val logs = mutableStateListOf<Log>() + + var status by mutableStateOf<Status>(Status.Idle) + private set + + //TODO Move to WorkManager + fun startAppProcess( + appName: String, + appVersions: List<String>? + ) { + viewModelScope.launch(Dispatchers.IO) { + downloadApp(appName, appVersions) + } + } + + fun postInstallStatus(pmStatus: Int, extra: String) { + if (pmStatus == PackageInstaller.STATUS_SUCCESS) { + status = Status.Installed + logs.add(Log.Success("Successfully installed")) + } else { + status = Status.Failure + logs.add(Log.Error("Failed to install app", extra)) + } + } + + private suspend fun downloadApp( + appName: String, + appVersions: List<String>?, + ) { + val downloader = getDownloader(appName) + + downloader.download(appVersions) { downloadStatus -> + when (downloadStatus) { + is DownloadStatus.File -> logs.add(Log.Info("Downloading ${downloadStatus.fileName}")) + is DownloadStatus.Error -> logs.add(Log.Error( + displayText = downloadStatus.displayError, + stacktrace = downloadStatus.stacktrace + )) + is DownloadStatus.Progress -> status = Status.Progress(downloadStatus.progress / 100) + is DownloadStatus.StartInstall -> { + logs.add(Log.Success("Successfully downloaded $appName")) + installApp(appName, appVersions) + } + } + } + } + + private fun installApp( + appName: String, + appVersions: List<String>?, + ) { + val installer = getInstaller(appName) + + status = Status.Installing + + installer.install(appVersions) + } + + private fun getDownloader( + appName: String + ) = when (appName) { + VANCED_NAME -> vancedDownloader + MUSIC_NAME -> musicDownloader + MICROG_NAME -> microgDownloader + else -> throw IllegalArgumentException("$appName is not a valid app") + } + + private fun getInstaller( + appName: String + ) = when (appName) { + VANCED_NAME -> vancedInstaller + MUSIC_NAME -> musicInstaller + MICROG_NAME -> microgInstaller + else -> throw IllegalArgumentException("$appName is not a valid app") + } + + private fun clear() { + logs.clear() + status = Status.Idle + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt index 992186fd87..640b683db3 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt @@ -3,6 +3,9 @@ package com.vanced.manager.ui.viewmodel import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import androidx.lifecycle.viewmodel.compose.viewModel +import com.vanced.manager.core.downloader.base.AppDownloader +import com.vanced.manager.core.downloader.util.DownloadStatus import com.vanced.manager.domain.model.App import com.vanced.manager.core.preferences.holder.managerVariantPref import com.vanced.manager.core.preferences.holder.musicEnabled From 760c9639e2c087675b4a2c22d856161e69ffbf18 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Wed, 3 Nov 2021 11:16:58 +0400 Subject: [PATCH 066/118] add Qodana linter --- .github/workflows/debug.yml | 1 + .github/workflows/lint.yml | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 .github/workflows/lint.yml diff --git a/.github/workflows/debug.yml b/.github/workflows/debug.yml index 901ccf42a9..88f9e20164 100644 --- a/.github/workflows/debug.yml +++ b/.github/workflows/debug.yml @@ -17,6 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 + - name: set up JDK 1.8 uses: actions/setup-java@v1 with: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000000..3ed45e68b8 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,26 @@ +name: Code Linter + +on: + push: + branches: + - dev + +jobs: + qodana: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - uses: actions/cache@v2 + with: + path: ~/work/_temp/_github_home/cache + key: ${{ runner.os }}-qodana-${{ github.ref }} + restore-keys: | + ${{ runner.os }}-qodana-${{ github.ref }} + ${{ runner.os }}-qodana- + - uses: docker://jetbrains/qodana-jvm-android + with: + args: --cache-dir=/github/home/cache --results-dir=/github/workspace/qodana --save-report --report-dir=/github/workspace/qodana/report + - uses: actions/upload-artifact@v2 + with: + path: qodana \ No newline at end of file From eb4751f9533d46389b79354b5f85cde801473eef Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 7 Nov 2021 19:35:03 +0400 Subject: [PATCH 067/118] implement Material You --- app/build.gradle.kts | 2 +- .../com/vanced/manager/ui/MainActivity.kt | 167 ++++------ .../ui/component/button/ManagerIconButton.kt | 4 +- .../component/button/ManagerThemedButton.kt | 12 +- .../manager/ui/component/card/ManagerCard.kt | 36 ++- .../ui/component/card/ManagerItemCard.kt | 65 ++-- .../ui/component/card/ManagerLinkCard.kt | 2 +- .../ui/component/card/ManagerThemedCard.kt | 21 +- .../ui/component/card/ManagerTonalCard.kt | 37 +++ .../ui/component/checkbox/ManagerCheckbox.kt | 20 +- .../component/color/ColorContentProvider.kt | 2 +- .../ui/component/color/ManagerColors.kt | 6 +- .../ui/component/dialog/ManagerDialog.kt | 53 ++-- .../ui/component/layout/ManagerLazyColumn.kt | 6 +- .../ui/component/layout/ManagerScaffold.kt | 32 ++ .../ui/component/layout/ManagerScrim.kt | 4 +- .../ui/component/layout/ManagerSurface.kt | 2 +- .../component/layout/ManagerSwipeRefresh.kt | 10 +- .../ui/component/layout/ScrollableItemRow.kt | 3 +- .../ui/component/menu/ManagerDropdownMenu.kt | 103 +++++++ .../component/menu/ManagerDropdownMenuItem.kt | 8 +- .../ui/component/modifier/ManagerClickable.kt | 6 +- .../preference/CheckboxDialogPreference.kt | 14 +- .../component/preference/DialogPreference.kt | 15 +- .../ui/component/preference/Preference.kt | 12 +- .../preference/RadiobuttonDialogPreference.kt | 18 +- .../ManagerProgressIndicator.kt | 4 +- .../radiobutton/ManagerRadiobutton.kt | 11 +- .../ui/component/text/AppVersionText.kt | 4 +- .../ui/component/text/CategoryTitleText.kt | 6 +- .../manager/ui/component/text/ManagerText.kt | 4 +- .../ui/component/text/ToolbarTitleText.kt | 6 +- .../component/topappbar/ManagerTopAppBar.kt | 30 ++ .../vanced/manager/ui/screens/AboutLayout.kt | 285 ++++++++++-------- .../vanced/manager/ui/screens/HomeLayout.kt | 226 ++++++++------ .../ui/screens/InstallPreferencesScreen.kt | 267 ++++++++++------ .../manager/ui/screens/InstallScreen.kt | 59 ++-- .../vanced/manager/ui/screens/LogLayout.kt | 41 --- .../manager/ui/screens/SettingsLayout.kt | 68 +++-- .../java/com/vanced/manager/ui/theme/Color.kt | 57 +++- .../java/com/vanced/manager/ui/theme/Shape.kt | 10 +- .../java/com/vanced/manager/ui/theme/Theme.kt | 113 +++++-- .../java/com/vanced/manager/ui/theme/Type.kt | 123 ++++++-- .../java/com/vanced/manager/ui/util/Screen.kt | 5 - .../manager/ui/viewmodel/MainViewModel.kt | 7 +- .../vanced/manager/ui/widget/app/AppCard.kt | 63 ++-- .../ui/widget/app/AppCardPlaceholder.kt | 31 +- .../manager/ui/widget/app/BaseAppCard.kt | 93 +++--- .../checkbox/ManagerAnimatedCheckbox.kt | 4 +- .../ui/widget/layout/CategoryLayout.kt | 72 ++++- .../widget/layout/SettingsCategoryLayout.kt | 2 - .../manager/ui/widget/list/CheckboxItem.kt | 2 +- .../manager/ui/widget/list/RadiobuttonItem.kt | 3 +- .../radiobutton/ManagerAnimatedRadiobutton.kt | 4 +- .../screens/settings/AccentColorItem.kt | 50 +-- 55 files changed, 1447 insertions(+), 863 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/ui/component/card/ManagerTonalCard.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScaffold.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenu.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/component/topappbar/ManagerTopAppBar.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/screens/LogLayout.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f5328a761e..36c1d36d13 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -90,7 +90,7 @@ dependencies { implementation("androidx.compose.material:material-icons-core:$composeVersion") implementation("androidx.compose.material:material-icons-extended:$composeVersion") implementation("androidx.compose.material:material:$composeVersion") - implementation("androidx.compose.material:material:$composeVersion") + implementation("androidx.compose.material3:material3:1.0.0-alpha01") implementation("androidx.compose.runtime:runtime-livedata:$composeVersion") implementation("androidx.compose.ui:ui-tooling:$composeVersion") implementation("androidx.compose.ui:ui-util:$composeVersion") diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index 098e37e072..8ff9716ce5 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -7,27 +7,17 @@ import android.content.IntentFilter import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.foundation.background -import androidx.compose.material.* -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.ArrowBackIos -import androidx.compose.material.icons.filled.MoreVert -import androidx.compose.runtime.* -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp +import androidx.compose.animation.* +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.SideEffect import com.github.zsoltk.compose.backpress.BackPressHandler import com.github.zsoltk.compose.backpress.LocalBackPressHandler import com.github.zsoltk.compose.router.Router import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.vanced.manager.core.installer.service.AppInstallService -import com.vanced.manager.ui.component.color.managerAnimatedColor import com.vanced.manager.ui.component.color.managerSurfaceColor -import com.vanced.manager.ui.component.color.managerTextColor -import com.vanced.manager.ui.component.menu.ManagerDropdownMenuItem -import com.vanced.manager.ui.component.text.ToolbarTitleText -import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.screens.* import com.vanced.manager.ui.theme.ManagerTheme import com.vanced.manager.ui.theme.isDark @@ -53,14 +43,15 @@ class MainActivity : ComponentActivity() { } } - @OptIn(ExperimentalAnimationApi::class) + @OptIn( + ExperimentalAnimationApi::class, + ExperimentalMaterial3Api::class, + ExperimentalFoundationApi::class + ) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { ManagerTheme { - var isMenuExpanded by remember { mutableStateOf(false) } - var currentScreen by remember { mutableStateOf<Screen>(Screen.Home) } - val surfaceColor = managerSurfaceColor() val isDark = isDark() @@ -78,98 +69,62 @@ class MainActivity : ComponentActivity() { LocalBackPressHandler provides backPressHandler ) { Router<Screen>("VancedManager", Screen.Home) { backStack -> - val screen = backStack.last() - currentScreen = screen - - Scaffold( - topBar = { - TopAppBar( - title = { - ToolbarTitleText( - text = managerString( - stringId = currentScreen.displayName - ) - ) + when (val screen = backStack.last()) { + is Screen.Home -> { + HomeLayout( + onToolbarScreenSelected = { + backStack.push(it) }, - backgroundColor = managerAnimatedColor(color = MaterialTheme.colors.surface), - actions = { - if (currentScreen is Screen.Home) { - IconButton( - onClick = { isMenuExpanded = true } - ) { - Icon( - imageVector = Icons.Default.MoreVert, - contentDescription = null, - tint = managerTextColor() + onAppInstallPress = { appName, appVersions, installationOptions -> + if (installationOptions != null) { + backStack.push( + Screen.InstallPreferences( + appName, + appVersions, + installationOptions ) - } - - DropdownMenu( - expanded = isMenuExpanded, - onDismissRequest = { - isMenuExpanded = false - }, - modifier = Modifier.background(MaterialTheme.colors.surface), - ) { - ManagerDropdownMenuItem( - title = stringResource(id = Screen.Settings.displayName) - ) { - isMenuExpanded = false - backStack.push(Screen.Settings) - } - } + ) + } else { + backStack.push(Screen.Install(appName, appVersions)) } + } + ) + } + is Screen.Settings -> { + SettingsLayout( + onToolbarBackButtonClick = { + backStack.pop() + } + ) + } + is Screen.About -> { + AboutLayout( + onToolbarBackButtonClick = { + backStack.pop() + } + ) + } + is Screen.Logs -> { + + } + is Screen.InstallPreferences -> { + InstallPreferencesScreen( + installationOptions = screen.appInstallationOptions, + onToolbarBackButtonClick = { + backStack.pop() }, - navigationIcon = if (currentScreen !is Screen.Home) { - { - IconButton(onClick = { - backStack.pop() - }) { - Icon( - imageVector = Icons.Default.ArrowBackIos, - contentDescription = null, - tint = managerTextColor() - ) - } - } - } else null, - elevation = 0.dp + onDoneClick = { + backStack.push( + Screen.Install( + screen.appName, + screen.appVersions + ) + ) + } ) - }, - backgroundColor = surfaceColor - ) { - when (screen) { - is Screen.Home -> { - HomeLayout( - onAppInstallPress = { appName, appVersions, installationOptions -> - if (installationOptions != null) { - backStack.push(Screen.InstallPreferences(appName, appVersions, installationOptions)) - } else { - backStack.push(Screen.Install(appName, appVersions)) - } - } - ) - } - is Screen.Settings -> { - SettingsLayout() - } - is Screen.About -> { - AboutLayout() - } - is Screen.Logs -> { - - } - is Screen.InstallPreferences -> { - InstallPreferencesScreen( - installationOptions = screen.appInstallationOptions, - onDoneClick = { - backStack.push(Screen.Install(screen.appName, screen.appVersions)) - } - ) - } - is Screen.Install -> { - InstallScreen(screen.appName, screen.appVersions) - } + } + is Screen.Install -> { + InstallScreen(screen.appName, screen.appVersions) } } } diff --git a/app/src/main/java/com/vanced/manager/ui/component/button/ManagerIconButton.kt b/app/src/main/java/com/vanced/manager/ui/component/button/ManagerIconButton.kt index 27a808e352..1ade716254 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/button/ManagerIconButton.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/button/ManagerIconButton.kt @@ -4,8 +4,8 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.size -import androidx.compose.material.Icon import androidx.compose.material.ripple.rememberRipple +import androidx.compose.material3.Icon import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Alignment @@ -15,7 +15,7 @@ import androidx.compose.ui.semantics.Role import androidx.compose.ui.unit.dp @Composable -fun IconButton( +fun ManagerIconButton( icon: ImageVector, contentDescription: String, onClick: () -> Unit diff --git a/app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedButton.kt b/app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedButton.kt index 8edc51abc1..cd47f06628 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedButton.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedButton.kt @@ -2,15 +2,15 @@ package com.vanced.manager.ui.component.button import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.material.Button -import androidx.compose.material.ButtonDefaults -import androidx.compose.material.MaterialTheme +import androidx.compose.material3.Button +import androidx.compose.material3.ButtonDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.luminance import androidx.compose.ui.unit.dp import com.vanced.manager.ui.component.color.managerAccentColor +import com.vanced.manager.ui.theme.MediumShape @Composable fun ManagerThemedButton( @@ -22,16 +22,16 @@ fun ManagerThemedButton( Button( modifier = modifier.fillMaxWidth(), onClick = onClick, - shape = MaterialTheme.shapes.medium, + shape = MediumShape, colors = ButtonDefaults.buttonColors( - backgroundColor = backgroundColor, + containerColor = backgroundColor, contentColor = if (backgroundColor.luminance() > 0.7) Color.Black else Color.White ), - elevation = ButtonDefaults.elevation(0.dp, 0.dp, 0.dp) + elevation = ButtonDefaults.elevatedButtonElevation(0.dp, 0.dp, 0.dp, 0.dp) ) { content() } diff --git a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerCard.kt b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerCard.kt index 49c9a88ae2..dd7dab42ee 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerCard.kt @@ -1,26 +1,31 @@ package com.vanced.manager.ui.component.card -import androidx.compose.material.Card import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.MaterialTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp +import com.vanced.manager.ui.theme.MediumShape @Composable fun ManagerCard( modifier: Modifier = Modifier, - shape: Shape = MaterialTheme.shapes.medium, - backgroundColor: Color = MaterialTheme.colors.surface, + shape: Shape = MediumShape, + backgroundColor: Color = MaterialTheme.colorScheme.surface, + tonalElevation: Dp = 0.dp, + shadowElevation: Dp = 0.dp, content: @Composable () -> Unit, ) { - Card( + Surface( modifier = modifier, shape = shape, - backgroundColor = backgroundColor, - elevation = 0.dp, + color = backgroundColor, + shadowElevation = shadowElevation, + tonalElevation = tonalElevation, content = content ) } @@ -29,17 +34,20 @@ fun ManagerCard( @Composable fun ManagerCard( modifier: Modifier = Modifier, - shape: Shape = MaterialTheme.shapes.medium, - backgroundColor: Color = MaterialTheme.colors.surface, + shape: Shape = MediumShape, + backgroundColor: Color = MaterialTheme.colorScheme.surface, + tonalElevation: Dp = 0.dp, + shadowElevation: Dp = 0.dp, onClick: () -> Unit, content: @Composable () -> Unit, ) { - Card( + Surface( modifier = modifier, shape = shape, - backgroundColor = backgroundColor, - elevation = 0.dp, - content = content, - onClick = onClick + color = backgroundColor, + shadowElevation = shadowElevation, + tonalElevation = tonalElevation, + onClick = onClick, + content = content ) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerItemCard.kt b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerItemCard.kt index 245b7311c1..2869da1c7e 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerItemCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerItemCard.kt @@ -1,25 +1,22 @@ package com.vanced.manager.ui.component.card import androidx.annotation.DrawableRes -import androidx.compose.foundation.Canvas import androidx.compose.foundation.layout.* -import androidx.compose.material.Icon -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.geometry.Offset import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import com.vanced.manager.ui.component.color.ThemedItemContentColorProvider -import com.vanced.manager.ui.component.color.managerAccentColor +import com.github.zsoltk.compose.backpress.LocalBackPressHandler +import com.vanced.manager.ui.component.text.ManagerText +import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal +import com.vanced.manager.ui.util.DefaultContentPaddingVertical private val cardModifier = Modifier.sizeIn( - minHeight = 95.dp, - minWidth = 95.dp + minHeight = 100.dp, + minWidth = 100.dp ) @Composable @@ -27,7 +24,8 @@ fun ManagerItemCard( title: String, @DrawableRes icon: Int? = null ) { - ManagerThemedCard( + LocalBackPressHandler.current.handle() + ManagerCard( modifier = cardModifier, ) { ManagerItemCardContent(title, icon) @@ -35,12 +33,12 @@ fun ManagerItemCard( } @Composable -fun ManagerClickableItemCard( +fun ManagerItemCard( title: String, @DrawableRes icon: Int? = null, onClick: () -> Unit ) { - ManagerClickableThemedCard( + ManagerTonalCard( modifier = cardModifier, onClick = onClick ) { @@ -53,34 +51,25 @@ private fun ManagerItemCardContent( title: String, @DrawableRes icon: Int? = null, ) { - val accentColor = managerAccentColor() - val circleOffset = 32.dp.value - Canvas(modifier = Modifier.requiredSize(72.dp)) { - drawCircle( - color = accentColor, - center = Offset(circleOffset, circleOffset) - ) - } - Box( - modifier = Modifier.padding(12.dp) + Column( + modifier = Modifier.padding( + horizontal = DefaultContentPaddingHorizontal, + vertical = DefaultContentPaddingVertical + ), + horizontalAlignment = Alignment.Start, + verticalArrangement = Arrangement.SpaceBetween ) { if (icon != null) { - ThemedItemContentColorProvider { - Icon( - modifier = Modifier - .size(28.dp) - .align(Alignment.TopStart), - painter = painterResource(id = icon), - contentDescription = title - ) - } + Icon( + modifier = Modifier + .size(36.dp), + painter = painterResource(id = icon), + contentDescription = title, + ) } - Text( - modifier = Modifier.align(Alignment.BottomStart), + ManagerText( text = title, - fontSize = 12.sp, - fontWeight = FontWeight.Medium, - color = MaterialTheme.colors.onSurface + textStyle = MaterialTheme.typography.labelLarge ) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerLinkCard.kt b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerLinkCard.kt index 3acd2e9be7..9a836928c4 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerLinkCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerLinkCard.kt @@ -20,7 +20,7 @@ fun ManagerLinkCard( val uri = remember { Uri.parse(link) } val intent = remember { Intent(Intent.ACTION_VIEW, uri) } val useCustomTabs by useCustomTabsPref - ManagerClickableItemCard( + ManagerItemCard( title = title, icon = icon ) { diff --git a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerThemedCard.kt b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerThemedCard.kt index c02e1c17f5..a1d9457ee8 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerThemedCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerThemedCard.kt @@ -1,38 +1,37 @@ package com.vanced.manager.ui.component.card -import androidx.compose.material.MaterialTheme +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Shape -import com.vanced.manager.ui.component.color.managerThemedCardColor +import com.vanced.manager.ui.theme.MediumShape @Composable -fun ManagerThemedCard( +fun ManagerContainerCard( modifier: Modifier = Modifier, - shape: Shape = MaterialTheme.shapes.medium, + shape: Shape = MediumShape, content: @Composable () -> Unit, ) { ManagerCard( modifier = modifier, shape = shape, - backgroundColor = managerThemedCardColor(), + backgroundColor = MaterialTheme.colorScheme.primaryContainer, content = content ) } @Composable -fun ManagerClickableThemedCard( +fun ManagerContainerCard( modifier: Modifier = Modifier, - shape: Shape = MaterialTheme.shapes.medium, + shape: Shape = MediumShape, onClick: () -> Unit, content: @Composable () -> Unit, ) { ManagerCard( modifier = modifier, shape = shape, - backgroundColor = managerThemedCardColor(), + backgroundColor = MaterialTheme.colorScheme.primaryContainer, onClick = onClick, - ) { - content() - } + content = content, + ) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerTonalCard.kt b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerTonalCard.kt new file mode 100644 index 0000000000..7ee452862b --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerTonalCard.kt @@ -0,0 +1,37 @@ +package com.vanced.manager.ui.component.card + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.unit.dp +import com.vanced.manager.ui.theme.MediumShape + +@Composable +fun ManagerTonalCard( + modifier: Modifier = Modifier, + shape: Shape = MediumShape, + content: @Composable () -> Unit, +) { + ManagerCard( + modifier = modifier, + shape = shape, + tonalElevation = 4.dp, + content = content + ) +} + +@Composable +fun ManagerTonalCard( + modifier: Modifier = Modifier, + shape: Shape = MediumShape, + onClick: () -> Unit, + content: @Composable () -> Unit, +) { + ManagerCard( + modifier = modifier, + shape = shape, + tonalElevation = 4.dp, + onClick = onClick, + content = content + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt b/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt index 65d2de6564..0f077a530f 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt @@ -3,33 +3,37 @@ package com.vanced.manager.ui.component.checkbox import android.annotation.SuppressLint import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.requiredSizeIn -import androidx.compose.material.Icon -import androidx.compose.material.MaterialTheme import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.Close import androidx.compose.material.icons.rounded.Done +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.contentColorFor import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Shape import com.vanced.manager.ui.component.card.ManagerCard -import com.vanced.manager.ui.component.color.contentColorForColor -import com.vanced.manager.ui.component.color.managerAccentColor import com.vanced.manager.ui.component.color.managerAnimatedColor -import com.vanced.manager.ui.component.color.managerThemedCardColor +import com.vanced.manager.ui.theme.MediumShape @SuppressLint("UnusedTransitionTargetStateParameter") @Composable fun ManagerCheckbox( modifier: Modifier, isChecked: Boolean, - shape: Shape = MaterialTheme.shapes.medium, + shape: Shape = MediumShape, onCheckedChange: (isChecked: Boolean) -> Unit ) { val cardColor = - managerAnimatedColor(if (isChecked) managerAccentColor() else managerThemedCardColor()) + managerAnimatedColor(if (isChecked) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.primaryContainer) val iconTint = - managerAnimatedColor(if (isChecked) contentColorForColor(cardColor) else managerAccentColor()) + managerAnimatedColor( + if (isChecked) + contentColorFor(MaterialTheme.colorScheme.primary) + else + contentColorFor(MaterialTheme.colorScheme.primaryContainer) + ) ManagerCard( modifier = modifier, diff --git a/app/src/main/java/com/vanced/manager/ui/component/color/ColorContentProvider.kt b/app/src/main/java/com/vanced/manager/ui/component/color/ColorContentProvider.kt index 00511baf30..6989d00033 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/color/ColorContentProvider.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/color/ColorContentProvider.kt @@ -1,6 +1,6 @@ package com.vanced.manager.ui.component.color -import androidx.compose.material.LocalContentColor +import androidx.compose.material3.LocalContentColor import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider diff --git a/app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt b/app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt index 081f83e620..9bb3021e19 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt @@ -2,7 +2,7 @@ package com.vanced.manager.ui.component.color import androidx.compose.animation.animateColorAsState import androidx.compose.animation.core.tween -import androidx.compose.material.MaterialTheme +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.luminance @@ -25,10 +25,10 @@ fun managerAccentColor(): Color { fun managerThemedCardColor() = managerAccentColor().copy(alpha = 0.27f) @Composable -fun managerTextColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.onSurface) +fun managerTextColor(): Color = managerAnimatedColor(color = MaterialTheme.colorScheme.onSurface) @Composable -fun managerSurfaceColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.surface) +fun managerSurfaceColor(): Color = managerAnimatedColor(color = MaterialTheme.colorScheme.surface) @Composable fun managerAnimatedColor( diff --git a/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt b/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt index 1dbd8b4ba4..0b4f1a5028 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt @@ -1,13 +1,16 @@ package com.vanced.manager.ui.component.dialog import androidx.compose.foundation.layout.* -import androidx.compose.material.MaterialTheme +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import com.vanced.manager.ui.component.card.ManagerCard import com.vanced.manager.ui.component.text.ManagerText +import com.vanced.manager.ui.theme.LargeShape import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal import com.vanced.manager.ui.util.DefaultContentPaddingVertical @@ -15,45 +18,25 @@ import com.vanced.manager.ui.util.DefaultContentPaddingVertical fun ManagerDialog( title: String, onDismissRequest: () -> Unit, - buttons: @Composable ColumnScope.() -> Unit, - content: @Composable ColumnScope.() -> Unit, + confirmButton: @Composable () -> Unit, + modifier: Modifier = Modifier, + dismissButton: @Composable (() -> Unit)? = null, + icon: @Composable (() -> Unit)? = null, + content: @Composable () -> Unit, ) { - ManagerDialog( + AlertDialog( + modifier = modifier, title = { ManagerText( - modifier = Modifier - .fillMaxWidth(), - textStyle = MaterialTheme.typography.h2, - textAlign = TextAlign.Center, text = title ) }, + text = content, onDismissRequest = onDismissRequest, - buttons = buttons, - content = content + confirmButton = confirmButton, + dismissButton = dismissButton, + icon = icon, + shape = LargeShape, + tonalElevation = 2.dp, ) -} - -@Composable -fun ManagerDialog( - title: @Composable ColumnScope.() -> Unit, - onDismissRequest: () -> Unit, - buttons: @Composable ColumnScope.() -> Unit, - content: @Composable ColumnScope.() -> Unit, -) { - Dialog( - onDismissRequest = onDismissRequest, - content = { - ManagerCard { - Column( - modifier = Modifier.padding(DefaultContentPaddingHorizontal), - verticalArrangement = Arrangement.spacedBy(DefaultContentPaddingVertical) - ) { - title() - content() - buttons() - } - } - }, - ) -} +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt index 49fa25d74b..c19a68644b 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt @@ -8,19 +8,15 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal +import com.vanced.manager.ui.util.DefaultContentPaddingVertical @Composable fun ManagerLazyColumn( modifier: Modifier = Modifier, - itemSpacing: Dp = 0.dp, - contentPadding: PaddingValues = PaddingValues(12.dp), content: LazyListScope.() -> Unit ) { LazyColumn( modifier = modifier, - contentPadding = contentPadding, - verticalArrangement = Arrangement.spacedBy(itemSpacing), content = content ) } diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScaffold.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScaffold.kt new file mode 100644 index 0000000000..06f747fb82 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScaffold.kt @@ -0,0 +1,32 @@ +package com.vanced.manager.ui.component.layout + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier + +@ExperimentalMaterial3Api +@Composable +fun ManagerScaffold( + modifier: Modifier = Modifier, + scaffoldState: ScaffoldState = rememberScaffoldState(), + topBar: @Composable () -> Unit = {}, + floatingActionButton: @Composable () -> Unit = {}, + floatingActionButtonPosition: FabPosition = FabPosition.End, + content: @Composable (PaddingValues) -> Unit +) { +// //M3 Scaffold doesn't support tonal elevation for Surface +// val absoluteTonalElevation = LocalAbsoluteTonalElevation.current + 1.dp +// CompositionLocalProvider( +// LocalAbsoluteTonalElevation provides absoluteTonalElevation +// ) { + Scaffold( + modifier = modifier, + scaffoldState = scaffoldState, + topBar = topBar, + floatingActionButton = floatingActionButton, + floatingActionButtonPosition = floatingActionButtonPosition, + content = content + ) +// } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrim.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrim.kt index 3318d3f6ec..256b62387f 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrim.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrim.kt @@ -4,7 +4,7 @@ import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.tween import androidx.compose.foundation.Canvas import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material.MaterialTheme +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.SideEffect import androidx.compose.runtime.getValue @@ -20,7 +20,7 @@ fun ManagerScrim( val systemUiController = rememberSystemUiController() val scrimColor = Color.Black.copy(alpha = 0.5f) - val surfaceColor = MaterialTheme.colors.surface + val surfaceColor = MaterialTheme.colorScheme.surface val isDark = isDark() diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSurface.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSurface.kt index 1823d721d2..f0bae0b15a 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSurface.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSurface.kt @@ -1,7 +1,7 @@ package com.vanced.manager.ui.component.layout import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material.Surface +import androidx.compose.material3.Surface import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import com.vanced.manager.ui.component.color.managerSurfaceColor diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSwipeRefresh.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSwipeRefresh.kt index c1234cc454..311952207f 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSwipeRefresh.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSwipeRefresh.kt @@ -1,18 +1,25 @@ package com.vanced.manager.ui.component.layout +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.dp import com.google.accompanist.swiperefresh.SwipeRefresh import com.google.accompanist.swiperefresh.SwipeRefreshIndicator import com.google.accompanist.swiperefresh.SwipeRefreshState +import com.vanced.manager.ui.component.card.ManagerCard import com.vanced.manager.ui.component.color.managerAccentColor @Composable fun ManagerSwipeRefresh( refreshState: SwipeRefreshState, onRefresh: () -> Unit, + modifier: Modifier = Modifier, content: @Composable () -> Unit ) { SwipeRefresh( + modifier = modifier, state = refreshState, onRefresh = onRefresh, indicator = { state, trigger -> @@ -20,7 +27,8 @@ fun ManagerSwipeRefresh( state = state, refreshTriggerDistance = trigger, scale = true, - contentColor = managerAccentColor() + contentColor = MaterialTheme.colorScheme.primary, + backgroundColor = MaterialTheme.colorScheme.surface ) }, content = content diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ScrollableItemRow.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ScrollableItemRow.kt index 7de9d56291..65dd614961 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ScrollableItemRow.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ScrollableItemRow.kt @@ -12,11 +12,12 @@ import androidx.compose.ui.unit.dp @Composable fun <T> ScrollableItemRow( items: List<T>, + modifier: Modifier = Modifier, content: @Composable (T) -> Unit ) { val state = rememberLazyListState() LazyRow( - modifier = Modifier.fillMaxWidth(), + modifier = modifier, horizontalArrangement = Arrangement.spacedBy(8.dp), state = state ) { diff --git a/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenu.kt b/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenu.kt new file mode 100644 index 0000000000..22b12c59f2 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenu.kt @@ -0,0 +1,103 @@ +package com.vanced.manager.ui.component.menu + +import androidx.compose.animation.* +import androidx.compose.animation.core.* +import androidx.compose.foundation.layout.* +import androidx.compose.runtime.* +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.draw.scale +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.unit.* +import androidx.compose.ui.window.Popup +import androidx.compose.ui.window.PopupPositionProvider +import androidx.compose.ui.window.PopupProperties +import com.vanced.manager.ui.component.card.ManagerCard + +private const val TransitionDuration = 200 + +@ExperimentalAnimationApi +@OptIn(ExperimentalComposeUiApi::class) +@Composable +fun ManagerDropdownMenu( + expanded: Boolean, + onDismissRequest: () -> Unit, + content: @Composable ColumnScope.() -> Unit, +) { + val expandedStates = remember { MutableTransitionState(false) } + expandedStates.targetState = expanded + + val transition = updateTransition(expandedStates, "ManagerDropDownMenu") + + val alphaAndScale by transition.animateFloat( + transitionSpec = { tween(durationMillis = TransitionDuration) }, + label = "AlphaAndScale" + ) { + if (it) 1f else 0f + } + + if (expandedStates.currentState || expandedStates.targetState) { + val density = LocalDensity.current + val popupPositionProvider = + ManagerDropdownMenuPopupPositionProvider(density) + + Popup( + popupPositionProvider = popupPositionProvider, + onDismissRequest = onDismissRequest, + properties = PopupProperties(focusable = true) + ) { + ManagerCard( + modifier = Modifier + .width(IntrinsicSize.Max) + .alpha(alphaAndScale) + .scale(alphaAndScale), + tonalElevation = 2.dp, + shadowElevation = 2.dp + ) { + Column(content = content) + } + } + } +} + +//Kanged from Menu.kt +data class ManagerDropdownMenuPopupPositionProvider( + val density: Density +) : PopupPositionProvider { + + override fun calculatePosition( + anchorBounds: IntRect, + windowSize: IntSize, + layoutDirection: LayoutDirection, + popupContentSize: IntSize + ): IntOffset { + val verticalMargin = with(density) { 48.dp.roundToPx() } + + //Compute horizontal position. + val toRight = anchorBounds.left + val toLeft = anchorBounds.right - popupContentSize.width + val toDisplayRight = windowSize.width - popupContentSize.width + val toDisplayLeft = 0 + val x = if (layoutDirection == LayoutDirection.Ltr) { + sequenceOf(toRight, toLeft, toDisplayRight) + } else { + sequenceOf(toLeft, toRight, toDisplayLeft) + }.firstOrNull { + it >= 0 && it + popupContentSize.width <= windowSize.width + } ?: toLeft + + // Compute vertical position. + val toBottom = maxOf(anchorBounds.bottom, verticalMargin) + val toTop = anchorBounds.top - popupContentSize.height + val toCenter = anchorBounds.top - popupContentSize.height / 2 + val toDisplayBottom = windowSize.height - popupContentSize.height - verticalMargin + val y = sequenceOf(toBottom, toTop, toCenter, toDisplayBottom).firstOrNull { + it >= verticalMargin && + it + popupContentSize.height <= windowSize.height - verticalMargin + } ?: toTop + + return IntOffset(x, y) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenuItem.kt b/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenuItem.kt index 632b9edadd..c76126dbd0 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenuItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenuItem.kt @@ -1,9 +1,12 @@ package com.vanced.manager.ui.component.menu import androidx.compose.material.DropdownMenuItem -import androidx.compose.material.MaterialTheme +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import com.vanced.manager.ui.component.text.ManagerText +import com.vanced.manager.ui.theme.SmallShape @Composable fun ManagerDropdownMenuItem( @@ -12,10 +15,11 @@ fun ManagerDropdownMenuItem( ) { DropdownMenuItem( onClick = onClick, + modifier = Modifier.clip(SmallShape), ) { ManagerText( text = title, - textStyle = MaterialTheme.typography.h6 + textStyle = MaterialTheme.typography.labelLarge ) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/modifier/ManagerClickable.kt b/app/src/main/java/com/vanced/manager/ui/component/modifier/ManagerClickable.kt index f834c53473..acb26b1f97 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/modifier/ManagerClickable.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/modifier/ManagerClickable.kt @@ -2,12 +2,12 @@ package com.vanced.manager.ui.component.modifier import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.material.MaterialTheme import androidx.compose.material.ripple.rememberRipple import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.composed import androidx.compose.ui.draw.clip +import com.vanced.manager.ui.theme.MediumShape fun Modifier.managerClickable( onClick: () -> Unit @@ -15,9 +15,7 @@ fun Modifier.managerClickable( val ripple = rememberRipple() val interactionSource = remember { MutableInteractionSource() } - return@composed then( - clip(MaterialTheme.shapes.medium) - ).then( + then(clip(MediumShape)).then( clickable( interactionSource = interactionSource, onClick = onClick, diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt index c58dbd1ddc..dec5ef49d3 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt @@ -4,6 +4,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items +import androidx.compose.material.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope @@ -15,6 +16,7 @@ import com.vanced.manager.R import com.vanced.manager.core.preferences.CheckboxPreference import com.vanced.manager.core.preferences.ManagerPreference import com.vanced.manager.ui.component.button.ManagerThemedTextButton +import com.vanced.manager.ui.component.text.ManagerText import com.vanced.manager.ui.widget.list.CheckboxItem import kotlinx.coroutines.launch @@ -37,10 +39,8 @@ fun CheckboxDialogPreference( } }.sortedBy { it.title }.joinToString(separator = ", ") { it.title }, trailing = trailing, - buttons = { isShown -> - ManagerThemedTextButton( - text = stringResource(id = R.string.dialog_button_save), - modifier = Modifier.fillMaxWidth(), + confirmButton = { isShown -> + TextButton( onClick = { coroutineScope.launch { isShown.value = false @@ -48,8 +48,10 @@ fun CheckboxDialogPreference( onSave(selectedButtons) } } - ) - } + ) { + ManagerText(stringResource(id = R.string.dialog_button_save)) + } + }, ) { LazyColumn( modifier = Modifier.heightIn(max = 400.dp) diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/DialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/DialogPreference.kt index 62039323b2..83604dbaf5 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/DialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/DialogPreference.kt @@ -1,6 +1,5 @@ package com.vanced.manager.ui.component.preference -import androidx.compose.foundation.layout.ColumnScope import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf @@ -13,8 +12,9 @@ fun DialogPreference( preferenceDescription: String? = null, onDismissRequest: () -> Unit = {}, trailing: @Composable () -> Unit = {}, - buttons: @Composable ColumnScope.(isShown: MutableState<Boolean>) -> Unit, - content: @Composable ColumnScope.() -> Unit + confirmButton: @Composable (isShown: MutableState<Boolean>) -> Unit, + dismissButton: @Composable ((isShown: MutableState<Boolean>) -> Unit)? = null, + content: @Composable () -> Unit ) { val isShown = remember { mutableStateOf(false) } Preference( @@ -31,7 +31,14 @@ fun DialogPreference( onDismissRequest() isShown.value = false }, - buttons = { buttons(isShown) }, + confirmButton = { + confirmButton(isShown) + }, + dismissButton = { + if (dismissButton != null) { + dismissButton(isShown) + } + }, content = content ) } diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt index bad3c9cd0f..2688da4d1f 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt @@ -1,9 +1,9 @@ package com.vanced.manager.ui.component.preference import androidx.compose.foundation.layout.padding -import androidx.compose.material.LocalContentColor -import androidx.compose.material.LocalTextStyle -import androidx.compose.material.MaterialTheme +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.LocalTextStyle +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier @@ -39,7 +39,7 @@ fun Preference( trailing: @Composable () -> Unit = {}, onClick: () -> Unit ) { - val color = managerAnimatedColor(color = MaterialTheme.colors.onSurface) + val color = managerAnimatedColor(color = MaterialTheme.colorScheme.onSurface) ManagerListItem( modifier = Modifier .managerClickable(onClick = onClick) @@ -47,7 +47,7 @@ fun Preference( title = { CompositionLocalProvider( LocalContentColor provides color, - LocalTextStyle provides MaterialTheme.typography.h6 + LocalTextStyle provides MaterialTheme.typography.titleSmall ) { preferenceTitle() } @@ -56,7 +56,7 @@ fun Preference( { CompositionLocalProvider( LocalContentColor provides color, - LocalTextStyle provides MaterialTheme.typography.subtitle1 + LocalTextStyle provides MaterialTheme.typography.bodySmall ) { preferenceDescription() } diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt index ceffad7799..5e439a2534 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt @@ -3,11 +3,15 @@ package com.vanced.manager.ui.component.preference import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items +import androidx.compose.material3.TextButton import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import com.vanced.manager.R import com.vanced.manager.core.preferences.ManagerPreference import com.vanced.manager.core.preferences.RadioButtonPreference +import com.vanced.manager.ui.component.text.ManagerText +import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.widget.button.ManagerSaveButton import com.vanced.manager.ui.widget.list.RadiobuttonItem import kotlinx.coroutines.launch @@ -27,13 +31,13 @@ fun RadiobuttonDialogPreference( preferenceTitle = preferenceTitle, preferenceDescription = buttons.find { it.key == pref }?.title, trailing = trailing, - buttons = { isShown -> - ManagerSaveButton { - coroutineScope.launch { - isShown.value = false - pref = currentSelection - onSave(currentSelection) - } + confirmButton = { isShown -> + TextButton(onClick = { + isShown.value = false + pref = currentSelection + onSave(currentSelection) + }) { + ManagerText(managerString(stringId = R.string.dialog_button_save)) } }, ) { diff --git a/app/src/main/java/com/vanced/manager/ui/component/progressindicator/ManagerProgressIndicator.kt b/app/src/main/java/com/vanced/manager/ui/component/progressindicator/ManagerProgressIndicator.kt index 74e53e6bf5..8375548432 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/progressindicator/ManagerProgressIndicator.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/progressindicator/ManagerProgressIndicator.kt @@ -4,7 +4,6 @@ import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.material.LinearProgressIndicator -import androidx.compose.material.MaterialTheme import androidx.compose.material.ProgressIndicatorDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -13,11 +12,12 @@ import androidx.compose.ui.composed import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp import com.vanced.manager.ui.component.color.managerAccentColor +import com.vanced.manager.ui.theme.MediumShape private val progressBarModifier = Modifier.composed { then(height(5.dp)) .then(fillMaxWidth()) - .then(clip(MaterialTheme.shapes.medium)) + .then(clip(MediumShape)) } @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/component/radiobutton/ManagerRadiobutton.kt b/app/src/main/java/com/vanced/manager/ui/component/radiobutton/ManagerRadiobutton.kt index 2a7190394b..3c99948cd3 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/radiobutton/ManagerRadiobutton.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/radiobutton/ManagerRadiobutton.kt @@ -1,25 +1,24 @@ package com.vanced.manager.ui.component.radiobutton import android.annotation.SuppressLint -import androidx.compose.material.MaterialTheme +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Shape import com.vanced.manager.ui.component.card.ManagerCard -import com.vanced.manager.ui.component.color.managerAccentColor import com.vanced.manager.ui.component.color.managerAnimatedColor -import com.vanced.manager.ui.component.color.managerThemedCardColor +import com.vanced.manager.ui.theme.MediumShape @SuppressLint("UnusedTransitionTargetStateParameter") @Composable fun ManagerRadiobutton( modifier: Modifier, isSelected: Boolean, - shape: Shape = MaterialTheme.shapes.medium, + shape: Shape = MediumShape, onClick: () -> Unit ) { - val accentColor = managerAccentColor() - val cardColor = managerAnimatedColor(if (isSelected) accentColor else managerThemedCardColor()) + val cardColor = + managerAnimatedColor(if (isSelected) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.primaryContainer) ManagerCard( modifier = modifier, onClick = onClick, diff --git a/app/src/main/java/com/vanced/manager/ui/component/text/AppVersionText.kt b/app/src/main/java/com/vanced/manager/ui/component/text/AppVersionText.kt index ab25f2c41d..3a6b4644da 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/text/AppVersionText.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/text/AppVersionText.kt @@ -1,6 +1,6 @@ package com.vanced.manager.ui.component.text -import androidx.compose.material.MaterialTheme +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -12,6 +12,6 @@ fun AppVersionText( ManagerText( modifier = modifier, text = text, - textStyle = MaterialTheme.typography.body2, + textStyle = MaterialTheme.typography.bodySmall, ) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/text/CategoryTitleText.kt b/app/src/main/java/com/vanced/manager/ui/component/text/CategoryTitleText.kt index 5684a59f12..25832fdbd5 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/text/CategoryTitleText.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/text/CategoryTitleText.kt @@ -1,7 +1,7 @@ package com.vanced.manager.ui.component.text import androidx.compose.foundation.layout.padding -import androidx.compose.material.MaterialTheme +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import com.vanced.manager.ui.component.color.managerAnimatedColor @@ -14,7 +14,7 @@ fun CategoryTitleText( ManagerText( modifier = Modifier.padding(start = DefaultContentPaddingHorizontal), text = text, - textStyle = MaterialTheme.typography.h2, - color = managerAnimatedColor(MaterialTheme.colors.onSurface) + textStyle = MaterialTheme.typography.headlineSmall, + color = managerAnimatedColor(MaterialTheme.colorScheme.onSurface) ) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/text/ManagerText.kt b/app/src/main/java/com/vanced/manager/ui/component/text/ManagerText.kt index 25870bd20f..b0ad8fe93c 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/text/ManagerText.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/text/ManagerText.kt @@ -1,7 +1,7 @@ package com.vanced.manager.ui.component.text -import androidx.compose.material.LocalTextStyle -import androidx.compose.material.Text +import androidx.compose.material3.LocalTextStyle +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color diff --git a/app/src/main/java/com/vanced/manager/ui/component/text/ToolbarTitleText.kt b/app/src/main/java/com/vanced/manager/ui/component/text/ToolbarTitleText.kt index cad4646d81..89fbe78095 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/text/ToolbarTitleText.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/text/ToolbarTitleText.kt @@ -1,6 +1,6 @@ package com.vanced.manager.ui.component.text -import androidx.compose.material.MaterialTheme +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import com.vanced.manager.ui.component.color.managerAnimatedColor @@ -10,7 +10,7 @@ fun ToolbarTitleText( ) { ManagerText( text = text, - textStyle = MaterialTheme.typography.h1, - color = managerAnimatedColor(MaterialTheme.colors.onSurface) + textStyle = MaterialTheme.typography.headlineMedium, + color = managerAnimatedColor(MaterialTheme.colorScheme.onSurface) ) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/topappbar/ManagerTopAppBar.kt b/app/src/main/java/com/vanced/manager/ui/component/topappbar/ManagerTopAppBar.kt new file mode 100644 index 0000000000..7fd2edb038 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/component/topappbar/ManagerTopAppBar.kt @@ -0,0 +1,30 @@ +package com.vanced.manager.ui.component.topappbar + +import androidx.compose.foundation.layout.RowScope +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.SmallTopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.vanced.manager.ui.component.color.managerAnimatedColor +import com.vanced.manager.ui.component.text.ManagerText + +@Composable +fun ManagerTopAppBar( + title: String, + modifier: Modifier = Modifier, + actions: @Composable RowScope.() -> Unit = {}, + navigationIcon: @Composable () -> Unit = {}, +) { + SmallTopAppBar( + modifier = modifier, + title = { + ManagerText( + text = title, + textStyle = MaterialTheme.typography.headlineMedium, + color = managerAnimatedColor(MaterialTheme.colorScheme.onSurface) + ) + }, + actions = actions, + navigationIcon = navigationIcon, + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt index 8ac9440680..b6740a9b68 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt @@ -2,11 +2,13 @@ package com.vanced.manager.ui.screens import androidx.annotation.DrawableRes import androidx.annotation.StringRes -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.material.MaterialTheme +import androidx.compose.foundation.layout.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.ArrowBackIosNew +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -15,96 +17,83 @@ import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp -import androidx.compose.ui.util.fastForEach import com.vanced.manager.R import com.vanced.manager.ui.component.card.ManagerLinkCard -import com.vanced.manager.ui.component.card.ManagerThemedCard -import com.vanced.manager.ui.component.layout.ManagerScrollableColumn +import com.vanced.manager.ui.component.card.ManagerTonalCard +import com.vanced.manager.ui.component.layout.ManagerLazyColumn +import com.vanced.manager.ui.component.layout.ManagerScaffold import com.vanced.manager.ui.component.layout.ScrollableItemRow import com.vanced.manager.ui.component.list.ManagerListItem import com.vanced.manager.ui.component.text.ManagerText +import com.vanced.manager.ui.component.topappbar.ManagerTopAppBar import com.vanced.manager.ui.resources.managerString +import com.vanced.manager.ui.theme.LargeShape +import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal import com.vanced.manager.ui.util.DefaultContentPaddingVertical -import com.vanced.manager.ui.widget.layout.CategoryLayout +import com.vanced.manager.ui.util.Screen +import com.vanced.manager.ui.widget.layout.managerCategory data class Person( val name: String, val contribution: String ) -data class Credit( - @StringRes val nameId: Int, - val persons: List<Person> -) - data class Source( @StringRes val nameId: Int, @DrawableRes val iconId: Int, val link: String ) -private val credits = listOf( - Credit( - nameId = R.string.about_category_credits_vanced_team, - persons = listOf( - Person( - name = "xfileFIN", - contribution = "Mods, Theming, Support" - ), - Person( - name = "Laura", - contribution = "Theming, Support" - ), - Person( - name = "ZaneZam", - contribution = "Publishing, Support" - ), - Person( - name = "KevinX8", - contribution = "Overlord, Support" - ) - ) +private val vancedTeam = listOf( + Person( + name = "xfileFIN", + contribution = "Mods, Theming, Support" ), - Credit( - nameId = R.string.about_category_credits_manager_devs, - persons = listOf( - Person( - name = "Xinto", - contribution = "Manager Core" - ), - Person( - name = "Koopah", - contribution = "Root installer" - ), - Person( - name = "Logan", - contribution = "UI" - ), - Person( - name = "HaliksaR", - contribution = "Refactoring, UI" - ), - ) + Person( + name = "Laura", + contribution = "Theming, Support" ), - Credit( - nameId = R.string.about_category_credits_other, - persons = listOf( - Person( - name = "bhatVikrant", - contribution = "Website" - ), - Person( - name = "bawm", - contribution = "Sponsorblock" - ), - Person( - name = "cane", - contribution = "Sponsorblock" - ), - ) + Person( + name = "ZaneZam", + contribution = "Publishing, Support" + ), + Person( + name = "KevinX8", + contribution = "Overlord, Support" + ), + Person( + name = "Xinto", + contribution = "Vanced Manager" ) ) +private val otherContributors = listOf( + Person( + name = "bhatVikrant", + contribution = "Website" + ), + Person( + name = "bawm", + contribution = "Sponsorblock" + ), + Person( + name = "cane", + contribution = "Sponsorblock" + ), + Person( + name = "Koopah", + contribution = "Vanced Manager root installer" + ), + Person( + name = "Logan", + contribution = "Vanced Manager UI" + ), + Person( + name = "HaliksaR", + contribution = "Vanced Manager Refactoring, UI" + ), +) + private val sources = listOf( Source( nameId = R.string.about_sources_source_code, @@ -118,79 +107,119 @@ private val sources = listOf( ) ) +@ExperimentalMaterial3Api @Composable -fun AboutLayout() { - ManagerScrollableColumn( - itemSpacing = 12.dp - ) { - AboutManagerCard() - credits.fastForEach { credit -> - CategoryLayout( - categoryName = managerString(stringId = credit.nameId), - categoryNameSpacing = 4.dp - ) { - Column { - credit.persons.fastForEach { person -> - ManagerListItem( - title = { - ManagerText( - text = person.name, - textStyle = MaterialTheme.typography.h6 - ) - }, - description = { - ManagerText( - text = person.contribution, - textStyle = MaterialTheme.typography.subtitle1 - ) - } +fun AboutLayout( + onToolbarBackButtonClick: () -> Unit +) { + val aboutCategoryVancedTeam = managerString(R.string.about_category_credits_vanced_team) + val aboutCategoryOtherContributors = managerString(R.string.about_category_credits_other) + val aboutCategorySources = managerString(R.string.about_category_sources) + + ManagerScaffold( + topBar = { + ManagerTopAppBar( + title = managerString(Screen.About.displayName), + navigationIcon = { + IconButton(onClick = onToolbarBackButtonClick) { + Icon( + imageVector = Icons.Rounded.ArrowBackIosNew, + contentDescription = "Back" ) } } - } + ) } - CategoryLayout( - categoryName = managerString( - stringId = R.string.about_category_sources - ), + ) { paddingValues -> + ManagerLazyColumn( + modifier = Modifier.fillMaxSize().padding(paddingValues), ) { - ScrollableItemRow(items = sources) { source -> - ManagerLinkCard( - title = managerString(source.nameId), - icon = source.iconId, - link = source.link + item { + ManagerTonalCard( + modifier = Modifier.fillMaxWidth(), + shape = LargeShape + ) { + Column( + modifier = Modifier.padding(vertical = DefaultContentPaddingVertical), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + ManagerText( + modifier = Modifier, + text = managerString(R.string.app_name), + textStyle = MaterialTheme.typography.headlineSmall + ) + ManagerText( + modifier = Modifier, + text = buildAnnotatedString { + append("Re") + withStyle(style = SpanStyle(Color(0xFFBBB529))) { + append("@Compose") + } + append("d") + }, + textStyle = MaterialTheme.typography.titleSmall + ) + } + } + } + managerCategory( + categoryName = aboutCategoryVancedTeam, + items = vancedTeam + ) { person -> + CreditPersonItem( + modifier = Modifier.fillMaxWidth(), + personName = person.name, + personContribution = person.contribution ) } + managerCategory( + categoryName = aboutCategoryOtherContributors, + items = otherContributors + ) { person -> + CreditPersonItem( + modifier = Modifier.fillMaxWidth(), + personName = person.name, + personContribution = person.contribution + ) + } + managerCategory(aboutCategorySources) { + ScrollableItemRow( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = DefaultContentPaddingHorizontal), + items = sources + ) { source -> + ManagerLinkCard( + title = managerString(source.nameId), + icon = source.iconId, + link = source.link + ) + } + } } } } @Composable -fun AboutManagerCard() { - ManagerThemedCard( - modifier = Modifier.fillMaxWidth() - ) { - Column( - modifier = Modifier.padding(vertical = DefaultContentPaddingVertical), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(4.dp) - ) { +private fun CreditPersonItem( + personName: String, + personContribution: String, + modifier: Modifier = Modifier, +) { + ManagerListItem( + modifier = modifier.padding(horizontal = DefaultContentPaddingHorizontal), + title = { ManagerText( - modifier = Modifier, - text = managerString(R.string.app_name), - textStyle = MaterialTheme.typography.h1 + text = personName, + textStyle = MaterialTheme.typography.titleSmall ) + }, + description = { ManagerText( - modifier = Modifier, - text = buildAnnotatedString { - append("Re") - withStyle(style = SpanStyle(Color(0xFFBBB529))) { - append("@Compose") - } - append("d") - }, - textStyle = MaterialTheme.typography.h5 + text = personContribution, + textStyle = MaterialTheme.typography.bodySmall ) } - } + ) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt index 647c1d650f..468fadec15 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt @@ -1,15 +1,14 @@ package com.vanced.manager.ui.screens import androidx.compose.animation.* -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.padding -import androidx.compose.material.MaterialTheme +import androidx.compose.foundation.layout.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.MoreVert +import androidx.compose.material3.* import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import androidx.navigation.NavController import coil.compose.rememberImagePainter import coil.request.CachePolicy import com.google.accompanist.swiperefresh.rememberSwipeRefreshState @@ -19,23 +18,28 @@ import com.vanced.manager.core.util.sponsors import com.vanced.manager.domain.model.InstallationOption import com.vanced.manager.ui.component.card.ManagerLinkCard import com.vanced.manager.ui.component.dialog.ManagerDialog -import com.vanced.manager.ui.component.layout.ManagerScrollableColumn +import com.vanced.manager.ui.component.layout.ManagerLazyColumn +import com.vanced.manager.ui.component.layout.ManagerScaffold import com.vanced.manager.ui.component.layout.ManagerSwipeRefresh import com.vanced.manager.ui.component.layout.ScrollableItemRow +import com.vanced.manager.ui.component.menu.ManagerDropdownMenu +import com.vanced.manager.ui.component.menu.ManagerDropdownMenuItem import com.vanced.manager.ui.component.text.ManagerText +import com.vanced.manager.ui.component.topappbar.ManagerTopAppBar import com.vanced.manager.ui.resources.managerString -import com.vanced.manager.ui.util.DefaultContentPaddingVertical +import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal import com.vanced.manager.ui.util.Screen import com.vanced.manager.ui.viewmodel.MainViewModel import com.vanced.manager.ui.widget.app.AppCard import com.vanced.manager.ui.widget.app.AppCardPlaceholder -import com.vanced.manager.ui.widget.button.ManagerCloseButton -import com.vanced.manager.ui.widget.layout.CategoryLayout +import com.vanced.manager.ui.widget.layout.managerCategory import org.koin.androidx.compose.getViewModel +@ExperimentalMaterial3Api @ExperimentalAnimationApi @Composable fun HomeLayout( + onToolbarScreenSelected: (Screen) -> Unit, onAppInstallPress: ( appName: String, appVersions: List<String>?, @@ -43,102 +47,152 @@ fun HomeLayout( ) -> Unit ) { val viewModel: MainViewModel = getViewModel() + val appState by viewModel.appState.collectAsState() val refreshState = rememberSwipeRefreshState(isRefreshing = appState is MainViewModel.AppState.Fetching) - ManagerSwipeRefresh( - refreshState = refreshState, - onRefresh = { viewModel.fetch() } - ) { - ManagerScrollableColumn( - contentPaddingVertical = DefaultContentPaddingVertical, - itemSpacing = 18.dp - ) { - CategoryLayout( - categoryName = managerString(R.string.home_category_apps), - contentPaddingHorizontal = 0.dp - ) { - AnimatedContent( - targetState = appState, - transitionSpec = { - scaleIn(initialScale = 0.9f) + fadeIn() with - scaleOut(targetScale = 0.9f) + fadeOut() + var isMenuExpanded by remember { mutableStateOf(false) } + val dropdownScreens = remember { listOf(Screen.Settings, Screen.About) } + + val homeCategoryApps = managerString(R.string.home_category_apps) + val homeCategorySupportUs = managerString(R.string.home_category_support_us) + val homeCategorySocialMedia = managerString(R.string.home_category_social_media) + + ManagerScaffold( + topBar = { + ManagerTopAppBar( + title = managerString(Screen.Home.displayName), + actions = { + IconButton(onClick = { isMenuExpanded = true }) { + Icon( + Icons.Rounded.MoreVert, + contentDescription = "Navigation" + ) } - ) { animatedAppState -> - Column( - verticalArrangement = Arrangement.spacedBy(8.dp) + + ManagerDropdownMenu( + expanded = isMenuExpanded, + onDismissRequest = { + isMenuExpanded = false + } ) { - when (animatedAppState) { - is MainViewModel.AppState.Success -> { - for (app in animatedAppState.apps) { - val appIcon = rememberImagePainter(app.iconUrl) { - diskCachePolicy(CachePolicy.ENABLED) - } + for (dropdownScreen in dropdownScreens) { + ManagerDropdownMenuItem( + title = managerString(dropdownScreen.displayName), + onClick = { + onToolbarScreenSelected(dropdownScreen) + isMenuExpanded = false + } + ) + } + } + } + ) + } + ) { paddingValues -> + ManagerSwipeRefresh( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues), + refreshState = refreshState, + onRefresh = { viewModel.fetch() } + ) { + ManagerLazyColumn { + managerCategory(homeCategoryApps) { + AnimatedContent( + targetState = appState, + transitionSpec = { + scaleIn(initialScale = 0.9f) + fadeIn() with + scaleOut(targetScale = 0.9f) + fadeOut() + } + ) { animatedAppState -> + Column( + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + when (animatedAppState) { + is MainViewModel.AppState.Success -> { + for (app in animatedAppState.apps) { + val appIcon = rememberImagePainter(app.iconUrl) { + diskCachePolicy(CachePolicy.ENABLED) + } - var showAppInfoDialog by rememberSaveable { mutableStateOf(false) } + var showAppInfoDialog by rememberSaveable { mutableStateOf(false) } - AppCard( - appName = app.name, - appIcon = appIcon, - appInstalledVersion = app.installedVersion, - appRemoteVersion = app.remoteVersion, - onDownloadClick = { - onAppInstallPress(app.name, app.versions, app.installationOptions) - }, - onUninstallClick = { /*TODO*/ }, - onLaunchClick = { /*TODO*/ }, - onInfoClick = { - showAppInfoDialog = true - } - ) + AppCard( + appName = app.name, + appIcon = appIcon, + appInstalledVersion = app.installedVersion, + appRemoteVersion = app.remoteVersion, + onAppDownloadClick = { + onAppInstallPress(app.name, app.versions, app.installationOptions) + }, + onAppUninstallClick = { /*TODO*/ }, + onAppLaunchClick = { /*TODO*/ }, + onAppInfoClick = { + showAppInfoDialog = true + } + ) - if (showAppInfoDialog) { - ManagerDialog( - title = managerString(R.string.app_info_title, app.name), - onDismissRequest = { showAppInfoDialog = false }, - buttons = { - ManagerCloseButton(onClick = { - showAppInfoDialog = false - }) + if (showAppInfoDialog) { + ManagerDialog( + title = managerString(R.string.app_info_title, app.name), + onDismissRequest = { showAppInfoDialog = false }, + confirmButton = { + TextButton(onClick = { + showAppInfoDialog = false + }) { + ManagerText(text = managerString(R.string.dialog_button_close)) + } + }, + ) { + ManagerText( + modifier = Modifier.padding(top = 4.dp), + text = app.changelog, + //textStyle = MaterialTheme.typography.bodyMedium + ) } - ) { - ManagerText( - modifier = Modifier.padding(top = 4.dp), - text = app.changelog, - textStyle = MaterialTheme.typography.subtitle1 - ) } } } - } - is MainViewModel.AppState.Fetching -> { - for (i in 0 until animatedAppState.placeholderAppsCount) { - AppCardPlaceholder() + is MainViewModel.AppState.Fetching -> { + for (i in 0 until animatedAppState.placeholderAppsCount) { + AppCardPlaceholder() + } } - } - is MainViewModel.AppState.Error -> { + is MainViewModel.AppState.Error -> { + } } } } } - } - CategoryLayout(managerString(R.string.home_category_support_us)) { - ScrollableItemRow(items = sponsors) { sponsor -> - ManagerLinkCard( - icon = sponsor.icon, - title = sponsor.title, - link = sponsor.link - ) + managerCategory(homeCategorySupportUs) { + ScrollableItemRow( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = DefaultContentPaddingHorizontal), + items = sponsors + ) { sponsor -> + ManagerLinkCard( + icon = sponsor.icon, + title = sponsor.title, + link = sponsor.link + ) + } } - } - CategoryLayout( managerString(R.string.home_category_social_media)) { - ScrollableItemRow(items = socialMedia) { socialMedia -> - ManagerLinkCard( - icon = socialMedia.icon, - title = socialMedia.title, - link = socialMedia.link - ) + managerCategory(homeCategorySocialMedia) { + ScrollableItemRow( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = DefaultContentPaddingHorizontal), + items = socialMedia + ) { socialMedia -> + ManagerLinkCard( + icon = socialMedia.icon, + title = socialMedia.title, + link = socialMedia.link + ) + } } } } diff --git a/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt b/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt index 8f9dc94e04..1424bdc03e 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt @@ -1,121 +1,144 @@ package com.vanced.manager.ui.screens -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.sizeIn -import androidx.compose.material.FloatingActionButton -import androidx.compose.material.Icon -import androidx.compose.material.Scaffold +import androidx.compose.animation.* +import androidx.compose.animation.core.tween +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.ArrowBackIosNew import androidx.compose.material.icons.rounded.Done +import androidx.compose.material.icons.rounded.NavigateBefore +import androidx.compose.material.icons.rounded.NavigateNext +import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.compose.ui.util.fastForEach -import androidx.compose.ui.util.fastForEachIndexed +import com.vanced.manager.R import com.vanced.manager.domain.model.InstallationOption -import com.vanced.manager.ui.component.card.ManagerClickableThemedCard -import com.vanced.manager.ui.component.layout.ManagerScrollableColumn +import com.vanced.manager.ui.component.card.ManagerTonalCard +import com.vanced.manager.ui.component.layout.ManagerLazyColumn +import com.vanced.manager.ui.component.layout.ManagerScaffold +import com.vanced.manager.ui.component.progressindicator.ManagerProgressIndicator import com.vanced.manager.ui.component.text.ManagerText +import com.vanced.manager.ui.component.topappbar.ManagerTopAppBar import com.vanced.manager.ui.resources.managerString +import com.vanced.manager.ui.theme.LargeShape import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal import com.vanced.manager.ui.util.DefaultContentPaddingVertical import com.vanced.manager.ui.widget.list.CheckboxItem import com.vanced.manager.ui.widget.list.RadiobuttonItem +@ExperimentalFoundationApi +@ExperimentalAnimationApi +@OptIn(ExperimentalMaterial3Api::class) @Composable fun InstallPreferencesScreen( installationOptions: List<InstallationOption>, - onDoneClick: () -> Unit + onToolbarBackButtonClick: () -> Unit, + onDoneClick: () -> Unit, ) { - var selectedOptionIndex by rememberSaveable { mutableStateOf(0) } + var currentOptionIndex by rememberSaveable { mutableStateOf(0) } - Scaffold( - floatingActionButton = { - FloatingActionButton( - onClick = onDoneClick - ) { - Icon( - imageVector = Icons.Rounded.Done, - contentDescription = "Done" + ManagerScaffold( + topBar = { + Column { + ManagerTopAppBar( + title = managerString(R.string.toolbar_installation_preferences), + navigationIcon = { + IconButton( + onClick = onToolbarBackButtonClick + ) { + Icon( + imageVector = Icons.Rounded.ArrowBackIosNew, + contentDescription = "Back" + ) + } + } + ) + ManagerProgressIndicator( + progress = (currentOptionIndex + 1).toFloat() / installationOptions.size.toFloat() ) } - } + }, ) { paddingValues -> - ManagerScrollableColumn( - modifier = Modifier.padding(paddingValues), - itemSpacing = DefaultContentPaddingVertical + Column( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues), ) { - installationOptions.fastForEachIndexed { index, installationOption -> - ManagerClickableThemedCard( + AnimatedContent( + modifier = Modifier + .padding( + horizontal = DefaultContentPaddingHorizontal, + vertical = DefaultContentPaddingVertical + ) + .weight(1f), + targetState = currentOptionIndex, + transitionSpec = { + getSlideAnimationSpec( + if (targetState > initialState) { + AnimatedContentScope.SlideDirection.Start + } else { + AnimatedContentScope.SlideDirection.End + } + ) + } + ) { optionIndex -> + val installationOption = installationOptions[optionIndex] + ManagerTonalCard( modifier = Modifier - .fillMaxWidth() - .padding(horizontal = DefaultContentPaddingHorizontal), - onClick = { - selectedOptionIndex = index - } + .wrapContentHeight( + align = Alignment.Top + ), + shape = LargeShape ) { - Column( - modifier = Modifier.padding(12.dp) - ) { + Column { ManagerText( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .fillMaxWidth() + .padding( + horizontal = DefaultContentPaddingHorizontal, + vertical = DefaultContentPaddingVertical + ), text = managerString(installationOption.itemTitleId), - textStyle = TextStyle( - fontSize = 20.sp, - fontWeight = FontWeight.SemiBold - ), - textAlign = TextAlign.Center + textStyle = MaterialTheme.typography.titleLarge, ) - AnimatedVisibility( - visible = index == selectedOptionIndex - ) { - ManagerScrollableColumn( - modifier = Modifier.sizeIn( - maxHeight = 400.dp - ) - ) { - when (installationOption) { - is InstallationOption.MultiSelect -> { - installationOption.items.fastForEach { item -> - val preference = installationOption.getOption() - CheckboxItem( - modifier = Modifier.fillMaxWidth(), - text = item.displayText(item.key), - isChecked = preference.contains(item.key), - onCheck = { - if (it) { - installationOption.addOption(item.key) - } else { - installationOption.removeOption(item.key) - } + ManagerLazyColumn { + when (installationOption) { + is InstallationOption.MultiSelect -> { + items(installationOption.items) { item -> + val preference = installationOption.getOption() + CheckboxItem( + modifier = Modifier.fillMaxWidth(), + text = item.displayText(item.key), + isChecked = preference.contains(item.key), + onCheck = { + if (it) { + installationOption.addOption(item.key) + } else { + installationOption.removeOption(item.key) } - ) - } + } + ) } - is InstallationOption.SingleSelect -> { - installationOption.items.fastForEach { item -> - val preference = installationOption.getOption() - RadiobuttonItem( - modifier = Modifier.fillMaxWidth(), - text = item.displayText(item.key), - isSelected = preference == item.key, - onSelect = { - installationOption.setOption(item.key) - }, - tag = item.key - ) - } + } + is InstallationOption.SingleSelect -> { + items(installationOption.items) { item -> + val preference = installationOption.getOption() + RadiobuttonItem( + modifier = Modifier.fillMaxWidth(), + text = item.displayText(item.key), + isSelected = preference == item.key, + onSelect = { + installationOption.setOption(item.key) + }, + tag = item.key + ) } } } @@ -123,8 +146,80 @@ fun InstallPreferencesScreen( } } } + Row( + modifier = Modifier + .fillMaxWidth() + .padding( + horizontal = DefaultContentPaddingHorizontal, + vertical = DefaultContentPaddingVertical + ), + ) { + AnimatedVisibility( + visible = currentOptionIndex > 0 + ) { + FloatingActionButton( + onClick = { + currentOptionIndex-- + } + ) { + Icon( + imageVector = Icons.Rounded.NavigateBefore, + contentDescription = "Back" + ) + } + } + Spacer(modifier = Modifier.weight(1f)) + AnimatedContent( + targetState = currentOptionIndex == installationOptions.lastIndex, + transitionSpec = { + + getSlideAnimationSpec( + if (initialState && !targetState) { + AnimatedContentScope.SlideDirection.Up + } else { + AnimatedContentScope.SlideDirection.Down + } + ) + } + ) { lastIndex -> + if (lastIndex) { + FloatingActionButton( + onClick = onDoneClick + ) { + Icon( + imageVector = Icons.Rounded.Done, + contentDescription = "Done" + ) + } + } else { + FloatingActionButton( + onClick = { + currentOptionIndex++ + } + ) { + Icon( + imageVector = Icons.Rounded.NavigateNext, + contentDescription = "Next" + ) + } + } + } + } } } +} - -} \ No newline at end of file +@ExperimentalAnimationApi +private fun <S> AnimatedContentScope<S>.getSlideAnimationSpec( + slideDirection: AnimatedContentScope.SlideDirection +) = slideIntoContainer( + towards = slideDirection, + animationSpec = tween(400) +) + fadeIn( + animationSpec = tween(400) +) with slideOutOfContainer( + towards = slideDirection, + animationSpec = tween(400) +) + fadeOut( + animationSpec = tween(400) +) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt b/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt index ea605e4c82..c125b8ba6b 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt @@ -5,33 +5,37 @@ import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.items -import androidx.compose.material.Icon -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Scaffold import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.ArrowDropDown +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate -import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.withStyle -import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.vanced.manager.R import com.vanced.manager.ui.component.layout.ManagerLazyColumn +import com.vanced.manager.ui.component.layout.ManagerScaffold import com.vanced.manager.ui.component.modifier.managerClickable import com.vanced.manager.ui.component.progressindicator.ManagerProgressIndicator import com.vanced.manager.ui.component.text.ManagerText +import com.vanced.manager.ui.component.topappbar.ManagerTopAppBar +import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal -import com.vanced.manager.ui.util.DefaultContentPaddingVertical import com.vanced.manager.ui.viewmodel.InstallViewModel import org.koin.androidx.compose.getViewModel -@OptIn(ExperimentalFoundationApi::class) +@OptIn( + ExperimentalFoundationApi::class, + ExperimentalMaterial3Api::class +) @Composable fun InstallScreen( appName: String, @@ -41,18 +45,12 @@ fun InstallScreen( viewModel.startAppProcess(appName, appVersions) - Scaffold( - floatingActionButton = { - - } - ) { paddingValues -> - ManagerLazyColumn( - modifier = Modifier - .fillMaxWidth() - .padding(paddingValues), - contentPadding = PaddingValues(0.dp), - ) { - stickyHeader { + ManagerScaffold( + topBar = { + Column { + ManagerTopAppBar( + title = managerString(R.string.toolbar_install), + ) when (val status = viewModel.status) { is InstallViewModel.Status.Progress -> { ManagerProgressIndicator(status.progress) @@ -63,11 +61,16 @@ fun InstallScreen( else -> {} } } + }, + floatingActionButton = { - item { - Spacer(Modifier.height(DefaultContentPaddingVertical)) - } - + } + ) { paddingValues -> + ManagerLazyColumn( + modifier = Modifier + .fillMaxWidth() + .padding(paddingValues), + ) { items(viewModel.logs) { log -> when (log) { is InstallViewModel.Log.Success -> { @@ -79,7 +82,7 @@ fun InstallScreen( textStyle = TextStyle( fontWeight = FontWeight.Bold, fontSize = 14.sp, - color = Color.Blue + color = MaterialTheme.colorScheme.tertiary ), ) } @@ -92,7 +95,7 @@ fun InstallScreen( textStyle = TextStyle( fontWeight = FontWeight.SemiBold, fontSize = 14.sp, - color = Color.Black + color = MaterialTheme.colorScheme.onSurface ), ) } @@ -114,7 +117,7 @@ fun InstallScreen( ) { ManagerText( text = buildAnnotatedString { - withStyle(SpanStyle(color = MaterialTheme.colors.error)) { + withStyle(SpanStyle(color = MaterialTheme.colorScheme.error)) { append(log.displayText) } }, @@ -127,7 +130,7 @@ fun InstallScreen( modifier = Modifier.rotate(iconRotation), imageVector = Icons.Rounded.ArrowDropDown, contentDescription = "expand", - tint = MaterialTheme.colors.error + tint = MaterialTheme.colorScheme.error ) } AnimatedVisibility(visible) { @@ -136,7 +139,7 @@ fun InstallScreen( textStyle = TextStyle( fontWeight = FontWeight.Bold, fontSize = 14.sp, - color = MaterialTheme.colors.error.copy(alpha = 0.7f) + color = MaterialTheme.colorScheme.error.copy(alpha = 0.7f) ), ) } diff --git a/app/src/main/java/com/vanced/manager/ui/screens/LogLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/LogLayout.kt deleted file mode 100644 index 5632b6bde0..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/screens/LogLayout.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.vanced.manager.ui.screens - -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.lazy.items -import androidx.compose.material.FloatingActionButton -import androidx.compose.material.Icon -import androidx.compose.material.Scaffold -import androidx.compose.material.Text -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Share -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.vanced.manager.ui.component.color.managerAccentColor -import com.vanced.manager.ui.component.color.managerSurfaceColor -import com.vanced.manager.ui.component.layout.ManagerLazyColumn -import com.vanced.manager.core.util.logs - -@Composable -fun LogLayout() { - Scaffold( - modifier = Modifier.fillMaxSize(), - floatingActionButton = { - FloatingActionButton( - onClick = { /*TODO*/ }, - backgroundColor = managerAccentColor() - ) { - Icon( - imageVector = Icons.Default.Share, - contentDescription = "share" - ) - } - }, - backgroundColor = managerSurfaceColor() - ) { - ManagerLazyColumn { - items(logs) { log -> - Text(text = log.body) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt index 7ee69359ff..376a471906 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt @@ -1,37 +1,59 @@ package com.vanced.manager.ui.screens +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.ArrowBackIosNew +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable -import androidx.compose.ui.unit.dp +import androidx.compose.ui.Modifier import com.vanced.manager.R -import com.vanced.manager.ui.component.layout.ManagerScrollableColumn +import com.vanced.manager.ui.component.layout.ManagerLazyColumn +import com.vanced.manager.ui.component.topappbar.ManagerTopAppBar import com.vanced.manager.ui.resources.managerString -import com.vanced.manager.ui.util.DefaultContentPaddingVertical -import com.vanced.manager.ui.widget.layout.SettingsCategoryLayout +import com.vanced.manager.ui.util.Screen +import com.vanced.manager.ui.widget.layout.managerCategory import com.vanced.manager.ui.widget.screens.settings.* +@ExperimentalMaterial3Api @Composable -fun SettingsLayout() { - ManagerScrollableColumn( - contentPaddingVertical = DefaultContentPaddingVertical, - itemSpacing = 12.dp - ) { - SettingsCategoryLayout( - categoryName = managerString( - stringId = R.string.settings_category_behaviour +fun SettingsLayout( + onToolbarBackButtonClick: () -> Unit, +) { + val settingsCategoryBehaviour = managerString(R.string.settings_category_behaviour) + val settingsCategoryApperance = managerString(R.string.settings_category_appearance) + + Scaffold( + modifier = Modifier.fillMaxSize(), + topBar = { + ManagerTopAppBar( + title = managerString(Screen.Settings.displayName), + navigationIcon = { + IconButton(onClick = onToolbarBackButtonClick) { + Icon( + imageVector = Icons.Rounded.ArrowBackIosNew, + contentDescription = "Back" + ) + } + } ) - ) { - SettingsCustomTabsItem() - SettingsNotificationsItem() - SettingsManagerVariantItem() } - SettingsCategoryLayout( - categoryName = managerString( - stringId = R.string.settings_category_appearance - ) + ) { paddingValues -> + ManagerLazyColumn( + modifier = Modifier.fillMaxSize().padding(paddingValues), ) { - SettingsAccentColorItem() - ThemeSettingsItem() + managerCategory(settingsCategoryBehaviour) { + SettingsCustomTabsItem() + SettingsNotificationsItem() + SettingsManagerVariantItem() + } + managerCategory(settingsCategoryApperance) { + SettingsAccentColorItem() + ThemeSettingsItem() + } } } - } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Color.kt b/app/src/main/java/com/vanced/manager/ui/theme/Color.kt index 03a4b67a59..922bd4452f 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Color.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Color.kt @@ -9,4 +9,59 @@ val darkSurface = Color.Black val darkOnSurface = Color(0xFFD5D5D5) val lightSurface = Color.White -val lightOnSurface = Color.Black \ No newline at end of file +val lightOnSurface = Color.Black + +val md_theme_light_primary = Color(0xFF0054d9) +val md_theme_light_onPrimary = Color(0xFFffffff) +val md_theme_light_primaryContainer = Color(0xFFdae2ff) +val md_theme_light_onPrimaryContainer = Color(0xFF00174a) +val md_theme_light_secondary = Color(0xFFc00020) +val md_theme_light_onSecondary = Color(0xFFffffff) +val md_theme_light_secondaryContainer = Color(0xFFffdad6) +val md_theme_light_onSecondaryContainer = Color(0xFF410005) +val md_theme_light_tertiary = Color(0xFF943896) +val md_theme_light_onTertiary = Color(0xFFffffff) +val md_theme_light_tertiaryContainer = Color(0xFFffd6fa) +val md_theme_light_onTertiaryContainer = Color(0xFF37003c) +val md_theme_light_error = Color(0xFFba1b1b) +val md_theme_light_errorContainer = Color(0xFFffdad4) +val md_theme_light_onError = Color(0xFFffffff) +val md_theme_light_onErrorContainer = Color(0xFF410001) +val md_theme_light_background = Color(0xFFfefbff) +val md_theme_light_onBackground = Color(0xFF1b1b1e) +val md_theme_light_surface = Color(0xFFfefbff) +val md_theme_light_onSurface = Color(0xFF1b1b1e) +val md_theme_light_surfaceVariant = Color(0xFFe2e2ec) +val md_theme_light_onSurfaceVariant = Color(0xFF44464e) +val md_theme_light_outline = Color(0xFF75767f) +val md_theme_light_inverseOnSurface = Color(0xFFf2f0f5) +val md_theme_light_inverseSurface = Color(0xFF303033) + +val md_theme_dark_primary = Color(0xFFb1c5ff) +val md_theme_dark_onPrimary = Color(0xFF002a77) +val md_theme_dark_primaryContainer = Color(0xFF003ea6) +val md_theme_dark_onPrimaryContainer = Color(0xFFdae2ff) +val md_theme_dark_secondary = Color(0xFFffb3af) +val md_theme_dark_onSecondary = Color(0xFF69000c) +val md_theme_dark_secondaryContainer = Color(0xFF920016) +val md_theme_dark_onSecondaryContainer = Color(0xFFffdad6) +val md_theme_dark_tertiary = Color(0xFFffa9fc) +val md_theme_dark_onTertiary = Color(0xFF5a0061) +val md_theme_dark_tertiaryContainer = Color(0xFF781c7c) +val md_theme_dark_onTertiaryContainer = Color(0xFFffd6fa) +val md_theme_dark_error = Color(0xFFffb4a9) +val md_theme_dark_errorContainer = Color(0xFF930006) +val md_theme_dark_onError = Color(0xFF680003) +val md_theme_dark_onErrorContainer = Color(0xFFffdad4) +val md_theme_dark_background = Color(0xFF1b1b1e) +val md_theme_dark_onBackground = Color(0xFFe3e1e6) +val md_theme_dark_surface = Color(0xFF1b1b1e) +val md_theme_dark_onSurface = Color(0xFFe3e1e6) +val md_theme_dark_surfaceVariant = Color(0xFF44464e) +val md_theme_dark_onSurfaceVariant = Color(0xFFc6c6d0) +val md_theme_dark_outline = Color(0xFF8f909a) +val md_theme_dark_inverseOnSurface = Color(0xFF1b1b1e) +val md_theme_dark_inverseSurface = Color(0xFFe3e1e6) + +val seed = Color(0xFF2e73ff) +val error = Color(0xFFba1b1b) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Shape.kt b/app/src/main/java/com/vanced/manager/ui/theme/Shape.kt index 82c29e3961..70afbea6d0 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Shape.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Shape.kt @@ -1,11 +1,9 @@ package com.vanced.manager.ui.theme import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Shapes import androidx.compose.ui.unit.dp -val shapes = Shapes( - small = RoundedCornerShape(8.dp), - medium = RoundedCornerShape(12.dp), - large = RoundedCornerShape(8.dp) -) \ No newline at end of file +//TODO M3 doesn't support Shapes yet +val SmallShape = RoundedCornerShape(8.dp) +val MediumShape = RoundedCornerShape(12.dp) +val LargeShape = RoundedCornerShape(16.dp) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt index 226f435d92..f8be63d5d4 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt @@ -1,26 +1,74 @@ package com.vanced.manager.ui.theme +import android.annotation.SuppressLint +import android.os.Build +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.LocalIndication +import androidx.compose.foundation.gestures.LocalOverScrollConfiguration +import androidx.compose.foundation.gestures.OverScrollConfiguration import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.material.MaterialTheme -import androidx.compose.material.darkColors -import androidx.compose.material.lightColors +import androidx.compose.material.ripple.rememberRipple +import androidx.compose.material3.* import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.platform.LocalContext import com.vanced.manager.core.preferences.holder.managerThemePref const val defAccentColor = 0xFF0477E1 -private val DarkColorPalette = darkColors( - primary = primaryColor, - primaryVariant = primaryColorVariant, - surface = darkSurface, - onSurface = darkOnSurface +private val LightThemeColors = lightColorScheme( + primary = md_theme_light_primary, + onPrimary = md_theme_light_onPrimary, + primaryContainer = md_theme_light_primaryContainer, + onPrimaryContainer = md_theme_light_onPrimaryContainer, + secondary = md_theme_light_secondary, + onSecondary = md_theme_light_onSecondary, + secondaryContainer = md_theme_light_secondaryContainer, + onSecondaryContainer = md_theme_light_onSecondaryContainer, + tertiary = md_theme_light_tertiary, + onTertiary = md_theme_light_onTertiary, + tertiaryContainer = md_theme_light_tertiaryContainer, + onTertiaryContainer = md_theme_light_onTertiaryContainer, + error = md_theme_light_error, + errorContainer = md_theme_light_errorContainer, + onError = md_theme_light_onError, + onErrorContainer = md_theme_light_onErrorContainer, + background = md_theme_light_background, + onBackground = md_theme_light_onBackground, + surface = md_theme_light_surface, + onSurface = md_theme_light_onSurface, + surfaceVariant = md_theme_light_surfaceVariant, + onSurfaceVariant = md_theme_light_onSurfaceVariant, + outline = md_theme_light_outline, + inverseOnSurface = md_theme_light_inverseOnSurface, + inverseSurface = md_theme_light_inverseSurface, ) - -private val LightColorPalette = lightColors( - primary = primaryColor, - primaryVariant = primaryColorVariant, - surface = lightSurface, - onSurface = lightOnSurface, +private val DarkThemeColors = darkColorScheme( + primary = md_theme_dark_primary, + onPrimary = md_theme_dark_onPrimary, + primaryContainer = md_theme_dark_primaryContainer, + onPrimaryContainer = md_theme_dark_onPrimaryContainer, + secondary = md_theme_dark_secondary, + onSecondary = md_theme_dark_onSecondary, + secondaryContainer = md_theme_dark_secondaryContainer, + onSecondaryContainer = md_theme_dark_onSecondaryContainer, + tertiary = md_theme_dark_tertiary, + onTertiary = md_theme_dark_onTertiary, + tertiaryContainer = md_theme_dark_tertiaryContainer, + onTertiaryContainer = md_theme_dark_onTertiaryContainer, + error = md_theme_dark_error, + errorContainer = md_theme_dark_errorContainer, + onError = md_theme_dark_onError, + onErrorContainer = md_theme_dark_onErrorContainer, + background = md_theme_dark_background, + onBackground = md_theme_dark_onBackground, + surface = md_theme_dark_surface, + onSurface = md_theme_dark_onSurface, + surfaceVariant = md_theme_dark_surfaceVariant, + onSurfaceVariant = md_theme_dark_onSurfaceVariant, + outline = md_theme_dark_outline, + inverseOnSurface = md_theme_dark_inverseOnSurface, + inverseSurface = md_theme_dark_inverseSurface, ) @Composable @@ -31,16 +79,41 @@ fun isDark(): Boolean = when (managerThemePref.value.value) { else -> throw IllegalArgumentException("Unknown theme") } +@SuppressLint("NewApi") +@ExperimentalFoundationApi @Composable fun ManagerTheme( content: @Composable () -> Unit ) { - val colors = if (isDark()) DarkColorPalette else LightColorPalette + val isAndroid12OrHigher = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S + val colorScheme = + if (isAndroid12OrHigher) { + val context = LocalContext.current + if (isDark()) { + dynamicDarkColorScheme(context) + } else { + dynamicLightColorScheme(context) + } + } else { + if (isDark()) { + DarkThemeColors + } else { + LightThemeColors + } + } MaterialTheme( - colors = colors, - typography = typography, - shapes = shapes, - content = content - ) + colorScheme = colorScheme, + typography = ManagerTypography, + ) { + val rippleIndication = rememberRipple() + CompositionLocalProvider( + LocalIndication provides rippleIndication, + LocalOverScrollConfiguration provides OverScrollConfiguration( + forceShowAlways = isAndroid12OrHigher + ) + ) { + content() + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Type.kt b/app/src/main/java/com/vanced/manager/ui/theme/Type.kt index 741a260083..6cf08c3399 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Type.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Type.kt @@ -1,6 +1,6 @@ package com.vanced.manager.ui.theme -import androidx.compose.material.Typography +import androidx.compose.material3.Typography import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily @@ -14,45 +14,112 @@ private val medium = Font(R.font.inter_medium, FontWeight.Medium) private val semibold = Font(R.font.inter_semibold, FontWeight.SemiBold) private val bold = Font(R.font.inter_bold, FontWeight.Bold) -private val interFontFamily = FontFamily(light, regular, medium, semibold, bold) +private val InterFontFamily = FontFamily(light, regular, medium, semibold, bold) -// Set of Material typography styles to start with -val typography = Typography( - defaultFontFamily = interFontFamily, - h1 = TextStyle( - fontSize = 24.sp, +val ManagerTypography = Typography( + displayLarge = TextStyle( + fontFamily = InterFontFamily, + fontWeight = FontWeight.Normal, + fontSize = 57.sp, + lineHeight = 64.sp, + letterSpacing = (-0.25).sp, + ), + displayMedium = TextStyle( + fontFamily = InterFontFamily, + fontWeight = FontWeight.Normal, + fontSize = 45.sp, + lineHeight = 52.sp, + letterSpacing = 0.sp, + ), + displaySmall = TextStyle( + fontFamily = InterFontFamily, + fontWeight = FontWeight.Normal, + fontSize = 36.sp, + lineHeight = 44.sp, + letterSpacing = 0.sp, + ), + headlineLarge = TextStyle( + fontFamily = InterFontFamily, fontWeight = FontWeight.Bold, + fontSize = 32.sp, + lineHeight = 40.sp, + letterSpacing = 0.sp, ), - h2 = TextStyle( - fontSize = 20.sp, - fontWeight = FontWeight.SemiBold + headlineMedium = TextStyle( + fontFamily = InterFontFamily, + fontWeight = FontWeight.Bold, + fontSize = 28.sp, + lineHeight = 36.sp, + letterSpacing = 0.sp, ), - h5 = TextStyle( - fontSize = 16.sp, + headlineSmall = TextStyle( + fontFamily = InterFontFamily, fontWeight = FontWeight.SemiBold, + fontSize = 24.sp, + lineHeight = 32.sp, + letterSpacing = 0.sp, ), - h6 = TextStyle( - fontSize = 14.sp, - fontWeight = FontWeight.Bold + titleLarge = TextStyle( + fontFamily = InterFontFamily, + fontWeight = FontWeight.SemiBold, + fontSize = 22.sp, + lineHeight = 28.sp, + letterSpacing = 0.sp, ), - body1 = TextStyle( - fontWeight = FontWeight.Medium, - fontSize = 12.sp + titleMedium = TextStyle( + fontFamily = InterFontFamily, + fontWeight = FontWeight.SemiBold, + fontSize = 18.sp, + lineHeight = 24.sp, + letterSpacing = 0.1.sp, ), - body2 = TextStyle( - fontWeight = FontWeight.Normal, - fontSize = 10.sp, + titleSmall = TextStyle( + fontFamily = InterFontFamily, + fontWeight = FontWeight.SemiBold, + fontSize = 16.sp, + lineHeight = 20.sp, + letterSpacing = 0.1.sp, ), - subtitle1 = TextStyle( + bodyLarge = TextStyle( + fontFamily = InterFontFamily, fontWeight = FontWeight.Normal, - fontSize = 12.sp, + fontSize = 16.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp, ), - subtitle2 = TextStyle( + bodyMedium = TextStyle( + fontFamily = InterFontFamily, + fontWeight = FontWeight.Medium, + fontSize = 14.sp, + lineHeight = 20.sp, + letterSpacing = 0.25.sp, + ), + bodySmall = TextStyle( + fontFamily = InterFontFamily, fontWeight = FontWeight.Normal, - fontSize = 14.sp + fontSize = 12.sp, + lineHeight = 14.sp, + letterSpacing = 0.sp, ), - button = TextStyle( + labelLarge = TextStyle( + fontFamily = InterFontFamily, + fontWeight = FontWeight.SemiBold, fontSize = 14.sp, - fontWeight = FontWeight.Medium - ) + lineHeight = 20.sp, + letterSpacing = 0.1.sp, + ), + labelMedium = TextStyle( + fontFamily = InterFontFamily, + fontWeight = FontWeight.Medium, + fontSize = 12.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp, + ), + labelSmall = TextStyle( + fontFamily = InterFontFamily, + fontWeight = FontWeight.Medium, + fontSize = 11.sp, + lineHeight = 16.sp, + letterSpacing = 0.5.sp, + ), ) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/util/Screen.kt b/app/src/main/java/com/vanced/manager/ui/util/Screen.kt index 216b3effc0..33806919a4 100644 --- a/app/src/main/java/com/vanced/manager/ui/util/Screen.kt +++ b/app/src/main/java/com/vanced/manager/ui/util/Screen.kt @@ -1,13 +1,8 @@ package com.vanced.manager.ui.util import androidx.annotation.StringRes -import androidx.compose.runtime.Composable import com.vanced.manager.R import com.vanced.manager.domain.model.InstallationOption -import com.vanced.manager.ui.screens.AboutLayout -import com.vanced.manager.ui.screens.HomeLayout -import com.vanced.manager.ui.screens.LogLayout -import com.vanced.manager.ui.screens.SettingsLayout sealed class Screen( val route: String, diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt index 640b683db3..ed12a72eea 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt @@ -3,13 +3,10 @@ package com.vanced.manager.ui.viewmodel import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import androidx.lifecycle.viewmodel.compose.viewModel -import com.vanced.manager.core.downloader.base.AppDownloader -import com.vanced.manager.core.downloader.util.DownloadStatus -import com.vanced.manager.domain.model.App import com.vanced.manager.core.preferences.holder.managerVariantPref import com.vanced.manager.core.preferences.holder.musicEnabled import com.vanced.manager.core.preferences.holder.vancedEnabled +import com.vanced.manager.domain.model.App import com.vanced.manager.repository.JsonRepository import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow @@ -34,7 +31,7 @@ class MainViewModel( val appState: StateFlow<AppState> = _appState fun fetch() { - viewModelScope.launch(Dispatchers.IO) { + viewModelScope.launch { val vancedEnabled = vancedEnabled.value.value val musicEnabled = musicEnabled.value.value val isNonroot = managerVariantPref.value.value == "nonroot" diff --git a/app/src/main/java/com/vanced/manager/ui/widget/app/AppCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/app/AppCard.kt index 3b77e17f11..cd58c59516 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/app/AppCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/app/AppCard.kt @@ -4,19 +4,22 @@ import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.Image import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.size -import androidx.compose.material.MaterialTheme import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Info import androidx.compose.material.icons.outlined.Info import androidx.compose.material.icons.rounded.DeleteForever import androidx.compose.material.icons.rounded.Download import androidx.compose.material.icons.rounded.Launch +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import coil.compose.ImagePainter import com.vanced.manager.R -import com.vanced.manager.ui.component.button.IconButton +import com.vanced.manager.ui.component.button.ManagerIconButton import com.vanced.manager.ui.component.text.AppVersionText import com.vanced.manager.ui.component.text.ManagerText @@ -27,17 +30,17 @@ fun AppCard( appIcon: ImagePainter, appInstalledVersion: String?, appRemoteVersion: String?, - onDownloadClick: () -> Unit, - onUninstallClick: () -> Unit, - onLaunchClick: () -> Unit, - onInfoClick: () -> Unit, + onAppDownloadClick: () -> Unit, + onAppUninstallClick: () -> Unit, + onAppLaunchClick: () -> Unit, + onAppInfoClick: () -> Unit, ) { BaseAppCard( appTitle = { ManagerText( modifier = Modifier.fillMaxSize(), text = appName, - textStyle = MaterialTheme.typography.h5 + textStyle = MaterialTheme.typography.titleMedium ) }, appIcon = { @@ -47,6 +50,14 @@ fun AppCard( contentDescription = "App Icon", ) }, + appTrailing = { + IconButton(onClick = onAppInfoClick) { + Icon( + imageVector = Icons.Outlined.Info, + contentDescription = "App Info" + ) + } + }, appVersionsColumn = { AppVersionText( text = stringResource( @@ -66,26 +77,24 @@ fun AppCard( ) }, appActionsRow = { - IconButton( - icon = Icons.Outlined.Info, - contentDescription = "App Info", - onClick = onInfoClick - ) - IconButton( - icon = Icons.Rounded.DeleteForever, - contentDescription = "Uninstall", - onClick = onUninstallClick - ) - IconButton( - icon = Icons.Rounded.Launch, - contentDescription = "Launch", - onClick = onLaunchClick - ) - IconButton( - icon = Icons.Rounded.Download, - contentDescription = "Install", - onClick = onDownloadClick - ) + IconButton(onClick = onAppUninstallClick) { + Icon( + imageVector = Icons.Rounded.DeleteForever, + contentDescription = "Uninstall" + ) + } + IconButton(onClick = onAppLaunchClick) { + Icon( + imageVector = Icons.Rounded.Launch, + contentDescription = "Launch", + ) + } + IconButton(onClick = onAppDownloadClick) { + Icon( + imageVector = Icons.Rounded.Download, + contentDescription = "Install", + ) + } } ) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/app/AppCardPlaceholder.kt b/app/src/main/java/com/vanced/manager/ui/widget/app/AppCardPlaceholder.kt index 3a6e67d6e2..92ae807b30 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/app/AppCardPlaceholder.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/app/AppCardPlaceholder.kt @@ -1,7 +1,12 @@ package com.vanced.manager.ui.widget.app -import androidx.compose.foundation.layout.* -import androidx.compose.material.MaterialTheme +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -9,6 +14,8 @@ import androidx.compose.ui.unit.dp import com.vanced.manager.ui.component.modifier.managerPlaceholder import com.vanced.manager.ui.component.text.AppVersionText import com.vanced.manager.ui.component.text.ManagerText +import com.vanced.manager.ui.theme.MediumShape +import com.vanced.manager.ui.theme.SmallShape @Composable fun AppCardPlaceholder() { @@ -16,38 +23,46 @@ fun AppCardPlaceholder() { appTitle = { ManagerText( modifier = Modifier - .clip(MaterialTheme.shapes.medium) + .clip(MediumShape) .managerPlaceholder(true), text = " ".repeat(40), - textStyle = MaterialTheme.typography.h5 + textStyle = MaterialTheme.typography.titleMedium ) }, appIcon = { Box( Modifier - .clip(MaterialTheme.shapes.medium) + .clip(MediumShape) .managerPlaceholder(true) .size(48.dp) ) }, + appTrailing = { + Box( + Modifier + .clip(CircleShape) + .managerPlaceholder(true) + .size(24.dp) + ) + }, appVersionsColumn = { AppVersionText( modifier = Modifier .managerPlaceholder(true) - .clip(MaterialTheme.shapes.small), + .clip(SmallShape), text = " ".repeat(30) ) AppVersionText( modifier = Modifier .managerPlaceholder(true) - .clip(MaterialTheme.shapes.small), + .clip(SmallShape), text = " ".repeat(30) ) }, appActionsRow = { Box( Modifier - .clip(MaterialTheme.shapes.medium) + .clip(MediumShape) .fillMaxWidth(0.8f) .height(36.dp) .managerPlaceholder(true) diff --git a/app/src/main/java/com/vanced/manager/ui/widget/app/BaseAppCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/app/BaseAppCard.kt index c85789ff15..4e66fb205b 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/app/BaseAppCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/app/BaseAppCard.kt @@ -1,19 +1,21 @@ package com.vanced.manager.ui.widget.app import androidx.compose.foundation.layout.* -import androidx.compose.material.LocalContentColor -import androidx.compose.material.MaterialTheme +import androidx.compose.material.Divider +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.vanced.manager.R -import com.vanced.manager.ui.component.card.ManagerCard -import com.vanced.manager.ui.component.card.ManagerThemedCard +import com.vanced.manager.ui.component.card.ManagerTonalCard import com.vanced.manager.ui.component.list.ManagerListItem import com.vanced.manager.ui.component.text.ManagerText +import com.vanced.manager.ui.theme.LargeShape +import com.vanced.manager.ui.theme.MediumShape import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal import com.vanced.manager.ui.util.DefaultContentPaddingVertical @@ -21,48 +23,59 @@ import com.vanced.manager.ui.util.DefaultContentPaddingVertical fun BaseAppCard( appTitle: @Composable () -> Unit, appIcon: @Composable () -> Unit, + appTrailing: @Composable () -> Unit, appVersionsColumn: @Composable ColumnScope.() -> Unit, appActionsRow: @Composable RowScope.() -> Unit, ) { - ManagerThemedCard { - Column { - ManagerCard { - ManagerListItem( - modifier = Modifier.padding( - horizontal = DefaultContentPaddingHorizontal, - vertical = DefaultContentPaddingVertical - ), - title = appTitle, - icon = appIcon - ) - } - CompositionLocalProvider( - LocalContentColor provides MaterialTheme.colors.onSurface + ManagerTonalCard( + modifier = Modifier.fillMaxWidth(), + shape = LargeShape, + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding( + horizontal = DefaultContentPaddingHorizontal, + vertical = DefaultContentPaddingVertical + ), + verticalArrangement = Arrangement + .spacedBy(DefaultContentPaddingVertical) + ) { + ManagerListItem( + modifier = Modifier.fillMaxWidth(), + title = appTitle, + icon = appIcon, + trailing = appTrailing + ) + Divider( + modifier = Modifier + .fillMaxWidth() + .clip(MediumShape), + thickness = 2.dp, + color = LocalContentColor.current.copy(alpha = 0.12f) + ) + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween ) { - Row( - modifier = Modifier.padding( - horizontal = DefaultContentPaddingHorizontal, - vertical = 8.dp - ), - verticalAlignment = Alignment.CenterVertically, + Column( + modifier = Modifier.wrapContentWidth(), + verticalArrangement = Arrangement.spacedBy(4.dp), + horizontalAlignment = Alignment.Start ) { - Column( - modifier = Modifier - .weight(1f) - .wrapContentWidth(Alignment.Start), - verticalArrangement = Arrangement.spacedBy(4.dp) - ) { - ManagerText(stringResource(id = R.string.app_versions)) - appVersionsColumn() - } - Row( - modifier = Modifier - .weight(1f) - .padding(start = 4.dp) - .wrapContentWidth(Alignment.End), - content = appActionsRow + ManagerText( + text = stringResource(id = R.string.app_versions), + textStyle = MaterialTheme.typography.bodyMedium ) + appVersionsColumn() } + Row( + modifier = Modifier.wrapContentWidth(), + content = appActionsRow, + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.End + ) } } } diff --git a/app/src/main/java/com/vanced/manager/ui/widget/checkbox/ManagerAnimatedCheckbox.kt b/app/src/main/java/com/vanced/manager/ui/widget/checkbox/ManagerAnimatedCheckbox.kt index 4385dc5178..d58890e687 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/checkbox/ManagerAnimatedCheckbox.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/checkbox/ManagerAnimatedCheckbox.kt @@ -2,7 +2,6 @@ package com.vanced.manager.ui.widget.checkbox import androidx.compose.animation.core.updateTransition import androidx.compose.foundation.layout.size -import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier @@ -10,12 +9,13 @@ import androidx.compose.ui.graphics.Shape import androidx.compose.ui.unit.Dp import com.vanced.manager.ui.component.animation.jumpAnimation import com.vanced.manager.ui.component.checkbox.ManagerCheckbox +import com.vanced.manager.ui.theme.MediumShape @Composable fun ManagerAnimatedCheckbox( size: Dp, isChecked: Boolean, - shape: Shape = MaterialTheme.shapes.medium, + shape: Shape = MediumShape, onCheckedChange: (isChecked: Boolean) -> Unit, ) { val transition = updateTransition( diff --git a/app/src/main/java/com/vanced/manager/ui/widget/layout/CategoryLayout.kt b/app/src/main/java/com/vanced/manager/ui/widget/layout/CategoryLayout.kt index f314532c52..3ad5489eb2 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/layout/CategoryLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/layout/CategoryLayout.kt @@ -1,29 +1,73 @@ package com.vanced.manager.ui.widget.layout import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyItemScope +import androidx.compose.foundation.lazy.LazyListScope +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.Dp -import com.vanced.manager.ui.component.text.CategoryTitleText +import com.vanced.manager.ui.component.color.managerAnimatedColor +import com.vanced.manager.ui.component.text.ManagerText import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal import com.vanced.manager.ui.util.DefaultContentPaddingVertical @Composable fun CategoryLayout( categoryName: String, - contentPaddingHorizontal: Dp = DefaultContentPaddingHorizontal, - categoryNameSpacing: Dp = DefaultContentPaddingVertical, - content: @Composable () -> Unit, + modifier: Modifier = Modifier, + content: @Composable ColumnScope.() -> Unit, ) { Column( - modifier = Modifier.fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(categoryNameSpacing), + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(DefaultContentPaddingVertical) ) { - CategoryTitleText(text = categoryName) - Box( - modifier = Modifier.padding(horizontal = contentPaddingHorizontal) - ) { - content() - } + ManagerText( + modifier = Modifier.padding(start = DefaultContentPaddingHorizontal), + text = categoryName, + textStyle = MaterialTheme.typography.headlineSmall, + color = managerAnimatedColor(MaterialTheme.colorScheme.onSurface) + ) + content() } -} \ No newline at end of file +} + +fun <T> LazyListScope.managerCategory( + categoryName: String, + items: List<T>, + itemContent: @Composable (T) -> Unit +) { + item { + ManagerText( + modifier = Modifier.padding( + horizontal = DefaultContentPaddingHorizontal, + vertical = DefaultContentPaddingVertical + ), + text = categoryName, + textStyle = MaterialTheme.typography.headlineSmall, + color = managerAnimatedColor(MaterialTheme.colorScheme.onSurface) + ) + } + items(items) { item -> + itemContent(item) + } +} + +fun LazyListScope.managerCategory( + categoryName: String, + content: @Composable LazyItemScope.() -> Unit, +) { + item { + ManagerText( + modifier = Modifier + .padding( + horizontal = DefaultContentPaddingHorizontal, + vertical = DefaultContentPaddingVertical + ), + text = categoryName, + textStyle = MaterialTheme.typography.headlineSmall, + color = managerAnimatedColor(MaterialTheme.colorScheme.onSurface) + ) + } + item(content = content) +} diff --git a/app/src/main/java/com/vanced/manager/ui/widget/layout/SettingsCategoryLayout.kt b/app/src/main/java/com/vanced/manager/ui/widget/layout/SettingsCategoryLayout.kt index 411c2c025f..d8235f93e3 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/layout/SettingsCategoryLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/layout/SettingsCategoryLayout.kt @@ -11,8 +11,6 @@ fun SettingsCategoryLayout( ) { CategoryLayout( categoryName = categoryName, - contentPaddingHorizontal = 0.dp, - categoryNameSpacing = 4.dp ) { Column { content() diff --git a/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt index cb2c60375f..afdd6c6988 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt @@ -1,7 +1,7 @@ package com.vanced.manager.ui.widget.list import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material.Text +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp diff --git a/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt index afdc156325..5e0db75221 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt @@ -1,8 +1,7 @@ package com.vanced.manager.ui.widget.list -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material.Text +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp diff --git a/app/src/main/java/com/vanced/manager/ui/widget/radiobutton/ManagerAnimatedRadiobutton.kt b/app/src/main/java/com/vanced/manager/ui/widget/radiobutton/ManagerAnimatedRadiobutton.kt index b3fb64c071..d7abf257a4 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/radiobutton/ManagerAnimatedRadiobutton.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/radiobutton/ManagerAnimatedRadiobutton.kt @@ -2,7 +2,6 @@ package com.vanced.manager.ui.widget.radiobutton import androidx.compose.animation.core.updateTransition import androidx.compose.foundation.layout.size -import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier @@ -10,12 +9,13 @@ import androidx.compose.ui.graphics.Shape import androidx.compose.ui.unit.Dp import com.vanced.manager.ui.component.animation.jumpAnimation import com.vanced.manager.ui.component.radiobutton.ManagerRadiobutton +import com.vanced.manager.ui.theme.MediumShape @Composable fun ManagerAnimatedRadiobutton( size: Dp, isSelected: Boolean, - shape: Shape = MaterialTheme.shapes.medium, + shape: Shape = MediumShape, onClick: () -> Unit ) { val transition = updateTransition( diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt index d93c27576c..eae4feecd6 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt @@ -13,29 +13,29 @@ import com.vanced.manager.ui.widget.button.ManagerSaveButton @Composable fun SettingsAccentColorItem() { - var localAccentColor by remember { mutableStateOf(managerAccentColorPref.value.value) } - DialogPreference( - preferenceTitle = managerString( - stringId = R.string.settings_preference_accent_color_title - ), - preferenceDescription = "#" + Integer.toHexString(localAccentColor.toInt()), - buttons = { isShown -> - ManagerResetButton( - backgroundColor = Color(localAccentColor) - ) { - isShown.value = false - managerAccentColorPref.save(defAccentColor) - } - ManagerSaveButton( - backgroundColor = Color(localAccentColor) - ) { - isShown.value = false - managerAccentColorPref.save(localAccentColor) - } - } - ) { - ManagerColorPicker { - localAccentColor = it - } - } +// var localAccentColor by remember { mutableStateOf(managerAccentColorPref.value.value) } +// DialogPreference( +// preferenceTitle = managerString( +// stringId = R.string.settings_preference_accent_color_title +// ), +// preferenceDescription = "#" + Integer.toHexString(localAccentColor.toInt()), +// buttons = { isShown -> +// ManagerResetButton( +// backgroundColor = Color(localAccentColor) +// ) { +// isShown.value = false +// managerAccentColorPref.save(defAccentColor) +// } +// ManagerSaveButton( +// backgroundColor = Color(localAccentColor) +// ) { +// isShown.value = false +// managerAccentColorPref.save(localAccentColor) +// } +// } +// ) { +// ManagerColorPicker { +// localAccentColor = it +// } +// } } \ No newline at end of file From 8b8232b81601a070f093dd58dc08c3687b17c390 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 7 Nov 2021 19:52:17 +0400 Subject: [PATCH 068/118] remove progress indicator from installation preferences screen --- .../ui/screens/InstallPreferencesScreen.kt | 29 ++++++++----------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt b/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt index 1424bdc03e..8d2b1ab333 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt @@ -46,24 +46,19 @@ fun InstallPreferencesScreen( ManagerScaffold( topBar = { - Column { - ManagerTopAppBar( - title = managerString(R.string.toolbar_installation_preferences), - navigationIcon = { - IconButton( - onClick = onToolbarBackButtonClick - ) { - Icon( - imageVector = Icons.Rounded.ArrowBackIosNew, - contentDescription = "Back" - ) - } + ManagerTopAppBar( + title = managerString(R.string.toolbar_installation_preferences), + navigationIcon = { + IconButton( + onClick = onToolbarBackButtonClick + ) { + Icon( + imageVector = Icons.Rounded.ArrowBackIosNew, + contentDescription = "Back" + ) } - ) - ManagerProgressIndicator( - progress = (currentOptionIndex + 1).toFloat() / installationOptions.size.toFloat() - ) - } + } + ) }, ) { paddingValues -> Column( From 25baeb003177239ed4f5aa946155cc8938017988 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 7 Nov 2021 19:53:06 +0400 Subject: [PATCH 069/118] update strings --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fe9274372b..e95a8e7fd7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -72,7 +72,7 @@ <string name="toolbar_logs">Logs</string> <string name="toolbar_settings">Settings</string> <string name="toolbar_install">Install</string> - <string name="toolbar_installation_preferences">Installation Preferences</string> + <string name="toolbar_installation_preferences">Configuration</string> <string name="toolbar_update_manager">Update Manager</string> <!-- App Card --> From a162a7162997a98151c7d66a3be4e6d3b8c36355 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 9 Nov 2021 11:45:44 +0400 Subject: [PATCH 070/118] update compose --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 36c1d36d13..9d5afd4657 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -84,7 +84,7 @@ dependencies { implementation("com.google.android.material:material:1.4.0") implementation("androidx.browser:browser:1.3.0") - val composeVersion = "1.1.0-beta01" + val composeVersion = "1.1.0-beta02" implementation("androidx.compose.compiler:compiler:$composeVersion") implementation("androidx.compose.foundation:foundation:$composeVersion") implementation("androidx.compose.material:material-icons-core:$composeVersion") From afd5bfef36d04b3e4500dd1d5180f7d5fbb6000d Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 9 Nov 2021 11:46:09 +0400 Subject: [PATCH 071/118] fixed app redownloading on configuration change --- .../ui/screens/InstallPreferencesScreen.kt | 1 - .../manager/ui/screens/InstallScreen.kt | 29 +++++++++++++++---- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt b/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt index 8d2b1ab333..f185901618 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt @@ -23,7 +23,6 @@ import com.vanced.manager.domain.model.InstallationOption import com.vanced.manager.ui.component.card.ManagerTonalCard import com.vanced.manager.ui.component.layout.ManagerLazyColumn import com.vanced.manager.ui.component.layout.ManagerScaffold -import com.vanced.manager.ui.component.progressindicator.ManagerProgressIndicator import com.vanced.manager.ui.component.text.ManagerText import com.vanced.manager.ui.component.topappbar.ManagerTopAppBar import com.vanced.manager.ui.resources.managerString diff --git a/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt b/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt index c125b8ba6b..be6017d89e 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt @@ -7,10 +7,10 @@ import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.ArrowDropDown -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme +import androidx.compose.material.icons.rounded.Done +import androidx.compose.material3.* import androidx.compose.runtime.* +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate @@ -43,7 +43,16 @@ fun InstallScreen( ) { val viewModel: InstallViewModel = getViewModel() - viewModel.startAppProcess(appName, appVersions) + var startedProcess by rememberSaveable { mutableStateOf(false) } + + // I don't know why, I don't know how, + // but it works as intended + LaunchedEffect(startedProcess) { + if (!startedProcess) { + startedProcess = true + viewModel.startAppProcess(appName, appVersions) + } + } ManagerScaffold( topBar = { @@ -63,12 +72,20 @@ fun InstallScreen( } }, floatingActionButton = { - + if (viewModel.status is InstallViewModel.Status.Installed) { + ExtendedFloatingActionButton( + text = { /*TODO*/ }, + icon = { + Icon(Icons.Rounded.Done, null) + }, + onClick = { /*TODO*/ }, + ) + } } ) { paddingValues -> ManagerLazyColumn( modifier = Modifier - .fillMaxWidth() + .fillMaxSize() .padding(paddingValues), ) { items(viewModel.logs) { log -> From f3913478154a8b714890b7125d350f2d43a8d7cb Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Wed, 10 Nov 2021 15:54:07 +0400 Subject: [PATCH 072/118] adjust link icon size --- .../com/vanced/manager/ui/component/card/ManagerItemCard.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerItemCard.kt b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerItemCard.kt index 2869da1c7e..70537848ea 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerItemCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerItemCard.kt @@ -62,7 +62,7 @@ private fun ManagerItemCardContent( if (icon != null) { Icon( modifier = Modifier - .size(36.dp), + .size(32.dp), painter = painterResource(id = icon), contentDescription = title, ) From 86e1a30c945fb098b9e8fc7726b6963d62ed44e9 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Wed, 10 Nov 2021 15:54:16 +0400 Subject: [PATCH 073/118] update icons --- app/src/main/res/drawable/ic_adguard.xml | 2 +- app/src/main/res/drawable/ic_brave.xml | 2 +- app/src/main/res/drawable/ic_discord.xml | 15 +++++++-------- app/src/main/res/drawable/ic_github.xml | 2 +- app/src/main/res/drawable/ic_instagram.xml | 2 +- app/src/main/res/drawable/ic_reddit.xml | 2 +- app/src/main/res/drawable/ic_telegram.xml | 2 +- app/src/main/res/drawable/ic_twitter.xml | 2 +- app/src/main/res/drawable/ic_youtube.xml | 2 +- 9 files changed, 15 insertions(+), 16 deletions(-) diff --git a/app/src/main/res/drawable/ic_adguard.xml b/app/src/main/res/drawable/ic_adguard.xml index f22d9c6d59..82500b4027 100644 --- a/app/src/main/res/drawable/ic_adguard.xml +++ b/app/src/main/res/drawable/ic_adguard.xml @@ -5,5 +5,5 @@ android:viewportHeight="24"> <path android:fillColor="#FF000000" - android:pathData="M11.7,2.1c3.6,0.1 6.7,0.7 9.7,2.1c0.3,0.1 0.4,0.3 0.4,0.6c0,3.2 -0.5,6.3 -1.9,9.2c-1.7,3.4 -4.3,6 -7.5,7.9c-0.1,0.1 -0.3,0.1 -0.4,0c-4.8,-3 -8.1,-7.1 -9.1,-12.7c-0.3,-1.5 -0.2,-3 -0.4,-4.5c0,-0.3 0.1,-0.4 0.3,-0.5c2,-1 4.2,-1.6 6.4,-1.9C10.1,2.2 11.1,2.1 11.7,2.1zM7.6,10.5c1.4,1.7 2.8,3.3 4.2,5c2,-2.7 3.9,-5.3 5.8,-7.9c-0.5,-0.3 -0.7,-0.2 -1.2,0.2c-1.5,1.6 -3,3.1 -4.4,4.7c-0.1,0.1 -0.2,0.2 -0.3,0.3c-0.6,-0.7 -1.1,-1.4 -1.7,-2.1C9.3,9.8 8.4,9.8 7.6,10.5z"/> + android:pathData="M12,0C8.249,0 3.725,0.861 0,2.755 0,6.845 -0.051,17.037 12,24 24.051,17.037 24,6.845 24,2.755 20.275,0.861 15.751,0 12,0zM11.894,15.429L6.857,9.612c0.331,-0.239 1.75,-1.143 2.794,0.042l2.187,2.588c0.009,-0.001 5.801,-5.948 5.815,-5.938 0.246,-0.22 0.694,-0.503 1.204,-0.101l-6.963,9.226z"/> </vector> diff --git a/app/src/main/res/drawable/ic_brave.xml b/app/src/main/res/drawable/ic_brave.xml index 536c6d03e2..32308d5525 100644 --- a/app/src/main/res/drawable/ic_brave.xml +++ b/app/src/main/res/drawable/ic_brave.xml @@ -5,5 +5,5 @@ android:viewportHeight="24"> <path android:fillColor="#FF000000" - android:pathData="M5.4,2.7c0.3,0 0.6,0.1 1,0.1c0,0 0.1,0 0.1,0c0.6,-0.7 1.2,-1.4 1.8,-2.1c0.1,-0.1 0.2,-0.1 0.3,-0.1c2.2,0 4.4,0 6.7,0c0.3,0 0.4,0.1 0.6,0.3c0.4,0.4 0.7,0.8 1.1,1.3c0.2,0.2 0.4,0.5 0.6,0.7c0,0 0.1,0.1 0.2,0c0.5,-0.1 1,-0.2 1.5,-0.1c0.4,0.1 0.8,0.2 1.2,0.5c0.3,0.4 0.7,0.7 1,1c0.1,0.1 0.2,0.2 0.4,0.4c0.1,0.1 0.1,0.1 0,0.2c-0.2,0.4 -0.3,0.7 -0.5,1.1c0,0.1 0,0.2 0,0.3c0.2,0.6 0.4,1.1 0.6,1.7c0,0.1 0,0.2 0,0.3c-0.1,0.4 -0.2,0.9 -0.3,1.3c-0.5,1.8 -0.9,3.5 -1.4,5.3c-0.3,1 -0.5,2 -0.8,3c-0.1,0.5 -0.3,0.9 -0.6,1.3c-0.3,0.3 -0.6,0.7 -1,0.9c-0.6,0.4 -1.2,0.8 -1.8,1.2c-0.5,0.3 -1,0.7 -1.5,1c-0.5,0.3 -1,0.7 -1.5,1c-0.2,0.1 -0.4,0.2 -0.6,0.3c-0.2,0.1 -0.5,0.1 -0.7,0c-0.2,-0.1 -0.4,-0.2 -0.5,-0.3c-0.8,-0.6 -1.7,-1.1 -2.5,-1.7c-0.5,-0.3 -1,-0.6 -1.4,-1c-0.4,-0.3 -0.8,-0.6 -1.2,-0.8c-0.7,-0.5 -1.1,-1.3 -1.4,-2.2c-0.1,-0.4 -0.2,-0.8 -0.3,-1.2c-0.3,-1.2 -0.6,-2.3 -1,-3.5c-0.2,-0.7 -0.4,-1.4 -0.5,-2.1C2.6,9.9 2.4,9 2.1,8.2c0,-0.1 0,-0.2 0,-0.3c0.2,-0.6 0.4,-1.1 0.6,-1.6c0,-0.1 0,-0.2 0,-0.3C2.6,5.6 2.4,5.2 2.3,4.9c0,-0.1 0,-0.1 0,-0.2c0.5,-0.5 1,-1 1.5,-1.5c0.3,-0.3 0.6,-0.3 1,-0.4C5,2.7 5.1,2.7 5.4,2.7zM6.7,6.7C6.7,6.7 6.7,6.7 6.7,6.7C6.8,6.7 6.9,6.6 7,6.6c0.3,0 0.5,-0.1 0.8,-0.1c0.4,0 0.9,-0.1 1.3,0c0.5,0.1 1.1,0.3 1.6,0.4C11,7.1 11.1,7.2 11,7.5c-0.1,0.7 -0.3,1.4 -0.4,2.1c-0.1,0.4 -0.1,0.7 -0.2,1.1c0,0.2 0.1,0.3 0.3,0.4c0.3,0.1 0.6,0.1 1,0.2c0.2,0 0.4,0 0.5,0c0.4,-0.1 0.8,-0.1 1.1,-0.2c0.3,-0.1 0.3,-0.2 0.3,-0.4c-0.1,-0.5 -0.2,-1 -0.2,-1.5c-0.1,-0.6 -0.2,-1.2 -0.3,-1.7c0,-0.3 0,-0.4 0.3,-0.5c0.2,-0.1 0.4,-0.1 0.6,-0.2c0.6,-0.2 1.1,-0.3 1.7,-0.3c0.5,0 0.9,0.1 1.4,0.1c0.1,0 0.2,0 0.2,0.1c0,0 0,0 0,0c0,0 -0.1,0 -0.1,0.1c-1,0.4 -1.9,0.7 -2.9,1.1C14,8 13.8,8.4 13.9,8.7c0.1,0.4 0.3,0.7 0.4,1c0.2,0.3 0.4,0.6 0.5,0.9c0.1,0.3 0.1,0.4 -0.2,0.6c-0.4,0.3 -0.8,0.5 -1.2,0.8c-0.3,0.2 -0.7,0.4 -1,0.7c-0.2,0.2 -0.2,0.3 0,0.5c0.2,0.2 0.4,0.4 0.6,0.6c0.7,0.6 1.5,1 2.3,1.4c0.3,0.1 0.5,0.1 0.7,-0.1c0.3,-0.2 0.6,-0.5 0.8,-0.8c0.2,-0.4 0.3,-0.8 0.2,-1.2c-0.1,-0.3 -0.2,-0.5 -0.3,-0.8c-0.1,-0.3 -0.1,-0.6 0.2,-0.9c0.1,-0.1 0.3,-0.2 0.4,-0.4c0.7,-0.7 1.3,-1.4 2,-2.1c0.4,-0.4 0.5,-0.9 0.2,-1.4c-0.3,-0.5 -0.6,-0.9 -1,-1.4c-0.4,-0.6 -0.8,-1.1 -1.3,-1.7c-0.1,-0.1 -0.1,-0.2 -0.3,-0.2c-0.6,0.1 -1.2,0.2 -1.8,0.3c-0.4,0.1 -0.8,0.1 -1.2,0c-0.3,-0.1 -0.6,-0.2 -0.9,-0.3c-0.6,-0.2 -1.2,-0.3 -1.8,-0.1c-0.4,0.1 -0.7,0.2 -1.1,0.4C9.9,4.6 9.6,4.7 9.3,4.7C8.6,4.6 7.9,4.4 7.1,4.3c-0.1,0 -0.2,0 -0.3,0.1C6.4,4.9 6,5.4 5.6,5.9C5.2,6.5 4.9,7.1 4.5,7.6c-0.3,0.5 -0.1,1 0.2,1.3c0.5,0.6 1.1,1.1 1.6,1.7c0.3,0.3 0.6,0.6 0.8,0.9c0.2,0.2 0.3,0.5 0.2,0.8c0,0.1 -0.1,0.2 -0.1,0.3C7.1,12.8 7,13 7,13.3c-0.1,0.3 0,0.7 0.2,1c0.2,0.3 0.4,0.6 0.7,0.8c0.3,0.2 0.6,0.3 1,0.1c0.4,-0.2 0.7,-0.3 1.1,-0.5c0.7,-0.3 1.2,-0.8 1.7,-1.4c0.2,-0.3 0.2,-0.4 0,-0.6c0,0 -0.1,-0.1 -0.1,-0.1c-0.3,-0.2 -0.6,-0.4 -0.9,-0.6c-0.4,-0.3 -0.8,-0.5 -1.2,-0.8c-0.3,-0.2 -0.3,-0.3 -0.2,-0.7c0.1,-0.3 0.3,-0.6 0.5,-0.9c0.2,-0.3 0.3,-0.6 0.4,-0.9c0.1,-0.2 0.1,-0.4 -0.1,-0.6C9.9,8 9.8,7.9 9.7,7.9C8.8,7.6 8,7.2 7.1,6.9C7,6.9 6.8,6.8 6.7,6.7zM12.1,14.8c-0.1,0 -0.1,0 -0.1,0c-0.2,0.1 -0.5,0.1 -0.7,0.2c-0.7,0.3 -1.4,0.7 -2.2,1.1c-0.2,0.1 -0.2,0.3 0,0.4c0,0 0.1,0.1 0.1,0.1c0.5,0.4 1,0.7 1.5,1.1c0.4,0.3 0.8,0.6 1.2,0.9c0.3,0.2 0.4,0.2 0.6,0c0.2,-0.2 0.4,-0.3 0.6,-0.5c0.7,-0.5 1.4,-1.1 2.1,-1.6c0.3,-0.2 0.2,-0.3 0,-0.5c-0.3,-0.2 -0.6,-0.3 -0.9,-0.5c-0.5,-0.2 -1,-0.5 -1.6,-0.7C12.4,14.9 12.2,14.9 12.1,14.8z"/> + android:pathData="M15.68,0l2.096,2.38s1.84,-0.512 2.709,0.358c0.868,0.87 1.584,1.638 1.584,1.638l-0.562,1.381 0.715,2.047s-2.104,7.98 -2.35,8.955c-0.486,1.919 -0.818,2.66 -2.198,3.633 -1.38,0.972 -3.884,2.66 -4.293,2.916 -0.409,0.256 -0.92,0.692 -1.38,0.692 -0.46,0 -0.97,-0.436 -1.38,-0.692a185.796,185.796 0,0 1,-4.293 -2.916c-1.38,-0.973 -1.712,-1.714 -2.197,-3.633 -0.247,-0.975 -2.351,-8.955 -2.351,-8.955l0.715,-2.047 -0.562,-1.381s0.716,-0.768 1.585,-1.638c0.868,-0.87 2.708,-0.358 2.708,-0.358L8.321,0h7.36zM12.001,14.936c-0.14,0 -1.038,0.317 -1.758,0.69 -0.72,0.373 -1.242,0.637 -1.409,0.742 -0.167,0.104 -0.065,0.301 0.087,0.409 0.152,0.107 2.194,1.69 2.393,1.866 0.198,0.175 0.489,0.464 0.687,0.464 0.198,0 0.49,-0.29 0.688,-0.464 0.198,-0.175 2.24,-1.759 2.392,-1.866 0.152,-0.108 0.254,-0.305 0.087,-0.41 -0.167,-0.104 -0.689,-0.368 -1.41,-0.741 -0.72,-0.373 -1.617,-0.69 -1.757,-0.69zM12.001,3.658s-0.409,0.001 -1.022,0.206 -1.278,0.46 -1.584,0.46c-0.307,0 -2.581,-0.434 -2.581,-0.434S4.119,7.152 4.119,7.849c0,0.697 0.339,0.881 0.68,1.243l2.02,2.149c0.192,0.203 0.59,0.511 0.356,1.066 -0.235,0.555 -0.58,1.26 -0.196,1.977 0.384,0.716 1.042,1.194 1.464,1.115 0.421,-0.08 1.412,-0.598 1.776,-0.834 0.364,-0.237 1.518,-1.19 1.518,-1.554 0,-0.365 -1.193,-1.02 -1.413,-1.168 -0.22,-0.15 -1.226,-0.725 -1.247,-0.95 -0.02,-0.227 -0.012,-0.293 0.284,-0.851 0.297,-0.559 0.831,-1.304 0.742,-1.8 -0.089,-0.495 -0.95,-0.753 -1.565,-0.986 -0.615,-0.232 -1.799,-0.671 -1.947,-0.74 -0.148,-0.068 -0.11,-0.133 0.339,-0.175 0.448,-0.043 1.719,-0.212 2.292,-0.052 0.573,0.16 1.552,0.403 1.632,0.532 0.079,0.13 0.149,0.134 0.067,0.579 -0.081,0.445 -0.5,2.581 -0.541,2.96 -0.04,0.38 -0.12,0.63 0.288,0.724 0.409,0.094 1.097,0.256 1.333,0.256s0.924,-0.162 1.333,-0.256c0.408,-0.093 0.329,-0.344 0.288,-0.723 -0.04,-0.38 -0.46,-2.516 -0.541,-2.961 -0.082,-0.445 -0.012,-0.45 0.067,-0.579 0.08,-0.129 1.059,-0.372 1.632,-0.532 0.573,-0.16 1.845,0.009 2.292,0.052 0.449,0.042 0.487,0.107 0.339,0.175 -0.148,0.069 -1.332,0.508 -1.947,0.74 -0.615,0.233 -1.476,0.49 -1.565,0.986 -0.09,0.496 0.445,1.241 0.742,1.8 0.297,0.558 0.304,0.624 0.284,0.85 -0.02,0.226 -1.026,0.802 -1.247,0.95 -0.22,0.15 -1.413,0.804 -1.413,1.169 0,0.364 1.154,1.317 1.518,1.554 0.364,0.236 1.355,0.755 1.776,0.834 0.422,0.079 1.08,-0.4 1.464,-1.115 0.384,-0.716 0.039,-1.422 -0.195,-1.977 -0.235,-0.555 0.163,-0.863 0.355,-1.066l2.02,-2.149c0.341,-0.362 0.68,-0.546 0.68,-1.243 0,-0.697 -2.695,-3.96 -2.695,-3.96s-2.274,0.436 -2.58,0.436c-0.307,0 -0.972,-0.256 -1.585,-0.461 -0.613,-0.205 -1.022,-0.206 -1.022,-0.206z"/> </vector> diff --git a/app/src/main/res/drawable/ic_discord.xml b/app/src/main/res/drawable/ic_discord.xml index 9dc3b8c15e..30f69d3645 100644 --- a/app/src/main/res/drawable/ic_discord.xml +++ b/app/src/main/res/drawable/ic_discord.xml @@ -1,10 +1,9 @@ -<vector - android:height="18.591549dp" - android:viewportHeight="55" - android:viewportWidth="71" +<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" - xmlns:android="http://schemas.android.com/apk/res/android"> - <path - android:fillColor="#FF000000" - android:pathData="M60.1045,4.8978C55.5792,2.8214 50.7265,1.2916 45.6527,0.4154C45.5603,0.3985 45.468,0.4408 45.4204,0.5253C44.7963,1.6353 44.105,3.0834 43.6209,4.2216C38.1637,3.4046 32.7345,3.4046 27.3892,4.2216C26.905,3.0581 26.1886,1.6353 25.5617,0.5253C25.5141,0.4436 25.4218,0.4013 25.3294,0.4154C20.2584,1.2888 15.4057,2.8186 10.8776,4.8978C10.8384,4.9147 10.8048,4.9429 10.7825,4.9795C1.578,18.7309 -0.9436,32.1443 0.2934,45.3914C0.299,45.4562 0.3354,45.5182 0.3858,45.5576C6.4587,50.0174 12.3413,52.7249 18.1147,54.5195C18.2071,54.5477 18.305,54.5139 18.3638,54.4378C19.7295,52.5728 20.9469,50.6063 21.9907,48.5383C22.0523,48.4172 21.9935,48.2735 21.8676,48.2256C19.9366,47.4931 18.0979,46.6 16.3292,45.5858C16.1893,45.5041 16.1781,45.304 16.3068,45.2082C16.679,44.9293 17.0513,44.6391 17.4067,44.3461C17.471,44.2926 17.5606,44.2813 17.6362,44.3151C29.2558,49.6202 41.8354,49.6202 53.3179,44.3151C53.3935,44.2785 53.4831,44.2898 53.5502,44.3433C53.9057,44.6363 54.2779,44.9293 54.6529,45.2082C54.7816,45.304 54.7732,45.5041 54.6333,45.5858C52.8646,46.6197 51.0259,47.4931 49.0921,48.2228C48.9662,48.2707 48.9102,48.4172 48.9718,48.5383C50.038,50.6034 51.2554,52.5699 52.5959,54.435C52.6519,54.5139 52.7526,54.5477 52.845,54.5195C58.6464,52.7249 64.529,50.0174 70.6019,45.5576C70.6551,45.5182 70.6887,45.459 70.6943,45.3942C72.1747,30.0791 68.2147,16.7757 60.1968,4.9823C60.1772,4.9429 60.1437,4.9147 60.1045,4.8978ZM23.7259,37.3253C20.2276,37.3253 17.3451,34.1136 17.3451,30.1693C17.3451,26.225 20.1717,23.0133 23.7259,23.0133C27.308,23.0133 30.1626,26.2532 30.1066,30.1693C30.1066,34.1136 27.28,37.3253 23.7259,37.3253ZM47.3178,37.3253C43.8196,37.3253 40.9371,34.1136 40.9371,30.1693C40.9371,26.225 43.7636,23.0133 47.3178,23.0133C50.9,23.0133 53.7545,26.2532 53.6986,30.1693C53.6986,34.1136 50.9,37.3253 47.3178,37.3253Z"/> + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="#FF000000" + android:pathData="M20.317,4.3698a19.7913,19.7913 0,0 0,-4.8851 -1.5152,0.0741 0.0741,0 0,0 -0.0785,0.0371c-0.211,0.3753 -0.4447,0.8648 -0.6083,1.2495 -1.8447,-0.2762 -3.68,-0.2762 -5.4868,0 -0.1636,-0.3933 -0.4058,-0.8742 -0.6177,-1.2495a0.077,0.077 0,0 0,-0.0785 -0.037,19.7363 19.7363,0 0,0 -4.8852,1.515 0.0699,0.0699 0,0 0,-0.0321 0.0277C0.5334,9.0458 -0.319,13.5799 0.0992,18.0578a0.0824,0.0824 0,0 0,0.0312 0.0561c2.0528,1.5076 4.0413,2.4228 5.9929,3.0294a0.0777,0.0777 0,0 0,0.0842 -0.0276c0.4616,-0.6304 0.8731,-1.2952 1.226,-1.9942a0.076,0.076 0,0 0,-0.0416 -0.1057c-0.6528,-0.2476 -1.2743,-0.5495 -1.8722,-0.8923a0.077,0.077 0,0 1,-0.0076 -0.1277c0.1258,-0.0943 0.2517,-0.1923 0.3718,-0.2914a0.0743,0.0743 0,0 1,0.0776 -0.0105c3.9278,1.7933 8.18,1.7933 12.0614,0a0.0739,0.0739 0,0 1,0.0785 0.0095c0.1202,0.099 0.246,0.1981 0.3728,0.2924a0.077,0.077 0,0 1,-0.0066 0.1276,12.2986 12.2986,0 0,1 -1.873,0.8914 0.0766,0.0766 0,0 0,-0.0407 0.1067c0.3604,0.698 0.7719,1.3628 1.225,1.9932a0.076,0.076 0,0 0,0.0842 0.0286c1.961,-0.6067 3.9495,-1.5219 6.0023,-3.0294a0.077,0.077 0,0 0,0.0313 -0.0552c0.5004,-5.177 -0.8382,-9.6739 -3.5485,-13.6604a0.061,0.061 0,0 0,-0.0312 -0.0286zM8.02,15.3312c-1.1825,0 -2.1569,-1.0857 -2.1569,-2.419 0,-1.3332 0.9555,-2.4189 2.157,-2.4189 1.2108,0 2.1757,1.0952 2.1568,2.419 0,1.3332 -0.9555,2.4189 -2.1569,2.4189zM15.9948,15.3312c-1.1825,0 -2.1569,-1.0857 -2.1569,-2.419 0,-1.3332 0.9554,-2.4189 2.1569,-2.4189 1.2108,0 2.1757,1.0952 2.1568,2.419 0,1.3332 -0.946,2.4189 -2.1568,2.4189Z"/> </vector> diff --git a/app/src/main/res/drawable/ic_github.xml b/app/src/main/res/drawable/ic_github.xml index 3e66680dd3..1305199291 100644 --- a/app/src/main/res/drawable/ic_github.xml +++ b/app/src/main/res/drawable/ic_github.xml @@ -5,5 +5,5 @@ android:viewportHeight="24"> <path android:fillColor="#FF000000" - android:pathData="M12,0c-6.626,0 -12,5.373 -12,12 0,5.302 3.438,9.8 8.207,11.387 0.599,0.111 0.793,-0.261 0.793,-0.577v-2.234c-3.338,0.726 -4.033,-1.416 -4.033,-1.416 -0.546,-1.387 -1.333,-1.756 -1.333,-1.756 -1.089,-0.745 0.083,-0.729 0.083,-0.729 1.205,0.084 1.839,1.237 1.839,1.237 1.07,1.834 2.807,1.304 3.492,0.997 0.107,-0.775 0.418,-1.305 0.762,-1.604 -2.665,-0.305 -5.467,-1.334 -5.467,-5.931 0,-1.311 0.469,-2.381 1.236,-3.221 -0.124,-0.303 -0.535,-1.524 0.117,-3.176 0,0 1.008,-0.322 3.301,1.23 0.957,-0.266 1.983,-0.399 3.003,-0.404 1.02,0.005 2.047,0.138 3.006,0.404 2.291,-1.552 3.297,-1.23 3.297,-1.23 0.653,1.653 0.242,2.874 0.118,3.176 0.77,0.84 1.235,1.911 1.235,3.221 0,4.609 -2.807,5.624 -5.479,5.921 0.43,0.372 0.823,1.102 0.823,2.222v3.293c0,0.319 0.192,0.694 0.801,0.576 4.765,-1.589 8.199,-6.086 8.199,-11.386 0,-6.627 -5.373,-12 -12,-12z"/> + android:pathData="M12,0.297c-6.63,0 -12,5.373 -12,12 0,5.303 3.438,9.8 8.205,11.385 0.6,0.113 0.82,-0.258 0.82,-0.577 0,-0.285 -0.01,-1.04 -0.015,-2.04 -3.338,0.724 -4.042,-1.61 -4.042,-1.61C4.422,18.07 3.633,17.7 3.633,17.7c-1.087,-0.744 0.084,-0.729 0.084,-0.729 1.205,0.084 1.838,1.236 1.838,1.236 1.07,1.835 2.809,1.305 3.495,0.998 0.108,-0.776 0.417,-1.305 0.76,-1.605 -2.665,-0.3 -5.466,-1.332 -5.466,-5.93 0,-1.31 0.465,-2.38 1.235,-3.22 -0.135,-0.303 -0.54,-1.523 0.105,-3.176 0,0 1.005,-0.322 3.3,1.23 0.96,-0.267 1.98,-0.399 3,-0.405 1.02,0.006 2.04,0.138 3,0.405 2.28,-1.552 3.285,-1.23 3.285,-1.23 0.645,1.653 0.24,2.873 0.12,3.176 0.765,0.84 1.23,1.91 1.23,3.22 0,4.61 -2.805,5.625 -5.475,5.92 0.42,0.36 0.81,1.096 0.81,2.22 0,1.606 -0.015,2.896 -0.015,3.286 0,0.315 0.21,0.69 0.825,0.57C20.565,22.092 24,17.592 24,12.297c0,-6.627 -5.373,-12 -12,-12"/> </vector> diff --git a/app/src/main/res/drawable/ic_instagram.xml b/app/src/main/res/drawable/ic_instagram.xml index 951f6a1bdb..ffbca436ec 100644 --- a/app/src/main/res/drawable/ic_instagram.xml +++ b/app/src/main/res/drawable/ic_instagram.xml @@ -5,5 +5,5 @@ android:viewportHeight="24"> <path android:fillColor="#FF000000" - android:pathData="M12,2.163c3.204,0 3.584,0.012 4.85,0.07 3.252,0.148 4.771,1.691 4.919,4.919 0.058,1.265 0.069,1.645 0.069,4.849 0,3.205 -0.012,3.584 -0.069,4.849 -0.149,3.225 -1.664,4.771 -4.919,4.919 -1.266,0.058 -1.644,0.07 -4.85,0.07 -3.204,0 -3.584,-0.012 -4.849,-0.07 -3.26,-0.149 -4.771,-1.699 -4.919,-4.92 -0.058,-1.265 -0.07,-1.644 -0.07,-4.849 0,-3.204 0.013,-3.583 0.07,-4.849 0.149,-3.227 1.664,-4.771 4.919,-4.919 1.266,-0.057 1.645,-0.069 4.849,-0.069zM12,0c-3.259,0 -3.667,0.014 -4.947,0.072 -4.358,0.2 -6.78,2.618 -6.98,6.98 -0.059,1.281 -0.073,1.689 -0.073,4.948 0,3.259 0.014,3.668 0.072,4.948 0.2,4.358 2.618,6.78 6.98,6.98 1.281,0.058 1.689,0.072 4.948,0.072 3.259,0 3.668,-0.014 4.948,-0.072 4.354,-0.2 6.782,-2.618 6.979,-6.98 0.059,-1.28 0.073,-1.689 0.073,-4.948 0,-3.259 -0.014,-3.667 -0.072,-4.947 -0.196,-4.354 -2.617,-6.78 -6.979,-6.98 -1.281,-0.059 -1.69,-0.073 -4.949,-0.073zM12,5.838c-3.403,0 -6.162,2.759 -6.162,6.162s2.759,6.163 6.162,6.163 6.162,-2.759 6.162,-6.163c0,-3.403 -2.759,-6.162 -6.162,-6.162zM12,16c-2.209,0 -4,-1.79 -4,-4 0,-2.209 1.791,-4 4,-4s4,1.791 4,4c0,2.21 -1.791,4 -4,4zM18.406,4.155c-0.796,0 -1.441,0.645 -1.441,1.44s0.645,1.44 1.441,1.44c0.795,0 1.439,-0.645 1.439,-1.44s-0.644,-1.44 -1.439,-1.44z"/> + android:pathData="M12,0C8.74,0 8.333,0.015 7.053,0.072 5.775,0.132 4.905,0.333 4.14,0.63c-0.789,0.306 -1.459,0.717 -2.126,1.384S0.935,3.35 0.63,4.14C0.333,4.905 0.131,5.775 0.072,7.053 0.012,8.333 0,8.74 0,12s0.015,3.667 0.072,4.947c0.06,1.277 0.261,2.148 0.558,2.913 0.306,0.788 0.717,1.459 1.384,2.126 0.667,0.666 1.336,1.079 2.126,1.384 0.766,0.296 1.636,0.499 2.913,0.558C8.333,23.988 8.74,24 12,24s3.667,-0.015 4.947,-0.072c1.277,-0.06 2.148,-0.262 2.913,-0.558 0.788,-0.306 1.459,-0.718 2.126,-1.384 0.666,-0.667 1.079,-1.335 1.384,-2.126 0.296,-0.765 0.499,-1.636 0.558,-2.913 0.06,-1.28 0.072,-1.687 0.072,-4.947s-0.015,-3.667 -0.072,-4.947c-0.06,-1.277 -0.262,-2.149 -0.558,-2.913 -0.306,-0.789 -0.718,-1.459 -1.384,-2.126C21.319,1.347 20.651,0.935 19.86,0.63c-0.765,-0.297 -1.636,-0.499 -2.913,-0.558C15.667,0.012 15.26,0 12,0zM12,2.16c3.203,0 3.585,0.016 4.85,0.071 1.17,0.055 1.805,0.249 2.227,0.415 0.562,0.217 0.96,0.477 1.382,0.896 0.419,0.42 0.679,0.819 0.896,1.381 0.164,0.422 0.36,1.057 0.413,2.227 0.057,1.266 0.07,1.646 0.07,4.85s-0.015,3.585 -0.074,4.85c-0.061,1.17 -0.256,1.805 -0.421,2.227 -0.224,0.562 -0.479,0.96 -0.899,1.382 -0.419,0.419 -0.824,0.679 -1.38,0.896 -0.42,0.164 -1.065,0.36 -2.235,0.413 -1.274,0.057 -1.649,0.07 -4.859,0.07 -3.211,0 -3.586,-0.015 -4.859,-0.074 -1.171,-0.061 -1.816,-0.256 -2.236,-0.421 -0.569,-0.224 -0.96,-0.479 -1.379,-0.899 -0.421,-0.419 -0.69,-0.824 -0.9,-1.38 -0.165,-0.42 -0.359,-1.065 -0.42,-2.235 -0.045,-1.26 -0.061,-1.649 -0.061,-4.844 0,-3.196 0.016,-3.586 0.061,-4.861 0.061,-1.17 0.255,-1.814 0.42,-2.234 0.21,-0.57 0.479,-0.96 0.9,-1.381 0.419,-0.419 0.81,-0.689 1.379,-0.898 0.42,-0.166 1.051,-0.361 2.221,-0.421 1.275,-0.045 1.65,-0.06 4.859,-0.06l0.045,0.03zM12,5.838c-3.405,0 -6.162,2.76 -6.162,6.162 0,3.405 2.76,6.162 6.162,6.162 3.405,0 6.162,-2.76 6.162,-6.162 0,-3.405 -2.76,-6.162 -6.162,-6.162zM12,16c-2.21,0 -4,-1.79 -4,-4s1.79,-4 4,-4 4,1.79 4,4 -1.79,4 -4,4zM19.846,5.595c0,0.795 -0.646,1.44 -1.44,1.44 -0.795,0 -1.44,-0.646 -1.44,-1.44 0,-0.794 0.646,-1.439 1.44,-1.439 0.793,-0.001 1.44,0.645 1.44,1.439z"/> </vector> diff --git a/app/src/main/res/drawable/ic_reddit.xml b/app/src/main/res/drawable/ic_reddit.xml index e11069eb2d..2d6d25f03d 100644 --- a/app/src/main/res/drawable/ic_reddit.xml +++ b/app/src/main/res/drawable/ic_reddit.xml @@ -5,5 +5,5 @@ android:viewportHeight="24"> <path android:fillColor="#FF000000" - android:pathData="M14.238,15.348c0.085,0.084 0.085,0.221 0,0.306 -0.465,0.462 -1.194,0.687 -2.231,0.687l-0.008,-0.002 -0.008,0.002c-1.036,0 -1.766,-0.225 -2.231,-0.688 -0.085,-0.084 -0.085,-0.221 0,-0.305 0.084,-0.084 0.222,-0.084 0.307,0 0.379,0.377 1.008,0.561 1.924,0.561l0.008,0.002 0.008,-0.002c0.915,0 1.544,-0.184 1.924,-0.561 0.085,-0.084 0.223,-0.084 0.307,0zM10.798,12.93c0,-0.507 -0.414,-0.919 -0.922,-0.919 -0.509,0 -0.923,0.412 -0.923,0.919 0,0.506 0.414,0.918 0.923,0.918 0.508,0.001 0.922,-0.411 0.922,-0.918zM24,12c0,6.627 -5.373,12 -12,12s-12,-5.373 -12,-12 5.373,-12 12,-12 12,5.373 12,12zM19,11.871c0,-0.851 -0.695,-1.543 -1.55,-1.543 -0.417,0 -0.795,0.167 -1.074,0.435 -1.056,-0.695 -2.485,-1.137 -4.066,-1.194l0.865,-2.724 2.343,0.549 -0.003,0.034c0,0.696 0.569,1.262 1.268,1.262 0.699,0 1.267,-0.566 1.267,-1.262s-0.568,-1.262 -1.267,-1.262c-0.537,0 -0.994,0.335 -1.179,0.804l-2.525,-0.592c-0.11,-0.027 -0.223,0.037 -0.257,0.145l-0.965,3.038c-1.656,0.02 -3.155,0.466 -4.258,1.181 -0.277,-0.255 -0.644,-0.415 -1.05,-0.415 -0.854,0.001 -1.549,0.693 -1.549,1.544 0,0.566 0.311,1.056 0.768,1.325 -0.03,0.164 -0.05,0.331 -0.05,0.5 0,2.281 2.805,4.137 6.253,4.137s6.253,-1.856 6.253,-4.137c0,-0.16 -0.017,-0.317 -0.044,-0.472 0.486,-0.261 0.82,-0.766 0.82,-1.353zM14.128,12.012c-0.509,0 -0.922,0.412 -0.922,0.919 0,0.506 0.414,0.918 0.922,0.918s0.922,-0.412 0.922,-0.918c0,-0.507 -0.413,-0.919 -0.922,-0.919z"/> + android:pathData="M12,0A12,12 0,0 0,0 12a12,12 0,0 0,12 12,12 12,0 0,0 12,-12A12,12 0,0 0,12 0zM17.01,4.744c0.688,0 1.25,0.561 1.25,1.249a1.25,1.25 0,0 1,-2.498 0.056l-2.597,-0.547 -0.8,3.747c1.824,0.07 3.48,0.632 4.674,1.488 0.308,-0.309 0.73,-0.491 1.207,-0.491 0.968,0 1.754,0.786 1.754,1.754 0,0.716 -0.435,1.333 -1.01,1.614a3.111,3.111 0,0 1,0.042 0.52c0,2.694 -3.13,4.87 -7.004,4.87 -3.874,0 -7.004,-2.176 -7.004,-4.87 0,-0.183 0.015,-0.366 0.043,-0.534A1.748,1.748 0,0 1,4.028 12c0,-0.968 0.786,-1.754 1.754,-1.754 0.463,0 0.898,0.196 1.207,0.49 1.207,-0.883 2.878,-1.43 4.744,-1.487l0.885,-4.182a0.342,0.342 0,0 1,0.14 -0.197,0.35 0.35,0 0,1 0.238,-0.042l2.906,0.617a1.214,1.214 0,0 1,1.108 -0.701zM9.25,12C8.561,12 8,12.562 8,13.25c0,0.687 0.561,1.248 1.25,1.248 0.687,0 1.248,-0.561 1.248,-1.249 0,-0.688 -0.561,-1.249 -1.249,-1.249zM14.75,12c-0.687,0 -1.248,0.561 -1.248,1.25 0,0.687 0.561,1.248 1.249,1.248 0.688,0 1.249,-0.561 1.249,-1.249 0,-0.687 -0.562,-1.249 -1.25,-1.249zM9.284,15.99a0.327,0.327 0,0 0,-0.231 0.094,0.33 0.33,0 0,0 0,0.463c0.842,0.842 2.484,0.913 2.961,0.913 0.477,0 2.105,-0.056 2.961,-0.913a0.361,0.361 0,0 0,0.029 -0.463,0.33 0.33,0 0,0 -0.464,0c-0.547,0.533 -1.684,0.73 -2.512,0.73 -0.828,0 -1.979,-0.196 -2.512,-0.73a0.326,0.326 0,0 0,-0.232 -0.095z"/> </vector> diff --git a/app/src/main/res/drawable/ic_telegram.xml b/app/src/main/res/drawable/ic_telegram.xml index bcb3724fa5..8149719e25 100644 --- a/app/src/main/res/drawable/ic_telegram.xml +++ b/app/src/main/res/drawable/ic_telegram.xml @@ -5,5 +5,5 @@ android:viewportHeight="24"> <path android:fillColor="#FF000000" - android:pathData="M18.384,22.779c0.322,0.228 0.737,0.285 1.107,0.145c0.37,-0.141 0.642,-0.457 0.724,-0.84c0.869,-4.084 2.977,-14.421 3.768,-18.136c0.06,-0.28 -0.04,-0.571 -0.26,-0.758c-0.22,-0.187 -0.525,-0.241 -0.797,-0.14c-4.193,1.552 -17.106,6.397 -22.384,8.35c-0.335,0.124 -0.553,0.446 -0.542,0.799c0.012,0.354 0.25,0.661 0.593,0.764c2.367,0.708 5.474,1.693 5.474,1.693c0,0 1.452,4.385 2.209,6.615c0.095,0.28 0.314,0.5 0.603,0.576c0.288,0.075 0.596,-0.004 0.811,-0.207c1.216,-1.148 3.096,-2.923 3.096,-2.923c0,0 3.572,2.619 5.598,4.062ZM7.374,14.102l1.679,5.538l0.373,-3.507c0,0 6.487,-5.851 10.185,-9.186c0.108,-0.098 0.123,-0.262 0.033,-0.377c-0.089,-0.115 -0.253,-0.142 -0.376,-0.064c-4.286,2.737 -11.894,7.596 -11.894,7.596Z"/> + android:pathData="M11.944,0A12,12 0,0 0,0 12a12,12 0,0 0,12 12,12 12,0 0,0 12,-12A12,12 0,0 0,12 0a12,12 0,0 0,-0.056 0zM16.906,7.224c0.1,-0.002 0.321,0.023 0.465,0.14a0.506,0.506 0,0 1,0.171 0.325c0.016,0.093 0.036,0.306 0.02,0.472 -0.18,1.898 -0.962,6.502 -1.36,8.627 -0.168,0.9 -0.499,1.201 -0.82,1.23 -0.696,0.065 -1.225,-0.46 -1.9,-0.902 -1.056,-0.693 -1.653,-1.124 -2.678,-1.8 -1.185,-0.78 -0.417,-1.21 0.258,-1.91 0.177,-0.184 3.247,-2.977 3.307,-3.23 0.007,-0.032 0.014,-0.15 -0.056,-0.212s-0.174,-0.041 -0.249,-0.024c-0.106,0.024 -1.793,1.14 -5.061,3.345 -0.48,0.33 -0.913,0.49 -1.302,0.48 -0.428,-0.008 -1.252,-0.241 -1.865,-0.44 -0.752,-0.245 -1.349,-0.374 -1.297,-0.789 0.027,-0.216 0.325,-0.437 0.893,-0.663 3.498,-1.524 5.83,-2.529 6.998,-3.014 3.332,-1.386 4.025,-1.627 4.476,-1.635z"/> </vector> diff --git a/app/src/main/res/drawable/ic_twitter.xml b/app/src/main/res/drawable/ic_twitter.xml index 1a097f6b91..cd35270eef 100644 --- a/app/src/main/res/drawable/ic_twitter.xml +++ b/app/src/main/res/drawable/ic_twitter.xml @@ -5,5 +5,5 @@ android:viewportHeight="24"> <path android:fillColor="#FF000000" - android:pathData="M24,4.557c-0.883,0.392 -1.832,0.656 -2.828,0.775 1.017,-0.609 1.798,-1.574 2.165,-2.724 -0.951,0.564 -2.005,0.974 -3.127,1.195 -0.897,-0.957 -2.178,-1.555 -3.594,-1.555 -3.179,0 -5.515,2.966 -4.797,6.045 -4.091,-0.205 -7.719,-2.165 -10.148,-5.144 -1.29,2.213 -0.669,5.108 1.523,6.574 -0.806,-0.026 -1.566,-0.247 -2.229,-0.616 -0.054,2.281 1.581,4.415 3.949,4.89 -0.693,0.188 -1.452,0.232 -2.224,0.084 0.626,1.956 2.444,3.379 4.6,3.419 -2.07,1.623 -4.678,2.348 -7.29,2.04 2.179,1.397 4.768,2.212 7.548,2.212 9.142,0 14.307,-7.721 13.995,-14.646 0.962,-0.695 1.797,-1.562 2.457,-2.549z"/> + android:pathData="M23.953,4.57a10,10 0,0 1,-2.825 0.775,4.958 4.958,0 0,0 2.163,-2.723c-0.951,0.555 -2.005,0.959 -3.127,1.184a4.92,4.92 0,0 0,-8.384 4.482C7.69,8.095 4.067,6.13 1.64,3.162a4.822,4.822 0,0 0,-0.666 2.475c0,1.71 0.87,3.213 2.188,4.096a4.904,4.904 0,0 1,-2.228 -0.616v0.06a4.923,4.923 0,0 0,3.946 4.827,4.996 4.996,0 0,1 -2.212,0.085 4.936,4.936 0,0 0,4.604 3.417,9.867 9.867,0 0,1 -6.102,2.105c-0.39,0 -0.779,-0.023 -1.17,-0.067a13.995,13.995 0,0 0,7.557 2.209c9.053,0 13.998,-7.496 13.998,-13.985 0,-0.21 0,-0.42 -0.015,-0.63A9.935,9.935 0,0 0,24 4.59z"/> </vector> diff --git a/app/src/main/res/drawable/ic_youtube.xml b/app/src/main/res/drawable/ic_youtube.xml index d52b0c4c8e..7f8a1a6bb4 100644 --- a/app/src/main/res/drawable/ic_youtube.xml +++ b/app/src/main/res/drawable/ic_youtube.xml @@ -5,5 +5,5 @@ android:viewportHeight="24"> <path android:fillColor="#FF000000" - android:pathData="M19.615,3.184c-3.604,-0.246 -11.631,-0.245 -15.23,0 -3.897,0.266 -4.356,2.62 -4.385,8.816 0.029,6.185 0.484,8.549 4.385,8.816 3.6,0.245 11.626,0.246 15.23,0 3.897,-0.266 4.356,-2.62 4.385,-8.816 -0.029,-6.185 -0.484,-8.549 -4.385,-8.816zM9,16v-8l8,3.993 -8,4.007z"/> + android:pathData="M23.498,6.186a3.016,3.016 0,0 0,-2.122 -2.136C19.505,3.545 12,3.545 12,3.545s-7.505,0 -9.377,0.505A3.017,3.017 0,0 0,0.502 6.186C0,8.07 0,12 0,12s0,3.93 0.502,5.814a3.016,3.016 0,0 0,2.122 2.136c1.871,0.505 9.376,0.505 9.376,0.505s7.505,0 9.377,-0.505a3.015,3.015 0,0 0,2.122 -2.136C24,15.93 24,12 24,12s0,-3.93 -0.502,-5.814zM9.545,15.568V8.432L15.818,12l-6.273,3.568z"/> </vector> From 4cb90b6d310fe0e46ce44f8d67b8803dcc652c5e Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Wed, 10 Nov 2021 17:40:10 +0400 Subject: [PATCH 074/118] update settings UI --- .../ui/component/list/ManagerListItem.kt | 2 +- .../preference/CheckboxDialogPreference.kt | 52 +++++++------- .../component/preference/DialogPreference.kt | 36 ++++------ .../ui/component/preference/Preference.kt | 72 +++++++++---------- .../preference/RadiobuttonDialogPreference.kt | 43 +++++------ .../manager/ui/screens/SettingsLayout.kt | 29 +++++--- .../screens/settings/ManagerVariantItem.kt | 24 ++++++- .../ui/widget/screens/settings/ThemeItem.kt | 30 ++++++-- 8 files changed, 157 insertions(+), 131 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/component/list/ManagerListItem.kt b/app/src/main/java/com/vanced/manager/ui/component/list/ManagerListItem.kt index 6bacb6ae7c..bcfe26ec92 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/list/ManagerListItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/list/ManagerListItem.kt @@ -46,7 +46,7 @@ fun ManagerListItem( if (trailing != null) { Box( modifier = Modifier - .size(56.dp) + .size(48.dp) .align(Alignment.CenterVertically), contentAlignment = Alignment.Center, ) { diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt index dec5ef49d3..f9ea847fc6 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt @@ -15,43 +15,43 @@ import androidx.compose.ui.unit.dp import com.vanced.manager.R import com.vanced.manager.core.preferences.CheckboxPreference import com.vanced.manager.core.preferences.ManagerPreference +import com.vanced.manager.core.preferences.RadioButtonPreference import com.vanced.manager.ui.component.button.ManagerThemedTextButton import com.vanced.manager.ui.component.text.ManagerText +import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.widget.list.CheckboxItem import kotlinx.coroutines.launch @Composable fun CheckboxDialogPreference( preferenceTitle: String, - preference: ManagerPreference<Set<String>>, + preferenceDescription: String, + isDialogVisible: Boolean, + currentSelectedKeys: List<String>, + buttons: List<RadioButtonPreference>, trailing: @Composable () -> Unit = {}, - buttons: List<CheckboxPreference>, - onSave: (checkedButtons: List<String>) -> Unit = {} + onPreferenceClick: () -> Unit, + onDismissRequest: () -> Unit, + onItemCheckChange: (isChecked: Boolean, itemKey: String) -> Unit, + onSave: () -> Unit, ) { - var pref by preference - val selectedButtons = remember { pref.toMutableStateList() } - val coroutineScope = rememberCoroutineScope() DialogPreference( preferenceTitle = preferenceTitle, - preferenceDescription = buttons.filter { button -> - pref.any { selectedButton -> - button.key == selectedButton - } - }.sortedBy { it.title }.joinToString(separator = ", ") { it.title }, + preferenceDescription = preferenceDescription, trailing = trailing, - confirmButton = { isShown -> - TextButton( - onClick = { - coroutineScope.launch { - isShown.value = false - pref = selectedButtons.toSet() - onSave(selectedButtons) - } - } - ) { - ManagerText(stringResource(id = R.string.dialog_button_save)) + confirmButton = { + TextButton(onClick = onSave) { + ManagerText(managerString(R.string.dialog_button_save)) + } + }, + dismissButton = { + TextButton(onClick = onDismissRequest) { + ManagerText(managerString(R.string.dialog_button_cancel)) } }, + onDismissRequest = onDismissRequest, + isDialogVisible = isDialogVisible, + onPreferenceClick = onPreferenceClick ) { LazyColumn( modifier = Modifier.heightIn(max = 400.dp) @@ -60,13 +60,9 @@ fun CheckboxDialogPreference( val (title, key) = button CheckboxItem( text = title, - isChecked = selectedButtons.contains(key), + isChecked = currentSelectedKeys.contains(key), onCheck = { isChecked -> - if (isChecked) { - selectedButtons.add(key) - } else { - selectedButtons.remove(key) - } + onItemCheckChange(isChecked, key) } ) } diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/DialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/DialogPreference.kt index 83604dbaf5..4e3b63ddb0 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/DialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/DialogPreference.kt @@ -1,44 +1,32 @@ package com.vanced.manager.ui.component.preference import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember import com.vanced.manager.ui.component.dialog.ManagerDialog @Composable fun DialogPreference( preferenceTitle: String, preferenceDescription: String? = null, - onDismissRequest: () -> Unit = {}, trailing: @Composable () -> Unit = {}, - confirmButton: @Composable (isShown: MutableState<Boolean>) -> Unit, - dismissButton: @Composable ((isShown: MutableState<Boolean>) -> Unit)? = null, + onPreferenceClick: () -> Unit, + isDialogVisible: Boolean, + onDismissRequest: () -> Unit, + confirmButton: @Composable () -> Unit, + dismissButton: @Composable () -> Unit = {}, content: @Composable () -> Unit ) { - val isShown = remember { mutableStateOf(false) } Preference( preferenceTitle = preferenceTitle, preferenceDescription = preferenceDescription, - trailing = trailing - ) { - isShown.value = true - } - if (isShown.value) { + trailing = trailing, + onClick = onPreferenceClick + ) + if (isDialogVisible) { ManagerDialog( title = preferenceTitle, - onDismissRequest = { - onDismissRequest() - isShown.value = false - }, - confirmButton = { - confirmButton(isShown) - }, - dismissButton = { - if (dismissButton != null) { - dismissButton(isShown) - } - }, + onDismissRequest = onDismissRequest, + confirmButton = confirmButton, + dismissButton = dismissButton, content = content ) } diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt index 2688da4d1f..2563ae89bf 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt @@ -7,11 +7,15 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.vanced.manager.ui.component.card.ManagerTonalCard import com.vanced.manager.ui.component.color.managerAnimatedColor import com.vanced.manager.ui.component.list.ManagerListItem import com.vanced.manager.ui.component.modifier.managerClickable import com.vanced.manager.ui.component.text.ManagerText +import com.vanced.manager.ui.theme.LargeShape import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal +import com.vanced.manager.ui.util.DefaultContentPaddingVertical @Composable fun Preference( @@ -19,49 +23,37 @@ fun Preference( preferenceDescription: String? = null, trailing: @Composable () -> Unit = {}, onClick: () -> Unit -) { - Preference( - preferenceTitle = { ManagerText(text = preferenceTitle) }, - preferenceDescription = if (preferenceDescription != null) { - { - ManagerText(text = preferenceDescription) - } - } else null, - trailing = trailing, - onClick = onClick - ) -} - -@Composable -fun Preference( - preferenceTitle: @Composable () -> Unit, - preferenceDescription: @Composable (() -> Unit)? = null, - trailing: @Composable () -> Unit = {}, - onClick: () -> Unit ) { val color = managerAnimatedColor(color = MaterialTheme.colorScheme.onSurface) - ManagerListItem( - modifier = Modifier - .managerClickable(onClick = onClick) - .padding(horizontal = DefaultContentPaddingHorizontal), - title = { - CompositionLocalProvider( - LocalContentColor provides color, - LocalTextStyle provides MaterialTheme.typography.titleSmall - ) { - preferenceTitle() - } - }, - description = if (preferenceDescription != null) { - { + ManagerTonalCard( + shape = LargeShape, + onClick = onClick + ) { + ManagerListItem( + modifier = Modifier + .padding( + horizontal = DefaultContentPaddingHorizontal, + vertical = 8.dp + ), + title = { CompositionLocalProvider( LocalContentColor provides color, - LocalTextStyle provides MaterialTheme.typography.bodySmall + LocalTextStyle provides MaterialTheme.typography.titleSmall ) { - preferenceDescription() + ManagerText(text = preferenceTitle) + } + }, + description = if (preferenceDescription != null) { + { + CompositionLocalProvider( + LocalContentColor provides color, + LocalTextStyle provides MaterialTheme.typography.bodySmall + ) { + ManagerText(text = preferenceDescription) + } } - } - } else null, - trailing = trailing, - ) -} + } else null, + trailing = trailing, + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt index 5e439a2534..93af305677 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt @@ -8,38 +8,41 @@ import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.vanced.manager.R -import com.vanced.manager.core.preferences.ManagerPreference import com.vanced.manager.core.preferences.RadioButtonPreference import com.vanced.manager.ui.component.text.ManagerText import com.vanced.manager.ui.resources.managerString -import com.vanced.manager.ui.widget.button.ManagerSaveButton import com.vanced.manager.ui.widget.list.RadiobuttonItem -import kotlinx.coroutines.launch @Composable fun RadiobuttonDialogPreference( preferenceTitle: String, - preference: ManagerPreference<String>, - trailing: @Composable () -> Unit = {}, + preferenceDescription: String, + isDialogVisible: Boolean, + currentSelectedKey: String, buttons: List<RadioButtonPreference>, - onSave: (newPref: String?) -> Unit = {} + trailing: @Composable () -> Unit = {}, + onPreferenceClick: () -> Unit, + onDismissRequest: () -> Unit, + onItemClick: (itemKey: String) -> Unit, + onSave: () -> Unit, ) { - var pref by preference - var currentSelection by remember { mutableStateOf(pref) } - val coroutineScope = rememberCoroutineScope() DialogPreference( preferenceTitle = preferenceTitle, - preferenceDescription = buttons.find { it.key == pref }?.title, + preferenceDescription = preferenceDescription, trailing = trailing, - confirmButton = { isShown -> - TextButton(onClick = { - isShown.value = false - pref = currentSelection - onSave(currentSelection) - }) { - ManagerText(managerString(stringId = R.string.dialog_button_save)) + confirmButton = { + TextButton(onClick = onSave) { + ManagerText(managerString(R.string.dialog_button_save)) + } + }, + dismissButton = { + TextButton(onClick = onDismissRequest) { + ManagerText(managerString(R.string.dialog_button_cancel)) } }, + onDismissRequest = onDismissRequest, + isDialogVisible = isDialogVisible, + onPreferenceClick = onPreferenceClick ) { LazyColumn( modifier = Modifier.heightIn(max = 400.dp) @@ -49,10 +52,8 @@ fun RadiobuttonDialogPreference( RadiobuttonItem( text = title, tag = key, - isSelected = currentSelection == key, - onSelect = { - currentSelection = it - } + isSelected = currentSelectedKey == key, + onSelect = onItemClick ) } } diff --git a/app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt index 376a471906..97bd3ef197 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt @@ -1,7 +1,6 @@ package com.vanced.manager.ui.screens -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.ArrowBackIosNew import androidx.compose.material3.ExperimentalMaterial3Api @@ -10,6 +9,7 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp import com.vanced.manager.R import com.vanced.manager.ui.component.layout.ManagerLazyColumn import com.vanced.manager.ui.component.topappbar.ManagerTopAppBar @@ -43,16 +43,29 @@ fun SettingsLayout( } ) { paddingValues -> ManagerLazyColumn( - modifier = Modifier.fillMaxSize().padding(paddingValues), + modifier = Modifier + .fillMaxSize() + .padding(paddingValues), ) { managerCategory(settingsCategoryBehaviour) { - SettingsCustomTabsItem() - SettingsNotificationsItem() - SettingsManagerVariantItem() + Column( + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + SettingsCustomTabsItem() + SettingsNotificationsItem() + SettingsManagerVariantItem() + } + } managerCategory(settingsCategoryApperance) { - SettingsAccentColorItem() - ThemeSettingsItem() + Column( + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + SettingsAccentColorItem() + ThemeSettingsItem() + } } } } diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt index a0121c150e..30ff0bea96 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt @@ -1,6 +1,6 @@ package com.vanced.manager.ui.widget.screens.settings -import androidx.compose.runtime.Composable +import androidx.compose.runtime.* import com.vanced.manager.R import com.vanced.manager.core.preferences.RadioButtonPreference import com.vanced.manager.core.preferences.holder.managerVariantPref @@ -9,11 +9,15 @@ import com.vanced.manager.ui.resources.managerString @Composable fun SettingsManagerVariantItem() { + var showDialog by remember { mutableStateOf(false) } + var selectedKey by remember { mutableStateOf(managerVariantPref.value.value) } RadiobuttonDialogPreference( preferenceTitle = managerString( stringId = R.string.settings_preference_variant_title ), - preference = managerVariantPref, + preferenceDescription = managerVariantPref.value.value, + isDialogVisible = showDialog, + currentSelectedKey = selectedKey, buttons = listOf( RadioButtonPreference( title = "nonroot", @@ -23,6 +27,20 @@ fun SettingsManagerVariantItem() { title = "root", key = "root" ), - ) + ), + onPreferenceClick = { + showDialog = true + }, + onDismissRequest = { + showDialog = false + selectedKey = managerVariantPref.value.value + }, + onItemClick = { + selectedKey = it + }, + onSave = { + managerVariantPref.save(selectedKey) + showDialog = false + } ) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt index 11038023f1..42b97eac50 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt @@ -1,6 +1,6 @@ package com.vanced.manager.ui.widget.screens.settings -import androidx.compose.runtime.Composable +import androidx.compose.runtime.* import com.vanced.manager.R import com.vanced.manager.core.preferences.RadioButtonPreference import com.vanced.manager.core.preferences.holder.managerThemePref @@ -9,22 +9,40 @@ import com.vanced.manager.ui.resources.managerString @Composable fun ThemeSettingsItem() { + var showDialog by remember { mutableStateOf(false) } + var selectedKey by remember { mutableStateOf(managerThemePref.value.value) } RadiobuttonDialogPreference( preferenceTitle = managerString(stringId = R.string.settings_preference_theme_title), - preference = managerThemePref, + preferenceDescription = managerThemePref.value.value, + isDialogVisible = showDialog, + currentSelectedKey = selectedKey, buttons = listOf( RadioButtonPreference( - title = managerString(stringId = R.string.settings_preference_theme_light), + title = managerString(R.string.settings_preference_theme_light), key = "Light" ), RadioButtonPreference( - title = managerString(stringId = R.string.settings_preference_theme_dark), + title = managerString(R.string.settings_preference_theme_dark), key = "Dark" ), RadioButtonPreference( - title = managerString(stringId = R.string.settings_option_system_default), + title = managerString(R.string.settings_option_system_default), key = "System Default" ) - ) + ), + onPreferenceClick = { + showDialog = true + }, + onDismissRequest = { + showDialog = false + selectedKey = managerThemePref.value.value + }, + onItemClick = { + selectedKey = it + }, + onSave = { + managerThemePref.save(selectedKey) + showDialog = false + } ) } From f3ebe85e301694a68e5317ad77ce895a201417d9 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Wed, 10 Nov 2021 17:40:57 +0400 Subject: [PATCH 075/118] update dialog UI --- .../manager/ui/component/dialog/ManagerDialog.kt | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt b/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt index 0b4f1a5028..f70c08ab26 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt @@ -1,18 +1,13 @@ package com.vanced.manager.ui.component.dialog -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material3.AlertDialog -import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.Dialog -import com.vanced.manager.ui.component.card.ManagerCard import com.vanced.manager.ui.component.text.ManagerText import com.vanced.manager.ui.theme.LargeShape -import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal -import com.vanced.manager.ui.util.DefaultContentPaddingVertical @Composable fun ManagerDialog( @@ -28,7 +23,9 @@ fun ManagerDialog( modifier = modifier, title = { ManagerText( - text = title + modifier = Modifier.fillMaxWidth(), + text = title, + textAlign = TextAlign.Center ) }, text = content, From f93210b62b4fdabbf243e6b83f7ad43da991130a Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Wed, 10 Nov 2021 18:55:30 +0400 Subject: [PATCH 076/118] refactor preferences --- .../core/downloader/impl/MusicDownloader.kt | 9 +++----- .../core/downloader/impl/VancedDownloader.kt | 15 +++++-------- .../core/installer/impl/MusicInstaller.kt | 7 +++---- .../core/installer/impl/VancedInstaller.kt | 7 ++----- .../preferences/holder/PreferenceHolder.kt | 21 +++++++++---------- .../manager/network/model/AppDtoMapper.kt | 18 ++++++++-------- .../ui/component/card/ManagerLinkCard.kt | 3 +-- .../ui/component/color/ManagerColors.kt | 3 +-- .../preference/CheckboxPreference.kt | 11 +++------- .../java/com/vanced/manager/ui/theme/Theme.kt | 2 +- .../manager/ui/viewmodel/MainViewModel.kt | 6 +++--- .../widget/screens/settings/CustomTabsItem.kt | 5 ++++- .../screens/settings/ManagerVariantItem.kt | 8 +++---- .../screens/settings/NotificationsItem.kt | 16 ++++++++------ .../ui/widget/screens/settings/ThemeItem.kt | 8 +++---- 15 files changed, 63 insertions(+), 76 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt index c317480234..024618d086 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt @@ -14,22 +14,19 @@ class MusicDownloader( private val context: Context, ) : AppDownloader() { - private val version by musicVersionPref - private val variant by managerVariantPref - private lateinit var absoluteVersion: String override suspend fun download( appVersions: List<String>?, onStatus: (DownloadStatus) -> Unit ) { - absoluteVersion = getLatestOrProvidedAppVersion(version, appVersions) + absoluteVersion = getLatestOrProvidedAppVersion(musicVersionPref, appVersions) downloadFiles( downloadFiles = arrayOf(DownloadFile( call = musicAPI.getFiles( version = absoluteVersion, - variant = variant, + variant = managerVariantPref, ), fileName = "music.apk" )), @@ -53,7 +50,7 @@ class MusicDownloader( override fun getSavedFilePath(): String { val directory = - File(context.getExternalFilesDir("vancedmusic")!!.path + "$absoluteVersion/$variant") + File(context.getExternalFilesDir("vancedmusic")!!.path + "$absoluteVersion/$managerVariantPref") if (!directory.exists()) directory.mkdirs() diff --git a/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt index 6cfcb69e56..a5f4c40d1b 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt @@ -17,29 +17,24 @@ class VancedDownloader( private val context: Context, ) : AppDownloader() { - private val theme by vancedThemePref - private val version by vancedVersionPref - private val variant by managerVariantPref - private val languages by vancedLanguagesPref - private lateinit var absoluteVersion: String override suspend fun download( appVersions: List<String>?, onStatus: (DownloadStatus) -> Unit ) { - absoluteVersion = getLatestOrProvidedAppVersion(version, appVersions) + absoluteVersion = getLatestOrProvidedAppVersion(vancedVersionPref, appVersions) val files = arrayOf( getFile( type = "Theme", - apkName = "$theme.apk", + apkName = "$vancedThemePref.apk", ), getFile( type = "Arch", apkName = "split_config.$arch.apk", ) - ) + languages.map { language -> + ) + vancedLanguagesPref.map { language -> getFile( type = "Language", apkName = "split_config.$language.apk", @@ -68,7 +63,7 @@ class VancedDownloader( override fun getSavedFilePath(): String { val directory = - File(context.getExternalFilesDir("vanced")!!.path + "/$absoluteVersion/$variant") + File(context.getExternalFilesDir("vanced")!!.path + "/$absoluteVersion/$managerVariantPref") if (!directory.exists()) directory.mkdirs() @@ -82,7 +77,7 @@ class VancedDownloader( ) = DownloadFile( call = vancedAPI.getFiles( version = absoluteVersion, - variant = variant, + variant = managerVariantPref, type = type, apkName = apkName ), diff --git a/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt index d19e64621e..8704ffb654 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt @@ -12,10 +12,9 @@ class MusicInstaller( ) : AppInstaller() { override fun install(appVersions: List<String>?) { - val version by musicVersionPref - val variant by managerVariantPref - - val musicApk = File(context.getExternalFilesDir("music/$version/$variant/music.apk")!!.path) + val musicApk = File( + context.getExternalFilesDir("music/$musicVersionPref/$managerVariantPref/music.apk")!!.path + ) installApp(musicApk, context) } diff --git a/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt index 7e6f3b24d2..5a99d105ec 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt @@ -12,13 +12,10 @@ class VancedInstaller( ) : AppInstaller() { override fun install(appVersions: List<String>?) { - val version by vancedVersionPref - val variant by managerVariantPref - - val absoluteVersion = getLatestOrProvidedAppVersion(version, appVersions) + val absoluteVersion = getLatestOrProvidedAppVersion(vancedVersionPref, appVersions) val apks = context - .getExternalFilesDir("vanced/$absoluteVersion/$variant")!! + .getExternalFilesDir("vanced/$absoluteVersion/$managerVariantPref")!! .listFiles { file -> file.extension == "apk" } diff --git a/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceHolder.kt b/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceHolder.kt index e537e2eee3..613b9aa3ed 100644 --- a/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceHolder.kt +++ b/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceHolder.kt @@ -6,18 +6,17 @@ import com.vanced.manager.core.preferences.managerStringPreference import com.vanced.manager.core.preferences.managerStringSetPreference import com.vanced.manager.ui.theme.defAccentColor -val useCustomTabsPref = managerBooleanPreference(USE_CUSTOM_TABS_KEY) -val managerVariantPref = managerStringPreference(MANAGER_VARIANT_KEY, MANAGER_VARIANT_DEFAULT_VALUE) +var useCustomTabsPref by managerBooleanPreference(USE_CUSTOM_TABS_KEY) +var managerVariantPref by managerStringPreference(MANAGER_VARIANT_KEY, MANAGER_VARIANT_DEFAULT_VALUE) -val managerThemePref = managerStringPreference(MANAGER_THEME_KEY, MANAGER_THEME_DEFAULT_VALUE) -val managerAccentColorPref = managerLongPreference(MANAGER_ACCENT_COLOR_KEY, defAccentColor) +var managerThemePref by managerStringPreference(MANAGER_THEME_KEY, MANAGER_THEME_DEFAULT_VALUE) +var managerAccentColorPref by managerLongPreference(MANAGER_ACCENT_COLOR_KEY, defAccentColor) -val vancedThemePref = managerStringPreference(APP_VANCED_THEME_KEY, VANCED_THEME_DEFAULT_VALUE) -val vancedVersionPref = managerStringPreference(APP_VANCED_VERSION_KEY, APP_VERSION_DEFAULT_VALUE) -val vancedLanguagesPref = - managerStringSetPreference(APP_VANCED_LANGUAGE_KEY, VANCED_LANGUAGE_DEFAULT_VALUE) +var vancedThemePref by managerStringPreference(APP_VANCED_THEME_KEY, VANCED_THEME_DEFAULT_VALUE) +var vancedVersionPref by managerStringPreference(APP_VANCED_VERSION_KEY, APP_VERSION_DEFAULT_VALUE) +var vancedLanguagesPref by managerStringSetPreference(APP_VANCED_LANGUAGE_KEY, VANCED_LANGUAGE_DEFAULT_VALUE) -val musicVersionPref = managerStringPreference(APP_MUSIC_VERSION_KEY, APP_VERSION_DEFAULT_VALUE) +var musicVersionPref by managerStringPreference(APP_MUSIC_VERSION_KEY, APP_VERSION_DEFAULT_VALUE) -val vancedEnabled = managerBooleanPreference(VANCED_ENABLED_KEY, APP_ENABLED_DEFAULT_VALUE) -val musicEnabled = managerBooleanPreference(MUSIC_ENABLED_KEY, APP_ENABLED_DEFAULT_VALUE) \ No newline at end of file +var vancedEnabled by managerBooleanPreference(VANCED_ENABLED_KEY, APP_ENABLED_DEFAULT_VALUE) +var musicEnabled by managerBooleanPreference(MUSIC_ENABLED_KEY, APP_ENABLED_DEFAULT_VALUE) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt index 6ef95e005b..6f6f570960 100644 --- a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt +++ b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt @@ -77,9 +77,9 @@ class AppDtoMapper( VANCED_NAME -> listOf( InstallationOption.SingleSelect( titleId = R.string.app_installation_options_theme, - getOption = { vancedThemePref.value.value }, + getOption = { vancedThemePref }, setOption = { - vancedThemePref.save(it) + vancedThemePref = it }, items = appThemes?.map { theme -> InstallationOptionItem( @@ -94,9 +94,9 @@ class AppDtoMapper( ), InstallationOption.SingleSelect( titleId = R.string.app_installation_options_version, - getOption = { vancedVersionPref.value.value }, + getOption = { vancedVersionPref }, setOption = { - vancedVersionPref.save(it) + vancedVersionPref = it }, items = appVersions?.map { version -> InstallationOptionItem( @@ -107,12 +107,12 @@ class AppDtoMapper( ), InstallationOption.MultiSelect( titleId = R.string.app_installation_options_language, - getOption = { vancedLanguagesPref.value.value }, + getOption = { vancedLanguagesPref }, addOption = { - vancedLanguagesPref.save(vancedLanguagesPref.value.value + it) + vancedLanguagesPref = vancedLanguagesPref + it }, removeOption = { - vancedLanguagesPref.save(vancedLanguagesPref.value.value - it) + vancedLanguagesPref = vancedLanguagesPref - it }, items = appLanguages?.map { language -> InstallationOptionItem( @@ -128,9 +128,9 @@ class AppDtoMapper( MUSIC_NAME -> listOf( InstallationOption.SingleSelect( titleId = R.string.app_installation_options_version, - getOption = { musicVersionPref.value.value }, + getOption = { musicVersionPref }, setOption = { - musicVersionPref.save(it) + musicVersionPref = it }, items = appVersions?.map { version -> InstallationOptionItem( diff --git a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerLinkCard.kt b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerLinkCard.kt index 9a836928c4..66e7d8bcd9 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerLinkCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerLinkCard.kt @@ -19,12 +19,11 @@ fun ManagerLinkCard( val customTabs = remember { CustomTabsIntent.Builder().build() } val uri = remember { Uri.parse(link) } val intent = remember { Intent(Intent.ACTION_VIEW, uri) } - val useCustomTabs by useCustomTabsPref ManagerItemCard( title = title, icon = icon ) { - if (useCustomTabs) { + if (useCustomTabsPref) { customTabs.launchUrl(context, uri) } else { context.startActivity(intent) diff --git a/app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt b/app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt index 9bb3021e19..c03074f252 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt @@ -17,8 +17,7 @@ fun contentColorForColor(color: Color) = @Composable fun managerAccentColor(): Color { - val accentColor by managerAccentColorPref - return Color(accentColor) + return Color(managerAccentColorPref) } @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt index b4533436aa..20a2c89dc1 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt @@ -11,18 +11,13 @@ import kotlinx.coroutines.launch fun CheckboxPreference( preferenceTitle: String, preferenceDescription: String? = null, - preference: ManagerPreference<Boolean>, + isChecked: Boolean, onCheckedChange: (isChecked: Boolean) -> Unit = {} ) { - var isChecked by preference - val coroutineScope = rememberCoroutineScope() - val onClick: () -> Unit = { - coroutineScope.launch { - isChecked = !isChecked - onCheckedChange(isChecked) - } + onCheckedChange(!isChecked) } + Preference( preferenceTitle = preferenceTitle, preferenceDescription = preferenceDescription, diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt index f8be63d5d4..6981c57966 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt @@ -72,7 +72,7 @@ private val DarkThemeColors = darkColorScheme( ) @Composable -fun isDark(): Boolean = when (managerThemePref.value.value) { +fun isDark(): Boolean = when (managerThemePref) { "Dark" -> true "Light" -> false "System Default" -> isSystemInDarkTheme() diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt index ed12a72eea..73a82bba8c 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt @@ -32,9 +32,9 @@ class MainViewModel( fun fetch() { viewModelScope.launch { - val vancedEnabled = vancedEnabled.value.value - val musicEnabled = musicEnabled.value.value - val isNonroot = managerVariantPref.value.value == "nonroot" + val vancedEnabled = vancedEnabled + val musicEnabled = musicEnabled + val isNonroot = managerVariantPref == "nonroot" var appsCount = 0 diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/CustomTabsItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/CustomTabsItem.kt index db01f79166..bfe7d412d8 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/CustomTabsItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/CustomTabsItem.kt @@ -11,6 +11,9 @@ fun SettingsCustomTabsItem() { CheckboxPreference( preferenceTitle = stringResource(id = R.string.settings_preference_use_custom_tabs_title), preferenceDescription = stringResource(id = R.string.settings_preference_use_custom_tabs_summary), - preference = useCustomTabsPref + isChecked = useCustomTabsPref, + onCheckedChange = { + useCustomTabsPref = it + } ) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt index 30ff0bea96..f68cc0dafd 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt @@ -10,12 +10,12 @@ import com.vanced.manager.ui.resources.managerString @Composable fun SettingsManagerVariantItem() { var showDialog by remember { mutableStateOf(false) } - var selectedKey by remember { mutableStateOf(managerVariantPref.value.value) } + var selectedKey by remember { mutableStateOf(managerVariantPref) } RadiobuttonDialogPreference( preferenceTitle = managerString( stringId = R.string.settings_preference_variant_title ), - preferenceDescription = managerVariantPref.value.value, + preferenceDescription = managerVariantPref, isDialogVisible = showDialog, currentSelectedKey = selectedKey, buttons = listOf( @@ -33,13 +33,13 @@ fun SettingsManagerVariantItem() { }, onDismissRequest = { showDialog = false - selectedKey = managerVariantPref.value.value + selectedKey = managerVariantPref }, onItemClick = { selectedKey = it }, onSave = { - managerVariantPref.save(selectedKey) + managerVariantPref = selectedKey showDialog = false } ) diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/NotificationsItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/NotificationsItem.kt index 342ff63ae1..5e6393e66d 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/NotificationsItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/NotificationsItem.kt @@ -7,15 +7,19 @@ import com.vanced.manager.ui.component.preference.CheckboxPreference @Composable fun SettingsNotificationsItem() { - notificationApps.forEach { - with(it) { + notificationApps.forEach { notificationApp -> + with(notificationApp) { + var appNotificationsPref by managerBooleanPreference( + key = "${prefKey}_notifications", + defaultValue = true + ) CheckboxPreference( preferenceTitle = "$app Push Notifications", preferenceDescription = "Receive push notifications when an update for $app is released", - preference = managerBooleanPreference( - key = "${prefKey}_notifications", - defaultValue = true - ) + isChecked = appNotificationsPref, + onCheckedChange = { + appNotificationsPref = it + } ) } } diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt index 42b97eac50..23818eab6c 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt @@ -10,10 +10,10 @@ import com.vanced.manager.ui.resources.managerString @Composable fun ThemeSettingsItem() { var showDialog by remember { mutableStateOf(false) } - var selectedKey by remember { mutableStateOf(managerThemePref.value.value) } + var selectedKey by remember { mutableStateOf(managerThemePref) } RadiobuttonDialogPreference( preferenceTitle = managerString(stringId = R.string.settings_preference_theme_title), - preferenceDescription = managerThemePref.value.value, + preferenceDescription = managerThemePref, isDialogVisible = showDialog, currentSelectedKey = selectedKey, buttons = listOf( @@ -35,13 +35,13 @@ fun ThemeSettingsItem() { }, onDismissRequest = { showDialog = false - selectedKey = managerThemePref.value.value + selectedKey = managerThemePref }, onItemClick = { selectedKey = it }, onSave = { - managerThemePref.save(selectedKey) + managerThemePref = selectedKey showDialog = false } ) From 7e13297e5daca2227af4d525221383aa8d070248 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Wed, 17 Nov 2021 12:58:23 +0400 Subject: [PATCH 077/118] refactor ManagerPreference --- .../core/preferences/ManagerPreference.kt | 48 ++++++++----------- 1 file changed, 20 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/core/preferences/ManagerPreference.kt b/app/src/main/java/com/vanced/manager/core/preferences/ManagerPreference.kt index 162a72f1c2..479928da9a 100644 --- a/app/src/main/java/com/vanced/manager/core/preferences/ManagerPreference.kt +++ b/app/src/main/java/com/vanced/manager/core/preferences/ManagerPreference.kt @@ -1,24 +1,18 @@ package com.vanced.manager.core.preferences import android.content.SharedPreferences -import androidx.compose.runtime.State +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue import androidx.core.content.edit import org.koin.core.component.KoinComponent import org.koin.core.component.inject import kotlin.reflect.KProperty -fun <T> managerPreference( - key: String, - defaultValue: T, - getter: SharedPreferences.(key: String, defaultValue: T) -> T?, - setter: SharedPreferences.Editor.(key: String, newValue: T) -> Unit -) = ManagerPreference(key, defaultValue, getter, setter) - fun managerStringPreference( key: String, defaultValue: String = "" -) = managerPreference( +) = ManagerPreference( key = key, defaultValue = defaultValue, getter = SharedPreferences::getString, @@ -28,7 +22,7 @@ fun managerStringPreference( fun managerStringSetPreference( key: String, defaultValue: Set<String> = setOf() -) = managerPreference( +) = ManagerPreference( key = key, defaultValue = defaultValue, getter = SharedPreferences::getStringSet, @@ -38,7 +32,7 @@ fun managerStringSetPreference( fun managerBooleanPreference( key: String, defaultValue: Boolean = false -) = managerPreference( +) = ManagerPreference( key = key, defaultValue = defaultValue, getter = SharedPreferences::getBoolean, @@ -48,7 +42,7 @@ fun managerBooleanPreference( fun managerIntPreference( key: String, defaultValue: Int = 0 -) = managerPreference( +) = ManagerPreference( key = key, defaultValue = defaultValue, getter = SharedPreferences::getInt, @@ -58,7 +52,7 @@ fun managerIntPreference( fun managerLongPreference( key: String, defaultValue: Long = 0 -) = managerPreference( +) = ManagerPreference( key = key, defaultValue = defaultValue, getter = SharedPreferences::getLong, @@ -74,25 +68,23 @@ class ManagerPreference<T>( private val sharedPreferences: SharedPreferences by inject() - private val _value = mutableStateOf(defaultValue) - val value: State<T> = _value + var value by mutableStateOf(sharedPreferences.getter(key, defaultValue) ?: defaultValue) + private set + + operator fun getValue( + thisRef: Any?, + property: KProperty<*> + ) = value - operator fun getValue(thisRef: Any?, property: KProperty<*>) = value.value - - operator fun setValue(thisRef: Any?, property: KProperty<*>, newValue: T) { - save(newValue) - } - - fun save(newValue: T) { - _value.value = newValue + operator fun setValue( + thisRef: Any?, + property: KProperty<*>, + newValue: T + ) { + value = newValue sharedPreferences.edit { setter(key, newValue) } } - //It's Chewsday innit - init { - _value.value = sharedPreferences.getter(key, defaultValue) ?: defaultValue - } - } \ No newline at end of file From 5369121f2c519f847a49da8bb9d725faee99dec1 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 22 Nov 2021 15:54:56 +0400 Subject: [PATCH 078/118] update libraries --- app/build.gradle.kts | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9d5afd4657..21d1cf9aeb 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -79,12 +79,20 @@ val languages: String get() { dependencies { implementation(kotlin("reflect")) + + // AndroidX implementation("androidx.core:core-ktx:1.7.0") implementation("androidx.appcompat:appcompat:1.3.1") - implementation("com.google.android.material:material:1.4.0") - implementation("androidx.browser:browser:1.3.0") + implementation("androidx.browser:browser:1.4.0") + implementation("androidx.preference:preference-ktx:1.1.1") + implementation("androidx.activity:activity-compose:1.4.0") + + val lifecycleVersion = "2.4.0" + implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleVersion") + implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycleVersion") - val composeVersion = "1.1.0-beta02" + // Compose + val composeVersion = "1.1.0-beta03" implementation("androidx.compose.compiler:compiler:$composeVersion") implementation("androidx.compose.foundation:foundation:$composeVersion") implementation("androidx.compose.material:material-icons-core:$composeVersion") @@ -96,15 +104,9 @@ dependencies { implementation("androidx.compose.ui:ui-util:$composeVersion") implementation("androidx.compose.ui:ui:$composeVersion") - implementation("com.github.zsoltk:compose-router:0.28.0") - - implementation("androidx.preference:preference-ktx:1.1.1") - implementation("androidx.activity:activity-compose:1.4.0") - - val lifecycleVersion = "2.4.0-beta01" - implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleVersion") - implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycleVersion") + // Google + implementation("com.google.android.material:material:1.4.0") val accompanistVersion = "0.20.0" implementation("com.google.accompanist:accompanist-navigation-animation:$accompanistVersion") @@ -112,11 +114,15 @@ dependencies { implementation("com.google.accompanist:accompanist-swiperefresh:$accompanistVersion") implementation("com.google.accompanist:accompanist-systemuicontroller:$accompanistVersion") + + // Other + implementation("com.github.zsoltk:compose-router:0.28.0") + implementation("io.coil-kt:coil-compose:1.4.0") implementation("com.github.skydoves:orchestra-colorpicker:1.1.0") - val koinVersion = "3.1.2" + val koinVersion = "3.1.3" implementation("io.insert-koin:koin-android:$koinVersion") implementation("io.insert-koin:koin-androidx-compose:$koinVersion") @@ -124,8 +130,6 @@ dependencies { implementation("com.squareup.retrofit2:retrofit:$retrofitVersion") implementation("com.squareup.retrofit2:converter-gson:$retrofitVersion") - implementation("com.github.x1nto:apkhelper:1.1.2") - testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.3") androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0") From c7e54ba6fafb20abeaef6fd824b9236997dc4a1d Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 22 Nov 2021 16:17:46 +0400 Subject: [PATCH 079/118] fix installation screen not receiving input after installation completes --- .../com/vanced/manager/ui/MainActivity.kt | 4 ++-- .../manager/ui/screens/InstallScreen.kt | 11 +++++---- .../manager/ui/viewmodel/InstallViewModel.kt | 24 ++++++++++++------- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index 8ff9716ce5..bb3c5dffe2 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -23,11 +23,11 @@ import com.vanced.manager.ui.theme.ManagerTheme import com.vanced.manager.ui.theme.isDark import com.vanced.manager.ui.util.Screen import com.vanced.manager.ui.viewmodel.InstallViewModel -import org.koin.android.ext.android.inject +import org.koin.androidx.viewmodel.ext.android.viewModel class MainActivity : ComponentActivity() { - private val installViewModel: InstallViewModel by inject() + private val installViewModel: InstallViewModel by viewModel() private val backPressHandler = BackPressHandler() diff --git a/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt b/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt index be6017d89e..7e95292c7b 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt @@ -45,6 +45,9 @@ fun InstallScreen( var startedProcess by rememberSaveable { mutableStateOf(false) } + val logs = viewModel.logs + val status = viewModel.status + // I don't know why, I don't know how, // but it works as intended LaunchedEffect(startedProcess) { @@ -60,7 +63,7 @@ fun InstallScreen( ManagerTopAppBar( title = managerString(R.string.toolbar_install), ) - when (val status = viewModel.status) { + when (status) { is InstallViewModel.Status.Progress -> { ManagerProgressIndicator(status.progress) } @@ -72,9 +75,9 @@ fun InstallScreen( } }, floatingActionButton = { - if (viewModel.status is InstallViewModel.Status.Installed) { + if (status is InstallViewModel.Status.Installed) { ExtendedFloatingActionButton( - text = { /*TODO*/ }, + text = { ManagerText("Finish") }, icon = { Icon(Icons.Rounded.Done, null) }, @@ -88,7 +91,7 @@ fun InstallScreen( .fillMaxSize() .padding(paddingValues), ) { - items(viewModel.logs) { log -> + items(logs) { log -> when (log) { is InstallViewModel.Log.Success -> { ManagerText( diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt index fa08a6b72f..2d399076df 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt @@ -63,12 +63,14 @@ class InstallViewModel( } fun postInstallStatus(pmStatus: Int, extra: String) { - if (pmStatus == PackageInstaller.STATUS_SUCCESS) { - status = Status.Installed - logs.add(Log.Success("Successfully installed")) - } else { - status = Status.Failure - logs.add(Log.Error("Failed to install app", extra)) + viewModelScope.launch(Dispatchers.IO) { + if (pmStatus == PackageInstaller.STATUS_SUCCESS) { + status = Status.Installed + log(Log.Success("Successfully installed")) + } else { + status = Status.Failure + log(Log.Error("Failed to install app", extra)) + } } } @@ -80,14 +82,14 @@ class InstallViewModel( downloader.download(appVersions) { downloadStatus -> when (downloadStatus) { - is DownloadStatus.File -> logs.add(Log.Info("Downloading ${downloadStatus.fileName}")) - is DownloadStatus.Error -> logs.add(Log.Error( + is DownloadStatus.File -> log(Log.Info("Downloading ${downloadStatus.fileName}")) + is DownloadStatus.Error -> log(Log.Error( displayText = downloadStatus.displayError, stacktrace = downloadStatus.stacktrace )) is DownloadStatus.Progress -> status = Status.Progress(downloadStatus.progress / 100) is DownloadStatus.StartInstall -> { - logs.add(Log.Success("Successfully downloaded $appName")) + log(Log.Success("Successfully downloaded $appName")) installApp(appName, appVersions) } } @@ -123,6 +125,10 @@ class InstallViewModel( else -> throw IllegalArgumentException("$appName is not a valid app") } + private fun log(data: Log) { + logs.add(data) + } + private fun clear() { logs.clear() status = Status.Idle From c83ee3df8fc152f56da8f8c7aebb3edb7aa51fdd Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 22 Nov 2021 16:30:47 +0400 Subject: [PATCH 080/118] cleanup --- .../core/downloader/impl/MicrogDownloader.kt | 11 +- .../core/downloader/impl/MusicDownloader.kt | 26 ++-- .../core/downloader/impl/VancedDownloader.kt | 10 +- .../installer/service/AppInstallService.kt | 5 +- .../core/preferences/ManagerPreference.kt | 2 +- .../preferences/holder/PreferenceHolder.kt | 10 +- .../manager/network/model/AppDtoMapper.kt | 134 +++++++++--------- .../com/vanced/manager/ui/MainActivity.kt | 13 +- .../ui/component/layout/ManagerLazyColumn.kt | 5 - .../ui/component/layout/ManagerScaffold.kt | 16 +-- .../component/layout/ManagerSwipeRefresh.kt | 4 - .../ui/component/layout/ScrollableItemRow.kt | 1 - .../ui/component/menu/ManagerDropdownMenu.kt | 16 ++- .../preference/CheckboxDialogPreference.kt | 9 -- .../preference/CheckboxPreference.kt | 3 - .../ui/component/preference/Preference.kt | 2 - .../preference/RadiobuttonDialogPreference.kt | 2 +- .../vanced/manager/ui/screens/AboutLayout.kt | 6 +- .../vanced/manager/ui/screens/HomeLayout.kt | 31 ++-- .../manager/ui/screens/InstallScreen.kt | 11 +- .../java/com/vanced/manager/ui/util/Screen.kt | 6 +- .../manager/ui/viewmodel/InstallViewModel.kt | 13 +- .../manager/ui/viewmodel/MainViewModel.kt | 1 - .../vanced/manager/ui/widget/app/AppCard.kt | 2 - .../ui/widget/app/AppCardPlaceholder.kt | 1 - .../ui/widget/layout/CategoryLayout.kt | 5 +- .../widget/layout/SettingsCategoryLayout.kt | 1 - .../screens/settings/AccentColorItem.kt | 11 +- 28 files changed, 187 insertions(+), 170 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt index daf1933f1a..9a02b181b4 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt @@ -1,7 +1,6 @@ package com.vanced.manager.core.downloader.impl import android.content.Context -import android.util.Log import com.vanced.manager.core.downloader.api.MicrogAPI import com.vanced.manager.core.downloader.base.AppDownloader import com.vanced.manager.core.downloader.util.DownloadStatus @@ -33,10 +32,12 @@ class MicrogDownloader( onStatus(DownloadStatus.StartInstall) }, onError = { error, fileName -> - onStatus(DownloadStatus.Error( - displayError = "Failed to download $fileName", - stacktrace = error - )) + onStatus( + DownloadStatus.Error( + displayError = "Failed to download $fileName", + stacktrace = error + ) + ) } ) } diff --git a/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt index 024618d086..bb8bf89724 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt @@ -23,13 +23,15 @@ class MusicDownloader( absoluteVersion = getLatestOrProvidedAppVersion(musicVersionPref, appVersions) downloadFiles( - downloadFiles = arrayOf(DownloadFile( - call = musicAPI.getFiles( - version = absoluteVersion, - variant = managerVariantPref, - ), - fileName = "music.apk" - )), + downloadFiles = arrayOf( + DownloadFile( + call = musicAPI.getFiles( + version = absoluteVersion, + variant = managerVariantPref, + ), + fileName = "music.apk" + ) + ), onProgress = { progress -> onStatus(DownloadStatus.Progress(progress)) }, @@ -40,10 +42,12 @@ class MusicDownloader( onStatus(DownloadStatus.StartInstall) }, onError = { error, fileName -> - onStatus(DownloadStatus.Error( - displayError = "Failed to download $fileName", - stacktrace = error - )) + onStatus( + DownloadStatus.Error( + displayError = "Failed to download $fileName", + stacktrace = error + ) + ) } ) } diff --git a/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt index a5f4c40d1b..8a66d25534 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt @@ -53,10 +53,12 @@ class VancedDownloader( onStatus(DownloadStatus.StartInstall) }, onError = { error, fileName -> - onStatus(DownloadStatus.Error( - displayError = "Failed to download $fileName", - stacktrace = error - )) + onStatus( + DownloadStatus.Error( + displayError = "Failed to download $fileName", + stacktrace = error + ) + ) } ) } diff --git a/app/src/main/java/com/vanced/manager/core/installer/service/AppInstallService.kt b/app/src/main/java/com/vanced/manager/core/installer/service/AppInstallService.kt index bef5867c7f..bd2cf420ca 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/service/AppInstallService.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/service/AppInstallService.kt @@ -24,7 +24,10 @@ class AppInstallService : Service() { sendBroadcast(Intent().apply { action = APP_INSTALL_STATUS putExtra(EXTRA_INSTALL_STATUS, status) - putExtra(EXTRA_INSTALL_EXTRA, intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE)) + putExtra( + EXTRA_INSTALL_EXTRA, + intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + ) }) } } diff --git a/app/src/main/java/com/vanced/manager/core/preferences/ManagerPreference.kt b/app/src/main/java/com/vanced/manager/core/preferences/ManagerPreference.kt index 479928da9a..c698311f81 100644 --- a/app/src/main/java/com/vanced/manager/core/preferences/ManagerPreference.kt +++ b/app/src/main/java/com/vanced/manager/core/preferences/ManagerPreference.kt @@ -70,7 +70,7 @@ class ManagerPreference<T>( var value by mutableStateOf(sharedPreferences.getter(key, defaultValue) ?: defaultValue) private set - + operator fun getValue( thisRef: Any?, property: KProperty<*> diff --git a/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceHolder.kt b/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceHolder.kt index 613b9aa3ed..3da7135c51 100644 --- a/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceHolder.kt +++ b/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceHolder.kt @@ -7,14 +7,20 @@ import com.vanced.manager.core.preferences.managerStringSetPreference import com.vanced.manager.ui.theme.defAccentColor var useCustomTabsPref by managerBooleanPreference(USE_CUSTOM_TABS_KEY) -var managerVariantPref by managerStringPreference(MANAGER_VARIANT_KEY, MANAGER_VARIANT_DEFAULT_VALUE) +var managerVariantPref by managerStringPreference( + MANAGER_VARIANT_KEY, + MANAGER_VARIANT_DEFAULT_VALUE +) var managerThemePref by managerStringPreference(MANAGER_THEME_KEY, MANAGER_THEME_DEFAULT_VALUE) var managerAccentColorPref by managerLongPreference(MANAGER_ACCENT_COLOR_KEY, defAccentColor) var vancedThemePref by managerStringPreference(APP_VANCED_THEME_KEY, VANCED_THEME_DEFAULT_VALUE) var vancedVersionPref by managerStringPreference(APP_VANCED_VERSION_KEY, APP_VERSION_DEFAULT_VALUE) -var vancedLanguagesPref by managerStringSetPreference(APP_VANCED_LANGUAGE_KEY, VANCED_LANGUAGE_DEFAULT_VALUE) +var vancedLanguagesPref by managerStringSetPreference( + APP_VANCED_LANGUAGE_KEY, + VANCED_LANGUAGE_DEFAULT_VALUE +) var musicVersionPref by managerStringPreference(APP_MUSIC_VERSION_KEY, APP_VERSION_DEFAULT_VALUE) diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt index 6f6f570960..934e326e36 100644 --- a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt +++ b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt @@ -74,72 +74,72 @@ class AppDtoMapper( appVersions: List<String>?, appLanguages: List<String>?, ) = when (appName) { - VANCED_NAME -> listOf( - InstallationOption.SingleSelect( - titleId = R.string.app_installation_options_theme, - getOption = { vancedThemePref }, - setOption = { - vancedThemePref = it - }, - items = appThemes?.map { theme -> - InstallationOptionItem( - displayText = { - theme.replaceFirstChar { - it.titlecase(Locale.getDefault()) - } - }, - key = theme - ) - } ?: emptyList(), - ), - InstallationOption.SingleSelect( - titleId = R.string.app_installation_options_version, - getOption = { vancedVersionPref }, - setOption = { - vancedVersionPref = it - }, - items = appVersions?.map { version -> - InstallationOptionItem( - displayText = { "v$version" }, - key = version - ) - }?.plus(latestVersionRadioButton)?.reversed() ?: emptyList(), - ), - InstallationOption.MultiSelect( - titleId = R.string.app_installation_options_language, - getOption = { vancedLanguagesPref }, - addOption = { - vancedLanguagesPref = vancedLanguagesPref + it - }, - removeOption = { - vancedLanguagesPref = vancedLanguagesPref - it - }, - items = appLanguages?.map { language -> - InstallationOptionItem( - displayText = { - val locale = Locale(it) - locale.getDisplayName(locale) - }, - key = language - ) - } ?: emptyList(), - ), - ) - MUSIC_NAME -> listOf( - InstallationOption.SingleSelect( - titleId = R.string.app_installation_options_version, - getOption = { musicVersionPref }, - setOption = { - musicVersionPref = it - }, - items = appVersions?.map { version -> - InstallationOptionItem( - displayText = { version }, - key = version - ) - } ?: emptyList(), - ) + VANCED_NAME -> listOf( + InstallationOption.SingleSelect( + titleId = R.string.app_installation_options_theme, + getOption = { vancedThemePref }, + setOption = { + vancedThemePref = it + }, + items = appThemes?.map { theme -> + InstallationOptionItem( + displayText = { + theme.replaceFirstChar { + it.titlecase(Locale.getDefault()) + } + }, + key = theme + ) + } ?: emptyList(), + ), + InstallationOption.SingleSelect( + titleId = R.string.app_installation_options_version, + getOption = { vancedVersionPref }, + setOption = { + vancedVersionPref = it + }, + items = appVersions?.map { version -> + InstallationOptionItem( + displayText = { "v$version" }, + key = version + ) + }?.plus(latestVersionRadioButton)?.reversed() ?: emptyList(), + ), + InstallationOption.MultiSelect( + titleId = R.string.app_installation_options_language, + getOption = { vancedLanguagesPref }, + addOption = { + vancedLanguagesPref = vancedLanguagesPref + it + }, + removeOption = { + vancedLanguagesPref = vancedLanguagesPref - it + }, + items = appLanguages?.map { language -> + InstallationOptionItem( + displayText = { + val locale = Locale(it) + locale.getDisplayName(locale) + }, + key = language + ) + } ?: emptyList(), + ), + ) + MUSIC_NAME -> listOf( + InstallationOption.SingleSelect( + titleId = R.string.app_installation_options_version, + getOption = { musicVersionPref }, + setOption = { + musicVersionPref = it + }, + items = appVersions?.map { version -> + InstallationOptionItem( + displayText = { version }, + key = version + ) + } ?: emptyList(), ) - else -> null - } + ) + else -> null + } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index bb3c5dffe2..6e31136a00 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -7,7 +7,7 @@ import android.content.IntentFilter import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.compose.animation.* +import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.CompositionLocalProvider @@ -23,11 +23,13 @@ import com.vanced.manager.ui.theme.ManagerTheme import com.vanced.manager.ui.theme.isDark import com.vanced.manager.ui.util.Screen import com.vanced.manager.ui.viewmodel.InstallViewModel +import com.vanced.manager.ui.viewmodel.MainViewModel import org.koin.androidx.viewmodel.ext.android.viewModel class MainActivity : ComponentActivity() { private val installViewModel: InstallViewModel by viewModel() + private val mainViewModel: MainViewModel by viewModel() private val backPressHandler = BackPressHandler() @@ -46,7 +48,7 @@ class MainActivity : ComponentActivity() { @OptIn( ExperimentalAnimationApi::class, ExperimentalMaterial3Api::class, - ExperimentalFoundationApi::class + ExperimentalFoundationApi::class, ) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -72,6 +74,7 @@ class MainActivity : ComponentActivity() { when (val screen = backStack.last()) { is Screen.Home -> { HomeLayout( + viewModel = mainViewModel, onToolbarScreenSelected = { backStack.push(it) }, @@ -124,7 +127,11 @@ class MainActivity : ComponentActivity() { ) } is Screen.Install -> { - InstallScreen(screen.appName, screen.appVersions) + InstallScreen( + appName = screen.appName, + appVersions = screen.appVersions, + viewModel = installViewModel + ) } } } diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt index c19a68644b..886b002de9 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt @@ -1,14 +1,9 @@ package com.vanced.manager.ui.component.layout -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.util.DefaultContentPaddingVertical @Composable fun ManagerLazyColumn( diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScaffold.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScaffold.kt index 06f747fb82..6a9fc88f2b 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScaffold.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScaffold.kt @@ -20,13 +20,13 @@ fun ManagerScaffold( // CompositionLocalProvider( // LocalAbsoluteTonalElevation provides absoluteTonalElevation // ) { - Scaffold( - modifier = modifier, - scaffoldState = scaffoldState, - topBar = topBar, - floatingActionButton = floatingActionButton, - floatingActionButtonPosition = floatingActionButtonPosition, - content = content - ) + Scaffold( + modifier = modifier, + scaffoldState = scaffoldState, + topBar = topBar, + floatingActionButton = floatingActionButton, + floatingActionButtonPosition = floatingActionButtonPosition, + content = content + ) // } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSwipeRefresh.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSwipeRefresh.kt index 311952207f..a03508c1f8 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSwipeRefresh.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSwipeRefresh.kt @@ -3,13 +3,9 @@ package com.vanced.manager.ui.component.layout import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.unit.dp import com.google.accompanist.swiperefresh.SwipeRefresh import com.google.accompanist.swiperefresh.SwipeRefreshIndicator import com.google.accompanist.swiperefresh.SwipeRefreshState -import com.vanced.manager.ui.component.card.ManagerCard -import com.vanced.manager.ui.component.color.managerAccentColor @Composable fun ManagerSwipeRefresh( diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ScrollableItemRow.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ScrollableItemRow.kt index 65dd614961..a20d65444c 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ScrollableItemRow.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ScrollableItemRow.kt @@ -1,7 +1,6 @@ package com.vanced.manager.ui.component.layout import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState diff --git a/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenu.kt b/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenu.kt index 22b12c59f2..d8a8493603 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenu.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenu.kt @@ -1,9 +1,17 @@ package com.vanced.manager.ui.component.menu -import androidx.compose.animation.* -import androidx.compose.animation.core.* -import androidx.compose.foundation.layout.* -import androidx.compose.runtime.* +import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.core.MutableTransitionState +import androidx.compose.animation.core.animateFloat +import androidx.compose.animation.core.tween +import androidx.compose.animation.core.updateTransition +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.IntrinsicSize +import androidx.compose.foundation.layout.width +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt index f9ea847fc6..93c1b29425 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt @@ -1,26 +1,17 @@ package com.vanced.manager.ui.component.preference -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material.TextButton import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.toMutableStateList import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.vanced.manager.R -import com.vanced.manager.core.preferences.CheckboxPreference -import com.vanced.manager.core.preferences.ManagerPreference import com.vanced.manager.core.preferences.RadioButtonPreference -import com.vanced.manager.ui.component.button.ManagerThemedTextButton import com.vanced.manager.ui.component.text.ManagerText import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.widget.list.CheckboxItem -import kotlinx.coroutines.launch @Composable fun CheckboxDialogPreference( diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt index 20a2c89dc1..7ed9213ffe 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt @@ -1,11 +1,8 @@ package com.vanced.manager.ui.component.preference import androidx.compose.runtime.Composable -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.unit.dp -import com.vanced.manager.core.preferences.ManagerPreference import com.vanced.manager.ui.widget.checkbox.ManagerAnimatedCheckbox -import kotlinx.coroutines.launch @Composable fun CheckboxPreference( diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt index 2563ae89bf..e4de9b96c2 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt @@ -11,11 +11,9 @@ import androidx.compose.ui.unit.dp import com.vanced.manager.ui.component.card.ManagerTonalCard import com.vanced.manager.ui.component.color.managerAnimatedColor import com.vanced.manager.ui.component.list.ManagerListItem -import com.vanced.manager.ui.component.modifier.managerClickable import com.vanced.manager.ui.component.text.ManagerText import com.vanced.manager.ui.theme.LargeShape import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal -import com.vanced.manager.ui.util.DefaultContentPaddingVertical @Composable fun Preference( diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt index 93af305677..533895e2e1 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt @@ -4,7 +4,7 @@ import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items import androidx.compose.material3.TextButton -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.vanced.manager.R diff --git a/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt index b6740a9b68..08dd4c38ec 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt @@ -67,7 +67,7 @@ private val vancedTeam = listOf( ) ) -private val otherContributors = listOf( +private val otherContributors = listOf( Person( name = "bhatVikrant", contribution = "Website" @@ -132,7 +132,9 @@ fun AboutLayout( } ) { paddingValues -> ManagerLazyColumn( - modifier = Modifier.fillMaxSize().padding(paddingValues), + modifier = Modifier + .fillMaxSize() + .padding(paddingValues), ) { item { ManagerTonalCard( diff --git a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt index 468fadec15..54a165e5b9 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt @@ -4,7 +4,10 @@ import androidx.compose.animation.* import androidx.compose.foundation.layout.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.MoreVert -import androidx.compose.material3.* +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.TextButton import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Modifier @@ -33,12 +36,12 @@ import com.vanced.manager.ui.viewmodel.MainViewModel import com.vanced.manager.ui.widget.app.AppCard import com.vanced.manager.ui.widget.app.AppCardPlaceholder import com.vanced.manager.ui.widget.layout.managerCategory -import org.koin.androidx.compose.getViewModel @ExperimentalMaterial3Api @ExperimentalAnimationApi @Composable fun HomeLayout( + viewModel: MainViewModel, onToolbarScreenSelected: (Screen) -> Unit, onAppInstallPress: ( appName: String, @@ -46,11 +49,10 @@ fun HomeLayout( installationOptions: List<InstallationOption>? ) -> Unit ) { - val viewModel: MainViewModel = getViewModel() - val appState by viewModel.appState.collectAsState() - val refreshState = rememberSwipeRefreshState(isRefreshing = appState is MainViewModel.AppState.Fetching) + val refreshState = + rememberSwipeRefreshState(isRefreshing = appState is MainViewModel.AppState.Fetching) var isMenuExpanded by remember { mutableStateOf(false) } val dropdownScreens = remember { listOf(Screen.Settings, Screen.About) } @@ -69,7 +71,7 @@ fun HomeLayout( contentDescription = "Navigation" ) } - + ManagerDropdownMenu( expanded = isMenuExpanded, onDismissRequest = { @@ -116,7 +118,11 @@ fun HomeLayout( diskCachePolicy(CachePolicy.ENABLED) } - var showAppInfoDialog by rememberSaveable { mutableStateOf(false) } + var showAppInfoDialog by rememberSaveable { + mutableStateOf( + false + ) + } AppCard( appName = app.name, @@ -124,7 +130,11 @@ fun HomeLayout( appInstalledVersion = app.installedVersion, appRemoteVersion = app.remoteVersion, onAppDownloadClick = { - onAppInstallPress(app.name, app.versions, app.installationOptions) + onAppInstallPress( + app.name, + app.versions, + app.installationOptions + ) }, onAppUninstallClick = { /*TODO*/ }, onAppLaunchClick = { /*TODO*/ }, @@ -135,7 +145,10 @@ fun HomeLayout( if (showAppInfoDialog) { ManagerDialog( - title = managerString(R.string.app_info_title, app.name), + title = managerString( + R.string.app_info_title, + app.name + ), onDismissRequest = { showAppInfoDialog = false }, confirmButton = { TextButton(onClick = { diff --git a/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt b/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt index 7e95292c7b..c0b394e392 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt @@ -8,7 +8,10 @@ import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.ArrowDropDown import androidx.compose.material.icons.rounded.Done -import androidx.compose.material3.* +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ExtendedFloatingActionButton +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment @@ -30,7 +33,6 @@ import com.vanced.manager.ui.component.topappbar.ManagerTopAppBar import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal import com.vanced.manager.ui.viewmodel.InstallViewModel -import org.koin.androidx.compose.getViewModel @OptIn( ExperimentalFoundationApi::class, @@ -39,10 +41,9 @@ import org.koin.androidx.compose.getViewModel @Composable fun InstallScreen( appName: String, - appVersions: List<String>? + appVersions: List<String>?, + viewModel: InstallViewModel, ) { - val viewModel: InstallViewModel = getViewModel() - var startedProcess by rememberSaveable { mutableStateOf(false) } val logs = viewModel.logs diff --git a/app/src/main/java/com/vanced/manager/ui/util/Screen.kt b/app/src/main/java/com/vanced/manager/ui/util/Screen.kt index 33806919a4..cfb77b6250 100644 --- a/app/src/main/java/com/vanced/manager/ui/util/Screen.kt +++ b/app/src/main/java/com/vanced/manager/ui/util/Screen.kt @@ -13,19 +13,21 @@ sealed class Screen( displayName = R.string.app_name ) - object Settings: Screen( + object Settings : Screen( route = "settings", displayName = R.string.toolbar_settings, ) - object About: Screen( + object About : Screen( route = "about", displayName = R.string.toolbar_about, ) + object Logs : Screen( route = "logs", displayName = R.string.toolbar_logs, ) + data class InstallPreferences( val appName: String, val appVersions: List<String>?, diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt index 2d399076df..94a80705c9 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt @@ -83,11 +83,14 @@ class InstallViewModel( downloader.download(appVersions) { downloadStatus -> when (downloadStatus) { is DownloadStatus.File -> log(Log.Info("Downloading ${downloadStatus.fileName}")) - is DownloadStatus.Error -> log(Log.Error( - displayText = downloadStatus.displayError, - stacktrace = downloadStatus.stacktrace - )) - is DownloadStatus.Progress -> status = Status.Progress(downloadStatus.progress / 100) + is DownloadStatus.Error -> log( + Log.Error( + displayText = downloadStatus.displayError, + stacktrace = downloadStatus.stacktrace + ) + ) + is DownloadStatus.Progress -> status = + Status.Progress(downloadStatus.progress / 100) is DownloadStatus.StartInstall -> { log(Log.Success("Successfully downloaded $appName")) installApp(appName, appVersions) diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt index 73a82bba8c..fd820950af 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt @@ -8,7 +8,6 @@ import com.vanced.manager.core.preferences.holder.musicEnabled import com.vanced.manager.core.preferences.holder.vancedEnabled import com.vanced.manager.domain.model.App import com.vanced.manager.repository.JsonRepository -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch diff --git a/app/src/main/java/com/vanced/manager/ui/widget/app/AppCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/app/AppCard.kt index cd58c59516..e0748a7b4a 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/app/AppCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/app/AppCard.kt @@ -5,7 +5,6 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.size import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Info import androidx.compose.material.icons.outlined.Info import androidx.compose.material.icons.rounded.DeleteForever import androidx.compose.material.icons.rounded.Download @@ -19,7 +18,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import coil.compose.ImagePainter import com.vanced.manager.R -import com.vanced.manager.ui.component.button.ManagerIconButton import com.vanced.manager.ui.component.text.AppVersionText import com.vanced.manager.ui.component.text.ManagerText diff --git a/app/src/main/java/com/vanced/manager/ui/widget/app/AppCardPlaceholder.kt b/app/src/main/java/com/vanced/manager/ui/widget/app/AppCardPlaceholder.kt index 92ae807b30..42d766d111 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/app/AppCardPlaceholder.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/app/AppCardPlaceholder.kt @@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier diff --git a/app/src/main/java/com/vanced/manager/ui/widget/layout/CategoryLayout.kt b/app/src/main/java/com/vanced/manager/ui/widget/layout/CategoryLayout.kt index 3ad5489eb2..031c48691e 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/layout/CategoryLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/layout/CategoryLayout.kt @@ -1,6 +1,9 @@ package com.vanced.manager.ui.widget.layout -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyItemScope import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.items diff --git a/app/src/main/java/com/vanced/manager/ui/widget/layout/SettingsCategoryLayout.kt b/app/src/main/java/com/vanced/manager/ui/widget/layout/SettingsCategoryLayout.kt index d8235f93e3..e14576947f 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/layout/SettingsCategoryLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/layout/SettingsCategoryLayout.kt @@ -2,7 +2,6 @@ package com.vanced.manager.ui.widget.layout import androidx.compose.foundation.layout.Column import androidx.compose.runtime.Composable -import androidx.compose.ui.unit.dp @Composable fun SettingsCategoryLayout( diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt index eae4feecd6..71da7a9445 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt @@ -1,15 +1,6 @@ package com.vanced.manager.ui.widget.screens.settings -import androidx.compose.runtime.* -import androidx.compose.ui.graphics.Color -import com.vanced.manager.R -import com.vanced.manager.core.preferences.holder.managerAccentColorPref -import com.vanced.manager.ui.component.color.ManagerColorPicker -import com.vanced.manager.ui.component.preference.DialogPreference -import com.vanced.manager.ui.resources.managerString -import com.vanced.manager.ui.theme.defAccentColor -import com.vanced.manager.ui.widget.button.ManagerResetButton -import com.vanced.manager.ui.widget.button.ManagerSaveButton +import androidx.compose.runtime.Composable @Composable fun SettingsAccentColorItem() { From b3e36746dcd6fab6e227b858e4c52d8eb3727d04 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 22 Nov 2021 16:47:18 +0400 Subject: [PATCH 081/118] update viewmodel to use state instead of flow --- .../vanced/manager/ui/screens/HomeLayout.kt | 2 +- .../manager/ui/viewmodel/MainViewModel.kt | 21 +++++++------------ 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt index 54a165e5b9..d29eec9b13 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt @@ -49,7 +49,7 @@ fun HomeLayout( installationOptions: List<InstallationOption>? ) -> Unit ) { - val appState by viewModel.appState.collectAsState() + val appState = viewModel.appState val refreshState = rememberSwipeRefreshState(isRefreshing = appState is MainViewModel.AppState.Fetching) diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt index fd820950af..103f6db7be 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt @@ -1,6 +1,9 @@ package com.vanced.manager.ui.viewmodel import android.util.Log +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.vanced.manager.core.preferences.holder.managerVariantPref @@ -8,8 +11,6 @@ import com.vanced.manager.core.preferences.holder.musicEnabled import com.vanced.manager.core.preferences.holder.vancedEnabled import com.vanced.manager.domain.model.App import com.vanced.manager.repository.JsonRepository -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch class MainViewModel( @@ -17,22 +18,16 @@ class MainViewModel( ) : ViewModel() { sealed class AppState { - data class Fetching(val placeholderAppsCount: Int) : AppState() - data class Success(val apps: List<App>) : AppState() - data class Error(val error: String) : AppState() - } - private val _appState = MutableStateFlow<AppState>(AppState.Fetching(3)) - val appState: StateFlow<AppState> = _appState + var appState by mutableStateOf<AppState>(AppState.Fetching(3)) + private set fun fetch() { viewModelScope.launch { - val vancedEnabled = vancedEnabled - val musicEnabled = musicEnabled val isNonroot = managerVariantPref == "nonroot" var appsCount = 0 @@ -41,7 +36,7 @@ class MainViewModel( if (musicEnabled) appsCount++ if (isNonroot) appsCount++ - _appState.value = AppState.Fetching(appsCount) + appState = AppState.Fetching(appsCount) try { with(repository.fetch()) { @@ -53,11 +48,11 @@ class MainViewModel( if (isNonroot) add(microg) } - _appState.value = AppState.Success(apps) + appState = AppState.Success(apps) } } catch (e: Exception) { val error = "failed to fetch: \n${e.stackTraceToString()}" - _appState.value = AppState.Error(error) + appState = AppState.Error(error) Log.d("MainViewModel", error) } } From 19f8219c3c1e9936c370c6f3558fc84a36b8327e Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 22 Nov 2021 17:31:15 +0400 Subject: [PATCH 082/118] bind launch action to app card --- .../manager/core/util/VancedAppPackages.kt | 3 + .../com/vanced/manager/di/ViewModelModule.kt | 3 +- .../vanced/manager/ui/screens/HomeLayout.kt | 8 ++- .../manager/ui/viewmodel/MainViewModel.kt | 56 +++++++++++++++++-- .../vanced/manager/ui/widget/app/AppCard.kt | 24 ++++---- 5 files changed, 75 insertions(+), 19 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/core/util/VancedAppPackages.kt diff --git a/app/src/main/java/com/vanced/manager/core/util/VancedAppPackages.kt b/app/src/main/java/com/vanced/manager/core/util/VancedAppPackages.kt new file mode 100644 index 0000000000..e9b5661cd4 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/util/VancedAppPackages.kt @@ -0,0 +1,3 @@ +package com.vanced.manager.core.util + +const val VANCED_PACKAGE = "" \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt index 4aebd1216a..20f62c99cf 100644 --- a/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt +++ b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt @@ -2,10 +2,11 @@ package com.vanced.manager.di import com.vanced.manager.ui.viewmodel.InstallViewModel import com.vanced.manager.ui.viewmodel.MainViewModel +import org.koin.android.ext.koin.androidApplication import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.dsl.module val viewModelModule = module { - viewModel { MainViewModel(get()) } + viewModel { MainViewModel(get(), androidApplication()) } viewModel { InstallViewModel(get(), get(), get(), get(), get(), get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt index d29eec9b13..254553bb6f 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt @@ -137,7 +137,13 @@ fun HomeLayout( ) }, onAppUninstallClick = { /*TODO*/ }, - onAppLaunchClick = { /*TODO*/ }, + onAppLaunchClick = { + viewModel.launchApp( + appName = app.name, + appPackage = app.packageName, + appPackageRoot = app.packageNameRoot + ) + }, onAppInfoClick = { showAppInfoDialog = true } diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt index 103f6db7be..b458a8cebb 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt @@ -1,21 +1,32 @@ package com.vanced.manager.ui.viewmodel +import android.app.Application +import android.content.ActivityNotFoundException +import android.content.ComponentName +import android.content.Intent import android.util.Log import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue -import androidx.lifecycle.ViewModel +import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.viewModelScope import com.vanced.manager.core.preferences.holder.managerVariantPref import com.vanced.manager.core.preferences.holder.musicEnabled import com.vanced.manager.core.preferences.holder.vancedEnabled import com.vanced.manager.domain.model.App +import com.vanced.manager.network.util.MICROG_NAME +import com.vanced.manager.network.util.MUSIC_NAME +import com.vanced.manager.network.util.VANCED_NAME import com.vanced.manager.repository.JsonRepository import kotlinx.coroutines.launch class MainViewModel( - private val repository: JsonRepository -) : ViewModel() { + private val repository: JsonRepository, + private val app: Application +) : AndroidViewModel(app) { + + private val isNonroot + get() = managerVariantPref == "nonroot" sealed class AppState { data class Fetching(val placeholderAppsCount: Int) : AppState() @@ -28,8 +39,6 @@ class MainViewModel( fun fetch() { viewModelScope.launch { - val isNonroot = managerVariantPref == "nonroot" - var appsCount = 0 if (vancedEnabled) appsCount++ @@ -53,8 +62,37 @@ class MainViewModel( } catch (e: Exception) { val error = "failed to fetch: \n${e.stackTraceToString()}" appState = AppState.Error(error) - Log.d("MainViewModel", error) + Log.d(TAG, error) + } + } + } + + fun launchApp( + appName: String, + appPackage: String, + appPackageRoot: String? + ) { + val pkg = if (isNonroot) appPackage else appPackageRoot ?: appPackage + val component = ComponentName( + /* pkg = */ appPackage, + /* cls = */ when (appName) { + VANCED_NAME -> "$pkg.HomeActivity" + MUSIC_NAME -> "$pkg.activities.MusicActivity" + MICROG_NAME -> "org.microg.gms.ui.SettingsActivity" + else -> throw IllegalArgumentException("$appName is not a valid app") } + ) + + try { + app.startActivity( + Intent().apply { + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + setComponent(component) + } + ) + } catch (e: ActivityNotFoundException) { + Log.d(TAG, "Unable to launch $appName") + e.printStackTrace() } } @@ -62,4 +100,10 @@ class MainViewModel( fetch() } + companion object { + + const val TAG = "MainViewModel" + + } + } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/app/AppCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/app/AppCard.kt index e0748a7b4a..fccebea87a 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/app/AppCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/app/AppCard.kt @@ -75,17 +75,19 @@ fun AppCard( ) }, appActionsRow = { - IconButton(onClick = onAppUninstallClick) { - Icon( - imageVector = Icons.Rounded.DeleteForever, - contentDescription = "Uninstall" - ) - } - IconButton(onClick = onAppLaunchClick) { - Icon( - imageVector = Icons.Rounded.Launch, - contentDescription = "Launch", - ) + if (appInstalledVersion != null) { + IconButton(onClick = onAppUninstallClick) { + Icon( + imageVector = Icons.Rounded.DeleteForever, + contentDescription = "Uninstall" + ) + } + IconButton(onClick = onAppLaunchClick) { + Icon( + imageVector = Icons.Rounded.Launch, + contentDescription = "Launch", + ) + } } IconButton(onClick = onAppDownloadClick) { Icon( From 7141df8af8997ded0260299ae64d7c321735a637 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 23 Nov 2021 18:28:04 +0400 Subject: [PATCH 083/118] implement nonroot uninstallation --- app/src/main/AndroidManifest.xml | 3 +- .../installer/service/AppInstallService.kt | 15 +++--- .../installer/service/AppUninstallService.kt | 39 ++++++++++++++ .../vanced/manager/core/installer/util/PM.kt | 54 +++++++++++-------- .../com/vanced/manager/ui/MainActivity.kt | 22 +++++--- .../vanced/manager/ui/screens/HomeLayout.kt | 6 ++- .../manager/ui/viewmodel/MainViewModel.kt | 8 +++ 7 files changed, 107 insertions(+), 40 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/core/installer/service/AppUninstallService.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d23988b9c8..ae12ca2a6d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,9 +41,8 @@ android:theme="@style/Theme.MaterialComponents.NoActionBar" android:label="@string/app_name"/> - <service android:name="com.xinto.apkhelper.services.PackageManagerService" /> - <service android:name=".core.installer.service.AppInstallService" /> + <service android:name=".core.installer.service.AppUninstallService" /> </application> diff --git a/app/src/main/java/com/vanced/manager/core/installer/service/AppInstallService.kt b/app/src/main/java/com/vanced/manager/core/installer/service/AppInstallService.kt index bd2cf420ca..ed3d318304 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/service/AppInstallService.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/service/AppInstallService.kt @@ -12,7 +12,9 @@ class AppInstallService : Service() { flags: Int, startId: Int ): Int { - when (val status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -999)) { + val extraStatus = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -999) + val extraStatusMessage = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) + when (extraStatus) { PackageInstaller.STATUS_PENDING_USER_ACTION -> { startActivity( intent.getParcelableExtra<Intent>(Intent.EXTRA_INTENT).apply { @@ -22,12 +24,9 @@ class AppInstallService : Service() { } else -> { sendBroadcast(Intent().apply { - action = APP_INSTALL_STATUS - putExtra(EXTRA_INSTALL_STATUS, status) - putExtra( - EXTRA_INSTALL_EXTRA, - intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) - ) + action = APP_INSTALL_ACTION + putExtra(EXTRA_INSTALL_STATUS, extraStatus) + putExtra(EXTRA_INSTALL_EXTRA, extraStatusMessage) }) } } @@ -38,7 +37,7 @@ class AppInstallService : Service() { override fun onBind(intent: Intent?): IBinder? = null companion object { - const val APP_INSTALL_STATUS = "APP_INSTALL_STATUS" + const val APP_INSTALL_ACTION = "APP_INSTALL_ACTION" const val EXTRA_INSTALL_STATUS = "EXTRA_INSTALL_STATUS" const val EXTRA_INSTALL_EXTRA = "EXTRA_INSTALL_EXTRA" diff --git a/app/src/main/java/com/vanced/manager/core/installer/service/AppUninstallService.kt b/app/src/main/java/com/vanced/manager/core/installer/service/AppUninstallService.kt new file mode 100644 index 0000000000..a06af6532a --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/installer/service/AppUninstallService.kt @@ -0,0 +1,39 @@ +package com.vanced.manager.core.installer.service + +import android.app.Service +import android.content.Intent +import android.content.pm.PackageInstaller +import android.os.IBinder + +class AppUninstallService : Service() { + + override fun onStartCommand( + intent: Intent, + flags: Int, + startId: Int + ): Int { + when (intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -999)) { + PackageInstaller.STATUS_PENDING_USER_ACTION -> { + startActivity( + intent.getParcelableExtra<Intent>(Intent.EXTRA_INTENT).apply { + this?.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + ) + } + else -> { + sendBroadcast(Intent().apply { + action = APP_UNINSTALL_ACTION + }) + } + } + stopSelf() + return START_NOT_STICKY + } + + override fun onBind(intent: Intent?): IBinder? = null + + companion object { + const val APP_UNINSTALL_ACTION = "APP_UNINSTALL_ACTION" + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/installer/util/PM.kt b/app/src/main/java/com/vanced/manager/core/installer/util/PM.kt index 8bb1f08a12..c419e33f40 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/util/PM.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/util/PM.kt @@ -7,6 +7,7 @@ import android.content.pm.PackageInstaller import android.content.pm.PackageManager import android.os.Build import com.vanced.manager.core.installer.service.AppInstallService +import com.vanced.manager.core.installer.service.AppUninstallService import java.io.File import java.io.FileInputStream @@ -17,7 +18,7 @@ fun installApp(apk: File, context: Context) { val session = packageInstaller.openSession(packageInstaller.createSession(sessionParams)) writeApkToSession(apk, session) - session.commit(getIntentSender(context)) + session.commit(context.installIntentSender) session.close() } @@ -28,10 +29,28 @@ fun installSplitApp(apks: Array<File>, context: Context) { for (apk in apks) { writeApkToSession(apk, session) } - session.commit(getIntentSender(context)) + session.commit(context.installIntentSender) session.close() } +fun uninstallPackage(pkg: String, context: Context) { + val packageInstaller = context.packageManager.packageInstaller + packageInstaller.uninstall(pkg, context.uninstallIntentSender) +} + +private fun writeApkToSession( + apk: File, + session: PackageInstaller.Session +) { + val inputStream = FileInputStream(apk) + val outputStream = session.openWrite(apk.name, 0, apk.length()) + inputStream.copyTo(outputStream, byteArraySize) + session.fsync(outputStream) + inputStream.close() + outputStream.flush() + outputStream.close() +} + private val intentFlags get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) PendingIntent.FLAG_MUTABLE @@ -47,27 +66,18 @@ private val sessionParams } } -private fun getIntentSender(context: Context) = - PendingIntent.getService( - context, +private val Context.installIntentSender + get() = PendingIntent.getService( + this, 0, - Intent(context, AppInstallService::class.java), + Intent(this, AppInstallService::class.java), intentFlags ).intentSender -private fun writeApkToSession( - apk: File, - session: PackageInstaller.Session -) { - val inputStream = FileInputStream(apk) - val outputStream = session.openWrite(apk.name, 0, apk.length()) - val buffer = ByteArray(byteArraySize) - var length: Int - while (inputStream.read(buffer).also { length = it } > 0) { - outputStream.write(buffer, 0, length) - } - session.fsync(outputStream) - inputStream.close() - outputStream.flush() - outputStream.close() -} \ No newline at end of file +private val Context.uninstallIntentSender + get() = PendingIntent.getService( + this, + 0, + Intent(this, AppUninstallService::class.java), + intentFlags + ).intentSender \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index 6e31136a00..006d0c7ff5 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -17,6 +17,7 @@ import com.github.zsoltk.compose.backpress.LocalBackPressHandler import com.github.zsoltk.compose.router.Router import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.vanced.manager.core.installer.service.AppInstallService +import com.vanced.manager.core.installer.service.AppUninstallService import com.vanced.manager.ui.component.color.managerSurfaceColor import com.vanced.manager.ui.screens.* import com.vanced.manager.ui.theme.ManagerTheme @@ -36,12 +37,18 @@ class MainActivity : ComponentActivity() { private val installBroadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { - if (intent?.action != AppInstallService.APP_INSTALL_STATUS) return - - installViewModel.postInstallStatus( - pmStatus = intent.getIntExtra(AppInstallService.EXTRA_INSTALL_STATUS, -999), - extra = intent.getStringExtra(AppInstallService.EXTRA_INSTALL_EXTRA)!!, - ) + when (intent?.action) { + AppInstallService.APP_INSTALL_ACTION -> { + installViewModel.postInstallStatus( + pmStatus = intent.getIntExtra(AppInstallService.EXTRA_INSTALL_STATUS, -999), + extra = intent.getStringExtra(AppInstallService.EXTRA_INSTALL_EXTRA)!!, + ) + mainViewModel.fetch() + } + AppUninstallService.APP_UNINSTALL_ACTION -> { + mainViewModel.fetch() + } + } } } @@ -151,7 +158,8 @@ class MainActivity : ComponentActivity() { registerReceiver( installBroadcastReceiver, IntentFilter().apply { - addAction(AppInstallService.APP_INSTALL_STATUS) + addAction(AppInstallService.APP_INSTALL_ACTION) + addAction(AppUninstallService.APP_UNINSTALL_ACTION) } ) } diff --git a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt index 254553bb6f..1777fa38b4 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt @@ -136,7 +136,11 @@ fun HomeLayout( app.installationOptions ) }, - onAppUninstallClick = { /*TODO*/ }, + onAppUninstallClick = { + viewModel.uninstallApp( + appPackage = app.packageName + ) + }, onAppLaunchClick = { viewModel.launchApp( appName = app.name, diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt index b458a8cebb..8b82a49851 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt @@ -10,6 +10,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.viewModelScope +import com.vanced.manager.core.installer.util.uninstallPackage import com.vanced.manager.core.preferences.holder.managerVariantPref import com.vanced.manager.core.preferences.holder.musicEnabled import com.vanced.manager.core.preferences.holder.vancedEnabled @@ -96,6 +97,13 @@ class MainViewModel( } } + //TODO implement root uninstallation + fun uninstallApp( + appPackage: String, + ) { + uninstallPackage(appPackage, app) + } + init { fetch() } From 770221290a299f78a033dde086284ff69e938d90 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 23 Nov 2021 18:35:57 +0400 Subject: [PATCH 084/118] clean up viewmodel --- .../com/vanced/manager/ui/MainActivity.kt | 1 + .../manager/ui/viewmodel/MainViewModel.kt | 25 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index 006d0c7ff5..7915ea3004 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -59,6 +59,7 @@ class MainActivity : ComponentActivity() { ) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + mainViewModel.fetch() setContent { ManagerTheme { val surfaceColor = managerSurfaceColor() diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt index 8b82a49851..23d0276022 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt @@ -35,18 +35,12 @@ class MainViewModel( data class Error(val error: String) : AppState() } - var appState by mutableStateOf<AppState>(AppState.Fetching(3)) + var appState by mutableStateOf<AppState>(AppState.Fetching(appCount)) private set fun fetch() { viewModelScope.launch { - var appsCount = 0 - - if (vancedEnabled) appsCount++ - if (musicEnabled) appsCount++ - if (isNonroot) appsCount++ - - appState = AppState.Fetching(appsCount) + appState = AppState.Fetching(appCount) try { with(repository.fetch()) { @@ -104,14 +98,19 @@ class MainViewModel( uninstallPackage(appPackage, app) } - init { - fetch() - } + private val appCount: Int + get() { + var appsCount = 0 - companion object { + if (vancedEnabled) appsCount++ + if (musicEnabled) appsCount++ + if (isNonroot) appsCount++ - const val TAG = "MainViewModel" + return appsCount + } + companion object { + const val TAG = "MainViewModel" } } \ No newline at end of file From 1c11980aeb6e8475d8fa0471a3bd5266dcb6e013 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sat, 27 Nov 2021 15:24:22 +0400 Subject: [PATCH 085/118] adjust version name in about layout --- .../com/vanced/manager/ui/screens/AboutLayout.kt | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt index 08dd4c38ec..b99855a6f8 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt @@ -15,8 +15,8 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString -import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp +import com.vanced.manager.BuildConfig import com.vanced.manager.R import com.vanced.manager.ui.component.card.ManagerLinkCard import com.vanced.manager.ui.component.card.ManagerTonalCard @@ -154,11 +154,14 @@ fun AboutLayout( ManagerText( modifier = Modifier, text = buildAnnotatedString { - append("Re") - withStyle(style = SpanStyle(Color(0xFFBBB529))) { - append("@Compose") - } - append("d") + append(BuildConfig.VERSION_NAME) + val compose = "@Compose" + val startIndex = BuildConfig.VERSION_NAME.indexOf(compose) + addStyle( + style = SpanStyle(Color(0xFFBBB529)), + start = startIndex, + end = startIndex + compose.length + ) }, textStyle = MaterialTheme.typography.titleSmall ) From 4717c8da4aa84bb950872f8b6a09db4d93c4c9ea Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sat, 27 Nov 2021 15:30:30 +0400 Subject: [PATCH 086/118] improve edge-to-edge layout --- .../manager/ui/component/layout/ScrollableItemRow.kt | 8 ++++++++ .../java/com/vanced/manager/ui/screens/AboutLayout.kt | 3 +-- .../main/java/com/vanced/manager/ui/screens/HomeLayout.kt | 6 ++---- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ScrollableItemRow.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ScrollableItemRow.kt index a20d65444c..e76cde7aab 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ScrollableItemRow.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ScrollableItemRow.kt @@ -1,6 +1,8 @@ package com.vanced.manager.ui.component.layout import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState @@ -20,8 +22,14 @@ fun <T> ScrollableItemRow( horizontalArrangement = Arrangement.spacedBy(8.dp), state = state ) { + item { + Spacer(Modifier.width(8.dp)) + } items(items) { item -> content(item) } + item { + Spacer(Modifier.width(8.dp)) + } } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt index b99855a6f8..6031a55cb3 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt @@ -191,8 +191,7 @@ fun AboutLayout( managerCategory(aboutCategorySources) { ScrollableItemRow( modifier = Modifier - .fillMaxWidth() - .padding(horizontal = DefaultContentPaddingHorizontal), + .fillMaxWidth(), items = sources ) { source -> ManagerLinkCard( diff --git a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt index 1777fa38b4..50bef3b605 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt @@ -192,8 +192,7 @@ fun HomeLayout( managerCategory(homeCategorySupportUs) { ScrollableItemRow( modifier = Modifier - .fillMaxWidth() - .padding(horizontal = DefaultContentPaddingHorizontal), + .fillMaxWidth(), items = sponsors ) { sponsor -> ManagerLinkCard( @@ -206,8 +205,7 @@ fun HomeLayout( managerCategory(homeCategorySocialMedia) { ScrollableItemRow( modifier = Modifier - .fillMaxWidth() - .padding(horizontal = DefaultContentPaddingHorizontal), + .fillMaxWidth(), items = socialMedia ) { socialMedia -> ManagerLinkCard( From ea8b359e9e8f6c3956ab96d6461013aaa8bd2075 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sat, 27 Nov 2021 15:48:37 +0400 Subject: [PATCH 087/118] improve installation preferences UI --- .../manager/ui/component/layout/ManagerLazyColumn.kt | 3 +++ .../manager/ui/screens/InstallPreferencesScreen.kt | 9 ++++++++- .../com/vanced/manager/ui/widget/list/CheckboxItem.kt | 8 ++++---- .../vanced/manager/ui/widget/list/RadiobuttonItem.kt | 10 +++++----- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt index 886b002de9..26f49e968b 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt @@ -1,5 +1,6 @@ package com.vanced.manager.ui.component.layout +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.runtime.Composable @@ -8,10 +9,12 @@ import androidx.compose.ui.Modifier @Composable fun ManagerLazyColumn( modifier: Modifier = Modifier, + contentPadding: PaddingValues = PaddingValues(), content: LazyListScope.() -> Unit ) { LazyColumn( modifier = modifier, + contentPadding = contentPadding, content = content ) } diff --git a/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt b/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt index f185901618..432d263317 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt @@ -18,6 +18,7 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp import com.vanced.manager.R import com.vanced.manager.domain.model.InstallationOption import com.vanced.manager.ui.component.card.ManagerTonalCard @@ -102,7 +103,13 @@ fun InstallPreferencesScreen( text = managerString(installationOption.itemTitleId), textStyle = MaterialTheme.typography.titleLarge, ) - ManagerLazyColumn { + ManagerLazyColumn( + contentPadding = PaddingValues( + start = 4.dp, + end = 4.dp, + bottom = DefaultContentPaddingVertical + ) + ) { when (installationOption) { is InstallationOption.MultiSelect -> { items(installationOption.items) { item -> diff --git a/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt index afdd6c6988..e61695f249 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt @@ -1,14 +1,14 @@ package com.vanced.manager.ui.widget.list import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material3.Text +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import com.vanced.manager.ui.component.color.managerTextColor import com.vanced.manager.ui.component.list.ManagerSelectableListItem import com.vanced.manager.ui.component.modifier.managerClickable +import com.vanced.manager.ui.component.text.ManagerText import com.vanced.manager.ui.widget.checkbox.ManagerAnimatedCheckbox @Composable @@ -24,10 +24,10 @@ fun CheckboxItem( modifier = modifier .managerClickable(onClick = toggle), title = { - Text( + ManagerText( text = text, color = managerTextColor(), - fontSize = 18.sp + textStyle = MaterialTheme.typography.titleSmall ) }, trailing = { diff --git a/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt index 5e0db75221..58619e0c98 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt @@ -1,14 +1,14 @@ package com.vanced.manager.ui.widget.list import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material3.Text +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import com.vanced.manager.ui.component.color.managerTextColor import com.vanced.manager.ui.component.list.ManagerSelectableListItem import com.vanced.manager.ui.component.modifier.managerClickable +import com.vanced.manager.ui.component.text.ManagerText import com.vanced.manager.ui.widget.radiobutton.ManagerAnimatedRadiobutton @Composable @@ -21,13 +21,13 @@ fun <T> RadiobuttonItem( ) { val onClick = { onSelect(tag) } ManagerSelectableListItem( - modifier = Modifier + modifier = modifier .managerClickable(onClick = onClick), title = { - Text( + ManagerText( text = text, color = managerTextColor(), - fontSize = 18.sp + textStyle = MaterialTheme.typography.titleSmall ) }, trailing = { From b6533e3b3751a82b2bd51047b5b3c5f42747e9a0 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sat, 27 Nov 2021 16:15:02 +0400 Subject: [PATCH 088/118] implement callback for finish button click --- app/src/main/java/com/vanced/manager/ui/MainActivity.kt | 5 ++++- .../main/java/com/vanced/manager/ui/screens/InstallScreen.kt | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index 7915ea3004..c84d6ab334 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -138,7 +138,10 @@ class MainActivity : ComponentActivity() { InstallScreen( appName = screen.appName, appVersions = screen.appVersions, - viewModel = installViewModel + viewModel = installViewModel, + onFinishClick = { + backStack.newRoot(Screen.Home) + } ) } } diff --git a/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt b/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt index c0b394e392..a2c7785c9c 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt @@ -43,6 +43,7 @@ fun InstallScreen( appName: String, appVersions: List<String>?, viewModel: InstallViewModel, + onFinishClick: () -> Unit ) { var startedProcess by rememberSaveable { mutableStateOf(false) } @@ -82,7 +83,7 @@ fun InstallScreen( icon = { Icon(Icons.Rounded.Done, null) }, - onClick = { /*TODO*/ }, + onClick = onFinishClick, ) } } From ff510d7ce0984c1fabd9377c50fed6b71a5fc63d Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 29 Nov 2021 19:43:42 +0400 Subject: [PATCH 089/118] implement new remote data type --- app/proguard-rules.pro | 2 +- .../java/com/vanced/manager/di/APIModule.kt | 1 + .../com/vanced/manager/di/MapperModule.kt | 6 +- .../com/vanced/manager/di/NetworkModule.kt | 5 +- .../vanced/manager/di/PackageManagerModule.kt | 12 +-- .../com/vanced/manager/di/PreferenceModule.kt | 1 + .../com/vanced/manager/di/RepositoryModule.kt | 29 +++++--- .../com/vanced/manager/di/ServiceModule.kt | 31 +++++--- .../com/vanced/manager/di/ViewModelModule.kt | 31 +++++++- .../com/vanced/manager/domain/model/App.kt | 4 - .../com/vanced/manager/domain/model/Data.kt | 6 ++ .../com/vanced/manager/domain/model/Json.kt | 9 --- .../vanced/manager/domain/pkg/PkgManager.kt | 30 ++++---- .../com/vanced/manager/network/DataService.kt | 11 +++ .../com/vanced/manager/network/JsonService.kt | 11 --- .../vanced/manager/network/model/AppDto.kt | 5 +- .../manager/network/model/AppDtoMapper.kt | 74 +++++++++---------- .../vanced/manager/network/model/DataDto.kt | 13 ++++ .../manager/network/model/DataDtoMapper.kt | 26 +++++++ .../vanced/manager/network/model/JsonDto.kt | 11 --- .../manager/network/model/JsonDtoMapper.kt | 21 ------ .../vanced/manager/network/util/Constants.kt | 3 +- .../manager/repository/DataRepository.kt | 9 +++ .../manager/repository/JsonRepository.kt | 9 --- .../manager/repository/JsonRepositoryImpl.kt | 16 ---- .../manager/repository/MainRepository.kt | 14 ++++ .../manager/repository/MirrorRepository.kt | 14 ++++ .../vanced/manager/ui/screens/HomeLayout.kt | 8 +- .../manager/ui/viewmodel/MainViewModel.kt | 64 ++++++++-------- 29 files changed, 257 insertions(+), 219 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/domain/model/Data.kt delete mode 100644 app/src/main/java/com/vanced/manager/domain/model/Json.kt create mode 100644 app/src/main/java/com/vanced/manager/network/DataService.kt delete mode 100644 app/src/main/java/com/vanced/manager/network/JsonService.kt create mode 100644 app/src/main/java/com/vanced/manager/network/model/DataDto.kt create mode 100644 app/src/main/java/com/vanced/manager/network/model/DataDtoMapper.kt delete mode 100644 app/src/main/java/com/vanced/manager/network/model/JsonDto.kt delete mode 100644 app/src/main/java/com/vanced/manager/network/model/JsonDtoMapper.kt create mode 100644 app/src/main/java/com/vanced/manager/repository/DataRepository.kt delete mode 100644 app/src/main/java/com/vanced/manager/repository/JsonRepository.kt delete mode 100644 app/src/main/java/com/vanced/manager/repository/JsonRepositoryImpl.kt create mode 100644 app/src/main/java/com/vanced/manager/repository/MainRepository.kt create mode 100644 app/src/main/java/com/vanced/manager/repository/MirrorRepository.kt diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index c9fae9e0dd..b9f5a5bfa1 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -16,7 +16,7 @@ *; } --keep class com.vanced.manager.network.model.JsonDto { +-keep class com.vanced.manager.network.model.DataDto { *; } diff --git a/app/src/main/java/com/vanced/manager/di/APIModule.kt b/app/src/main/java/com/vanced/manager/di/APIModule.kt index 04477c78c8..bddadd8995 100644 --- a/app/src/main/java/com/vanced/manager/di/APIModule.kt +++ b/app/src/main/java/com/vanced/manager/di/APIModule.kt @@ -8,6 +8,7 @@ import okhttp3.OkHttpClient import org.koin.dsl.module import retrofit2.Retrofit +//TODO Add mirror support val apiModule = module { fun provideVancedAPI( diff --git a/app/src/main/java/com/vanced/manager/di/MapperModule.kt b/app/src/main/java/com/vanced/manager/di/MapperModule.kt index 2c0560bdaf..e6a8159cf8 100644 --- a/app/src/main/java/com/vanced/manager/di/MapperModule.kt +++ b/app/src/main/java/com/vanced/manager/di/MapperModule.kt @@ -3,7 +3,7 @@ package com.vanced.manager.di import android.content.Context import com.vanced.manager.domain.datasource.PackageInformationDataSource import com.vanced.manager.network.model.AppDtoMapper -import com.vanced.manager.network.model.JsonDtoMapper +import com.vanced.manager.network.model.DataDtoMapper import org.koin.dsl.module val mapperModule = module { @@ -15,9 +15,7 @@ val mapperModule = module { fun provideJsonMapper( appDtoMapper: AppDtoMapper - ): JsonDtoMapper = JsonDtoMapper( - appDtoMapper = appDtoMapper - ) + ) = DataDtoMapper(appDtoMapper) single { provideAppMapper(get(), get()) } single { provideJsonMapper(get()) } diff --git a/app/src/main/java/com/vanced/manager/di/NetworkModule.kt b/app/src/main/java/com/vanced/manager/di/NetworkModule.kt index 94a10c829f..94a901075f 100644 --- a/app/src/main/java/com/vanced/manager/di/NetworkModule.kt +++ b/app/src/main/java/com/vanced/manager/di/NetworkModule.kt @@ -5,9 +5,8 @@ import org.koin.dsl.module val networkModule = module { - fun provideOkHttpClient(): OkHttpClient { - return OkHttpClient() - } + fun provideOkHttpClient() = + OkHttpClient() single { provideOkHttpClient() } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/PackageManagerModule.kt b/app/src/main/java/com/vanced/manager/di/PackageManagerModule.kt index 4ea917b6d7..9c4170b209 100644 --- a/app/src/main/java/com/vanced/manager/di/PackageManagerModule.kt +++ b/app/src/main/java/com/vanced/manager/di/PackageManagerModule.kt @@ -11,19 +11,15 @@ val packageManagerModule = module { fun providePackageManager( context: Context - ): PkgManager { - return PkgManagerImpl( + ): PkgManager = + PkgManagerImpl( packageManager = context.packageManager ) - } fun providePackageInformationDataSource( pkgManager: PkgManager - ): PackageInformationDataSource { - return PackageInformationDataSourceImpl( - pkgManager = pkgManager - ) - } + ): PackageInformationDataSource = + PackageInformationDataSourceImpl(pkgManager) single { providePackageManager(get()) } single { providePackageInformationDataSource(get()) } diff --git a/app/src/main/java/com/vanced/manager/di/PreferenceModule.kt b/app/src/main/java/com/vanced/manager/di/PreferenceModule.kt index d43742ffb4..4c93449474 100644 --- a/app/src/main/java/com/vanced/manager/di/PreferenceModule.kt +++ b/app/src/main/java/com/vanced/manager/di/PreferenceModule.kt @@ -4,6 +4,7 @@ import android.content.Context import org.koin.dsl.module val preferenceModule = module { + fun provideDatastore( context: Context ) = context.getSharedPreferences("manager_settings", Context.MODE_PRIVATE) diff --git a/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt b/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt index ec4773f834..fae09460f5 100644 --- a/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt +++ b/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt @@ -1,20 +1,25 @@ package com.vanced.manager.di -import com.vanced.manager.network.JsonService -import com.vanced.manager.network.model.JsonDtoMapper -import com.vanced.manager.repository.JsonRepository -import com.vanced.manager.repository.JsonRepositoryImpl +import com.vanced.manager.network.DataService +import com.vanced.manager.network.model.DataDtoMapper +import com.vanced.manager.repository.DataRepository +import com.vanced.manager.repository.MainRepository +import com.vanced.manager.repository.MirrorRepository +import org.koin.core.qualifier.named import org.koin.dsl.module val repositoryModule = module { - fun provideJsonRepository( - jsonService: JsonService, - jsonDtoMapper: JsonDtoMapper - ): JsonRepository = JsonRepositoryImpl( - jsonService, - jsonDtoMapper - ) + fun provideMainRepository( + dataService: DataService, + dataDtoMapper: DataDtoMapper + ) = MainRepository(dataService, dataDtoMapper) - single { provideJsonRepository(get(), get()) } + fun provideMirrorRepository( + dataService: DataService, + dataDtoMapper: DataDtoMapper + ) = MirrorRepository(dataService, dataDtoMapper) + + single { provideMainRepository(get(named("main")), get()) } + single { provideMirrorRepository(get(named("mirror")), get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/ServiceModule.kt b/app/src/main/java/com/vanced/manager/di/ServiceModule.kt index 743a82aa27..5da133f876 100644 --- a/app/src/main/java/com/vanced/manager/di/ServiceModule.kt +++ b/app/src/main/java/com/vanced/manager/di/ServiceModule.kt @@ -1,22 +1,35 @@ package com.vanced.manager.di import com.google.gson.GsonBuilder -import com.vanced.manager.network.JsonService +import com.vanced.manager.network.DataService import com.vanced.manager.network.util.BASE_GITHUB +import com.vanced.manager.network.util.BASE_MIRROR import okhttp3.OkHttpClient +import org.koin.core.qualifier.named import org.koin.dsl.module import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory val serviceModule = module { - fun provideRetrofitService(okHttpClient: OkHttpClient): JsonService = - Retrofit.Builder() - .baseUrl(BASE_GITHUB) - .addConverterFactory(GsonConverterFactory.create(GsonBuilder().create())) - .client(okHttpClient) - .build() - .create(JsonService::class.java) + fun provideMainService( + okHttpClient: OkHttpClient + ) = Retrofit.Builder() + .baseUrl(BASE_GITHUB) + .addConverterFactory(GsonConverterFactory.create(GsonBuilder().create())) + .client(okHttpClient) + .build() + .create(DataService::class.java) - single { provideRetrofitService(get()) } + fun provideMirrorService( + okHttpClient: OkHttpClient + ) = Retrofit.Builder() + .baseUrl(BASE_MIRROR) + .addConverterFactory(GsonConverterFactory.create(GsonBuilder().create())) + .client(okHttpClient) + .build() + .create(DataService::class.java) + + single(named("main")) { provideMainService(get()) } + single(named("mirror")) { provideMirrorService(get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt index 20f62c99cf..7e6a3f15d4 100644 --- a/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt +++ b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt @@ -1,5 +1,15 @@ package com.vanced.manager.di +import android.app.Application +import com.vanced.manager.core.downloader.impl.MicrogDownloader +import com.vanced.manager.core.downloader.impl.MusicDownloader +import com.vanced.manager.core.downloader.impl.VancedDownloader +import com.vanced.manager.core.installer.impl.MicrogInstaller +import com.vanced.manager.core.installer.impl.MusicInstaller +import com.vanced.manager.core.installer.impl.VancedInstaller +import com.vanced.manager.repository.DataRepository +import com.vanced.manager.repository.MainRepository +import com.vanced.manager.repository.MirrorRepository import com.vanced.manager.ui.viewmodel.InstallViewModel import com.vanced.manager.ui.viewmodel.MainViewModel import org.koin.android.ext.koin.androidApplication @@ -7,6 +17,23 @@ import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.dsl.module val viewModelModule = module { - viewModel { MainViewModel(get(), androidApplication()) } - viewModel { InstallViewModel(get(), get(), get(), get(), get(), get()) } + + fun provideMainViewModel( + mainRepository: MainRepository, + mirrorRepository: MirrorRepository, + app: Application, + ) = MainViewModel(mainRepository, mirrorRepository, app) + + fun provideInstallViewModel( + vancedDownloader: VancedDownloader, + musicDownloader: MusicDownloader, + microgDownloader: MicrogDownloader, + + vancedInstaller: VancedInstaller, + musicInstaller: MusicInstaller, + microgInstaller: MicrogInstaller, + ) = InstallViewModel(vancedDownloader, musicDownloader, microgDownloader, vancedInstaller, musicInstaller, microgInstaller) + + viewModel { provideMainViewModel(get(), get(), androidApplication()) } + viewModel { provideInstallViewModel(get(), get(), get(), get(), get(), get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/domain/model/App.kt b/app/src/main/java/com/vanced/manager/domain/model/App.kt index a93d7dc0ef..82db872ea0 100644 --- a/app/src/main/java/com/vanced/manager/domain/model/App.kt +++ b/app/src/main/java/com/vanced/manager/domain/model/App.kt @@ -6,13 +6,9 @@ data class App( val remoteVersionCode: Int, val installedVersion: String?, val installedVersionCode: Int?, - val installedVersionRoot: String?, - val installedVersionCodeRoot: Int?, val iconUrl: String?, val appStatus: AppStatus, - val appStatusRoot: AppStatus, val packageName: String, - val packageNameRoot: String?, val changelog: String, val url: String?, val versions: List<String>?, diff --git a/app/src/main/java/com/vanced/manager/domain/model/Data.kt b/app/src/main/java/com/vanced/manager/domain/model/Data.kt new file mode 100644 index 0000000000..89577d2328 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/domain/model/Data.kt @@ -0,0 +1,6 @@ +package com.vanced.manager.domain.model + +data class Data( + val manager: App, + val apps: List<App>, +) diff --git a/app/src/main/java/com/vanced/manager/domain/model/Json.kt b/app/src/main/java/com/vanced/manager/domain/model/Json.kt deleted file mode 100644 index ad1d20e139..0000000000 --- a/app/src/main/java/com/vanced/manager/domain/model/Json.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.vanced.manager.domain.model - -data class Json( - val isMicrogBroken: Boolean, - val manager: App, - val vanced: App, - val music: App, - val microg: App -) diff --git a/app/src/main/java/com/vanced/manager/domain/pkg/PkgManager.kt b/app/src/main/java/com/vanced/manager/domain/pkg/PkgManager.kt index 3e01ad1b67..885dceb3f3 100644 --- a/app/src/main/java/com/vanced/manager/domain/pkg/PkgManager.kt +++ b/app/src/main/java/com/vanced/manager/domain/pkg/PkgManager.kt @@ -25,23 +25,25 @@ class PkgManagerImpl( @SuppressLint("WrongConstant") @Suppress("DEPRECATION") @Throws(PackageManager.NameNotFoundException::class) - override suspend fun getVersionCode(packageName: String): Int { - return with(packageManager) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - getPackageInfo(packageName, PACKAGE_FLAG_ALL_OFF) - .longVersionCode - .and(MAJOR_IGNORE) - .toInt() - } else { - getPackageInfo(packageName, PACKAGE_FLAG_ALL_OFF) - .versionCode - } + override suspend fun getVersionCode( + packageName: String + ) = with(packageManager) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + getPackageInfo(packageName, PACKAGE_FLAG_ALL_OFF) + .longVersionCode + .and(MAJOR_IGNORE) + .toInt() + } else { + getPackageInfo(packageName, PACKAGE_FLAG_ALL_OFF) + .versionCode } } @SuppressLint("WrongConstant") @Throws(PackageManager.NameNotFoundException::class) - override suspend fun getVersionName(packageName: String): String = - packageManager.getPackageInfo(packageName, PACKAGE_FLAG_ALL_OFF) - .versionName + override suspend fun getVersionName( + packageName: String + ): String = packageManager + .getPackageInfo(packageName, PACKAGE_FLAG_ALL_OFF) + .versionName } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/DataService.kt b/app/src/main/java/com/vanced/manager/network/DataService.kt new file mode 100644 index 0000000000..a18e50380e --- /dev/null +++ b/app/src/main/java/com/vanced/manager/network/DataService.kt @@ -0,0 +1,11 @@ +package com.vanced.manager.network + +import com.vanced.manager.network.model.DataDto +import retrofit2.http.GET + +interface DataService { + + @GET("latest.json") + suspend fun get(): DataDto + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/JsonService.kt b/app/src/main/java/com/vanced/manager/network/JsonService.kt deleted file mode 100644 index 48a8836376..0000000000 --- a/app/src/main/java/com/vanced/manager/network/JsonService.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.vanced.manager.network - -import com.vanced.manager.network.model.JsonDto -import retrofit2.http.GET - -interface JsonService { - - @GET("latest.json") - suspend fun get(): JsonDto - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDto.kt b/app/src/main/java/com/vanced/manager/network/model/AppDto.kt index ed5042121e..d1161ca6ba 100644 --- a/app/src/main/java/com/vanced/manager/network/model/AppDto.kt +++ b/app/src/main/java/com/vanced/manager/network/model/AppDto.kt @@ -5,11 +5,10 @@ import com.google.gson.annotations.SerializedName data class AppDto( @SerializedName("name") val name: String, @SerializedName("version") val version: String, - @SerializedName("versionCode") val versionCode: Int, + @SerializedName("version_code") val versionCode: Int, @SerializedName("changelog") val changelog: String, - @SerializedName("icon_url") val iconUrl: String? = null, + @SerializedName("icon_url") val iconUrl: String, @SerializedName("package_name") val packageName: String, - @SerializedName("package_name_root") val packageNameRoot: String? = null, @SerializedName("url") val url: String? = null, @SerializedName("versions") val versions: List<String>? = null, @SerializedName("themes") val themes: List<String>? = null, diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt index 934e326e36..fc310eecec 100644 --- a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt +++ b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt @@ -17,8 +17,8 @@ import com.vanced.manager.network.util.VANCED_NAME import java.util.* class AppDtoMapper( - private val packageInformationDataSource: PackageInformationDataSource, - context: Context + private val pkgInfoDataSource: PackageInformationDataSource, + private val context: Context ) : EntityMapper<AppDto, App> { private val latestVersionRadioButton = @@ -27,46 +27,40 @@ class AppDtoMapper( key = "latest" ) - override suspend fun mapToModel(entity: AppDto): App = - with(entity) { - val localVersionCode = packageInformationDataSource.getVersionCode(packageName) - val localVersionCodeRoot = - packageInformationDataSource.getVersionCode(packageNameRoot ?: "") - val localVersionName = packageInformationDataSource.getVersionName(packageName) - val localVersionNameRoot = - packageInformationDataSource.getVersionName(packageNameRoot ?: "") - App( - name = name, - remoteVersion = version, - remoteVersionCode = versionCode, - installedVersion = localVersionName, - installedVersionCode = localVersionCode, - installedVersionRoot = localVersionNameRoot, - installedVersionCodeRoot = localVersionCodeRoot, - appStatus = compareVersionCodes(versionCode, localVersionCode), - appStatusRoot = compareVersionCodes(versionCode, localVersionCodeRoot), - packageName = packageName, - packageNameRoot = packageNameRoot, - iconUrl = iconUrl, - changelog = changelog, - url = url, - versions = versions, - themes = themes, - languages = languages, - installationOptions = getInstallationOptions(name, themes, versions, languages) - ) - } + override suspend fun mapToModel( + entity: AppDto + ) = with(entity) { + val localVersionCode = pkgInfoDataSource.getVersionCode(packageName) + App( + name = name, + remoteVersion = version, + remoteVersionCode = versionCode, + installedVersion = pkgInfoDataSource.getVersionName(packageName), + installedVersionCode = localVersionCode, + appStatus = compareVersionCodes(versionCode, localVersionCode), + packageName = packageName, + iconUrl = iconUrl, + changelog = changelog, + url = url, + versions = versions, + themes = themes, + languages = languages, + installationOptions = getInstallationOptions(name, themes, versions, languages) + ) + } - private fun compareVersionCodes(remote: Int?, local: Int?) = - if (local != null && remote != null) { - when { - remote > local -> AppStatus.Update - remote <= local -> AppStatus.Reinstall - else -> AppStatus.Install - } - } else { - AppStatus.Install + private fun compareVersionCodes( + remote: Int?, + local: Int? + ) = if (local != null && remote != null) { + when { + remote > local -> AppStatus.Update + remote <= local -> AppStatus.Reinstall + else -> AppStatus.Install } + } else { + AppStatus.Install + } private fun getInstallationOptions( appName: String, diff --git a/app/src/main/java/com/vanced/manager/network/model/DataDto.kt b/app/src/main/java/com/vanced/manager/network/model/DataDto.kt new file mode 100644 index 0000000000..36a3242f1c --- /dev/null +++ b/app/src/main/java/com/vanced/manager/network/model/DataDto.kt @@ -0,0 +1,13 @@ +package com.vanced.manager.network.model + +import com.google.gson.annotations.SerializedName + +data class DataDto( + @SerializedName("manager") val manager: AppDto, + @SerializedName("apps") val apps: DataAppDto +) + +data class DataAppDto( + @SerializedName("nonroot") val nonroot: List<AppDto>, + @SerializedName("root") val root: List<AppDto>, +) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/model/DataDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/DataDtoMapper.kt new file mode 100644 index 0000000000..479b8cc6a3 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/network/model/DataDtoMapper.kt @@ -0,0 +1,26 @@ +package com.vanced.manager.network.model + +import com.vanced.manager.core.preferences.holder.managerVariantPref +import com.vanced.manager.domain.model.Data +import com.vanced.manager.domain.util.EntityMapper + +class DataDtoMapper( + private val appDtoMapper: AppDtoMapper +) : EntityMapper<DataDto, Data> { + + override suspend fun mapToModel( + entity: DataDto + ) = with(entity) { + Data( + manager = appDtoMapper.mapToModel(manager), + apps = + if (managerVariantPref == "root") { + apps.root + } else { + apps.nonroot + }.map { appDto -> + appDtoMapper.mapToModel(appDto) + } + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/model/JsonDto.kt b/app/src/main/java/com/vanced/manager/network/model/JsonDto.kt deleted file mode 100644 index b0b9f8d3fa..0000000000 --- a/app/src/main/java/com/vanced/manager/network/model/JsonDto.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.vanced.manager.network.model - -import com.google.gson.annotations.SerializedName - -data class JsonDto( - @SerializedName("is_microg_broken") var isMicrogBroken: Boolean, - @SerializedName("manager") var manager: AppDto, - @SerializedName("vanced") var vanced: AppDto, - @SerializedName("music") var music: AppDto, - @SerializedName("microg") var microg: AppDto -) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/model/JsonDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/JsonDtoMapper.kt deleted file mode 100644 index 7d94416402..0000000000 --- a/app/src/main/java/com/vanced/manager/network/model/JsonDtoMapper.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.vanced.manager.network.model - -import com.vanced.manager.domain.model.Json -import com.vanced.manager.domain.util.EntityMapper - -class JsonDtoMapper( - private val appDtoMapper: AppDtoMapper -) : EntityMapper<JsonDto, Json> { - - override suspend fun mapToModel(entity: JsonDto): Json = - with(entity) { - Json( - isMicrogBroken = isMicrogBroken, - manager = appDtoMapper.mapToModel(manager), - vanced = appDtoMapper.mapToModel(vanced), - music = appDtoMapper.mapToModel(music), - microg = appDtoMapper.mapToModel(microg) - ) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/util/Constants.kt b/app/src/main/java/com/vanced/manager/network/util/Constants.kt index 7e791feb3e..71dafac84a 100644 --- a/app/src/main/java/com/vanced/manager/network/util/Constants.kt +++ b/app/src/main/java/com/vanced/manager/network/util/Constants.kt @@ -1,7 +1,8 @@ package com.vanced.manager.network.util const val BASE = "https://api.vancedapp.com/api/v1/" -const val BASE_GITHUB = "https://x1nto.github.io/VancedFiles/" +const val BASE_MIRROR = "https://x1nto.github.io/VancedFiles/api/v2/" //TODO +const val BASE_GITHUB = "https://x1nto.github.io/VancedFiles/api/v2/" const val VANCED_NAME = "YouTube Vanced" const val MUSIC_NAME = "YouTube Vanced Music" diff --git a/app/src/main/java/com/vanced/manager/repository/DataRepository.kt b/app/src/main/java/com/vanced/manager/repository/DataRepository.kt new file mode 100644 index 0000000000..3879b0a896 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/repository/DataRepository.kt @@ -0,0 +1,9 @@ +package com.vanced.manager.repository + +import com.vanced.manager.domain.model.Data + +interface DataRepository { + + suspend fun fetch(): Data + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/repository/JsonRepository.kt b/app/src/main/java/com/vanced/manager/repository/JsonRepository.kt deleted file mode 100644 index 8ae38e35ef..0000000000 --- a/app/src/main/java/com/vanced/manager/repository/JsonRepository.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.vanced.manager.repository - -import com.vanced.manager.domain.model.Json - -interface JsonRepository { - - suspend fun fetch(): Json - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/repository/JsonRepositoryImpl.kt b/app/src/main/java/com/vanced/manager/repository/JsonRepositoryImpl.kt deleted file mode 100644 index 7cbc27cbe5..0000000000 --- a/app/src/main/java/com/vanced/manager/repository/JsonRepositoryImpl.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.vanced.manager.repository - -import com.vanced.manager.domain.model.Json -import com.vanced.manager.network.JsonService -import com.vanced.manager.network.model.JsonDtoMapper - -class JsonRepositoryImpl( - private val service: JsonService, - private val mapper: JsonDtoMapper -) : JsonRepository { - - override suspend fun fetch(): Json { - return mapper.mapToModel(service.get()) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/repository/MainRepository.kt b/app/src/main/java/com/vanced/manager/repository/MainRepository.kt new file mode 100644 index 0000000000..eab19bd7d9 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/repository/MainRepository.kt @@ -0,0 +1,14 @@ +package com.vanced.manager.repository + +import com.vanced.manager.network.DataService +import com.vanced.manager.network.model.DataDtoMapper + +class MainRepository( + private val mainService: DataService, + private val mapper: DataDtoMapper +) : DataRepository { + + override suspend fun fetch() = + mapper.mapToModel(mainService.get()) + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/repository/MirrorRepository.kt b/app/src/main/java/com/vanced/manager/repository/MirrorRepository.kt new file mode 100644 index 0000000000..5f0eb5ed0b --- /dev/null +++ b/app/src/main/java/com/vanced/manager/repository/MirrorRepository.kt @@ -0,0 +1,14 @@ +package com.vanced.manager.repository + +import com.vanced.manager.network.DataService +import com.vanced.manager.network.model.DataDtoMapper + +class MirrorRepository( + private val mirrorService: DataService, + private val mapper: DataDtoMapper +) : DataRepository { + + override suspend fun fetch() = + mapper.mapToModel(mirrorService.get()) + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt index 50bef3b605..e30900f9e8 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt @@ -30,7 +30,6 @@ import com.vanced.manager.ui.component.menu.ManagerDropdownMenuItem import com.vanced.manager.ui.component.text.ManagerText import com.vanced.manager.ui.component.topappbar.ManagerTopAppBar import com.vanced.manager.ui.resources.managerString -import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal import com.vanced.manager.ui.util.Screen import com.vanced.manager.ui.viewmodel.MainViewModel import com.vanced.manager.ui.widget.app.AppCard @@ -145,7 +144,6 @@ fun HomeLayout( viewModel.launchApp( appName = app.name, appPackage = app.packageName, - appPackageRoot = app.packageNameRoot ) }, onAppInfoClick = { @@ -191,8 +189,7 @@ fun HomeLayout( } managerCategory(homeCategorySupportUs) { ScrollableItemRow( - modifier = Modifier - .fillMaxWidth(), + modifier = Modifier.fillMaxWidth(), items = sponsors ) { sponsor -> ManagerLinkCard( @@ -204,8 +201,7 @@ fun HomeLayout( } managerCategory(homeCategorySocialMedia) { ScrollableItemRow( - modifier = Modifier - .fillMaxWidth(), + modifier = Modifier.fillMaxWidth(), items = socialMedia ) { socialMedia -> ManagerLinkCard( diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt index 23d0276022..7732618a7f 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt @@ -12,22 +12,25 @@ import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.viewModelScope import com.vanced.manager.core.installer.util.uninstallPackage import com.vanced.manager.core.preferences.holder.managerVariantPref -import com.vanced.manager.core.preferences.holder.musicEnabled -import com.vanced.manager.core.preferences.holder.vancedEnabled import com.vanced.manager.domain.model.App import com.vanced.manager.network.util.MICROG_NAME import com.vanced.manager.network.util.MUSIC_NAME import com.vanced.manager.network.util.VANCED_NAME -import com.vanced.manager.repository.JsonRepository +import com.vanced.manager.repository.MainRepository +import com.vanced.manager.repository.MirrorRepository import kotlinx.coroutines.launch class MainViewModel( - private val repository: JsonRepository, + private val mainRepository: MainRepository, + private val mirrorRepository: MirrorRepository, private val app: Application ) : AndroidViewModel(app) { - private val isNonroot - get() = managerVariantPref == "nonroot" + private val isRoot + get() = managerVariantPref == "root" + + private val appCount: Int + get() = if (isRoot) 2 else 3 sealed class AppState { data class Fetching(val placeholderAppsCount: Int) : AppState() @@ -42,37 +45,19 @@ class MainViewModel( viewModelScope.launch { appState = AppState.Fetching(appCount) - try { - with(repository.fetch()) { - val apps = mutableListOf<App>() - - apps.apply { - if (vancedEnabled) add(vanced) - if (musicEnabled) add(music) - if (isNonroot) add(microg) - } - - appState = AppState.Success(apps) - } - } catch (e: Exception) { - val error = "failed to fetch: \n${e.stackTraceToString()}" - appState = AppState.Error(error) - Log.d(TAG, error) - } + fetchData() } } fun launchApp( appName: String, appPackage: String, - appPackageRoot: String? ) { - val pkg = if (isNonroot) appPackage else appPackageRoot ?: appPackage val component = ComponentName( /* pkg = */ appPackage, /* cls = */ when (appName) { - VANCED_NAME -> "$pkg.HomeActivity" - MUSIC_NAME -> "$pkg.activities.MusicActivity" + VANCED_NAME -> "com.google.android.youtube.HomeActivity" + MUSIC_NAME -> "com.google.android.apps.youtube.music.activities.MusicActivity" MICROG_NAME -> "org.microg.gms.ui.SettingsActivity" else -> throw IllegalArgumentException("$appName is not a valid app") } @@ -98,16 +83,25 @@ class MainViewModel( uninstallPackage(appPackage, app) } - private val appCount: Int - get() { - var appsCount = 0 - - if (vancedEnabled) appsCount++ - if (musicEnabled) appsCount++ - if (isNonroot) appsCount++ + private suspend fun fetchData( + fromMirror: Boolean = false + ) { + try { + val repository = if (fromMirror) mirrorRepository else mainRepository + with(repository.fetch()) { + appState = AppState.Success(apps) + } + } catch (e: Exception) { + if (!fromMirror) { + fetchData(true) + return + } - return appsCount + val error = "failed to fetch: \n${e.stackTraceToString()}" + appState = AppState.Error(error) + Log.d(TAG, error) } + } companion object { const val TAG = "MainViewModel" From 275597629ea40c837eb9cd69ceb8cd4f93d15517 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 29 Nov 2021 19:45:40 +0400 Subject: [PATCH 090/118] clear logs after clicking the finish button --- .../main/java/com/vanced/manager/ui/MainActivity.kt | 1 + .../vanced/manager/ui/viewmodel/InstallViewModel.kt | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index c84d6ab334..3609ec6727 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -140,6 +140,7 @@ class MainActivity : ComponentActivity() { appVersions = screen.appVersions, viewModel = installViewModel, onFinishClick = { + installViewModel.clear() backStack.newRoot(Screen.Home) } ) diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt index 94a80705c9..1ec6871638 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt @@ -74,6 +74,11 @@ class InstallViewModel( } } + fun clear() { + logs.clear() + status = Status.Idle + } + private suspend fun downloadApp( appName: String, appVersions: List<String>?, @@ -132,9 +137,4 @@ class InstallViewModel( logs.add(data) } - private fun clear() { - logs.clear() - status = Status.Idle - } - } \ No newline at end of file From 918031bf706d625d4e752dc61f83a84ea77ad384 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 29 Nov 2021 19:56:10 +0400 Subject: [PATCH 091/118] fix app download paths --- .../core/downloader/impl/MicrogDownloader.kt | 4 ++-- .../core/downloader/impl/MusicDownloader.kt | 4 ++-- .../core/downloader/impl/VancedDownloader.kt | 4 ++-- .../core/downloader/util/DownloadPath.kt | 19 +++++++++++++++++++ .../core/installer/impl/MicrogInstaller.kt | 8 ++++++-- .../core/installer/impl/MusicInstaller.kt | 13 +++++++++---- .../core/installer/impl/VancedInstaller.kt | 9 ++++++--- 7 files changed, 46 insertions(+), 15 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/core/downloader/util/DownloadPath.kt diff --git a/app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt index 9a02b181b4..99581ce38f 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt @@ -4,6 +4,7 @@ import android.content.Context import com.vanced.manager.core.downloader.api.MicrogAPI import com.vanced.manager.core.downloader.base.AppDownloader import com.vanced.manager.core.downloader.util.DownloadStatus +import com.vanced.manager.core.downloader.util.getMicrogPath import java.io.File class MicrogDownloader( @@ -43,8 +44,7 @@ class MicrogDownloader( } override fun getSavedFilePath(): String { - val directory = - File(context.getExternalFilesDir("microg")!!.path) + val directory = File(getMicrogPath(context)) if (!directory.exists()) directory.mkdirs() diff --git a/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt index bb8bf89724..b715b76e08 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt @@ -4,6 +4,7 @@ import android.content.Context import com.vanced.manager.core.downloader.api.MusicAPI import com.vanced.manager.core.downloader.base.AppDownloader import com.vanced.manager.core.downloader.util.DownloadStatus +import com.vanced.manager.core.downloader.util.getVancedMusicPath import com.vanced.manager.core.preferences.holder.managerVariantPref import com.vanced.manager.core.preferences.holder.musicVersionPref import com.vanced.manager.core.util.getLatestOrProvidedAppVersion @@ -53,8 +54,7 @@ class MusicDownloader( } override fun getSavedFilePath(): String { - val directory = - File(context.getExternalFilesDir("vancedmusic")!!.path + "$absoluteVersion/$managerVariantPref") + val directory = File(getVancedMusicPath(absoluteVersion, managerVariantPref, context)) if (!directory.exists()) directory.mkdirs() diff --git a/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt index 8a66d25534..7f8811f20b 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt @@ -4,6 +4,7 @@ import android.content.Context import com.vanced.manager.core.downloader.api.VancedAPI import com.vanced.manager.core.downloader.base.AppDownloader import com.vanced.manager.core.downloader.util.DownloadStatus +import com.vanced.manager.core.downloader.util.getVancedMusicPath import com.vanced.manager.core.preferences.holder.managerVariantPref import com.vanced.manager.core.preferences.holder.vancedLanguagesPref import com.vanced.manager.core.preferences.holder.vancedThemePref @@ -64,8 +65,7 @@ class VancedDownloader( } override fun getSavedFilePath(): String { - val directory = - File(context.getExternalFilesDir("vanced")!!.path + "/$absoluteVersion/$managerVariantPref") + val directory = File(getVancedMusicPath(absoluteVersion, managerVariantPref, context)) if (!directory.exists()) directory.mkdirs() diff --git a/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadPath.kt b/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadPath.kt new file mode 100644 index 0000000000..0692eb902b --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadPath.kt @@ -0,0 +1,19 @@ +package com.vanced.manager.core.downloader.util + +import android.content.Context + +fun getVancedPath( + version: String, + variant: String, + context: Context +) = context.getExternalFilesDir("vanced_youtube")!!.path + "/$version/$variant" + +fun getVancedMusicPath( + version: String, + variant: String, + context: Context +) = context.getExternalFilesDir("vanced_music")!!.path + "/$version/$variant" + +fun getMicrogPath( + context: Context +) = context.getExternalFilesDir("microg")!!.path \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt index 766a9b2dcd..6c673a75d0 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt @@ -1,6 +1,7 @@ package com.vanced.manager.core.installer.impl import android.content.Context +import com.vanced.manager.core.downloader.util.getMicrogPath import com.vanced.manager.core.installer.base.AppInstaller import com.vanced.manager.core.installer.util.installApp import java.io.File @@ -9,8 +10,11 @@ class MicrogInstaller( private val context: Context ) : AppInstaller() { - override fun install(appVersions: List<String>?) { - val musicApk = File(context.getExternalFilesDir("microg/microg.apk")!!.path) + override fun install( + appVersions: List<String>? + ) { + val musicApk = File(getMicrogPath(context) + "/microg.apk") + installApp(musicApk, context) } diff --git a/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt index 8704ffb654..825c29ecb9 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt @@ -1,20 +1,25 @@ package com.vanced.manager.core.installer.impl import android.content.Context +import com.vanced.manager.core.downloader.util.getVancedMusicPath import com.vanced.manager.core.installer.base.AppInstaller import com.vanced.manager.core.installer.util.installApp import com.vanced.manager.core.preferences.holder.managerVariantPref import com.vanced.manager.core.preferences.holder.musicVersionPref +import com.vanced.manager.core.preferences.holder.vancedVersionPref +import com.vanced.manager.core.util.getLatestOrProvidedAppVersion import java.io.File class MusicInstaller( private val context: Context ) : AppInstaller() { - override fun install(appVersions: List<String>?) { - val musicApk = File( - context.getExternalFilesDir("music/$musicVersionPref/$managerVariantPref/music.apk")!!.path - ) + override fun install( + appVersions: List<String>? + ) { + val absoluteVersion = getLatestOrProvidedAppVersion(musicVersionPref, appVersions) + + val musicApk = File(getVancedMusicPath(absoluteVersion, managerVariantPref, context) + "/music.apk") installApp(musicApk, context) } diff --git a/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt index 5a99d105ec..7ba18eaddb 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt @@ -1,21 +1,24 @@ package com.vanced.manager.core.installer.impl import android.content.Context +import com.vanced.manager.core.downloader.util.getVancedPath import com.vanced.manager.core.installer.base.AppInstaller import com.vanced.manager.core.installer.util.installSplitApp import com.vanced.manager.core.preferences.holder.managerVariantPref import com.vanced.manager.core.preferences.holder.vancedVersionPref import com.vanced.manager.core.util.getLatestOrProvidedAppVersion +import java.io.File class VancedInstaller( private val context: Context ) : AppInstaller() { - override fun install(appVersions: List<String>?) { + override fun install( + appVersions: List<String>? + ) { val absoluteVersion = getLatestOrProvidedAppVersion(vancedVersionPref, appVersions) - val apks = context - .getExternalFilesDir("vanced/$absoluteVersion/$managerVariantPref")!! + val apks = File(getVancedPath(absoluteVersion, managerVariantPref, context)) .listFiles { file -> file.extension == "apk" } From ce3977c667cdaef7e9eb304a967cc76f65f11688 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 30 Nov 2021 13:58:12 +0400 Subject: [PATCH 092/118] fix more downloader issues --- .../vanced/manager/core/downloader/impl/VancedDownloader.kt | 4 ++-- .../com/vanced/manager/core/downloader/util/DownloadPath.kt | 2 +- .../vanced/manager/core/installer/impl/VancedInstaller.kt | 4 ++-- app/src/main/java/com/vanced/manager/core/util/Arch.kt | 2 +- app/src/main/java/com/vanced/manager/di/DownloaderModule.kt | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt index 7f8811f20b..adb6ae3bb8 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt @@ -4,7 +4,7 @@ import android.content.Context import com.vanced.manager.core.downloader.api.VancedAPI import com.vanced.manager.core.downloader.base.AppDownloader import com.vanced.manager.core.downloader.util.DownloadStatus -import com.vanced.manager.core.downloader.util.getVancedMusicPath +import com.vanced.manager.core.downloader.util.getVancedYoutubePath import com.vanced.manager.core.preferences.holder.managerVariantPref import com.vanced.manager.core.preferences.holder.vancedLanguagesPref import com.vanced.manager.core.preferences.holder.vancedThemePref @@ -65,7 +65,7 @@ class VancedDownloader( } override fun getSavedFilePath(): String { - val directory = File(getVancedMusicPath(absoluteVersion, managerVariantPref, context)) + val directory = File(getVancedYoutubePath(absoluteVersion, managerVariantPref, context)) if (!directory.exists()) directory.mkdirs() diff --git a/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadPath.kt b/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadPath.kt index 0692eb902b..5aa02e5cd9 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadPath.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadPath.kt @@ -2,7 +2,7 @@ package com.vanced.manager.core.downloader.util import android.content.Context -fun getVancedPath( +fun getVancedYoutubePath( version: String, variant: String, context: Context diff --git a/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt index 7ba18eaddb..1d10cce107 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt @@ -1,7 +1,7 @@ package com.vanced.manager.core.installer.impl import android.content.Context -import com.vanced.manager.core.downloader.util.getVancedPath +import com.vanced.manager.core.downloader.util.getVancedYoutubePath import com.vanced.manager.core.installer.base.AppInstaller import com.vanced.manager.core.installer.util.installSplitApp import com.vanced.manager.core.preferences.holder.managerVariantPref @@ -18,7 +18,7 @@ class VancedInstaller( ) { val absoluteVersion = getLatestOrProvidedAppVersion(vancedVersionPref, appVersions) - val apks = File(getVancedPath(absoluteVersion, managerVariantPref, context)) + val apks = File(getVancedYoutubePath(absoluteVersion, managerVariantPref, context)) .listFiles { file -> file.extension == "apk" } diff --git a/app/src/main/java/com/vanced/manager/core/util/Arch.kt b/app/src/main/java/com/vanced/manager/core/util/Arch.kt index 4c2247f50b..fed980ff11 100644 --- a/app/src/main/java/com/vanced/manager/core/util/Arch.kt +++ b/app/src/main/java/com/vanced/manager/core/util/Arch.kt @@ -2,7 +2,7 @@ package com.vanced.manager.core.util import android.os.Build -val arch = when { +val arch get() = when { Build.SUPPORTED_ABIS.contains("x86") -> "x86" Build.SUPPORTED_ABIS.contains("arm64-v8a") -> "arm64_v8a" else -> "armeabi_v7a" diff --git a/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt b/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt index 050c6c330f..c9f093b62a 100644 --- a/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt +++ b/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt @@ -26,7 +26,7 @@ val downloaderModule = module { context: Context, ) = MicrogDownloader(microgAPI, context) - factory { provideVancedDownloader(get(), get()) } - factory { provideMusicDownloader(get(), get()) } - factory { provideMicrogDownloader(get(), get()) } + single { provideVancedDownloader(get(), get()) } + single { provideMusicDownloader(get(), get()) } + single { provideMicrogDownloader(get(), get()) } } \ No newline at end of file From a0761554b2b31095f59716fbfc24b8fc0012ccfe Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Thu, 2 Dec 2021 15:39:54 +0400 Subject: [PATCH 093/118] update APIs --- app/build.gradle.kts | 9 +++++---- .../ui/component/layout/ManagerScaffold.kt | 2 -- .../manager/ui/widget/list/CheckboxItem.kt | 17 +++++++---------- .../manager/ui/widget/list/RadiobuttonItem.kt | 10 +++------- build.gradle.kts | 2 +- 5 files changed, 16 insertions(+), 24 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 21d1cf9aeb..c34a6474c4 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -4,6 +4,8 @@ plugins { id("kotlin-parcelize") } +val composeVersion = "1.1.0-beta04" + android { compileSdk = 31 @@ -49,7 +51,7 @@ android { } composeOptions { - kotlinCompilerExtensionVersion = "1.1.0-alpha06" + kotlinCompilerExtensionVersion = composeVersion } } @@ -82,7 +84,7 @@ dependencies { // AndroidX implementation("androidx.core:core-ktx:1.7.0") - implementation("androidx.appcompat:appcompat:1.3.1") + implementation("androidx.appcompat:appcompat:1.4.0") implementation("androidx.browser:browser:1.4.0") implementation("androidx.preference:preference-ktx:1.1.1") implementation("androidx.activity:activity-compose:1.4.0") @@ -92,13 +94,12 @@ dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycleVersion") // Compose - val composeVersion = "1.1.0-beta03" implementation("androidx.compose.compiler:compiler:$composeVersion") implementation("androidx.compose.foundation:foundation:$composeVersion") implementation("androidx.compose.material:material-icons-core:$composeVersion") implementation("androidx.compose.material:material-icons-extended:$composeVersion") implementation("androidx.compose.material:material:$composeVersion") - implementation("androidx.compose.material3:material3:1.0.0-alpha01") + implementation("androidx.compose.material3:material3:1.0.0-alpha02") implementation("androidx.compose.runtime:runtime-livedata:$composeVersion") implementation("androidx.compose.ui:ui-tooling:$composeVersion") implementation("androidx.compose.ui:ui-util:$composeVersion") diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScaffold.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScaffold.kt index 6a9fc88f2b..b54594e4ba 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScaffold.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScaffold.kt @@ -9,7 +9,6 @@ import androidx.compose.ui.Modifier @Composable fun ManagerScaffold( modifier: Modifier = Modifier, - scaffoldState: ScaffoldState = rememberScaffoldState(), topBar: @Composable () -> Unit = {}, floatingActionButton: @Composable () -> Unit = {}, floatingActionButtonPosition: FabPosition = FabPosition.End, @@ -22,7 +21,6 @@ fun ManagerScaffold( // ) { Scaffold( modifier = modifier, - scaffoldState = scaffoldState, topBar = topBar, floatingActionButton = floatingActionButton, floatingActionButtonPosition = floatingActionButtonPosition, diff --git a/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt index e61695f249..9f16f5a4f3 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt @@ -1,15 +1,13 @@ package com.vanced.manager.ui.widget.list -import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Checkbox import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp import com.vanced.manager.ui.component.color.managerTextColor import com.vanced.manager.ui.component.list.ManagerSelectableListItem import com.vanced.manager.ui.component.modifier.managerClickable import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.widget.checkbox.ManagerAnimatedCheckbox @Composable fun CheckboxItem( @@ -31,13 +29,12 @@ fun CheckboxItem( ) }, trailing = { - ManagerAnimatedCheckbox( - size = 24.dp, - shape = CircleShape, - isChecked = isChecked - ) { - toggle() - } + Checkbox( + checked = isChecked, + onCheckedChange = { + toggle() + } + ) } ) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt index 58619e0c98..3cc8c2345e 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt @@ -1,15 +1,13 @@ package com.vanced.manager.ui.widget.list -import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.RadioButton import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp import com.vanced.manager.ui.component.color.managerTextColor import com.vanced.manager.ui.component.list.ManagerSelectableListItem import com.vanced.manager.ui.component.modifier.managerClickable import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.widget.radiobutton.ManagerAnimatedRadiobutton @Composable fun <T> RadiobuttonItem( @@ -31,10 +29,8 @@ fun <T> RadiobuttonItem( ) }, trailing = { - ManagerAnimatedRadiobutton( - size = 24.dp, - shape = CircleShape, - isSelected = isSelected, + RadioButton( + selected = isSelected, onClick = onClick ) } diff --git a/build.gradle.kts b/build.gradle.kts index a057b51296..50c0d25f54 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ buildscript { mavenCentral() } - val kotlinVersion = "1.5.31" + val kotlinVersion = "1.6.0" dependencies { classpath("com.android.tools.build:gradle:7.0.3") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") From e9e42220143442578283796357350199c633785e Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Thu, 2 Dec 2021 15:45:35 +0400 Subject: [PATCH 094/118] update clickable list items --- ...ference.kt => MultiSelectDialogPreference.kt} | 6 +++--- ...erence.kt => SingleSelectDialogPreference.kt} | 9 +++++---- .../ui/screens/InstallPreferencesScreen.kt | 9 ++++----- .../manager/ui/widget/list/CheckboxItem.kt | 16 +++++++--------- .../manager/ui/widget/list/RadiobuttonItem.kt | 12 +++++------- .../screens/settings/ManagerVariantItem.kt | 4 ++-- .../ui/widget/screens/settings/ThemeItem.kt | 4 ++-- 7 files changed, 28 insertions(+), 32 deletions(-) rename app/src/main/java/com/vanced/manager/ui/component/preference/{CheckboxDialogPreference.kt => MultiSelectDialogPreference.kt} (93%) rename app/src/main/java/com/vanced/manager/ui/component/preference/{RadiobuttonDialogPreference.kt => SingleSelectDialogPreference.kt} (91%) diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/MultiSelectDialogPreference.kt similarity index 93% rename from app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt rename to app/src/main/java/com/vanced/manager/ui/component/preference/MultiSelectDialogPreference.kt index 93c1b29425..f4532451a2 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/MultiSelectDialogPreference.kt @@ -14,7 +14,7 @@ import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.widget.list.CheckboxItem @Composable -fun CheckboxDialogPreference( +fun MultiSelectDialogPreference( preferenceTitle: String, preferenceDescription: String, isDialogVisible: Boolean, @@ -51,8 +51,8 @@ fun CheckboxDialogPreference( val (title, key) = button CheckboxItem( text = title, - isChecked = currentSelectedKeys.contains(key), - onCheck = { isChecked -> + checked = currentSelectedKeys.contains(key), + onCheckedChange = { isChecked -> onItemCheckChange(isChecked, key) } ) diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/SingleSelectDialogPreference.kt similarity index 91% rename from app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt rename to app/src/main/java/com/vanced/manager/ui/component/preference/SingleSelectDialogPreference.kt index 533895e2e1..6454962b0f 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/RadiobuttonDialogPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/preference/SingleSelectDialogPreference.kt @@ -14,7 +14,7 @@ import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.widget.list.RadiobuttonItem @Composable -fun RadiobuttonDialogPreference( +fun SingleSelectDialogPreference( preferenceTitle: String, preferenceDescription: String, isDialogVisible: Boolean, @@ -51,9 +51,10 @@ fun RadiobuttonDialogPreference( val (title, key) = button RadiobuttonItem( text = title, - tag = key, - isSelected = currentSelectedKey == key, - onSelect = onItemClick + selected = currentSelectedKey == key, + onClick = { + onItemClick(key) + } ) } } diff --git a/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt b/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt index 432d263317..f1cb4514bf 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt @@ -117,8 +117,8 @@ fun InstallPreferencesScreen( CheckboxItem( modifier = Modifier.fillMaxWidth(), text = item.displayText(item.key), - isChecked = preference.contains(item.key), - onCheck = { + checked = preference.contains(item.key), + onCheckedChange = { if (it) { installationOption.addOption(item.key) } else { @@ -134,11 +134,10 @@ fun InstallPreferencesScreen( RadiobuttonItem( modifier = Modifier.fillMaxWidth(), text = item.displayText(item.key), - isSelected = preference == item.key, - onSelect = { + selected = preference == item.key, + onClick = { installationOption.setOption(item.key) }, - tag = item.key ) } } diff --git a/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt index 9f16f5a4f3..974c5faed5 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt @@ -12,15 +12,15 @@ import com.vanced.manager.ui.component.text.ManagerText @Composable fun CheckboxItem( text: String, - isChecked: Boolean, - onCheck: (Boolean) -> Unit, + checked: Boolean, + onCheckedChange: (Boolean) -> Unit, modifier: Modifier = Modifier, ) { - val toggle = { onCheck(!isChecked) } - ManagerSelectableListItem( modifier = modifier - .managerClickable(onClick = toggle), + .managerClickable(onClick = { + onCheckedChange(!checked) + }), title = { ManagerText( text = text, @@ -30,10 +30,8 @@ fun CheckboxItem( }, trailing = { Checkbox( - checked = isChecked, - onCheckedChange = { - toggle() - } + checked = checked, + onCheckedChange = null ) } ) diff --git a/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt index 3cc8c2345e..0a4aeb7148 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt @@ -10,14 +10,12 @@ import com.vanced.manager.ui.component.modifier.managerClickable import com.vanced.manager.ui.component.text.ManagerText @Composable -fun <T> RadiobuttonItem( +fun RadiobuttonItem( text: String, - tag: T, - isSelected: Boolean, - onSelect: (tag: T) -> Unit, + selected: Boolean, + onClick: () -> Unit, modifier: Modifier = Modifier ) { - val onClick = { onSelect(tag) } ManagerSelectableListItem( modifier = modifier .managerClickable(onClick = onClick), @@ -30,8 +28,8 @@ fun <T> RadiobuttonItem( }, trailing = { RadioButton( - selected = isSelected, - onClick = onClick + selected = selected, + onClick = null ) } ) diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt index f68cc0dafd..121a30a1ad 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt @@ -4,14 +4,14 @@ import androidx.compose.runtime.* import com.vanced.manager.R import com.vanced.manager.core.preferences.RadioButtonPreference import com.vanced.manager.core.preferences.holder.managerVariantPref -import com.vanced.manager.ui.component.preference.RadiobuttonDialogPreference +import com.vanced.manager.ui.component.preference.SingleSelectDialogPreference import com.vanced.manager.ui.resources.managerString @Composable fun SettingsManagerVariantItem() { var showDialog by remember { mutableStateOf(false) } var selectedKey by remember { mutableStateOf(managerVariantPref) } - RadiobuttonDialogPreference( + SingleSelectDialogPreference( preferenceTitle = managerString( stringId = R.string.settings_preference_variant_title ), diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt index 23818eab6c..45392cef53 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt @@ -4,14 +4,14 @@ import androidx.compose.runtime.* import com.vanced.manager.R import com.vanced.manager.core.preferences.RadioButtonPreference import com.vanced.manager.core.preferences.holder.managerThemePref -import com.vanced.manager.ui.component.preference.RadiobuttonDialogPreference +import com.vanced.manager.ui.component.preference.SingleSelectDialogPreference import com.vanced.manager.ui.resources.managerString @Composable fun ThemeSettingsItem() { var showDialog by remember { mutableStateOf(false) } var selectedKey by remember { mutableStateOf(managerThemePref) } - RadiobuttonDialogPreference( + SingleSelectDialogPreference( preferenceTitle = managerString(stringId = R.string.settings_preference_theme_title), preferenceDescription = managerThemePref, isDialogVisible = showDialog, From 22ac84e4480e77bac84bf704eda78f2913f4d926 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sat, 4 Dec 2021 18:36:22 +0400 Subject: [PATCH 095/118] update installation option getter --- .../manager/network/model/AppDtoMapper.kt | 139 ++++++++++-------- 1 file changed, 78 insertions(+), 61 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt index fc310eecec..bf11e6ffe7 100644 --- a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt +++ b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt @@ -67,73 +67,90 @@ class AppDtoMapper( appThemes: List<String>?, appVersions: List<String>?, appLanguages: List<String>?, - ) = when (appName) { - VANCED_NAME -> listOf( - InstallationOption.SingleSelect( - titleId = R.string.app_installation_options_theme, - getOption = { vancedThemePref }, - setOption = { - vancedThemePref = it - }, - items = appThemes?.map { theme -> - InstallationOptionItem( - displayText = { - theme.replaceFirstChar { - it.titlecase(Locale.getDefault()) - } + ) : List<InstallationOption>? = when (appName) { + VANCED_NAME -> buildList { + if (appThemes != null) { + add( + InstallationOption.SingleSelect( + titleId = R.string.app_installation_options_theme, + getOption = { vancedThemePref }, + setOption = { + vancedThemePref = it + }, + items = appThemes.map { theme -> + InstallationOptionItem( + displayText = { + theme.replaceFirstChar { + it.titlecase(Locale.getDefault()) + } + }, + key = theme + ) }, - key = theme ) - } ?: emptyList(), - ), - InstallationOption.SingleSelect( - titleId = R.string.app_installation_options_version, - getOption = { vancedVersionPref }, - setOption = { - vancedVersionPref = it - }, - items = appVersions?.map { version -> - InstallationOptionItem( - displayText = { "v$version" }, - key = version + ) + } + if (appVersions != null) { + add( + InstallationOption.SingleSelect( + titleId = R.string.app_installation_options_version, + getOption = { vancedVersionPref }, + setOption = { + vancedVersionPref = it + }, + items = (appVersions.map { version -> + InstallationOptionItem( + displayText = { "v$version" }, + key = version + ) + } + latestVersionRadioButton).reversed(), ) - }?.plus(latestVersionRadioButton)?.reversed() ?: emptyList(), - ), - InstallationOption.MultiSelect( - titleId = R.string.app_installation_options_language, - getOption = { vancedLanguagesPref }, - addOption = { - vancedLanguagesPref = vancedLanguagesPref + it - }, - removeOption = { - vancedLanguagesPref = vancedLanguagesPref - it - }, - items = appLanguages?.map { language -> - InstallationOptionItem( - displayText = { - val locale = Locale(it) - locale.getDisplayName(locale) + ) + } + if (appLanguages != null) { + add( + InstallationOption.MultiSelect( + titleId = R.string.app_installation_options_language, + getOption = { vancedLanguagesPref }, + addOption = { + vancedLanguagesPref = vancedLanguagesPref + it + }, + removeOption = { + vancedLanguagesPref = vancedLanguagesPref - it + }, + items = appLanguages.map { language -> + InstallationOptionItem( + displayText = { + val locale = Locale(it) + locale.getDisplayName(locale) + }, + key = language + ) }, - key = language ) - } ?: emptyList(), - ), - ) - MUSIC_NAME -> listOf( - InstallationOption.SingleSelect( - titleId = R.string.app_installation_options_version, - getOption = { musicVersionPref }, - setOption = { - musicVersionPref = it - }, - items = appVersions?.map { version -> - InstallationOptionItem( - displayText = { version }, - key = version + ) + } + } + MUSIC_NAME -> buildList { + if (appVersions != null) { + add( + InstallationOption.SingleSelect( + titleId = R.string.app_installation_options_version, + getOption = { musicVersionPref }, + setOption = { + musicVersionPref = it + }, + items = (appVersions.map { version -> + InstallationOptionItem( + displayText = { "v$version" }, + key = version + ) + } + latestVersionRadioButton).reversed(), ) - } ?: emptyList(), - ) - ) + ) + } + + } else -> null } } \ No newline at end of file From cbd48dce7218b77bfe38ebd62228361833be29b0 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 12 Dec 2021 14:56:07 +0400 Subject: [PATCH 096/118] added root package manager and patcher classes --- app/build.gradle.kts | 5 + .../core/downloader/util/DownloadPath.kt | 5 + .../core/installer/base/AppInstaller.kt | 2 + .../core/installer/impl/MicrogInstaller.kt | 8 +- .../core/installer/impl/MusicInstaller.kt | 9 +- .../core/installer/impl/VancedInstaller.kt | 18 +- .../installer/service/AppInstallService.kt | 4 +- .../vanced/manager/core/installer/util/PM.kt | 41 +++-- .../manager/core/installer/util/PMRoot.kt | 139 +++++++++++++++ .../core/installer/util/PMRootStatus.kt | 72 ++++++++ .../manager/core/installer/util/Patcher.kt | 163 ++++++++++++++++++ .../vanced/manager/core/io/ManagerSuFile.kt | 32 ++++ .../com/vanced/manager/core/util/SuShell.kt | 13 ++ .../com/vanced/manager/ui/MainActivity.kt | 2 +- .../vanced/manager/ui/SplashScreenActivity.kt | 22 ++- .../manager/ui/viewmodel/InstallViewModel.kt | 24 ++- 16 files changed, 513 insertions(+), 46 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/core/installer/util/PMRoot.kt create mode 100644 app/src/main/java/com/vanced/manager/core/installer/util/PMRootStatus.kt create mode 100644 app/src/main/java/com/vanced/manager/core/installer/util/Patcher.kt create mode 100644 app/src/main/java/com/vanced/manager/core/io/ManagerSuFile.kt create mode 100644 app/src/main/java/com/vanced/manager/core/util/SuShell.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c34a6474c4..a0f70ec168 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -123,6 +123,11 @@ dependencies { implementation("com.github.skydoves:orchestra-colorpicker:1.1.0") + val libsuVersion = "3.1.2" + implementation("com.github.topjohnwu.libsu:core:$libsuVersion") + implementation("com.github.topjohnwu.libsu:io:$libsuVersion") + implementation("com.github.topjohnwu.libsu:busybox:$libsuVersion") + val koinVersion = "3.1.3" implementation("io.insert-koin:koin-android:$koinVersion") implementation("io.insert-koin:koin-androidx-compose:$koinVersion") diff --git a/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadPath.kt b/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadPath.kt index 5aa02e5cd9..76511b779f 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadPath.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadPath.kt @@ -8,6 +8,11 @@ fun getVancedYoutubePath( context: Context ) = context.getExternalFilesDir("vanced_youtube")!!.path + "/$version/$variant" +fun getStockYoutubePath( + version: String, + context: Context +) = context.getExternalFilesDir("stock_youtube")!!.path + "/$version" + fun getVancedMusicPath( version: String, variant: String, diff --git a/app/src/main/java/com/vanced/manager/core/installer/base/AppInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/base/AppInstaller.kt index 24d029944d..592290a971 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/base/AppInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/base/AppInstaller.kt @@ -4,4 +4,6 @@ abstract class AppInstaller { abstract fun install(appVersions: List<String>?) + abstract fun installRoot(appVersions: List<String>?) + } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt index 6c673a75d0..993cce4015 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt @@ -3,7 +3,7 @@ package com.vanced.manager.core.installer.impl import android.content.Context import com.vanced.manager.core.downloader.util.getMicrogPath import com.vanced.manager.core.installer.base.AppInstaller -import com.vanced.manager.core.installer.util.installApp +import com.vanced.manager.core.installer.util.PM import java.io.File class MicrogInstaller( @@ -15,7 +15,11 @@ class MicrogInstaller( ) { val musicApk = File(getMicrogPath(context) + "/microg.apk") - installApp(musicApk, context) + PM.installApp(musicApk, context) + } + + override fun installRoot(appVersions: List<String>?) { + throw IllegalAccessException("Vanced microG does not have a root installer") } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt index 825c29ecb9..2880a6a46e 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt @@ -3,10 +3,9 @@ package com.vanced.manager.core.installer.impl import android.content.Context import com.vanced.manager.core.downloader.util.getVancedMusicPath import com.vanced.manager.core.installer.base.AppInstaller -import com.vanced.manager.core.installer.util.installApp +import com.vanced.manager.core.installer.util.PM import com.vanced.manager.core.preferences.holder.managerVariantPref import com.vanced.manager.core.preferences.holder.musicVersionPref -import com.vanced.manager.core.preferences.holder.vancedVersionPref import com.vanced.manager.core.util.getLatestOrProvidedAppVersion import java.io.File @@ -21,7 +20,11 @@ class MusicInstaller( val musicApk = File(getVancedMusicPath(absoluteVersion, managerVariantPref, context) + "/music.apk") - installApp(musicApk, context) + PM.installApp(musicApk, context) + } + + override fun installRoot(appVersions: List<String>?) { + } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt index 1d10cce107..08de16fdc3 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt @@ -1,11 +1,13 @@ package com.vanced.manager.core.installer.impl import android.content.Context +import android.content.Intent +import com.vanced.manager.core.downloader.util.getStockYoutubePath import com.vanced.manager.core.downloader.util.getVancedYoutubePath import com.vanced.manager.core.installer.base.AppInstaller -import com.vanced.manager.core.installer.util.installSplitApp -import com.vanced.manager.core.preferences.holder.managerVariantPref +import com.vanced.manager.core.installer.util.* import com.vanced.manager.core.preferences.holder.vancedVersionPref +import com.vanced.manager.core.util.Message import com.vanced.manager.core.util.getLatestOrProvidedAppVersion import java.io.File @@ -18,12 +20,14 @@ class VancedInstaller( ) { val absoluteVersion = getLatestOrProvidedAppVersion(vancedVersionPref, appVersions) - val apks = File(getVancedYoutubePath(absoluteVersion, managerVariantPref, context)) - .listFiles { file -> - file.extension == "apk" - } + val apks = File(getVancedYoutubePath(absoluteVersion, "nonroot", context)) + .listFiles() + + PM.installSplitApp(apks!!, context) + } + + override fun installRoot(appVersions: List<String>?) { - installSplitApp(apks!!, context) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/installer/service/AppInstallService.kt b/app/src/main/java/com/vanced/manager/core/installer/service/AppInstallService.kt index ed3d318304..559ccd12dc 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/service/AppInstallService.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/service/AppInstallService.kt @@ -26,7 +26,7 @@ class AppInstallService : Service() { sendBroadcast(Intent().apply { action = APP_INSTALL_ACTION putExtra(EXTRA_INSTALL_STATUS, extraStatus) - putExtra(EXTRA_INSTALL_EXTRA, extraStatusMessage) + putExtra(EXTRA_INSTALL_STATUS_MESSAGE, extraStatusMessage) }) } } @@ -40,7 +40,7 @@ class AppInstallService : Service() { const val APP_INSTALL_ACTION = "APP_INSTALL_ACTION" const val EXTRA_INSTALL_STATUS = "EXTRA_INSTALL_STATUS" - const val EXTRA_INSTALL_EXTRA = "EXTRA_INSTALL_EXTRA" + const val EXTRA_INSTALL_STATUS_MESSAGE = "EXTRA_INSTALL_STATUS_MESSAGE" } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/installer/util/PM.kt b/app/src/main/java/com/vanced/manager/core/installer/util/PM.kt index c419e33f40..285cefc991 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/util/PM.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/util/PM.kt @@ -13,29 +13,32 @@ import java.io.FileInputStream private const val byteArraySize = 1024 * 1024 // Because 1,048,576 is not readable -fun installApp(apk: File, context: Context) { - val packageInstaller = context.packageManager.packageInstaller - val session = - packageInstaller.openSession(packageInstaller.createSession(sessionParams)) - writeApkToSession(apk, session) - session.commit(context.installIntentSender) - session.close() -} +object PM { -fun installSplitApp(apks: Array<File>, context: Context) { - val packageInstaller = context.packageManager.packageInstaller - val session = - packageInstaller.openSession(packageInstaller.createSession(sessionParams)) - for (apk in apks) { + fun installApp(apk: File, context: Context) { + val packageInstaller = context.packageManager.packageInstaller + val session = + packageInstaller.openSession(packageInstaller.createSession(sessionParams)) writeApkToSession(apk, session) + session.commit(context.installIntentSender) + session.close() + } + + fun installSplitApp(apks: Array<File>, context: Context) { + val packageInstaller = context.packageManager.packageInstaller + val session = + packageInstaller.openSession(packageInstaller.createSession(sessionParams)) + for (apk in apks) { + writeApkToSession(apk, session) + } + session.commit(context.installIntentSender) + session.close() } - session.commit(context.installIntentSender) - session.close() -} -fun uninstallPackage(pkg: String, context: Context) { - val packageInstaller = context.packageManager.packageInstaller - packageInstaller.uninstall(pkg, context.uninstallIntentSender) + fun uninstallPackage(pkg: String, context: Context) { + val packageInstaller = context.packageManager.packageInstaller + packageInstaller.uninstall(pkg, context.uninstallIntentSender) + } } private fun writeApkToSession( diff --git a/app/src/main/java/com/vanced/manager/core/installer/util/PMRoot.kt b/app/src/main/java/com/vanced/manager/core/installer/util/PMRoot.kt new file mode 100644 index 0000000000..9e35096f68 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/installer/util/PMRoot.kt @@ -0,0 +1,139 @@ +package com.vanced.manager.core.installer.util + +import com.topjohnwu.superuser.Shell +import com.topjohnwu.superuser.io.SuFile +import com.topjohnwu.superuser.io.SuFileOutputStream +import com.vanced.manager.core.util.errString +import com.vanced.manager.core.util.outString +import java.io.File +import java.io.IOException + +object PMRoot { + + fun installApp(apkPath: String): PMRootStatus<Nothing> { + val apk = File(apkPath) + val tmpApk = copyApkToTemp(apk) { error -> + return PMRootStatus.Error(PMRootStatusType.SESSION_FAILED_COPY, error) + } + + val install = Shell.su("pm", "install", "-r", tmpApk.absolutePath).exec() + + tmpApk.delete() + + if (!install.isSuccess) { + val errString = install.errString + return PMRootStatus.Error(getEnumForInstallFailed(errString), errString) + } + + return PMRootStatus.Success() + } + + fun installSplitApp(apkPaths: List<String>): PMRootStatus<Nothing> { + val installCreate = Shell.su("pm", "install-create", "-r").exec() + + if (!installCreate.isSuccess) + return PMRootStatus.Error(PMRootStatusType.SESSION_FAILED_CREATE, installCreate.errString) + + val sessionId = installCreate.outString + + if (sessionId.toIntOrNull() == null) + return PMRootStatus.Error(PMRootStatusType.SESSION_INVALID_ID, installCreate.errString) + + for (apkPath in apkPaths) { + val apk = File(apkPath) + val tmpApk = copyApkToTemp(apk) { error -> + return PMRootStatus.Error(PMRootStatusType.SESSION_FAILED_COPY, error) + } + + val installWrite = + Shell.su("pm", "install-write", sessionId, tmpApk.name, tmpApk.absolutePath) + .exec() + + tmpApk.delete() + + if (!installWrite.isSuccess) + return PMRootStatus.Error(PMRootStatusType.SESSION_FAILED_WRITE, installWrite.errString) + } + + val installCommit = Shell.su("pm", "install-commit", sessionId).exec() + + if (!installCommit.isSuccess) { + val errString = installCommit.errString + return PMRootStatus.Error(getEnumForInstallFailed(errString), errString) + } + + return PMRootStatus.Success() + } + + fun uninstallApp(pkg: String): PMRootStatus<Nothing> { + val uninstall = Shell.su("pm", "uninstall", pkg).exec() + + if (!uninstall.isSuccess) + return PMRootStatus.Error(PMRootStatusType.UNINSTALL_FAILED, uninstall.errString) + + return PMRootStatus.Success() + } + + fun setInstallerPackage(targetPkg: String, installerPkg: String): PMRootStatus<Nothing> { + val setInstaller = Shell.su("pm", "set-installer", targetPkg, installerPkg) + .exec() + + if (!setInstaller.isSuccess) + return PMRootStatus.Error(PMRootStatusType.ACTION_FAILED_SET_INSTALLER, setInstaller.errString) + + return PMRootStatus.Success() + } + + fun forceStopApp(pkg: String): PMRootStatus<Nothing> { + val stopApp = Shell.su("am", "force-stop", pkg).exec() + + if (!stopApp.isSuccess) + return PMRootStatus.Error(PMRootStatusType.ACTION_FAILED_FORCE_STOP_APP, stopApp.errString) + + return PMRootStatus.Success() + } + + fun getPackageDir(pkg: String): PMRootStatus<String> { + val delimeter = "path: " + val dumpsys = Shell.su("dumpsys", "package", pkg, "|", "grep", delimeter).exec() + + if (!dumpsys.isSuccess) + return PMRootStatus.Error(PMRootStatusType.ACTION_FAILED_GET_PACKAGE_DIR, dumpsys.errString) + + return PMRootStatus.Success(dumpsys.outString.removePrefix(delimeter)) + } +} + +private inline fun copyApkToTemp( + apk: File, + onError: (String) -> Unit +): SuFile { + val tmpPath = "/data/local/tmp/${apk.name}" + + val tmpApk = SuFile(tmpPath).apply { + createNewFile() + } + + try { + SuFileOutputStream.open(tmpApk).use { + it.write(apk.readBytes()) + it.flush() + } + } catch (e: IOException) { + onError(e.stackTraceToString()) + } + + return tmpApk +} + +private fun getEnumForInstallFailed(outString: String) = + when { + outString.contains("INSTALL_FAILED_ABORTED") -> PMRootStatusType.INSTALL_FAILED_ABORTED + outString.contains("INSTALL_FAILED_ALREADY_EXISTS") -> PMRootStatusType.INSTALL_FAILED_ALREADY_EXISTS + outString.contains("INSTALL_FAILED_CPU_ABI_INCOMPATIBLE") -> PMRootStatusType.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE + outString.contains("INSTALL_FAILED_INSUFFICIENT_STORAGE") -> PMRootStatusType.INSTALL_FAILED_INSUFFICIENT_STORAGE + outString.contains("INSTALL_FAILED_INVALID_APK") -> PMRootStatusType.INSTALL_FAILED_INVALID_APK + outString.contains("INSTALL_FAILED_VERSION_DOWNGRADE") -> PMRootStatusType.INSTALL_FAILED_VERSION_DOWNGRADE + outString.contains("INSTALL_PARSE_FAILED_NO_CERTIFICATES") -> PMRootStatusType.INSTALL_FAILED_PARSE_NO_CERTIFICATES + else -> PMRootStatusType.INSTALL_FAILED_UNKNOWN + } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/installer/util/PMRootStatus.kt b/app/src/main/java/com/vanced/manager/core/installer/util/PMRootStatus.kt new file mode 100644 index 0000000000..8da7394257 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/installer/util/PMRootStatus.kt @@ -0,0 +1,72 @@ +package com.vanced.manager.core.installer.util + +enum class PMRootStatusType { + ACTION_FAILED_SET_INSTALLER, + ACTION_FAILED_GET_PACKAGE_DIR, + ACTION_FAILED_FORCE_STOP_APP, + + INSTALL_SUCCESSFUL, + INSTALL_FAILED_ABORTED, + INSTALL_FAILED_ALREADY_EXISTS, + INSTALL_FAILED_CPU_ABI_INCOMPATIBLE, + INSTALL_FAILED_INSUFFICIENT_STORAGE, + INSTALL_FAILED_INVALID_APK, + INSTALL_FAILED_VERSION_DOWNGRADE, + INSTALL_FAILED_PARSE_NO_CERTIFICATES, + INSTALL_FAILED_UNKNOWN, + + LINK_FAILED_UNMOUNT, + LINK_FAILED_MOUNT, + + PATCH_FAILED_COPY, + PATCH_FAILED_CHMOD, + PATCH_FAILED_CHOWN, + PATCH_FAILED_CHCON, + PATCH_FAILED_DESTROY, + + SESSION_FAILED_CREATE, + SESSION_FAILED_WRITE, + SESSION_FAILED_COPY, + SESSION_INVALID_ID, + + SCRIPT_FAILED_SETUP_POST_FS, + SCRIPT_FAILED_SETUP_SERVICE_D, + SCRIPT_FAILED_DESTROY_POST_FS, + SCRIPT_FAILED_DESTROY_SERVICE_D, + + UNINSTALL_SUCCESSFUL, + UNINSTALL_FAILED, +} + +sealed class PMRootStatus<out V> { + data class Success<out V>(val value: V? = null) : PMRootStatus<V>() + data class Error(val error: PMRootStatusType, val message: String) : PMRootStatus<Nothing>() +} + +inline fun <V, S : PMRootStatus<V>> S.exec( + onError: (PMRootStatusType, String) -> Unit, + onSuccess: () -> Unit +) { + when (this) { + is PMRootStatus.Success<*> -> { + onSuccess() + } + is PMRootStatus.Error -> { + onError(error, message) + } + } +} + +inline fun <reified V, S : PMRootStatus<V>> S.execWithValue( + onError: (PMRootStatusType, String) -> Unit, + onSuccess: (value: V?) -> Unit +) { + when (this) { + is PMRootStatus.Success<*> -> { + onSuccess(value as V?) + } + is PMRootStatus.Error -> { + onError(error, message) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/installer/util/Patcher.kt b/app/src/main/java/com/vanced/manager/core/installer/util/Patcher.kt new file mode 100644 index 0000000000..4d0fb9036b --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/installer/util/Patcher.kt @@ -0,0 +1,163 @@ +package com.vanced.manager.core.installer.util + +import com.topjohnwu.superuser.Shell +import com.topjohnwu.superuser.io.SuFile +import com.topjohnwu.superuser.io.SuFileOutputStream +import com.vanced.manager.core.util.errString +import java.io.File +import java.io.IOException + +object Patcher { + + fun setupScript( + app: String, + pkg: String, + stockPath: String, + ): PMRootStatus<Nothing> { + val postFsDataScriptPath = getAppPostFsScriptPath(app) + val serviceDScriptPath = getAppServiceDScriptPath(app) + + val postFsDataScript = getPostFsDataScript(pkg) + val serviceDScript = getServiceDScript(getAppPatchPath(app), stockPath) + + copyScriptToDestination(postFsDataScriptPath, postFsDataScript) { error -> + return PMRootStatus.Error(PMRootStatusType.SCRIPT_FAILED_SETUP_POST_FS, error) + } + + copyScriptToDestination(serviceDScriptPath, serviceDScript) { error -> + return PMRootStatus.Error(PMRootStatusType.SCRIPT_FAILED_SETUP_SERVICE_D, error) + } + + return PMRootStatus.Success() + } + + fun movePatchToDataAdb(patchPath: String, app: String): PMRootStatus<Nothing> { + val newPatchPath = getAppPatchPath(app) + + val patchApk = File(patchPath) + val newPatchApk = SuFile(newPatchPath).apply { + if (exists()) + delete() + + createNewFile() + } + + try { + patchApk.copyTo(newPatchApk) + } catch (e: IOException) { + return PMRootStatus.Error(PMRootStatusType.PATCH_FAILED_COPY, e.stackTraceToString()) + } + + val chmod = Shell.su("chmod", "644", newPatchPath).exec() + if (!chmod.isSuccess) + return PMRootStatus.Error(PMRootStatusType.PATCH_FAILED_CHMOD, chmod.errString) + + val chown = Shell.su("chown", "system:system", newPatchPath).exec() + if (!chmod.isSuccess) + return PMRootStatus.Error(PMRootStatusType.PATCH_FAILED_CHOWN, chown.errString) + + return PMRootStatus.Success() + } + + fun chconPatch(app: String): PMRootStatus<Nothing> { + val chcon = Shell.su("chcon u:object_r:apk_data_file:s0 ${getAppPatchPath(app)}").exec() + if (!chcon.isSuccess) + return PMRootStatus.Error(PMRootStatusType.PATCH_FAILED_CHCON, chcon.errString) + + return PMRootStatus.Success() + } + + fun linkPatch(app: String, pkg: String, stockPath: String): PMRootStatus<Nothing> { + val umount = Shell.su("""for i in ${'$'}(ls /data/app/ | grep $pkg | tr " "); do umount -l "/data/app/${"$"}i/base.apk"; done """).exec() + if (!umount.isSuccess) + return PMRootStatus.Error(PMRootStatusType.LINK_FAILED_UNMOUNT, umount.errString) + + val mount = Shell.su("su", "-mm", "-c", """"mount -o bind ${getAppPatchPath(app)} $stockPath"""").exec() + if (!mount.isSuccess) + return PMRootStatus.Error(PMRootStatusType.LINK_FAILED_MOUNT, mount.errString) + + return PMRootStatus.Success() + } + + fun destroyPatch(app: String) = + cleanPatchFiles( + postFsPath = getAppPostFsScriptPath(app), + serviceDPath = getAppServiceDScriptPath(app), + patchPath = getAppPatchPath(app) + ) + + //TODO + fun destroyOldPatch(app: String) = + cleanPatchFiles( + postFsPath = "", + serviceDPath = "", + patchPath = "" + ) + + //TODO return proper error if destroying was unsuccessful + private fun cleanPatchFiles( + postFsPath: String, + serviceDPath: String, + patchPath: String, + ): PMRootStatus<Nothing> { + val postFs = SuFile(postFsPath) + if (postFs.exists() && !postFs.delete()) + return PMRootStatus.Error(PMRootStatusType.SCRIPT_FAILED_DESTROY_POST_FS, "") + + val serviceD = SuFile(serviceDPath) + if (serviceD.exists() && !serviceD.delete()) + return PMRootStatus.Error(PMRootStatusType.SCRIPT_FAILED_DESTROY_SERVICE_D, "") + + val patch = SuFile(patchPath) + if (patch.exists() && !patch.delete()) + return PMRootStatus.Error(PMRootStatusType.PATCH_FAILED_DESTROY, "") + + return PMRootStatus.Success() + } +} + +private fun getAppPatchPath(app: String) = "${getAppPatchFolderPath(app)}/base.apk" +private fun getAppPatchFolderPath(app: String) = "/data/adb/vanced_manager/$app" +private fun getAppPostFsScriptPath(app: String) = "/data/adb/post-fs-data.d/$app.sh" +private fun getAppServiceDScriptPath(app: String) = "/data/adb/service.d/$app.sh" + +//TODO support dynamic sleep timer +private fun getServiceDScript(patchPath: String, stockPath: String) = + """ + #!/system/bin/sh + while [ "${'$'}(getprop sys.boot_completed | tr -d '\r')" != "1" ]; do sleep 1; done + sleep 1 + chcon u:object_r:apk_data_file:s0 $patchPath + mount -o bind $patchPath $stockPath + """.trimIndent() + +private fun getPostFsDataScript(pkg: String) = + """ + #!/system/bin/sh + while read line; do echo \${'$'}{line} | grep $pkg | awk '{print \${'$'}2}' | xargs umount -l; done< /proc/mounts + """.trimIndent() + +private inline fun copyScriptToDestination( + scriptDestination: String, + script: String, + onError: (String) -> Unit +) { + val scriptFile = SuFile(scriptDestination) + .apply { + if (!exists()) + createNewFile() + } + + try { + SuFileOutputStream.open(scriptFile).use { + it.write(script.toByteArray()) + it.flush() + } + val chmod = Shell.su("chmod", "744", scriptFile.absolutePath).exec() + if (!chmod.isSuccess) { + onError(chmod.errString) + } + } catch (e: IOException) { + onError(e.stackTraceToString()) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/io/ManagerSuFile.kt b/app/src/main/java/com/vanced/manager/core/io/ManagerSuFile.kt new file mode 100644 index 0000000000..7c97db259a --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/io/ManagerSuFile.kt @@ -0,0 +1,32 @@ +package com.vanced.manager.core.io + +import com.topjohnwu.superuser.Shell +import com.topjohnwu.superuser.io.SuFile +import com.vanced.manager.core.util.errString +import com.vanced.manager.core.util.outString +import java.io.File + +class ManagerSuFile : SuFile { + + sealed class SuFileResult { + data class Success<out V>(val result: V? = null) : SuFileResult() + data class Error(val error: String) : SuFileResult() + } + + constructor(pathName: String) : super(pathName) + + constructor(parent: String, child: String) : super(parent, child) + + constructor(parent: File, child: String) : super(parent, child) + + private fun cmd(input: String): SuFileResult { + val cmd = Shell.su(input.replace("@@", escapedPath)).exec() + if (!cmd.isSuccess) + return SuFileResult.Error(cmd.errString) + + return SuFileResult.Success(cmd.outString) + } + + fun deleteResult() = cmd("rm -f @@ || rmdir -f @@") + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/util/SuShell.kt b/app/src/main/java/com/vanced/manager/core/util/SuShell.kt new file mode 100644 index 0000000000..7173aa05ad --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/util/SuShell.kt @@ -0,0 +1,13 @@ +package com.vanced.manager.core.util + +import com.topjohnwu.superuser.Shell + +val Shell.Result.outString + get() = out.joinToString("\n") + +val Shell.Result.errString + get() = err.joinToString("\n") + +val isMagiskInstalled + get() = Shell.su("magisk", "-c").exec().isSuccess + diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index 3609ec6727..61c268424c 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -41,7 +41,7 @@ class MainActivity : ComponentActivity() { AppInstallService.APP_INSTALL_ACTION -> { installViewModel.postInstallStatus( pmStatus = intent.getIntExtra(AppInstallService.EXTRA_INSTALL_STATUS, -999), - extra = intent.getStringExtra(AppInstallService.EXTRA_INSTALL_EXTRA)!!, + extra = intent.getStringExtra(AppInstallService.EXTRA_INSTALL_STATUS_MESSAGE)!!, ) mainViewModel.fetch() } diff --git a/app/src/main/java/com/vanced/manager/ui/SplashScreenActivity.kt b/app/src/main/java/com/vanced/manager/ui/SplashScreenActivity.kt index c2697d5c3d..1670d3866e 100644 --- a/app/src/main/java/com/vanced/manager/ui/SplashScreenActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/SplashScreenActivity.kt @@ -3,16 +3,30 @@ package com.vanced.manager.ui import android.content.Intent import android.os.Bundle import androidx.activity.ComponentActivity +import com.topjohnwu.superuser.BusyBoxInstaller +import com.topjohnwu.superuser.Shell +import com.vanced.manager.BuildConfig class SplashScreenActivity : ComponentActivity() { + init { + Shell.enableVerboseLogging = BuildConfig.DEBUG; + Shell.setDefaultBuilder( + Shell.Builder + .create() + .setInitializers(BusyBoxInstaller::class.java) + ) + } + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - startActivity( - Intent(this, MainActivity::class.java) - ) - finish() + Shell.getShell { + startActivity( + Intent(this, MainActivity::class.java) + ) + finish() + } } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt index 1ec6871638..f965d66ea2 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt @@ -63,14 +63,22 @@ class InstallViewModel( } fun postInstallStatus(pmStatus: Int, extra: String) { - viewModelScope.launch(Dispatchers.IO) { - if (pmStatus == PackageInstaller.STATUS_SUCCESS) { - status = Status.Installed - log(Log.Success("Successfully installed")) - } else { - status = Status.Failure - log(Log.Error("Failed to install app", extra)) - } + if (pmStatus == PackageInstaller.STATUS_SUCCESS) { + status = Status.Installed + log(Log.Success("Successfully installed")) + } else { + status = Status.Failure + log(Log.Error("Failed to install app", extra)) + } + } + + fun postInstallStatusRoot(pmStatus: Int, extra: String) { + if (pmStatus == PackageInstaller.STATUS_SUCCESS) { + status = Status.Installed + log(Log.Success("Successfully installed")) + } else { + status = Status.Failure + log(Log.Error("Failed to install app", extra)) } } From 3ba238c8a43ea0f9d110674cbd5920262395f07a Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 12 Dec 2021 14:57:07 +0400 Subject: [PATCH 097/118] update AGP --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 50c0d25f54..b1ebe4894f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ buildscript { val kotlinVersion = "1.6.0" dependencies { - classpath("com.android.tools.build:gradle:7.0.3") + classpath("com.android.tools.build:gradle:7.0.4") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") } } From 528f0971b5710d8a53bb936c495ae376924d9b64 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 13 Dec 2021 13:58:56 +0400 Subject: [PATCH 098/118] update ManagerSuFile --- .../java/com/vanced/manager/core/io/ManagerSuFile.kt | 11 +++++++++-- .../java/com/vanced/manager/core/io/SUIOException.kt | 4 ++++ 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/core/io/SUIOException.kt diff --git a/app/src/main/java/com/vanced/manager/core/io/ManagerSuFile.kt b/app/src/main/java/com/vanced/manager/core/io/ManagerSuFile.kt index 7c97db259a..9b2d1b4867 100644 --- a/app/src/main/java/com/vanced/manager/core/io/ManagerSuFile.kt +++ b/app/src/main/java/com/vanced/manager/core/io/ManagerSuFile.kt @@ -5,11 +5,12 @@ import com.topjohnwu.superuser.io.SuFile import com.vanced.manager.core.util.errString import com.vanced.manager.core.util.outString import java.io.File +import java.io.IOException class ManagerSuFile : SuFile { sealed class SuFileResult { - data class Success<out V>(val result: V? = null) : SuFileResult() + data class Success(val output: String) : SuFileResult() data class Error(val error: String) : SuFileResult() } @@ -27,6 +28,12 @@ class ManagerSuFile : SuFile { return SuFileResult.Success(cmd.outString) } - fun deleteResult() = cmd("rm -f @@ || rmdir -f @@") + override fun delete(): Boolean { + val result = cmd("rm -f @@ || rmdir -f @@") + if (result is SuFileResult.Error) + throw SUIOException(result.error) + + return true + } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/io/SUIOException.kt b/app/src/main/java/com/vanced/manager/core/io/SUIOException.kt new file mode 100644 index 0000000000..e9af15dac7 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/io/SUIOException.kt @@ -0,0 +1,4 @@ +package com.vanced.manager.core.io + +class SUIOException { +} \ No newline at end of file From be21c309543d61c6db2aeca7af32ffdafe05bce3 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 13 Dec 2021 13:59:27 +0400 Subject: [PATCH 099/118] update cleanPatchFiles method --- .../manager/core/installer/util/Patcher.kt | 50 ++++++++++--------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/core/installer/util/Patcher.kt b/app/src/main/java/com/vanced/manager/core/installer/util/Patcher.kt index 4d0fb9036b..dca7fc9c6e 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/util/Patcher.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/util/Patcher.kt @@ -3,6 +3,8 @@ package com.vanced.manager.core.installer.util import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.io.SuFile import com.topjohnwu.superuser.io.SuFileOutputStream +import com.vanced.manager.core.io.ManagerSuFile +import com.vanced.manager.core.io.SUIOException import com.vanced.manager.core.util.errString import java.io.File import java.io.IOException @@ -93,27 +95,6 @@ object Patcher { serviceDPath = "", patchPath = "" ) - - //TODO return proper error if destroying was unsuccessful - private fun cleanPatchFiles( - postFsPath: String, - serviceDPath: String, - patchPath: String, - ): PMRootStatus<Nothing> { - val postFs = SuFile(postFsPath) - if (postFs.exists() && !postFs.delete()) - return PMRootStatus.Error(PMRootStatusType.SCRIPT_FAILED_DESTROY_POST_FS, "") - - val serviceD = SuFile(serviceDPath) - if (serviceD.exists() && !serviceD.delete()) - return PMRootStatus.Error(PMRootStatusType.SCRIPT_FAILED_DESTROY_SERVICE_D, "") - - val patch = SuFile(patchPath) - if (patch.exists() && !patch.delete()) - return PMRootStatus.Error(PMRootStatusType.PATCH_FAILED_DESTROY, "") - - return PMRootStatus.Success() - } } private fun getAppPatchPath(app: String) = "${getAppPatchFolderPath(app)}/base.apk" @@ -137,6 +118,30 @@ private fun getPostFsDataScript(pkg: String) = while read line; do echo \${'$'}{line} | grep $pkg | awk '{print \${'$'}2}' | xargs umount -l; done< /proc/mounts """.trimIndent() +private fun cleanPatchFiles( + postFsPath: String, + serviceDPath: String, + patchPath: String, +): PMRootStatus<Nothing> { + val files = mapOf( + postFsPath to PMRootStatusType.SCRIPT_FAILED_DESTROY_POST_FS, + serviceDPath to PMRootStatusType.SCRIPT_FAILED_DESTROY_SERVICE_D, + patchPath to PMRootStatusType.PATCH_FAILED_DESTROY, + ) + + for ((filePath, statusType) in files) { + try { + with(ManagerSuFile(filePath)) { + if (exists()) delete() + } + } catch (e: SUIOException) { + return PMRootStatus.Error(statusType, e.stackTraceToString()) + } + } + + return PMRootStatus.Success() +} + private inline fun copyScriptToDestination( scriptDestination: String, script: String, @@ -144,8 +149,7 @@ private inline fun copyScriptToDestination( ) { val scriptFile = SuFile(scriptDestination) .apply { - if (!exists()) - createNewFile() + if (!exists()) createNewFile() } try { From 909f509095371076a442ad983fe10053d75fcf5a Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 13 Dec 2021 13:59:38 +0400 Subject: [PATCH 100/118] update libsu --- app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a0f70ec168..9b49f17c16 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -123,7 +123,7 @@ dependencies { implementation("com.github.skydoves:orchestra-colorpicker:1.1.0") - val libsuVersion = "3.1.2" + val libsuVersion = "3.2.1" implementation("com.github.topjohnwu.libsu:core:$libsuVersion") implementation("com.github.topjohnwu.libsu:io:$libsuVersion") implementation("com.github.topjohnwu.libsu:busybox:$libsuVersion") From 20e67bbb7cd314c1ce9c0ce216b6e67082a04a3e Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Mon, 13 Dec 2021 14:00:38 +0400 Subject: [PATCH 101/118] update SUIOException --- .../main/java/com/vanced/manager/core/io/SUIOException.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/vanced/manager/core/io/SUIOException.kt b/app/src/main/java/com/vanced/manager/core/io/SUIOException.kt index e9af15dac7..00641f20e4 100644 --- a/app/src/main/java/com/vanced/manager/core/io/SUIOException.kt +++ b/app/src/main/java/com/vanced/manager/core/io/SUIOException.kt @@ -1,4 +1,9 @@ package com.vanced.manager.core.io -class SUIOException { +import java.io.IOException + +class SUIOException : IOException { + constructor(message: String) : super(message) + constructor(message: String, cause: Throwable) : super(message, cause) + constructor(cause: Throwable) : super(cause) } \ No newline at end of file From f2107b1477c53ae27a635925ffbc8a21589e953e Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 28 Dec 2021 14:08:20 +0400 Subject: [PATCH 102/118] further implement root installer --- .../core/downloader/base/AppDownloader.kt | 80 ++++++-------- .../core/downloader/impl/MicrogDownloader.kt | 41 ++++--- .../core/downloader/impl/MusicDownloader.kt | 45 ++++---- .../core/downloader/impl/VancedDownloader.kt | 41 ++++--- .../core/downloader/util/DownloadPath.kt | 31 ++++-- .../core/downloader/util/DownloadStatus.kt | 16 --- .../core/installer/base/AppInstaller.kt | 4 +- .../core/installer/impl/MicrogInstaller.kt | 3 +- .../core/installer/impl/MusicInstaller.kt | 37 ++++++- .../core/installer/impl/VancedInstaller.kt | 31 +++++- .../vanced/manager/core/installer/util/PM.kt | 23 ++-- .../manager/core/installer/util/PMRoot.kt | 102 +++++++++++------- .../util/{PMRootStatus.kt => PMRootResult.kt} | 43 +++----- .../manager/core/installer/util/Patcher.kt | 81 +++++++------- .../core/installer/util/RootPatchHelper.kt | 64 +++++++++++ .../java/com/vanced/manager/core/io/Util.kt | 36 +++++++ .../vanced/manager/core/util/AppPackages.kt | 7 ++ .../vanced/manager/core/util/Coroutines.kt | 14 +++ .../vanced/manager/core/util/DownloadLog.kt | 9 -- .../java/com/vanced/manager/core/util/Log.kt | 37 ------- .../com/vanced/manager/core/util/SuShell.kt | 9 +- .../manager/core/util/VancedAppPackages.kt | 3 - .../manager/ui/screens/SettingsLayout.kt | 2 +- .../manager/ui/viewmodel/InstallViewModel.kt | 70 +++++++----- .../manager/ui/viewmodel/MainViewModel.kt | 4 +- .../{screens => }/settings/AccentColorItem.kt | 2 +- .../{screens => }/settings/ClearFilesItem.kt | 2 +- .../{screens => }/settings/CustomTabsItem.kt | 2 +- .../settings/ManagerVariantItem.kt | 6 +- .../settings/NotificationsItem.kt | 2 +- .../{screens => }/settings/ThemeItem.kt | 2 +- 31 files changed, 492 insertions(+), 357 deletions(-) delete mode 100644 app/src/main/java/com/vanced/manager/core/downloader/util/DownloadStatus.kt rename app/src/main/java/com/vanced/manager/core/installer/util/{PMRootStatus.kt => PMRootResult.kt} (51%) create mode 100644 app/src/main/java/com/vanced/manager/core/installer/util/RootPatchHelper.kt create mode 100644 app/src/main/java/com/vanced/manager/core/io/Util.kt create mode 100644 app/src/main/java/com/vanced/manager/core/util/AppPackages.kt create mode 100644 app/src/main/java/com/vanced/manager/core/util/Coroutines.kt delete mode 100644 app/src/main/java/com/vanced/manager/core/util/DownloadLog.kt delete mode 100644 app/src/main/java/com/vanced/manager/core/util/Log.kt delete mode 100644 app/src/main/java/com/vanced/manager/core/util/VancedAppPackages.kt rename app/src/main/java/com/vanced/manager/ui/widget/{screens => }/settings/AccentColorItem.kt (95%) rename app/src/main/java/com/vanced/manager/ui/widget/{screens => }/settings/ClearFilesItem.kt (88%) rename app/src/main/java/com/vanced/manager/ui/widget/{screens => }/settings/CustomTabsItem.kt (92%) rename app/src/main/java/com/vanced/manager/ui/widget/{screens => }/settings/ManagerVariantItem.kt (87%) rename app/src/main/java/com/vanced/manager/ui/widget/{screens => }/settings/NotificationsItem.kt (94%) rename app/src/main/java/com/vanced/manager/ui/widget/{screens => }/settings/ThemeItem.kt (96%) diff --git a/app/src/main/java/com/vanced/manager/core/downloader/base/AppDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/base/AppDownloader.kt index 7901506f23..efeb9eb0be 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/base/AppDownloader.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/base/AppDownloader.kt @@ -1,83 +1,67 @@ package com.vanced.manager.core.downloader.base -import com.vanced.manager.core.downloader.util.DownloadStatus +import com.vanced.manager.core.io.writeFile import okhttp3.ResponseBody import retrofit2.Call import retrofit2.awaitResponse -import java.io.FileOutputStream - -typealias DownloadCall = Call<ResponseBody> abstract class AppDownloader { data class DownloadFile( val fileName: String, - val call: DownloadCall, + val call: Call<ResponseBody>, ) - private lateinit var call: DownloadCall + sealed class DownloadStatus { + object Success : DownloadStatus() + data class Error(val error: String, val fileName: String) : DownloadStatus() + + val isSuccess + get() = this is Success + + val isError + get() = this is Error + } abstract suspend fun download( appVersions: List<String>?, - onStatus: (DownloadStatus) -> Unit - ) + onProgress: (Float) -> Unit, + onFile: (String) -> Unit + ): DownloadStatus + + abstract suspend fun downloadRoot( + appVersions: List<String>?, + onProgress: (Float) -> Unit, + onFile: (String) -> Unit + ): DownloadStatus abstract fun getSavedFilePath(): String - suspend fun downloadFiles( - downloadFiles: Array<DownloadFile>, - onFile: (String) -> Unit, + suspend inline fun downloadFiles( + files: Array<DownloadFile>, onProgress: (Float) -> Unit, - onError: (error: String, fileName: String) -> Unit, - onSuccess: () -> Unit - ) { - for (downloadFile in downloadFiles) { + onFile: (String) -> Unit + ): DownloadStatus { + for (file in files) { try { - this.call = downloadFile.call - - onFile(downloadFile.fileName) + onFile(file.fileName) - val response = call.awaitResponse() + val response = file.call.awaitResponse() if (response.isSuccessful) { - val body = response.body() - if (body != null) { - writeFile(body, downloadFile.fileName, onProgress) - } + response.body()?.writeFile(getSavedFilePath() + "/${file.fileName}", onProgress) continue } val error = response.errorBody()?.toString() if (error != null) { - onError(error, downloadFile.fileName) - return + return DownloadStatus.Error(error, file.fileName) } } catch (e: Exception) { - onError(e.stackTraceToString(), downloadFile.fileName) - return + return DownloadStatus.Error(e.stackTraceToString(), file.fileName) } } - onSuccess() - } - - private inline fun writeFile( - body: ResponseBody, - fileName: String, - onProgress: (Float) -> Unit - ) { - val inputStream = body.byteStream() - val outputStream = FileOutputStream(getSavedFilePath() + "/$fileName") - val totalBytes = body.contentLength() - val fileReader = ByteArray(4096) - var downloadedBytes = 0L - var read: Int - while (inputStream.read(fileReader).also { read = it } != -1) { - outputStream.write(fileReader, 0, read) - downloadedBytes += read - onProgress((downloadedBytes * 100 / totalBytes).toFloat()) - } - inputStream.close() - outputStream.close() + return DownloadStatus.Success } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt index 99581ce38f..ca810c8ee2 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt @@ -3,7 +3,6 @@ package com.vanced.manager.core.downloader.impl import android.content.Context import com.vanced.manager.core.downloader.api.MicrogAPI import com.vanced.manager.core.downloader.base.AppDownloader -import com.vanced.manager.core.downloader.util.DownloadStatus import com.vanced.manager.core.downloader.util.getMicrogPath import java.io.File @@ -14,33 +13,31 @@ class MicrogDownloader( override suspend fun download( appVersions: List<String>?, - onStatus: (DownloadStatus) -> Unit - ) { - downloadFiles( - downloadFiles = arrayOf( + onProgress: (Float) -> Unit, + onFile: (String) -> Unit + ): DownloadStatus { + val downloadStatus = downloadFiles( + files = arrayOf( DownloadFile( call = microgAPI.getFile(), fileName = "microg.apk" ) ), - onProgress = { progress -> - onStatus(DownloadStatus.Progress(progress)) - }, - onFile = { fileName -> - onStatus(DownloadStatus.File(fileName)) - }, - onSuccess = { - onStatus(DownloadStatus.StartInstall) - }, - onError = { error, fileName -> - onStatus( - DownloadStatus.Error( - displayError = "Failed to download $fileName", - stacktrace = error - ) - ) - } + onProgress = onProgress, + onFile = onFile ) + if (downloadStatus.isError) + return downloadStatus + + return DownloadStatus.Success + } + + override suspend fun downloadRoot( + appVersions: List<String>?, + onProgress: (Float) -> Unit, + onFile: (String) -> Unit + ): DownloadStatus { + throw IllegalAccessException("Vanced microG does not have a root downloader") } override fun getSavedFilePath(): String { diff --git a/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt index b715b76e08..0947705230 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt @@ -3,8 +3,7 @@ package com.vanced.manager.core.downloader.impl import android.content.Context import com.vanced.manager.core.downloader.api.MusicAPI import com.vanced.manager.core.downloader.base.AppDownloader -import com.vanced.manager.core.downloader.util.DownloadStatus -import com.vanced.manager.core.downloader.util.getVancedMusicPath +import com.vanced.manager.core.downloader.util.getVancedYoutubeMusicPath import com.vanced.manager.core.preferences.holder.managerVariantPref import com.vanced.manager.core.preferences.holder.musicVersionPref import com.vanced.manager.core.util.getLatestOrProvidedAppVersion @@ -19,12 +18,13 @@ class MusicDownloader( override suspend fun download( appVersions: List<String>?, - onStatus: (DownloadStatus) -> Unit - ) { + onProgress: (Float) -> Unit, + onFile: (String) -> Unit + ): DownloadStatus { absoluteVersion = getLatestOrProvidedAppVersion(musicVersionPref, appVersions) - downloadFiles( - downloadFiles = arrayOf( + val downloadStatus = downloadFiles( + files = arrayOf( DownloadFile( call = musicAPI.getFiles( version = absoluteVersion, @@ -33,28 +33,25 @@ class MusicDownloader( fileName = "music.apk" ) ), - onProgress = { progress -> - onStatus(DownloadStatus.Progress(progress)) - }, - onFile = { fileName -> - onStatus(DownloadStatus.File(fileName)) - }, - onSuccess = { - onStatus(DownloadStatus.StartInstall) - }, - onError = { error, fileName -> - onStatus( - DownloadStatus.Error( - displayError = "Failed to download $fileName", - stacktrace = error - ) - ) - } + onProgress = onProgress, + onFile = onFile ) + if (downloadStatus.isError) + return downloadStatus + + return DownloadStatus.Success + } + + override suspend fun downloadRoot( + appVersions: List<String>?, + onProgress: (Float) -> Unit, + onFile: (String) -> Unit + ): DownloadStatus { + return DownloadStatus.Success } override fun getSavedFilePath(): String { - val directory = File(getVancedMusicPath(absoluteVersion, managerVariantPref, context)) + val directory = File(getVancedYoutubeMusicPath(absoluteVersion, managerVariantPref, context)) if (!directory.exists()) directory.mkdirs() diff --git a/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt b/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt index adb6ae3bb8..364c918782 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt @@ -3,7 +3,6 @@ package com.vanced.manager.core.downloader.impl import android.content.Context import com.vanced.manager.core.downloader.api.VancedAPI import com.vanced.manager.core.downloader.base.AppDownloader -import com.vanced.manager.core.downloader.util.DownloadStatus import com.vanced.manager.core.downloader.util.getVancedYoutubePath import com.vanced.manager.core.preferences.holder.managerVariantPref import com.vanced.manager.core.preferences.holder.vancedLanguagesPref @@ -22,8 +21,9 @@ class VancedDownloader( override suspend fun download( appVersions: List<String>?, - onStatus: (DownloadStatus) -> Unit - ) { + onProgress: (Float) -> Unit, + onFile: (String) -> Unit + ): DownloadStatus { absoluteVersion = getLatestOrProvidedAppVersion(vancedVersionPref, appVersions) val files = arrayOf( @@ -42,26 +42,23 @@ class VancedDownloader( ) } - downloadFiles( - downloadFiles = files, - onProgress = { progress -> - onStatus(DownloadStatus.Progress(progress)) - }, - onFile = { fileName -> - onStatus(DownloadStatus.File(fileName)) - }, - onSuccess = { - onStatus(DownloadStatus.StartInstall) - }, - onError = { error, fileName -> - onStatus( - DownloadStatus.Error( - displayError = "Failed to download $fileName", - stacktrace = error - ) - ) - } + val downloadStatus = downloadFiles( + files = files, + onProgress = onProgress, + onFile = onFile, ) + if (downloadStatus.isError) + return downloadStatus + + return DownloadStatus.Success + } + + override suspend fun downloadRoot( + appVersions: List<String>?, + onProgress: (Float) -> Unit, + onFile: (String) -> Unit + ): DownloadStatus { + return DownloadStatus.Success } override fun getSavedFilePath(): String { diff --git a/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadPath.kt b/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadPath.kt index 76511b779f..746e4b5905 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadPath.kt +++ b/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadPath.kt @@ -6,19 +6,34 @@ fun getVancedYoutubePath( version: String, variant: String, context: Context -) = context.getExternalFilesDir("vanced_youtube")!!.path + "/$version/$variant" +) = context.getExternalFilesDirPath("vanced_youtube") + "/$version/$variant" -fun getStockYoutubePath( +fun getVancedYoutubeMusicPath( version: String, + variant: String, + context: Context +) = context.getExternalFilesDirPath("vanced_music") + "/$version/$variant" + +fun getMicrogPath( context: Context -) = context.getExternalFilesDir("stock_youtube")!!.path + "/$version" +) = context.getExternalFilesDirPath("microg") -fun getVancedMusicPath( +fun getStockYoutubePath( version: String, - variant: String, context: Context -) = context.getExternalFilesDir("vanced_music")!!.path + "/$version/$variant" +) = context.getExternalFilesDirPath("stock_youtube") + "/$version" -fun getMicrogPath( +fun getStockYoutubeMusicPath( + version: String, context: Context -) = context.getExternalFilesDir("microg")!!.path \ No newline at end of file +) = context.getExternalFilesDirPath("stock_youtube_music") + "/$version" + +private fun Context.getExternalFilesDirPath( + type: String +): String { + val filesDir = getExternalFilesDir(type)!! //fuck null safety, amirite? + if (!filesDir.exists()) + filesDir.mkdirs() + + return filesDir.path +} diff --git a/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadStatus.kt b/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadStatus.kt deleted file mode 100644 index ee01c5d02c..0000000000 --- a/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadStatus.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.vanced.manager.core.downloader.util - -sealed class DownloadStatus { - - object StartInstall : DownloadStatus() - - data class File(val fileName: String) : DownloadStatus() - - data class Progress(val progress: Float) : DownloadStatus() - - data class Error( - val displayError: String, - val stacktrace: String, - ) : DownloadStatus() - -} diff --git a/app/src/main/java/com/vanced/manager/core/installer/base/AppInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/base/AppInstaller.kt index 592290a971..61e5b38e98 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/base/AppInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/base/AppInstaller.kt @@ -1,9 +1,11 @@ package com.vanced.manager.core.installer.base +import com.vanced.manager.core.installer.util.PMRootResult + abstract class AppInstaller { abstract fun install(appVersions: List<String>?) - abstract fun installRoot(appVersions: List<String>?) + abstract fun installRoot(appVersions: List<String>?): PMRootResult<Nothing> } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt index 993cce4015..55642b2550 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt @@ -4,6 +4,7 @@ import android.content.Context import com.vanced.manager.core.downloader.util.getMicrogPath import com.vanced.manager.core.installer.base.AppInstaller import com.vanced.manager.core.installer.util.PM +import com.vanced.manager.core.installer.util.PMRootResult import java.io.File class MicrogInstaller( @@ -18,7 +19,7 @@ class MicrogInstaller( PM.installApp(musicApk, context) } - override fun installRoot(appVersions: List<String>?) { + override fun installRoot(appVersions: List<String>?): PMRootResult<Nothing> { throw IllegalAccessException("Vanced microG does not have a root installer") } diff --git a/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt index 2880a6a46e..46ee003b1f 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt @@ -1,11 +1,14 @@ package com.vanced.manager.core.installer.impl import android.content.Context -import com.vanced.manager.core.downloader.util.getVancedMusicPath +import com.vanced.manager.core.downloader.util.getStockYoutubeMusicPath +import com.vanced.manager.core.downloader.util.getVancedYoutubeMusicPath import com.vanced.manager.core.installer.base.AppInstaller -import com.vanced.manager.core.installer.util.PM +import com.vanced.manager.core.installer.util.* import com.vanced.manager.core.preferences.holder.managerVariantPref import com.vanced.manager.core.preferences.holder.musicVersionPref +import com.vanced.manager.core.preferences.holder.vancedVersionPref +import com.vanced.manager.core.util.VANCED_MUSIC_PACKAGE_ROOT import com.vanced.manager.core.util.getLatestOrProvidedAppVersion import java.io.File @@ -18,13 +21,39 @@ class MusicInstaller( ) { val absoluteVersion = getLatestOrProvidedAppVersion(musicVersionPref, appVersions) - val musicApk = File(getVancedMusicPath(absoluteVersion, managerVariantPref, context) + "/music.apk") + val musicApk = File(getVancedYoutubeMusicPath(absoluteVersion, managerVariantPref, context) + "/music.apk") PM.installApp(musicApk, context) } - override fun installRoot(appVersions: List<String>?) { + override fun installRoot(appVersions: List<String>?): PMRootResult<Nothing> { + val absoluteVersion = getLatestOrProvidedAppVersion(vancedVersionPref, appVersions) + + val stockPath = getStockYoutubeMusicPath(absoluteVersion, context) + "/base.apk" + val vancedPath = getVancedYoutubeMusicPath(absoluteVersion, "root", context) + "/base.apk" + + val prepareStock = RootPatchHelper.prepareStock( + stockPackage = VANCED_MUSIC_PACKAGE_ROOT, + stockVersion = absoluteVersion + ) { + PMRoot.installApp(stockPath) + } + if (prepareStock.isError) + return prepareStock + + val patchStock = RootPatchHelper.patchStock( + patchPath = vancedPath, + stockPackage = VANCED_MUSIC_PACKAGE_ROOT, + app = APP_KEY + ) + if (patchStock.isError) + return patchStock + + return PMRootResult.Success() + } + companion object { + const val APP_KEY = "youtube_music_vanced" } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt b/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt index 08de16fdc3..bdcbf86667 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt @@ -1,13 +1,12 @@ package com.vanced.manager.core.installer.impl import android.content.Context -import android.content.Intent import com.vanced.manager.core.downloader.util.getStockYoutubePath import com.vanced.manager.core.downloader.util.getVancedYoutubePath import com.vanced.manager.core.installer.base.AppInstaller import com.vanced.manager.core.installer.util.* import com.vanced.manager.core.preferences.holder.vancedVersionPref -import com.vanced.manager.core.util.Message +import com.vanced.manager.core.util.VANCED_YOUTUBE_PACKAGE_ROOT import com.vanced.manager.core.util.getLatestOrProvidedAppVersion import java.io.File @@ -26,8 +25,34 @@ class VancedInstaller( PM.installSplitApp(apks!!, context) } - override fun installRoot(appVersions: List<String>?) { + override fun installRoot(appVersions: List<String>?): PMRootResult<Nothing> { + val absoluteVersion = getLatestOrProvidedAppVersion(vancedVersionPref, appVersions) + val stockApks = File(getStockYoutubePath(absoluteVersion, context)) + .listFiles()?.map { it.absolutePath } + val vancedBaseApk = getVancedYoutubePath(absoluteVersion, "root", context) + "/base.apk" + + val prepareStock = RootPatchHelper.prepareStock( + stockPackage = VANCED_YOUTUBE_PACKAGE_ROOT, + stockVersion = absoluteVersion, + ) { + PMRoot.installSplitApp(stockApks!!) + } + if (prepareStock.isError) + return prepareStock + + val patchStock = RootPatchHelper.patchStock( + patchPath = vancedBaseApk, + stockPackage = VANCED_YOUTUBE_PACKAGE_ROOT, + app = APP_KEY + ) + if (patchStock.isError) + return patchStock + + return PMRootResult.Success() } + companion object { + const val APP_KEY = "youtube_vanced" + } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/installer/util/PM.kt b/app/src/main/java/com/vanced/manager/core/installer/util/PM.kt index 285cefc991..45412f4551 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/util/PM.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/util/PM.kt @@ -9,7 +9,6 @@ import android.os.Build import com.vanced.manager.core.installer.service.AppInstallService import com.vanced.manager.core.installer.service.AppUninstallService import java.io.File -import java.io.FileInputStream private const val byteArraySize = 1024 * 1024 // Because 1,048,576 is not readable @@ -19,7 +18,7 @@ object PM { val packageInstaller = context.packageManager.packageInstaller val session = packageInstaller.openSession(packageInstaller.createSession(sessionParams)) - writeApkToSession(apk, session) + session.writeApk(apk) session.commit(context.installIntentSender) session.close() } @@ -29,7 +28,7 @@ object PM { val session = packageInstaller.openSession(packageInstaller.createSession(sessionParams)) for (apk in apks) { - writeApkToSession(apk, session) + session.writeApk(apk) } session.commit(context.installIntentSender) session.close() @@ -41,17 +40,13 @@ object PM { } } -private fun writeApkToSession( - apk: File, - session: PackageInstaller.Session -) { - val inputStream = FileInputStream(apk) - val outputStream = session.openWrite(apk.name, 0, apk.length()) - inputStream.copyTo(outputStream, byteArraySize) - session.fsync(outputStream) - inputStream.close() - outputStream.flush() - outputStream.close() +private fun PackageInstaller.Session.writeApk(apk: File) { + apk.inputStream().use { inputStream -> + openWrite(apk.name, 0, apk.length()).use { outputStream -> + inputStream.copyTo(outputStream, byteArraySize) + fsync(outputStream) + } + } } private val intentFlags diff --git a/app/src/main/java/com/vanced/manager/core/installer/util/PMRoot.kt b/app/src/main/java/com/vanced/manager/core/installer/util/PMRoot.kt index 9e35096f68..8cea3a28f9 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/util/PMRoot.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/util/PMRoot.kt @@ -10,10 +10,10 @@ import java.io.IOException object PMRoot { - fun installApp(apkPath: String): PMRootStatus<Nothing> { + fun installApp(apkPath: String): PMRootResult<Nothing> { val apk = File(apkPath) - val tmpApk = copyApkToTemp(apk) { error -> - return PMRootStatus.Error(PMRootStatusType.SESSION_FAILED_COPY, error) + val tmpApk = copyApkToTemp(apk).getOrElse { exception -> + return PMRootResult.Error(PMRootStatus.SESSION_FAILED_COPY, exception.stackTraceToString()) } val install = Shell.su("pm", "install", "-r", tmpApk.absolutePath).exec() @@ -22,27 +22,27 @@ object PMRoot { if (!install.isSuccess) { val errString = install.errString - return PMRootStatus.Error(getEnumForInstallFailed(errString), errString) + return PMRootResult.Error(getEnumForInstallFailed(errString), errString) } - return PMRootStatus.Success() + return PMRootResult.Success() } - fun installSplitApp(apkPaths: List<String>): PMRootStatus<Nothing> { + fun installSplitApp(apkPaths: List<String>): PMRootResult<Nothing> { val installCreate = Shell.su("pm", "install-create", "-r").exec() if (!installCreate.isSuccess) - return PMRootStatus.Error(PMRootStatusType.SESSION_FAILED_CREATE, installCreate.errString) + return PMRootResult.Error(PMRootStatus.SESSION_FAILED_CREATE, installCreate.errString) val sessionId = installCreate.outString if (sessionId.toIntOrNull() == null) - return PMRootStatus.Error(PMRootStatusType.SESSION_INVALID_ID, installCreate.errString) + return PMRootResult.Error(PMRootStatus.SESSION_INVALID_ID, installCreate.errString) for (apkPath in apkPaths) { val apk = File(apkPath) - val tmpApk = copyApkToTemp(apk) { error -> - return PMRootStatus.Error(PMRootStatusType.SESSION_FAILED_COPY, error) + val tmpApk = copyApkToTemp(apk).getOrElse { exception -> + return PMRootResult.Error(PMRootStatus.SESSION_FAILED_COPY, exception.stackTraceToString()) } val installWrite = @@ -52,62 +52,82 @@ object PMRoot { tmpApk.delete() if (!installWrite.isSuccess) - return PMRootStatus.Error(PMRootStatusType.SESSION_FAILED_WRITE, installWrite.errString) + return PMRootResult.Error(PMRootStatus.SESSION_FAILED_WRITE, installWrite.errString) } val installCommit = Shell.su("pm", "install-commit", sessionId).exec() if (!installCommit.isSuccess) { val errString = installCommit.errString - return PMRootStatus.Error(getEnumForInstallFailed(errString), errString) + return PMRootResult.Error(getEnumForInstallFailed(errString), errString) } - return PMRootStatus.Success() + return PMRootResult.Success() } - fun uninstallApp(pkg: String): PMRootStatus<Nothing> { + fun uninstallApp(pkg: String): PMRootResult<Nothing> { val uninstall = Shell.su("pm", "uninstall", pkg).exec() if (!uninstall.isSuccess) - return PMRootStatus.Error(PMRootStatusType.UNINSTALL_FAILED, uninstall.errString) + return PMRootResult.Error(PMRootStatus.UNINSTALL_FAILED, uninstall.errString) - return PMRootStatus.Success() + return PMRootResult.Success() } - fun setInstallerPackage(targetPkg: String, installerPkg: String): PMRootStatus<Nothing> { + fun setInstallerPackage(targetPkg: String, installerPkg: String): PMRootResult<Nothing> { val setInstaller = Shell.su("pm", "set-installer", targetPkg, installerPkg) .exec() if (!setInstaller.isSuccess) - return PMRootStatus.Error(PMRootStatusType.ACTION_FAILED_SET_INSTALLER, setInstaller.errString) + return PMRootResult.Error(PMRootStatus.ACTION_FAILED_SET_INSTALLER, setInstaller.errString) - return PMRootStatus.Success() + return PMRootResult.Success() } - fun forceStopApp(pkg: String): PMRootStatus<Nothing> { + fun forceStopApp(pkg: String): PMRootResult<Nothing> { val stopApp = Shell.su("am", "force-stop", pkg).exec() if (!stopApp.isSuccess) - return PMRootStatus.Error(PMRootStatusType.ACTION_FAILED_FORCE_STOP_APP, stopApp.errString) + return PMRootResult.Error(PMRootStatus.ACTION_FAILED_FORCE_STOP_APP, stopApp.errString) - return PMRootStatus.Success() + return PMRootResult.Success() } - fun getPackageDir(pkg: String): PMRootStatus<String> { - val delimeter = "path: " - val dumpsys = Shell.su("dumpsys", "package", pkg, "|", "grep", delimeter).exec() + fun getPackageVersionName(pkg: String): PMRootResult<String> { + val keyword = "versionName=" + val dumpsys = Shell.su("dumpsys", "package", pkg, "|", "grep", keyword).exec() if (!dumpsys.isSuccess) - return PMRootStatus.Error(PMRootStatusType.ACTION_FAILED_GET_PACKAGE_DIR, dumpsys.errString) + return PMRootResult.Error(PMRootStatus.ACTION_FAILED_GET_PACKAGE_VERSION_NAME, + dumpsys.errString) - return PMRootStatus.Success(dumpsys.outString.removePrefix(delimeter)) + return PMRootResult.Success(dumpsys.outString.removePrefix(keyword)) + } + + fun getPackageVersionCode(pkg: String): PMRootResult<Long> { + val keyword = "versionCode=" + val dumpsys = Shell.su("dumpsys", "package", pkg, "|", "grep", keyword).exec() + + if (!dumpsys.isSuccess) + return PMRootResult.Error(PMRootStatus.ACTION_FAILED_GET_PACKAGE_VERSION_CODE, + dumpsys.errString) + + return PMRootResult.Success(dumpsys.outString.removePrefix(keyword).substringAfter("minSdk") + .toLong()) + } + + fun getPackageDir(pkg: String): PMRootResult<String> { + val keyword = "path: " + val dumpsys = Shell.su("dumpsys", "package", pkg, "|", "grep", keyword).exec() + + if (!dumpsys.isSuccess) + return PMRootResult.Error(PMRootStatus.ACTION_FAILED_GET_PACKAGE_DIR, dumpsys.errString) + + return PMRootResult.Success(dumpsys.outString.removePrefix(keyword)) } } -private inline fun copyApkToTemp( - apk: File, - onError: (String) -> Unit -): SuFile { +private fun copyApkToTemp(apk: File, ): Result<SuFile> { val tmpPath = "/data/local/tmp/${apk.name}" val tmpApk = SuFile(tmpPath).apply { @@ -120,20 +140,20 @@ private inline fun copyApkToTemp( it.flush() } } catch (e: IOException) { - onError(e.stackTraceToString()) + return Result.failure(e) } - return tmpApk + return Result.success(tmpApk) } private fun getEnumForInstallFailed(outString: String) = when { - outString.contains("INSTALL_FAILED_ABORTED") -> PMRootStatusType.INSTALL_FAILED_ABORTED - outString.contains("INSTALL_FAILED_ALREADY_EXISTS") -> PMRootStatusType.INSTALL_FAILED_ALREADY_EXISTS - outString.contains("INSTALL_FAILED_CPU_ABI_INCOMPATIBLE") -> PMRootStatusType.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE - outString.contains("INSTALL_FAILED_INSUFFICIENT_STORAGE") -> PMRootStatusType.INSTALL_FAILED_INSUFFICIENT_STORAGE - outString.contains("INSTALL_FAILED_INVALID_APK") -> PMRootStatusType.INSTALL_FAILED_INVALID_APK - outString.contains("INSTALL_FAILED_VERSION_DOWNGRADE") -> PMRootStatusType.INSTALL_FAILED_VERSION_DOWNGRADE - outString.contains("INSTALL_PARSE_FAILED_NO_CERTIFICATES") -> PMRootStatusType.INSTALL_FAILED_PARSE_NO_CERTIFICATES - else -> PMRootStatusType.INSTALL_FAILED_UNKNOWN + outString.contains("INSTALL_FAILED_ABORTED") -> PMRootStatus.INSTALL_FAILED_ABORTED + outString.contains("INSTALL_FAILED_ALREADY_EXISTS") -> PMRootStatus.INSTALL_FAILED_ALREADY_EXISTS + outString.contains("INSTALL_FAILED_CPU_ABI_INCOMPATIBLE") -> PMRootStatus.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE + outString.contains("INSTALL_FAILED_INSUFFICIENT_STORAGE") -> PMRootStatus.INSTALL_FAILED_INSUFFICIENT_STORAGE + outString.contains("INSTALL_FAILED_INVALID_APK") -> PMRootStatus.INSTALL_FAILED_INVALID_APK + outString.contains("INSTALL_FAILED_VERSION_DOWNGRADE") -> PMRootStatus.INSTALL_FAILED_VERSION_DOWNGRADE + outString.contains("INSTALL_PARSE_FAILED_NO_CERTIFICATES") -> PMRootStatus.INSTALL_FAILED_PARSE_NO_CERTIFICATES + else -> PMRootStatus.INSTALL_FAILED_UNKNOWN } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/installer/util/PMRootStatus.kt b/app/src/main/java/com/vanced/manager/core/installer/util/PMRootResult.kt similarity index 51% rename from app/src/main/java/com/vanced/manager/core/installer/util/PMRootStatus.kt rename to app/src/main/java/com/vanced/manager/core/installer/util/PMRootResult.kt index 8da7394257..13a5178013 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/util/PMRootStatus.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/util/PMRootResult.kt @@ -1,8 +1,10 @@ package com.vanced.manager.core.installer.util -enum class PMRootStatusType { +enum class PMRootStatus { ACTION_FAILED_SET_INSTALLER, ACTION_FAILED_GET_PACKAGE_DIR, + ACTION_FAILED_GET_PACKAGE_VERSION_NAME, + ACTION_FAILED_GET_PACKAGE_VERSION_CODE, ACTION_FAILED_FORCE_STOP_APP, INSTALL_SUCCESSFUL, @@ -38,35 +40,20 @@ enum class PMRootStatusType { UNINSTALL_FAILED, } -sealed class PMRootStatus<out V> { - data class Success<out V>(val value: V? = null) : PMRootStatus<V>() - data class Error(val error: PMRootStatusType, val message: String) : PMRootStatus<Nothing>() -} +sealed class PMRootResult<out V> { + data class Success<out V>(val value: V? = null) : PMRootResult<V>() + data class Error(val error: PMRootStatus, val message: String) : PMRootResult<Nothing>() -inline fun <V, S : PMRootStatus<V>> S.exec( - onError: (PMRootStatusType, String) -> Unit, - onSuccess: () -> Unit -) { - when (this) { - is PMRootStatus.Success<*> -> { - onSuccess() - } - is PMRootStatus.Error -> { - onError(error, message) - } - } + val isError + get() = this is Error + + val isSuccess + get() = this is Success } -inline fun <reified V, S : PMRootStatus<V>> S.execWithValue( - onError: (PMRootStatusType, String) -> Unit, - onSuccess: (value: V?) -> Unit -) { - when (this) { - is PMRootStatus.Success<*> -> { - onSuccess(value as V?) - } - is PMRootStatus.Error -> { - onError(error, message) - } +inline fun <R, T : R> PMRootResult<T>.getOrElse(onError: (PMRootResult.Error) -> R): R? { + return when (this) { + is PMRootResult.Error -> onError(this) + is PMRootResult.Success -> return this.value } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/installer/util/Patcher.kt b/app/src/main/java/com/vanced/manager/core/installer/util/Patcher.kt index dca7fc9c6e..99e5a965ac 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/util/Patcher.kt +++ b/app/src/main/java/com/vanced/manager/core/installer/util/Patcher.kt @@ -13,27 +13,29 @@ object Patcher { fun setupScript( app: String, - pkg: String, + stockPackage: String, stockPath: String, - ): PMRootStatus<Nothing> { + ): PMRootResult<Nothing> { val postFsDataScriptPath = getAppPostFsScriptPath(app) val serviceDScriptPath = getAppServiceDScriptPath(app) - val postFsDataScript = getPostFsDataScript(pkg) + val postFsDataScript = getPostFsDataScript(stockPackage) val serviceDScript = getServiceDScript(getAppPatchPath(app), stockPath) - copyScriptToDestination(postFsDataScriptPath, postFsDataScript) { error -> - return PMRootStatus.Error(PMRootStatusType.SCRIPT_FAILED_SETUP_POST_FS, error) - } + val copyServiceDScript = copyScriptToDestination(postFsDataScript, postFsDataScriptPath) + if (copyServiceDScript.isFailure) + return PMRootResult.Error(PMRootStatus.SCRIPT_FAILED_SETUP_POST_FS, + copyServiceDScript.exceptionOrNull()!!.stackTraceToString()) - copyScriptToDestination(serviceDScriptPath, serviceDScript) { error -> - return PMRootStatus.Error(PMRootStatusType.SCRIPT_FAILED_SETUP_SERVICE_D, error) - } + val copyPostFsDataScript = copyScriptToDestination(serviceDScript, serviceDScriptPath) + if (copyPostFsDataScript.isFailure) + return PMRootResult.Error(PMRootStatus.SCRIPT_FAILED_SETUP_SERVICE_D, + copyPostFsDataScript.exceptionOrNull()!!.stackTraceToString()) - return PMRootStatus.Success() + return PMRootResult.Success() } - fun movePatchToDataAdb(patchPath: String, app: String): PMRootStatus<Nothing> { + fun movePatchToDataAdb(patchPath: String, app: String): PMRootResult<Nothing> { val newPatchPath = getAppPatchPath(app) val patchApk = File(patchPath) @@ -47,38 +49,38 @@ object Patcher { try { patchApk.copyTo(newPatchApk) } catch (e: IOException) { - return PMRootStatus.Error(PMRootStatusType.PATCH_FAILED_COPY, e.stackTraceToString()) + return PMRootResult.Error(PMRootStatus.PATCH_FAILED_COPY, e.stackTraceToString()) } val chmod = Shell.su("chmod", "644", newPatchPath).exec() if (!chmod.isSuccess) - return PMRootStatus.Error(PMRootStatusType.PATCH_FAILED_CHMOD, chmod.errString) + return PMRootResult.Error(PMRootStatus.PATCH_FAILED_CHMOD, chmod.errString) val chown = Shell.su("chown", "system:system", newPatchPath).exec() if (!chmod.isSuccess) - return PMRootStatus.Error(PMRootStatusType.PATCH_FAILED_CHOWN, chown.errString) + return PMRootResult.Error(PMRootStatus.PATCH_FAILED_CHOWN, chown.errString) - return PMRootStatus.Success() + return PMRootResult.Success() } - fun chconPatch(app: String): PMRootStatus<Nothing> { + fun chconPatch(app: String): PMRootResult<Nothing> { val chcon = Shell.su("chcon u:object_r:apk_data_file:s0 ${getAppPatchPath(app)}").exec() if (!chcon.isSuccess) - return PMRootStatus.Error(PMRootStatusType.PATCH_FAILED_CHCON, chcon.errString) + return PMRootResult.Error(PMRootStatus.PATCH_FAILED_CHCON, chcon.errString) - return PMRootStatus.Success() + return PMRootResult.Success() } - fun linkPatch(app: String, pkg: String, stockPath: String): PMRootStatus<Nothing> { - val umount = Shell.su("""for i in ${'$'}(ls /data/app/ | grep $pkg | tr " "); do umount -l "/data/app/${"$"}i/base.apk"; done """).exec() + fun linkPatch(app: String, stockPackage: String, stockPath: String): PMRootResult<Nothing> { + val umount = Shell.su("""for i in ${'$'}(ls /data/app/ | grep $stockPackage | tr " "); do umount -l "/data/app/${"$"}i/base.apk"; done """).exec() if (!umount.isSuccess) - return PMRootStatus.Error(PMRootStatusType.LINK_FAILED_UNMOUNT, umount.errString) + return PMRootResult.Error(PMRootStatus.LINK_FAILED_UNMOUNT, umount.errString) val mount = Shell.su("su", "-mm", "-c", """"mount -o bind ${getAppPatchPath(app)} $stockPath"""").exec() if (!mount.isSuccess) - return PMRootStatus.Error(PMRootStatusType.LINK_FAILED_MOUNT, mount.errString) + return PMRootResult.Error(PMRootStatus.LINK_FAILED_MOUNT, mount.errString) - return PMRootStatus.Success() + return PMRootResult.Success() } fun destroyPatch(app: String) = @@ -112,42 +114,41 @@ private fun getServiceDScript(patchPath: String, stockPath: String) = mount -o bind $patchPath $stockPath """.trimIndent() -private fun getPostFsDataScript(pkg: String) = +private fun getPostFsDataScript(stockPackage: String) = """ #!/system/bin/sh - while read line; do echo \${'$'}{line} | grep $pkg | awk '{print \${'$'}2}' | xargs umount -l; done< /proc/mounts + while read line; do echo \${'$'}{line} | grep $stockPackage | awk '{print \${'$'}2}' | xargs umount -l; done< /proc/mounts """.trimIndent() private fun cleanPatchFiles( postFsPath: String, serviceDPath: String, patchPath: String, -): PMRootStatus<Nothing> { +): PMRootResult<Nothing> { val files = mapOf( - postFsPath to PMRootStatusType.SCRIPT_FAILED_DESTROY_POST_FS, - serviceDPath to PMRootStatusType.SCRIPT_FAILED_DESTROY_SERVICE_D, - patchPath to PMRootStatusType.PATCH_FAILED_DESTROY, + postFsPath to PMRootStatus.SCRIPT_FAILED_DESTROY_POST_FS, + serviceDPath to PMRootStatus.SCRIPT_FAILED_DESTROY_SERVICE_D, + patchPath to PMRootStatus.PATCH_FAILED_DESTROY, ) - for ((filePath, statusType) in files) { + for ((filePath, errorStatusType) in files) { try { with(ManagerSuFile(filePath)) { if (exists()) delete() } } catch (e: SUIOException) { - return PMRootStatus.Error(statusType, e.stackTraceToString()) + return PMRootResult.Error(errorStatusType, e.stackTraceToString()) } } - return PMRootStatus.Success() + return PMRootResult.Success() } -private inline fun copyScriptToDestination( - scriptDestination: String, +private fun copyScriptToDestination( script: String, - onError: (String) -> Unit -) { - val scriptFile = SuFile(scriptDestination) + destination: String, +): Result<Nothing?> { + val scriptFile = SuFile(destination) .apply { if (!exists()) createNewFile() } @@ -159,9 +160,11 @@ private inline fun copyScriptToDestination( } val chmod = Shell.su("chmod", "744", scriptFile.absolutePath).exec() if (!chmod.isSuccess) { - onError(chmod.errString) + return Result.failure(Exception(chmod.errString)) } } catch (e: IOException) { - onError(e.stackTraceToString()) + return Result.failure(e) } + + return Result.success(null) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/installer/util/RootPatchHelper.kt b/app/src/main/java/com/vanced/manager/core/installer/util/RootPatchHelper.kt new file mode 100644 index 0000000000..bf23db0157 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/installer/util/RootPatchHelper.kt @@ -0,0 +1,64 @@ +package com.vanced.manager.core.installer.util + +object RootPatchHelper { + + fun cleanPatches(app: String): PMRootResult<Nothing> { + val cleanOldPatches = Patcher.destroyOldPatch(app) + if (cleanOldPatches.isError) + return cleanOldPatches + + val cleanPatches = Patcher.destroyPatch(app) + if (cleanOldPatches.isError) + return cleanPatches + + return PMRootResult.Success() + } + + inline fun prepareStock( + stockPackage: String, + stockVersion: String, + install: () -> PMRootResult<Nothing> + ): PMRootResult<Nothing> { + val stockYoutubeVersion = PMRoot.getPackageVersionName(stockPackage) + .getOrElse { null } + if (stockYoutubeVersion != stockVersion) { + val uninstallStock = PMRoot.uninstallApp(stockPackage) + if (uninstallStock.isError) + return uninstallStock + + val installStock = install() + if (installStock.isError) + return installStock + } + + return PMRootResult.Success() + } + + fun patchStock( + patchPath: String, + stockPackage: String, + app: String + ): PMRootResult<Nothing> { + val movePatch = Patcher.movePatchToDataAdb(patchPath, app) + if (movePatch.isError) + return movePatch + + val chconPatch = Patcher.chconPatch(app) + if (chconPatch.isError) + return chconPatch + + val stockPackageDir = PMRoot.getPackageDir(stockPackage) + .getOrElse { error -> return error }!! + + val setupScript = Patcher.setupScript(app, stockPackage, stockPackageDir) + if (setupScript is PMRootResult.Error) + return setupScript + + val linkPatch = Patcher.linkPatch(app, stockPackage, stockPackageDir) + if (linkPatch is PMRootResult.Error) + return linkPatch + + return PMRootResult.Success() + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/io/Util.kt b/app/src/main/java/com/vanced/manager/core/io/Util.kt new file mode 100644 index 0000000000..df387453ae --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/io/Util.kt @@ -0,0 +1,36 @@ +package com.vanced.manager.core.io + +import okhttp3.ResponseBody +import java.io.FileOutputStream +import java.io.InputStream +import java.io.OutputStream + +inline fun ResponseBody.writeFile( + filePath: String, + onProgress: (Float) -> Unit +) { + byteStream().use { inputStream -> + FileOutputStream(filePath).use { outputStream -> + val totalBytes = contentLength() + inputStream.copyTo(outputStream, 8192) { bytes -> + onProgress((bytes * 100 / totalBytes).toFloat()) + } + } + } +} + +inline fun InputStream.copyTo( + outputStream: OutputStream, + bufferSize: Int, + onProgress: (Long) -> Unit +) { + val buffer = ByteArray(bufferSize) + var bytesCopied: Long = 0 + var bytes = read(buffer) + while (bytes >= 0) { + outputStream.write(buffer, 0, bytes) + bytesCopied += bytes + bytes = read(buffer) + onProgress(bytesCopied) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/util/AppPackages.kt b/app/src/main/java/com/vanced/manager/core/util/AppPackages.kt new file mode 100644 index 0000000000..7e97628798 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/util/AppPackages.kt @@ -0,0 +1,7 @@ +package com.vanced.manager.core.util + +const val VANCED_YOUTUBE_PACKAGE = "com.vanced.android.youtube" +const val VANCED_YOUTUBE_PACKAGE_ROOT = "com.google.android.youtube" + +const val VANCED_MUSIC_PACKAGE = "com.vanced.android.apps.youtube.music" +const val VANCED_MUSIC_PACKAGE_ROOT = "com.google.android.apps.youtube.music" \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/util/Coroutines.kt b/app/src/main/java/com/vanced/manager/core/util/Coroutines.kt new file mode 100644 index 0000000000..6339e3f96b --- /dev/null +++ b/app/src/main/java/com/vanced/manager/core/util/Coroutines.kt @@ -0,0 +1,14 @@ +package com.vanced.manager.core.util + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch +import java.util.concurrent.Executor +import kotlin.coroutines.CoroutineContext + +fun CoroutineContext.asExecutor(): Executor = object : Executor { + private val scope = CoroutineScope(this@asExecutor) + + override fun execute(command: Runnable) { + scope.launch { command.run() } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/util/DownloadLog.kt b/app/src/main/java/com/vanced/manager/core/util/DownloadLog.kt deleted file mode 100644 index fdfa563ac9..0000000000 --- a/app/src/main/java/com/vanced/manager/core/util/DownloadLog.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.vanced.manager.core.util - -sealed class Message { - data class Success(val message: String) : Message() - data class Warning(val message: String) : Message() - data class Error(val message: String) : Message() -} - -val downloadLogs = mutableListOf<Message>() \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/util/Log.kt b/app/src/main/java/com/vanced/manager/core/util/Log.kt deleted file mode 100644 index 5476699fff..0000000000 --- a/app/src/main/java/com/vanced/manager/core/util/Log.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.vanced.manager.core.util - -import android.util.Log -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.AnnotatedString -import androidx.compose.ui.text.SpanStyle -import androidx.compose.ui.text.buildAnnotatedString -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.withStyle - -data class LogContent( - val body: AnnotatedString, -) - -val logs = mutableListOf<LogContent>() - -fun log(tag: String, message: String) { - Log.i(tag, message) - logs.add( - LogContent( - body = buildAnnotatedString { - withStyle( - SpanStyle( - color = Color(0xFF2E73FF), - fontWeight = FontWeight.Bold - ) - ) { - append("$tag:") - } - append("") - withStyle(SpanStyle(color = Color.Magenta)) { - append(message) - } - } - ) - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/util/SuShell.kt b/app/src/main/java/com/vanced/manager/core/util/SuShell.kt index 7173aa05ad..6a6324d427 100644 --- a/app/src/main/java/com/vanced/manager/core/util/SuShell.kt +++ b/app/src/main/java/com/vanced/manager/core/util/SuShell.kt @@ -1,6 +1,8 @@ package com.vanced.manager.core.util import com.topjohnwu.superuser.Shell +import kotlin.coroutines.resume +import kotlin.coroutines.suspendCoroutine val Shell.Result.outString get() = out.joinToString("\n") @@ -9,5 +11,10 @@ val Shell.Result.errString get() = err.joinToString("\n") val isMagiskInstalled - get() = Shell.su("magisk", "-c").exec().isSuccess + get() = Shell.rootAccess() && Shell.su("magisk", "-c").exec().isSuccess + +suspend fun Shell.Job.await() = + suspendCoroutine<Shell.Result> { continuation -> + submit(/*continuation.context.asExecutor(),*/ continuation::resume) + } diff --git a/app/src/main/java/com/vanced/manager/core/util/VancedAppPackages.kt b/app/src/main/java/com/vanced/manager/core/util/VancedAppPackages.kt deleted file mode 100644 index e9b5661cd4..0000000000 --- a/app/src/main/java/com/vanced/manager/core/util/VancedAppPackages.kt +++ /dev/null @@ -1,3 +0,0 @@ -package com.vanced.manager.core.util - -const val VANCED_PACKAGE = "" \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt index 97bd3ef197..ec5050f818 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt @@ -16,7 +16,7 @@ import com.vanced.manager.ui.component.topappbar.ManagerTopAppBar import com.vanced.manager.ui.resources.managerString import com.vanced.manager.ui.util.Screen import com.vanced.manager.ui.widget.layout.managerCategory -import com.vanced.manager.ui.widget.screens.settings.* +import com.vanced.manager.ui.widget.settings.* @ExperimentalMaterial3Api @Composable diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt index f965d66ea2..201dc8e0c6 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt @@ -7,13 +7,15 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.vanced.manager.core.downloader.base.AppDownloader import com.vanced.manager.core.downloader.impl.MicrogDownloader import com.vanced.manager.core.downloader.impl.MusicDownloader import com.vanced.manager.core.downloader.impl.VancedDownloader -import com.vanced.manager.core.downloader.util.DownloadStatus import com.vanced.manager.core.installer.impl.MicrogInstaller import com.vanced.manager.core.installer.impl.MusicInstaller import com.vanced.manager.core.installer.impl.VancedInstaller +import com.vanced.manager.core.installer.util.PMRootResult +import com.vanced.manager.core.preferences.holder.managerVariantPref import com.vanced.manager.network.util.MICROG_NAME import com.vanced.manager.network.util.MUSIC_NAME import com.vanced.manager.network.util.VANCED_NAME @@ -30,6 +32,9 @@ class InstallViewModel( private val microgInstaller: MicrogInstaller, ) : ViewModel() { + private val isRoot + get() = managerVariantPref == "root" + sealed class Log { data class Info(val infoText: String) : Log() data class Success(val successText: String) : Log() @@ -72,16 +77,6 @@ class InstallViewModel( } } - fun postInstallStatusRoot(pmStatus: Int, extra: String) { - if (pmStatus == PackageInstaller.STATUS_SUCCESS) { - status = Status.Installed - log(Log.Success("Successfully installed")) - } else { - status = Status.Failure - log(Log.Error("Failed to install app", extra)) - } - } - fun clear() { logs.clear() status = Status.Idle @@ -93,21 +88,29 @@ class InstallViewModel( ) { val downloader = getDownloader(appName) - downloader.download(appVersions) { downloadStatus -> - when (downloadStatus) { - is DownloadStatus.File -> log(Log.Info("Downloading ${downloadStatus.fileName}")) - is DownloadStatus.Error -> log( - Log.Error( - displayText = downloadStatus.displayError, - stacktrace = downloadStatus.stacktrace - ) - ) - is DownloadStatus.Progress -> status = - Status.Progress(downloadStatus.progress / 100) - is DownloadStatus.StartInstall -> { - log(Log.Success("Successfully downloaded $appName")) - installApp(appName, appVersions) - } + val onProgress: (Float) -> Unit = { progress -> + status = Status.Progress(progress / 100) + } + val onFile: (String) -> Unit = { file -> + log(Log.Info("Downloading $file")) + } + + val download = + if (isRoot) + downloader.downloadRoot(appVersions, onProgress, onFile) + else + downloader.download(appVersions, onProgress, onFile) + + when (download) { + is AppDownloader.DownloadStatus.Success -> { + log(Log.Success("Successfully downloaded $appName")) + installApp(appName, appVersions) + } + is AppDownloader.DownloadStatus.Error -> { + log(Log.Error( + displayText = "Failed to download ${download.fileName}", + stacktrace = download.error + )) } } } @@ -120,7 +123,20 @@ class InstallViewModel( status = Status.Installing - installer.install(appVersions) + if (isRoot) { + when (val installStatus = installer.installRoot(appVersions)) { + is PMRootResult.Success -> { + status = Status.Installed + log(Log.Success("Successfully installed")) + } + is PMRootResult.Error -> { + status = Status.Failure + log(Log.Error("Failed to install app", installStatus.message)) + } + } + } else { + installer.install(appVersions) + } } private fun getDownloader( diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt index 7732618a7f..1a7b7e6525 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt @@ -10,7 +10,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.viewModelScope -import com.vanced.manager.core.installer.util.uninstallPackage +import com.vanced.manager.core.installer.util.PM import com.vanced.manager.core.preferences.holder.managerVariantPref import com.vanced.manager.domain.model.App import com.vanced.manager.network.util.MICROG_NAME @@ -80,7 +80,7 @@ class MainViewModel( fun uninstallApp( appPackage: String, ) { - uninstallPackage(appPackage, app) + PM.uninstallPackage(appPackage, app) } private suspend fun fetchData( diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/settings/AccentColorItem.kt similarity index 95% rename from app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt rename to app/src/main/java/com/vanced/manager/ui/widget/settings/AccentColorItem.kt index 71da7a9445..996ee85762 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/AccentColorItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/settings/AccentColorItem.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.widget.screens.settings +package com.vanced.manager.ui.widget.settings import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ClearFilesItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/settings/ClearFilesItem.kt similarity index 88% rename from app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ClearFilesItem.kt rename to app/src/main/java/com/vanced/manager/ui/widget/settings/ClearFilesItem.kt index 57cb4ed4bc..7dedf13ee1 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ClearFilesItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/settings/ClearFilesItem.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.widget.screens.settings +package com.vanced.manager.ui.widget.settings import androidx.compose.runtime.Composable import com.vanced.manager.R diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/CustomTabsItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/settings/CustomTabsItem.kt similarity index 92% rename from app/src/main/java/com/vanced/manager/ui/widget/screens/settings/CustomTabsItem.kt rename to app/src/main/java/com/vanced/manager/ui/widget/settings/CustomTabsItem.kt index bfe7d412d8..b71f0da325 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/CustomTabsItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/settings/CustomTabsItem.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.widget.screens.settings +package com.vanced.manager.ui.widget.settings import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/settings/ManagerVariantItem.kt similarity index 87% rename from app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt rename to app/src/main/java/com/vanced/manager/ui/widget/settings/ManagerVariantItem.kt index 121a30a1ad..dd553b5a19 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ManagerVariantItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/settings/ManagerVariantItem.kt @@ -1,9 +1,10 @@ -package com.vanced.manager.ui.widget.screens.settings +package com.vanced.manager.ui.widget.settings import androidx.compose.runtime.* import com.vanced.manager.R import com.vanced.manager.core.preferences.RadioButtonPreference import com.vanced.manager.core.preferences.holder.managerVariantPref +import com.vanced.manager.core.util.isMagiskInstalled import com.vanced.manager.ui.component.preference.SingleSelectDialogPreference import com.vanced.manager.ui.resources.managerString @@ -36,6 +37,9 @@ fun SettingsManagerVariantItem() { selectedKey = managerVariantPref }, onItemClick = { + if (it == "root" && !isMagiskInstalled) + return@SingleSelectDialogPreference + selectedKey = it }, onSave = { diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/NotificationsItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/settings/NotificationsItem.kt similarity index 94% rename from app/src/main/java/com/vanced/manager/ui/widget/screens/settings/NotificationsItem.kt rename to app/src/main/java/com/vanced/manager/ui/widget/settings/NotificationsItem.kt index 5e6393e66d..8fb8d8c6dc 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/NotificationsItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/settings/NotificationsItem.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.widget.screens.settings +package com.vanced.manager.ui.widget.settings import androidx.compose.runtime.Composable import com.vanced.manager.core.preferences.managerBooleanPreference diff --git a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/settings/ThemeItem.kt similarity index 96% rename from app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt rename to app/src/main/java/com/vanced/manager/ui/widget/settings/ThemeItem.kt index 45392cef53..4ae1d778a5 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/screens/settings/ThemeItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/settings/ThemeItem.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.widget.screens.settings +package com.vanced.manager.ui.widget.settings import androidx.compose.runtime.* import com.vanced.manager.R From 4477180d2d044206c444729903b162905f98db2b Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Wed, 9 Feb 2022 13:48:00 +0400 Subject: [PATCH 103/118] update deps --- app/build.gradle.kts | 17 ++++++++--------- build.gradle.kts | 4 ++-- gradle/wrapper/gradle-wrapper.properties | 2 +- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9b49f17c16..922e6bdbdc 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -4,7 +4,7 @@ plugins { id("kotlin-parcelize") } -val composeVersion = "1.1.0-beta04" +val composeVersion = "1.1.0-rc03" android { compileSdk = 31 @@ -24,7 +24,8 @@ android { } lint { - disable("MissingTranslation", "ExtraTranslation") + disable += "MissingTranslation" + disable += "ExtraTranslation" } buildTypes { @@ -84,9 +85,9 @@ dependencies { // AndroidX implementation("androidx.core:core-ktx:1.7.0") - implementation("androidx.appcompat:appcompat:1.4.0") + implementation("androidx.appcompat:appcompat:1.4.1") implementation("androidx.browser:browser:1.4.0") - implementation("androidx.preference:preference-ktx:1.1.1") + implementation("androidx.preference:preference-ktx:1.2.0") implementation("androidx.activity:activity-compose:1.4.0") val lifecycleVersion = "2.4.0" @@ -99,23 +100,21 @@ dependencies { implementation("androidx.compose.material:material-icons-core:$composeVersion") implementation("androidx.compose.material:material-icons-extended:$composeVersion") implementation("androidx.compose.material:material:$composeVersion") - implementation("androidx.compose.material3:material3:1.0.0-alpha02") + implementation("androidx.compose.material3:material3:1.0.0-alpha04") implementation("androidx.compose.runtime:runtime-livedata:$composeVersion") implementation("androidx.compose.ui:ui-tooling:$composeVersion") implementation("androidx.compose.ui:ui-util:$composeVersion") implementation("androidx.compose.ui:ui:$composeVersion") - // Google - implementation("com.google.android.material:material:1.4.0") + implementation("com.google.android.material:material:1.5.0") - val accompanistVersion = "0.20.0" + val accompanistVersion = "0.22.1-rc" implementation("com.google.accompanist:accompanist-navigation-animation:$accompanistVersion") implementation("com.google.accompanist:accompanist-placeholder-material:$accompanistVersion") implementation("com.google.accompanist:accompanist-swiperefresh:$accompanistVersion") implementation("com.google.accompanist:accompanist-systemuicontroller:$accompanistVersion") - // Other implementation("com.github.zsoltk:compose-router:0.28.0") diff --git a/build.gradle.kts b/build.gradle.kts index b1ebe4894f..23e841ea6c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,9 +4,9 @@ buildscript { mavenCentral() } - val kotlinVersion = "1.6.0" + val kotlinVersion = "1.6.10" dependencies { - classpath("com.android.tools.build:gradle:7.0.4") + classpath("com.android.tools.build:gradle:7.1.0") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") } } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0f80bbf516..ffed3a254e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From db0f2b44c9f7b3b2e547d718369e1e59fe5b7fcf Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Wed, 9 Feb 2022 18:34:05 +0400 Subject: [PATCH 104/118] update configurations screen --- .../com/vanced/manager/di/ViewModelModule.kt | 6 + .../domain/model/InstallationOption.kt | 20 +- .../com/vanced/manager/ui/MainActivity.kt | 8 +- .../manager/ui/screens/ConfigurationScreen.kt | 259 ++++++++++++++++++ .../ui/screens/InstallPreferencesScreen.kt | 225 --------------- .../java/com/vanced/manager/ui/util/Screen.kt | 2 +- .../ui/viewmodel/ConfigurationViewModel.kt | 25 ++ .../manager/ui/widget/list/CheckboxItem.kt | 2 + .../manager/ui/widget/list/RadiobuttonItem.kt | 2 + 9 files changed, 309 insertions(+), 240 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/ui/screens/ConfigurationScreen.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/viewmodel/ConfigurationViewModel.kt diff --git a/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt index 7e6a3f15d4..3752c1e271 100644 --- a/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt +++ b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt @@ -10,6 +10,7 @@ import com.vanced.manager.core.installer.impl.VancedInstaller import com.vanced.manager.repository.DataRepository import com.vanced.manager.repository.MainRepository import com.vanced.manager.repository.MirrorRepository +import com.vanced.manager.ui.viewmodel.ConfigurationViewModel import com.vanced.manager.ui.viewmodel.InstallViewModel import com.vanced.manager.ui.viewmodel.MainViewModel import org.koin.android.ext.koin.androidApplication @@ -34,6 +35,11 @@ val viewModelModule = module { microgInstaller: MicrogInstaller, ) = InstallViewModel(vancedDownloader, musicDownloader, microgDownloader, vancedInstaller, musicInstaller, microgInstaller) + fun provideConfigurationViewModel(): ConfigurationViewModel { + return ConfigurationViewModel() + } + viewModel { provideMainViewModel(get(), get(), androidApplication()) } viewModel { provideInstallViewModel(get(), get(), get(), get(), get(), get()) } + viewModel { provideConfigurationViewModel() } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/domain/model/InstallationOption.kt b/app/src/main/java/com/vanced/manager/domain/model/InstallationOption.kt index c79cd4e2be..4f7471d031 100644 --- a/app/src/main/java/com/vanced/manager/domain/model/InstallationOption.kt +++ b/app/src/main/java/com/vanced/manager/domain/model/InstallationOption.kt @@ -1,29 +1,29 @@ package com.vanced.manager.domain.model import android.os.Parcelable -import androidx.annotation.StringRes import kotlinx.parcelize.Parcelize -sealed class InstallationOption( - @StringRes val itemTitleId: Int, -) : Parcelable { +sealed class InstallationOption : Parcelable { + + abstract val titleId: Int + abstract val items: List<InstallationOptionItem> @Parcelize data class MultiSelect( - @StringRes val titleId: Int, - val items: List<InstallationOptionItem>, + override val titleId: Int, + override val items: List<InstallationOptionItem>, val getOption: () -> Set<String>, val addOption: (String) -> Unit, val removeOption: (String) -> Unit - ) : InstallationOption(titleId) + ) : InstallationOption() @Parcelize data class SingleSelect( - @StringRes val titleId: Int, - val items: List<InstallationOptionItem>, + override val titleId: Int, + override val items: List<InstallationOptionItem>, val getOption: () -> String, val setOption: (String) -> Unit, - ) : InstallationOption(titleId) + ) : InstallationOption() } diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index 61c268424c..4909f7d1ce 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -89,7 +89,7 @@ class MainActivity : ComponentActivity() { onAppInstallPress = { appName, appVersions, installationOptions -> if (installationOptions != null) { backStack.push( - Screen.InstallPreferences( + Screen.Configuration( appName, appVersions, installationOptions @@ -118,13 +118,13 @@ class MainActivity : ComponentActivity() { is Screen.Logs -> { } - is Screen.InstallPreferences -> { - InstallPreferencesScreen( + is Screen.Configuration -> { + ConfigurationScreen( installationOptions = screen.appInstallationOptions, onToolbarBackButtonClick = { backStack.pop() }, - onDoneClick = { + onFinishClick = { backStack.push( Screen.Install( screen.appName, diff --git a/app/src/main/java/com/vanced/manager/ui/screens/ConfigurationScreen.kt b/app/src/main/java/com/vanced/manager/ui/screens/ConfigurationScreen.kt new file mode 100644 index 0000000000..6b82d129dd --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/screens/ConfigurationScreen.kt @@ -0,0 +1,259 @@ +package com.vanced.manager.ui.screens + +import androidx.compose.animation.* +import androidx.compose.animation.core.tween +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.ListItem +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.ArrowBackIosNew +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.vanced.manager.R +import com.vanced.manager.domain.model.InstallationOption +import com.vanced.manager.ui.component.card.ManagerTonalCard +import com.vanced.manager.ui.component.text.ManagerText +import com.vanced.manager.ui.component.topappbar.ManagerTopAppBar +import com.vanced.manager.ui.resources.managerString +import com.vanced.manager.ui.theme.LargeShape +import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal +import com.vanced.manager.ui.util.DefaultContentPaddingVertical +import com.vanced.manager.ui.viewmodel.ConfigurationViewModel +import com.vanced.manager.ui.widget.layout.managerCategory +import org.koin.androidx.compose.getViewModel + +@ExperimentalFoundationApi +@ExperimentalAnimationApi +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun ConfigurationScreen( + installationOptions: List<InstallationOption>, + onToolbarBackButtonClick: () -> Unit, + onFinishClick: () -> Unit, +) { + val viewModel: ConfigurationViewModel = getViewModel() + Scaffold( + topBar = { + ManagerTopAppBar( + title = managerString(R.string.toolbar_installation_preferences), + navigationIcon = { + IconButton( + onClick = { + onToolbarBackButtonClick() + viewModel.reset() + } + ) { + Icon( + imageVector = Icons.Rounded.ArrowBackIosNew, + contentDescription = "Back" + ) + } + } + ) + }, + bottomBar = { + ConfigurationButtons( + modifier = Modifier + .padding( + horizontal = DefaultContentPaddingHorizontal, + vertical = DefaultContentPaddingVertical + ), + lastIndex = installationOptions.lastIndex, + currentIndex = viewModel.currentIndex, + onBackClick = { + viewModel.back() + }, + onNextClick = { + viewModel.next() + }, + onFinishClick = { + onFinishClick() + viewModel.reset() + } + ) + } + ) { paddingValues -> + ConfigurationBody( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues), + currentIndex = viewModel.currentIndex, + installationOptions = installationOptions + ) + } +} + +@OptIn(ExperimentalAnimationApi::class, ExperimentalMaterial3Api::class) +@Composable +private fun ConfigurationBody( + currentIndex: Int, + installationOptions: List<InstallationOption>, + modifier: Modifier = Modifier +) { + AnimatedContent( + modifier = modifier, + targetState = currentIndex, + transitionSpec = { + slideAnimationSpec( + if (targetState > initialState) { + AnimatedContentScope.SlideDirection.Start + } else { + AnimatedContentScope.SlideDirection.End + } + ) + } + ) { optionIndex -> + val installationOption = installationOptions[optionIndex] + val categoryName = managerString(installationOption.titleId) + LazyColumn { + when (installationOption) { + is InstallationOption.SingleSelect -> { + managerCategory( + categoryName = categoryName, + items = installationOption.items + ) { item -> + val preference = installationOption.getOption() + ConfigurationItem( + modifier = Modifier + .fillMaxWidth(), + text = item.displayText(item.key), + onClick = { + installationOption.setOption(item.key) + }, + trailing = { + RadioButton( + selected = preference == item.key, + onClick = null + ) + } + ) + } + } + is InstallationOption.MultiSelect -> { + managerCategory( + categoryName = categoryName, + items = installationOption.items + ) { item -> + val preference = installationOption.getOption() + ConfigurationItem( + modifier = Modifier + .fillMaxWidth(), + text = item.displayText(item.key), + onClick = { + if (preference.contains(item.key)) { + installationOption.removeOption(item.key) + } else { + installationOption.addOption(item.key) + } + }, + trailing = { + Checkbox( + checked = preference.contains(item.key), + onCheckedChange = null + ) + } + ) + } + } + } + } + } +} + +@OptIn(ExperimentalAnimationApi::class) +@Composable +private fun ConfigurationButtons( + currentIndex: Int, + lastIndex: Int, + onBackClick: () -> Unit, + onNextClick: () -> Unit, + onFinishClick: () -> Unit, + modifier: Modifier = Modifier, +) { + Row(modifier = modifier) { + AnimatedVisibility( + modifier = Modifier + .wrapContentWidth(Alignment.Start) + .weight(1f), + visible = currentIndex > 0) { + TextButton(onClick = onBackClick) { + ManagerText(text = "Back") + } + } + AnimatedContent( + modifier = Modifier + .wrapContentWidth(Alignment.End) + .weight(1f), + targetState = currentIndex == lastIndex, + transitionSpec = { + slideAnimationSpec( + if (initialState && !targetState) { + AnimatedContentScope.SlideDirection.Up + } else { + AnimatedContentScope.SlideDirection.Down + } + ) + } + ) { isLastIndex -> + if (isLastIndex) { + ElevatedButton(onClick = onFinishClick) { + ManagerText(text = "Finish") + } + } else { + OutlinedButton(onClick = onNextClick) { + ManagerText(text = "Next") + } + } + } + } +} + +@OptIn(ExperimentalMaterialApi::class) +@Composable +private fun ConfigurationItem( + text: String, + onClick: () -> Unit, + trailing: @Composable () -> Unit, + modifier: Modifier = Modifier, +) { + ManagerTonalCard( + modifier = modifier + .padding( + start = 6.dp, + end = 6.dp, + bottom = 8.dp + ), + shape = LargeShape, + onClick = onClick + ) { + ListItem( + text = { + ManagerText( + text = text, + textStyle = MaterialTheme.typography.titleSmall + ) + }, + trailing = trailing, + ) + } +} + +@ExperimentalAnimationApi +private fun <S> AnimatedContentScope<S>.slideAnimationSpec( + slideDirection: AnimatedContentScope.SlideDirection +) = slideIntoContainer( + towards = slideDirection, + animationSpec = tween(400) +) + fadeIn( + animationSpec = tween(400) +) with slideOutOfContainer( + towards = slideDirection, + animationSpec = tween(400) +) + fadeOut( + animationSpec = tween(400) +) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt b/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt deleted file mode 100644 index f1cb4514bf..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/screens/InstallPreferencesScreen.kt +++ /dev/null @@ -1,225 +0,0 @@ -package com.vanced.manager.ui.screens - -import androidx.compose.animation.* -import androidx.compose.animation.core.tween -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.items -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.ArrowBackIosNew -import androidx.compose.material.icons.rounded.Done -import androidx.compose.material.icons.rounded.NavigateBefore -import androidx.compose.material.icons.rounded.NavigateNext -import androidx.compose.material3.* -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.vanced.manager.R -import com.vanced.manager.domain.model.InstallationOption -import com.vanced.manager.ui.component.card.ManagerTonalCard -import com.vanced.manager.ui.component.layout.ManagerLazyColumn -import com.vanced.manager.ui.component.layout.ManagerScaffold -import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.component.topappbar.ManagerTopAppBar -import com.vanced.manager.ui.resources.managerString -import com.vanced.manager.ui.theme.LargeShape -import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal -import com.vanced.manager.ui.util.DefaultContentPaddingVertical -import com.vanced.manager.ui.widget.list.CheckboxItem -import com.vanced.manager.ui.widget.list.RadiobuttonItem - -@ExperimentalFoundationApi -@ExperimentalAnimationApi -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun InstallPreferencesScreen( - installationOptions: List<InstallationOption>, - onToolbarBackButtonClick: () -> Unit, - onDoneClick: () -> Unit, -) { - var currentOptionIndex by rememberSaveable { mutableStateOf(0) } - - ManagerScaffold( - topBar = { - ManagerTopAppBar( - title = managerString(R.string.toolbar_installation_preferences), - navigationIcon = { - IconButton( - onClick = onToolbarBackButtonClick - ) { - Icon( - imageVector = Icons.Rounded.ArrowBackIosNew, - contentDescription = "Back" - ) - } - } - ) - }, - ) { paddingValues -> - Column( - modifier = Modifier - .fillMaxSize() - .padding(paddingValues), - ) { - AnimatedContent( - modifier = Modifier - .padding( - horizontal = DefaultContentPaddingHorizontal, - vertical = DefaultContentPaddingVertical - ) - .weight(1f), - targetState = currentOptionIndex, - transitionSpec = { - getSlideAnimationSpec( - if (targetState > initialState) { - AnimatedContentScope.SlideDirection.Start - } else { - AnimatedContentScope.SlideDirection.End - } - ) - } - ) { optionIndex -> - val installationOption = installationOptions[optionIndex] - ManagerTonalCard( - modifier = Modifier - .wrapContentHeight( - align = Alignment.Top - ), - shape = LargeShape - ) { - Column { - ManagerText( - modifier = Modifier - .fillMaxWidth() - .padding( - horizontal = DefaultContentPaddingHorizontal, - vertical = DefaultContentPaddingVertical - ), - text = managerString(installationOption.itemTitleId), - textStyle = MaterialTheme.typography.titleLarge, - ) - ManagerLazyColumn( - contentPadding = PaddingValues( - start = 4.dp, - end = 4.dp, - bottom = DefaultContentPaddingVertical - ) - ) { - when (installationOption) { - is InstallationOption.MultiSelect -> { - items(installationOption.items) { item -> - val preference = installationOption.getOption() - CheckboxItem( - modifier = Modifier.fillMaxWidth(), - text = item.displayText(item.key), - checked = preference.contains(item.key), - onCheckedChange = { - if (it) { - installationOption.addOption(item.key) - } else { - installationOption.removeOption(item.key) - } - } - ) - } - } - is InstallationOption.SingleSelect -> { - items(installationOption.items) { item -> - val preference = installationOption.getOption() - RadiobuttonItem( - modifier = Modifier.fillMaxWidth(), - text = item.displayText(item.key), - selected = preference == item.key, - onClick = { - installationOption.setOption(item.key) - }, - ) - } - } - } - } - } - } - } - Row( - modifier = Modifier - .fillMaxWidth() - .padding( - horizontal = DefaultContentPaddingHorizontal, - vertical = DefaultContentPaddingVertical - ), - ) { - AnimatedVisibility( - visible = currentOptionIndex > 0 - ) { - FloatingActionButton( - onClick = { - currentOptionIndex-- - } - ) { - Icon( - imageVector = Icons.Rounded.NavigateBefore, - contentDescription = "Back" - ) - } - } - Spacer(modifier = Modifier.weight(1f)) - AnimatedContent( - targetState = currentOptionIndex == installationOptions.lastIndex, - transitionSpec = { - - getSlideAnimationSpec( - if (initialState && !targetState) { - AnimatedContentScope.SlideDirection.Up - } else { - AnimatedContentScope.SlideDirection.Down - } - ) - } - ) { lastIndex -> - if (lastIndex) { - FloatingActionButton( - onClick = onDoneClick - ) { - Icon( - imageVector = Icons.Rounded.Done, - contentDescription = "Done" - ) - } - } else { - FloatingActionButton( - onClick = { - currentOptionIndex++ - } - ) { - Icon( - imageVector = Icons.Rounded.NavigateNext, - contentDescription = "Next" - ) - } - } - } - } - } - } -} - -@ExperimentalAnimationApi -private fun <S> AnimatedContentScope<S>.getSlideAnimationSpec( - slideDirection: AnimatedContentScope.SlideDirection -) = slideIntoContainer( - towards = slideDirection, - animationSpec = tween(400) -) + fadeIn( - animationSpec = tween(400) -) with slideOutOfContainer( - towards = slideDirection, - animationSpec = tween(400) -) + fadeOut( - animationSpec = tween(400) -) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/util/Screen.kt b/app/src/main/java/com/vanced/manager/ui/util/Screen.kt index cfb77b6250..0c193b14f2 100644 --- a/app/src/main/java/com/vanced/manager/ui/util/Screen.kt +++ b/app/src/main/java/com/vanced/manager/ui/util/Screen.kt @@ -28,7 +28,7 @@ sealed class Screen( displayName = R.string.toolbar_logs, ) - data class InstallPreferences( + data class Configuration( val appName: String, val appVersions: List<String>?, val appInstallationOptions: List<InstallationOption> diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/ConfigurationViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/ConfigurationViewModel.kt new file mode 100644 index 0000000000..42052f6c57 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/ConfigurationViewModel.kt @@ -0,0 +1,25 @@ +package com.vanced.manager.ui.viewmodel + +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.lifecycle.ViewModel + +class ConfigurationViewModel : ViewModel() { + + var currentIndex by mutableStateOf(0) + private set + + fun next() { + currentIndex++ + } + + fun back() { + currentIndex-- + } + + fun reset() { + currentIndex = 0 + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt index 974c5faed5..71d59961e4 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt @@ -1,6 +1,7 @@ package com.vanced.manager.ui.widget.list import androidx.compose.material3.Checkbox +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -9,6 +10,7 @@ import com.vanced.manager.ui.component.list.ManagerSelectableListItem import com.vanced.manager.ui.component.modifier.managerClickable import com.vanced.manager.ui.component.text.ManagerText +@OptIn(ExperimentalMaterial3Api::class) @Composable fun CheckboxItem( text: String, diff --git a/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt index 0a4aeb7148..01fb8ad2bc 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt @@ -1,5 +1,6 @@ package com.vanced.manager.ui.widget.list +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.RadioButton import androidx.compose.runtime.Composable @@ -9,6 +10,7 @@ import com.vanced.manager.ui.component.list.ManagerSelectableListItem import com.vanced.manager.ui.component.modifier.managerClickable import com.vanced.manager.ui.component.text.ManagerText +@OptIn(ExperimentalMaterial3Api::class) @Composable fun RadiobuttonItem( text: String, From e03d039c8ca3d46a642b4e2a7315822aa64de3f8 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Wed, 9 Feb 2022 22:02:08 +0400 Subject: [PATCH 105/118] update configuration transitions --- .../manager/ui/screens/ConfigurationScreen.kt | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/ui/screens/ConfigurationScreen.kt b/app/src/main/java/com/vanced/manager/ui/screens/ConfigurationScreen.kt index 6b82d129dd..78490a6c9c 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/ConfigurationScreen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screens/ConfigurationScreen.kt @@ -27,6 +27,9 @@ import com.vanced.manager.ui.viewmodel.ConfigurationViewModel import com.vanced.manager.ui.widget.layout.managerCategory import org.koin.androidx.compose.getViewModel +private const val enterDuration = 300 +private const val exitDuration = 250 + @ExperimentalFoundationApi @ExperimentalAnimationApi @OptIn(ExperimentalMaterial3Api::class) @@ -180,7 +183,15 @@ private fun ConfigurationButtons( modifier = Modifier .wrapContentWidth(Alignment.Start) .weight(1f), - visible = currentIndex > 0) { + visible = currentIndex > 0, + enter = fadeIn(tween(enterDuration)) + + expandHorizontally(tween(enterDuration)) + + scaleIn(tween(enterDuration)), + exit = fadeOut(tween(exitDuration)) + + shrinkHorizontally(tween(exitDuration)) + + scaleOut(tween(exitDuration)), + + ) { TextButton(onClick = onBackClick) { ManagerText(text = "Back") } @@ -248,12 +259,12 @@ private fun <S> AnimatedContentScope<S>.slideAnimationSpec( slideDirection: AnimatedContentScope.SlideDirection ) = slideIntoContainer( towards = slideDirection, - animationSpec = tween(400) + animationSpec = tween(enterDuration) ) + fadeIn( - animationSpec = tween(400) + animationSpec = tween(enterDuration) ) with slideOutOfContainer( towards = slideDirection, - animationSpec = tween(400) + animationSpec = tween(exitDuration) ) + fadeOut( - animationSpec = tween(400) + animationSpec = tween(exitDuration) ) \ No newline at end of file From 5cf2cd1cbe621f4b3a9d83c917ffe8a3e4cb5d07 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Thu, 10 Feb 2022 14:19:19 +0400 Subject: [PATCH 106/118] update deps --- app/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 922e6bdbdc..299c9e4516 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -4,7 +4,7 @@ plugins { id("kotlin-parcelize") } -val composeVersion = "1.1.0-rc03" +val composeVersion = "1.1.0" android { compileSdk = 31 @@ -100,7 +100,7 @@ dependencies { implementation("androidx.compose.material:material-icons-core:$composeVersion") implementation("androidx.compose.material:material-icons-extended:$composeVersion") implementation("androidx.compose.material:material:$composeVersion") - implementation("androidx.compose.material3:material3:1.0.0-alpha04") + implementation("androidx.compose.material3:material3:1.0.0-alpha05") implementation("androidx.compose.runtime:runtime-livedata:$composeVersion") implementation("androidx.compose.ui:ui-tooling:$composeVersion") implementation("androidx.compose.ui:ui-util:$composeVersion") From 1902d2b94ab05d41adaf47f8b241fb713597ea82 Mon Sep 17 00:00:00 2001 From: Milind Goel <milindgoel15@gmail.com> Date: Tue, 15 Feb 2022 12:55:34 +0530 Subject: [PATCH 107/118] Added support for themed icon (Android 13 only) --- .../res/drawable/ic_manager_monet_icon.xml | 49 +++++++++++++++++++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 1 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 1 + 3 files changed, 51 insertions(+) create mode 100644 app/src/main/res/drawable/ic_manager_monet_icon.xml diff --git a/app/src/main/res/drawable/ic_manager_monet_icon.xml b/app/src/main/res/drawable/ic_manager_monet_icon.xml new file mode 100644 index 0000000000..d7b9b9db93 --- /dev/null +++ b/app/src/main/res/drawable/ic_manager_monet_icon.xml @@ -0,0 +1,49 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + <path + android:fillColor="#FF000000" + android:pathData="M11.9288,9.11a0.4558,0.4558 0,0 1,-0.039 -0.5383l0.0078,-0.0156a0.4655,0.4655 0,0 1,0.64 -0.1716l1.1545,0.7489C12.88,9.11 12.1706,9.11 12.1706,9.11ZM17.7169,11.7232 L16.89,11.1932c0.0234,0.3511 0.039,0.6943 0.0468,0.96l0.07,0.039a0.4967,0.4967 0,0 1,0 0.85l-0.07,0.039L12.03,15.9745a0.62,0.62 0,0 0,-0.1326 0.1092h0a0.4579,0.4579 0,0 0,-0.0468 0.53l0.0078,0.0156a0.4618,0.4618 0,0 0,0.64 0.1716l1.1779,-0.7488 3.1983,-2.0282 0.8191,-0.5226A1.0439,1.0439 0,0 0,17.7169 11.7231Z"/> + <path + android:fillColor="#FF000000" + android:pathData="M12.9351,12.3178l-1.4575,-0.8372a0.2845,0.2845 0,0 0,-0.4261 0.2467v1.6818a0.2845,0.2845 0,0 0,0.4261 0.2466l1.4575,-0.8371A0.2937,0.2937 0,0 0,12.9351 12.3178Z" + android:strokeWidth="0.0502" + android:strokeColor="#000"/> + <path + android:pathData="M12.5716,12.4526a0.047,0.047 0,0 1,-0.0384 -0.0128l-0.55,-0.32a0.0746,0.0746 0,0 1,0.0767 -0.128l0.55,0.32a0.0692,0.0692 0,0 1,0.0256 0.1024A0.07,0.07 0,0 1,12.5716 12.4526ZM12.7763,12.4142a0.0768,0.0768 0,1 1,-0.0767 0.0768A0.0768,0.0768 0,0 1,12.7763 12.4142Z" + android:strokeWidth="0.0859" + android:fillColor="#fff" + android:strokeColor="#000"/> + <path + android:fillColor="#FF000000" + android:pathData="M15.7571,10.9923a0.09,0.09 0,0 1,-0.09 -0.0672c-0.0075,-0.03 -0.0149,-0.0524 -0.0224,-0.0823a1.0414,1.0414 0,0 0,-0.5158 -0.6577,1.1661 1.1661,0 0,0 -0.2242,-0.09c-0.0448,-0.0075 -0.0822,-0.0225 -0.12,-0.03a1.5581,1.5581 0,0 0,-0.1943 -0.03,0.0909 0.0909,0 1,1 0.03,-0.1794c0.1046,0.0149 0.1868,0.03 0.2018,0.03h0a0.8656,0.8656 0,0 1,0.1345 0.03h0a1.3342,1.3342 0,0 1,0.2691 0.1046,1.251 1.251,0 0,1 0.6054,0.77l0.0225,0.09a0.0831,0.0831 0,0 1,-0.0673 0.1046A0.0562,0.0562 0,0 1,15.7571 10.9923Z" + android:strokeWidth="0.1186" + android:strokeColor="#000"/> + <path + android:fillColor="#FF000000" + android:pathData="M15.8576,11.418m-0.0972,0a0.0972,0.0972 0,1 1,0.1944 0a0.0972,0.0972 0,1 1,-0.1944 0" + android:strokeWidth="0.1186" + android:strokeColor="#000"/> + <path + android:fillColor="#FF000000" + android:pathData="M8.3108,14.1474a0.09,0.09 0,0 1,0.09 0.0673c0.0075,0.03 0.015,0.0523 0.0224,0.0822a1.061,1.061 0,0 0,0.5158 0.6578,1.3979 1.3979,0 0,0 0.2242,0.09c0.0449,0.0075 0.0822,0.0224 0.1271,0.03 0.0374,0.0075 0.1121,0.0224 0.1869,0.03a0.0909,0.0909 0,0 1,-0.03 0.1794c-0.1047,-0.015 -0.1869,-0.03 -0.2019,-0.03h0a0.88,0.88 0,0 1,-0.1345 -0.03h0a1.1223,1.1223 0,0 1,-0.2616 -0.1047,1.2262 1.2262,0 0,1 -0.6054,-0.77l-0.0225,-0.09a0.0925,0.0925 0,0 1,0.0673 -0.1047A0.0274,0.0274 0,0 1,8.3108 14.1474Z" + android:strokeWidth="0.1186" + android:strokeColor="#000"/> + <path + android:fillColor="#FF000000" + android:pathData="M8.22,13.7061m-0.0972,0a0.0972,0.0972 0,1 1,0.1944 0a0.0972,0.0972 0,1 1,-0.1944 0" + android:strokeWidth="0.1186" + android:strokeColor="#000"/> + <path + android:pathData="M16.7453,12.5616l0,0.0462c0,0.03 -0.0005,0.0737 -0.0012,0.1287s-0.0019,0.1213 -0.0035,0.1962 -0.0039,0.1588 -0.0068,0.2488c-0.0024,0.0712 -0.0053,0.1464 -0.0087,0.2243s-0.0074,0.1585 -0.0121,0.2405 -0.01,0.1654 -0.016,0.249 -0.0129,0.1673 -0.0207,0.25c-0.0072,0.0773 -0.0151,0.1537 -0.0238,0.2282s-0.0183,0.1472 -0.0287,0.2168 -0.0218,0.1364 -0.0341,0.1992 -0.0257,0.1215 -0.04,0.1752a1.1793,1.1793 0,0 1,-0.5435 0.7143,1.1632 1.1632,0 0,1 -0.2841,0.1192 2.69,2.69 0,0 1,-0.333 0.0608c-0.1352,0.0178 -0.2917,0.0332 -0.4618,0.0467s-0.3537,0.0248 -0.5429,0.0345 -0.384,0.0178 -0.5766,0.0244c-0.2242,0.0077 -0.4453,0.0135 -0.6508,0.0179s-0.3956,0.0072 -0.5576,0.0091 -0.2959,0.0029 -0.3894,0.0034 -0.1464,0.0005 -0.1464,0.0005h-0.0913c-0.125,-0.0005 -0.37,-0.0021 -0.6764,-0.0069s-0.6759,-0.0128 -1.05,-0.0262 -0.7524,-0.0323 -1.0784,-0.0588a4.8923,4.8923 0,0 1,-0.7626 -0.1047,1.156 1.156,0 0,1 -0.2841,-0.1188 1.179,1.179 0,0 1,-0.5434 -0.7146,4.78 4.78,0 0,1 -0.1133,-0.6855c-0.0275,-0.26 -0.0459,-0.5372 -0.0581,-0.7917s-0.0184,-0.4859 -0.0214,-0.6538 -0.0031,-0.2722 -0.0031,-0.2722 0,-0.1035 0.0031,-0.27 0.0091,-0.3967 0.0214,-0.65 0.0306,-0.5288 0.0581,-0.7873a4.7763,4.7763 0,0 1,0.1133 -0.6836,1.168 1.168,0 0,1 0.118,-0.286 1.1814,1.1814 0,0 1,0.4254 -0.4283,1.1646 1.1646,0 0,1 0.2841,-0.1191 4.26,4.26 0,0 1,0.6392 -0.094c0.2713,-0.0248 0.588,-0.0436 0.9124,-0.058s0.6564,-0.024 0.9581,-0.0307 0.5731,-0.01 0.7763,-0.0124l0.1551,-0.0013 0.1173,-0.0006 0.0742,0h0.0259l0.1071,0c0.0688,0 0.1682,0.0009 0.2906,0.0021s0.2676,0.003 0.4282,0.0057 0.3365,0.0062 0.52,0.011l0.0778,0.0022 0.0788,0.0022 0.0794,0.0022 0.08,0.0023 0.0082,0 0.0082,0 0.0081,0 0.0079,0 0.0531,0.0018 0.0533,0.0019 0.0535,0.0019 0.0536,0.0018 0.112,0.0045 0.1116,0.0048 0.1108,0.0051 0.1095,0.0054c0.0936,0.005 0.1856,0.01 0.2752,0.0162s0.1767,0.0121 0.26,0.0189 0.164,0.014 0.24,0.0218 0.1474,0.016 0.2135,0.0249l0.0038,0 0.0038,0.0006 0.0036,0.0005 0.0035,0.0006 0.0087,0.0011 0.0086,0.0012 0.0086,0.0013 0.0087,0.0015 0.0363,0.0055 0.0349,0.0056 0.0336,0.0055 0.0321,0.0055 0.036,0.0069 0.0341,0.0073 0.0319,0.0076 0.03,0.0077a1.1544,1.1544 0,0 1,0.2841 0.1188,1.1787 1.1787,0 0,1 0.5435,0.7146c0.0188,0.0709 0.0357,0.15 0.0511,0.2359s0.0291,0.1774 0.0414,0.2731 0.0231,0.1955 0.0327,0.2968 0.0178,0.2044 0.025,0.3067c0.0062,0.0906 0.0117,0.1806 0.0164,0.2684s0.0086,0.1736 0.0119,0.2556 0.006,0.16 0.0081,0.2333 0.0037,0.1406 0.0048,0.2013c0.0011,0.049 0.0019,0.0934 0.0026,0.1326l0.0013,0.1006 0,0.064Z" + android:strokeWidth="0.6367" + android:fillColor="#00000000" + android:strokeColor="#000"/> + <path + android:pathData="M9.0209,9.1409V8.4464A1.0643,1.0643 0,0 1,9.42 7.6336a1.4955,1.4955 0,0 1,0.9637 -0.3367h3.2484a1.4955,1.4955 0,0 1,0.9637 0.3367,1.0643 1.0643,0 0,1 0.3991,0.8128v0.6945" + android:strokeWidth="0.7" + android:fillColor="#00000000" + android:strokeColor="#000"/> +</vector> \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index 7353dbd1fd..48bb75f3d0 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -2,4 +2,5 @@ <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <background android:drawable="@color/ic_launcher_background"/> <foreground android:drawable="@drawable/ic_launcher_foreground"/> + <monochrome android:drawable="@drawable/ic_manager_monet_icon" /> </adaptive-icon> \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml index 7353dbd1fd..48bb75f3d0 100644 --- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -2,4 +2,5 @@ <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <background android:drawable="@color/ic_launcher_background"/> <foreground android:drawable="@drawable/ic_launcher_foreground"/> + <monochrome android:drawable="@drawable/ic_manager_monet_icon" /> </adaptive-icon> \ No newline at end of file From 9d73cae456b8a39ad6d3c6706e2686ee4bd66d23 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 22 Feb 2022 22:27:10 +0400 Subject: [PATCH 108/118] refactor ui components --- app/build.gradle.kts | 15 +- .../com/vanced/manager/ui/MainActivity.kt | 29 +- .../manager/ui/component/ManagerButton.kt | 148 +++++++++ .../manager/ui/component/ManagerCard.kt | 125 ++++++++ .../component/{dialog => }/ManagerDialog.kt | 5 +- .../{menu => }/ManagerDropdownMenu.kt | 37 ++- .../manager/ui/component/ManagerLazyColumn.kt | 63 ++++ .../manager/ui/component/ManagerLazyRow.kt | 42 +++ .../component/{list => }/ManagerListItem.kt | 32 +- .../ManagerNavigator.kt | 43 ++- .../manager/ui/component/ManagerPreference.kt | 263 ++++++++++++++++ .../ui/component/ManagerProgressIndicator.kt | 43 +++ .../component/{layout => }/ManagerScaffold.kt | 18 +- .../{list => }/ManagerSelectableListItem.kt | 2 +- .../{layout => }/ManagerSwipeRefresh.kt | 22 +- .../ui/component/{text => }/ManagerText.kt | 2 +- .../manager/ui/component/ManagerTopAppBar.kt | 44 +++ .../ui/component/animation/JumpAnimation.kt | 26 -- .../ui/component/button/ManagerIconButton.kt | 41 --- .../component/button/ManagerThemedButton.kt | 38 --- .../button/ManagerThemedTextButton.kt | 23 -- .../manager/ui/component/card/ManagerCard.kt | 53 ---- .../ui/component/card/ManagerItemCard.kt | 75 ----- .../ui/component/card/ManagerLinkCard.kt | 32 -- .../ui/component/card/ManagerThemedCard.kt | 37 --- .../ui/component/card/ManagerTonalCard.kt | 37 --- .../ui/component/checkbox/ManagerCheckbox.kt | 60 ---- .../component/color/ColorContentProvider.kt | 35 --- .../manager/ui/component/color/ColorPicker.kt | 27 -- .../ui/component/color/ManagerColors.kt | 38 --- .../component/layout/ManagerButtonColumn.kt | 20 -- .../ui/component/layout/ManagerLazyColumn.kt | 20 -- .../ui/component/layout/ManagerScrim.kt | 50 --- .../layout/ManagerScrollableColumn.kt | 32 -- .../ui/component/layout/ManagerSurface.kt | 18 -- .../ui/component/layout/ScrollableItemRow.kt | 35 --- .../component/menu/ManagerDropdownMenuItem.kt | 25 -- .../ui/component/modifier/ManagerClickable.kt | 25 -- .../component/modifier/ManagerPlaceholder.kt | 18 -- .../ui/component/modifier/ModifierBuilder.kt | 7 - .../preference/CheckboxPreference.kt | 30 -- .../component/preference/DialogPreference.kt | 33 -- .../preference/MultiSelectDialogPreference.kt | 62 ---- .../ui/component/preference/Preference.kt | 57 ---- .../SingleSelectDialogPreference.kt | 62 ---- .../ManagerProgressIndicator.kt | 44 --- .../radiobutton/ManagerRadiobutton.kt | 29 -- .../ui/component/text/AppVersionText.kt | 17 -- .../ui/component/text/CategoryTitleText.kt | 20 -- .../ui/component/text/ToolbarTitleText.kt | 16 - .../component/topappbar/ManagerTopAppBar.kt | 30 -- .../ui/navigation/NavigationController.kt | 44 --- .../{resources => resource}/ManagerString.kt | 2 +- .../AboutLayout.kt => screen/AboutScreen.kt} | 139 +++++---- .../ConfigurationScreen.kt | 138 ++++----- .../vanced/manager/ui/screen/HomeScreen.kt | 284 ++++++++++++++++++ .../ui/{screens => screen}/InstallScreen.kt | 26 +- .../manager/ui/screen/SettingsScreen.kt | 73 +++++ .../vanced/manager/ui/screens/HomeLayout.kt | 217 ------------- .../manager/ui/screens/SettingsLayout.kt | 72 ----- .../java/com/vanced/manager/ui/theme/Theme.kt | 46 +-- .../java/com/vanced/manager/ui/util/Color.kt | 10 + .../java/com/vanced/manager/ui/util/Const.kt | 4 +- .../manager/ui/viewmodel/MainViewModel.kt | 4 + .../com/vanced/manager/ui/widget/AppCard.kt | 257 ++++++++++++++++ .../com/vanced/manager/ui/widget/LinkCard.kt | 68 +++++ .../com/vanced/manager/ui/widget/Settings.kt | 138 +++++++++ .../vanced/manager/ui/widget/app/AppCard.kt | 100 ------ .../ui/widget/app/AppCardPlaceholder.kt | 71 ----- .../manager/ui/widget/app/BaseAppCard.kt | 82 ----- .../ui/widget/button/ManagerCancelButton.kt | 21 -- .../ui/widget/button/ManagerCloseButton.kt | 21 -- .../ui/widget/button/ManagerDownloadButton.kt | 21 -- .../ui/widget/button/ManagerResetButton.kt | 25 -- .../ui/widget/button/ManagerSaveButton.kt | 25 -- .../checkbox/ManagerAnimatedCheckbox.kt | 35 --- .../ui/widget/layout/CategoryLayout.kt | 76 ----- .../widget/layout/SettingsCategoryLayout.kt | 18 -- .../manager/ui/widget/list/CheckboxItem.kt | 40 --- .../manager/ui/widget/list/RadiobuttonItem.kt | 38 --- .../radiobutton/ManagerAnimatedRadiobutton.kt | 35 --- .../ui/widget/settings/AccentColorItem.kt | 32 -- .../ui/widget/settings/ClearFilesItem.kt | 17 -- .../ui/widget/settings/CustomTabsItem.kt | 19 -- .../ui/widget/settings/ManagerVariantItem.kt | 50 --- .../ui/widget/settings/NotificationsItem.kt | 26 -- .../manager/ui/widget/settings/ThemeItem.kt | 48 --- 87 files changed, 1882 insertions(+), 2545 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/ui/component/ManagerButton.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/component/ManagerCard.kt rename app/src/main/java/com/vanced/manager/ui/component/{dialog => }/ManagerDialog.kt (82%) rename app/src/main/java/com/vanced/manager/ui/component/{menu => }/ManagerDropdownMenu.kt (80%) create mode 100644 app/src/main/java/com/vanced/manager/ui/component/ManagerLazyColumn.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/component/ManagerLazyRow.kt rename app/src/main/java/com/vanced/manager/ui/component/{list => }/ManagerListItem.kt (55%) rename app/src/main/java/com/vanced/manager/ui/{navigation => component}/ManagerNavigator.kt (61%) create mode 100644 app/src/main/java/com/vanced/manager/ui/component/ManagerPreference.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/component/ManagerProgressIndicator.kt rename app/src/main/java/com/vanced/manager/ui/component/{layout => }/ManagerScaffold.kt (56%) rename app/src/main/java/com/vanced/manager/ui/component/{list => }/ManagerSelectableListItem.kt (95%) rename app/src/main/java/com/vanced/manager/ui/component/{layout => }/ManagerSwipeRefresh.kt (52%) rename app/src/main/java/com/vanced/manager/ui/component/{text => }/ManagerText.kt (95%) create mode 100644 app/src/main/java/com/vanced/manager/ui/component/ManagerTopAppBar.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/animation/JumpAnimation.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/button/ManagerIconButton.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedButton.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedTextButton.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/card/ManagerCard.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/card/ManagerItemCard.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/card/ManagerLinkCard.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/card/ManagerThemedCard.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/card/ManagerTonalCard.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/color/ColorContentProvider.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/color/ColorPicker.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/layout/ManagerButtonColumn.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrim.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrollableColumn.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSurface.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/layout/ScrollableItemRow.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenuItem.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/modifier/ManagerClickable.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/modifier/ManagerPlaceholder.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/modifier/ModifierBuilder.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/preference/DialogPreference.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/preference/MultiSelectDialogPreference.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/preference/SingleSelectDialogPreference.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/progressindicator/ManagerProgressIndicator.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/radiobutton/ManagerRadiobutton.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/text/AppVersionText.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/text/CategoryTitleText.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/text/ToolbarTitleText.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/topappbar/ManagerTopAppBar.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/navigation/NavigationController.kt rename app/src/main/java/com/vanced/manager/ui/{resources => resource}/ManagerString.kt (91%) rename app/src/main/java/com/vanced/manager/ui/{screens/AboutLayout.kt => screen/AboutScreen.kt} (63%) rename app/src/main/java/com/vanced/manager/ui/{screens => screen}/ConfigurationScreen.kt (63%) create mode 100644 app/src/main/java/com/vanced/manager/ui/screen/HomeScreen.kt rename app/src/main/java/com/vanced/manager/ui/{screens => screen}/InstallScreen.kt (88%) create mode 100644 app/src/main/java/com/vanced/manager/ui/screen/SettingsScreen.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/util/Color.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widget/AppCard.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widget/LinkCard.kt create mode 100644 app/src/main/java/com/vanced/manager/ui/widget/Settings.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/app/AppCard.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/app/AppCardPlaceholder.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/app/BaseAppCard.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/button/ManagerCancelButton.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/button/ManagerCloseButton.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/button/ManagerDownloadButton.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/button/ManagerResetButton.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/button/ManagerSaveButton.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/checkbox/ManagerAnimatedCheckbox.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/layout/CategoryLayout.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/layout/SettingsCategoryLayout.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/radiobutton/ManagerAnimatedRadiobutton.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/settings/AccentColorItem.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/settings/ClearFilesItem.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/settings/CustomTabsItem.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/settings/ManagerVariantItem.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/settings/NotificationsItem.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/settings/ThemeItem.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 299c9e4516..eda4419531 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,3 +1,6 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions + plugins { id("com.android.application") kotlin("android") @@ -57,13 +60,21 @@ android { } -tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> { + +tasks.withType<KotlinCompile>().configureEach { kotlinOptions { jvmTarget = "11" - freeCompilerArgs = freeCompilerArgs + "-Xopt-in=kotlin.RequiresOptIn" + optIn("androidx.compose.material3.ExperimentalMaterial3Api") + optIn("androidx.compose.animation.ExperimentalAnimationApi") + optIn("androidx.compose.foundation.ExperimentalFoundationApi") } } +fun KotlinJvmOptions.optIn(library: String) { + freeCompilerArgs = freeCompilerArgs + + "-opt-in=$library" +} + val languages: String get() { val langs = arrayListOf("en", "bn_BD", "bn_IN", "pa_IN", "pa_PK", "pt_BR", "pt_PT", "zh_CN", "zh_TW") val exceptions = arrayOf("bn", "pa", "pt", "zh") diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index 4909f7d1ce..6c87b62067 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -7,9 +7,7 @@ import android.content.IntentFilter import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.SideEffect import com.github.zsoltk.compose.backpress.BackPressHandler @@ -18,11 +16,11 @@ import com.github.zsoltk.compose.router.Router import com.google.accompanist.systemuicontroller.rememberSystemUiController import com.vanced.manager.core.installer.service.AppInstallService import com.vanced.manager.core.installer.service.AppUninstallService -import com.vanced.manager.ui.component.color.managerSurfaceColor -import com.vanced.manager.ui.screens.* +import com.vanced.manager.ui.screen.* import com.vanced.manager.ui.theme.ManagerTheme import com.vanced.manager.ui.theme.isDark import com.vanced.manager.ui.util.Screen +import com.vanced.manager.ui.util.animated import com.vanced.manager.ui.viewmodel.InstallViewModel import com.vanced.manager.ui.viewmodel.MainViewModel import org.koin.androidx.viewmodel.ext.android.viewModel @@ -52,17 +50,12 @@ class MainActivity : ComponentActivity() { } } - @OptIn( - ExperimentalAnimationApi::class, - ExperimentalMaterial3Api::class, - ExperimentalFoundationApi::class, - ) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mainViewModel.fetch() setContent { ManagerTheme { - val surfaceColor = managerSurfaceColor() + val surfaceColor = MaterialTheme.colorScheme.surface.animated val isDark = isDark() @@ -81,12 +74,12 @@ class MainActivity : ComponentActivity() { Router<Screen>("VancedManager", Screen.Home) { backStack -> when (val screen = backStack.last()) { is Screen.Home -> { - HomeLayout( + HomeScreen( viewModel = mainViewModel, onToolbarScreenSelected = { backStack.push(it) }, - onAppInstallPress = { appName, appVersions, installationOptions -> + onAppDownloadClick = { appName, appVersions, installationOptions -> if (installationOptions != null) { backStack.push( Screen.Configuration( @@ -98,18 +91,24 @@ class MainActivity : ComponentActivity() { } else { backStack.push(Screen.Install(appName, appVersions)) } + }, + onAppLaunchClick = { appName, packageName -> + mainViewModel.launchApp(appName, packageName) + }, + onAppUninstallClick = { packageName -> + mainViewModel.uninstallApp(packageName) } ) } is Screen.Settings -> { - SettingsLayout( + SettingsScreen( onToolbarBackButtonClick = { backStack.pop() } ) } is Screen.About -> { - AboutLayout( + AboutScreen( onToolbarBackButtonClick = { backStack.pop() } diff --git a/app/src/main/java/com/vanced/manager/ui/component/ManagerButton.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerButton.kt new file mode 100644 index 0000000000..86e3c2203c --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerButton.kt @@ -0,0 +1,148 @@ +package com.vanced.manager.ui.component + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.unit.dp + +@Composable +fun ManagerButton( + onClick: () -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + elevation: ButtonElevation? = ButtonDefaults.buttonElevation(), + shape: Shape = RoundedCornerShape(20.0.dp), + border: BorderStroke? = null, + colors: ButtonColors = ButtonDefaults.buttonColors(), + contentPadding: PaddingValues = ButtonDefaults.ContentPadding, + content: @Composable RowScope.() -> Unit +) { + Button( + onClick, + modifier, + enabled, + interactionSource, + elevation, + shape, + border, + colors, + contentPadding, + content + ) +} + +@Composable +fun ManagerElevatedButton( + onClick: () -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + elevation: ButtonElevation? = ButtonDefaults.elevatedButtonElevation(), + shape: Shape = RoundedCornerShape(20.0.dp), + border: BorderStroke? = null, + colors: ButtonColors = ButtonDefaults.elevatedButtonColors(), + contentPadding: PaddingValues = ButtonDefaults.ContentPadding, + content: @Composable RowScope.() -> Unit +) { + ElevatedButton( + onClick, + modifier, + enabled, + interactionSource, + elevation, + shape, + border, + colors, + contentPadding, + content + ) +} + +@Composable +fun ManagerFilledTonalButton( + onClick: () -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + elevation: ButtonElevation? = ButtonDefaults.filledTonalButtonElevation(), + shape: Shape = RoundedCornerShape(20.0.dp), + border: BorderStroke? = null, + colors: ButtonColors = ButtonDefaults.filledTonalButtonColors(), + contentPadding: PaddingValues = ButtonDefaults.ContentPadding, + content: @Composable RowScope.() -> Unit +) { + FilledTonalButton( + onClick, + modifier, + enabled, + interactionSource, + elevation, + shape, + border, + colors, + contentPadding, + content + ) +} + +@Composable +fun ManagerOutlinedButton( + onClick: () -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + elevation: ButtonElevation? = null, + shape: Shape = RoundedCornerShape(20.0.dp), + border: BorderStroke? = ButtonDefaults.outlinedButtonBorder, + colors: ButtonColors = ButtonDefaults.outlinedButtonColors(), + contentPadding: PaddingValues = ButtonDefaults.ContentPadding, + content: @Composable RowScope.() -> Unit +) { + Button( + onClick, + modifier, + enabled, + interactionSource, + elevation, + shape, + border, + colors, + contentPadding, + content + ) +} + +@Composable +fun ManagerTextButton( + onClick: () -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + elevation: ButtonElevation? = null, + shape: Shape = RoundedCornerShape(20.0.dp), + border: BorderStroke? = null, + colors: ButtonColors = ButtonDefaults.textButtonColors(), + contentPadding: PaddingValues = ButtonDefaults.ContentPadding, + content: @Composable RowScope.() -> Unit +) { + TextButton( + onClick, + modifier, + enabled, + interactionSource, + elevation, + shape, + border, + colors, + contentPadding, + content + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/ManagerCard.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerCard.kt new file mode 100644 index 0000000000..cbf96514f6 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerCard.kt @@ -0,0 +1,125 @@ +package com.vanced.manager.ui.component + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Shape +import com.vanced.manager.ui.theme.MediumShape +import com.vanced.manager.ui.util.animated + +@Composable +fun ManagerCard( + modifier: Modifier = Modifier, + onClick: (() -> Unit)? = null, + shape: Shape = MediumShape, + containerColor: Color = MaterialTheme.colorScheme.surface, + contentColor: Color = contentColorFor(containerColor), + elevation: CardElevation = CardDefaults.cardElevation(), + content: @Composable ColumnScope.() -> Unit, +) { + if (onClick != null) { + val interactionSource = remember { MutableInteractionSource() } + Card( + modifier = modifier + .clickable( + interactionSource = interactionSource, + indication = null, + onClick = onClick + ), + interactionSource = interactionSource, + shape = shape, + containerColor = containerColor.animated, + contentColor = contentColor.animated, + elevation = elevation, + content = content + ) + } else { + Card( + modifier = modifier, + shape = shape, + containerColor = containerColor.animated, + contentColor = contentColor.animated, + elevation = elevation, + content = content + ) + } +} +@Composable +fun ManagerElevatedCard( + modifier: Modifier = Modifier, + onClick: (() -> Unit)? = null, + shape: Shape = MediumShape, + containerColor: Color = MaterialTheme.colorScheme.surface, + contentColor: Color = contentColorFor(containerColor), + elevation: CardElevation = CardDefaults.elevatedCardElevation(), + content: @Composable ColumnScope.() -> Unit, +) { + if (onClick != null) { + val interactionSource = remember { MutableInteractionSource() } + ElevatedCard( + modifier = modifier + .clickable( + interactionSource = interactionSource, + indication = null, + onClick = onClick + ), + interactionSource = interactionSource, + shape = shape, + containerColor = containerColor.animated, + contentColor = contentColor.animated, + elevation = elevation, + content = content + ) + } else { + ElevatedCard( + modifier = modifier, + shape = shape, + containerColor = containerColor.animated, + contentColor = contentColor.animated, + elevation = elevation, + content = content + ) + } +} +@Composable +fun ManagerOutlinedCard( + modifier: Modifier = Modifier, + onClick: (() -> Unit)? = null, + shape: Shape = MediumShape, + containerColor: Color = MaterialTheme.colorScheme.surface, + contentColor: Color = contentColorFor(containerColor), + elevation: CardElevation = CardDefaults.outlinedCardElevation(), + content: @Composable ColumnScope.() -> Unit, +) { + if (onClick != null) { + val interactionSource = remember { MutableInteractionSource() } + OutlinedCard( + modifier = modifier + .clickable( + interactionSource = interactionSource, + indication = null, + onClick = onClick + ), + interactionSource = interactionSource, + shape = shape, + containerColor = containerColor.animated, + contentColor = contentColor.animated, + elevation = elevation, + content = content + ) + } else { + OutlinedCard( + modifier = modifier, + shape = shape, + containerColor = containerColor.animated, + contentColor = contentColor.animated, + elevation = elevation, + content = content + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerDialog.kt similarity index 82% rename from app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt rename to app/src/main/java/com/vanced/manager/ui/component/ManagerDialog.kt index f70c08ab26..0b577290ba 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/dialog/ManagerDialog.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerDialog.kt @@ -1,12 +1,10 @@ -package com.vanced.manager.ui.component.dialog +package com.vanced.manager.ui.component -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material3.AlertDialog import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.component.text.ManagerText import com.vanced.manager.ui.theme.LargeShape @Composable @@ -23,7 +21,6 @@ fun ManagerDialog( modifier = modifier, title = { ManagerText( - modifier = Modifier.fillMaxWidth(), text = title, textAlign = TextAlign.Center ) diff --git a/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenu.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerDropdownMenu.kt similarity index 80% rename from app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenu.kt rename to app/src/main/java/com/vanced/manager/ui/component/ManagerDropdownMenu.kt index d8a8493603..8076b88016 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenu.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerDropdownMenu.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.component.menu +package com.vanced.manager.ui.component import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.core.MutableTransitionState @@ -9,24 +9,26 @@ import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.width +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.OutlinedCard import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember -import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha +import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.scale import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.* import androidx.compose.ui.window.Popup import androidx.compose.ui.window.PopupPositionProvider import androidx.compose.ui.window.PopupProperties -import com.vanced.manager.ui.component.card.ManagerCard +import com.vanced.manager.ui.theme.SmallShape private const val TransitionDuration = 200 @ExperimentalAnimationApi -@OptIn(ExperimentalComposeUiApi::class) @Composable fun ManagerDropdownMenu( expanded: Boolean, @@ -47,21 +49,19 @@ fun ManagerDropdownMenu( if (expandedStates.currentState || expandedStates.targetState) { val density = LocalDensity.current - val popupPositionProvider = - ManagerDropdownMenuPopupPositionProvider(density) + val popupPositionProvider = ManagerDropdownMenuPopupPositionProvider(density) Popup( popupPositionProvider = popupPositionProvider, onDismissRequest = onDismissRequest, properties = PopupProperties(focusable = true) ) { - ManagerCard( + OutlinedCard( modifier = Modifier .width(IntrinsicSize.Max) .alpha(alphaAndScale) .scale(alphaAndScale), - tonalElevation = 2.dp, - shadowElevation = 2.dp + elevation = CardDefaults.elevatedCardElevation() ) { Column(content = content) } @@ -69,8 +69,22 @@ fun ManagerDropdownMenu( } } +@Composable +fun ManagerDropdownMenuItem( + title: String, + onClick: () -> Unit +) { + DropdownMenuItem( + onClick = onClick, + modifier = Modifier.clip(SmallShape), + text = { + ManagerText(text = title) + } + ) +} + //Kanged from Menu.kt -data class ManagerDropdownMenuPopupPositionProvider( +private data class ManagerDropdownMenuPopupPositionProvider( val density: Density ) : PopupPositionProvider { @@ -101,8 +115,7 @@ data class ManagerDropdownMenuPopupPositionProvider( val toCenter = anchorBounds.top - popupContentSize.height / 2 val toDisplayBottom = windowSize.height - popupContentSize.height - verticalMargin val y = sequenceOf(toBottom, toTop, toCenter, toDisplayBottom).firstOrNull { - it >= verticalMargin && - it + popupContentSize.height <= windowSize.height - verticalMargin + it >= verticalMargin && it + popupContentSize.height <= windowSize.height - verticalMargin } ?: toTop return IntOffset(x, y) diff --git a/app/src/main/java/com/vanced/manager/ui/component/ManagerLazyColumn.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerLazyColumn.kt new file mode 100644 index 0000000000..f08381f435 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerLazyColumn.kt @@ -0,0 +1,63 @@ +package com.vanced.manager.ui.component + +import androidx.compose.foundation.gestures.FlingBehavior +import androidx.compose.foundation.gestures.ScrollableDefaults +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListScope +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.vanced.manager.ui.util.EdgeToEdgeContentPadding + +@Composable +fun ManagerLazyColumn( + modifier: Modifier = Modifier, + state: LazyListState = rememberLazyListState(), + contentPadding: PaddingValues = PaddingValues( + start = EdgeToEdgeContentPadding, + end = EdgeToEdgeContentPadding, + bottom = 8.dp + ), + reverseLayout: Boolean = false, + verticalArrangement: Arrangement.Vertical = + Arrangement.spacedBy(8.dp, if (!reverseLayout) Alignment.Top else Alignment.Bottom), + horizontalAlignment: Alignment.Horizontal = Alignment.Start, + flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(), + content: LazyListScope.() -> Unit +) { + LazyColumn( + modifier = modifier, + state = state, + contentPadding = contentPadding, + reverseLayout = reverseLayout, + verticalArrangement = verticalArrangement, + horizontalAlignment = horizontalAlignment, + flingBehavior = flingBehavior, + content = content + ) +} + +inline fun LazyListScope.managerCategory( + noinline categoryName: @Composable () -> String, + content: LazyListScope.() -> Unit, +) { + item { + ManagerText( + modifier = Modifier + .padding( + start = 8.dp, + top = 4.dp + ), + text = categoryName(), + textStyle = MaterialTheme.typography.headlineSmall, + ) + } + content() +} diff --git a/app/src/main/java/com/vanced/manager/ui/component/ManagerLazyRow.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerLazyRow.kt new file mode 100644 index 0000000000..4d48a6c94f --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerLazyRow.kt @@ -0,0 +1,42 @@ +package com.vanced.manager.ui.component + +import androidx.compose.foundation.gestures.FlingBehavior +import androidx.compose.foundation.gestures.ScrollableDefaults +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.lazy.LazyListScope +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.vanced.manager.ui.util.EdgeToEdgeContentPadding + +@Composable +fun ManagerLazyRow( + modifier: Modifier = Modifier, + state: LazyListState = rememberLazyListState(), + contentPadding: PaddingValues = PaddingValues( + start = EdgeToEdgeContentPadding, + end = EdgeToEdgeContentPadding, + ), + reverseLayout: Boolean = false, + horizontalArrangement: Arrangement.Horizontal = + Arrangement.spacedBy(8.dp, if (!reverseLayout) Alignment.Start else Alignment.End), + verticalAlignment: Alignment.Vertical = Alignment.Top, + flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(), + content: LazyListScope.() -> Unit +) { + LazyRow( + modifier = modifier, + state = state, + contentPadding = contentPadding, + reverseLayout = reverseLayout, + horizontalArrangement = horizontalArrangement, + verticalAlignment = verticalAlignment, + flingBehavior = flingBehavior, + content = content + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/list/ManagerListItem.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerListItem.kt similarity index 55% rename from app/src/main/java/com/vanced/manager/ui/component/list/ManagerListItem.kt rename to app/src/main/java/com/vanced/manager/ui/component/ManagerListItem.kt index bcfe26ec92..e4d68452e6 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/list/ManagerListItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerListItem.kt @@ -1,13 +1,17 @@ -package com.vanced.manager.ui.component.list +package com.vanced.manager.ui.component import androidx.compose.foundation.layout.* import androidx.compose.material.ContentAlpha import androidx.compose.material.LocalContentAlpha +import androidx.compose.material3.LocalTextStyle +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal +import com.vanced.manager.ui.util.DefaultContentPaddingVertical @Composable fun ManagerListItem( @@ -17,7 +21,10 @@ fun ManagerListItem( icon: @Composable (() -> Unit)? = null, trailing: @Composable (() -> Unit)? = null ) { - Row(modifier = modifier) { + Row( + modifier = modifier, + horizontalArrangement = Arrangement.spacedBy(DefaultContentPaddingHorizontal) + ) { if (icon != null) { Box( modifier = Modifier.align(Alignment.CenterVertically) @@ -29,25 +36,28 @@ fun ManagerListItem( modifier = Modifier .weight(1f) .padding( - start = if (icon != null) 12.dp else 0.dp, - top = if (description != null) 6.dp else 12.dp, - bottom = if (description != null) 6.dp else 12.dp, - end = if (trailing != null) 12.dp else 0.dp, + vertical = + if (description != null) DefaultContentPaddingVertical - 4.dp else DefaultContentPaddingVertical, ) .align(Alignment.CenterVertically) ) { - title() + CompositionLocalProvider( + LocalTextStyle provides MaterialTheme.typography.titleSmall + ) { + title() + } if (description != null) { - CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) { + CompositionLocalProvider( + LocalContentAlpha provides ContentAlpha.medium, + LocalTextStyle provides MaterialTheme.typography.bodySmall + ) { description() } } } if (trailing != null) { Box( - modifier = Modifier - .size(48.dp) - .align(Alignment.CenterVertically), + modifier = Modifier.align(Alignment.CenterVertically), contentAlignment = Alignment.Center, ) { trailing() diff --git a/app/src/main/java/com/vanced/manager/ui/navigation/ManagerNavigator.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerNavigator.kt similarity index 61% rename from app/src/main/java/com/vanced/manager/ui/navigation/ManagerNavigator.kt rename to app/src/main/java/com/vanced/manager/ui/component/ManagerNavigator.kt index d9f88cc813..af5466b166 100644 --- a/app/src/main/java/com/vanced/manager/ui/navigation/ManagerNavigator.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerNavigator.kt @@ -2,17 +2,54 @@ package com.vanced.manager.ui.navigation import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedContentScope -import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.animation.with import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveableStateHolder +import androidx.compose.runtime.snapshots.SnapshotStateList import com.vanced.manager.ui.util.Screen -@OptIn(ExperimentalAnimationApi::class) +@Composable +fun <T> rememberManagerNavigationController( + initialScreen: T +) = remember { + ManagerNavigationControllerImpl(initialScreen) +} + +interface ManagerNavigationController<T> { + + val screens: SnapshotStateList<T> + + fun push(item: T) + + fun pop(): Boolean + +} + +class ManagerNavigationControllerImpl<T>( + initialScreen: T +) : ManagerNavigationController<T> { + + override val screens: SnapshotStateList<T> = + mutableStateListOf(initialScreen) + + override fun push(item: T) { + screens.add(item) + } + + override fun pop(): Boolean { + if (screens.size > 1) { + screens.removeLast() + return true + } + return false + } +} + @Composable fun <T : Screen> ManagerNavigator( - navigationController: NavigationController<T>, + navigationController: ManagerNavigationController<T>, content: @Composable (targetContent: T) -> Unit ) { val saveableStateHolder = rememberSaveableStateHolder() diff --git a/app/src/main/java/com/vanced/manager/ui/component/ManagerPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerPreference.kt new file mode 100644 index 0000000000..a7028659df --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerPreference.kt @@ -0,0 +1,263 @@ +package com.vanced.manager.ui.component + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.Checkbox +import androidx.compose.material.Switch +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.RadioButton +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.unit.dp +import com.vanced.manager.R +import com.vanced.manager.core.preferences.RadioButtonPreference +import com.vanced.manager.ui.resource.managerString +import com.vanced.manager.ui.theme.LargeShape +import com.vanced.manager.ui.theme.SmallShape +import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal + +@Composable +fun ManagerPreference( + preferenceTitle: String, + preferenceDescription: String? = null, + trailing: @Composable () -> Unit = {}, + onClick: () -> Unit +) { + ManagerElevatedCard( + shape = LargeShape, + onClick = onClick + ) { + ManagerListItem( + modifier = Modifier + .padding(horizontal = DefaultContentPaddingHorizontal), + title = { + ManagerText(text = preferenceTitle) + }, + description = if (preferenceDescription != null) { + { + ManagerText(text = preferenceDescription) + } + } else null, + trailing = trailing, + ) + } +} + +@Composable +fun ManagerSwitchPreference( + preferenceTitle: String, + preferenceDescription: String? = null, + isChecked: Boolean, + onCheckedChange: (isChecked: Boolean) -> Unit +) { + ManagerPreference( + preferenceTitle = preferenceTitle, + preferenceDescription = preferenceDescription, + onClick = { + onCheckedChange(!isChecked) + }, + trailing = { + Switch( + checked = isChecked, + onCheckedChange = null + ) + } + ) +} + +@Composable +fun ManagerDialogPreference( + preferenceTitle: String, + preferenceDescription: String? = null, + trailing: @Composable () -> Unit = {}, + onPreferenceClick: () -> Unit, + isDialogVisible: Boolean, + onDismissRequest: () -> Unit, + confirmButton: @Composable () -> Unit, + dismissButton: @Composable () -> Unit = {}, + content: @Composable () -> Unit +) { + ManagerPreference( + preferenceTitle = preferenceTitle, + preferenceDescription = preferenceDescription, + trailing = trailing, + onClick = onPreferenceClick + ) + if (isDialogVisible) { + ManagerDialog( + title = preferenceTitle, + onDismissRequest = onDismissRequest, + confirmButton = confirmButton, + dismissButton = dismissButton, + content = content + ) + } +} + +@Composable +fun ManagerSingleSelectDialogPreference( + preferenceTitle: String, + preferenceDescription: String, + isDialogVisible: Boolean, + currentSelectedKey: String, + buttons: List<RadioButtonPreference>, + trailing: @Composable () -> Unit = {}, + onPreferenceClick: () -> Unit, + onDismissRequest: () -> Unit, + onItemClick: (itemKey: String) -> Unit, + onSave: () -> Unit, +) { + ManagerDialogPreference( + preferenceTitle = preferenceTitle, + preferenceDescription = preferenceDescription, + trailing = trailing, + confirmButton = { + TextButton(onClick = onSave) { + ManagerText(managerString(R.string.dialog_button_save)) + } + }, + dismissButton = { + TextButton(onClick = onDismissRequest) { + ManagerText(managerString(R.string.dialog_button_cancel)) + } + }, + onDismissRequest = onDismissRequest, + isDialogVisible = isDialogVisible, + onPreferenceClick = onPreferenceClick + ) { + LazyColumn( + modifier = Modifier.heightIn(max = 400.dp) + ) { + items(buttons) { button -> + val (title, key) = button + ListDialogRadiobuttonItem( + modifier = Modifier.fillMaxWidth(), + text = title, + selected = currentSelectedKey == key, + onClick = { + onItemClick(key) + } + ) + } + } + } +} + +@Composable +fun ManagerMultiSelectDialogPreference( + preferenceTitle: String, + preferenceDescription: String, + isDialogVisible: Boolean, + currentSelectedKeys: List<String>, + buttons: List<RadioButtonPreference>, + trailing: @Composable () -> Unit = {}, + onPreferenceClick: () -> Unit, + onDismissRequest: () -> Unit, + onItemCheckChange: (isChecked: Boolean, itemKey: String) -> Unit, + onSave: () -> Unit, +) { + ManagerDialogPreference( + preferenceTitle = preferenceTitle, + preferenceDescription = preferenceDescription, + trailing = trailing, + confirmButton = { + androidx.compose.material.TextButton(onClick = onSave) { + ManagerText(managerString(R.string.dialog_button_save)) + } + }, + dismissButton = { + androidx.compose.material.TextButton(onClick = onDismissRequest) { + ManagerText(managerString(R.string.dialog_button_cancel)) + } + }, + onDismissRequest = onDismissRequest, + isDialogVisible = isDialogVisible, + onPreferenceClick = onPreferenceClick + ) { + LazyColumn( + modifier = Modifier.heightIn(max = 400.dp) + ) { + items(buttons) { button -> + val (title, key) = button + ListDialogCheckboxItem( + text = title, + checked = currentSelectedKeys.contains(key), + onCheckedChange = { isChecked -> + onItemCheckChange(isChecked, key) + } + ) + } + } + } +} + +@Composable +private fun ListDialogRadiobuttonItem( + text: String, + selected: Boolean, + onClick: () -> Unit, + modifier: Modifier = Modifier +) { + ListDialogItem( + modifier = modifier, + text = text, + onClick = onClick, + trailing = { + RadioButton( + selected = selected, + onClick = null + ) + } + ) +} + +@Composable +private fun ListDialogCheckboxItem( + text: String, + checked: Boolean, + onCheckedChange: (Boolean) -> Unit, + modifier: Modifier = Modifier +) { + ListDialogItem( + modifier = modifier, + text = text, + onClick = { + onCheckedChange(!checked) + }, + trailing = { + Checkbox( + checked = checked, + onCheckedChange = null + ) + } + ) +} + +@Composable +private fun ListDialogItem( + text: String, + onClick: () -> Unit, + trailing: @Composable () -> Unit, + modifier: Modifier = Modifier +) { + Row( + modifier = modifier + .clip(SmallShape) + .clickable(onClick = onClick) + .padding(8.dp), + horizontalArrangement = Arrangement.spacedBy(8.dp), + verticalAlignment = Alignment.CenterVertically + ) { + ManagerText( + modifier = Modifier.weight(1f), + text = text, + textStyle = MaterialTheme.typography.titleSmall + ) + trailing() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/ManagerProgressIndicator.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerProgressIndicator.kt new file mode 100644 index 0000000000..5ac2f88401 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerProgressIndicator.kt @@ -0,0 +1,43 @@ +package com.vanced.manager.ui.component + +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.material.ProgressIndicatorDefaults +import androidx.compose.material3.LinearProgressIndicator +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import com.vanced.manager.ui.util.animated + +@Composable +fun ManagerProgressIndicator( + modifier: Modifier = Modifier, + color: Color = MaterialTheme.colorScheme.primary, + trackColor: Color = MaterialTheme.colorScheme.surfaceVariant, +) { + LinearProgressIndicator( + modifier = modifier, + color = color.animated, + trackColor = trackColor.animated + ) +} + +@Composable +fun ManagerProgressIndicator( + progress: Float, + modifier: Modifier = Modifier, + color: Color = MaterialTheme.colorScheme.primary, + trackColor: Color = MaterialTheme.colorScheme.surfaceVariant, +) { + val animatedProgress by animateFloatAsState( + targetValue = progress, + animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec + ) + LinearProgressIndicator( + progress = animatedProgress, + modifier = modifier, + color = color.animated, + trackColor = trackColor.animated + ) +} diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScaffold.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerScaffold.kt similarity index 56% rename from app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScaffold.kt rename to app/src/main/java/com/vanced/manager/ui/component/ManagerScaffold.kt index b54594e4ba..364d5e82b2 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScaffold.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerScaffold.kt @@ -1,17 +1,25 @@ -package com.vanced.manager.ui.component.layout +package com.vanced.manager.ui.component import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.material3.* +import androidx.compose.material3.FabPosition +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.contentColorFor import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import com.vanced.manager.ui.util.animated -@ExperimentalMaterial3Api @Composable fun ManagerScaffold( modifier: Modifier = Modifier, topBar: @Composable () -> Unit = {}, + bottomBar: @Composable () -> Unit = {}, + snackbarHost: @Composable () -> Unit = {}, floatingActionButton: @Composable () -> Unit = {}, floatingActionButtonPosition: FabPosition = FabPosition.End, + containerColor: Color = MaterialTheme.colorScheme.background, + contentColor: Color = contentColorFor(containerColor), content: @Composable (PaddingValues) -> Unit ) { // //M3 Scaffold doesn't support tonal elevation for Surface @@ -22,8 +30,12 @@ fun ManagerScaffold( Scaffold( modifier = modifier, topBar = topBar, + bottomBar = bottomBar, + snackbarHost = snackbarHost, floatingActionButton = floatingActionButton, floatingActionButtonPosition = floatingActionButtonPosition, + containerColor = containerColor.animated, + contentColor = contentColor.animated, content = content ) // } diff --git a/app/src/main/java/com/vanced/manager/ui/component/list/ManagerSelectableListItem.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerSelectableListItem.kt similarity index 95% rename from app/src/main/java/com/vanced/manager/ui/component/list/ManagerSelectableListItem.kt rename to app/src/main/java/com/vanced/manager/ui/component/ManagerSelectableListItem.kt index f7b6f6fb50..99c31e2fe1 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/list/ManagerSelectableListItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerSelectableListItem.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.component.list +package com.vanced.manager.ui.component import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSwipeRefresh.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerSwipeRefresh.kt similarity index 52% rename from app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSwipeRefresh.kt rename to app/src/main/java/com/vanced/manager/ui/component/ManagerSwipeRefresh.kt index a03508c1f8..c66668d31c 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSwipeRefresh.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerSwipeRefresh.kt @@ -1,22 +1,31 @@ -package com.vanced.manager.ui.component.layout +package com.vanced.manager.ui.component +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp import com.google.accompanist.swiperefresh.SwipeRefresh import com.google.accompanist.swiperefresh.SwipeRefreshIndicator import com.google.accompanist.swiperefresh.SwipeRefreshState @Composable fun ManagerSwipeRefresh( - refreshState: SwipeRefreshState, + swipeRefreshState: SwipeRefreshState, onRefresh: () -> Unit, modifier: Modifier = Modifier, - content: @Composable () -> Unit + swipeEnabled: Boolean = true, + refreshTriggerDistance: Dp = 80.dp, + indicatorAlignment: Alignment = Alignment.TopCenter, + indicatorPadding: PaddingValues = PaddingValues(0.dp), + clipIndicatorToPadding: Boolean = true, + content: @Composable () -> Unit, ) { SwipeRefresh( modifier = modifier, - state = refreshState, + state = swipeRefreshState, onRefresh = onRefresh, indicator = { state, trigger -> SwipeRefreshIndicator( @@ -27,6 +36,11 @@ fun ManagerSwipeRefresh( backgroundColor = MaterialTheme.colorScheme.surface ) }, + swipeEnabled = swipeEnabled, + refreshTriggerDistance = refreshTriggerDistance, + indicatorAlignment = indicatorAlignment, + indicatorPadding = indicatorPadding, + clipIndicatorToPadding = clipIndicatorToPadding, content = content ) } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/text/ManagerText.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerText.kt similarity index 95% rename from app/src/main/java/com/vanced/manager/ui/component/text/ManagerText.kt rename to app/src/main/java/com/vanced/manager/ui/component/ManagerText.kt index b0ad8fe93c..bb326ef6a0 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/text/ManagerText.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerText.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.component.text +package com.vanced.manager.ui.component import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.Text diff --git a/app/src/main/java/com/vanced/manager/ui/component/ManagerTopAppBar.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerTopAppBar.kt new file mode 100644 index 0000000000..d702b86d4e --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerTopAppBar.kt @@ -0,0 +1,44 @@ +package com.vanced.manager.ui.component + +import androidx.compose.foundation.layout.RowScope +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier + +@Composable +fun ManagerSmallTopAppBar( + title: @Composable () -> Unit, + modifier: Modifier = Modifier, + navigationIcon: @Composable () -> Unit = {}, + actions: @Composable RowScope.() -> Unit = {}, + colors: TopAppBarColors = TopAppBarDefaults.smallTopAppBarColors(), + scrollBehavior: TopAppBarScrollBehavior? = null +) { + SmallTopAppBar( + modifier = modifier, + title = title, + actions = actions, + navigationIcon = navigationIcon, + colors = colors, + scrollBehavior = scrollBehavior + ) +} + +@Composable +fun ManagerCenterAlignedTopAppBar( + title: @Composable () -> Unit, + modifier: Modifier = Modifier, + navigationIcon: @Composable () -> Unit = {}, + actions: @Composable RowScope.() -> Unit = {}, + colors: TopAppBarColors = TopAppBarDefaults.smallTopAppBarColors(), + scrollBehavior: TopAppBarScrollBehavior? = null +) { + CenterAlignedTopAppBar( + modifier = modifier, + title = title, + actions = actions, + navigationIcon = navigationIcon, + colors = colors, + scrollBehavior = scrollBehavior + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/animation/JumpAnimation.kt b/app/src/main/java/com/vanced/manager/ui/component/animation/JumpAnimation.kt deleted file mode 100644 index 4bf21c2453..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/animation/JumpAnimation.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.vanced.manager.ui.component.animation - -import android.annotation.SuppressLint -import androidx.compose.animation.core.Transition -import androidx.compose.animation.core.animateDp -import androidx.compose.animation.core.keyframes -import androidx.compose.runtime.Composable -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp - -@SuppressLint("UnusedTransitionTargetStateParameter") -@Composable -fun <T> Transition<T>.jumpAnimation( - initialValue: Dp, - label: String -) = animateDp( - transitionSpec = { - keyframes { - durationMillis = 250 - initialValue - 8.dp at 50 - initialValue + 8.dp at 150 - initialValue at 250 - } - }, - label = label -) { initialValue } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/button/ManagerIconButton.kt b/app/src/main/java/com/vanced/manager/ui/component/button/ManagerIconButton.kt deleted file mode 100644 index 1ade716254..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/button/ManagerIconButton.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.vanced.manager.ui.component.button - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.size -import androidx.compose.material.ripple.rememberRipple -import androidx.compose.material3.Icon -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.vector.ImageVector -import androidx.compose.ui.semantics.Role -import androidx.compose.ui.unit.dp - -@Composable -fun ManagerIconButton( - icon: ImageVector, - contentDescription: String, - onClick: () -> Unit -) { - val interactionSource = remember { MutableInteractionSource() } - val buttonSize = 36.dp - Box( - modifier = Modifier - .clickable( - onClick = onClick, - role = Role.Button, - interactionSource = interactionSource, - indication = rememberRipple(radius = buttonSize / 2) - ) - .size(buttonSize), - contentAlignment = Alignment.Center - ) { - Icon( - imageVector = icon, - contentDescription = contentDescription - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedButton.kt b/app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedButton.kt deleted file mode 100644 index cd47f06628..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedButton.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.vanced.manager.ui.component.button - -import androidx.compose.foundation.layout.RowScope -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.luminance -import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.component.color.managerAccentColor -import com.vanced.manager.ui.theme.MediumShape - -@Composable -fun ManagerThemedButton( - modifier: Modifier = Modifier, - backgroundColor: Color = managerAccentColor(), - onClick: () -> Unit, - content: @Composable RowScope.() -> Unit -) { - Button( - modifier = modifier.fillMaxWidth(), - onClick = onClick, - shape = MediumShape, - colors = ButtonDefaults.buttonColors( - containerColor = backgroundColor, - contentColor = - if (backgroundColor.luminance() > 0.7) - Color.Black - else - Color.White - ), - elevation = ButtonDefaults.elevatedButtonElevation(0.dp, 0.dp, 0.dp, 0.dp) - ) { - content() - } -} diff --git a/app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedTextButton.kt b/app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedTextButton.kt deleted file mode 100644 index ad46c351ef..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/button/ManagerThemedTextButton.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.vanced.manager.ui.component.button - -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import com.vanced.manager.ui.component.color.managerAccentColor -import com.vanced.manager.ui.component.text.ManagerText - -@Composable -fun ManagerThemedTextButton( - modifier: Modifier = Modifier, - backgroundColor: Color = managerAccentColor(), - text: String, - onClick: () -> Unit -) { - ManagerThemedButton( - modifier = modifier, - backgroundColor = backgroundColor, - onClick = onClick - ) { - ManagerText(text = text) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerCard.kt b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerCard.kt deleted file mode 100644 index dd7dab42ee..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerCard.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.vanced.manager.ui.component.card - -import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.theme.MediumShape - -@Composable -fun ManagerCard( - modifier: Modifier = Modifier, - shape: Shape = MediumShape, - backgroundColor: Color = MaterialTheme.colorScheme.surface, - tonalElevation: Dp = 0.dp, - shadowElevation: Dp = 0.dp, - content: @Composable () -> Unit, -) { - Surface( - modifier = modifier, - shape = shape, - color = backgroundColor, - shadowElevation = shadowElevation, - tonalElevation = tonalElevation, - content = content - ) -} - -@OptIn(ExperimentalMaterialApi::class) -@Composable -fun ManagerCard( - modifier: Modifier = Modifier, - shape: Shape = MediumShape, - backgroundColor: Color = MaterialTheme.colorScheme.surface, - tonalElevation: Dp = 0.dp, - shadowElevation: Dp = 0.dp, - onClick: () -> Unit, - content: @Composable () -> Unit, -) { - Surface( - modifier = modifier, - shape = shape, - color = backgroundColor, - shadowElevation = shadowElevation, - tonalElevation = tonalElevation, - onClick = onClick, - content = content - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerItemCard.kt b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerItemCard.kt deleted file mode 100644 index 70537848ea..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerItemCard.kt +++ /dev/null @@ -1,75 +0,0 @@ -package com.vanced.manager.ui.component.card - -import androidx.annotation.DrawableRes -import androidx.compose.foundation.layout.* -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.unit.dp -import com.github.zsoltk.compose.backpress.LocalBackPressHandler -import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal -import com.vanced.manager.ui.util.DefaultContentPaddingVertical - -private val cardModifier = Modifier.sizeIn( - minHeight = 100.dp, - minWidth = 100.dp -) - -@Composable -fun ManagerItemCard( - title: String, - @DrawableRes icon: Int? = null -) { - LocalBackPressHandler.current.handle() - ManagerCard( - modifier = cardModifier, - ) { - ManagerItemCardContent(title, icon) - } -} - -@Composable -fun ManagerItemCard( - title: String, - @DrawableRes icon: Int? = null, - onClick: () -> Unit -) { - ManagerTonalCard( - modifier = cardModifier, - onClick = onClick - ) { - ManagerItemCardContent(title, icon) - } -} - -@Composable -private fun ManagerItemCardContent( - title: String, - @DrawableRes icon: Int? = null, -) { - Column( - modifier = Modifier.padding( - horizontal = DefaultContentPaddingHorizontal, - vertical = DefaultContentPaddingVertical - ), - horizontalAlignment = Alignment.Start, - verticalArrangement = Arrangement.SpaceBetween - ) { - if (icon != null) { - Icon( - modifier = Modifier - .size(32.dp), - painter = painterResource(id = icon), - contentDescription = title, - ) - } - ManagerText( - text = title, - textStyle = MaterialTheme.typography.labelLarge - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerLinkCard.kt b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerLinkCard.kt deleted file mode 100644 index 66e7d8bcd9..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerLinkCard.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.vanced.manager.ui.component.card - -import android.content.Intent -import android.net.Uri -import androidx.annotation.DrawableRes -import androidx.browser.customtabs.CustomTabsIntent -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.platform.LocalContext -import com.vanced.manager.core.preferences.holder.useCustomTabsPref - -@Composable -fun ManagerLinkCard( - title: String, - @DrawableRes icon: Int, - link: String -) { - val context = LocalContext.current - val customTabs = remember { CustomTabsIntent.Builder().build() } - val uri = remember { Uri.parse(link) } - val intent = remember { Intent(Intent.ACTION_VIEW, uri) } - ManagerItemCard( - title = title, - icon = icon - ) { - if (useCustomTabsPref) { - customTabs.launchUrl(context, uri) - } else { - context.startActivity(intent) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerThemedCard.kt b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerThemedCard.kt deleted file mode 100644 index a1d9457ee8..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerThemedCard.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.vanced.manager.ui.component.card - -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Shape -import com.vanced.manager.ui.theme.MediumShape - -@Composable -fun ManagerContainerCard( - modifier: Modifier = Modifier, - shape: Shape = MediumShape, - content: @Composable () -> Unit, -) { - ManagerCard( - modifier = modifier, - shape = shape, - backgroundColor = MaterialTheme.colorScheme.primaryContainer, - content = content - ) -} - -@Composable -fun ManagerContainerCard( - modifier: Modifier = Modifier, - shape: Shape = MediumShape, - onClick: () -> Unit, - content: @Composable () -> Unit, -) { - ManagerCard( - modifier = modifier, - shape = shape, - backgroundColor = MaterialTheme.colorScheme.primaryContainer, - onClick = onClick, - content = content, - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerTonalCard.kt b/app/src/main/java/com/vanced/manager/ui/component/card/ManagerTonalCard.kt deleted file mode 100644 index 7ee452862b..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/card/ManagerTonalCard.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.vanced.manager.ui.component.card - -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.theme.MediumShape - -@Composable -fun ManagerTonalCard( - modifier: Modifier = Modifier, - shape: Shape = MediumShape, - content: @Composable () -> Unit, -) { - ManagerCard( - modifier = modifier, - shape = shape, - tonalElevation = 4.dp, - content = content - ) -} - -@Composable -fun ManagerTonalCard( - modifier: Modifier = Modifier, - shape: Shape = MediumShape, - onClick: () -> Unit, - content: @Composable () -> Unit, -) { - ManagerCard( - modifier = modifier, - shape = shape, - tonalElevation = 4.dp, - onClick = onClick, - content = content - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt b/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt deleted file mode 100644 index 0f077a530f..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/checkbox/ManagerCheckbox.kt +++ /dev/null @@ -1,60 +0,0 @@ -package com.vanced.manager.ui.component.checkbox - -import android.annotation.SuppressLint -import androidx.compose.foundation.layout.BoxWithConstraints -import androidx.compose.foundation.layout.requiredSizeIn -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.Close -import androidx.compose.material.icons.rounded.Done -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.contentColorFor -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Shape -import com.vanced.manager.ui.component.card.ManagerCard -import com.vanced.manager.ui.component.color.managerAnimatedColor -import com.vanced.manager.ui.theme.MediumShape - -@SuppressLint("UnusedTransitionTargetStateParameter") -@Composable -fun ManagerCheckbox( - modifier: Modifier, - isChecked: Boolean, - shape: Shape = MediumShape, - onCheckedChange: (isChecked: Boolean) -> Unit -) { - val cardColor = - managerAnimatedColor(if (isChecked) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.primaryContainer) - val iconTint = - managerAnimatedColor( - if (isChecked) - contentColorFor(MaterialTheme.colorScheme.primary) - else - contentColorFor(MaterialTheme.colorScheme.primaryContainer) - ) - - ManagerCard( - modifier = modifier, - shape = shape, - onClick = { onCheckedChange(!isChecked) }, - backgroundColor = cardColor - ) { - BoxWithConstraints { - Icon( - modifier = Modifier - .requiredSizeIn( - minWidth = minWidth / 1.6f, - minHeight = minHeight / 1.6f, - maxWidth = maxWidth / 1.6f, - maxHeight = maxHeight / 1.6f, - ) - .align(Alignment.Center), - imageVector = if (isChecked) Icons.Rounded.Done else Icons.Rounded.Close, - tint = iconTint, - contentDescription = null - ) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/color/ColorContentProvider.kt b/app/src/main/java/com/vanced/manager/ui/component/color/ColorContentProvider.kt deleted file mode 100644 index 6989d00033..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/color/ColorContentProvider.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.vanced.manager.ui.component.color - -import androidx.compose.material3.LocalContentColor -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider - -@Composable -fun ThemedItemContentColorProvider( - content: @Composable () -> Unit -) { - CompositionLocalProvider( - LocalContentColor provides contentColorForColor(managerAccentColor()), - content = content - ) -} - -@Composable -fun ThemedCardContentColorProvider( - content: @Composable () -> Unit -) { - CompositionLocalProvider( - LocalContentColor provides contentColorForColor(managerAccentColor()), - content = content - ) -} - -@Composable -fun ThemedContentColorProvider( - content: @Composable () -> Unit -) { - CompositionLocalProvider( - LocalContentColor provides managerAccentColor(), - content = content - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/color/ColorPicker.kt b/app/src/main/java/com/vanced/manager/ui/component/color/ColorPicker.kt deleted file mode 100644 index be52927483..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/color/ColorPicker.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.vanced.manager.ui.component.color - -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.skydoves.colorpickerview.ColorEnvelope -import com.skydoves.orchestra.colorpicker.ColorPicker - -@Composable -fun ManagerColorPicker( - onColorSelected: (color: Long) -> Unit -) { - val (selectedColor, setColor) = remember { mutableStateOf(ColorEnvelope(0)) } - ColorPicker( - modifier = Modifier - .fillMaxWidth() - .height(300.dp), - onColorListener = { envelope, _ -> setColor(envelope) }, - children = {}, - initialColor = managerAccentColor() - ) - onColorSelected(selectedColor.color.toLong()) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt b/app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt deleted file mode 100644 index c03074f252..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/color/ManagerColors.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.vanced.manager.ui.component.color - -import androidx.compose.animation.animateColorAsState -import androidx.compose.animation.core.tween -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.luminance -import com.vanced.manager.core.preferences.holder.managerAccentColorPref - -@Composable -fun contentColorForColor(color: Color) = - if (color.luminance() > 0.7) - Color.Black - else - Color.White - -@Composable -fun managerAccentColor(): Color { - return Color(managerAccentColorPref) -} - -@Composable -fun managerThemedCardColor() = managerAccentColor().copy(alpha = 0.27f) - -@Composable -fun managerTextColor(): Color = managerAnimatedColor(color = MaterialTheme.colorScheme.onSurface) - -@Composable -fun managerSurfaceColor(): Color = managerAnimatedColor(color = MaterialTheme.colorScheme.surface) - -@Composable -fun managerAnimatedColor( - color: Color -): Color = animateColorAsState( - targetValue = color, - animationSpec = tween(500) -).value \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerButtonColumn.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerButtonColumn.kt deleted file mode 100644 index 48e1f840b1..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerButtonColumn.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.vanced.manager.ui.component.layout - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.vanced.manager.ui.util.DefaultContentPaddingVertical - -@Composable -fun ManagerButtonColumn( - modifier: Modifier = Modifier, - content: @Composable ColumnScope.() -> Unit -) { - Column( - modifier = modifier, - verticalArrangement = Arrangement.spacedBy(DefaultContentPaddingVertical), - content = content - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt deleted file mode 100644 index 26f49e968b..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerLazyColumn.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.vanced.manager.ui.component.layout - -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyListScope -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier - -@Composable -fun ManagerLazyColumn( - modifier: Modifier = Modifier, - contentPadding: PaddingValues = PaddingValues(), - content: LazyListScope.() -> Unit -) { - LazyColumn( - modifier = modifier, - contentPadding = contentPadding, - content = content - ) -} diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrim.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrim.kt deleted file mode 100644 index 256b62387f..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrim.kt +++ /dev/null @@ -1,50 +0,0 @@ -package com.vanced.manager.ui.component.layout - -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.animation.core.tween -import androidx.compose.foundation.Canvas -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.runtime.SideEffect -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import com.google.accompanist.systemuicontroller.rememberSystemUiController -import com.vanced.manager.ui.theme.isDark - -@Composable -fun ManagerScrim( - show: Boolean -) { - val systemUiController = rememberSystemUiController() - - val scrimColor = Color.Black.copy(alpha = 0.5f) - val surfaceColor = MaterialTheme.colorScheme.surface - - val isDark = isDark() - - val scrimAlpha by animateFloatAsState( - targetValue = if (show) 1f else 0f, - animationSpec = tween() - ) - - SideEffect { - //TODO fix colors in navigation bars - if (show) { - systemUiController.setSystemBarsColor(scrimColor, false) - } else { - systemUiController.setSystemBarsColor(surfaceColor, !isDark) - } - } - - Canvas( - Modifier - .fillMaxSize() - ) { - drawRect( - color = scrimColor, - alpha = scrimAlpha - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrollableColumn.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrollableColumn.kt deleted file mode 100644 index be7f89c028..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerScrollableColumn.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.vanced.manager.ui.component.layout - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.util.DefaultContentPaddingVertical - -@Composable -fun ManagerScrollableColumn( - modifier: Modifier = Modifier, - contentPaddingVertical: Dp = DefaultContentPaddingVertical, - itemSpacing: Dp = 0.dp, - content: @Composable ColumnScope.() -> Unit -) { - val scrollState = rememberScrollState() - Column( - modifier = modifier - .verticalScroll(scrollState) - .padding(vertical = contentPaddingVertical), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(itemSpacing), - content = content - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSurface.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSurface.kt deleted file mode 100644 index f0bae0b15a..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ManagerSurface.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.vanced.manager.ui.component.layout - -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.vanced.manager.ui.component.color.managerSurfaceColor - -@Composable -fun ManagerSurface( - content: @Composable () -> Unit -) { - Surface( - modifier = Modifier.fillMaxSize(), - color = managerSurfaceColor(), - content = content - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/layout/ScrollableItemRow.kt b/app/src/main/java/com/vanced/manager/ui/component/layout/ScrollableItemRow.kt deleted file mode 100644 index e76cde7aab..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/layout/ScrollableItemRow.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.vanced.manager.ui.component.layout - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.lazy.LazyRow -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp - -@Composable -fun <T> ScrollableItemRow( - items: List<T>, - modifier: Modifier = Modifier, - content: @Composable (T) -> Unit -) { - val state = rememberLazyListState() - LazyRow( - modifier = modifier, - horizontalArrangement = Arrangement.spacedBy(8.dp), - state = state - ) { - item { - Spacer(Modifier.width(8.dp)) - } - items(items) { item -> - content(item) - } - item { - Spacer(Modifier.width(8.dp)) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenuItem.kt b/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenuItem.kt deleted file mode 100644 index c76126dbd0..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/menu/ManagerDropdownMenuItem.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.vanced.manager.ui.component.menu - -import androidx.compose.material.DropdownMenuItem -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.theme.SmallShape - -@Composable -fun ManagerDropdownMenuItem( - title: String, - onClick: () -> Unit -) { - DropdownMenuItem( - onClick = onClick, - modifier = Modifier.clip(SmallShape), - ) { - ManagerText( - text = title, - textStyle = MaterialTheme.typography.labelLarge - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/modifier/ManagerClickable.kt b/app/src/main/java/com/vanced/manager/ui/component/modifier/ManagerClickable.kt deleted file mode 100644 index acb26b1f97..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/modifier/ManagerClickable.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.vanced.manager.ui.component.modifier - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.material.ripple.rememberRipple -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier -import androidx.compose.ui.composed -import androidx.compose.ui.draw.clip -import com.vanced.manager.ui.theme.MediumShape - -fun Modifier.managerClickable( - onClick: () -> Unit -) = composed { - val ripple = rememberRipple() - val interactionSource = remember { MutableInteractionSource() } - - then(clip(MediumShape)).then( - clickable( - interactionSource = interactionSource, - onClick = onClick, - indication = ripple - ) - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/modifier/ManagerPlaceholder.kt b/app/src/main/java/com/vanced/manager/ui/component/modifier/ManagerPlaceholder.kt deleted file mode 100644 index 6e45eb7422..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/modifier/ManagerPlaceholder.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.vanced.manager.ui.component.modifier - -import androidx.compose.ui.Modifier -import androidx.compose.ui.composed -import com.google.accompanist.placeholder.PlaceholderHighlight -import com.google.accompanist.placeholder.material.placeholder -import com.google.accompanist.placeholder.material.shimmer - -fun Modifier.managerPlaceholder( - visible: Boolean -) = composed { - then( - placeholder( - visible = visible, - highlight = PlaceholderHighlight.shimmer() - ) - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/modifier/ModifierBuilder.kt b/app/src/main/java/com/vanced/manager/ui/component/modifier/ModifierBuilder.kt deleted file mode 100644 index 6892891f2f..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/modifier/ModifierBuilder.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.vanced.manager.ui.component.modifier - -import androidx.compose.ui.Modifier - -fun modifierBuilder( - block: Modifier.() -> Unit -) = Modifier.block() \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt deleted file mode 100644 index 7ed9213ffe..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/CheckboxPreference.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.vanced.manager.ui.component.preference - -import androidx.compose.runtime.Composable -import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.widget.checkbox.ManagerAnimatedCheckbox - -@Composable -fun CheckboxPreference( - preferenceTitle: String, - preferenceDescription: String? = null, - isChecked: Boolean, - onCheckedChange: (isChecked: Boolean) -> Unit = {} -) { - val onClick: () -> Unit = { - onCheckedChange(!isChecked) - } - - Preference( - preferenceTitle = preferenceTitle, - preferenceDescription = preferenceDescription, - onClick = onClick, - trailing = { - ManagerAnimatedCheckbox( - isChecked = isChecked, - onCheckedChange = { onClick() }, - size = 40.dp - ) - } - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/DialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/DialogPreference.kt deleted file mode 100644 index 4e3b63ddb0..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/DialogPreference.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.vanced.manager.ui.component.preference - -import androidx.compose.runtime.Composable -import com.vanced.manager.ui.component.dialog.ManagerDialog - -@Composable -fun DialogPreference( - preferenceTitle: String, - preferenceDescription: String? = null, - trailing: @Composable () -> Unit = {}, - onPreferenceClick: () -> Unit, - isDialogVisible: Boolean, - onDismissRequest: () -> Unit, - confirmButton: @Composable () -> Unit, - dismissButton: @Composable () -> Unit = {}, - content: @Composable () -> Unit -) { - Preference( - preferenceTitle = preferenceTitle, - preferenceDescription = preferenceDescription, - trailing = trailing, - onClick = onPreferenceClick - ) - if (isDialogVisible) { - ManagerDialog( - title = preferenceTitle, - onDismissRequest = onDismissRequest, - confirmButton = confirmButton, - dismissButton = dismissButton, - content = content - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/MultiSelectDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/MultiSelectDialogPreference.kt deleted file mode 100644 index f4532451a2..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/MultiSelectDialogPreference.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.vanced.manager.ui.component.preference - -import androidx.compose.foundation.layout.heightIn -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material.TextButton -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.vanced.manager.R -import com.vanced.manager.core.preferences.RadioButtonPreference -import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.resources.managerString -import com.vanced.manager.ui.widget.list.CheckboxItem - -@Composable -fun MultiSelectDialogPreference( - preferenceTitle: String, - preferenceDescription: String, - isDialogVisible: Boolean, - currentSelectedKeys: List<String>, - buttons: List<RadioButtonPreference>, - trailing: @Composable () -> Unit = {}, - onPreferenceClick: () -> Unit, - onDismissRequest: () -> Unit, - onItemCheckChange: (isChecked: Boolean, itemKey: String) -> Unit, - onSave: () -> Unit, -) { - DialogPreference( - preferenceTitle = preferenceTitle, - preferenceDescription = preferenceDescription, - trailing = trailing, - confirmButton = { - TextButton(onClick = onSave) { - ManagerText(managerString(R.string.dialog_button_save)) - } - }, - dismissButton = { - TextButton(onClick = onDismissRequest) { - ManagerText(managerString(R.string.dialog_button_cancel)) - } - }, - onDismissRequest = onDismissRequest, - isDialogVisible = isDialogVisible, - onPreferenceClick = onPreferenceClick - ) { - LazyColumn( - modifier = Modifier.heightIn(max = 400.dp) - ) { - items(buttons) { button -> - val (title, key) = button - CheckboxItem( - text = title, - checked = currentSelectedKeys.contains(key), - onCheckedChange = { isChecked -> - onItemCheckChange(isChecked, key) - } - ) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt deleted file mode 100644 index e4de9b96c2..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/Preference.kt +++ /dev/null @@ -1,57 +0,0 @@ -package com.vanced.manager.ui.component.preference - -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.LocalContentColor -import androidx.compose.material3.LocalTextStyle -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.component.card.ManagerTonalCard -import com.vanced.manager.ui.component.color.managerAnimatedColor -import com.vanced.manager.ui.component.list.ManagerListItem -import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.theme.LargeShape -import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal - -@Composable -fun Preference( - preferenceTitle: String, - preferenceDescription: String? = null, - trailing: @Composable () -> Unit = {}, - onClick: () -> Unit -) { - val color = managerAnimatedColor(color = MaterialTheme.colorScheme.onSurface) - ManagerTonalCard( - shape = LargeShape, - onClick = onClick - ) { - ManagerListItem( - modifier = Modifier - .padding( - horizontal = DefaultContentPaddingHorizontal, - vertical = 8.dp - ), - title = { - CompositionLocalProvider( - LocalContentColor provides color, - LocalTextStyle provides MaterialTheme.typography.titleSmall - ) { - ManagerText(text = preferenceTitle) - } - }, - description = if (preferenceDescription != null) { - { - CompositionLocalProvider( - LocalContentColor provides color, - LocalTextStyle provides MaterialTheme.typography.bodySmall - ) { - ManagerText(text = preferenceDescription) - } - } - } else null, - trailing = trailing, - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/preference/SingleSelectDialogPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/preference/SingleSelectDialogPreference.kt deleted file mode 100644 index 6454962b0f..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/preference/SingleSelectDialogPreference.kt +++ /dev/null @@ -1,62 +0,0 @@ -package com.vanced.manager.ui.component.preference - -import androidx.compose.foundation.layout.heightIn -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material3.TextButton -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.vanced.manager.R -import com.vanced.manager.core.preferences.RadioButtonPreference -import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.resources.managerString -import com.vanced.manager.ui.widget.list.RadiobuttonItem - -@Composable -fun SingleSelectDialogPreference( - preferenceTitle: String, - preferenceDescription: String, - isDialogVisible: Boolean, - currentSelectedKey: String, - buttons: List<RadioButtonPreference>, - trailing: @Composable () -> Unit = {}, - onPreferenceClick: () -> Unit, - onDismissRequest: () -> Unit, - onItemClick: (itemKey: String) -> Unit, - onSave: () -> Unit, -) { - DialogPreference( - preferenceTitle = preferenceTitle, - preferenceDescription = preferenceDescription, - trailing = trailing, - confirmButton = { - TextButton(onClick = onSave) { - ManagerText(managerString(R.string.dialog_button_save)) - } - }, - dismissButton = { - TextButton(onClick = onDismissRequest) { - ManagerText(managerString(R.string.dialog_button_cancel)) - } - }, - onDismissRequest = onDismissRequest, - isDialogVisible = isDialogVisible, - onPreferenceClick = onPreferenceClick - ) { - LazyColumn( - modifier = Modifier.heightIn(max = 400.dp) - ) { - items(buttons) { button -> - val (title, key) = button - RadiobuttonItem( - text = title, - selected = currentSelectedKey == key, - onClick = { - onItemClick(key) - } - ) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/progressindicator/ManagerProgressIndicator.kt b/app/src/main/java/com/vanced/manager/ui/component/progressindicator/ManagerProgressIndicator.kt deleted file mode 100644 index 8375548432..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/progressindicator/ManagerProgressIndicator.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.vanced.manager.ui.component.progressindicator - -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.material.LinearProgressIndicator -import androidx.compose.material.ProgressIndicatorDefaults -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.composed -import androidx.compose.ui.draw.clip -import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.component.color.managerAccentColor -import com.vanced.manager.ui.theme.MediumShape - -private val progressBarModifier = Modifier.composed { - then(height(5.dp)) - .then(fillMaxWidth()) - .then(clip(MediumShape)) -} - -@Composable -fun ManagerProgressIndicator() { - LinearProgressIndicator( - modifier = progressBarModifier, - color = managerAccentColor() - ) -} - -@Composable -fun ManagerProgressIndicator( - progress: Float -) { - val animatedProgress by animateFloatAsState( - targetValue = progress, - animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec - ) - LinearProgressIndicator( - modifier = progressBarModifier, - color = managerAccentColor(), - progress = animatedProgress - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/radiobutton/ManagerRadiobutton.kt b/app/src/main/java/com/vanced/manager/ui/component/radiobutton/ManagerRadiobutton.kt deleted file mode 100644 index 3c99948cd3..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/radiobutton/ManagerRadiobutton.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.vanced.manager.ui.component.radiobutton - -import android.annotation.SuppressLint -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Shape -import com.vanced.manager.ui.component.card.ManagerCard -import com.vanced.manager.ui.component.color.managerAnimatedColor -import com.vanced.manager.ui.theme.MediumShape - -@SuppressLint("UnusedTransitionTargetStateParameter") -@Composable -fun ManagerRadiobutton( - modifier: Modifier, - isSelected: Boolean, - shape: Shape = MediumShape, - onClick: () -> Unit -) { - val cardColor = - managerAnimatedColor(if (isSelected) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.primaryContainer) - ManagerCard( - modifier = modifier, - onClick = onClick, - shape = shape, - backgroundColor = cardColor, - content = {} - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/text/AppVersionText.kt b/app/src/main/java/com/vanced/manager/ui/component/text/AppVersionText.kt deleted file mode 100644 index 3a6b4644da..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/text/AppVersionText.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.vanced.manager.ui.component.text - -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier - -@Composable -fun AppVersionText( - text: String, - modifier: Modifier = Modifier, -) { - ManagerText( - modifier = modifier, - text = text, - textStyle = MaterialTheme.typography.bodySmall, - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/text/CategoryTitleText.kt b/app/src/main/java/com/vanced/manager/ui/component/text/CategoryTitleText.kt deleted file mode 100644 index 25832fdbd5..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/text/CategoryTitleText.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.vanced.manager.ui.component.text - -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.vanced.manager.ui.component.color.managerAnimatedColor -import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal - -@Composable -fun CategoryTitleText( - text: String -) { - ManagerText( - modifier = Modifier.padding(start = DefaultContentPaddingHorizontal), - text = text, - textStyle = MaterialTheme.typography.headlineSmall, - color = managerAnimatedColor(MaterialTheme.colorScheme.onSurface) - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/text/ToolbarTitleText.kt b/app/src/main/java/com/vanced/manager/ui/component/text/ToolbarTitleText.kt deleted file mode 100644 index 89fbe78095..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/text/ToolbarTitleText.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.vanced.manager.ui.component.text - -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import com.vanced.manager.ui.component.color.managerAnimatedColor - -@Composable -fun ToolbarTitleText( - text: String -) { - ManagerText( - text = text, - textStyle = MaterialTheme.typography.headlineMedium, - color = managerAnimatedColor(MaterialTheme.colorScheme.onSurface) - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/topappbar/ManagerTopAppBar.kt b/app/src/main/java/com/vanced/manager/ui/component/topappbar/ManagerTopAppBar.kt deleted file mode 100644 index 7fd2edb038..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/topappbar/ManagerTopAppBar.kt +++ /dev/null @@ -1,30 +0,0 @@ -package com.vanced.manager.ui.component.topappbar - -import androidx.compose.foundation.layout.RowScope -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.SmallTopAppBar -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.vanced.manager.ui.component.color.managerAnimatedColor -import com.vanced.manager.ui.component.text.ManagerText - -@Composable -fun ManagerTopAppBar( - title: String, - modifier: Modifier = Modifier, - actions: @Composable RowScope.() -> Unit = {}, - navigationIcon: @Composable () -> Unit = {}, -) { - SmallTopAppBar( - modifier = modifier, - title = { - ManagerText( - text = title, - textStyle = MaterialTheme.typography.headlineMedium, - color = managerAnimatedColor(MaterialTheme.colorScheme.onSurface) - ) - }, - actions = actions, - navigationIcon = navigationIcon, - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/navigation/NavigationController.kt b/app/src/main/java/com/vanced/manager/ui/navigation/NavigationController.kt deleted file mode 100644 index 5694ab745e..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/navigation/NavigationController.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.vanced.manager.ui.navigation - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateListOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.snapshots.SnapshotStateList - -@Composable -fun <T> rememberNavigationController( - initialScreen: T -) = remember { - NavigationControllerImpl(initialScreen) -} - -interface NavigationController<T> { - - val screens: SnapshotStateList<T> - - fun push(item: T) - - fun pop(): Boolean - -} - -class NavigationControllerImpl<T>( - initialScreen: T -) : NavigationController<T> { - - override val screens: SnapshotStateList<T> = - mutableStateListOf(initialScreen) - - override fun push(item: T) { - screens.add(item) - } - - override fun pop(): Boolean { - if (screens.size > 1) { - screens.removeLast() - return true - } - return false - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/resources/ManagerString.kt b/app/src/main/java/com/vanced/manager/ui/resource/ManagerString.kt similarity index 91% rename from app/src/main/java/com/vanced/manager/ui/resources/ManagerString.kt rename to app/src/main/java/com/vanced/manager/ui/resource/ManagerString.kt index 04a35744d3..91201b1640 100644 --- a/app/src/main/java/com/vanced/manager/ui/resources/ManagerString.kt +++ b/app/src/main/java/com/vanced/manager/ui/resource/ManagerString.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.resources +package com.vanced.manager.ui.resource import androidx.annotation.StringRes import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt b/app/src/main/java/com/vanced/manager/ui/screen/AboutScreen.kt similarity index 63% rename from app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt rename to app/src/main/java/com/vanced/manager/ui/screen/AboutScreen.kt index 6031a55cb3..0ffa09fa98 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/AboutLayout.kt +++ b/app/src/main/java/com/vanced/manager/ui/screen/AboutScreen.kt @@ -1,8 +1,9 @@ -package com.vanced.manager.ui.screens +package com.vanced.manager.ui.screen import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.ArrowBackIosNew import androidx.compose.material3.ExperimentalMaterial3Api @@ -13,25 +14,19 @@ import androidx.compose.runtime.Composable 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.text.SpanStyle import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.unit.dp import com.vanced.manager.BuildConfig import com.vanced.manager.R -import com.vanced.manager.ui.component.card.ManagerLinkCard -import com.vanced.manager.ui.component.card.ManagerTonalCard -import com.vanced.manager.ui.component.layout.ManagerLazyColumn -import com.vanced.manager.ui.component.layout.ManagerScaffold -import com.vanced.manager.ui.component.layout.ScrollableItemRow -import com.vanced.manager.ui.component.list.ManagerListItem -import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.component.topappbar.ManagerTopAppBar -import com.vanced.manager.ui.resources.managerString +import com.vanced.manager.ui.component.* +import com.vanced.manager.ui.resource.managerString import com.vanced.manager.ui.theme.LargeShape import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal import com.vanced.manager.ui.util.DefaultContentPaddingVertical import com.vanced.manager.ui.util.Screen -import com.vanced.manager.ui.widget.layout.managerCategory +import com.vanced.manager.ui.widget.LinkCard data class Person( val name: String, @@ -109,17 +104,15 @@ private val sources = listOf( @ExperimentalMaterial3Api @Composable -fun AboutLayout( +fun AboutScreen( onToolbarBackButtonClick: () -> Unit ) { - val aboutCategoryVancedTeam = managerString(R.string.about_category_credits_vanced_team) - val aboutCategoryOtherContributors = managerString(R.string.about_category_credits_other) - val aboutCategorySources = managerString(R.string.about_category_sources) - ManagerScaffold( topBar = { - ManagerTopAppBar( - title = managerString(Screen.About.displayName), + ManagerSmallTopAppBar( + title = { + ManagerText(managerString(Screen.About.displayName)) + }, navigationIcon = { IconButton(onClick = onToolbarBackButtonClick) { Icon( @@ -137,12 +130,17 @@ fun AboutLayout( .padding(paddingValues), ) { item { - ManagerTonalCard( + ManagerElevatedCard( modifier = Modifier.fillMaxWidth(), shape = LargeShape ) { Column( - modifier = Modifier.padding(vertical = DefaultContentPaddingVertical), + modifier = Modifier + .fillMaxWidth() + .padding( + vertical = DefaultContentPaddingVertical, + horizontal = DefaultContentPaddingHorizontal + ), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(4.dp) ) { @@ -168,62 +166,73 @@ fun AboutLayout( } } } - managerCategory( - categoryName = aboutCategoryVancedTeam, - items = vancedTeam - ) { person -> - CreditPersonItem( - modifier = Modifier.fillMaxWidth(), - personName = person.name, - personContribution = person.contribution - ) - } - managerCategory( - categoryName = aboutCategoryOtherContributors, - items = otherContributors - ) { person -> - CreditPersonItem( - modifier = Modifier.fillMaxWidth(), - personName = person.name, - personContribution = person.contribution - ) + managerCategory(categoryName = { + managerString(R.string.about_category_credits_vanced_team) + }) { + items(vancedTeam) { person -> + CreditCard( + modifier = Modifier.fillMaxWidth(), + personName = person.name, + personContribution = person.contribution + ) + } } - managerCategory(aboutCategorySources) { - ScrollableItemRow( - modifier = Modifier - .fillMaxWidth(), - items = sources - ) { source -> - ManagerLinkCard( - title = managerString(source.nameId), - icon = source.iconId, - link = source.link + managerCategory(categoryName = { + managerString(R.string.about_category_credits_other) + }) { + items(otherContributors) { person -> + CreditCard( + modifier = Modifier.fillMaxWidth(), + personName = person.name, + personContribution = person.contribution ) } } + managerCategory(categoryName = { + managerString(R.string.about_category_sources) + }) { + item { + ManagerLazyRow(modifier = Modifier.fillMaxWidth()) { + items(sources) { source -> + LinkCard( + text = managerString(source.nameId), + icon = painterResource(source.iconId), + url = source.link + ) + } + } + } + } } } } @Composable -private fun CreditPersonItem( +private fun CreditCard( personName: String, personContribution: String, modifier: Modifier = Modifier, ) { - ManagerListItem( - modifier = modifier.padding(horizontal = DefaultContentPaddingHorizontal), - title = { - ManagerText( - text = personName, - textStyle = MaterialTheme.typography.titleSmall - ) - }, - description = { - ManagerText( - text = personContribution, - textStyle = MaterialTheme.typography.bodySmall - ) - } - ) + ManagerElevatedCard( + modifier = modifier, + shape = LargeShape + ) { + ManagerListItem( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = DefaultContentPaddingHorizontal), + title = { + ManagerText( + text = personName, + textStyle = MaterialTheme.typography.titleSmall + ) + }, + description = { + ManagerText( + text = personContribution, + textStyle = MaterialTheme.typography.bodySmall + ) + } + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/screens/ConfigurationScreen.kt b/app/src/main/java/com/vanced/manager/ui/screen/ConfigurationScreen.kt similarity index 63% rename from app/src/main/java/com/vanced/manager/ui/screens/ConfigurationScreen.kt rename to app/src/main/java/com/vanced/manager/ui/screen/ConfigurationScreen.kt index 78490a6c9c..df3802fb90 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/ConfigurationScreen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screen/ConfigurationScreen.kt @@ -1,38 +1,28 @@ -package com.vanced.manager.ui.screens +package com.vanced.manager.ui.screen import androidx.compose.animation.* import androidx.compose.animation.core.tween -import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.ListItem +import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.ArrowBackIosNew import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp import com.vanced.manager.R import com.vanced.manager.domain.model.InstallationOption -import com.vanced.manager.ui.component.card.ManagerTonalCard -import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.component.topappbar.ManagerTopAppBar -import com.vanced.manager.ui.resources.managerString +import com.vanced.manager.ui.component.* +import com.vanced.manager.ui.resource.managerString import com.vanced.manager.ui.theme.LargeShape import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal import com.vanced.manager.ui.util.DefaultContentPaddingVertical import com.vanced.manager.ui.viewmodel.ConfigurationViewModel -import com.vanced.manager.ui.widget.layout.managerCategory import org.koin.androidx.compose.getViewModel private const val enterDuration = 300 private const val exitDuration = 250 -@ExperimentalFoundationApi -@ExperimentalAnimationApi -@OptIn(ExperimentalMaterial3Api::class) @Composable fun ConfigurationScreen( installationOptions: List<InstallationOption>, @@ -42,8 +32,10 @@ fun ConfigurationScreen( val viewModel: ConfigurationViewModel = getViewModel() Scaffold( topBar = { - ManagerTopAppBar( - title = managerString(R.string.toolbar_installation_preferences), + ManagerSmallTopAppBar( + title = { + ManagerText(managerString(R.string.toolbar_installation_preferences)) + }, navigationIcon = { IconButton( onClick = { @@ -60,7 +52,7 @@ fun ConfigurationScreen( ) }, bottomBar = { - ConfigurationButtons( + ConfigurationBottomBar( modifier = Modifier .padding( horizontal = DefaultContentPaddingHorizontal, @@ -91,7 +83,6 @@ fun ConfigurationScreen( } } -@OptIn(ExperimentalAnimationApi::class, ExperimentalMaterial3Api::class) @Composable private fun ConfigurationBody( currentIndex: Int, @@ -112,55 +103,52 @@ private fun ConfigurationBody( } ) { optionIndex -> val installationOption = installationOptions[optionIndex] - val categoryName = managerString(installationOption.titleId) - LazyColumn { - when (installationOption) { - is InstallationOption.SingleSelect -> { - managerCategory( - categoryName = categoryName, - items = installationOption.items - ) { item -> - val preference = installationOption.getOption() - ConfigurationItem( - modifier = Modifier - .fillMaxWidth(), - text = item.displayText(item.key), - onClick = { - installationOption.setOption(item.key) - }, - trailing = { - RadioButton( - selected = preference == item.key, - onClick = null - ) - } - ) + ManagerLazyColumn { + managerCategory(categoryName = { + managerString(installationOption.titleId) + }) { + when (installationOption) { + is InstallationOption.SingleSelect -> { + items(installationOption.items) { item -> + val preference = installationOption.getOption() + ConfigurationItem( + modifier = Modifier + .fillMaxWidth(), + text = item.displayText(item.key), + onClick = { + installationOption.setOption(item.key) + }, + trailing = { + RadioButton( + selected = preference == item.key, + onClick = null + ) + } + ) + } } - } - is InstallationOption.MultiSelect -> { - managerCategory( - categoryName = categoryName, - items = installationOption.items - ) { item -> - val preference = installationOption.getOption() - ConfigurationItem( - modifier = Modifier - .fillMaxWidth(), - text = item.displayText(item.key), - onClick = { - if (preference.contains(item.key)) { - installationOption.removeOption(item.key) - } else { - installationOption.addOption(item.key) + is InstallationOption.MultiSelect -> { + items(installationOption.items) { item -> + val preference = installationOption.getOption() + ConfigurationItem( + modifier = Modifier + .fillMaxWidth(), + text = item.displayText(item.key), + onClick = { + if (preference.contains(item.key)) { + installationOption.removeOption(item.key) + } else { + installationOption.addOption(item.key) + } + }, + trailing = { + Checkbox( + checked = preference.contains(item.key), + onCheckedChange = null + ) } - }, - trailing = { - Checkbox( - checked = preference.contains(item.key), - onCheckedChange = null - ) - } - ) + ) + } } } } @@ -168,9 +156,8 @@ private fun ConfigurationBody( } } -@OptIn(ExperimentalAnimationApi::class) @Composable -private fun ConfigurationButtons( +private fun ConfigurationBottomBar( currentIndex: Int, lastIndex: Int, onBackClick: () -> Unit, @@ -224,7 +211,6 @@ private fun ConfigurationButtons( } } -@OptIn(ExperimentalMaterialApi::class) @Composable private fun ConfigurationItem( text: String, @@ -232,18 +218,16 @@ private fun ConfigurationItem( trailing: @Composable () -> Unit, modifier: Modifier = Modifier, ) { - ManagerTonalCard( - modifier = modifier - .padding( - start = 6.dp, - end = 6.dp, - bottom = 8.dp - ), + ManagerElevatedCard( + modifier = modifier, shape = LargeShape, onClick = onClick ) { - ListItem( - text = { + ManagerListItem( + modifier = Modifier.padding( + horizontal = DefaultContentPaddingHorizontal + ), + title = { ManagerText( text = text, textStyle = MaterialTheme.typography.titleSmall diff --git a/app/src/main/java/com/vanced/manager/ui/screen/HomeScreen.kt b/app/src/main/java/com/vanced/manager/ui/screen/HomeScreen.kt new file mode 100644 index 0000000000..e3959bb9ea --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/screen/HomeScreen.kt @@ -0,0 +1,284 @@ +package com.vanced.manager.ui.screen + +import androidx.compose.animation.* +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyListScope +import androidx.compose.foundation.lazy.items +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.MoreVert +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.TextButton +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.unit.dp +import coil.compose.rememberImagePainter +import coil.request.CachePolicy +import com.google.accompanist.swiperefresh.rememberSwipeRefreshState +import com.vanced.manager.R +import com.vanced.manager.core.util.socialMedia +import com.vanced.manager.core.util.sponsors +import com.vanced.manager.domain.model.App +import com.vanced.manager.domain.model.InstallationOption +import com.vanced.manager.ui.component.* +import com.vanced.manager.ui.resource.managerString +import com.vanced.manager.ui.util.Screen +import com.vanced.manager.ui.viewmodel.MainViewModel +import com.vanced.manager.ui.widget.AppCard +import com.vanced.manager.ui.widget.AppCardPlaceholder +import com.vanced.manager.ui.widget.LinkCard + +@Composable +fun HomeScreen( + viewModel: MainViewModel, + onToolbarScreenSelected: (Screen) -> Unit, + onAppDownloadClick: ( + appName: String, + appVersions: List<String>?, + installationOptions: List<InstallationOption>? + ) -> Unit, + onAppUninstallClick: (appPackage: String) -> Unit, + onAppLaunchClick: (appName: String, appPackage: String) -> Unit, +) { + val refreshState = + rememberSwipeRefreshState(isRefreshing = viewModel.appState.isFetching) + var menuExpanded by remember { mutableStateOf(false) } + val dropdownScreens = remember { listOf(Screen.Settings, Screen.About) } + + ManagerScaffold( + topBar = { + HomeScreenTopBar( + modifier = Modifier, + menuExpanded = menuExpanded, + dropdownScreens = dropdownScreens, + onActionClick = { + menuExpanded = true + }, + onDropdownItemClick = onToolbarScreenSelected, + onDropdownDismissRequest = { + menuExpanded = false + }) + } + ) { paddingValues -> + ManagerSwipeRefresh( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues), + swipeRefreshState = refreshState, + onRefresh = { viewModel.fetch() } + ) { + AnimatedContent( + modifier = Modifier.fillMaxSize(), + targetState = viewModel.appState, + transitionSpec = { + scaleIn(initialScale = 0.9f) + fadeIn() with + scaleOut(targetScale = 0.9f) + fadeOut() + } + ) { animatedAppState -> + when (animatedAppState) { + is StateFetching -> { + HomeScreenLoading( + modifier = Modifier.fillMaxSize(), + appsCount = animatedAppState.placeholderAppsCount + ) + } + is StateSuccess -> { + HomeScreenLoaded( + modifier = Modifier.fillMaxSize(), + apps = animatedAppState.apps, + onAppDownloadClick = onAppDownloadClick, + onAppUninstallClick = onAppUninstallClick, + onAppLaunchClick = onAppLaunchClick + ) + } + is StateError -> { + //TODO + } + } + } + } + } +} + +typealias StateFetching = MainViewModel.AppState.Fetching +typealias StateSuccess = MainViewModel.AppState.Success +typealias StateError = MainViewModel.AppState.Error + +@Composable +private fun HomeScreenTopBar( + menuExpanded: Boolean, + dropdownScreens: List<Screen>, + onActionClick: () -> Unit, + onDropdownItemClick: (Screen) -> Unit, + onDropdownDismissRequest: () -> Unit, + modifier: Modifier = Modifier +) { + ManagerCenterAlignedTopAppBar( + modifier = modifier, + title = { + ManagerText(managerString(Screen.Home.displayName)) + }, + actions = { + IconButton(onClick = onActionClick) { + Icon( + Icons.Rounded.MoreVert, + contentDescription = "Navigation" + ) + } + + ManagerDropdownMenu( + expanded = menuExpanded, + onDismissRequest = onDropdownDismissRequest + ) { + for (dropdownScreen in dropdownScreens) { + ManagerDropdownMenuItem( + title = managerString(dropdownScreen.displayName), + onClick = { + onDropdownItemClick(dropdownScreen) + } + ) + } + } + } + ) +} + +@Composable +private fun HomeScreenLoaded( + modifier: Modifier = Modifier, + apps: List<App>, + onAppDownloadClick: ( + appName: String, + appVersions: List<String>?, + installationOptions: List<InstallationOption>? + ) -> Unit, + onAppUninstallClick: (appPackage: String) -> Unit, + onAppLaunchClick: (appName: String, appPackage: String) -> Unit, +) { + HomeScreenBody(modifier = modifier) { + managerCategory(categoryName = { + managerString(R.string.home_category_apps) + }) { + items(apps) { app -> + val appIcon = rememberImagePainter(app.iconUrl) { + diskCachePolicy(CachePolicy.ENABLED) + } + + var showAppInfoDialog by remember { mutableStateOf(false) } + + AppCard( + modifier = Modifier + .fillMaxWidth(), + appName = app.name, + appIcon = appIcon, + appInstalledVersion = app.installedVersion, + appRemoteVersion = app.remoteVersion, + onAppDownloadClick = { + onAppDownloadClick( + app.name, + app.versions, + app.installationOptions + ) + }, + onAppUninstallClick = { + onAppUninstallClick( + app.packageName + ) + }, + onAppLaunchClick = { + onAppLaunchClick( + app.name, + app.packageName, + ) + }, + onAppInfoClick = { + showAppInfoDialog = true + } + ) + + if (showAppInfoDialog) { + ManagerDialog( + title = managerString( + R.string.app_info_title, + app.name + ), + onDismissRequest = { showAppInfoDialog = false }, + confirmButton = { + TextButton(onClick = { + showAppInfoDialog = false + }) { + ManagerText(text = managerString(R.string.dialog_button_close)) + } + }, + ) { + ManagerText( + modifier = Modifier.padding(top = 4.dp), + text = app.changelog, + ) + } + } + } + } + } +} + +@Composable +private fun HomeScreenLoading( + modifier: Modifier = Modifier, + appsCount: Int, +) { + HomeScreenBody(modifier = modifier) { + managerCategory(categoryName = { + managerString(R.string.home_category_apps) + }) { + items(appsCount) { + AppCardPlaceholder( + modifier = Modifier.fillMaxWidth() + ) + } + } + } +} + +@Composable +private inline fun HomeScreenBody( + modifier: Modifier = Modifier, + crossinline appsCategory: LazyListScope.() -> Unit, +) { + ManagerLazyColumn(modifier = modifier) { + appsCategory() + managerCategory(categoryName = { + managerString(R.string.home_category_support_us) + }) { + item { + ManagerLazyRow(modifier = Modifier.fillMaxWidth()) { + items(sponsors) { sponsor -> + LinkCard( + text = sponsor.title, + icon = painterResource(sponsor.icon), + url = sponsor.link + ) + } + } + } + } + managerCategory(categoryName = { + managerString(R.string.home_category_social_media) + }) { + item { + ManagerLazyRow(modifier = Modifier.fillMaxWidth()) { + items(socialMedia) { socialMedia -> + LinkCard( + text = socialMedia.title, + icon = painterResource(socialMedia.icon), + url = socialMedia.link + ) + } + } + } + } + } +} diff --git a/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt b/app/src/main/java/com/vanced/manager/ui/screen/InstallScreen.kt similarity index 88% rename from app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt rename to app/src/main/java/com/vanced/manager/ui/screen/InstallScreen.kt index a2c7785c9c..653a4cbf34 100644 --- a/app/src/main/java/com/vanced/manager/ui/screens/InstallScreen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screen/InstallScreen.kt @@ -1,14 +1,13 @@ -package com.vanced.manager.ui.screens +package com.vanced.manager.ui.screen import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.ArrowDropDown import androidx.compose.material.icons.rounded.Done -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExtendedFloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme @@ -24,20 +23,11 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.sp import com.vanced.manager.R -import com.vanced.manager.ui.component.layout.ManagerLazyColumn -import com.vanced.manager.ui.component.layout.ManagerScaffold -import com.vanced.manager.ui.component.modifier.managerClickable -import com.vanced.manager.ui.component.progressindicator.ManagerProgressIndicator -import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.component.topappbar.ManagerTopAppBar -import com.vanced.manager.ui.resources.managerString +import com.vanced.manager.ui.component.* +import com.vanced.manager.ui.resource.managerString import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal import com.vanced.manager.ui.viewmodel.InstallViewModel -@OptIn( - ExperimentalFoundationApi::class, - ExperimentalMaterial3Api::class -) @Composable fun InstallScreen( appName: String, @@ -62,8 +52,10 @@ fun InstallScreen( ManagerScaffold( topBar = { Column { - ManagerTopAppBar( - title = managerString(R.string.toolbar_install), + ManagerSmallTopAppBar( + title = { + ManagerText(managerString(R.string.toolbar_install)) + }, ) when (status) { is InstallViewModel.Status.Progress -> { @@ -127,7 +119,7 @@ fun InstallScreen( Column( modifier = Modifier .fillMaxWidth() - .managerClickable { + .clickable { visible = !visible } .padding(horizontal = DefaultContentPaddingHorizontal), diff --git a/app/src/main/java/com/vanced/manager/ui/screen/SettingsScreen.kt b/app/src/main/java/com/vanced/manager/ui/screen/SettingsScreen.kt new file mode 100644 index 0000000000..8f1ae68c6d --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/screen/SettingsScreen.kt @@ -0,0 +1,73 @@ +package com.vanced.manager.ui.screen + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.items +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.ArrowBackIosNew +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.vanced.manager.R +import com.vanced.manager.core.util.notificationApps +import com.vanced.manager.ui.component.* +import com.vanced.manager.ui.resource.managerString +import com.vanced.manager.ui.util.Screen +import com.vanced.manager.ui.widget.SettingsCustomTabsItem +import com.vanced.manager.ui.widget.SettingsManagerVariantItem +import com.vanced.manager.ui.widget.SettingsNotificationsItem +import com.vanced.manager.ui.widget.ThemeSettingsItem + +@ExperimentalMaterial3Api +@Composable +fun SettingsScreen( + onToolbarBackButtonClick: () -> Unit, +) { + ManagerScaffold( + modifier = Modifier.fillMaxSize(), + topBar = { + ManagerSmallTopAppBar( + title = { + ManagerText(managerString(Screen.Settings.displayName)) + }, + navigationIcon = { + IconButton(onClick = onToolbarBackButtonClick) { + Icon( + imageVector = Icons.Rounded.ArrowBackIosNew, + contentDescription = "Back" + ) + } + } + ) + } + ) { paddingValues -> + ManagerLazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues), + ) { + managerCategory(categoryName = { + managerString(R.string.settings_category_behaviour) + }) { + item { + SettingsCustomTabsItem() + } + items(notificationApps) { notificationApp -> + SettingsNotificationsItem(notificationApp) + } + item { + SettingsManagerVariantItem() + } + } + managerCategory(categoryName = { + managerString(R.string.settings_category_appearance) + }) { + item { + ThemeSettingsItem() + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt deleted file mode 100644 index e30900f9e8..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/screens/HomeLayout.kt +++ /dev/null @@ -1,217 +0,0 @@ -package com.vanced.manager.ui.screens - -import androidx.compose.animation.* -import androidx.compose.foundation.layout.* -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.MoreVert -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.TextButton -import androidx.compose.runtime.* -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import coil.compose.rememberImagePainter -import coil.request.CachePolicy -import com.google.accompanist.swiperefresh.rememberSwipeRefreshState -import com.vanced.manager.R -import com.vanced.manager.core.util.socialMedia -import com.vanced.manager.core.util.sponsors -import com.vanced.manager.domain.model.InstallationOption -import com.vanced.manager.ui.component.card.ManagerLinkCard -import com.vanced.manager.ui.component.dialog.ManagerDialog -import com.vanced.manager.ui.component.layout.ManagerLazyColumn -import com.vanced.manager.ui.component.layout.ManagerScaffold -import com.vanced.manager.ui.component.layout.ManagerSwipeRefresh -import com.vanced.manager.ui.component.layout.ScrollableItemRow -import com.vanced.manager.ui.component.menu.ManagerDropdownMenu -import com.vanced.manager.ui.component.menu.ManagerDropdownMenuItem -import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.component.topappbar.ManagerTopAppBar -import com.vanced.manager.ui.resources.managerString -import com.vanced.manager.ui.util.Screen -import com.vanced.manager.ui.viewmodel.MainViewModel -import com.vanced.manager.ui.widget.app.AppCard -import com.vanced.manager.ui.widget.app.AppCardPlaceholder -import com.vanced.manager.ui.widget.layout.managerCategory - -@ExperimentalMaterial3Api -@ExperimentalAnimationApi -@Composable -fun HomeLayout( - viewModel: MainViewModel, - onToolbarScreenSelected: (Screen) -> Unit, - onAppInstallPress: ( - appName: String, - appVersions: List<String>?, - installationOptions: List<InstallationOption>? - ) -> Unit -) { - val appState = viewModel.appState - - val refreshState = - rememberSwipeRefreshState(isRefreshing = appState is MainViewModel.AppState.Fetching) - var isMenuExpanded by remember { mutableStateOf(false) } - val dropdownScreens = remember { listOf(Screen.Settings, Screen.About) } - - val homeCategoryApps = managerString(R.string.home_category_apps) - val homeCategorySupportUs = managerString(R.string.home_category_support_us) - val homeCategorySocialMedia = managerString(R.string.home_category_social_media) - - ManagerScaffold( - topBar = { - ManagerTopAppBar( - title = managerString(Screen.Home.displayName), - actions = { - IconButton(onClick = { isMenuExpanded = true }) { - Icon( - Icons.Rounded.MoreVert, - contentDescription = "Navigation" - ) - } - - ManagerDropdownMenu( - expanded = isMenuExpanded, - onDismissRequest = { - isMenuExpanded = false - } - ) { - for (dropdownScreen in dropdownScreens) { - ManagerDropdownMenuItem( - title = managerString(dropdownScreen.displayName), - onClick = { - onToolbarScreenSelected(dropdownScreen) - isMenuExpanded = false - } - ) - } - } - } - ) - } - ) { paddingValues -> - ManagerSwipeRefresh( - modifier = Modifier - .fillMaxSize() - .padding(paddingValues), - refreshState = refreshState, - onRefresh = { viewModel.fetch() } - ) { - ManagerLazyColumn { - managerCategory(homeCategoryApps) { - AnimatedContent( - targetState = appState, - transitionSpec = { - scaleIn(initialScale = 0.9f) + fadeIn() with - scaleOut(targetScale = 0.9f) + fadeOut() - } - ) { animatedAppState -> - Column( - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - when (animatedAppState) { - is MainViewModel.AppState.Success -> { - for (app in animatedAppState.apps) { - val appIcon = rememberImagePainter(app.iconUrl) { - diskCachePolicy(CachePolicy.ENABLED) - } - - var showAppInfoDialog by rememberSaveable { - mutableStateOf( - false - ) - } - - AppCard( - appName = app.name, - appIcon = appIcon, - appInstalledVersion = app.installedVersion, - appRemoteVersion = app.remoteVersion, - onAppDownloadClick = { - onAppInstallPress( - app.name, - app.versions, - app.installationOptions - ) - }, - onAppUninstallClick = { - viewModel.uninstallApp( - appPackage = app.packageName - ) - }, - onAppLaunchClick = { - viewModel.launchApp( - appName = app.name, - appPackage = app.packageName, - ) - }, - onAppInfoClick = { - showAppInfoDialog = true - } - ) - - if (showAppInfoDialog) { - ManagerDialog( - title = managerString( - R.string.app_info_title, - app.name - ), - onDismissRequest = { showAppInfoDialog = false }, - confirmButton = { - TextButton(onClick = { - showAppInfoDialog = false - }) { - ManagerText(text = managerString(R.string.dialog_button_close)) - } - }, - ) { - ManagerText( - modifier = Modifier.padding(top = 4.dp), - text = app.changelog, - //textStyle = MaterialTheme.typography.bodyMedium - ) - } - } - } - } - is MainViewModel.AppState.Fetching -> { - for (i in 0 until animatedAppState.placeholderAppsCount) { - AppCardPlaceholder() - } - } - is MainViewModel.AppState.Error -> { - - } - } - } - } - } - managerCategory(homeCategorySupportUs) { - ScrollableItemRow( - modifier = Modifier.fillMaxWidth(), - items = sponsors - ) { sponsor -> - ManagerLinkCard( - icon = sponsor.icon, - title = sponsor.title, - link = sponsor.link - ) - } - } - managerCategory(homeCategorySocialMedia) { - ScrollableItemRow( - modifier = Modifier.fillMaxWidth(), - items = socialMedia - ) { socialMedia -> - ManagerLinkCard( - icon = socialMedia.icon, - title = socialMedia.title, - link = socialMedia.link - ) - } - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt b/app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt deleted file mode 100644 index ec5050f818..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/screens/SettingsLayout.kt +++ /dev/null @@ -1,72 +0,0 @@ -package com.vanced.manager.ui.screens - -import androidx.compose.foundation.layout.* -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.ArrowBackIosNew -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.Scaffold -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.vanced.manager.R -import com.vanced.manager.ui.component.layout.ManagerLazyColumn -import com.vanced.manager.ui.component.topappbar.ManagerTopAppBar -import com.vanced.manager.ui.resources.managerString -import com.vanced.manager.ui.util.Screen -import com.vanced.manager.ui.widget.layout.managerCategory -import com.vanced.manager.ui.widget.settings.* - -@ExperimentalMaterial3Api -@Composable -fun SettingsLayout( - onToolbarBackButtonClick: () -> Unit, -) { - val settingsCategoryBehaviour = managerString(R.string.settings_category_behaviour) - val settingsCategoryApperance = managerString(R.string.settings_category_appearance) - - Scaffold( - modifier = Modifier.fillMaxSize(), - topBar = { - ManagerTopAppBar( - title = managerString(Screen.Settings.displayName), - navigationIcon = { - IconButton(onClick = onToolbarBackButtonClick) { - Icon( - imageVector = Icons.Rounded.ArrowBackIosNew, - contentDescription = "Back" - ) - } - } - ) - } - ) { paddingValues -> - ManagerLazyColumn( - modifier = Modifier - .fillMaxSize() - .padding(paddingValues), - ) { - managerCategory(settingsCategoryBehaviour) { - Column( - modifier = Modifier.fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - SettingsCustomTabsItem() - SettingsNotificationsItem() - SettingsManagerVariantItem() - } - - } - managerCategory(settingsCategoryApperance) { - Column( - modifier = Modifier.fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(8.dp) - ) { - SettingsAccentColorItem() - ThemeSettingsItem() - } - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt index 6981c57966..6ad82a89e2 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt @@ -1,13 +1,9 @@ package com.vanced.manager.ui.theme -import android.annotation.SuppressLint import android.os.Build -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.LocalIndication import androidx.compose.foundation.gestures.LocalOverScrollConfiguration import androidx.compose.foundation.gestures.OverScrollConfiguration import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.material.ripple.rememberRipple import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider @@ -79,38 +75,42 @@ fun isDark(): Boolean = when (managerThemePref) { else -> throw IllegalArgumentException("Unknown theme") } -@SuppressLint("NewApi") -@ExperimentalFoundationApi +@Composable +inline fun apiDependantColorScheme( + dynamic: () -> ColorScheme, + static: () -> ColorScheme +): ColorScheme { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + dynamic() + } else { + static() + } +} + @Composable fun ManagerTheme( content: @Composable () -> Unit ) { - val isAndroid12OrHigher = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S + val context = LocalContext.current val colorScheme = - if (isAndroid12OrHigher) { - val context = LocalContext.current - if (isDark()) { - dynamicDarkColorScheme(context) - } else { - dynamicLightColorScheme(context) - } + if (isDark()) { + apiDependantColorScheme( + dynamic = { dynamicDarkColorScheme(context) }, + static = { DarkThemeColors } + ) } else { - if (isDark()) { - DarkThemeColors - } else { - LightThemeColors - } + apiDependantColorScheme( + dynamic = { dynamicLightColorScheme(context)}, + static = { LightThemeColors } + ) } - MaterialTheme( colorScheme = colorScheme, typography = ManagerTypography, ) { - val rippleIndication = rememberRipple() CompositionLocalProvider( - LocalIndication provides rippleIndication, LocalOverScrollConfiguration provides OverScrollConfiguration( - forceShowAlways = isAndroid12OrHigher + forceShowAlways = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ) ) { content() diff --git a/app/src/main/java/com/vanced/manager/ui/util/Color.kt b/app/src/main/java/com/vanced/manager/ui/util/Color.kt new file mode 100644 index 0000000000..241453a5f7 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/util/Color.kt @@ -0,0 +1,10 @@ +package com.vanced.manager.ui.util + +import androidx.compose.animation.animateColorAsState +import androidx.compose.animation.core.tween +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color + +val Color.animated + @Composable + get() = animateColorAsState(this, animationSpec = tween(400)).value \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/util/Const.kt b/app/src/main/java/com/vanced/manager/ui/util/Const.kt index abd4c2d659..2b1432a73b 100644 --- a/app/src/main/java/com/vanced/manager/ui/util/Const.kt +++ b/app/src/main/java/com/vanced/manager/ui/util/Const.kt @@ -3,4 +3,6 @@ package com.vanced.manager.ui.util import androidx.compose.ui.unit.dp val DefaultContentPaddingHorizontal = 16.dp -val DefaultContentPaddingVertical = 12.dp \ No newline at end of file +val DefaultContentPaddingVertical = 12.dp + +val EdgeToEdgeContentPadding = 8.dp \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt index 1a7b7e6525..625a1db0f1 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt @@ -36,6 +36,10 @@ class MainViewModel( data class Fetching(val placeholderAppsCount: Int) : AppState() data class Success(val apps: List<App>) : AppState() data class Error(val error: String) : AppState() + + val isFetching get() = this is Fetching + val isSuccess get() = this is Success + val isError get() = this is Error } var appState by mutableStateOf<AppState>(AppState.Fetching(appCount)) diff --git a/app/src/main/java/com/vanced/manager/ui/widget/AppCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/AppCard.kt new file mode 100644 index 0000000000..93da10c2a2 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widget/AppCard.kt @@ -0,0 +1,257 @@ +package com.vanced.manager.ui.widget + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Info +import androidx.compose.material.icons.rounded.DeleteForever +import androidx.compose.material.icons.rounded.Download +import androidx.compose.material.icons.rounded.Launch +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.composed +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import coil.compose.ImagePainter +import com.google.accompanist.placeholder.PlaceholderHighlight +import com.google.accompanist.placeholder.placeholder +import com.google.accompanist.placeholder.shimmer +import com.vanced.manager.R +import com.vanced.manager.ui.component.ManagerElevatedCard +import com.vanced.manager.ui.component.ManagerListItem +import com.vanced.manager.ui.component.ManagerText +import com.vanced.manager.ui.theme.LargeShape +import com.vanced.manager.ui.theme.MediumShape +import com.vanced.manager.ui.theme.SmallShape +import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal +import com.vanced.manager.ui.util.DefaultContentPaddingVertical + +@Composable +fun AppCard( + appName: String, + appIcon: ImagePainter, + appInstalledVersion: String?, + appRemoteVersion: String?, + onAppDownloadClick: () -> Unit, + onAppUninstallClick: () -> Unit, + onAppLaunchClick: () -> Unit, + onAppInfoClick: () -> Unit, + modifier: Modifier = Modifier, +) { + BaseAppCard( + modifier = modifier, + appTitle = { + ManagerText( + modifier = Modifier.fillMaxSize(), + text = appName, + textStyle = MaterialTheme.typography.titleMedium + ) + }, + appIcon = { + Image( + modifier = Modifier.size(48.dp), + painter = appIcon, + contentDescription = "App Icon", + ) + }, + appTrailing = { + IconButton(onClick = onAppInfoClick) { + Icon( + imageVector = Icons.Outlined.Info, + contentDescription = "App Info" + ) + } + }, + appVersionsColumn = { + ManagerText( + text = stringResource( + id = R.string.app_version_latest, + appRemoteVersion ?: stringResource( + id = R.string.app_content_unavailable + ) + ) + ) + ManagerText( + text = stringResource( + id = R.string.app_version_installed, + appInstalledVersion ?: stringResource( + id = R.string.app_content_unavailable + ) + ) + ) + }, + appActionsRow = { + if (appInstalledVersion != null) { + IconButton(onClick = onAppUninstallClick) { + Icon( + imageVector = Icons.Rounded.DeleteForever, + contentDescription = "Uninstall" + ) + } + IconButton(onClick = onAppLaunchClick) { + Icon( + imageVector = Icons.Rounded.Launch, + contentDescription = "Launch", + ) + } + } + IconButton(onClick = onAppDownloadClick) { + Icon( + imageVector = Icons.Rounded.Download, + contentDescription = "Install", + ) + } + } + ) +} + +@Composable +fun AppCardPlaceholder( + modifier: Modifier = Modifier +) { + BaseAppCard( + modifier = modifier, + appTitle = { + ManagerText( + modifier = Modifier + .managerPlaceholder( + visible = true, + shape = MediumShape + ), + text = " ".repeat(40), + textStyle = MaterialTheme.typography.titleMedium + ) + }, + appIcon = { + Box( + modifier = Modifier + .managerPlaceholder( + visible = true, + shape = RoundedCornerShape(24.dp) + ) + .size(48.dp) + ) + }, + appTrailing = { + Box( + modifier = Modifier + .managerPlaceholder( + visible = true, + shape = MediumShape + ) + .size(24.dp) + ) + }, + appVersionsColumn = { + ManagerText( + modifier = Modifier + .managerPlaceholder( + visible = true, + shape = SmallShape + ), + text = " ".repeat(30) + ) + ManagerText( + modifier = Modifier + .managerPlaceholder( + visible = true, + shape = SmallShape + ), + text = " ".repeat(30) + ) + }, + appActionsRow = { + Box( + modifier = Modifier + .fillMaxWidth(0.8f) + .height(36.dp) + .managerPlaceholder( + visible = true, + shape = MediumShape + ) + ) + } + ) +} + +@Composable +private fun BaseAppCard( + appTitle: @Composable () -> Unit, + appIcon: @Composable () -> Unit, + appTrailing: @Composable () -> Unit, + appVersionsColumn: @Composable ColumnScope.() -> Unit, + appActionsRow: @Composable RowScope.() -> Unit, + modifier: Modifier = Modifier +) { + ManagerElevatedCard( + modifier = modifier, + shape = LargeShape, + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding( + horizontal = DefaultContentPaddingHorizontal, + vertical = DefaultContentPaddingVertical + ), + verticalArrangement = Arrangement + .spacedBy(DefaultContentPaddingVertical) + ) { + ManagerListItem( + modifier = Modifier.fillMaxWidth(), + title = appTitle, + icon = appIcon, + trailing = appTrailing + ) + Divider( + modifier = Modifier + .fillMaxWidth() + .clip(LargeShape), + thickness = 2.dp, + ) + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Column( + verticalArrangement = Arrangement.spacedBy(4.dp), + horizontalAlignment = Alignment.Start + ) { + ManagerText( + text = stringResource(id = R.string.app_versions), + textStyle = MaterialTheme.typography.bodyMedium + ) + ProvideTextStyle(value = MaterialTheme.typography.bodySmall) { + appVersionsColumn() + } + } + Row( + modifier = Modifier.wrapContentWidth(), + content = appActionsRow, + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.End + ) + } + } + } +} + +private fun Modifier.managerPlaceholder( + visible: Boolean, + shape: Shape +) = composed { + placeholder( + visible = visible, + shape = shape, + color = MaterialTheme.colorScheme.surfaceVariant, + highlight = PlaceholderHighlight.shimmer( + highlightColor = MaterialTheme.colorScheme.onSurfaceVariant + ) + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/LinkCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/LinkCard.kt new file mode 100644 index 0000000000..3af59e1b1c --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widget/LinkCard.kt @@ -0,0 +1,68 @@ +package com.vanced.manager.ui.widget + +import android.content.Intent +import android.net.Uri +import androidx.browser.customtabs.CustomTabsIntent +import androidx.compose.foundation.layout.* +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.unit.dp +import com.vanced.manager.core.preferences.holder.useCustomTabsPref +import com.vanced.manager.ui.component.ManagerElevatedCard +import com.vanced.manager.ui.component.ManagerText +import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal +import com.vanced.manager.ui.util.DefaultContentPaddingVertical + +//TODO this composable should not handle opening links +@Composable +fun LinkCard( + text: String, + icon: Painter, + url: String, + modifier: Modifier = Modifier +) { + val context = LocalContext.current + val customTabs = remember { CustomTabsIntent.Builder().build() } + val uri = remember { Uri.parse(url) } + val intent = remember { Intent(Intent.ACTION_VIEW, uri) } + ManagerElevatedCard( + modifier = modifier + .height(100.dp) + .widthIn(min = 100.dp), + onClick = { + if (useCustomTabsPref) { + customTabs.launchUrl(context, uri) + } else { + context.startActivity(intent) + } + } + ) { + Box( + modifier = Modifier + .fillMaxSize() + .padding( + horizontal = DefaultContentPaddingHorizontal, + vertical = DefaultContentPaddingVertical + ), + ) { + Icon( + modifier = Modifier + .size(32.dp) + .align(Alignment.TopStart), + painter = icon, + contentDescription = null, + ) + ManagerText( + modifier = Modifier.align(Alignment.BottomStart), + text = text, + textStyle = MaterialTheme.typography.labelLarge + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/Settings.kt b/app/src/main/java/com/vanced/manager/ui/widget/Settings.kt new file mode 100644 index 0000000000..ff0cf6f060 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/widget/Settings.kt @@ -0,0 +1,138 @@ +package com.vanced.manager.ui.widget + +import androidx.compose.runtime.* +import androidx.compose.ui.res.stringResource +import com.vanced.manager.R +import com.vanced.manager.core.preferences.RadioButtonPreference +import com.vanced.manager.core.preferences.holder.managerThemePref +import com.vanced.manager.core.preferences.holder.managerVariantPref +import com.vanced.manager.core.preferences.holder.useCustomTabsPref +import com.vanced.manager.core.preferences.managerBooleanPreference +import com.vanced.manager.core.util.isMagiskInstalled +import com.vanced.manager.domain.model.NotificationPrefModel +import com.vanced.manager.ui.component.ManagerPreference +import com.vanced.manager.ui.component.ManagerSingleSelectDialogPreference +import com.vanced.manager.ui.component.ManagerSwitchPreference +import com.vanced.manager.ui.resource.managerString + +@Composable +fun SettingsClearFilesItem() { + ManagerPreference( + preferenceTitle = managerString( + stringId = R.string.settings_preference_clear_files_title + ), + preferenceDescription = null, + onClick = {} + ) +} + +@Composable +fun SettingsCustomTabsItem() { + ManagerSwitchPreference( + preferenceTitle = stringResource(id = R.string.settings_preference_use_custom_tabs_title), + preferenceDescription = stringResource(id = R.string.settings_preference_use_custom_tabs_summary), + isChecked = useCustomTabsPref, + onCheckedChange = { + useCustomTabsPref = it + } + ) +} + +@Composable +fun SettingsManagerVariantItem() { + var showDialog by remember { mutableStateOf(false) } + var selectedKey by remember { mutableStateOf(managerVariantPref) } + ManagerSingleSelectDialogPreference( + preferenceTitle = managerString( + stringId = R.string.settings_preference_variant_title + ), + preferenceDescription = managerVariantPref, + isDialogVisible = showDialog, + currentSelectedKey = selectedKey, + buttons = listOf( + RadioButtonPreference( + title = "nonroot", + key = "nonroot" + ), + RadioButtonPreference( + title = "root", + key = "root" + ), + ), + onPreferenceClick = { + showDialog = true + }, + onDismissRequest = { + showDialog = false + selectedKey = managerVariantPref + }, + onItemClick = { + if (it == "root" && !isMagiskInstalled) + return@ManagerSingleSelectDialogPreference + + selectedKey = it + }, + onSave = { + managerVariantPref = selectedKey + showDialog = false + } + ) +} + +@Composable +fun SettingsNotificationsItem(notificationApp: NotificationPrefModel) { + with(notificationApp) { + var appNotificationsPref by managerBooleanPreference( + key = "${prefKey}_notifications", + defaultValue = true + ) + ManagerSwitchPreference( + preferenceTitle = "$app Push Notifications", + preferenceDescription = "Receive push notifications when an update for $app is released", + isChecked = appNotificationsPref, + onCheckedChange = { + appNotificationsPref = it + } + ) + } +} + +@Composable +fun ThemeSettingsItem() { + var showDialog by remember { mutableStateOf(false) } + var selectedKey by remember { mutableStateOf(managerThemePref) } + ManagerSingleSelectDialogPreference( + preferenceTitle = managerString(stringId = R.string.settings_preference_theme_title), + preferenceDescription = managerThemePref, + isDialogVisible = showDialog, + currentSelectedKey = selectedKey, + buttons = listOf( + RadioButtonPreference( + title = managerString(R.string.settings_preference_theme_light), + key = "Light" + ), + RadioButtonPreference( + title = managerString(R.string.settings_preference_theme_dark), + key = "Dark" + ), + RadioButtonPreference( + title = managerString(R.string.settings_option_system_default), + key = "System Default" + ) + ), + onPreferenceClick = { + showDialog = true + }, + onDismissRequest = { + showDialog = false + selectedKey = managerThemePref + }, + onItemClick = { + selectedKey = it + }, + onSave = { + managerThemePref = selectedKey + showDialog = false + } + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/app/AppCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/app/AppCard.kt deleted file mode 100644 index fccebea87a..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/app/AppCard.kt +++ /dev/null @@ -1,100 +0,0 @@ -package com.vanced.manager.ui.widget.app - -import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.size -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Info -import androidx.compose.material.icons.rounded.DeleteForever -import androidx.compose.material.icons.rounded.Download -import androidx.compose.material.icons.rounded.Launch -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import coil.compose.ImagePainter -import com.vanced.manager.R -import com.vanced.manager.ui.component.text.AppVersionText -import com.vanced.manager.ui.component.text.ManagerText - -@OptIn(ExperimentalAnimationApi::class) -@Composable -fun AppCard( - appName: String, - appIcon: ImagePainter, - appInstalledVersion: String?, - appRemoteVersion: String?, - onAppDownloadClick: () -> Unit, - onAppUninstallClick: () -> Unit, - onAppLaunchClick: () -> Unit, - onAppInfoClick: () -> Unit, -) { - BaseAppCard( - appTitle = { - ManagerText( - modifier = Modifier.fillMaxSize(), - text = appName, - textStyle = MaterialTheme.typography.titleMedium - ) - }, - appIcon = { - Image( - modifier = Modifier.size(48.dp), - painter = appIcon, - contentDescription = "App Icon", - ) - }, - appTrailing = { - IconButton(onClick = onAppInfoClick) { - Icon( - imageVector = Icons.Outlined.Info, - contentDescription = "App Info" - ) - } - }, - appVersionsColumn = { - AppVersionText( - text = stringResource( - id = R.string.app_version_latest, - appRemoteVersion ?: stringResource( - id = R.string.app_content_unavailable - ) - ) - ) - AppVersionText( - text = stringResource( - id = R.string.app_version_installed, - appInstalledVersion ?: stringResource( - id = R.string.app_content_unavailable - ) - ) - ) - }, - appActionsRow = { - if (appInstalledVersion != null) { - IconButton(onClick = onAppUninstallClick) { - Icon( - imageVector = Icons.Rounded.DeleteForever, - contentDescription = "Uninstall" - ) - } - IconButton(onClick = onAppLaunchClick) { - Icon( - imageVector = Icons.Rounded.Launch, - contentDescription = "Launch", - ) - } - } - IconButton(onClick = onAppDownloadClick) { - Icon( - imageVector = Icons.Rounded.Download, - contentDescription = "Install", - ) - } - } - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/app/AppCardPlaceholder.kt b/app/src/main/java/com/vanced/manager/ui/widget/app/AppCardPlaceholder.kt deleted file mode 100644 index 42d766d111..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/app/AppCardPlaceholder.kt +++ /dev/null @@ -1,71 +0,0 @@ -package com.vanced.manager.ui.widget.app - -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.component.modifier.managerPlaceholder -import com.vanced.manager.ui.component.text.AppVersionText -import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.theme.MediumShape -import com.vanced.manager.ui.theme.SmallShape - -@Composable -fun AppCardPlaceholder() { - BaseAppCard( - appTitle = { - ManagerText( - modifier = Modifier - .clip(MediumShape) - .managerPlaceholder(true), - text = " ".repeat(40), - textStyle = MaterialTheme.typography.titleMedium - ) - }, - appIcon = { - Box( - Modifier - .clip(MediumShape) - .managerPlaceholder(true) - .size(48.dp) - ) - }, - appTrailing = { - Box( - Modifier - .clip(CircleShape) - .managerPlaceholder(true) - .size(24.dp) - ) - }, - appVersionsColumn = { - AppVersionText( - modifier = Modifier - .managerPlaceholder(true) - .clip(SmallShape), - text = " ".repeat(30) - ) - AppVersionText( - modifier = Modifier - .managerPlaceholder(true) - .clip(SmallShape), - text = " ".repeat(30) - ) - }, - appActionsRow = { - Box( - Modifier - .clip(MediumShape) - .fillMaxWidth(0.8f) - .height(36.dp) - .managerPlaceholder(true) - ) - } - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/app/BaseAppCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/app/BaseAppCard.kt deleted file mode 100644 index 4e66fb205b..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/app/BaseAppCard.kt +++ /dev/null @@ -1,82 +0,0 @@ -package com.vanced.manager.ui.widget.app - -import androidx.compose.foundation.layout.* -import androidx.compose.material.Divider -import androidx.compose.material3.LocalContentColor -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import com.vanced.manager.R -import com.vanced.manager.ui.component.card.ManagerTonalCard -import com.vanced.manager.ui.component.list.ManagerListItem -import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.theme.LargeShape -import com.vanced.manager.ui.theme.MediumShape -import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal -import com.vanced.manager.ui.util.DefaultContentPaddingVertical - -@Composable -fun BaseAppCard( - appTitle: @Composable () -> Unit, - appIcon: @Composable () -> Unit, - appTrailing: @Composable () -> Unit, - appVersionsColumn: @Composable ColumnScope.() -> Unit, - appActionsRow: @Composable RowScope.() -> Unit, -) { - ManagerTonalCard( - modifier = Modifier.fillMaxWidth(), - shape = LargeShape, - ) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding( - horizontal = DefaultContentPaddingHorizontal, - vertical = DefaultContentPaddingVertical - ), - verticalArrangement = Arrangement - .spacedBy(DefaultContentPaddingVertical) - ) { - ManagerListItem( - modifier = Modifier.fillMaxWidth(), - title = appTitle, - icon = appIcon, - trailing = appTrailing - ) - Divider( - modifier = Modifier - .fillMaxWidth() - .clip(MediumShape), - thickness = 2.dp, - color = LocalContentColor.current.copy(alpha = 0.12f) - ) - Row( - modifier = Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - Column( - modifier = Modifier.wrapContentWidth(), - verticalArrangement = Arrangement.spacedBy(4.dp), - horizontalAlignment = Alignment.Start - ) { - ManagerText( - text = stringResource(id = R.string.app_versions), - textStyle = MaterialTheme.typography.bodyMedium - ) - appVersionsColumn() - } - Row( - modifier = Modifier.wrapContentWidth(), - content = appActionsRow, - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.End - ) - } - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerCancelButton.kt b/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerCancelButton.kt deleted file mode 100644 index 3115b51f98..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerCancelButton.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.vanced.manager.ui.widget.button - -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.vanced.manager.R -import com.vanced.manager.ui.component.button.ManagerThemedTextButton -import com.vanced.manager.ui.resources.managerString - -@Composable -fun ManagerCancelButton( - onClick: () -> Unit -) { - ManagerThemedTextButton( - modifier = Modifier.fillMaxWidth(), - text = managerString( - stringId = R.string.dialog_button_cancel - ), - onClick = onClick - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerCloseButton.kt b/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerCloseButton.kt deleted file mode 100644 index 5e292ac700..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerCloseButton.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.vanced.manager.ui.widget.button - -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.vanced.manager.R -import com.vanced.manager.ui.component.button.ManagerThemedTextButton -import com.vanced.manager.ui.resources.managerString - -@Composable -fun ManagerCloseButton( - onClick: () -> Unit -) { - ManagerThemedTextButton( - modifier = Modifier.fillMaxWidth(), - text = managerString( - stringId = R.string.dialog_button_close - ), - onClick = onClick - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerDownloadButton.kt b/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerDownloadButton.kt deleted file mode 100644 index ba3766c61f..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerDownloadButton.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.vanced.manager.ui.widget.button - -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.vanced.manager.R -import com.vanced.manager.ui.component.button.ManagerThemedTextButton -import com.vanced.manager.ui.resources.managerString - -@Composable -fun ManagerDownloadButton( - onClick: () -> Unit -) { - ManagerThemedTextButton( - modifier = Modifier.fillMaxWidth(), - text = managerString( - stringId = R.string.app_download_dialog_confirm - ), - onClick = onClick - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerResetButton.kt b/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerResetButton.kt deleted file mode 100644 index 2e77dd3e2e..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerResetButton.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.vanced.manager.ui.widget.button - -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import com.vanced.manager.R -import com.vanced.manager.ui.component.button.ManagerThemedTextButton -import com.vanced.manager.ui.component.color.managerAccentColor -import com.vanced.manager.ui.resources.managerString - -@Composable -fun ManagerResetButton( - backgroundColor: Color = managerAccentColor(), - onClick: () -> Unit -) { - ManagerThemedTextButton( - modifier = Modifier.fillMaxWidth(), - text = managerString( - stringId = R.string.dialog_button_reset - ), - backgroundColor = backgroundColor, - onClick = onClick - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerSaveButton.kt b/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerSaveButton.kt deleted file mode 100644 index 34bb326f8e..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/button/ManagerSaveButton.kt +++ /dev/null @@ -1,25 +0,0 @@ -package com.vanced.manager.ui.widget.button - -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import com.vanced.manager.R -import com.vanced.manager.ui.component.button.ManagerThemedTextButton -import com.vanced.manager.ui.component.color.managerAccentColor -import com.vanced.manager.ui.resources.managerString - -@Composable -fun ManagerSaveButton( - backgroundColor: Color = managerAccentColor(), - onClick: () -> Unit -) { - ManagerThemedTextButton( - modifier = Modifier.fillMaxWidth(), - text = managerString( - stringId = R.string.dialog_button_save - ), - backgroundColor = backgroundColor, - onClick = onClick - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/checkbox/ManagerAnimatedCheckbox.kt b/app/src/main/java/com/vanced/manager/ui/widget/checkbox/ManagerAnimatedCheckbox.kt deleted file mode 100644 index d58890e687..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/checkbox/ManagerAnimatedCheckbox.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.vanced.manager.ui.widget.checkbox - -import androidx.compose.animation.core.updateTransition -import androidx.compose.foundation.layout.size -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.unit.Dp -import com.vanced.manager.ui.component.animation.jumpAnimation -import com.vanced.manager.ui.component.checkbox.ManagerCheckbox -import com.vanced.manager.ui.theme.MediumShape - -@Composable -fun ManagerAnimatedCheckbox( - size: Dp, - isChecked: Boolean, - shape: Shape = MediumShape, - onCheckedChange: (isChecked: Boolean) -> Unit, -) { - val transition = updateTransition( - targetState = isChecked, - label = "Checkbox Animation" - ) - val animatedSize by transition.jumpAnimation( - initialValue = size, - label = "Checkbox Size" - ) - ManagerCheckbox( - modifier = Modifier.size(animatedSize), - isChecked = isChecked, - shape = shape, - onCheckedChange = onCheckedChange - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/layout/CategoryLayout.kt b/app/src/main/java/com/vanced/manager/ui/widget/layout/CategoryLayout.kt deleted file mode 100644 index 031c48691e..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/layout/CategoryLayout.kt +++ /dev/null @@ -1,76 +0,0 @@ -package com.vanced.manager.ui.widget.layout - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyItemScope -import androidx.compose.foundation.lazy.LazyListScope -import androidx.compose.foundation.lazy.items -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.vanced.manager.ui.component.color.managerAnimatedColor -import com.vanced.manager.ui.component.text.ManagerText -import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal -import com.vanced.manager.ui.util.DefaultContentPaddingVertical - -@Composable -fun CategoryLayout( - categoryName: String, - modifier: Modifier = Modifier, - content: @Composable ColumnScope.() -> Unit, -) { - Column( - modifier = modifier, - verticalArrangement = Arrangement.spacedBy(DefaultContentPaddingVertical) - ) { - ManagerText( - modifier = Modifier.padding(start = DefaultContentPaddingHorizontal), - text = categoryName, - textStyle = MaterialTheme.typography.headlineSmall, - color = managerAnimatedColor(MaterialTheme.colorScheme.onSurface) - ) - content() - } -} - -fun <T> LazyListScope.managerCategory( - categoryName: String, - items: List<T>, - itemContent: @Composable (T) -> Unit -) { - item { - ManagerText( - modifier = Modifier.padding( - horizontal = DefaultContentPaddingHorizontal, - vertical = DefaultContentPaddingVertical - ), - text = categoryName, - textStyle = MaterialTheme.typography.headlineSmall, - color = managerAnimatedColor(MaterialTheme.colorScheme.onSurface) - ) - } - items(items) { item -> - itemContent(item) - } -} - -fun LazyListScope.managerCategory( - categoryName: String, - content: @Composable LazyItemScope.() -> Unit, -) { - item { - ManagerText( - modifier = Modifier - .padding( - horizontal = DefaultContentPaddingHorizontal, - vertical = DefaultContentPaddingVertical - ), - text = categoryName, - textStyle = MaterialTheme.typography.headlineSmall, - color = managerAnimatedColor(MaterialTheme.colorScheme.onSurface) - ) - } - item(content = content) -} diff --git a/app/src/main/java/com/vanced/manager/ui/widget/layout/SettingsCategoryLayout.kt b/app/src/main/java/com/vanced/manager/ui/widget/layout/SettingsCategoryLayout.kt deleted file mode 100644 index e14576947f..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/layout/SettingsCategoryLayout.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.vanced.manager.ui.widget.layout - -import androidx.compose.foundation.layout.Column -import androidx.compose.runtime.Composable - -@Composable -fun SettingsCategoryLayout( - categoryName: String, - content: @Composable () -> Unit -) { - CategoryLayout( - categoryName = categoryName, - ) { - Column { - content() - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt deleted file mode 100644 index 71d59961e4..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/list/CheckboxItem.kt +++ /dev/null @@ -1,40 +0,0 @@ -package com.vanced.manager.ui.widget.list - -import androidx.compose.material3.Checkbox -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.vanced.manager.ui.component.color.managerTextColor -import com.vanced.manager.ui.component.list.ManagerSelectableListItem -import com.vanced.manager.ui.component.modifier.managerClickable -import com.vanced.manager.ui.component.text.ManagerText - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun CheckboxItem( - text: String, - checked: Boolean, - onCheckedChange: (Boolean) -> Unit, - modifier: Modifier = Modifier, -) { - ManagerSelectableListItem( - modifier = modifier - .managerClickable(onClick = { - onCheckedChange(!checked) - }), - title = { - ManagerText( - text = text, - color = managerTextColor(), - textStyle = MaterialTheme.typography.titleSmall - ) - }, - trailing = { - Checkbox( - checked = checked, - onCheckedChange = null - ) - } - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt deleted file mode 100644 index 01fb8ad2bc..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/list/RadiobuttonItem.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.vanced.manager.ui.widget.list - -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.RadioButton -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.vanced.manager.ui.component.color.managerTextColor -import com.vanced.manager.ui.component.list.ManagerSelectableListItem -import com.vanced.manager.ui.component.modifier.managerClickable -import com.vanced.manager.ui.component.text.ManagerText - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun RadiobuttonItem( - text: String, - selected: Boolean, - onClick: () -> Unit, - modifier: Modifier = Modifier -) { - ManagerSelectableListItem( - modifier = modifier - .managerClickable(onClick = onClick), - title = { - ManagerText( - text = text, - color = managerTextColor(), - textStyle = MaterialTheme.typography.titleSmall - ) - }, - trailing = { - RadioButton( - selected = selected, - onClick = null - ) - } - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/radiobutton/ManagerAnimatedRadiobutton.kt b/app/src/main/java/com/vanced/manager/ui/widget/radiobutton/ManagerAnimatedRadiobutton.kt deleted file mode 100644 index d7abf257a4..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/radiobutton/ManagerAnimatedRadiobutton.kt +++ /dev/null @@ -1,35 +0,0 @@ -package com.vanced.manager.ui.widget.radiobutton - -import androidx.compose.animation.core.updateTransition -import androidx.compose.foundation.layout.size -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.unit.Dp -import com.vanced.manager.ui.component.animation.jumpAnimation -import com.vanced.manager.ui.component.radiobutton.ManagerRadiobutton -import com.vanced.manager.ui.theme.MediumShape - -@Composable -fun ManagerAnimatedRadiobutton( - size: Dp, - isSelected: Boolean, - shape: Shape = MediumShape, - onClick: () -> Unit -) { - val transition = updateTransition( - targetState = isSelected, - label = "Radiobutton Animation" - ) - val animatedSize by transition.jumpAnimation( - initialValue = size, - label = "Checkbox Size" - ) - ManagerRadiobutton( - modifier = Modifier.size(animatedSize), - isSelected = isSelected, - shape = shape, - onClick = onClick - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/settings/AccentColorItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/settings/AccentColorItem.kt deleted file mode 100644 index 996ee85762..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/settings/AccentColorItem.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.vanced.manager.ui.widget.settings - -import androidx.compose.runtime.Composable - -@Composable -fun SettingsAccentColorItem() { -// var localAccentColor by remember { mutableStateOf(managerAccentColorPref.value.value) } -// DialogPreference( -// preferenceTitle = managerString( -// stringId = R.string.settings_preference_accent_color_title -// ), -// preferenceDescription = "#" + Integer.toHexString(localAccentColor.toInt()), -// buttons = { isShown -> -// ManagerResetButton( -// backgroundColor = Color(localAccentColor) -// ) { -// isShown.value = false -// managerAccentColorPref.save(defAccentColor) -// } -// ManagerSaveButton( -// backgroundColor = Color(localAccentColor) -// ) { -// isShown.value = false -// managerAccentColorPref.save(localAccentColor) -// } -// } -// ) { -// ManagerColorPicker { -// localAccentColor = it -// } -// } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/settings/ClearFilesItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/settings/ClearFilesItem.kt deleted file mode 100644 index 7dedf13ee1..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/settings/ClearFilesItem.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.vanced.manager.ui.widget.settings - -import androidx.compose.runtime.Composable -import com.vanced.manager.R -import com.vanced.manager.ui.component.preference.Preference -import com.vanced.manager.ui.resources.managerString - -@Composable -fun SettingsClearFilesItem() { - Preference( - preferenceTitle = managerString( - stringId = R.string.settings_preference_clear_files_title - ), - preferenceDescription = null, - onClick = {} - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/settings/CustomTabsItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/settings/CustomTabsItem.kt deleted file mode 100644 index b71f0da325..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/settings/CustomTabsItem.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.vanced.manager.ui.widget.settings - -import androidx.compose.runtime.Composable -import androidx.compose.ui.res.stringResource -import com.vanced.manager.R -import com.vanced.manager.core.preferences.holder.useCustomTabsPref -import com.vanced.manager.ui.component.preference.CheckboxPreference - -@Composable -fun SettingsCustomTabsItem() { - CheckboxPreference( - preferenceTitle = stringResource(id = R.string.settings_preference_use_custom_tabs_title), - preferenceDescription = stringResource(id = R.string.settings_preference_use_custom_tabs_summary), - isChecked = useCustomTabsPref, - onCheckedChange = { - useCustomTabsPref = it - } - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/settings/ManagerVariantItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/settings/ManagerVariantItem.kt deleted file mode 100644 index dd553b5a19..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/settings/ManagerVariantItem.kt +++ /dev/null @@ -1,50 +0,0 @@ -package com.vanced.manager.ui.widget.settings - -import androidx.compose.runtime.* -import com.vanced.manager.R -import com.vanced.manager.core.preferences.RadioButtonPreference -import com.vanced.manager.core.preferences.holder.managerVariantPref -import com.vanced.manager.core.util.isMagiskInstalled -import com.vanced.manager.ui.component.preference.SingleSelectDialogPreference -import com.vanced.manager.ui.resources.managerString - -@Composable -fun SettingsManagerVariantItem() { - var showDialog by remember { mutableStateOf(false) } - var selectedKey by remember { mutableStateOf(managerVariantPref) } - SingleSelectDialogPreference( - preferenceTitle = managerString( - stringId = R.string.settings_preference_variant_title - ), - preferenceDescription = managerVariantPref, - isDialogVisible = showDialog, - currentSelectedKey = selectedKey, - buttons = listOf( - RadioButtonPreference( - title = "nonroot", - key = "nonroot" - ), - RadioButtonPreference( - title = "root", - key = "root" - ), - ), - onPreferenceClick = { - showDialog = true - }, - onDismissRequest = { - showDialog = false - selectedKey = managerVariantPref - }, - onItemClick = { - if (it == "root" && !isMagiskInstalled) - return@SingleSelectDialogPreference - - selectedKey = it - }, - onSave = { - managerVariantPref = selectedKey - showDialog = false - } - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/settings/NotificationsItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/settings/NotificationsItem.kt deleted file mode 100644 index 8fb8d8c6dc..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/settings/NotificationsItem.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.vanced.manager.ui.widget.settings - -import androidx.compose.runtime.Composable -import com.vanced.manager.core.preferences.managerBooleanPreference -import com.vanced.manager.core.util.notificationApps -import com.vanced.manager.ui.component.preference.CheckboxPreference - -@Composable -fun SettingsNotificationsItem() { - notificationApps.forEach { notificationApp -> - with(notificationApp) { - var appNotificationsPref by managerBooleanPreference( - key = "${prefKey}_notifications", - defaultValue = true - ) - CheckboxPreference( - preferenceTitle = "$app Push Notifications", - preferenceDescription = "Receive push notifications when an update for $app is released", - isChecked = appNotificationsPref, - onCheckedChange = { - appNotificationsPref = it - } - ) - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/settings/ThemeItem.kt b/app/src/main/java/com/vanced/manager/ui/widget/settings/ThemeItem.kt deleted file mode 100644 index 4ae1d778a5..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/settings/ThemeItem.kt +++ /dev/null @@ -1,48 +0,0 @@ -package com.vanced.manager.ui.widget.settings - -import androidx.compose.runtime.* -import com.vanced.manager.R -import com.vanced.manager.core.preferences.RadioButtonPreference -import com.vanced.manager.core.preferences.holder.managerThemePref -import com.vanced.manager.ui.component.preference.SingleSelectDialogPreference -import com.vanced.manager.ui.resources.managerString - -@Composable -fun ThemeSettingsItem() { - var showDialog by remember { mutableStateOf(false) } - var selectedKey by remember { mutableStateOf(managerThemePref) } - SingleSelectDialogPreference( - preferenceTitle = managerString(stringId = R.string.settings_preference_theme_title), - preferenceDescription = managerThemePref, - isDialogVisible = showDialog, - currentSelectedKey = selectedKey, - buttons = listOf( - RadioButtonPreference( - title = managerString(R.string.settings_preference_theme_light), - key = "Light" - ), - RadioButtonPreference( - title = managerString(R.string.settings_preference_theme_dark), - key = "Dark" - ), - RadioButtonPreference( - title = managerString(R.string.settings_option_system_default), - key = "System Default" - ) - ), - onPreferenceClick = { - showDialog = true - }, - onDismissRequest = { - showDialog = false - selectedKey = managerThemePref - }, - onItemClick = { - selectedKey = it - }, - onSave = { - managerThemePref = selectedKey - showDialog = false - } - ) -} From 2f9690ec04a3acc7396e2f1b6deefd1d2cd586d3 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Thu, 24 Feb 2022 21:28:53 +0400 Subject: [PATCH 109/118] update dependencies --- app/build.gradle.kts | 8 ++++---- build.gradle.kts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index eda4419531..4b947956c2 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -7,7 +7,7 @@ plugins { id("kotlin-parcelize") } -val composeVersion = "1.1.0" +val composeVersion = "1.1.1" android { compileSdk = 31 @@ -101,9 +101,9 @@ dependencies { implementation("androidx.preference:preference-ktx:1.2.0") implementation("androidx.activity:activity-compose:1.4.0") - val lifecycleVersion = "2.4.0" - implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleVersion") + val lifecycleVersion = "2.4.1" implementation("androidx.lifecycle:lifecycle-viewmodel-compose:$lifecycleVersion") + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycleVersion") // Compose implementation("androidx.compose.compiler:compiler:$composeVersion") @@ -111,7 +111,7 @@ dependencies { implementation("androidx.compose.material:material-icons-core:$composeVersion") implementation("androidx.compose.material:material-icons-extended:$composeVersion") implementation("androidx.compose.material:material:$composeVersion") - implementation("androidx.compose.material3:material3:1.0.0-alpha05") + implementation("androidx.compose.material3:material3:1.0.0-alpha06") implementation("androidx.compose.runtime:runtime-livedata:$composeVersion") implementation("androidx.compose.ui:ui-tooling:$composeVersion") implementation("androidx.compose.ui:ui-util:$composeVersion") diff --git a/build.gradle.kts b/build.gradle.kts index 23e841ea6c..480ec660e0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ buildscript { val kotlinVersion = "1.6.10" dependencies { - classpath("com.android.tools.build:gradle:7.1.0") + classpath("com.android.tools.build:gradle:7.1.2") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") } } From 11ac0d0e75df182766097c1c9333392e1ee27dae Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 27 Feb 2022 12:59:11 +0400 Subject: [PATCH 110/118] update settings --- .../com/vanced/manager/di/ViewModelModule.kt | 12 +- .../com/vanced/manager/ui/MainActivity.kt | 9 +- .../manager/ui/component/ManagerLazyColumn.kt | 31 +++- .../manager/ui/component/ManagerPreference.kt | 73 ++++----- .../manager/ui/screen/SettingsScreen.kt | 95 ++++++++++-- .../java/com/vanced/manager/ui/theme/Theme.kt | 32 +++- .../manager/ui/viewmodel/MainViewModel.kt | 14 +- .../manager/ui/viewmodel/SettingsViewModel.kt | 30 ++++ .../com/vanced/manager/ui/widget/Settings.kt | 138 ------------------ 9 files changed, 231 insertions(+), 203 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/ui/viewmodel/SettingsViewModel.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/widget/Settings.kt diff --git a/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt index 3752c1e271..a7e40aca74 100644 --- a/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt +++ b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt @@ -1,6 +1,7 @@ package com.vanced.manager.di import android.app.Application +import android.content.SharedPreferences import com.vanced.manager.core.downloader.impl.MicrogDownloader import com.vanced.manager.core.downloader.impl.MusicDownloader import com.vanced.manager.core.downloader.impl.VancedDownloader @@ -13,6 +14,7 @@ import com.vanced.manager.repository.MirrorRepository import com.vanced.manager.ui.viewmodel.ConfigurationViewModel import com.vanced.manager.ui.viewmodel.InstallViewModel import com.vanced.manager.ui.viewmodel.MainViewModel +import com.vanced.manager.ui.viewmodel.SettingsViewModel import org.koin.android.ext.koin.androidApplication import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.dsl.module @@ -22,8 +24,9 @@ val viewModelModule = module { fun provideMainViewModel( mainRepository: MainRepository, mirrorRepository: MirrorRepository, + preferences: SharedPreferences, app: Application, - ) = MainViewModel(mainRepository, mirrorRepository, app) + ) = MainViewModel(mainRepository, mirrorRepository, preferences, app) fun provideInstallViewModel( vancedDownloader: VancedDownloader, @@ -39,7 +42,12 @@ val viewModelModule = module { return ConfigurationViewModel() } - viewModel { provideMainViewModel(get(), get(), androidApplication()) } + fun provideSettingsViewModel(): SettingsViewModel { + return SettingsViewModel() + } + + viewModel { provideMainViewModel(get(), get(), get(), androidApplication()) } viewModel { provideInstallViewModel(get(), get(), get(), get(), get(), get()) } viewModel { provideConfigurationViewModel() } + viewModel { provideSettingsViewModel() } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index 6c87b62067..fa427e385d 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -18,7 +18,6 @@ import com.vanced.manager.core.installer.service.AppInstallService import com.vanced.manager.core.installer.service.AppUninstallService import com.vanced.manager.ui.screen.* import com.vanced.manager.ui.theme.ManagerTheme -import com.vanced.manager.ui.theme.isDark import com.vanced.manager.ui.util.Screen import com.vanced.manager.ui.util.animated import com.vanced.manager.ui.viewmodel.InstallViewModel @@ -54,11 +53,10 @@ class MainActivity : ComponentActivity() { super.onCreate(savedInstanceState) mainViewModel.fetch() setContent { - ManagerTheme { + val isDark = mainViewModel.appTheme.isDark() + ManagerTheme(darkMode = isDark) { val surfaceColor = MaterialTheme.colorScheme.surface.animated - val isDark = isDark() - val systemUiController = rememberSystemUiController() SideEffect { @@ -104,6 +102,9 @@ class MainActivity : ComponentActivity() { SettingsScreen( onToolbarBackButtonClick = { backStack.pop() + }, + onThemeChange = { + mainViewModel.appTheme = it } ) } diff --git a/app/src/main/java/com/vanced/manager/ui/component/ManagerLazyColumn.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerLazyColumn.kt index f08381f435..0720e1ff94 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/ManagerLazyColumn.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerLazyColumn.kt @@ -5,10 +5,7 @@ import androidx.compose.foundation.gestures.ScrollableDefaults import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyListScope -import androidx.compose.foundation.lazy.LazyListState -import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.lazy.* import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -61,3 +58,29 @@ inline fun LazyListScope.managerCategory( } content() } + +inline fun <K, V> LazyListScope.items( + items: Map<K, V>, + noinline key: ((key: K, value: V) -> Any)? = null, + crossinline itemContent: @Composable LazyItemScope.(key: K, value: V) -> Unit +) = items( + count = items.size, + key = if (key != null) { index -> + key(items.keys.elementAt(index), items.values.elementAt(index)) + } else null +) { index -> + itemContent(items.keys.elementAt(index), items.values.elementAt(index)) +} + +inline fun <K, V> LazyListScope.itemsIndexed( + items: Map<K, V>, + noinline key: ((index: Int, key: K, value: V) -> Any)? = null, + crossinline itemContent: @Composable LazyItemScope.(index: Int, key: K, value: V) -> Unit +) = items( + count = items.size, + key = if (key != null) { index -> + key(index, items.keys.elementAt(index), items.values.elementAt(index)) + } else null +) { index -> + itemContent(index, items.keys.elementAt(index), items.values.elementAt(index)) +} diff --git a/app/src/main/java/com/vanced/manager/ui/component/ManagerPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerPreference.kt index a7028659df..eac363d787 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/ManagerPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerPreference.kt @@ -3,7 +3,6 @@ package com.vanced.manager.ui.component import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items import androidx.compose.material.Checkbox import androidx.compose.material.Switch import androidx.compose.material3.MaterialTheme @@ -15,12 +14,17 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.unit.dp import com.vanced.manager.R -import com.vanced.manager.core.preferences.RadioButtonPreference import com.vanced.manager.ui.resource.managerString import com.vanced.manager.ui.theme.LargeShape import com.vanced.manager.ui.theme.SmallShape import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal +@JvmInline +value class EntryText(val text: String) + +@JvmInline +value class EntryValue(val value: String) + @Composable fun ManagerPreference( preferenceTitle: String, @@ -74,21 +78,21 @@ fun ManagerSwitchPreference( fun ManagerDialogPreference( preferenceTitle: String, preferenceDescription: String? = null, - trailing: @Composable () -> Unit = {}, - onPreferenceClick: () -> Unit, - isDialogVisible: Boolean, + showDialog: Boolean, + onClick: () -> Unit, onDismissRequest: () -> Unit, confirmButton: @Composable () -> Unit, dismissButton: @Composable () -> Unit = {}, + trailing: @Composable () -> Unit = {}, content: @Composable () -> Unit ) { ManagerPreference( preferenceTitle = preferenceTitle, preferenceDescription = preferenceDescription, trailing = trailing, - onClick = onPreferenceClick + onClick = onClick ) - if (isDialogVisible) { + if (showDialog) { ManagerDialog( title = preferenceTitle, onDismissRequest = onDismissRequest, @@ -103,13 +107,13 @@ fun ManagerDialogPreference( fun ManagerSingleSelectDialogPreference( preferenceTitle: String, preferenceDescription: String, - isDialogVisible: Boolean, - currentSelectedKey: String, - buttons: List<RadioButtonPreference>, + showDialog: Boolean, + selected: EntryValue, + entries: Map<EntryText, EntryValue>, trailing: @Composable () -> Unit = {}, - onPreferenceClick: () -> Unit, + onClick: () -> Unit, onDismissRequest: () -> Unit, - onItemClick: (itemKey: String) -> Unit, + onEntrySelect: (EntryValue) -> Unit, onSave: () -> Unit, ) { ManagerDialogPreference( @@ -127,20 +131,19 @@ fun ManagerSingleSelectDialogPreference( } }, onDismissRequest = onDismissRequest, - isDialogVisible = isDialogVisible, - onPreferenceClick = onPreferenceClick + showDialog = showDialog, + onClick = onClick ) { LazyColumn( modifier = Modifier.heightIn(max = 400.dp) ) { - items(buttons) { button -> - val (title, key) = button + items(entries) { entryText, entryValue -> ListDialogRadiobuttonItem( modifier = Modifier.fillMaxWidth(), - text = title, - selected = currentSelectedKey == key, + text = entryText.text, + selected = selected == entryValue, onClick = { - onItemClick(key) + onEntrySelect(entryValue) } ) } @@ -152,13 +155,13 @@ fun ManagerSingleSelectDialogPreference( fun ManagerMultiSelectDialogPreference( preferenceTitle: String, preferenceDescription: String, - isDialogVisible: Boolean, - currentSelectedKeys: List<String>, - buttons: List<RadioButtonPreference>, + showDialog: Boolean, + selected: List<EntryValue>, + entries: Map<EntryText, EntryValue>, trailing: @Composable () -> Unit = {}, - onPreferenceClick: () -> Unit, + onClick: () -> Unit, onDismissRequest: () -> Unit, - onItemCheckChange: (isChecked: Boolean, itemKey: String) -> Unit, + onEntriesSelect: (List<EntryValue>) -> Unit, onSave: () -> Unit, ) { ManagerDialogPreference( @@ -166,29 +169,33 @@ fun ManagerMultiSelectDialogPreference( preferenceDescription = preferenceDescription, trailing = trailing, confirmButton = { - androidx.compose.material.TextButton(onClick = onSave) { + TextButton(onClick = onSave) { ManagerText(managerString(R.string.dialog_button_save)) } }, dismissButton = { - androidx.compose.material.TextButton(onClick = onDismissRequest) { + TextButton(onClick = onDismissRequest) { ManagerText(managerString(R.string.dialog_button_cancel)) } }, onDismissRequest = onDismissRequest, - isDialogVisible = isDialogVisible, - onPreferenceClick = onPreferenceClick + showDialog = showDialog, + onClick = onClick ) { LazyColumn( modifier = Modifier.heightIn(max = 400.dp) ) { - items(buttons) { button -> - val (title, key) = button + items(entries) { entryText, entryValue -> ListDialogCheckboxItem( - text = title, - checked = currentSelectedKeys.contains(key), + text = entryText.text, + checked = selected.contains(entryValue), onCheckedChange = { isChecked -> - onItemCheckChange(isChecked, key) + val mutableSelected = selected.toMutableList() + when (isChecked) { + true -> mutableSelected.add(entryValue) + false -> mutableSelected.remove(entryValue) + } + onEntriesSelect(mutableSelected) } ) } diff --git a/app/src/main/java/com/vanced/manager/ui/screen/SettingsScreen.kt b/app/src/main/java/com/vanced/manager/ui/screen/SettingsScreen.kt index 8f1ae68c6d..0a94efd5e6 100644 --- a/app/src/main/java/com/vanced/manager/ui/screen/SettingsScreen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screen/SettingsScreen.kt @@ -2,29 +2,32 @@ package com.vanced.manager.ui.screen import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.rounded.ArrowBackIosNew import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton -import androidx.compose.runtime.Composable +import androidx.compose.runtime.* import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource import com.vanced.manager.R -import com.vanced.manager.core.util.notificationApps +import com.vanced.manager.core.preferences.holder.managerThemePref +import com.vanced.manager.core.preferences.holder.managerVariantPref +import com.vanced.manager.core.util.isMagiskInstalled import com.vanced.manager.ui.component.* import com.vanced.manager.ui.resource.managerString +import com.vanced.manager.ui.theme.ManagerTheme import com.vanced.manager.ui.util.Screen -import com.vanced.manager.ui.widget.SettingsCustomTabsItem -import com.vanced.manager.ui.widget.SettingsManagerVariantItem -import com.vanced.manager.ui.widget.SettingsNotificationsItem -import com.vanced.manager.ui.widget.ThemeSettingsItem +import com.vanced.manager.ui.viewmodel.SettingsViewModel +import org.koin.androidx.compose.viewModel @ExperimentalMaterial3Api @Composable fun SettingsScreen( onToolbarBackButtonClick: () -> Unit, + onThemeChange: (ManagerTheme) -> Unit, ) { + val viewModel: SettingsViewModel by viewModel() ManagerScaffold( modifier = Modifier.fillMaxSize(), topBar = { @@ -52,20 +55,86 @@ fun SettingsScreen( managerString(R.string.settings_category_behaviour) }) { item { - SettingsCustomTabsItem() - } - items(notificationApps) { notificationApp -> - SettingsNotificationsItem(notificationApp) + ManagerSwitchPreference( + preferenceTitle = stringResource(id = R.string.settings_preference_use_custom_tabs_title), + preferenceDescription = stringResource(id = R.string.settings_preference_use_custom_tabs_summary), + isChecked = viewModel.managerUseCustomTabs, + onCheckedChange = { + viewModel.managerUseCustomTabs = it + } + ) } item { - SettingsManagerVariantItem() + var showDialog by remember { mutableStateOf(false) } + var selectedMode by remember { mutableStateOf(EntryValue(viewModel.managerMode)) } + ManagerSingleSelectDialogPreference( + preferenceTitle = managerString( + stringId = R.string.settings_preference_variant_title + ), + preferenceDescription = selectedMode.value, + showDialog = showDialog, + selected = selectedMode, + entries = mapOf( + EntryText("nonroot") to EntryValue("nonroot"), + EntryText("root") to EntryValue("root"), + ), + onClick = { + showDialog = true + }, + onDismissRequest = { + showDialog = false + selectedMode = EntryValue(managerVariantPref) + }, + onEntrySelect = { + if (it.value == "root" && !isMagiskInstalled) + return@ManagerSingleSelectDialogPreference + + selectedMode = it + }, + onSave = { + viewModel.managerMode = selectedMode.value + showDialog = false + } + ) } } managerCategory(categoryName = { managerString(R.string.settings_category_appearance) }) { item { - ThemeSettingsItem() + var showDialog by remember { mutableStateOf(false) } + var selectedTheme by remember { mutableStateOf(EntryValue(managerThemePref)) } + ManagerSingleSelectDialogPreference( + preferenceTitle = managerString(stringId = R.string.settings_preference_theme_title), + preferenceDescription = managerString( + stringId = viewModel.getThemeStringIdByValue(selectedTheme.value) + ), + showDialog = showDialog, + selected = selectedTheme, + entries = mapOf( + EntryText(managerString(viewModel.getThemeStringIdByValue(SettingsViewModel.THEME_LIGHT_VALUE))) to + EntryValue(SettingsViewModel.THEME_LIGHT_VALUE), + EntryText(managerString(viewModel.getThemeStringIdByValue(SettingsViewModel.THEME_DARK_VALUE))) to + EntryValue(SettingsViewModel.THEME_DARK_VALUE), + EntryText(managerString(viewModel.getThemeStringIdByValue(SettingsViewModel.THEME_SYSTEM_DEFAULT_VALUE))) to + EntryValue(SettingsViewModel.THEME_SYSTEM_DEFAULT_VALUE), + ), + onClick = { + showDialog = true + }, + onDismissRequest = { + showDialog = false + selectedTheme = EntryValue(viewModel.managerTheme) + }, + onEntrySelect = { + selectedTheme = it + }, + onSave = { + viewModel.managerTheme = selectedTheme.value + showDialog = false + onThemeChange(ManagerTheme.fromKey(selectedTheme.value)) + } + ) } } } diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt index 6ad82a89e2..8eb0a3c2f7 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt @@ -8,7 +8,7 @@ import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.platform.LocalContext -import com.vanced.manager.core.preferences.holder.managerThemePref +import com.vanced.manager.ui.viewmodel.SettingsViewModel const val defAccentColor = 0xFF0477E1 @@ -67,12 +67,27 @@ private val DarkThemeColors = darkColorScheme( inverseSurface = md_theme_dark_inverseSurface, ) -@Composable -fun isDark(): Boolean = when (managerThemePref) { - "Dark" -> true - "Light" -> false - "System Default" -> isSystemInDarkTheme() - else -> throw IllegalArgumentException("Unknown theme") +enum class ManagerTheme { + LIGHT, + DARK, + SYSTEM_DEFAULT; + + @Composable + fun isDark() = when (this) { + LIGHT -> false + DARK -> true + SYSTEM_DEFAULT -> isSystemInDarkTheme() + } + + companion object { + fun fromKey(key: String?): ManagerTheme { + return when (key) { + SettingsViewModel.THEME_DARK_VALUE -> DARK + SettingsViewModel.THEME_LIGHT_VALUE -> LIGHT + else -> SYSTEM_DEFAULT + } + } + } } @Composable @@ -89,11 +104,12 @@ inline fun apiDependantColorScheme( @Composable fun ManagerTheme( + darkMode: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit ) { val context = LocalContext.current val colorScheme = - if (isDark()) { + if (darkMode) { apiDependantColorScheme( dynamic = { dynamicDarkColorScheme(context) }, static = { DarkThemeColors } diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt index 625a1db0f1..a028799eca 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt @@ -4,6 +4,7 @@ import android.app.Application import android.content.ActivityNotFoundException import android.content.ComponentName import android.content.Intent +import android.content.SharedPreferences import android.util.Log import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -18,12 +19,14 @@ import com.vanced.manager.network.util.MUSIC_NAME import com.vanced.manager.network.util.VANCED_NAME import com.vanced.manager.repository.MainRepository import com.vanced.manager.repository.MirrorRepository +import com.vanced.manager.ui.theme.ManagerTheme import kotlinx.coroutines.launch class MainViewModel( private val mainRepository: MainRepository, private val mirrorRepository: MirrorRepository, - private val app: Application + private val preferences: SharedPreferences, + private val app: Application, ) : AndroidViewModel(app) { private val isRoot @@ -45,6 +48,15 @@ class MainViewModel( var appState by mutableStateOf<AppState>(AppState.Fetching(appCount)) private set + var appTheme by mutableStateOf( + ManagerTheme.fromKey( + preferences.getString( + SettingsViewModel.MANAGER_THEME_KEY, + SettingsViewModel.THEME_SYSTEM_DEFAULT_VALUE + ) + ) + ) + fun fetch() { viewModelScope.launch { appState = AppState.Fetching(appCount) diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/SettingsViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/SettingsViewModel.kt new file mode 100644 index 0000000000..7623e99639 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/SettingsViewModel.kt @@ -0,0 +1,30 @@ +package com.vanced.manager.ui.viewmodel + +import androidx.lifecycle.ViewModel +import com.vanced.manager.R +import com.vanced.manager.core.preferences.managerBooleanPreference +import com.vanced.manager.core.preferences.managerStringPreference + +class SettingsViewModel : ViewModel() { + + companion object { + const val MANAGER_THEME_KEY = "manager_theme" + const val MANAGER_MODE_KEY = "manager_mode" + + const val THEME_DARK_VALUE = "dark" + const val THEME_LIGHT_VALUE = "light" + const val THEME_SYSTEM_DEFAULT_VALUE = "system_default" + } + + var managerUseCustomTabs by managerBooleanPreference(key = "manager_use_custom_tabs") + var managerMode by managerStringPreference(key = MANAGER_MODE_KEY, defaultValue = "nonroot") + var managerTheme by managerStringPreference(MANAGER_THEME_KEY, THEME_SYSTEM_DEFAULT_VALUE) + + fun getThemeStringIdByValue(value: String): Int { + return when (value) { + THEME_DARK_VALUE -> R.string.settings_preference_theme_dark + THEME_LIGHT_VALUE -> R.string.settings_preference_theme_light + else -> R.string.settings_option_system_default + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/widget/Settings.kt b/app/src/main/java/com/vanced/manager/ui/widget/Settings.kt deleted file mode 100644 index ff0cf6f060..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/widget/Settings.kt +++ /dev/null @@ -1,138 +0,0 @@ -package com.vanced.manager.ui.widget - -import androidx.compose.runtime.* -import androidx.compose.ui.res.stringResource -import com.vanced.manager.R -import com.vanced.manager.core.preferences.RadioButtonPreference -import com.vanced.manager.core.preferences.holder.managerThemePref -import com.vanced.manager.core.preferences.holder.managerVariantPref -import com.vanced.manager.core.preferences.holder.useCustomTabsPref -import com.vanced.manager.core.preferences.managerBooleanPreference -import com.vanced.manager.core.util.isMagiskInstalled -import com.vanced.manager.domain.model.NotificationPrefModel -import com.vanced.manager.ui.component.ManagerPreference -import com.vanced.manager.ui.component.ManagerSingleSelectDialogPreference -import com.vanced.manager.ui.component.ManagerSwitchPreference -import com.vanced.manager.ui.resource.managerString - -@Composable -fun SettingsClearFilesItem() { - ManagerPreference( - preferenceTitle = managerString( - stringId = R.string.settings_preference_clear_files_title - ), - preferenceDescription = null, - onClick = {} - ) -} - -@Composable -fun SettingsCustomTabsItem() { - ManagerSwitchPreference( - preferenceTitle = stringResource(id = R.string.settings_preference_use_custom_tabs_title), - preferenceDescription = stringResource(id = R.string.settings_preference_use_custom_tabs_summary), - isChecked = useCustomTabsPref, - onCheckedChange = { - useCustomTabsPref = it - } - ) -} - -@Composable -fun SettingsManagerVariantItem() { - var showDialog by remember { mutableStateOf(false) } - var selectedKey by remember { mutableStateOf(managerVariantPref) } - ManagerSingleSelectDialogPreference( - preferenceTitle = managerString( - stringId = R.string.settings_preference_variant_title - ), - preferenceDescription = managerVariantPref, - isDialogVisible = showDialog, - currentSelectedKey = selectedKey, - buttons = listOf( - RadioButtonPreference( - title = "nonroot", - key = "nonroot" - ), - RadioButtonPreference( - title = "root", - key = "root" - ), - ), - onPreferenceClick = { - showDialog = true - }, - onDismissRequest = { - showDialog = false - selectedKey = managerVariantPref - }, - onItemClick = { - if (it == "root" && !isMagiskInstalled) - return@ManagerSingleSelectDialogPreference - - selectedKey = it - }, - onSave = { - managerVariantPref = selectedKey - showDialog = false - } - ) -} - -@Composable -fun SettingsNotificationsItem(notificationApp: NotificationPrefModel) { - with(notificationApp) { - var appNotificationsPref by managerBooleanPreference( - key = "${prefKey}_notifications", - defaultValue = true - ) - ManagerSwitchPreference( - preferenceTitle = "$app Push Notifications", - preferenceDescription = "Receive push notifications when an update for $app is released", - isChecked = appNotificationsPref, - onCheckedChange = { - appNotificationsPref = it - } - ) - } -} - -@Composable -fun ThemeSettingsItem() { - var showDialog by remember { mutableStateOf(false) } - var selectedKey by remember { mutableStateOf(managerThemePref) } - ManagerSingleSelectDialogPreference( - preferenceTitle = managerString(stringId = R.string.settings_preference_theme_title), - preferenceDescription = managerThemePref, - isDialogVisible = showDialog, - currentSelectedKey = selectedKey, - buttons = listOf( - RadioButtonPreference( - title = managerString(R.string.settings_preference_theme_light), - key = "Light" - ), - RadioButtonPreference( - title = managerString(R.string.settings_preference_theme_dark), - key = "Dark" - ), - RadioButtonPreference( - title = managerString(R.string.settings_option_system_default), - key = "System Default" - ) - ), - onPreferenceClick = { - showDialog = true - }, - onDismissRequest = { - showDialog = false - selectedKey = managerThemePref - }, - onItemClick = { - selectedKey = it - }, - onSave = { - managerThemePref = selectedKey - showDialog = false - } - ) -} \ No newline at end of file From 73ee8d4f7a8e1b66342c67523f939bfb51a1f365 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sun, 27 Feb 2022 13:02:02 +0400 Subject: [PATCH 111/118] component cleanup --- ...ManagerLazyColumn.kt => ManagerLazyDsl.kt} | 31 +++++++++++++- .../manager/ui/component/ManagerLazyRow.kt | 42 ------------------- .../ui/component/ManagerSelectableListItem.kt | 39 ----------------- 3 files changed, 29 insertions(+), 83 deletions(-) rename app/src/main/java/com/vanced/manager/ui/component/{ManagerLazyColumn.kt => ManagerLazyDsl.kt} (73%) delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/ManagerLazyRow.kt delete mode 100644 app/src/main/java/com/vanced/manager/ui/component/ManagerSelectableListItem.kt diff --git a/app/src/main/java/com/vanced/manager/ui/component/ManagerLazyColumn.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerLazyDsl.kt similarity index 73% rename from app/src/main/java/com/vanced/manager/ui/component/ManagerLazyColumn.kt rename to app/src/main/java/com/vanced/manager/ui/component/ManagerLazyDsl.kt index 0720e1ff94..4c0e5aac19 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/ManagerLazyColumn.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerLazyDsl.kt @@ -41,9 +41,36 @@ fun ManagerLazyColumn( ) } +@Composable +fun ManagerLazyRow( + modifier: Modifier = Modifier, + state: LazyListState = rememberLazyListState(), + contentPadding: PaddingValues = PaddingValues( + start = EdgeToEdgeContentPadding, + end = EdgeToEdgeContentPadding, + ), + reverseLayout: Boolean = false, + horizontalArrangement: Arrangement.Horizontal = + Arrangement.spacedBy(8.dp, if (!reverseLayout) Alignment.Start else Alignment.End), + verticalAlignment: Alignment.Vertical = Alignment.Top, + flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(), + content: LazyListScope.() -> Unit +) { + LazyRow( + modifier = modifier, + state = state, + contentPadding = contentPadding, + reverseLayout = reverseLayout, + horizontalArrangement = horizontalArrangement, + verticalAlignment = verticalAlignment, + flingBehavior = flingBehavior, + content = content + ) +} + inline fun LazyListScope.managerCategory( - noinline categoryName: @Composable () -> String, - content: LazyListScope.() -> Unit, + crossinline categoryName: @Composable () -> String, + content: LazyListScope.() -> Unit ) { item { ManagerText( diff --git a/app/src/main/java/com/vanced/manager/ui/component/ManagerLazyRow.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerLazyRow.kt deleted file mode 100644 index 4d48a6c94f..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/ManagerLazyRow.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.vanced.manager.ui.component - -import androidx.compose.foundation.gestures.FlingBehavior -import androidx.compose.foundation.gestures.ScrollableDefaults -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.lazy.LazyListScope -import androidx.compose.foundation.lazy.LazyListState -import androidx.compose.foundation.lazy.LazyRow -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.vanced.manager.ui.util.EdgeToEdgeContentPadding - -@Composable -fun ManagerLazyRow( - modifier: Modifier = Modifier, - state: LazyListState = rememberLazyListState(), - contentPadding: PaddingValues = PaddingValues( - start = EdgeToEdgeContentPadding, - end = EdgeToEdgeContentPadding, - ), - reverseLayout: Boolean = false, - horizontalArrangement: Arrangement.Horizontal = - Arrangement.spacedBy(8.dp, if (!reverseLayout) Alignment.Start else Alignment.End), - verticalAlignment: Alignment.Vertical = Alignment.Top, - flingBehavior: FlingBehavior = ScrollableDefaults.flingBehavior(), - content: LazyListScope.() -> Unit -) { - LazyRow( - modifier = modifier, - state = state, - contentPadding = contentPadding, - reverseLayout = reverseLayout, - horizontalArrangement = horizontalArrangement, - verticalAlignment = verticalAlignment, - flingBehavior = flingBehavior, - content = content - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/component/ManagerSelectableListItem.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerSelectableListItem.kt deleted file mode 100644 index 99c31e2fe1..0000000000 --- a/app/src/main/java/com/vanced/manager/ui/component/ManagerSelectableListItem.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.vanced.manager.ui.component - -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp - -@Composable -fun ManagerSelectableListItem( - modifier: Modifier = Modifier, - title: @Composable () -> Unit, - trailing: @Composable (() -> Unit) -) { - Row( - modifier = modifier - .padding(vertical = 8.dp, horizontal = 6.dp) - ) { - Box( - modifier = Modifier - .weight(1f) - .padding(horizontal = 6.dp) - .align(Alignment.CenterVertically), - ) { - title() - } - Box( - modifier = Modifier - .size(30.dp) - .align(Alignment.CenterVertically), - contentAlignment = Alignment.Center, - ) { - trailing() - } - } -} \ No newline at end of file From 6960cb67b15a2c4e5a5a210b2184e25e51ea7a0f Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 1 Mar 2022 19:01:03 +0400 Subject: [PATCH 112/118] switch to github as backend --- app/build.gradle.kts | 4 + app/proguard-rules.pro | 4 +- .../com/vanced/manager/ManagerApplication.kt | 5 +- .../core/preferences/CheckboxPreference.kt | 6 - .../core/preferences/RadioButtonPreference.kt | 6 - .../preferences/holder/PreferenceHolder.kt | 12 +- .../com/vanced/manager/core/util/Variant.kt | 7 - .../manager/datasource/PkgInfoDatasource.kt | 50 +++++ .../datasource/PreferenceDatasource.kt | 68 +++++++ .../com/vanced/manager/di/CustomTabsModule.kt | 13 ++ .../com/vanced/manager/di/DatasourceModule.kt | 31 ++++ .../com/vanced/manager/di/MapperModule.kt | 22 --- .../vanced/manager/di/PackageManagerModule.kt | 26 --- .../com/vanced/manager/di/PreferenceModule.kt | 13 -- .../com/vanced/manager/di/RepositoryModule.kt | 38 ++-- .../com/vanced/manager/di/ServiceModule.kt | 44 ++--- .../com/vanced/manager/di/ViewModelModule.kt | 31 ++-- .../PackageInformationDataSource.kt | 36 ---- .../com/vanced/manager/domain/model/App.kt | 62 +++++-- .../vanced/manager/domain/model/AppStatus.kt | 9 - .../com/vanced/manager/domain/model/Data.kt | 6 - .../vanced/manager/domain/pkg/PkgManager.kt | 49 ----- .../manager/domain/util/EntityMapper.kt | 7 - .../com/vanced/manager/network/DataService.kt | 11 -- .../vanced/manager/network/GithubService.kt | 22 +++ .../vanced/manager/network/dto/GithubDto.kt | 25 +++ .../vanced/manager/network/model/AppDto.kt | 16 -- .../manager/network/model/AppDtoMapper.kt | 156 ---------------- .../vanced/manager/network/model/DataDto.kt | 13 -- .../manager/network/model/DataDtoMapper.kt | 26 --- .../vanced/manager/network/util/Constants.kt | 4 +- .../manager/repository/AppRepository.kt | 172 ++++++++++++++++++ .../manager/repository/DataRepository.kt | 9 - .../manager/repository/MainRepository.kt | 14 -- .../manager/repository/MirrorRepository.kt | 14 -- .../repository/PreferenceRepository.kt | 77 ++++++++ .../com/vanced/manager/ui/MainActivity.kt | 19 +- .../vanced/manager/ui/screen/HomeScreen.kt | 71 +++----- .../manager/ui/screen/SettingsScreen.kt | 37 ++-- .../java/com/vanced/manager/ui/theme/Theme.kt | 24 --- .../manager/ui/viewmodel/MainViewModel.kt | 143 ++++++--------- .../manager/ui/viewmodel/SettingsViewModel.kt | 47 +++-- .../com/vanced/manager/ui/widget/AppCard.kt | 35 +++- .../com/vanced/manager/ui/widget/LinkCard.kt | 12 +- build.gradle.kts | 3 +- 45 files changed, 756 insertions(+), 743 deletions(-) delete mode 100644 app/src/main/java/com/vanced/manager/core/preferences/CheckboxPreference.kt delete mode 100644 app/src/main/java/com/vanced/manager/core/preferences/RadioButtonPreference.kt delete mode 100644 app/src/main/java/com/vanced/manager/core/util/Variant.kt create mode 100644 app/src/main/java/com/vanced/manager/datasource/PkgInfoDatasource.kt create mode 100644 app/src/main/java/com/vanced/manager/datasource/PreferenceDatasource.kt create mode 100644 app/src/main/java/com/vanced/manager/di/CustomTabsModule.kt create mode 100644 app/src/main/java/com/vanced/manager/di/DatasourceModule.kt delete mode 100644 app/src/main/java/com/vanced/manager/di/MapperModule.kt delete mode 100644 app/src/main/java/com/vanced/manager/di/PackageManagerModule.kt delete mode 100644 app/src/main/java/com/vanced/manager/di/PreferenceModule.kt delete mode 100644 app/src/main/java/com/vanced/manager/domain/datasource/PackageInformationDataSource.kt delete mode 100644 app/src/main/java/com/vanced/manager/domain/model/AppStatus.kt delete mode 100644 app/src/main/java/com/vanced/manager/domain/model/Data.kt delete mode 100644 app/src/main/java/com/vanced/manager/domain/pkg/PkgManager.kt delete mode 100644 app/src/main/java/com/vanced/manager/domain/util/EntityMapper.kt delete mode 100644 app/src/main/java/com/vanced/manager/network/DataService.kt create mode 100644 app/src/main/java/com/vanced/manager/network/GithubService.kt create mode 100644 app/src/main/java/com/vanced/manager/network/dto/GithubDto.kt delete mode 100644 app/src/main/java/com/vanced/manager/network/model/AppDto.kt delete mode 100644 app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt delete mode 100644 app/src/main/java/com/vanced/manager/network/model/DataDto.kt delete mode 100644 app/src/main/java/com/vanced/manager/network/model/DataDtoMapper.kt create mode 100644 app/src/main/java/com/vanced/manager/repository/AppRepository.kt delete mode 100644 app/src/main/java/com/vanced/manager/repository/DataRepository.kt delete mode 100644 app/src/main/java/com/vanced/manager/repository/MainRepository.kt delete mode 100644 app/src/main/java/com/vanced/manager/repository/MirrorRepository.kt create mode 100644 app/src/main/java/com/vanced/manager/repository/PreferenceRepository.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4b947956c2..1c91716180 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -5,6 +5,7 @@ plugins { id("com.android.application") kotlin("android") id("kotlin-parcelize") + kotlin("plugin.serialization") } val composeVersion = "1.1.1" @@ -93,6 +94,7 @@ val languages: String get() { dependencies { implementation(kotlin("reflect")) + implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2") // AndroidX implementation("androidx.core:core-ktx:1.7.0") @@ -146,6 +148,8 @@ dependencies { implementation("com.squareup.retrofit2:retrofit:$retrofitVersion") implementation("com.squareup.retrofit2:converter-gson:$retrofitVersion") + implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0") + testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.3") androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0") diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index b9f5a5bfa1..a00bb84096 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -12,11 +12,11 @@ # public *; #} --keep class com.vanced.manager.network.model.AppDto { +-keep class com.vanced.manager.network.dto.GithubReleaseDto { *; } --keep class com.vanced.manager.network.model.DataDto { +-keep class com.vanced.manager.network.dto.GithubReleaseAssetDto { *; } diff --git a/app/src/main/java/com/vanced/manager/ManagerApplication.kt b/app/src/main/java/com/vanced/manager/ManagerApplication.kt index eb39aee21f..b22a632e69 100644 --- a/app/src/main/java/com/vanced/manager/ManagerApplication.kt +++ b/app/src/main/java/com/vanced/manager/ManagerApplication.kt @@ -15,12 +15,11 @@ class ManagerApplication : Application() { modules( apiModule, + customTabsModule, + datasourceModule, downloaderModule, installerModule, - mapperModule, networkModule, - packageManagerModule, - preferenceModule, repositoryModule, serviceModule, viewModelModule, diff --git a/app/src/main/java/com/vanced/manager/core/preferences/CheckboxPreference.kt b/app/src/main/java/com/vanced/manager/core/preferences/CheckboxPreference.kt deleted file mode 100644 index ceb47e2fb5..0000000000 --- a/app/src/main/java/com/vanced/manager/core/preferences/CheckboxPreference.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.vanced.manager.core.preferences - -data class CheckboxPreference( - val title: String, - val key: String, -) diff --git a/app/src/main/java/com/vanced/manager/core/preferences/RadioButtonPreference.kt b/app/src/main/java/com/vanced/manager/core/preferences/RadioButtonPreference.kt deleted file mode 100644 index 491b4fbf41..0000000000 --- a/app/src/main/java/com/vanced/manager/core/preferences/RadioButtonPreference.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.vanced.manager.core.preferences - -data class RadioButtonPreference( - val title: String, - val key: String -) diff --git a/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceHolder.kt b/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceHolder.kt index 3da7135c51..9769bbb35d 100644 --- a/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceHolder.kt +++ b/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceHolder.kt @@ -1,20 +1,13 @@ package com.vanced.manager.core.preferences.holder -import com.vanced.manager.core.preferences.managerBooleanPreference -import com.vanced.manager.core.preferences.managerLongPreference import com.vanced.manager.core.preferences.managerStringPreference import com.vanced.manager.core.preferences.managerStringSetPreference -import com.vanced.manager.ui.theme.defAccentColor -var useCustomTabsPref by managerBooleanPreference(USE_CUSTOM_TABS_KEY) var managerVariantPref by managerStringPreference( MANAGER_VARIANT_KEY, MANAGER_VARIANT_DEFAULT_VALUE ) -var managerThemePref by managerStringPreference(MANAGER_THEME_KEY, MANAGER_THEME_DEFAULT_VALUE) -var managerAccentColorPref by managerLongPreference(MANAGER_ACCENT_COLOR_KEY, defAccentColor) - var vancedThemePref by managerStringPreference(APP_VANCED_THEME_KEY, VANCED_THEME_DEFAULT_VALUE) var vancedVersionPref by managerStringPreference(APP_VANCED_VERSION_KEY, APP_VERSION_DEFAULT_VALUE) var vancedLanguagesPref by managerStringSetPreference( @@ -22,7 +15,4 @@ var vancedLanguagesPref by managerStringSetPreference( VANCED_LANGUAGE_DEFAULT_VALUE ) -var musicVersionPref by managerStringPreference(APP_MUSIC_VERSION_KEY, APP_VERSION_DEFAULT_VALUE) - -var vancedEnabled by managerBooleanPreference(VANCED_ENABLED_KEY, APP_ENABLED_DEFAULT_VALUE) -var musicEnabled by managerBooleanPreference(MUSIC_ENABLED_KEY, APP_ENABLED_DEFAULT_VALUE) \ No newline at end of file +var musicVersionPref by managerStringPreference(APP_MUSIC_VERSION_KEY, APP_VERSION_DEFAULT_VALUE) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/util/Variant.kt b/app/src/main/java/com/vanced/manager/core/util/Variant.kt deleted file mode 100644 index 850f40cf9b..0000000000 --- a/app/src/main/java/com/vanced/manager/core/util/Variant.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.vanced.manager.core.util - -enum class Variant { - - Root, Nonroot - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/datasource/PkgInfoDatasource.kt b/app/src/main/java/com/vanced/manager/datasource/PkgInfoDatasource.kt new file mode 100644 index 0000000000..bbcfd0c46a --- /dev/null +++ b/app/src/main/java/com/vanced/manager/datasource/PkgInfoDatasource.kt @@ -0,0 +1,50 @@ +package com.vanced.manager.datasource + +import android.annotation.SuppressLint +import android.content.pm.PackageManager +import android.os.Build + +interface PkgInfoDatasource { + + fun getVersionCode(packageName: String): Int? + + fun getVersionName(packageName: String): String? + +} + +class PkgInfoDatasourceImpl( + private val packageManager: PackageManager +) : PkgInfoDatasource { + + private companion object { + const val FLAG_NOTHING = 0 + const val VERSION_IGNORE_MAJOR = 0xFFFFFFFF + } + + @SuppressLint("WrongConstant") + override fun getVersionCode(packageName: String): Int? { + return try { + val packageInfo = packageManager.getPackageInfo(packageName, FLAG_NOTHING) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + packageInfo.longVersionCode.and(VERSION_IGNORE_MAJOR).toInt() + } else { + @Suppress("DEPRECATION") + packageInfo.versionCode + } + } catch (e: PackageManager.NameNotFoundException) { + null + } + } + + @Suppress("DEPRECATION") + @SuppressLint("WrongConstant") + override fun getVersionName(packageName: String): String? { + return try { + packageManager + .getPackageInfo(packageName, FLAG_NOTHING) + .versionName + } catch (e: PackageManager.NameNotFoundException) { + null + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/datasource/PreferenceDatasource.kt b/app/src/main/java/com/vanced/manager/datasource/PreferenceDatasource.kt new file mode 100644 index 0000000000..7fd5c2fedf --- /dev/null +++ b/app/src/main/java/com/vanced/manager/datasource/PreferenceDatasource.kt @@ -0,0 +1,68 @@ +package com.vanced.manager.datasource + +import android.content.SharedPreferences + +interface PreferenceDatasource { + + var managerUseCustomTabs: Boolean + var managerMode: String + var managerTheme: String + +} + +class PreferenceDatasourceImpl( + private val sharedPreferences: SharedPreferences +) : PreferenceDatasource { + + override var managerUseCustomTabs: Boolean + get() = getBoolean(PreferenceData.MANAGER_USE_CUSTOM_TABS_KEY, PreferenceData.MANAGER_USE_CUSTOM_TABS_DEFAULT_VALUE) + set(value) { + putBoolean(PreferenceData.MANAGER_USE_CUSTOM_TABS_KEY, value) + } + + override var managerMode: String + get() = getString(PreferenceData.MANAGER_MODE_KEY, PreferenceData.MANAGER_MODE_DEFAULT_VALUE) + set(value) { + putString(PreferenceData.MANAGER_MODE_KEY, value) + } + + override var managerTheme: String + get() = getString(PreferenceData.MANAGER_THEME_KEY, PreferenceData.MANAGER_THEME_DEFAULT_VALUE) + set(value) { + putString(PreferenceData.MANAGER_THEME_KEY, value) + } + + private fun getString(key: String, defaultValue: String): String { + return sharedPreferences.getString(key, defaultValue) ?: defaultValue + } + + private fun getBoolean(key: String, defaultValue: Boolean): Boolean { + return sharedPreferences.getBoolean(key, defaultValue) + } + + private fun putString(key: String, value: String) { + sharedPreferences.edit().putString(key, value).apply() + } + + private fun putBoolean(key: String, value: Boolean) { + sharedPreferences.edit().putBoolean(key, value).apply() + } +} + +object PreferenceData { + + const val MANAGER_USE_CUSTOM_TABS_KEY = "manager_behaviour_use_custom_tabs" + const val MANAGER_USE_CUSTOM_TABS_DEFAULT_VALUE = true + + const val MANAGER_MODE_KEY = "manager_behaviour_mode" + const val MANAGER_MODE_VALUE_ROOT = "root" + const val MANAGER_MODE_VALUE_NONROOT= "nonroot" + const val MANAGER_MODE_DEFAULT_VALUE = MANAGER_MODE_VALUE_NONROOT + + const val MANAGER_THEME_KEY = "manager_appearance_theme" + const val MANAGER_THEME_VALUE_LIGHT = "light" + const val MANAGER_THEME_VALUE_DARK = "dark" + const val MANAGER_THEME_VALUE_SYSTEM_DEFAULT = "system_default" + const val MANAGER_THEME_DEFAULT_VALUE = MANAGER_THEME_VALUE_SYSTEM_DEFAULT + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/CustomTabsModule.kt b/app/src/main/java/com/vanced/manager/di/CustomTabsModule.kt new file mode 100644 index 0000000000..ea29dcad00 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/di/CustomTabsModule.kt @@ -0,0 +1,13 @@ +package com.vanced.manager.di + +import androidx.browser.customtabs.CustomTabsIntent +import org.koin.dsl.module + +val customTabsModule = module { + fun provideChromeCustomTabs(): CustomTabsIntent { + return CustomTabsIntent.Builder() + .build() + } + + single { provideChromeCustomTabs() } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/DatasourceModule.kt b/app/src/main/java/com/vanced/manager/di/DatasourceModule.kt new file mode 100644 index 0000000000..9984dff740 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/di/DatasourceModule.kt @@ -0,0 +1,31 @@ +package com.vanced.manager.di + +import android.content.Context +import com.vanced.manager.datasource.PkgInfoDatasource +import com.vanced.manager.datasource.PkgInfoDatasourceImpl +import com.vanced.manager.datasource.PreferenceDatasource +import com.vanced.manager.datasource.PreferenceDatasourceImpl +import org.koin.android.ext.koin.androidContext +import org.koin.dsl.module + +val datasourceModule = module { + + fun providePkgInfoDatasource( + context: Context + ): PkgInfoDatasource { + return PkgInfoDatasourceImpl( + packageManager = context.packageManager + ) + } + + fun providePreferenceDatasource( + context: Context + ): PreferenceDatasource { + return PreferenceDatasourceImpl( + sharedPreferences = context.getSharedPreferences("manager_settings", Context.MODE_PRIVATE) + ) + } + + single { providePkgInfoDatasource(androidContext()) } + single { providePreferenceDatasource(androidContext()) } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/MapperModule.kt b/app/src/main/java/com/vanced/manager/di/MapperModule.kt deleted file mode 100644 index e6a8159cf8..0000000000 --- a/app/src/main/java/com/vanced/manager/di/MapperModule.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.vanced.manager.di - -import android.content.Context -import com.vanced.manager.domain.datasource.PackageInformationDataSource -import com.vanced.manager.network.model.AppDtoMapper -import com.vanced.manager.network.model.DataDtoMapper -import org.koin.dsl.module - -val mapperModule = module { - - fun provideAppMapper( - packageInformationDataSource: PackageInformationDataSource, - context: Context, - ) = AppDtoMapper(packageInformationDataSource, context) - - fun provideJsonMapper( - appDtoMapper: AppDtoMapper - ) = DataDtoMapper(appDtoMapper) - - single { provideAppMapper(get(), get()) } - single { provideJsonMapper(get()) } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/PackageManagerModule.kt b/app/src/main/java/com/vanced/manager/di/PackageManagerModule.kt deleted file mode 100644 index 9c4170b209..0000000000 --- a/app/src/main/java/com/vanced/manager/di/PackageManagerModule.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.vanced.manager.di - -import android.content.Context -import com.vanced.manager.domain.datasource.PackageInformationDataSource -import com.vanced.manager.domain.datasource.PackageInformationDataSourceImpl -import com.vanced.manager.domain.pkg.PkgManager -import com.vanced.manager.domain.pkg.PkgManagerImpl -import org.koin.dsl.module - -val packageManagerModule = module { - - fun providePackageManager( - context: Context - ): PkgManager = - PkgManagerImpl( - packageManager = context.packageManager - ) - - fun providePackageInformationDataSource( - pkgManager: PkgManager - ): PackageInformationDataSource = - PackageInformationDataSourceImpl(pkgManager) - - single { providePackageManager(get()) } - single { providePackageInformationDataSource(get()) } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/PreferenceModule.kt b/app/src/main/java/com/vanced/manager/di/PreferenceModule.kt deleted file mode 100644 index 4c93449474..0000000000 --- a/app/src/main/java/com/vanced/manager/di/PreferenceModule.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.vanced.manager.di - -import android.content.Context -import org.koin.dsl.module - -val preferenceModule = module { - - fun provideDatastore( - context: Context - ) = context.getSharedPreferences("manager_settings", Context.MODE_PRIVATE) - - single { provideDatastore(get()) } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt b/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt index fae09460f5..a58352e36f 100644 --- a/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt +++ b/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt @@ -1,25 +1,31 @@ package com.vanced.manager.di -import com.vanced.manager.network.DataService -import com.vanced.manager.network.model.DataDtoMapper -import com.vanced.manager.repository.DataRepository -import com.vanced.manager.repository.MainRepository -import com.vanced.manager.repository.MirrorRepository -import org.koin.core.qualifier.named +import com.vanced.manager.datasource.PkgInfoDatasource +import com.vanced.manager.datasource.PreferenceDatasource +import com.vanced.manager.network.GithubService +import com.vanced.manager.repository.* import org.koin.dsl.module val repositoryModule = module { - fun provideMainRepository( - dataService: DataService, - dataDtoMapper: DataDtoMapper - ) = MainRepository(dataService, dataDtoMapper) + fun provideGithubRepository( + githubService: GithubService, + pkgInfoDatasource: PkgInfoDatasource + ): AppRepository { + return AppRepositoryImpl( + githubService = githubService, + pkgInfoDatasource = pkgInfoDatasource + ) + } - fun provideMirrorRepository( - dataService: DataService, - dataDtoMapper: DataDtoMapper - ) = MirrorRepository(dataService, dataDtoMapper) + fun providePreferenceRepository( + preferenceDatasource: PreferenceDatasource + ): PreferenceRepository { + return PreferenceRepositoryImpl( + preferenceDatasource = preferenceDatasource + ) + } - single { provideMainRepository(get(named("main")), get()) } - single { provideMirrorRepository(get(named("mirror")), get()) } + single { provideGithubRepository(get(), get()) } + single { providePreferenceRepository(get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/ServiceModule.kt b/app/src/main/java/com/vanced/manager/di/ServiceModule.kt index 5da133f876..c828e70f95 100644 --- a/app/src/main/java/com/vanced/manager/di/ServiceModule.kt +++ b/app/src/main/java/com/vanced/manager/di/ServiceModule.kt @@ -1,35 +1,31 @@ package com.vanced.manager.di -import com.google.gson.GsonBuilder -import com.vanced.manager.network.DataService -import com.vanced.manager.network.util.BASE_GITHUB -import com.vanced.manager.network.util.BASE_MIRROR +import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory +import com.vanced.manager.network.GithubService +import com.vanced.manager.network.util.GITHUB_API_BASE +import kotlinx.serialization.json.Json +import okhttp3.MediaType import okhttp3.OkHttpClient -import org.koin.core.qualifier.named import org.koin.dsl.module import retrofit2.Retrofit -import retrofit2.converter.gson.GsonConverterFactory +import retrofit2.create -val serviceModule = module { +private val json = Json { + ignoreUnknownKeys = true +} - fun provideMainService( - okHttpClient: OkHttpClient - ) = Retrofit.Builder() - .baseUrl(BASE_GITHUB) - .addConverterFactory(GsonConverterFactory.create(GsonBuilder().create())) - .client(okHttpClient) - .build() - .create(DataService::class.java) +val serviceModule = module { - fun provideMirrorService( + fun provideGithubService( okHttpClient: OkHttpClient - ) = Retrofit.Builder() - .baseUrl(BASE_MIRROR) - .addConverterFactory(GsonConverterFactory.create(GsonBuilder().create())) - .client(okHttpClient) - .build() - .create(DataService::class.java) + ): GithubService { + return Retrofit.Builder() + .baseUrl(GITHUB_API_BASE) + .addConverterFactory(json.asConverterFactory(MediaType.get("application/json"))) + .client(okHttpClient) + .build() + .create() + } - single(named("main")) { provideMainService(get()) } - single(named("mirror")) { provideMirrorService(get()) } + single { provideGithubService(get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt index a7e40aca74..8c41131082 100644 --- a/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt +++ b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt @@ -1,16 +1,14 @@ package com.vanced.manager.di import android.app.Application -import android.content.SharedPreferences import com.vanced.manager.core.downloader.impl.MicrogDownloader import com.vanced.manager.core.downloader.impl.MusicDownloader import com.vanced.manager.core.downloader.impl.VancedDownloader import com.vanced.manager.core.installer.impl.MicrogInstaller import com.vanced.manager.core.installer.impl.MusicInstaller import com.vanced.manager.core.installer.impl.VancedInstaller -import com.vanced.manager.repository.DataRepository -import com.vanced.manager.repository.MainRepository -import com.vanced.manager.repository.MirrorRepository +import com.vanced.manager.repository.AppRepository +import com.vanced.manager.repository.PreferenceRepository import com.vanced.manager.ui.viewmodel.ConfigurationViewModel import com.vanced.manager.ui.viewmodel.InstallViewModel import com.vanced.manager.ui.viewmodel.MainViewModel @@ -22,11 +20,16 @@ import org.koin.dsl.module val viewModelModule = module { fun provideMainViewModel( - mainRepository: MainRepository, - mirrorRepository: MirrorRepository, - preferences: SharedPreferences, + appRepository: AppRepository, + preferenceRepository: PreferenceRepository, app: Application, - ) = MainViewModel(mainRepository, mirrorRepository, preferences, app) + ): MainViewModel { + return MainViewModel( + appRepository = appRepository, + preferenceRepository = preferenceRepository, + app = app + ) + } fun provideInstallViewModel( vancedDownloader: VancedDownloader, @@ -42,12 +45,16 @@ val viewModelModule = module { return ConfigurationViewModel() } - fun provideSettingsViewModel(): SettingsViewModel { - return SettingsViewModel() + fun provideSettingsViewModel( + preferenceRepository: PreferenceRepository + ): SettingsViewModel { + return SettingsViewModel( + preferenceRepository = preferenceRepository + ) } - viewModel { provideMainViewModel(get(), get(), get(), androidApplication()) } + viewModel { provideMainViewModel(get(), get(), androidApplication()) } viewModel { provideInstallViewModel(get(), get(), get(), get(), get(), get()) } viewModel { provideConfigurationViewModel() } - viewModel { provideSettingsViewModel() } + viewModel { provideSettingsViewModel(get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/domain/datasource/PackageInformationDataSource.kt b/app/src/main/java/com/vanced/manager/domain/datasource/PackageInformationDataSource.kt deleted file mode 100644 index f0d1ec1679..0000000000 --- a/app/src/main/java/com/vanced/manager/domain/datasource/PackageInformationDataSource.kt +++ /dev/null @@ -1,36 +0,0 @@ -package com.vanced.manager.domain.datasource - -import android.content.pm.PackageManager -import com.vanced.manager.domain.pkg.PkgManager -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext - -interface PackageInformationDataSource { - - suspend fun getVersionCode(packageName: String): Int? - - suspend fun getVersionName(packageName: String): String? -} - -class PackageInformationDataSourceImpl( - private val pkgManager: PkgManager -) : PackageInformationDataSource { - - override suspend fun getVersionCode(packageName: String): Int? = - withContext(Dispatchers.IO) { - try { - pkgManager.getVersionCode(packageName) - } catch (exception: PackageManager.NameNotFoundException) { - null - } - } - - override suspend fun getVersionName(packageName: String): String? = - withContext(Dispatchers.IO) { - try { - pkgManager.getVersionName(packageName) - } catch (exception: PackageManager.NameNotFoundException) { - null - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/domain/model/App.kt b/app/src/main/java/com/vanced/manager/domain/model/App.kt index 82db872ea0..0b5a7c06d3 100644 --- a/app/src/main/java/com/vanced/manager/domain/model/App.kt +++ b/app/src/main/java/com/vanced/manager/domain/model/App.kt @@ -1,18 +1,58 @@ package com.vanced.manager.domain.model +import androidx.annotation.DrawableRes +import com.vanced.manager.R + data class App( val name: String, - val remoteVersion: String, + @DrawableRes val iconResId: Int, + val changelog: String, val remoteVersionCode: Int, - val installedVersion: String?, + val remoteVersionName: String, val installedVersionCode: Int?, - val iconUrl: String?, - val appStatus: AppStatus, + val installedVersionName: String?, val packageName: String, - val changelog: String, - val url: String?, - val versions: List<String>?, - val themes: List<String>?, - val languages: List<String>?, - val installationOptions: List<InstallationOption>? -) \ No newline at end of file + val launchActivity: String, + val state: AppState, + val app: AppType +) + +object AppData { + const val NAME_VANCED_YOUTUBE = "YouTube Vanced" + const val NAME_VANCED_YOUTUBE_MUSIC = "YouTube Vanced Music" + const val NAME_VANCED_MICROG = "Vanced microG" + const val NAME_VANCED_MANAGER = "Vanced Manager" + + const val ICON_VANCED_YOUTUBE = R.drawable.ic_vanced + const val ICON_VANCED_YOUTUBE_MUSIC = R.drawable.ic_music + const val ICON_VANCED_MICROG = R.drawable.ic_microg + const val ICON_VANCED_MANAGER = R.drawable.ic_manager + + const val PACKAGE_VANCED_YOUTUBE = "com.vanced.android.youtube" + const val PACKAGE_VANCED_YOUTUBE_MUSIC = "com.vanced.android.youtube.apps.music" + const val PACKAGE_VANCED_MICROG = "com.mgoogle.android.gms" + const val PACKAGE_VANCED_MANAGER = "com.vanced.manager" + + const val PACKAGE_ROOT_VANCED_YOUTUBE = "com.google.android.youtube" + const val PACKAGE_ROOT_VANCED_YOUTUBE_MUSIC = "com.google.android.youtube.apps.music" + + const val LAUNCH_ACTIVITY_VANCED_YOUTUBE = "com.google.android.youtube.HomeActivity" + const val LAUNCH_ACTIVITY_VANCED_YOUTUBE_MUSIC = "com.google.android.apps.youtube.music.activities.MusicActivity" + const val LAUNCH_ACTIVITY_VANCED_MICROG = "org.microg.gms.ui.SettingsActivity" + const val LAUNCH_ACTIVITY_VANCED_MANAGER = "" +} + +enum class AppType { + VANCED_YOUTUBE, + VANCED_YOUTUBE_MUSIC, + VANCED_MICROG, + VANCED_MANAGER, +} + +enum class AppState { + NOT_INSTALLED, + INSTALLED, + NEEDS_UPDATE +} + + diff --git a/app/src/main/java/com/vanced/manager/domain/model/AppStatus.kt b/app/src/main/java/com/vanced/manager/domain/model/AppStatus.kt deleted file mode 100644 index e0ef6e978c..0000000000 --- a/app/src/main/java/com/vanced/manager/domain/model/AppStatus.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.vanced.manager.domain.model - -enum class AppStatus { - - Install, - Reinstall, - Update, - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/domain/model/Data.kt b/app/src/main/java/com/vanced/manager/domain/model/Data.kt deleted file mode 100644 index 89577d2328..0000000000 --- a/app/src/main/java/com/vanced/manager/domain/model/Data.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.vanced.manager.domain.model - -data class Data( - val manager: App, - val apps: List<App>, -) diff --git a/app/src/main/java/com/vanced/manager/domain/pkg/PkgManager.kt b/app/src/main/java/com/vanced/manager/domain/pkg/PkgManager.kt deleted file mode 100644 index 885dceb3f3..0000000000 --- a/app/src/main/java/com/vanced/manager/domain/pkg/PkgManager.kt +++ /dev/null @@ -1,49 +0,0 @@ -package com.vanced.manager.domain.pkg - -import android.annotation.SuppressLint -import android.content.pm.PackageManager -import android.os.Build - -interface PkgManager { - - @Throws(PackageManager.NameNotFoundException::class) - suspend fun getVersionCode(packageName: String): Int - - @Throws(PackageManager.NameNotFoundException::class) - suspend fun getVersionName(packageName: String): String -} - -class PkgManagerImpl( - private val packageManager: PackageManager -) : PkgManager { - - private companion object { - const val PACKAGE_FLAG_ALL_OFF = 0 - const val MAJOR_IGNORE = 0xFFFFFFFF - } - - @SuppressLint("WrongConstant") - @Suppress("DEPRECATION") - @Throws(PackageManager.NameNotFoundException::class) - override suspend fun getVersionCode( - packageName: String - ) = with(packageManager) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - getPackageInfo(packageName, PACKAGE_FLAG_ALL_OFF) - .longVersionCode - .and(MAJOR_IGNORE) - .toInt() - } else { - getPackageInfo(packageName, PACKAGE_FLAG_ALL_OFF) - .versionCode - } - } - - @SuppressLint("WrongConstant") - @Throws(PackageManager.NameNotFoundException::class) - override suspend fun getVersionName( - packageName: String - ): String = packageManager - .getPackageInfo(packageName, PACKAGE_FLAG_ALL_OFF) - .versionName -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/domain/util/EntityMapper.kt b/app/src/main/java/com/vanced/manager/domain/util/EntityMapper.kt deleted file mode 100644 index e7d847e6b9..0000000000 --- a/app/src/main/java/com/vanced/manager/domain/util/EntityMapper.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.vanced.manager.domain.util - -interface EntityMapper<T, Model> { - - suspend fun mapToModel(entity: T): Model - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/DataService.kt b/app/src/main/java/com/vanced/manager/network/DataService.kt deleted file mode 100644 index a18e50380e..0000000000 --- a/app/src/main/java/com/vanced/manager/network/DataService.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.vanced.manager.network - -import com.vanced.manager.network.model.DataDto -import retrofit2.http.GET - -interface DataService { - - @GET("latest.json") - suspend fun get(): DataDto - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/GithubService.kt b/app/src/main/java/com/vanced/manager/network/GithubService.kt new file mode 100644 index 0000000000..6927d45e8c --- /dev/null +++ b/app/src/main/java/com/vanced/manager/network/GithubService.kt @@ -0,0 +1,22 @@ +package com.vanced.manager.network + +import com.vanced.manager.network.dto.GithubReleaseDto +import retrofit2.http.GET + +private const val REPOS_VANCED = "repos/YTVanced" + +interface GithubService { + + @GET("$REPOS_VANCED/Vanced/releases/latest") + suspend fun getVancedYoutubeRelease(): GithubReleaseDto + + @GET("$REPOS_VANCED/VancedMusic/releases/latest") + suspend fun getVancedYoutubeMusicRelease(): GithubReleaseDto + + @GET("$REPOS_VANCED/VancedMicrog/releases/latest") + suspend fun getVancedMicrogRelease(): GithubReleaseDto + + @GET("$REPOS_VANCED/VancedManager/releases/latest") + suspend fun getVancedManagerRelease(): GithubReleaseDto + +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/dto/GithubDto.kt b/app/src/main/java/com/vanced/manager/network/dto/GithubDto.kt new file mode 100644 index 0000000000..c9ced164ce --- /dev/null +++ b/app/src/main/java/com/vanced/manager/network/dto/GithubDto.kt @@ -0,0 +1,25 @@ +package com.vanced.manager.network.dto + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class GithubReleaseDto( + @SerialName("tag_name") + val tagName: String, + + @SerialName("body") + val body: String, + + @SerialName("assets") + val assets: List<GithubReleaseAssetDto> +) + +@Serializable +data class GithubReleaseAssetDto( + @SerialName("name") + val name: String, + + @SerialName("browser_download_url") + val browserDownloadUrl: String +) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDto.kt b/app/src/main/java/com/vanced/manager/network/model/AppDto.kt deleted file mode 100644 index d1161ca6ba..0000000000 --- a/app/src/main/java/com/vanced/manager/network/model/AppDto.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.vanced.manager.network.model - -import com.google.gson.annotations.SerializedName - -data class AppDto( - @SerializedName("name") val name: String, - @SerializedName("version") val version: String, - @SerializedName("version_code") val versionCode: Int, - @SerializedName("changelog") val changelog: String, - @SerializedName("icon_url") val iconUrl: String, - @SerializedName("package_name") val packageName: String, - @SerializedName("url") val url: String? = null, - @SerializedName("versions") val versions: List<String>? = null, - @SerializedName("themes") val themes: List<String>? = null, - @SerializedName("langs") val languages: List<String>? = null, -) diff --git a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt deleted file mode 100644 index bf11e6ffe7..0000000000 --- a/app/src/main/java/com/vanced/manager/network/model/AppDtoMapper.kt +++ /dev/null @@ -1,156 +0,0 @@ -package com.vanced.manager.network.model - -import android.content.Context -import com.vanced.manager.R -import com.vanced.manager.core.preferences.holder.musicVersionPref -import com.vanced.manager.core.preferences.holder.vancedLanguagesPref -import com.vanced.manager.core.preferences.holder.vancedThemePref -import com.vanced.manager.core.preferences.holder.vancedVersionPref -import com.vanced.manager.domain.datasource.PackageInformationDataSource -import com.vanced.manager.domain.model.App -import com.vanced.manager.domain.model.AppStatus -import com.vanced.manager.domain.model.InstallationOption -import com.vanced.manager.domain.model.InstallationOptionItem -import com.vanced.manager.domain.util.EntityMapper -import com.vanced.manager.network.util.MUSIC_NAME -import com.vanced.manager.network.util.VANCED_NAME -import java.util.* - -class AppDtoMapper( - private val pkgInfoDataSource: PackageInformationDataSource, - private val context: Context -) : EntityMapper<AppDto, App> { - - private val latestVersionRadioButton = - InstallationOptionItem( - displayText = { context.getString(R.string.app_version_dialog_option_latest) }, - key = "latest" - ) - - override suspend fun mapToModel( - entity: AppDto - ) = with(entity) { - val localVersionCode = pkgInfoDataSource.getVersionCode(packageName) - App( - name = name, - remoteVersion = version, - remoteVersionCode = versionCode, - installedVersion = pkgInfoDataSource.getVersionName(packageName), - installedVersionCode = localVersionCode, - appStatus = compareVersionCodes(versionCode, localVersionCode), - packageName = packageName, - iconUrl = iconUrl, - changelog = changelog, - url = url, - versions = versions, - themes = themes, - languages = languages, - installationOptions = getInstallationOptions(name, themes, versions, languages) - ) - } - - private fun compareVersionCodes( - remote: Int?, - local: Int? - ) = if (local != null && remote != null) { - when { - remote > local -> AppStatus.Update - remote <= local -> AppStatus.Reinstall - else -> AppStatus.Install - } - } else { - AppStatus.Install - } - - private fun getInstallationOptions( - appName: String, - appThemes: List<String>?, - appVersions: List<String>?, - appLanguages: List<String>?, - ) : List<InstallationOption>? = when (appName) { - VANCED_NAME -> buildList { - if (appThemes != null) { - add( - InstallationOption.SingleSelect( - titleId = R.string.app_installation_options_theme, - getOption = { vancedThemePref }, - setOption = { - vancedThemePref = it - }, - items = appThemes.map { theme -> - InstallationOptionItem( - displayText = { - theme.replaceFirstChar { - it.titlecase(Locale.getDefault()) - } - }, - key = theme - ) - }, - ) - ) - } - if (appVersions != null) { - add( - InstallationOption.SingleSelect( - titleId = R.string.app_installation_options_version, - getOption = { vancedVersionPref }, - setOption = { - vancedVersionPref = it - }, - items = (appVersions.map { version -> - InstallationOptionItem( - displayText = { "v$version" }, - key = version - ) - } + latestVersionRadioButton).reversed(), - ) - ) - } - if (appLanguages != null) { - add( - InstallationOption.MultiSelect( - titleId = R.string.app_installation_options_language, - getOption = { vancedLanguagesPref }, - addOption = { - vancedLanguagesPref = vancedLanguagesPref + it - }, - removeOption = { - vancedLanguagesPref = vancedLanguagesPref - it - }, - items = appLanguages.map { language -> - InstallationOptionItem( - displayText = { - val locale = Locale(it) - locale.getDisplayName(locale) - }, - key = language - ) - }, - ) - ) - } - } - MUSIC_NAME -> buildList { - if (appVersions != null) { - add( - InstallationOption.SingleSelect( - titleId = R.string.app_installation_options_version, - getOption = { musicVersionPref }, - setOption = { - musicVersionPref = it - }, - items = (appVersions.map { version -> - InstallationOptionItem( - displayText = { "v$version" }, - key = version - ) - } + latestVersionRadioButton).reversed(), - ) - ) - } - - } - else -> null - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/model/DataDto.kt b/app/src/main/java/com/vanced/manager/network/model/DataDto.kt deleted file mode 100644 index 36a3242f1c..0000000000 --- a/app/src/main/java/com/vanced/manager/network/model/DataDto.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.vanced.manager.network.model - -import com.google.gson.annotations.SerializedName - -data class DataDto( - @SerializedName("manager") val manager: AppDto, - @SerializedName("apps") val apps: DataAppDto -) - -data class DataAppDto( - @SerializedName("nonroot") val nonroot: List<AppDto>, - @SerializedName("root") val root: List<AppDto>, -) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/model/DataDtoMapper.kt b/app/src/main/java/com/vanced/manager/network/model/DataDtoMapper.kt deleted file mode 100644 index 479b8cc6a3..0000000000 --- a/app/src/main/java/com/vanced/manager/network/model/DataDtoMapper.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.vanced.manager.network.model - -import com.vanced.manager.core.preferences.holder.managerVariantPref -import com.vanced.manager.domain.model.Data -import com.vanced.manager.domain.util.EntityMapper - -class DataDtoMapper( - private val appDtoMapper: AppDtoMapper -) : EntityMapper<DataDto, Data> { - - override suspend fun mapToModel( - entity: DataDto - ) = with(entity) { - Data( - manager = appDtoMapper.mapToModel(manager), - apps = - if (managerVariantPref == "root") { - apps.root - } else { - apps.nonroot - }.map { appDto -> - appDtoMapper.mapToModel(appDto) - } - ) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/network/util/Constants.kt b/app/src/main/java/com/vanced/manager/network/util/Constants.kt index 71dafac84a..bfffd1f745 100644 --- a/app/src/main/java/com/vanced/manager/network/util/Constants.kt +++ b/app/src/main/java/com/vanced/manager/network/util/Constants.kt @@ -1,8 +1,8 @@ package com.vanced.manager.network.util const val BASE = "https://api.vancedapp.com/api/v1/" -const val BASE_MIRROR = "https://x1nto.github.io/VancedFiles/api/v2/" //TODO -const val BASE_GITHUB = "https://x1nto.github.io/VancedFiles/api/v2/" + +const val GITHUB_API_BASE = "https://api.github.com/" const val VANCED_NAME = "YouTube Vanced" const val MUSIC_NAME = "YouTube Vanced Music" diff --git a/app/src/main/java/com/vanced/manager/repository/AppRepository.kt b/app/src/main/java/com/vanced/manager/repository/AppRepository.kt new file mode 100644 index 0000000000..918a94abce --- /dev/null +++ b/app/src/main/java/com/vanced/manager/repository/AppRepository.kt @@ -0,0 +1,172 @@ +package com.vanced.manager.repository + +import com.vanced.manager.datasource.PkgInfoDatasource +import com.vanced.manager.domain.model.AppData +import com.vanced.manager.domain.model.AppState +import com.vanced.manager.domain.model.AppType +import com.vanced.manager.domain.model.App +import com.vanced.manager.network.GithubService +import com.vanced.manager.network.dto.GithubReleaseDto + +interface AppRepository { + + suspend fun getVancedYoutubeNonroot(): App + + suspend fun getVancedYoutubeRoot(): App + + suspend fun getVancedYoutubeMusicNonroot(): App + + suspend fun getVancedYoutubeMusicRoot(): App + + suspend fun getVancedMicrog(): App + + suspend fun getVancedManager(): App + +} + +class AppRepositoryImpl( + private val githubService: GithubService, + private val pkgInfoDatasource: PkgInfoDatasource, +) : AppRepository { + + override suspend fun getVancedYoutubeNonroot(): App { + val githubRelease = githubService.getVancedYoutubeRelease() + val remoteVersionCode = githubRelease.getVersionCode() + val remoteVersionName = githubRelease.getVersionName() + val installedVersionCode = pkgInfoDatasource.getVersionCode(AppData.PACKAGE_VANCED_YOUTUBE) + val installedVersionName = pkgInfoDatasource.getVersionName(AppData.PACKAGE_VANCED_YOUTUBE) + return App( + name = AppData.NAME_VANCED_YOUTUBE, + iconResId = AppData.ICON_VANCED_YOUTUBE, + changelog = githubRelease.body, + remoteVersionCode = remoteVersionCode, + remoteVersionName = remoteVersionName, + installedVersionCode = installedVersionCode, + installedVersionName = installedVersionName, + packageName = AppData.PACKAGE_VANCED_YOUTUBE, + launchActivity = AppData.LAUNCH_ACTIVITY_VANCED_YOUTUBE, + state = getNoonrotAppState(installedVersionCode, remoteVersionCode), + app = AppType.VANCED_YOUTUBE, + ) + } + + override suspend fun getVancedYoutubeRoot(): App { + val githubRelease = githubService.getVancedYoutubeRelease() + val remoteVersionCode = githubRelease.getVersionCode() + val remoteVersionName = githubRelease.getVersionName() + val installedVersionCode = pkgInfoDatasource.getVersionCode(AppData.PACKAGE_ROOT_VANCED_YOUTUBE) + val installedVersionName = pkgInfoDatasource.getVersionName(AppData.PACKAGE_ROOT_VANCED_YOUTUBE) + return App( + name = AppData.NAME_VANCED_YOUTUBE, + iconResId = AppData.ICON_VANCED_YOUTUBE, + changelog = githubRelease.body, + remoteVersionCode = remoteVersionCode, + remoteVersionName = remoteVersionName, + installedVersionCode = installedVersionCode, + installedVersionName = installedVersionName, + packageName = AppData.PACKAGE_VANCED_YOUTUBE, + launchActivity = AppData.LAUNCH_ACTIVITY_VANCED_YOUTUBE, + state = getNoonrotAppState(installedVersionCode, remoteVersionCode), + app = AppType.VANCED_YOUTUBE, + ) + } + + override suspend fun getVancedYoutubeMusicNonroot(): App { + val githubRelease = githubService.getVancedYoutubeMusicRelease() + val remoteVersionCode = githubRelease.getVersionCode() + val remoteVersionName = githubRelease.getVersionName() + val installedVersionCode = pkgInfoDatasource.getVersionCode(AppData.PACKAGE_VANCED_YOUTUBE_MUSIC) + val installedVersionName = pkgInfoDatasource.getVersionName(AppData.PACKAGE_VANCED_YOUTUBE_MUSIC) + return App( + name = AppData.NAME_VANCED_YOUTUBE_MUSIC, + iconResId = AppData.ICON_VANCED_YOUTUBE_MUSIC, + changelog = githubRelease.body, + remoteVersionCode = remoteVersionCode, + remoteVersionName = remoteVersionName, + installedVersionCode = installedVersionCode, + installedVersionName = installedVersionName, + packageName = AppData.PACKAGE_VANCED_YOUTUBE_MUSIC, + launchActivity = AppData.LAUNCH_ACTIVITY_VANCED_YOUTUBE_MUSIC, + state = getNoonrotAppState(installedVersionCode, remoteVersionCode), + app = AppType.VANCED_YOUTUBE_MUSIC, + ) + } + + override suspend fun getVancedYoutubeMusicRoot(): App { + val githubRelease = githubService.getVancedYoutubeMusicRelease() + val remoteVersionCode = githubRelease.getVersionCode() + val remoteVersionName = githubRelease.getVersionName() + val installedVersionCode = pkgInfoDatasource.getVersionCode(AppData.PACKAGE_ROOT_VANCED_YOUTUBE_MUSIC) + val installedVersionName = pkgInfoDatasource.getVersionName(AppData.PACKAGE_ROOT_VANCED_YOUTUBE_MUSIC) + return App( + name = AppData.NAME_VANCED_YOUTUBE_MUSIC, + iconResId = AppData.ICON_VANCED_YOUTUBE_MUSIC, + changelog = githubRelease.body, + remoteVersionCode = remoteVersionCode, + remoteVersionName = remoteVersionName, + installedVersionCode = installedVersionCode, + installedVersionName = installedVersionName, + packageName = AppData.PACKAGE_VANCED_YOUTUBE_MUSIC, + launchActivity = AppData.LAUNCH_ACTIVITY_VANCED_YOUTUBE_MUSIC, + state = getNoonrotAppState(installedVersionCode, remoteVersionCode), + app = AppType.VANCED_YOUTUBE_MUSIC, + ) + } + + override suspend fun getVancedMicrog(): App { + val githubRelease = githubService.getVancedMicrogRelease() + val remoteVersionCode = githubRelease.getVersionCode() + val remoteVersionName = githubRelease.getVersionName() + val installedVersionCode = pkgInfoDatasource.getVersionCode(AppData.PACKAGE_VANCED_MICROG) + val installedVersionName = pkgInfoDatasource.getVersionName(AppData.PACKAGE_VANCED_MICROG) + return App( + name = AppData.NAME_VANCED_MICROG, + iconResId = AppData.ICON_VANCED_MICROG, + changelog = githubRelease.body, + remoteVersionCode = remoteVersionCode, + remoteVersionName = remoteVersionName, + installedVersionCode = installedVersionCode, + installedVersionName = installedVersionName, + packageName = AppData.PACKAGE_VANCED_MICROG, + launchActivity = AppData.LAUNCH_ACTIVITY_VANCED_MICROG, + state = getNoonrotAppState(installedVersionCode, remoteVersionCode), + app = AppType.VANCED_MICROG, + ) + } + + override suspend fun getVancedManager(): App { + val githubRelease = githubService.getVancedManagerRelease() + val remoteVersionCode = githubRelease.getVersionCode() + val remoteVersionName = githubRelease.getVersionName() + val installedVersionCode = pkgInfoDatasource.getVersionCode(AppData.PACKAGE_VANCED_MANAGER) + val installedVersionName = pkgInfoDatasource.getVersionName(AppData.PACKAGE_VANCED_MANAGER) + return App( + name = AppData.NAME_VANCED_MANAGER, + iconResId = AppData.ICON_VANCED_MANAGER, + changelog = githubRelease.body, + remoteVersionCode = remoteVersionCode, + remoteVersionName = remoteVersionName, + installedVersionCode = installedVersionCode, + installedVersionName = installedVersionName, + packageName = AppData.PACKAGE_VANCED_MANAGER, + launchActivity = AppData.LAUNCH_ACTIVITY_VANCED_MANAGER, + state = getNoonrotAppState(installedVersionCode, remoteVersionCode), + app = AppType.VANCED_MANAGER, + ) + } + + private fun getNoonrotAppState( + installedVersionCode: Int?, + remoteVersionCode: Int + ): AppState { + return when { + installedVersionCode == null -> AppState.NOT_INSTALLED + installedVersionCode < remoteVersionCode -> AppState.NEEDS_UPDATE + installedVersionCode >= remoteVersionCode -> AppState.INSTALLED + else -> AppState.NOT_INSTALLED + } + } + + private fun GithubReleaseDto.getVersionCode() = tagName.substringAfter("-").toInt() + private fun GithubReleaseDto.getVersionName() = tagName.substringBefore("-") +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/repository/DataRepository.kt b/app/src/main/java/com/vanced/manager/repository/DataRepository.kt deleted file mode 100644 index 3879b0a896..0000000000 --- a/app/src/main/java/com/vanced/manager/repository/DataRepository.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.vanced.manager.repository - -import com.vanced.manager.domain.model.Data - -interface DataRepository { - - suspend fun fetch(): Data - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/repository/MainRepository.kt b/app/src/main/java/com/vanced/manager/repository/MainRepository.kt deleted file mode 100644 index eab19bd7d9..0000000000 --- a/app/src/main/java/com/vanced/manager/repository/MainRepository.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.vanced.manager.repository - -import com.vanced.manager.network.DataService -import com.vanced.manager.network.model.DataDtoMapper - -class MainRepository( - private val mainService: DataService, - private val mapper: DataDtoMapper -) : DataRepository { - - override suspend fun fetch() = - mapper.mapToModel(mainService.get()) - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/repository/MirrorRepository.kt b/app/src/main/java/com/vanced/manager/repository/MirrorRepository.kt deleted file mode 100644 index 5f0eb5ed0b..0000000000 --- a/app/src/main/java/com/vanced/manager/repository/MirrorRepository.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.vanced.manager.repository - -import com.vanced.manager.network.DataService -import com.vanced.manager.network.model.DataDtoMapper - -class MirrorRepository( - private val mirrorService: DataService, - private val mapper: DataDtoMapper -) : DataRepository { - - override suspend fun fetch() = - mapper.mapToModel(mirrorService.get()) - -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/repository/PreferenceRepository.kt b/app/src/main/java/com/vanced/manager/repository/PreferenceRepository.kt new file mode 100644 index 0000000000..be9b71d744 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/repository/PreferenceRepository.kt @@ -0,0 +1,77 @@ +package com.vanced.manager.repository + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.runtime.Composable +import com.vanced.manager.datasource.PreferenceData +import com.vanced.manager.datasource.PreferenceDatasource + +interface PreferenceRepository { + + var managerUseCustomTabs: Boolean + var managerMode: ManagerMode + var managerTheme: ManagerTheme + +} + +class PreferenceRepositoryImpl( + private val preferenceDatasource: PreferenceDatasource +) : PreferenceRepository { + + override var managerUseCustomTabs: Boolean + get() = preferenceDatasource.managerUseCustomTabs + set(value) { + preferenceDatasource.managerUseCustomTabs = value + } + + override var managerMode: ManagerMode + get() = ManagerMode.fromValue(preferenceDatasource.managerMode) + set(value) { + preferenceDatasource.managerMode = value.value + } + + override var managerTheme: ManagerTheme + get() = ManagerTheme.fromValue(preferenceDatasource.managerTheme) + set(value) { + preferenceDatasource.managerTheme = value.value + } + +} + + +enum class ManagerTheme(val value: String) { + LIGHT(PreferenceData.MANAGER_THEME_VALUE_LIGHT), + DARK(PreferenceData.MANAGER_THEME_VALUE_DARK), + SYSTEM_DEFAULT(PreferenceData.MANAGER_THEME_VALUE_SYSTEM_DEFAULT); + + @Composable + fun isDark() = when (this) { + LIGHT -> false + DARK -> true + SYSTEM_DEFAULT -> isSystemInDarkTheme() + } + + companion object { + fun fromValue(value: String?): ManagerTheme { + return values().find { + it.value == value + } ?: SYSTEM_DEFAULT + } + } +} + +enum class ManagerMode(val value: String) { + ROOT(PreferenceData.MANAGER_MODE_VALUE_ROOT), + NONROOT(PreferenceData.MANAGER_MODE_VALUE_NONROOT); + + val isRoot get() = this == ROOT + val isNonroot get() = this == NONROOT + + companion object { + fun fromValue(value: String?): ManagerMode { + return when (value) { + "root" -> ROOT + else -> NONROOT + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index fa427e385d..a8882d520b 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -73,12 +73,15 @@ class MainActivity : ComponentActivity() { when (val screen = backStack.last()) { is Screen.Home -> { HomeScreen( - viewModel = mainViewModel, + managerState = mainViewModel.appState, + onRefresh = { + mainViewModel.fetch() + }, onToolbarScreenSelected = { backStack.push(it) }, - onAppDownloadClick = { appName, appVersions, installationOptions -> - if (installationOptions != null) { + onAppDownloadClick = { app -> + /*if (installationOptions != null) { backStack.push( Screen.Configuration( appName, @@ -88,13 +91,13 @@ class MainActivity : ComponentActivity() { ) } else { backStack.push(Screen.Install(appName, appVersions)) - } + }*/ }, - onAppLaunchClick = { appName, packageName -> - mainViewModel.launchApp(appName, packageName) + onAppLaunchClick = { app -> + mainViewModel.launchApp(app.packageName, app.launchActivity) }, - onAppUninstallClick = { packageName -> - mainViewModel.uninstallApp(packageName) + onAppUninstallClick = { app -> + mainViewModel.uninstallApp(app.packageName) } ) } diff --git a/app/src/main/java/com/vanced/manager/ui/screen/HomeScreen.kt b/app/src/main/java/com/vanced/manager/ui/screen/HomeScreen.kt index e3959bb9ea..d97c6911e0 100644 --- a/app/src/main/java/com/vanced/manager/ui/screen/HomeScreen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screen/HomeScreen.kt @@ -15,36 +15,30 @@ import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp -import coil.compose.rememberImagePainter -import coil.request.CachePolicy import com.google.accompanist.swiperefresh.rememberSwipeRefreshState import com.vanced.manager.R import com.vanced.manager.core.util.socialMedia import com.vanced.manager.core.util.sponsors import com.vanced.manager.domain.model.App -import com.vanced.manager.domain.model.InstallationOption import com.vanced.manager.ui.component.* import com.vanced.manager.ui.resource.managerString import com.vanced.manager.ui.util.Screen -import com.vanced.manager.ui.viewmodel.MainViewModel +import com.vanced.manager.ui.viewmodel.ManagerState import com.vanced.manager.ui.widget.AppCard import com.vanced.manager.ui.widget.AppCardPlaceholder import com.vanced.manager.ui.widget.LinkCard @Composable fun HomeScreen( - viewModel: MainViewModel, + managerState: ManagerState, + onRefresh: () -> Unit, onToolbarScreenSelected: (Screen) -> Unit, - onAppDownloadClick: ( - appName: String, - appVersions: List<String>?, - installationOptions: List<InstallationOption>? - ) -> Unit, - onAppUninstallClick: (appPackage: String) -> Unit, - onAppLaunchClick: (appName: String, appPackage: String) -> Unit, + onAppDownloadClick: (App) -> Unit, + onAppUninstallClick: (App) -> Unit, + onAppLaunchClick: (App) -> Unit, ) { val refreshState = - rememberSwipeRefreshState(isRefreshing = viewModel.appState.isFetching) + rememberSwipeRefreshState(isRefreshing = managerState.isFetching) var menuExpanded by remember { mutableStateOf(false) } val dropdownScreens = remember { listOf(Screen.Settings, Screen.About) } @@ -68,24 +62,24 @@ fun HomeScreen( .fillMaxSize() .padding(paddingValues), swipeRefreshState = refreshState, - onRefresh = { viewModel.fetch() } + onRefresh = onRefresh ) { AnimatedContent( modifier = Modifier.fillMaxSize(), - targetState = viewModel.appState, + targetState = managerState, transitionSpec = { scaleIn(initialScale = 0.9f) + fadeIn() with scaleOut(targetScale = 0.9f) + fadeOut() } ) { animatedAppState -> when (animatedAppState) { - is StateFetching -> { + is ManagerState.Fetching -> { HomeScreenLoading( modifier = Modifier.fillMaxSize(), appsCount = animatedAppState.placeholderAppsCount ) } - is StateSuccess -> { + is ManagerState.Success -> { HomeScreenLoaded( modifier = Modifier.fillMaxSize(), apps = animatedAppState.apps, @@ -94,7 +88,7 @@ fun HomeScreen( onAppLaunchClick = onAppLaunchClick ) } - is StateError -> { + is ManagerState.Error -> { //TODO } } @@ -103,10 +97,6 @@ fun HomeScreen( } } -typealias StateFetching = MainViewModel.AppState.Fetching -typealias StateSuccess = MainViewModel.AppState.Success -typealias StateError = MainViewModel.AppState.Error - @Composable private fun HomeScreenTopBar( menuExpanded: Boolean, @@ -150,49 +140,34 @@ private fun HomeScreenTopBar( private fun HomeScreenLoaded( modifier: Modifier = Modifier, apps: List<App>, - onAppDownloadClick: ( - appName: String, - appVersions: List<String>?, - installationOptions: List<InstallationOption>? - ) -> Unit, - onAppUninstallClick: (appPackage: String) -> Unit, - onAppLaunchClick: (appName: String, appPackage: String) -> Unit, + onAppDownloadClick: (App) -> Unit, + onAppUninstallClick: (App) -> Unit, + onAppLaunchClick: (App) -> Unit, ) { HomeScreenBody(modifier = modifier) { managerCategory(categoryName = { managerString(R.string.home_category_apps) }) { items(apps) { app -> - val appIcon = rememberImagePainter(app.iconUrl) { - diskCachePolicy(CachePolicy.ENABLED) - } + val appIcon = painterResource(id = app.iconResId) var showAppInfoDialog by remember { mutableStateOf(false) } AppCard( - modifier = Modifier - .fillMaxWidth(), + modifier = Modifier.fillMaxWidth(), appName = app.name, appIcon = appIcon, - appInstalledVersion = app.installedVersion, - appRemoteVersion = app.remoteVersion, + appInstalledVersion = app.installedVersionName, + appRemoteVersion = app.remoteVersionName, + appState = app.state, onAppDownloadClick = { - onAppDownloadClick( - app.name, - app.versions, - app.installationOptions - ) + onAppDownloadClick(app) }, onAppUninstallClick = { - onAppUninstallClick( - app.packageName - ) + onAppUninstallClick(app) }, onAppLaunchClick = { - onAppLaunchClick( - app.name, - app.packageName, - ) + onAppLaunchClick(app) }, onAppInfoClick = { showAppInfoDialog = true diff --git a/app/src/main/java/com/vanced/manager/ui/screen/SettingsScreen.kt b/app/src/main/java/com/vanced/manager/ui/screen/SettingsScreen.kt index 0a94efd5e6..9f0d081fda 100644 --- a/app/src/main/java/com/vanced/manager/ui/screen/SettingsScreen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screen/SettingsScreen.kt @@ -11,12 +11,11 @@ import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import com.vanced.manager.R -import com.vanced.manager.core.preferences.holder.managerThemePref -import com.vanced.manager.core.preferences.holder.managerVariantPref import com.vanced.manager.core.util.isMagiskInstalled +import com.vanced.manager.repository.ManagerMode +import com.vanced.manager.repository.ManagerTheme import com.vanced.manager.ui.component.* import com.vanced.manager.ui.resource.managerString -import com.vanced.manager.ui.theme.ManagerTheme import com.vanced.manager.ui.util.Screen import com.vanced.manager.ui.viewmodel.SettingsViewModel import org.koin.androidx.compose.viewModel @@ -60,13 +59,13 @@ fun SettingsScreen( preferenceDescription = stringResource(id = R.string.settings_preference_use_custom_tabs_summary), isChecked = viewModel.managerUseCustomTabs, onCheckedChange = { - viewModel.managerUseCustomTabs = it + viewModel.saveManagerUseCustomTabs(it) } ) } item { var showDialog by remember { mutableStateOf(false) } - var selectedMode by remember { mutableStateOf(EntryValue(viewModel.managerMode)) } + var selectedMode by remember { mutableStateOf(EntryValue(viewModel.managerMode.value)) } ManagerSingleSelectDialogPreference( preferenceTitle = managerString( stringId = R.string.settings_preference_variant_title @@ -83,7 +82,7 @@ fun SettingsScreen( }, onDismissRequest = { showDialog = false - selectedMode = EntryValue(managerVariantPref) + selectedMode = EntryValue(viewModel.managerMode.value) }, onEntrySelect = { if (it.value == "root" && !isMagiskInstalled) @@ -92,7 +91,7 @@ fun SettingsScreen( selectedMode = it }, onSave = { - viewModel.managerMode = selectedMode.value + viewModel.saveManagerMode(ManagerMode.fromValue(selectedMode.value)) showDialog = false } ) @@ -103,36 +102,38 @@ fun SettingsScreen( }) { item { var showDialog by remember { mutableStateOf(false) } - var selectedTheme by remember { mutableStateOf(EntryValue(managerThemePref)) } + var selectedTheme by remember { mutableStateOf(EntryValue(viewModel.managerTheme.value)) } ManagerSingleSelectDialogPreference( preferenceTitle = managerString(stringId = R.string.settings_preference_theme_title), preferenceDescription = managerString( - stringId = viewModel.getThemeStringIdByValue(selectedTheme.value) + stringId = viewModel.getThemeStringId( + ManagerTheme.fromValue(selectedTheme.value) + ) ), showDialog = showDialog, selected = selectedTheme, entries = mapOf( - EntryText(managerString(viewModel.getThemeStringIdByValue(SettingsViewModel.THEME_LIGHT_VALUE))) to - EntryValue(SettingsViewModel.THEME_LIGHT_VALUE), - EntryText(managerString(viewModel.getThemeStringIdByValue(SettingsViewModel.THEME_DARK_VALUE))) to - EntryValue(SettingsViewModel.THEME_DARK_VALUE), - EntryText(managerString(viewModel.getThemeStringIdByValue(SettingsViewModel.THEME_SYSTEM_DEFAULT_VALUE))) to - EntryValue(SettingsViewModel.THEME_SYSTEM_DEFAULT_VALUE), + EntryText(managerString(viewModel.getThemeStringId(ManagerTheme.LIGHT))) + to EntryValue(ManagerTheme.LIGHT.value), + EntryText(managerString(viewModel.getThemeStringId(ManagerTheme.DARK))) + to EntryValue(ManagerTheme.DARK.value), + EntryText(managerString(viewModel.getThemeStringId(ManagerTheme.SYSTEM_DEFAULT))) + to EntryValue(ManagerTheme.SYSTEM_DEFAULT.value), ), onClick = { showDialog = true }, onDismissRequest = { showDialog = false - selectedTheme = EntryValue(viewModel.managerTheme) + selectedTheme = EntryValue(viewModel.managerTheme.value) }, onEntrySelect = { selectedTheme = it }, onSave = { - viewModel.managerTheme = selectedTheme.value showDialog = false - onThemeChange(ManagerTheme.fromKey(selectedTheme.value)) + viewModel.saveManagerTheme(ManagerTheme.fromValue(selectedTheme.value)) + onThemeChange(ManagerTheme.fromValue(selectedTheme.value)) } ) } diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt index 8eb0a3c2f7..683ba4811f 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt @@ -8,7 +8,6 @@ import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.platform.LocalContext -import com.vanced.manager.ui.viewmodel.SettingsViewModel const val defAccentColor = 0xFF0477E1 @@ -67,29 +66,6 @@ private val DarkThemeColors = darkColorScheme( inverseSurface = md_theme_dark_inverseSurface, ) -enum class ManagerTheme { - LIGHT, - DARK, - SYSTEM_DEFAULT; - - @Composable - fun isDark() = when (this) { - LIGHT -> false - DARK -> true - SYSTEM_DEFAULT -> isSystemInDarkTheme() - } - - companion object { - fun fromKey(key: String?): ManagerTheme { - return when (key) { - SettingsViewModel.THEME_DARK_VALUE -> DARK - SettingsViewModel.THEME_LIGHT_VALUE -> LIGHT - else -> SYSTEM_DEFAULT - } - } - } -} - @Composable inline fun apiDependantColorScheme( dynamic: () -> ColorScheme, diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt index a028799eca..8292a840a2 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt @@ -1,95 +1,84 @@ package com.vanced.manager.ui.viewmodel import android.app.Application -import android.content.ActivityNotFoundException import android.content.ComponentName import android.content.Intent -import android.content.SharedPreferences -import android.util.Log import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.viewModelScope import com.vanced.manager.core.installer.util.PM -import com.vanced.manager.core.preferences.holder.managerVariantPref import com.vanced.manager.domain.model.App -import com.vanced.manager.network.util.MICROG_NAME -import com.vanced.manager.network.util.MUSIC_NAME -import com.vanced.manager.network.util.VANCED_NAME -import com.vanced.manager.repository.MainRepository -import com.vanced.manager.repository.MirrorRepository -import com.vanced.manager.ui.theme.ManagerTheme +import com.vanced.manager.repository.* +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitAll import kotlinx.coroutines.launch +import kotlinx.coroutines.supervisorScope +import retrofit2.HttpException class MainViewModel( - private val mainRepository: MainRepository, - private val mirrorRepository: MirrorRepository, - private val preferences: SharedPreferences, + private val appRepository: AppRepository, + private val preferenceRepository: PreferenceRepository, private val app: Application, ) : AndroidViewModel(app) { - private val isRoot - get() = managerVariantPref == "root" + var appMode by mutableStateOf(preferenceRepository.managerMode) + var appTheme by mutableStateOf(preferenceRepository.managerTheme) - private val appCount: Int - get() = if (isRoot) 2 else 3 - - sealed class AppState { - data class Fetching(val placeholderAppsCount: Int) : AppState() - data class Success(val apps: List<App>) : AppState() - data class Error(val error: String) : AppState() - - val isFetching get() = this is Fetching - val isSuccess get() = this is Success - val isError get() = this is Error - } + private val appCount + get() = when (appMode) { + ManagerMode.ROOT -> 2 + ManagerMode.NONROOT -> 3 + } - var appState by mutableStateOf<AppState>(AppState.Fetching(appCount)) + var appState by mutableStateOf<ManagerState>(ManagerState.Fetching(appCount)) private set - var appTheme by mutableStateOf( - ManagerTheme.fromKey( - preferences.getString( - SettingsViewModel.MANAGER_THEME_KEY, - SettingsViewModel.THEME_SYSTEM_DEFAULT_VALUE - ) - ) - ) - fun fetch() { viewModelScope.launch { - appState = AppState.Fetching(appCount) - - fetchData() + try { + supervisorScope { + appState = ManagerState.Fetching(appCount) + + when (appMode) { + ManagerMode.ROOT -> { + appState = ManagerState.Success( + apps = listOf( + async { appRepository.getVancedYoutubeRoot() }, + async { appRepository.getVancedYoutubeMusicRoot() } + ).awaitAll() + ) + } + ManagerMode.NONROOT -> { + appState = ManagerState.Success( + apps = listOf( + async { appRepository.getVancedYoutubeNonroot() }, + async { appRepository.getVancedYoutubeMusicNonroot() }, + async { appRepository.getVancedMicrog() } + ).awaitAll() + ) + } + } + } + } catch (e: HttpException) { + appState = ManagerState.Error(e.message()) + } catch (e: Exception) { + appState = ManagerState.Error(e.toString()) + } } } fun launchApp( - appName: String, - appPackage: String, + packageName: String, + launchActivity: String ) { - val component = ComponentName( - /* pkg = */ appPackage, - /* cls = */ when (appName) { - VANCED_NAME -> "com.google.android.youtube.HomeActivity" - MUSIC_NAME -> "com.google.android.apps.youtube.music.activities.MusicActivity" - MICROG_NAME -> "org.microg.gms.ui.SettingsActivity" - else -> throw IllegalArgumentException("$appName is not a valid app") - } - ) - - try { - app.startActivity( - Intent().apply { - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - setComponent(component) - } - ) - } catch (e: ActivityNotFoundException) { - Log.d(TAG, "Unable to launch $appName") - e.printStackTrace() + val component = ComponentName(packageName, launchActivity) + val intent = Intent().apply { + setComponent(component) + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) } + app.startActivity(intent) } //TODO implement root uninstallation @@ -99,28 +88,14 @@ class MainViewModel( PM.uninstallPackage(appPackage, app) } - private suspend fun fetchData( - fromMirror: Boolean = false - ) { - try { - val repository = if (fromMirror) mirrorRepository else mainRepository - with(repository.fetch()) { - appState = AppState.Success(apps) - } - } catch (e: Exception) { - if (!fromMirror) { - fetchData(true) - return - } +} - val error = "failed to fetch: \n${e.stackTraceToString()}" - appState = AppState.Error(error) - Log.d(TAG, error) - } - } - - companion object { - const val TAG = "MainViewModel" - } +sealed class ManagerState { + data class Fetching(val placeholderAppsCount: Int) : ManagerState() + data class Success(val apps: List<App>) : ManagerState() + data class Error(val error: String) : ManagerState() + val isFetching get() = this is Fetching + val isSuccess get() = this is Success + val isError get() = this is Error } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/SettingsViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/SettingsViewModel.kt index 7623e99639..807bb31a48 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/SettingsViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/SettingsViewModel.kt @@ -1,29 +1,46 @@ package com.vanced.manager.ui.viewmodel +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel import com.vanced.manager.R import com.vanced.manager.core.preferences.managerBooleanPreference import com.vanced.manager.core.preferences.managerStringPreference +import com.vanced.manager.repository.ManagerMode +import com.vanced.manager.repository.ManagerTheme +import com.vanced.manager.repository.PreferenceRepository -class SettingsViewModel : ViewModel() { +class SettingsViewModel( + private val preferenceRepository: PreferenceRepository +) : ViewModel() { - companion object { - const val MANAGER_THEME_KEY = "manager_theme" - const val MANAGER_MODE_KEY = "manager_mode" - - const val THEME_DARK_VALUE = "dark" - const val THEME_LIGHT_VALUE = "light" - const val THEME_SYSTEM_DEFAULT_VALUE = "system_default" + var managerUseCustomTabs by mutableStateOf(preferenceRepository.managerUseCustomTabs) + private set + var managerMode by mutableStateOf(preferenceRepository.managerMode) + private set + var managerTheme by mutableStateOf(preferenceRepository.managerTheme) + private set + + fun saveManagerUseCustomTabs(value: Boolean) { + managerUseCustomTabs = value + preferenceRepository.managerUseCustomTabs = value + } + + fun saveManagerMode(value: ManagerMode) { + managerMode = value + preferenceRepository.managerMode = value + } + + fun saveManagerTheme(value: ManagerTheme) { + managerTheme = value + preferenceRepository.managerTheme = value } - var managerUseCustomTabs by managerBooleanPreference(key = "manager_use_custom_tabs") - var managerMode by managerStringPreference(key = MANAGER_MODE_KEY, defaultValue = "nonroot") - var managerTheme by managerStringPreference(MANAGER_THEME_KEY, THEME_SYSTEM_DEFAULT_VALUE) - - fun getThemeStringIdByValue(value: String): Int { + fun getThemeStringId(value: ManagerTheme): Int { return when (value) { - THEME_DARK_VALUE -> R.string.settings_preference_theme_dark - THEME_LIGHT_VALUE -> R.string.settings_preference_theme_light + ManagerTheme.DARK -> R.string.settings_preference_theme_dark + ManagerTheme.LIGHT -> R.string.settings_preference_theme_light else -> R.string.settings_option_system_default } } diff --git a/app/src/main/java/com/vanced/manager/ui/widget/AppCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/AppCard.kt index 93da10c2a2..63a79eccd9 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/AppCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/AppCard.kt @@ -5,9 +5,7 @@ import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Info -import androidx.compose.material.icons.rounded.DeleteForever -import androidx.compose.material.icons.rounded.Download -import androidx.compose.material.icons.rounded.Launch +import androidx.compose.material.icons.rounded.* import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -15,13 +13,14 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.composed import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import coil.compose.ImagePainter import com.google.accompanist.placeholder.PlaceholderHighlight import com.google.accompanist.placeholder.placeholder import com.google.accompanist.placeholder.shimmer import com.vanced.manager.R +import com.vanced.manager.domain.model.AppState import com.vanced.manager.ui.component.ManagerElevatedCard import com.vanced.manager.ui.component.ManagerListItem import com.vanced.manager.ui.component.ManagerText @@ -34,9 +33,10 @@ import com.vanced.manager.ui.util.DefaultContentPaddingVertical @Composable fun AppCard( appName: String, - appIcon: ImagePainter, + appIcon: Painter, appInstalledVersion: String?, appRemoteVersion: String?, + appState: AppState, onAppDownloadClick: () -> Unit, onAppUninstallClick: () -> Unit, onAppLaunchClick: () -> Unit, @@ -101,10 +101,27 @@ fun AppCard( } } IconButton(onClick = onAppDownloadClick) { - Icon( - imageVector = Icons.Rounded.Download, - contentDescription = "Install", - ) + when (appState) { + AppState.NOT_INSTALLED -> { + Icon( + imageVector = Icons.Rounded.GetApp, + contentDescription = "Install", + ) + } + AppState.INSTALLED -> { + Icon( + imageVector = Icons.Rounded.GetApp, + contentDescription = "Install", + ) + } + AppState.NEEDS_UPDATE -> { + Icon( + imageVector = Icons.Rounded.Update, + contentDescription = "Update", + ) + } + } + } } ) diff --git a/app/src/main/java/com/vanced/manager/ui/widget/LinkCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/LinkCard.kt index 3af59e1b1c..7a97ff5a3b 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/LinkCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/LinkCard.kt @@ -1,6 +1,5 @@ package com.vanced.manager.ui.widget -import android.content.Intent import android.net.Uri import androidx.browser.customtabs.CustomTabsIntent import androidx.compose.foundation.layout.* @@ -13,11 +12,11 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.unit.dp -import com.vanced.manager.core.preferences.holder.useCustomTabsPref import com.vanced.manager.ui.component.ManagerElevatedCard import com.vanced.manager.ui.component.ManagerText import com.vanced.manager.ui.util.DefaultContentPaddingHorizontal import com.vanced.manager.ui.util.DefaultContentPaddingVertical +import org.koin.androidx.compose.inject //TODO this composable should not handle opening links @Composable @@ -28,19 +27,14 @@ fun LinkCard( modifier: Modifier = Modifier ) { val context = LocalContext.current - val customTabs = remember { CustomTabsIntent.Builder().build() } + val customTabs: CustomTabsIntent by inject() val uri = remember { Uri.parse(url) } - val intent = remember { Intent(Intent.ACTION_VIEW, uri) } ManagerElevatedCard( modifier = modifier .height(100.dp) .widthIn(min = 100.dp), onClick = { - if (useCustomTabsPref) { - customTabs.launchUrl(context, uri) - } else { - context.startActivity(intent) - } + customTabs.launchUrl(context, uri) } ) { Box( diff --git a/build.gradle.kts b/build.gradle.kts index 480ec660e0..90bbc909db 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,7 +7,8 @@ buildscript { val kotlinVersion = "1.6.10" dependencies { classpath("com.android.tools.build:gradle:7.1.2") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") + classpath(kotlin("gradle-plugin", version = kotlinVersion)) + classpath(kotlin("serialization", version = kotlinVersion)) } } From 0b590fd0e98c21f8556092c3e73035e2be1ee3f9 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Tue, 1 Mar 2022 20:23:31 +0400 Subject: [PATCH 113/118] organize di modules --- .../java/com/vanced/manager/di/APIModule.kt | 37 +++++++++++-------- .../com/vanced/manager/di/CustomTabsModule.kt | 1 + .../com/vanced/manager/di/DownloaderModule.kt | 28 +++++++++++--- .../com/vanced/manager/di/InstallerModuke.kt | 25 ++++++++++--- .../com/vanced/manager/di/NetworkModule.kt | 6 ++- .../com/vanced/manager/di/ViewModelModule.kt | 12 +++++- 6 files changed, 79 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/di/APIModule.kt b/app/src/main/java/com/vanced/manager/di/APIModule.kt index bddadd8995..0ac77bcc22 100644 --- a/app/src/main/java/com/vanced/manager/di/APIModule.kt +++ b/app/src/main/java/com/vanced/manager/di/APIModule.kt @@ -7,33 +7,40 @@ import com.vanced.manager.network.util.BASE import okhttp3.OkHttpClient import org.koin.dsl.module import retrofit2.Retrofit +import retrofit2.create //TODO Add mirror support val apiModule = module { fun provideVancedAPI( okHttpClient: OkHttpClient - ) = Retrofit.Builder() - .baseUrl(BASE) - .client(okHttpClient) - .build() - .create(VancedAPI::class.java) + ): VancedAPI { + return Retrofit.Builder() + .baseUrl(BASE) + .client(okHttpClient) + .build() + .create() + } fun provideMusicAPI( okHttpClient: OkHttpClient - ) = Retrofit.Builder() - .baseUrl(BASE) - .client(okHttpClient) - .build() - .create(MusicAPI::class.java) + ): MusicAPI { + return Retrofit.Builder() + .baseUrl(BASE) + .client(okHttpClient) + .build() + .create() + } fun provideMicrogAPI( okHttpClient: OkHttpClient - ) = Retrofit.Builder() - .baseUrl("https://github.com/YTVanced/VancedMicroG/") - .client(okHttpClient) - .build() - .create(MicrogAPI::class.java) + ): MicrogAPI { + return Retrofit.Builder() + .baseUrl("https://github.com/YTVanced/VancedMicroG/") + .client(okHttpClient) + .build() + .create(MicrogAPI::class.java) + } single { provideVancedAPI(get()) } single { provideMusicAPI(get()) } diff --git a/app/src/main/java/com/vanced/manager/di/CustomTabsModule.kt b/app/src/main/java/com/vanced/manager/di/CustomTabsModule.kt index ea29dcad00..ac552d20c3 100644 --- a/app/src/main/java/com/vanced/manager/di/CustomTabsModule.kt +++ b/app/src/main/java/com/vanced/manager/di/CustomTabsModule.kt @@ -4,6 +4,7 @@ import androidx.browser.customtabs.CustomTabsIntent import org.koin.dsl.module val customTabsModule = module { + fun provideChromeCustomTabs(): CustomTabsIntent { return CustomTabsIntent.Builder() .build() diff --git a/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt b/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt index c9f093b62a..642e9bccbd 100644 --- a/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt +++ b/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt @@ -7,6 +7,7 @@ import com.vanced.manager.core.downloader.api.VancedAPI import com.vanced.manager.core.downloader.impl.MicrogDownloader import com.vanced.manager.core.downloader.impl.MusicDownloader import com.vanced.manager.core.downloader.impl.VancedDownloader +import org.koin.android.ext.koin.androidContext import org.koin.dsl.module val downloaderModule = module { @@ -14,19 +15,34 @@ val downloaderModule = module { fun provideVancedDownloader( vancedAPI: VancedAPI, context: Context, - ) = VancedDownloader(vancedAPI, context) + ): VancedDownloader { + return VancedDownloader( + vancedAPI = vancedAPI, + context = context + ) + } fun provideMusicDownloader( musicAPI: MusicAPI, context: Context, - ) = MusicDownloader(musicAPI, context) + ): MusicDownloader { + return MusicDownloader( + musicAPI = musicAPI, + context = context + ) + } fun provideMicrogDownloader( microgAPI: MicrogAPI, context: Context, - ) = MicrogDownloader(microgAPI, context) + ): MicrogDownloader { + return MicrogDownloader( + microgAPI = microgAPI, + context = context + ) + } - single { provideVancedDownloader(get(), get()) } - single { provideMusicDownloader(get(), get()) } - single { provideMicrogDownloader(get(), get()) } + single { provideVancedDownloader(get(), androidContext()) } + single { provideMusicDownloader(get(), androidContext()) } + single { provideMicrogDownloader(get(), androidContext()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt b/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt index 7c90797c1c..31f6f43af8 100644 --- a/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt +++ b/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt @@ -4,23 +4,36 @@ import android.content.Context import com.vanced.manager.core.installer.impl.MicrogInstaller import com.vanced.manager.core.installer.impl.MusicInstaller import com.vanced.manager.core.installer.impl.VancedInstaller +import org.koin.android.ext.koin.androidContext import org.koin.dsl.module val installerModule = module { fun provideVancedInstaller( context: Context - ) = VancedInstaller(context) + ): VancedInstaller { + return VancedInstaller( + context = context + ) + } fun provideMusicInstaller( context: Context - ) = MusicInstaller(context) + ): MusicInstaller { + return MusicInstaller( + context = context + ) + } fun provideMicrogInstaller( context: Context - ) = MicrogInstaller(context) + ): MicrogInstaller { + return MicrogInstaller( + context = context + ) + } - single { provideVancedInstaller(get()) } - single { provideMusicInstaller(get()) } - single { provideMicrogInstaller(get()) } + single { provideVancedInstaller(androidContext()) } + single { provideMusicInstaller(androidContext()) } + single { provideMicrogInstaller(androidContext()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/NetworkModule.kt b/app/src/main/java/com/vanced/manager/di/NetworkModule.kt index 94a901075f..bf3545b918 100644 --- a/app/src/main/java/com/vanced/manager/di/NetworkModule.kt +++ b/app/src/main/java/com/vanced/manager/di/NetworkModule.kt @@ -5,8 +5,10 @@ import org.koin.dsl.module val networkModule = module { - fun provideOkHttpClient() = - OkHttpClient() + fun provideOkHttpClient(): OkHttpClient { + return OkHttpClient.Builder() + .build() + } single { provideOkHttpClient() } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt index 8c41131082..2119b9eced 100644 --- a/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt +++ b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt @@ -39,7 +39,17 @@ val viewModelModule = module { vancedInstaller: VancedInstaller, musicInstaller: MusicInstaller, microgInstaller: MicrogInstaller, - ) = InstallViewModel(vancedDownloader, musicDownloader, microgDownloader, vancedInstaller, musicInstaller, microgInstaller) + ): InstallViewModel { + return InstallViewModel( + vancedDownloader = vancedDownloader, + musicDownloader = musicDownloader, + microgDownloader = microgDownloader, + + vancedInstaller = vancedInstaller, + musicInstaller = musicInstaller, + microgInstaller = microgInstaller + ) + } fun provideConfigurationViewModel(): ConfigurationViewModel { return ConfigurationViewModel() From d192c967d526aca8c060721a56305f4ec09b22a5 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Wed, 2 Mar 2022 00:20:50 +0400 Subject: [PATCH 114/118] convert installation option to sealed interface --- .../vanced/manager/domain/model/InstallationOption.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/vanced/manager/domain/model/InstallationOption.kt b/app/src/main/java/com/vanced/manager/domain/model/InstallationOption.kt index 4f7471d031..0900856732 100644 --- a/app/src/main/java/com/vanced/manager/domain/model/InstallationOption.kt +++ b/app/src/main/java/com/vanced/manager/domain/model/InstallationOption.kt @@ -3,10 +3,10 @@ package com.vanced.manager.domain.model import android.os.Parcelable import kotlinx.parcelize.Parcelize -sealed class InstallationOption : Parcelable { +sealed interface InstallationOption : Parcelable { - abstract val titleId: Int - abstract val items: List<InstallationOptionItem> + val titleId: Int + val items: List<InstallationOptionItem> @Parcelize data class MultiSelect( @@ -15,7 +15,7 @@ sealed class InstallationOption : Parcelable { val getOption: () -> Set<String>, val addOption: (String) -> Unit, val removeOption: (String) -> Unit - ) : InstallationOption() + ) : InstallationOption @Parcelize data class SingleSelect( @@ -23,7 +23,7 @@ sealed class InstallationOption : Parcelable { override val items: List<InstallationOptionItem>, val getOption: () -> String, val setOption: (String) -> Unit, - ) : InstallationOption() + ) : InstallationOption } From e010ed0e806044017475f5f1c662ad26eb83443f Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Wed, 2 Mar 2022 15:24:22 +0400 Subject: [PATCH 115/118] package refactor --- app/src/main/AndroidManifest.xml | 4 +- .../manager/core/util/AppNotifications.kt | 21 ------ .../vanced/manager/core/util/AppPackages.kt | 7 -- .../java/com/vanced/manager/core/util/Arch.kt | 9 --- .../vanced/manager/core/util/SocialLinks.kt | 61 ----------------- .../java/com/vanced/manager/di/APIModule.kt | 6 +- .../com/vanced/manager/di/DatasourceModule.kt | 13 ++-- .../com/vanced/manager/di/DownloaderModule.kt | 12 ++-- .../com/vanced/manager/di/InstallerModuke.kt | 6 +- .../com/vanced/manager/di/RepositoryModule.kt | 9 ++- .../com/vanced/manager/di/ViewModelModule.kt | 12 ++-- .../com/vanced/manager/domain/model/App.kt | 3 +- .../com/vanced/manager/domain/model/Link.kt | 9 --- .../domain/model/NotificationPrefModel.kt | 6 -- .../{core => }/downloader/api/MicrogAPI.kt | 2 +- .../{core => }/downloader/api/MusicAPI.kt | 2 +- .../{core => }/downloader/api/VancedAPI.kt | 2 +- .../downloader/base/AppDownloader.kt | 4 +- .../downloader/impl/MicrogDownloader.kt | 8 +-- .../downloader/impl/MusicDownloader.kt | 17 ++--- .../downloader/impl/VancedDownloader.kt | 20 +++--- .../downloader/util/DownloadPath.kt | 2 +- .../{core => }/installer/base/AppInstaller.kt | 4 +- .../installer/impl/MicrogInstaller.kt | 10 +-- .../installer/impl/MusicInstaller.kt | 35 ++++++---- .../installer/impl/VancedInstaller.kt | 23 ++++--- .../installer/service/AppInstallService.kt | 2 +- .../installer/service/AppUninstallService.kt | 2 +- .../manager/{core => }/installer/util/PM.kt | 6 +- .../{core => }/installer/util/PMRoot.kt | 43 ++++++++---- .../{core => }/installer/util/PMRootResult.kt | 2 +- .../{core => }/installer/util/Patcher.kt | 28 +++++--- .../installer/util/RootPatchHelper.kt | 2 +- .../manager/{core => }/io/ManagerSuFile.kt | 10 +-- .../manager/{core => }/io/SUIOException.kt | 2 +- .../vanced/manager/network/util/Constants.kt | 20 +++--- .../preferences/ManagerPreference.kt | 2 +- .../holder/PreferenceDefaultValueHolder.kt | 2 +- .../preferences/holder/PreferenceHolder.kt | 6 +- .../preferences/holder/PreferenceKeyHolder.kt | 2 +- .../manager/repository/AppRepository.kt | 22 +++--- .../repository/PreferenceRepository.kt | 4 +- .../source}/PkgInfoDatasource.kt | 4 +- .../source}/PreferenceDatasource.kt | 23 +++++-- .../com/vanced/manager/ui/MainActivity.kt | 4 +- .../vanced/manager/ui/SplashScreenActivity.kt | 2 +- .../manager/ui/component/ManagerCard.kt | 2 + .../manager/ui/component/ManagerListItem.kt | 2 +- .../manager/ui/component/ManagerNavigator.kt | 2 +- .../manager/ui/component/ManagerPreference.kt | 4 +- .../manager/ui/screen/ConfigurationScreen.kt | 2 +- .../vanced/manager/ui/screen/HomeScreen.kt | 67 ++++++++++++++++++- .../manager/ui/screen/SettingsScreen.kt | 2 +- .../java/com/vanced/manager/ui/theme/Theme.kt | 2 +- .../manager/ui/viewmodel/InstallViewModel.kt | 28 ++++---- .../manager/ui/viewmodel/MainViewModel.kt | 6 +- .../manager/ui/viewmodel/SettingsViewModel.kt | 8 +-- .../com/vanced/manager/ui/widget/AppCard.kt | 5 +- .../manager/{core => }/util/AppHelper.kt | 2 +- .../main/java/com/vanced/manager/util/Arch.kt | 10 +++ .../manager/{core => }/util/Coroutines.kt | 2 +- .../manager/{core/io/Util.kt => util/IO.kt} | 2 +- .../vanced/manager/{core => }/util/SuShell.kt | 2 +- 63 files changed, 332 insertions(+), 311 deletions(-) delete mode 100644 app/src/main/java/com/vanced/manager/core/util/AppNotifications.kt delete mode 100644 app/src/main/java/com/vanced/manager/core/util/AppPackages.kt delete mode 100644 app/src/main/java/com/vanced/manager/core/util/Arch.kt delete mode 100644 app/src/main/java/com/vanced/manager/core/util/SocialLinks.kt delete mode 100644 app/src/main/java/com/vanced/manager/domain/model/Link.kt delete mode 100644 app/src/main/java/com/vanced/manager/domain/model/NotificationPrefModel.kt rename app/src/main/java/com/vanced/manager/{core => }/downloader/api/MicrogAPI.kt (83%) rename app/src/main/java/com/vanced/manager/{core => }/downloader/api/MusicAPI.kt (88%) rename app/src/main/java/com/vanced/manager/{core => }/downloader/api/VancedAPI.kt (90%) rename app/src/main/java/com/vanced/manager/{core => }/downloader/base/AppDownloader.kt (95%) rename app/src/main/java/com/vanced/manager/{core => }/downloader/impl/MicrogDownloader.kt (84%) rename app/src/main/java/com/vanced/manager/{core => }/downloader/impl/MusicDownloader.kt (71%) rename app/src/main/java/com/vanced/manager/{core => }/downloader/impl/VancedDownloader.kt (76%) rename app/src/main/java/com/vanced/manager/{core => }/downloader/util/DownloadPath.kt (95%) rename app/src/main/java/com/vanced/manager/{core => }/installer/base/AppInstaller.kt (61%) rename app/src/main/java/com/vanced/manager/{core => }/installer/impl/MicrogInstaller.kt (64%) rename app/src/main/java/com/vanced/manager/{core => }/installer/impl/MusicInstaller.kt (53%) rename app/src/main/java/com/vanced/manager/{core => }/installer/impl/VancedInstaller.kt (65%) rename app/src/main/java/com/vanced/manager/{core => }/installer/service/AppInstallService.kt (96%) rename app/src/main/java/com/vanced/manager/{core => }/installer/service/AppUninstallService.kt (95%) rename app/src/main/java/com/vanced/manager/{core => }/installer/util/PM.kt (92%) rename app/src/main/java/com/vanced/manager/{core => }/installer/util/PMRoot.kt (81%) rename app/src/main/java/com/vanced/manager/{core => }/installer/util/PMRootResult.kt (96%) rename app/src/main/java/com/vanced/manager/{core => }/installer/util/Patcher.kt (87%) rename app/src/main/java/com/vanced/manager/{core => }/installer/util/RootPatchHelper.kt (97%) rename app/src/main/java/com/vanced/manager/{core => }/io/ManagerSuFile.kt (85%) rename app/src/main/java/com/vanced/manager/{core => }/io/SUIOException.kt (87%) rename app/src/main/java/com/vanced/manager/{core => }/preferences/ManagerPreference.kt (98%) rename app/src/main/java/com/vanced/manager/{core => }/preferences/holder/PreferenceDefaultValueHolder.kt (85%) rename app/src/main/java/com/vanced/manager/{core => }/preferences/holder/PreferenceHolder.kt (73%) rename app/src/main/java/com/vanced/manager/{core => }/preferences/holder/PreferenceKeyHolder.kt (91%) rename app/src/main/java/com/vanced/manager/{datasource => repository/source}/PkgInfoDatasource.kt (94%) rename app/src/main/java/com/vanced/manager/{datasource => repository/source}/PreferenceDatasource.kt (78%) rename app/src/main/java/com/vanced/manager/{core => }/util/AppHelper.kt (86%) create mode 100644 app/src/main/java/com/vanced/manager/util/Arch.kt rename app/src/main/java/com/vanced/manager/{core => }/util/Coroutines.kt (90%) rename app/src/main/java/com/vanced/manager/{core/io/Util.kt => util/IO.kt} (96%) rename app/src/main/java/com/vanced/manager/{core => }/util/SuShell.kt (93%) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ae12ca2a6d..edf4095177 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -41,8 +41,8 @@ android:theme="@style/Theme.MaterialComponents.NoActionBar" android:label="@string/app_name"/> - <service android:name=".core.installer.service.AppInstallService" /> - <service android:name=".core.installer.service.AppUninstallService" /> + <service android:name="com.vanced.manager.installer.service.AppInstallService" /> + <service android:name="com.vanced.manager.installer.service.AppUninstallService" /> </application> diff --git a/app/src/main/java/com/vanced/manager/core/util/AppNotifications.kt b/app/src/main/java/com/vanced/manager/core/util/AppNotifications.kt deleted file mode 100644 index 221bf3db1f..0000000000 --- a/app/src/main/java/com/vanced/manager/core/util/AppNotifications.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.vanced.manager.core.util - -import com.vanced.manager.domain.model.NotificationPrefModel -import com.vanced.manager.network.util.MICROG_NAME -import com.vanced.manager.network.util.MUSIC_NAME -import com.vanced.manager.network.util.VANCED_NAME - -val notificationApps = arrayOf( - NotificationPrefModel( - app = VANCED_NAME, - prefKey = "vanced" - ), - NotificationPrefModel( - app = MUSIC_NAME, - prefKey = "music" - ), - NotificationPrefModel( - app = MICROG_NAME, - prefKey = "microg" - ) -) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/util/AppPackages.kt b/app/src/main/java/com/vanced/manager/core/util/AppPackages.kt deleted file mode 100644 index 7e97628798..0000000000 --- a/app/src/main/java/com/vanced/manager/core/util/AppPackages.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.vanced.manager.core.util - -const val VANCED_YOUTUBE_PACKAGE = "com.vanced.android.youtube" -const val VANCED_YOUTUBE_PACKAGE_ROOT = "com.google.android.youtube" - -const val VANCED_MUSIC_PACKAGE = "com.vanced.android.apps.youtube.music" -const val VANCED_MUSIC_PACKAGE_ROOT = "com.google.android.apps.youtube.music" \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/util/Arch.kt b/app/src/main/java/com/vanced/manager/core/util/Arch.kt deleted file mode 100644 index fed980ff11..0000000000 --- a/app/src/main/java/com/vanced/manager/core/util/Arch.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.vanced.manager.core.util - -import android.os.Build - -val arch get() = when { - Build.SUPPORTED_ABIS.contains("x86") -> "x86" - Build.SUPPORTED_ABIS.contains("arm64-v8a") -> "arm64_v8a" - else -> "armeabi_v7a" -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/util/SocialLinks.kt b/app/src/main/java/com/vanced/manager/core/util/SocialLinks.kt deleted file mode 100644 index 06cbd82a6b..0000000000 --- a/app/src/main/java/com/vanced/manager/core/util/SocialLinks.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.vanced.manager.core.util - -import com.vanced.manager.R -import com.vanced.manager.domain.model.Link -import com.vanced.manager.network.util.* - -val sponsors = listOf( - Link( - title = "Brave", - link = BRAVE, - icon = R.drawable.ic_brave - ), - Link( - title = "Adguard", - link = ADGUARD, - icon = R.drawable.ic_adguard - ) -) - -val socialMedia = listOf( - Link( - title = "Instagram", - link = INSTAGRAM, - icon = R.drawable.ic_instagram - ), - Link( - title = "YouTube", - link = YOUTUBE, - icon = R.drawable.ic_youtube - ), - Link( - title = "GitHub", - link = GITHUB, - icon = R.drawable.ic_github - ), - Link( - title = "Website", - link = WEBSITE, - icon = R.drawable.ic_website - ), - Link( - title = "Telegram", - link = TELEGRAM, - icon = R.drawable.ic_telegram - ), - Link( - title = "Twitter", - link = TWITTER, - icon = R.drawable.ic_twitter - ), - Link( - title = "Discord", - link = DISCORD, - icon = R.drawable.ic_discord - ), - Link( - title = "Reddit", - link = REDDIT, - icon = R.drawable.ic_reddit - ), -) \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/APIModule.kt b/app/src/main/java/com/vanced/manager/di/APIModule.kt index 0ac77bcc22..8ebd2b3006 100644 --- a/app/src/main/java/com/vanced/manager/di/APIModule.kt +++ b/app/src/main/java/com/vanced/manager/di/APIModule.kt @@ -1,8 +1,8 @@ package com.vanced.manager.di -import com.vanced.manager.core.downloader.api.MicrogAPI -import com.vanced.manager.core.downloader.api.MusicAPI -import com.vanced.manager.core.downloader.api.VancedAPI +import com.vanced.manager.downloader.api.MicrogAPI +import com.vanced.manager.downloader.api.MusicAPI +import com.vanced.manager.downloader.api.VancedAPI import com.vanced.manager.network.util.BASE import okhttp3.OkHttpClient import org.koin.dsl.module diff --git a/app/src/main/java/com/vanced/manager/di/DatasourceModule.kt b/app/src/main/java/com/vanced/manager/di/DatasourceModule.kt index 9984dff740..65164f05cc 100644 --- a/app/src/main/java/com/vanced/manager/di/DatasourceModule.kt +++ b/app/src/main/java/com/vanced/manager/di/DatasourceModule.kt @@ -1,10 +1,10 @@ package com.vanced.manager.di import android.content.Context -import com.vanced.manager.datasource.PkgInfoDatasource -import com.vanced.manager.datasource.PkgInfoDatasourceImpl -import com.vanced.manager.datasource.PreferenceDatasource -import com.vanced.manager.datasource.PreferenceDatasourceImpl +import com.vanced.manager.repository.source.PkgInfoDatasource +import com.vanced.manager.repository.source.PkgInfoDatasourceImpl +import com.vanced.manager.repository.source.PreferenceDatasource +import com.vanced.manager.repository.source.PreferenceDatasourceImpl import org.koin.android.ext.koin.androidContext import org.koin.dsl.module @@ -22,7 +22,10 @@ val datasourceModule = module { context: Context ): PreferenceDatasource { return PreferenceDatasourceImpl( - sharedPreferences = context.getSharedPreferences("manager_settings", Context.MODE_PRIVATE) + sharedPreferences = context.getSharedPreferences( + "manager_settings", + Context.MODE_PRIVATE + ) ) } diff --git a/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt b/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt index 642e9bccbd..87521bad74 100644 --- a/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt +++ b/app/src/main/java/com/vanced/manager/di/DownloaderModule.kt @@ -1,12 +1,12 @@ package com.vanced.manager.di import android.content.Context -import com.vanced.manager.core.downloader.api.MicrogAPI -import com.vanced.manager.core.downloader.api.MusicAPI -import com.vanced.manager.core.downloader.api.VancedAPI -import com.vanced.manager.core.downloader.impl.MicrogDownloader -import com.vanced.manager.core.downloader.impl.MusicDownloader -import com.vanced.manager.core.downloader.impl.VancedDownloader +import com.vanced.manager.downloader.api.MicrogAPI +import com.vanced.manager.downloader.api.MusicAPI +import com.vanced.manager.downloader.api.VancedAPI +import com.vanced.manager.downloader.impl.MicrogDownloader +import com.vanced.manager.downloader.impl.MusicDownloader +import com.vanced.manager.downloader.impl.VancedDownloader import org.koin.android.ext.koin.androidContext import org.koin.dsl.module diff --git a/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt b/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt index 31f6f43af8..2fa146aa4b 100644 --- a/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt +++ b/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt @@ -1,9 +1,9 @@ package com.vanced.manager.di import android.content.Context -import com.vanced.manager.core.installer.impl.MicrogInstaller -import com.vanced.manager.core.installer.impl.MusicInstaller -import com.vanced.manager.core.installer.impl.VancedInstaller +import com.vanced.manager.installer.impl.MicrogInstaller +import com.vanced.manager.installer.impl.MusicInstaller +import com.vanced.manager.installer.impl.VancedInstaller import org.koin.android.ext.koin.androidContext import org.koin.dsl.module diff --git a/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt b/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt index a58352e36f..103ad99446 100644 --- a/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt +++ b/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt @@ -1,9 +1,12 @@ package com.vanced.manager.di -import com.vanced.manager.datasource.PkgInfoDatasource -import com.vanced.manager.datasource.PreferenceDatasource import com.vanced.manager.network.GithubService -import com.vanced.manager.repository.* +import com.vanced.manager.repository.AppRepository +import com.vanced.manager.repository.AppRepositoryImpl +import com.vanced.manager.repository.PreferenceRepository +import com.vanced.manager.repository.PreferenceRepositoryImpl +import com.vanced.manager.repository.source.PkgInfoDatasource +import com.vanced.manager.repository.source.PreferenceDatasource import org.koin.dsl.module val repositoryModule = module { diff --git a/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt index 2119b9eced..d82ede038d 100644 --- a/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt +++ b/app/src/main/java/com/vanced/manager/di/ViewModelModule.kt @@ -1,12 +1,12 @@ package com.vanced.manager.di import android.app.Application -import com.vanced.manager.core.downloader.impl.MicrogDownloader -import com.vanced.manager.core.downloader.impl.MusicDownloader -import com.vanced.manager.core.downloader.impl.VancedDownloader -import com.vanced.manager.core.installer.impl.MicrogInstaller -import com.vanced.manager.core.installer.impl.MusicInstaller -import com.vanced.manager.core.installer.impl.VancedInstaller +import com.vanced.manager.downloader.impl.MicrogDownloader +import com.vanced.manager.downloader.impl.MusicDownloader +import com.vanced.manager.downloader.impl.VancedDownloader +import com.vanced.manager.installer.impl.MicrogInstaller +import com.vanced.manager.installer.impl.MusicInstaller +import com.vanced.manager.installer.impl.VancedInstaller import com.vanced.manager.repository.AppRepository import com.vanced.manager.repository.PreferenceRepository import com.vanced.manager.ui.viewmodel.ConfigurationViewModel diff --git a/app/src/main/java/com/vanced/manager/domain/model/App.kt b/app/src/main/java/com/vanced/manager/domain/model/App.kt index 0b5a7c06d3..d9a76e21ea 100644 --- a/app/src/main/java/com/vanced/manager/domain/model/App.kt +++ b/app/src/main/java/com/vanced/manager/domain/model/App.kt @@ -37,7 +37,8 @@ object AppData { const val PACKAGE_ROOT_VANCED_YOUTUBE_MUSIC = "com.google.android.youtube.apps.music" const val LAUNCH_ACTIVITY_VANCED_YOUTUBE = "com.google.android.youtube.HomeActivity" - const val LAUNCH_ACTIVITY_VANCED_YOUTUBE_MUSIC = "com.google.android.apps.youtube.music.activities.MusicActivity" + const val LAUNCH_ACTIVITY_VANCED_YOUTUBE_MUSIC = + "com.google.android.apps.youtube.music.activities.MusicActivity" const val LAUNCH_ACTIVITY_VANCED_MICROG = "org.microg.gms.ui.SettingsActivity" const val LAUNCH_ACTIVITY_VANCED_MANAGER = "" } diff --git a/app/src/main/java/com/vanced/manager/domain/model/Link.kt b/app/src/main/java/com/vanced/manager/domain/model/Link.kt deleted file mode 100644 index 080ba76d18..0000000000 --- a/app/src/main/java/com/vanced/manager/domain/model/Link.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.vanced.manager.domain.model - -import androidx.annotation.DrawableRes - -data class Link( - val title: String, - val link: String, - @DrawableRes val icon: Int -) diff --git a/app/src/main/java/com/vanced/manager/domain/model/NotificationPrefModel.kt b/app/src/main/java/com/vanced/manager/domain/model/NotificationPrefModel.kt deleted file mode 100644 index eb975d7896..0000000000 --- a/app/src/main/java/com/vanced/manager/domain/model/NotificationPrefModel.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.vanced.manager.domain.model - -data class NotificationPrefModel( - val app: String, - val prefKey: String -) diff --git a/app/src/main/java/com/vanced/manager/core/downloader/api/MicrogAPI.kt b/app/src/main/java/com/vanced/manager/downloader/api/MicrogAPI.kt similarity index 83% rename from app/src/main/java/com/vanced/manager/core/downloader/api/MicrogAPI.kt rename to app/src/main/java/com/vanced/manager/downloader/api/MicrogAPI.kt index 14c99d626c..e379b85ce0 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/api/MicrogAPI.kt +++ b/app/src/main/java/com/vanced/manager/downloader/api/MicrogAPI.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.core.downloader.api +package com.vanced.manager.downloader.api import okhttp3.ResponseBody import retrofit2.Call diff --git a/app/src/main/java/com/vanced/manager/core/downloader/api/MusicAPI.kt b/app/src/main/java/com/vanced/manager/downloader/api/MusicAPI.kt similarity index 88% rename from app/src/main/java/com/vanced/manager/core/downloader/api/MusicAPI.kt rename to app/src/main/java/com/vanced/manager/downloader/api/MusicAPI.kt index 0eaec89f7d..9eece8b5c8 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/api/MusicAPI.kt +++ b/app/src/main/java/com/vanced/manager/downloader/api/MusicAPI.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.core.downloader.api +package com.vanced.manager.downloader.api import okhttp3.ResponseBody import retrofit2.Call diff --git a/app/src/main/java/com/vanced/manager/core/downloader/api/VancedAPI.kt b/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt similarity index 90% rename from app/src/main/java/com/vanced/manager/core/downloader/api/VancedAPI.kt rename to app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt index 1e44b2681a..27ae1e3096 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/api/VancedAPI.kt +++ b/app/src/main/java/com/vanced/manager/downloader/api/VancedAPI.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.core.downloader.api +package com.vanced.manager.downloader.api import okhttp3.ResponseBody import retrofit2.Call diff --git a/app/src/main/java/com/vanced/manager/core/downloader/base/AppDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/base/AppDownloader.kt similarity index 95% rename from app/src/main/java/com/vanced/manager/core/downloader/base/AppDownloader.kt rename to app/src/main/java/com/vanced/manager/downloader/base/AppDownloader.kt index efeb9eb0be..d808a566a2 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/base/AppDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/base/AppDownloader.kt @@ -1,6 +1,6 @@ -package com.vanced.manager.core.downloader.base +package com.vanced.manager.downloader.base -import com.vanced.manager.core.io.writeFile +import com.vanced.manager.util.writeFile import okhttp3.ResponseBody import retrofit2.Call import retrofit2.awaitResponse diff --git a/app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt similarity index 84% rename from app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt rename to app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt index ca810c8ee2..bcadbb472b 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/impl/MicrogDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/impl/MicrogDownloader.kt @@ -1,9 +1,9 @@ -package com.vanced.manager.core.downloader.impl +package com.vanced.manager.downloader.impl import android.content.Context -import com.vanced.manager.core.downloader.api.MicrogAPI -import com.vanced.manager.core.downloader.base.AppDownloader -import com.vanced.manager.core.downloader.util.getMicrogPath +import com.vanced.manager.downloader.api.MicrogAPI +import com.vanced.manager.downloader.base.AppDownloader +import com.vanced.manager.downloader.util.getMicrogPath import java.io.File class MicrogDownloader( diff --git a/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt similarity index 71% rename from app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt rename to app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt index 0947705230..5c3b6c669f 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/impl/MusicDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/impl/MusicDownloader.kt @@ -1,12 +1,12 @@ -package com.vanced.manager.core.downloader.impl +package com.vanced.manager.downloader.impl import android.content.Context -import com.vanced.manager.core.downloader.api.MusicAPI -import com.vanced.manager.core.downloader.base.AppDownloader -import com.vanced.manager.core.downloader.util.getVancedYoutubeMusicPath -import com.vanced.manager.core.preferences.holder.managerVariantPref -import com.vanced.manager.core.preferences.holder.musicVersionPref -import com.vanced.manager.core.util.getLatestOrProvidedAppVersion +import com.vanced.manager.downloader.api.MusicAPI +import com.vanced.manager.downloader.base.AppDownloader +import com.vanced.manager.downloader.util.getVancedYoutubeMusicPath +import com.vanced.manager.preferences.holder.managerVariantPref +import com.vanced.manager.preferences.holder.musicVersionPref +import com.vanced.manager.util.getLatestOrProvidedAppVersion import java.io.File class MusicDownloader( @@ -51,7 +51,8 @@ class MusicDownloader( } override fun getSavedFilePath(): String { - val directory = File(getVancedYoutubeMusicPath(absoluteVersion, managerVariantPref, context)) + val directory = + File(getVancedYoutubeMusicPath(absoluteVersion, managerVariantPref, context)) if (!directory.exists()) directory.mkdirs() diff --git a/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt b/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt similarity index 76% rename from app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt rename to app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt index 364c918782..909baf318a 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/impl/VancedDownloader.kt +++ b/app/src/main/java/com/vanced/manager/downloader/impl/VancedDownloader.kt @@ -1,15 +1,15 @@ -package com.vanced.manager.core.downloader.impl +package com.vanced.manager.downloader.impl import android.content.Context -import com.vanced.manager.core.downloader.api.VancedAPI -import com.vanced.manager.core.downloader.base.AppDownloader -import com.vanced.manager.core.downloader.util.getVancedYoutubePath -import com.vanced.manager.core.preferences.holder.managerVariantPref -import com.vanced.manager.core.preferences.holder.vancedLanguagesPref -import com.vanced.manager.core.preferences.holder.vancedThemePref -import com.vanced.manager.core.preferences.holder.vancedVersionPref -import com.vanced.manager.core.util.arch -import com.vanced.manager.core.util.getLatestOrProvidedAppVersion +import com.vanced.manager.downloader.api.VancedAPI +import com.vanced.manager.downloader.base.AppDownloader +import com.vanced.manager.downloader.util.getVancedYoutubePath +import com.vanced.manager.preferences.holder.managerVariantPref +import com.vanced.manager.preferences.holder.vancedLanguagesPref +import com.vanced.manager.preferences.holder.vancedThemePref +import com.vanced.manager.preferences.holder.vancedVersionPref +import com.vanced.manager.util.arch +import com.vanced.manager.util.getLatestOrProvidedAppVersion import java.io.File class VancedDownloader( diff --git a/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadPath.kt b/app/src/main/java/com/vanced/manager/downloader/util/DownloadPath.kt similarity index 95% rename from app/src/main/java/com/vanced/manager/core/downloader/util/DownloadPath.kt rename to app/src/main/java/com/vanced/manager/downloader/util/DownloadPath.kt index 746e4b5905..50df4f5b6d 100644 --- a/app/src/main/java/com/vanced/manager/core/downloader/util/DownloadPath.kt +++ b/app/src/main/java/com/vanced/manager/downloader/util/DownloadPath.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.core.downloader.util +package com.vanced.manager.downloader.util import android.content.Context diff --git a/app/src/main/java/com/vanced/manager/core/installer/base/AppInstaller.kt b/app/src/main/java/com/vanced/manager/installer/base/AppInstaller.kt similarity index 61% rename from app/src/main/java/com/vanced/manager/core/installer/base/AppInstaller.kt rename to app/src/main/java/com/vanced/manager/installer/base/AppInstaller.kt index 61e5b38e98..e5de5b53e5 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/base/AppInstaller.kt +++ b/app/src/main/java/com/vanced/manager/installer/base/AppInstaller.kt @@ -1,6 +1,6 @@ -package com.vanced.manager.core.installer.base +package com.vanced.manager.installer.base -import com.vanced.manager.core.installer.util.PMRootResult +import com.vanced.manager.installer.util.PMRootResult abstract class AppInstaller { diff --git a/app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt b/app/src/main/java/com/vanced/manager/installer/impl/MicrogInstaller.kt similarity index 64% rename from app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt rename to app/src/main/java/com/vanced/manager/installer/impl/MicrogInstaller.kt index 55642b2550..6334dc7700 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/impl/MicrogInstaller.kt +++ b/app/src/main/java/com/vanced/manager/installer/impl/MicrogInstaller.kt @@ -1,10 +1,10 @@ -package com.vanced.manager.core.installer.impl +package com.vanced.manager.installer.impl import android.content.Context -import com.vanced.manager.core.downloader.util.getMicrogPath -import com.vanced.manager.core.installer.base.AppInstaller -import com.vanced.manager.core.installer.util.PM -import com.vanced.manager.core.installer.util.PMRootResult +import com.vanced.manager.downloader.util.getMicrogPath +import com.vanced.manager.installer.base.AppInstaller +import com.vanced.manager.installer.util.PM +import com.vanced.manager.installer.util.PMRootResult import java.io.File class MicrogInstaller( diff --git a/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt b/app/src/main/java/com/vanced/manager/installer/impl/MusicInstaller.kt similarity index 53% rename from app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt rename to app/src/main/java/com/vanced/manager/installer/impl/MusicInstaller.kt index 46ee003b1f..3572b7507d 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/impl/MusicInstaller.kt +++ b/app/src/main/java/com/vanced/manager/installer/impl/MusicInstaller.kt @@ -1,15 +1,18 @@ -package com.vanced.manager.core.installer.impl +package com.vanced.manager.installer.impl import android.content.Context -import com.vanced.manager.core.downloader.util.getStockYoutubeMusicPath -import com.vanced.manager.core.downloader.util.getVancedYoutubeMusicPath -import com.vanced.manager.core.installer.base.AppInstaller -import com.vanced.manager.core.installer.util.* -import com.vanced.manager.core.preferences.holder.managerVariantPref -import com.vanced.manager.core.preferences.holder.musicVersionPref -import com.vanced.manager.core.preferences.holder.vancedVersionPref -import com.vanced.manager.core.util.VANCED_MUSIC_PACKAGE_ROOT -import com.vanced.manager.core.util.getLatestOrProvidedAppVersion +import com.vanced.manager.domain.model.AppData +import com.vanced.manager.downloader.util.getStockYoutubeMusicPath +import com.vanced.manager.downloader.util.getVancedYoutubeMusicPath +import com.vanced.manager.installer.base.AppInstaller +import com.vanced.manager.installer.util.PM +import com.vanced.manager.installer.util.PMRoot +import com.vanced.manager.installer.util.PMRootResult +import com.vanced.manager.installer.util.RootPatchHelper +import com.vanced.manager.preferences.holder.managerVariantPref +import com.vanced.manager.preferences.holder.musicVersionPref +import com.vanced.manager.preferences.holder.vancedVersionPref +import com.vanced.manager.util.getLatestOrProvidedAppVersion import java.io.File class MusicInstaller( @@ -21,7 +24,13 @@ class MusicInstaller( ) { val absoluteVersion = getLatestOrProvidedAppVersion(musicVersionPref, appVersions) - val musicApk = File(getVancedYoutubeMusicPath(absoluteVersion, managerVariantPref, context) + "/music.apk") + val musicApk = File( + getVancedYoutubeMusicPath( + absoluteVersion, + managerVariantPref, + context + ) + "/music.apk" + ) PM.installApp(musicApk, context) } @@ -33,7 +42,7 @@ class MusicInstaller( val vancedPath = getVancedYoutubeMusicPath(absoluteVersion, "root", context) + "/base.apk" val prepareStock = RootPatchHelper.prepareStock( - stockPackage = VANCED_MUSIC_PACKAGE_ROOT, + stockPackage = AppData.PACKAGE_ROOT_VANCED_YOUTUBE_MUSIC, stockVersion = absoluteVersion ) { PMRoot.installApp(stockPath) @@ -43,7 +52,7 @@ class MusicInstaller( val patchStock = RootPatchHelper.patchStock( patchPath = vancedPath, - stockPackage = VANCED_MUSIC_PACKAGE_ROOT, + stockPackage = AppData.PACKAGE_ROOT_VANCED_YOUTUBE_MUSIC, app = APP_KEY ) if (patchStock.isError) diff --git a/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt b/app/src/main/java/com/vanced/manager/installer/impl/VancedInstaller.kt similarity index 65% rename from app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt rename to app/src/main/java/com/vanced/manager/installer/impl/VancedInstaller.kt index bdcbf86667..e1763e38dd 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/impl/VancedInstaller.kt +++ b/app/src/main/java/com/vanced/manager/installer/impl/VancedInstaller.kt @@ -1,13 +1,16 @@ -package com.vanced.manager.core.installer.impl +package com.vanced.manager.installer.impl import android.content.Context -import com.vanced.manager.core.downloader.util.getStockYoutubePath -import com.vanced.manager.core.downloader.util.getVancedYoutubePath -import com.vanced.manager.core.installer.base.AppInstaller -import com.vanced.manager.core.installer.util.* -import com.vanced.manager.core.preferences.holder.vancedVersionPref -import com.vanced.manager.core.util.VANCED_YOUTUBE_PACKAGE_ROOT -import com.vanced.manager.core.util.getLatestOrProvidedAppVersion +import com.vanced.manager.domain.model.AppData +import com.vanced.manager.downloader.util.getStockYoutubePath +import com.vanced.manager.downloader.util.getVancedYoutubePath +import com.vanced.manager.installer.base.AppInstaller +import com.vanced.manager.installer.util.PM +import com.vanced.manager.installer.util.PMRoot +import com.vanced.manager.installer.util.PMRootResult +import com.vanced.manager.installer.util.RootPatchHelper +import com.vanced.manager.preferences.holder.vancedVersionPref +import com.vanced.manager.util.getLatestOrProvidedAppVersion import java.io.File class VancedInstaller( @@ -33,7 +36,7 @@ class VancedInstaller( val vancedBaseApk = getVancedYoutubePath(absoluteVersion, "root", context) + "/base.apk" val prepareStock = RootPatchHelper.prepareStock( - stockPackage = VANCED_YOUTUBE_PACKAGE_ROOT, + stockPackage = AppData.PACKAGE_ROOT_VANCED_YOUTUBE, stockVersion = absoluteVersion, ) { PMRoot.installSplitApp(stockApks!!) @@ -43,7 +46,7 @@ class VancedInstaller( val patchStock = RootPatchHelper.patchStock( patchPath = vancedBaseApk, - stockPackage = VANCED_YOUTUBE_PACKAGE_ROOT, + stockPackage = AppData.PACKAGE_ROOT_VANCED_YOUTUBE, app = APP_KEY ) if (patchStock.isError) diff --git a/app/src/main/java/com/vanced/manager/core/installer/service/AppInstallService.kt b/app/src/main/java/com/vanced/manager/installer/service/AppInstallService.kt similarity index 96% rename from app/src/main/java/com/vanced/manager/core/installer/service/AppInstallService.kt rename to app/src/main/java/com/vanced/manager/installer/service/AppInstallService.kt index 559ccd12dc..3eb740e3a0 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/service/AppInstallService.kt +++ b/app/src/main/java/com/vanced/manager/installer/service/AppInstallService.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.core.installer.service +package com.vanced.manager.installer.service import android.app.Service import android.content.Intent diff --git a/app/src/main/java/com/vanced/manager/core/installer/service/AppUninstallService.kt b/app/src/main/java/com/vanced/manager/installer/service/AppUninstallService.kt similarity index 95% rename from app/src/main/java/com/vanced/manager/core/installer/service/AppUninstallService.kt rename to app/src/main/java/com/vanced/manager/installer/service/AppUninstallService.kt index a06af6532a..28c04fab7c 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/service/AppUninstallService.kt +++ b/app/src/main/java/com/vanced/manager/installer/service/AppUninstallService.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.core.installer.service +package com.vanced.manager.installer.service import android.app.Service import android.content.Intent diff --git a/app/src/main/java/com/vanced/manager/core/installer/util/PM.kt b/app/src/main/java/com/vanced/manager/installer/util/PM.kt similarity index 92% rename from app/src/main/java/com/vanced/manager/core/installer/util/PM.kt rename to app/src/main/java/com/vanced/manager/installer/util/PM.kt index 45412f4551..b60d06c754 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/util/PM.kt +++ b/app/src/main/java/com/vanced/manager/installer/util/PM.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.core.installer.util +package com.vanced.manager.installer.util import android.app.PendingIntent import android.content.Context @@ -6,8 +6,8 @@ import android.content.Intent import android.content.pm.PackageInstaller import android.content.pm.PackageManager import android.os.Build -import com.vanced.manager.core.installer.service.AppInstallService -import com.vanced.manager.core.installer.service.AppUninstallService +import com.vanced.manager.installer.service.AppInstallService +import com.vanced.manager.installer.service.AppUninstallService import java.io.File private const val byteArraySize = 1024 * 1024 // Because 1,048,576 is not readable diff --git a/app/src/main/java/com/vanced/manager/core/installer/util/PMRoot.kt b/app/src/main/java/com/vanced/manager/installer/util/PMRoot.kt similarity index 81% rename from app/src/main/java/com/vanced/manager/core/installer/util/PMRoot.kt rename to app/src/main/java/com/vanced/manager/installer/util/PMRoot.kt index 8cea3a28f9..8e95a5297e 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/util/PMRoot.kt +++ b/app/src/main/java/com/vanced/manager/installer/util/PMRoot.kt @@ -1,10 +1,10 @@ -package com.vanced.manager.core.installer.util +package com.vanced.manager.installer.util import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.io.SuFile import com.topjohnwu.superuser.io.SuFileOutputStream -import com.vanced.manager.core.util.errString -import com.vanced.manager.core.util.outString +import com.vanced.manager.util.errString +import com.vanced.manager.util.outString import java.io.File import java.io.IOException @@ -13,7 +13,10 @@ object PMRoot { fun installApp(apkPath: String): PMRootResult<Nothing> { val apk = File(apkPath) val tmpApk = copyApkToTemp(apk).getOrElse { exception -> - return PMRootResult.Error(PMRootStatus.SESSION_FAILED_COPY, exception.stackTraceToString()) + return PMRootResult.Error( + PMRootStatus.SESSION_FAILED_COPY, + exception.stackTraceToString() + ) } val install = Shell.su("pm", "install", "-r", tmpApk.absolutePath).exec() @@ -42,7 +45,10 @@ object PMRoot { for (apkPath in apkPaths) { val apk = File(apkPath) val tmpApk = copyApkToTemp(apk).getOrElse { exception -> - return PMRootResult.Error(PMRootStatus.SESSION_FAILED_COPY, exception.stackTraceToString()) + return PMRootResult.Error( + PMRootStatus.SESSION_FAILED_COPY, + exception.stackTraceToString() + ) } val installWrite = @@ -79,7 +85,10 @@ object PMRoot { .exec() if (!setInstaller.isSuccess) - return PMRootResult.Error(PMRootStatus.ACTION_FAILED_SET_INSTALLER, setInstaller.errString) + return PMRootResult.Error( + PMRootStatus.ACTION_FAILED_SET_INSTALLER, + setInstaller.errString + ) return PMRootResult.Success() } @@ -98,8 +107,10 @@ object PMRoot { val dumpsys = Shell.su("dumpsys", "package", pkg, "|", "grep", keyword).exec() if (!dumpsys.isSuccess) - return PMRootResult.Error(PMRootStatus.ACTION_FAILED_GET_PACKAGE_VERSION_NAME, - dumpsys.errString) + return PMRootResult.Error( + PMRootStatus.ACTION_FAILED_GET_PACKAGE_VERSION_NAME, + dumpsys.errString + ) return PMRootResult.Success(dumpsys.outString.removePrefix(keyword)) } @@ -109,11 +120,15 @@ object PMRoot { val dumpsys = Shell.su("dumpsys", "package", pkg, "|", "grep", keyword).exec() if (!dumpsys.isSuccess) - return PMRootResult.Error(PMRootStatus.ACTION_FAILED_GET_PACKAGE_VERSION_CODE, - dumpsys.errString) - - return PMRootResult.Success(dumpsys.outString.removePrefix(keyword).substringAfter("minSdk") - .toLong()) + return PMRootResult.Error( + PMRootStatus.ACTION_FAILED_GET_PACKAGE_VERSION_CODE, + dumpsys.errString + ) + + return PMRootResult.Success( + dumpsys.outString.removePrefix(keyword).substringAfter("minSdk") + .toLong() + ) } fun getPackageDir(pkg: String): PMRootResult<String> { @@ -127,7 +142,7 @@ object PMRoot { } } -private fun copyApkToTemp(apk: File, ): Result<SuFile> { +private fun copyApkToTemp(apk: File): Result<SuFile> { val tmpPath = "/data/local/tmp/${apk.name}" val tmpApk = SuFile(tmpPath).apply { diff --git a/app/src/main/java/com/vanced/manager/core/installer/util/PMRootResult.kt b/app/src/main/java/com/vanced/manager/installer/util/PMRootResult.kt similarity index 96% rename from app/src/main/java/com/vanced/manager/core/installer/util/PMRootResult.kt rename to app/src/main/java/com/vanced/manager/installer/util/PMRootResult.kt index 13a5178013..975d383b79 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/util/PMRootResult.kt +++ b/app/src/main/java/com/vanced/manager/installer/util/PMRootResult.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.core.installer.util +package com.vanced.manager.installer.util enum class PMRootStatus { ACTION_FAILED_SET_INSTALLER, diff --git a/app/src/main/java/com/vanced/manager/core/installer/util/Patcher.kt b/app/src/main/java/com/vanced/manager/installer/util/Patcher.kt similarity index 87% rename from app/src/main/java/com/vanced/manager/core/installer/util/Patcher.kt rename to app/src/main/java/com/vanced/manager/installer/util/Patcher.kt index 99e5a965ac..f9bfb13df9 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/util/Patcher.kt +++ b/app/src/main/java/com/vanced/manager/installer/util/Patcher.kt @@ -1,11 +1,11 @@ -package com.vanced.manager.core.installer.util +package com.vanced.manager.installer.util import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.io.SuFile import com.topjohnwu.superuser.io.SuFileOutputStream -import com.vanced.manager.core.io.ManagerSuFile -import com.vanced.manager.core.io.SUIOException -import com.vanced.manager.core.util.errString +import com.vanced.manager.io.ManagerSuFile +import com.vanced.manager.io.SUIOException +import com.vanced.manager.util.errString import java.io.File import java.io.IOException @@ -24,13 +24,17 @@ object Patcher { val copyServiceDScript = copyScriptToDestination(postFsDataScript, postFsDataScriptPath) if (copyServiceDScript.isFailure) - return PMRootResult.Error(PMRootStatus.SCRIPT_FAILED_SETUP_POST_FS, - copyServiceDScript.exceptionOrNull()!!.stackTraceToString()) + return PMRootResult.Error( + PMRootStatus.SCRIPT_FAILED_SETUP_POST_FS, + copyServiceDScript.exceptionOrNull()!!.stackTraceToString() + ) val copyPostFsDataScript = copyScriptToDestination(serviceDScript, serviceDScriptPath) if (copyPostFsDataScript.isFailure) - return PMRootResult.Error(PMRootStatus.SCRIPT_FAILED_SETUP_SERVICE_D, - copyPostFsDataScript.exceptionOrNull()!!.stackTraceToString()) + return PMRootResult.Error( + PMRootStatus.SCRIPT_FAILED_SETUP_SERVICE_D, + copyPostFsDataScript.exceptionOrNull()!!.stackTraceToString() + ) return PMRootResult.Success() } @@ -72,11 +76,15 @@ object Patcher { } fun linkPatch(app: String, stockPackage: String, stockPath: String): PMRootResult<Nothing> { - val umount = Shell.su("""for i in ${'$'}(ls /data/app/ | grep $stockPackage | tr " "); do umount -l "/data/app/${"$"}i/base.apk"; done """).exec() + val umount = + Shell.su("""for i in ${'$'}(ls /data/app/ | grep $stockPackage | tr " "); do umount -l "/data/app/${"$"}i/base.apk"; done """) + .exec() if (!umount.isSuccess) return PMRootResult.Error(PMRootStatus.LINK_FAILED_UNMOUNT, umount.errString) - val mount = Shell.su("su", "-mm", "-c", """"mount -o bind ${getAppPatchPath(app)} $stockPath"""").exec() + val mount = + Shell.su("su", "-mm", "-c", """"mount -o bind ${getAppPatchPath(app)} $stockPath"""") + .exec() if (!mount.isSuccess) return PMRootResult.Error(PMRootStatus.LINK_FAILED_MOUNT, mount.errString) diff --git a/app/src/main/java/com/vanced/manager/core/installer/util/RootPatchHelper.kt b/app/src/main/java/com/vanced/manager/installer/util/RootPatchHelper.kt similarity index 97% rename from app/src/main/java/com/vanced/manager/core/installer/util/RootPatchHelper.kt rename to app/src/main/java/com/vanced/manager/installer/util/RootPatchHelper.kt index bf23db0157..a7c3b6b5cd 100644 --- a/app/src/main/java/com/vanced/manager/core/installer/util/RootPatchHelper.kt +++ b/app/src/main/java/com/vanced/manager/installer/util/RootPatchHelper.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.core.installer.util +package com.vanced.manager.installer.util object RootPatchHelper { diff --git a/app/src/main/java/com/vanced/manager/core/io/ManagerSuFile.kt b/app/src/main/java/com/vanced/manager/io/ManagerSuFile.kt similarity index 85% rename from app/src/main/java/com/vanced/manager/core/io/ManagerSuFile.kt rename to app/src/main/java/com/vanced/manager/io/ManagerSuFile.kt index 9b2d1b4867..f0f7ce83f2 100644 --- a/app/src/main/java/com/vanced/manager/core/io/ManagerSuFile.kt +++ b/app/src/main/java/com/vanced/manager/io/ManagerSuFile.kt @@ -1,11 +1,10 @@ -package com.vanced.manager.core.io +package com.vanced.manager.io import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.io.SuFile -import com.vanced.manager.core.util.errString -import com.vanced.manager.core.util.outString +import com.vanced.manager.util.errString +import com.vanced.manager.util.outString import java.io.File -import java.io.IOException class ManagerSuFile : SuFile { @@ -15,9 +14,7 @@ class ManagerSuFile : SuFile { } constructor(pathName: String) : super(pathName) - constructor(parent: String, child: String) : super(parent, child) - constructor(parent: File, child: String) : super(parent, child) private fun cmd(input: String): SuFileResult { @@ -35,5 +32,4 @@ class ManagerSuFile : SuFile { return true } - } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/io/SUIOException.kt b/app/src/main/java/com/vanced/manager/io/SUIOException.kt similarity index 87% rename from app/src/main/java/com/vanced/manager/core/io/SUIOException.kt rename to app/src/main/java/com/vanced/manager/io/SUIOException.kt index 00641f20e4..1f73c8fb08 100644 --- a/app/src/main/java/com/vanced/manager/core/io/SUIOException.kt +++ b/app/src/main/java/com/vanced/manager/io/SUIOException.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.core.io +package com.vanced.manager.io import java.io.IOException diff --git a/app/src/main/java/com/vanced/manager/network/util/Constants.kt b/app/src/main/java/com/vanced/manager/network/util/Constants.kt index bfffd1f745..deed27c078 100644 --- a/app/src/main/java/com/vanced/manager/network/util/Constants.kt +++ b/app/src/main/java/com/vanced/manager/network/util/Constants.kt @@ -8,14 +8,14 @@ const val VANCED_NAME = "YouTube Vanced" const val MUSIC_NAME = "YouTube Vanced Music" const val MICROG_NAME = "Vanced microG" -const val BRAVE = "https://vancedapp.com/brave" -const val ADGUARD = "https://adguard.com/?aid=31141&source=manager" +const val URL_SPONSOR_BRAVE = "https://vancedapp.com/brave" +const val URL_SPONSOR_ADGUARD = "https://adguard.com/?aid=31141&source=manager" -const val INSTAGRAM = "https://instagram.com/vanced.youtube" -const val YOUTUBE = "https://youtube.com/c/YouTubeVanced" -const val GITHUB = "https://github.com/YTVanced/VancedManager" -const val WEBSITE = "https://vancedapp.com" -const val TELEGRAM = "https://t.me/joinchat/AAAAAEHf-pi4jH1SDlAL4w" -const val TWITTER = "https://twitter.com/YTVanced" -const val DISCORD = "https://discord.gg/WCGNdRruzb" -const val REDDIT = "https://www.reddit.com/r/Vanced/" \ No newline at end of file +const val URL_MEDIA_INSTAGRAM = "https://instagram.com/vanced.youtube" +const val URL_MEDIA_YOUTUBE = "https://youtube.com/c/YouTubeVanced" +const val URL_MEDIA_GITHUB = "https://github.com/YTVanced/VancedManager" +const val URL_MEDIA_WEBSITE = "https://vancedapp.com" +const val URL_MEDIA_TELEGRAM = "https://t.me/joinchat/AAAAAEHf-pi4jH1SDlAL4w" +const val URL_MEDIA_TWITTER = "https://twitter.com/YTVanced" +const val URL_MEDIA_DISCORD = "https://discord.gg/WCGNdRruzb" +const val URL_MEDIA_REDDIT = "https://www.reddit.com/r/Vanced/" \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/preferences/ManagerPreference.kt b/app/src/main/java/com/vanced/manager/preferences/ManagerPreference.kt similarity index 98% rename from app/src/main/java/com/vanced/manager/core/preferences/ManagerPreference.kt rename to app/src/main/java/com/vanced/manager/preferences/ManagerPreference.kt index c698311f81..064db582be 100644 --- a/app/src/main/java/com/vanced/manager/core/preferences/ManagerPreference.kt +++ b/app/src/main/java/com/vanced/manager/preferences/ManagerPreference.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.core.preferences +package com.vanced.manager.preferences import android.content.SharedPreferences import androidx.compose.runtime.getValue diff --git a/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceDefaultValueHolder.kt b/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceDefaultValueHolder.kt similarity index 85% rename from app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceDefaultValueHolder.kt rename to app/src/main/java/com/vanced/manager/preferences/holder/PreferenceDefaultValueHolder.kt index 9972b2d009..cb209aa519 100644 --- a/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceDefaultValueHolder.kt +++ b/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceDefaultValueHolder.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.core.preferences.holder +package com.vanced.manager.preferences.holder const val MANAGER_VARIANT_DEFAULT_VALUE = "nonroot" diff --git a/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceHolder.kt b/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceHolder.kt similarity index 73% rename from app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceHolder.kt rename to app/src/main/java/com/vanced/manager/preferences/holder/PreferenceHolder.kt index 9769bbb35d..bc000f9d18 100644 --- a/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceHolder.kt +++ b/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceHolder.kt @@ -1,7 +1,7 @@ -package com.vanced.manager.core.preferences.holder +package com.vanced.manager.preferences.holder -import com.vanced.manager.core.preferences.managerStringPreference -import com.vanced.manager.core.preferences.managerStringSetPreference +import com.vanced.manager.preferences.managerStringPreference +import com.vanced.manager.preferences.managerStringSetPreference var managerVariantPref by managerStringPreference( MANAGER_VARIANT_KEY, diff --git a/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceKeyHolder.kt b/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceKeyHolder.kt similarity index 91% rename from app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceKeyHolder.kt rename to app/src/main/java/com/vanced/manager/preferences/holder/PreferenceKeyHolder.kt index 42dbbc6472..c24886805e 100644 --- a/app/src/main/java/com/vanced/manager/core/preferences/holder/PreferenceKeyHolder.kt +++ b/app/src/main/java/com/vanced/manager/preferences/holder/PreferenceKeyHolder.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.core.preferences.holder +package com.vanced.manager.preferences.holder const val USE_CUSTOM_TABS_KEY = "use_custom_tabs" const val MANAGER_VARIANT_KEY = "manager_variant" diff --git a/app/src/main/java/com/vanced/manager/repository/AppRepository.kt b/app/src/main/java/com/vanced/manager/repository/AppRepository.kt index 918a94abce..964e1663c5 100644 --- a/app/src/main/java/com/vanced/manager/repository/AppRepository.kt +++ b/app/src/main/java/com/vanced/manager/repository/AppRepository.kt @@ -1,12 +1,12 @@ package com.vanced.manager.repository -import com.vanced.manager.datasource.PkgInfoDatasource +import com.vanced.manager.domain.model.App import com.vanced.manager.domain.model.AppData import com.vanced.manager.domain.model.AppState import com.vanced.manager.domain.model.AppType -import com.vanced.manager.domain.model.App import com.vanced.manager.network.GithubService import com.vanced.manager.network.dto.GithubReleaseDto +import com.vanced.manager.repository.source.PkgInfoDatasource interface AppRepository { @@ -54,8 +54,10 @@ class AppRepositoryImpl( val githubRelease = githubService.getVancedYoutubeRelease() val remoteVersionCode = githubRelease.getVersionCode() val remoteVersionName = githubRelease.getVersionName() - val installedVersionCode = pkgInfoDatasource.getVersionCode(AppData.PACKAGE_ROOT_VANCED_YOUTUBE) - val installedVersionName = pkgInfoDatasource.getVersionName(AppData.PACKAGE_ROOT_VANCED_YOUTUBE) + val installedVersionCode = + pkgInfoDatasource.getVersionCode(AppData.PACKAGE_ROOT_VANCED_YOUTUBE) + val installedVersionName = + pkgInfoDatasource.getVersionName(AppData.PACKAGE_ROOT_VANCED_YOUTUBE) return App( name = AppData.NAME_VANCED_YOUTUBE, iconResId = AppData.ICON_VANCED_YOUTUBE, @@ -75,8 +77,10 @@ class AppRepositoryImpl( val githubRelease = githubService.getVancedYoutubeMusicRelease() val remoteVersionCode = githubRelease.getVersionCode() val remoteVersionName = githubRelease.getVersionName() - val installedVersionCode = pkgInfoDatasource.getVersionCode(AppData.PACKAGE_VANCED_YOUTUBE_MUSIC) - val installedVersionName = pkgInfoDatasource.getVersionName(AppData.PACKAGE_VANCED_YOUTUBE_MUSIC) + val installedVersionCode = + pkgInfoDatasource.getVersionCode(AppData.PACKAGE_VANCED_YOUTUBE_MUSIC) + val installedVersionName = + pkgInfoDatasource.getVersionName(AppData.PACKAGE_VANCED_YOUTUBE_MUSIC) return App( name = AppData.NAME_VANCED_YOUTUBE_MUSIC, iconResId = AppData.ICON_VANCED_YOUTUBE_MUSIC, @@ -96,8 +100,10 @@ class AppRepositoryImpl( val githubRelease = githubService.getVancedYoutubeMusicRelease() val remoteVersionCode = githubRelease.getVersionCode() val remoteVersionName = githubRelease.getVersionName() - val installedVersionCode = pkgInfoDatasource.getVersionCode(AppData.PACKAGE_ROOT_VANCED_YOUTUBE_MUSIC) - val installedVersionName = pkgInfoDatasource.getVersionName(AppData.PACKAGE_ROOT_VANCED_YOUTUBE_MUSIC) + val installedVersionCode = + pkgInfoDatasource.getVersionCode(AppData.PACKAGE_ROOT_VANCED_YOUTUBE_MUSIC) + val installedVersionName = + pkgInfoDatasource.getVersionName(AppData.PACKAGE_ROOT_VANCED_YOUTUBE_MUSIC) return App( name = AppData.NAME_VANCED_YOUTUBE_MUSIC, iconResId = AppData.ICON_VANCED_YOUTUBE_MUSIC, diff --git a/app/src/main/java/com/vanced/manager/repository/PreferenceRepository.kt b/app/src/main/java/com/vanced/manager/repository/PreferenceRepository.kt index be9b71d744..b4140d19c6 100644 --- a/app/src/main/java/com/vanced/manager/repository/PreferenceRepository.kt +++ b/app/src/main/java/com/vanced/manager/repository/PreferenceRepository.kt @@ -2,8 +2,8 @@ package com.vanced.manager.repository import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.runtime.Composable -import com.vanced.manager.datasource.PreferenceData -import com.vanced.manager.datasource.PreferenceDatasource +import com.vanced.manager.repository.source.PreferenceData +import com.vanced.manager.repository.source.PreferenceDatasource interface PreferenceRepository { diff --git a/app/src/main/java/com/vanced/manager/datasource/PkgInfoDatasource.kt b/app/src/main/java/com/vanced/manager/repository/source/PkgInfoDatasource.kt similarity index 94% rename from app/src/main/java/com/vanced/manager/datasource/PkgInfoDatasource.kt rename to app/src/main/java/com/vanced/manager/repository/source/PkgInfoDatasource.kt index bbcfd0c46a..b9e57d6ba4 100644 --- a/app/src/main/java/com/vanced/manager/datasource/PkgInfoDatasource.kt +++ b/app/src/main/java/com/vanced/manager/repository/source/PkgInfoDatasource.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.datasource +package com.vanced.manager.repository.source import android.annotation.SuppressLint import android.content.pm.PackageManager @@ -40,7 +40,7 @@ class PkgInfoDatasourceImpl( @SuppressLint("WrongConstant") override fun getVersionName(packageName: String): String? { return try { - packageManager + packageManager .getPackageInfo(packageName, FLAG_NOTHING) .versionName } catch (e: PackageManager.NameNotFoundException) { diff --git a/app/src/main/java/com/vanced/manager/datasource/PreferenceDatasource.kt b/app/src/main/java/com/vanced/manager/repository/source/PreferenceDatasource.kt similarity index 78% rename from app/src/main/java/com/vanced/manager/datasource/PreferenceDatasource.kt rename to app/src/main/java/com/vanced/manager/repository/source/PreferenceDatasource.kt index 7fd5c2fedf..8d26d67459 100644 --- a/app/src/main/java/com/vanced/manager/datasource/PreferenceDatasource.kt +++ b/app/src/main/java/com/vanced/manager/repository/source/PreferenceDatasource.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.datasource +package com.vanced.manager.repository.source import android.content.SharedPreferences @@ -15,19 +15,28 @@ class PreferenceDatasourceImpl( ) : PreferenceDatasource { override var managerUseCustomTabs: Boolean - get() = getBoolean(PreferenceData.MANAGER_USE_CUSTOM_TABS_KEY, PreferenceData.MANAGER_USE_CUSTOM_TABS_DEFAULT_VALUE) + get() = getBoolean( + PreferenceData.MANAGER_USE_CUSTOM_TABS_KEY, + PreferenceData.MANAGER_USE_CUSTOM_TABS_DEFAULT_VALUE + ) set(value) { putBoolean(PreferenceData.MANAGER_USE_CUSTOM_TABS_KEY, value) } override var managerMode: String - get() = getString(PreferenceData.MANAGER_MODE_KEY, PreferenceData.MANAGER_MODE_DEFAULT_VALUE) + get() = getString( + PreferenceData.MANAGER_MODE_KEY, + PreferenceData.MANAGER_MODE_DEFAULT_VALUE + ) set(value) { putString(PreferenceData.MANAGER_MODE_KEY, value) } override var managerTheme: String - get() = getString(PreferenceData.MANAGER_THEME_KEY, PreferenceData.MANAGER_THEME_DEFAULT_VALUE) + get() = getString( + PreferenceData.MANAGER_THEME_KEY, + PreferenceData.MANAGER_THEME_DEFAULT_VALUE + ) set(value) { putString(PreferenceData.MANAGER_THEME_KEY, value) } @@ -39,11 +48,11 @@ class PreferenceDatasourceImpl( private fun getBoolean(key: String, defaultValue: Boolean): Boolean { return sharedPreferences.getBoolean(key, defaultValue) } - + private fun putString(key: String, value: String) { sharedPreferences.edit().putString(key, value).apply() } - + private fun putBoolean(key: String, value: Boolean) { sharedPreferences.edit().putBoolean(key, value).apply() } @@ -56,7 +65,7 @@ object PreferenceData { const val MANAGER_MODE_KEY = "manager_behaviour_mode" const val MANAGER_MODE_VALUE_ROOT = "root" - const val MANAGER_MODE_VALUE_NONROOT= "nonroot" + const val MANAGER_MODE_VALUE_NONROOT = "nonroot" const val MANAGER_MODE_DEFAULT_VALUE = MANAGER_MODE_VALUE_NONROOT const val MANAGER_THEME_KEY = "manager_appearance_theme" diff --git a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt index a8882d520b..9416609e69 100644 --- a/app/src/main/java/com/vanced/manager/ui/MainActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/MainActivity.kt @@ -14,8 +14,8 @@ import com.github.zsoltk.compose.backpress.BackPressHandler import com.github.zsoltk.compose.backpress.LocalBackPressHandler import com.github.zsoltk.compose.router.Router import com.google.accompanist.systemuicontroller.rememberSystemUiController -import com.vanced.manager.core.installer.service.AppInstallService -import com.vanced.manager.core.installer.service.AppUninstallService +import com.vanced.manager.installer.service.AppInstallService +import com.vanced.manager.installer.service.AppUninstallService import com.vanced.manager.ui.screen.* import com.vanced.manager.ui.theme.ManagerTheme import com.vanced.manager.ui.util.Screen diff --git a/app/src/main/java/com/vanced/manager/ui/SplashScreenActivity.kt b/app/src/main/java/com/vanced/manager/ui/SplashScreenActivity.kt index 1670d3866e..c82dcf68ab 100644 --- a/app/src/main/java/com/vanced/manager/ui/SplashScreenActivity.kt +++ b/app/src/main/java/com/vanced/manager/ui/SplashScreenActivity.kt @@ -10,7 +10,7 @@ import com.vanced.manager.BuildConfig class SplashScreenActivity : ComponentActivity() { init { - Shell.enableVerboseLogging = BuildConfig.DEBUG; + Shell.enableVerboseLogging = BuildConfig.DEBUG Shell.setDefaultBuilder( Shell.Builder .create() diff --git a/app/src/main/java/com/vanced/manager/ui/component/ManagerCard.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerCard.kt index cbf96514f6..890d68c7e0 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/ManagerCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerCard.kt @@ -49,6 +49,7 @@ fun ManagerCard( ) } } + @Composable fun ManagerElevatedCard( modifier: Modifier = Modifier, @@ -86,6 +87,7 @@ fun ManagerElevatedCard( ) } } + @Composable fun ManagerOutlinedCard( modifier: Modifier = Modifier, diff --git a/app/src/main/java/com/vanced/manager/ui/component/ManagerListItem.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerListItem.kt index e4d68452e6..b89e021dee 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/ManagerListItem.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerListItem.kt @@ -37,7 +37,7 @@ fun ManagerListItem( .weight(1f) .padding( vertical = - if (description != null) DefaultContentPaddingVertical - 4.dp else DefaultContentPaddingVertical, + if (description != null) DefaultContentPaddingVertical - 4.dp else DefaultContentPaddingVertical, ) .align(Alignment.CenterVertically) ) { diff --git a/app/src/main/java/com/vanced/manager/ui/component/ManagerNavigator.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerNavigator.kt index af5466b166..7148c92b31 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/ManagerNavigator.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerNavigator.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.ui.navigation +package com.vanced.manager.ui.component import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedContentScope diff --git a/app/src/main/java/com/vanced/manager/ui/component/ManagerPreference.kt b/app/src/main/java/com/vanced/manager/ui/component/ManagerPreference.kt index eac363d787..c3329422a6 100644 --- a/app/src/main/java/com/vanced/manager/ui/component/ManagerPreference.kt +++ b/app/src/main/java/com/vanced/manager/ui/component/ManagerPreference.kt @@ -212,7 +212,7 @@ private fun ListDialogRadiobuttonItem( ) { ListDialogItem( modifier = modifier, - text = text, + text = text, onClick = onClick, trailing = { RadioButton( @@ -232,7 +232,7 @@ private fun ListDialogCheckboxItem( ) { ListDialogItem( modifier = modifier, - text = text, + text = text, onClick = { onCheckedChange(!checked) }, diff --git a/app/src/main/java/com/vanced/manager/ui/screen/ConfigurationScreen.kt b/app/src/main/java/com/vanced/manager/ui/screen/ConfigurationScreen.kt index df3802fb90..7a388f6721 100644 --- a/app/src/main/java/com/vanced/manager/ui/screen/ConfigurationScreen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screen/ConfigurationScreen.kt @@ -178,7 +178,7 @@ private fun ConfigurationBottomBar( shrinkHorizontally(tween(exitDuration)) + scaleOut(tween(exitDuration)), - ) { + ) { TextButton(onClick = onBackClick) { ManagerText(text = "Back") } diff --git a/app/src/main/java/com/vanced/manager/ui/screen/HomeScreen.kt b/app/src/main/java/com/vanced/manager/ui/screen/HomeScreen.kt index d97c6911e0..369ef1d774 100644 --- a/app/src/main/java/com/vanced/manager/ui/screen/HomeScreen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screen/HomeScreen.kt @@ -1,5 +1,6 @@ package com.vanced.manager.ui.screen +import androidx.annotation.DrawableRes import androidx.compose.animation.* import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth @@ -17,9 +18,8 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.unit.dp import com.google.accompanist.swiperefresh.rememberSwipeRefreshState import com.vanced.manager.R -import com.vanced.manager.core.util.socialMedia -import com.vanced.manager.core.util.sponsors import com.vanced.manager.domain.model.App +import com.vanced.manager.network.util.* import com.vanced.manager.ui.component.* import com.vanced.manager.ui.resource.managerString import com.vanced.manager.ui.util.Screen @@ -257,3 +257,66 @@ private inline fun HomeScreenBody( } } } + +data class Link( + val title: String, + val link: String, + @DrawableRes val icon: Int +) + + +val sponsors = listOf( + Link( + title = "Brave", + link = URL_SPONSOR_BRAVE, + icon = R.drawable.ic_brave + ), + Link( + title = "Adguard", + link = URL_SPONSOR_ADGUARD, + icon = R.drawable.ic_adguard + ) +) + +val socialMedia = listOf( + Link( + title = "Instagram", + link = URL_MEDIA_INSTAGRAM, + icon = R.drawable.ic_instagram + ), + Link( + title = "YouTube", + link = URL_MEDIA_YOUTUBE, + icon = R.drawable.ic_youtube + ), + Link( + title = "GitHub", + link = URL_MEDIA_GITHUB, + icon = R.drawable.ic_github + ), + Link( + title = "Website", + link = URL_MEDIA_WEBSITE, + icon = R.drawable.ic_website + ), + Link( + title = "Telegram", + link = URL_MEDIA_TELEGRAM, + icon = R.drawable.ic_telegram + ), + Link( + title = "Twitter", + link = URL_MEDIA_TWITTER, + icon = R.drawable.ic_twitter + ), + Link( + title = "Discord", + link = URL_MEDIA_DISCORD, + icon = R.drawable.ic_discord + ), + Link( + title = "Reddit", + link = URL_MEDIA_REDDIT, + icon = R.drawable.ic_reddit + ), +) diff --git a/app/src/main/java/com/vanced/manager/ui/screen/SettingsScreen.kt b/app/src/main/java/com/vanced/manager/ui/screen/SettingsScreen.kt index 9f0d081fda..a9dd76a110 100644 --- a/app/src/main/java/com/vanced/manager/ui/screen/SettingsScreen.kt +++ b/app/src/main/java/com/vanced/manager/ui/screen/SettingsScreen.kt @@ -11,13 +11,13 @@ import androidx.compose.runtime.* import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import com.vanced.manager.R -import com.vanced.manager.core.util.isMagiskInstalled import com.vanced.manager.repository.ManagerMode import com.vanced.manager.repository.ManagerTheme import com.vanced.manager.ui.component.* import com.vanced.manager.ui.resource.managerString import com.vanced.manager.ui.util.Screen import com.vanced.manager.ui.viewmodel.SettingsViewModel +import com.vanced.manager.util.isMagiskInstalled import org.koin.androidx.compose.viewModel @ExperimentalMaterial3Api diff --git a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt index 683ba4811f..26ded2916b 100644 --- a/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt +++ b/app/src/main/java/com/vanced/manager/ui/theme/Theme.kt @@ -92,7 +92,7 @@ fun ManagerTheme( ) } else { apiDependantColorScheme( - dynamic = { dynamicLightColorScheme(context)}, + dynamic = { dynamicLightColorScheme(context) }, static = { LightThemeColors } ) } diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt index 201dc8e0c6..e04ba03e3d 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt @@ -7,18 +7,18 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.vanced.manager.core.downloader.base.AppDownloader -import com.vanced.manager.core.downloader.impl.MicrogDownloader -import com.vanced.manager.core.downloader.impl.MusicDownloader -import com.vanced.manager.core.downloader.impl.VancedDownloader -import com.vanced.manager.core.installer.impl.MicrogInstaller -import com.vanced.manager.core.installer.impl.MusicInstaller -import com.vanced.manager.core.installer.impl.VancedInstaller -import com.vanced.manager.core.installer.util.PMRootResult -import com.vanced.manager.core.preferences.holder.managerVariantPref +import com.vanced.manager.downloader.base.AppDownloader +import com.vanced.manager.downloader.impl.MicrogDownloader +import com.vanced.manager.downloader.impl.MusicDownloader +import com.vanced.manager.downloader.impl.VancedDownloader +import com.vanced.manager.installer.impl.MicrogInstaller +import com.vanced.manager.installer.impl.MusicInstaller +import com.vanced.manager.installer.impl.VancedInstaller +import com.vanced.manager.installer.util.PMRootResult import com.vanced.manager.network.util.MICROG_NAME import com.vanced.manager.network.util.MUSIC_NAME import com.vanced.manager.network.util.VANCED_NAME +import com.vanced.manager.preferences.holder.managerVariantPref import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -107,10 +107,12 @@ class InstallViewModel( installApp(appName, appVersions) } is AppDownloader.DownloadStatus.Error -> { - log(Log.Error( - displayText = "Failed to download ${download.fileName}", - stacktrace = download.error - )) + log( + Log.Error( + displayText = "Failed to download ${download.fileName}", + stacktrace = download.error + ) + ) } } } diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt index 8292a840a2..aaeba38af6 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/MainViewModel.kt @@ -8,9 +8,11 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.AndroidViewModel import androidx.lifecycle.viewModelScope -import com.vanced.manager.core.installer.util.PM import com.vanced.manager.domain.model.App -import com.vanced.manager.repository.* +import com.vanced.manager.installer.util.PM +import com.vanced.manager.repository.AppRepository +import com.vanced.manager.repository.ManagerMode +import com.vanced.manager.repository.PreferenceRepository import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.launch diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/SettingsViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/SettingsViewModel.kt index 807bb31a48..9d2dd1c02f 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/SettingsViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/SettingsViewModel.kt @@ -5,8 +5,6 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue import androidx.lifecycle.ViewModel import com.vanced.manager.R -import com.vanced.manager.core.preferences.managerBooleanPreference -import com.vanced.manager.core.preferences.managerStringPreference import com.vanced.manager.repository.ManagerMode import com.vanced.manager.repository.ManagerTheme import com.vanced.manager.repository.PreferenceRepository @@ -21,17 +19,17 @@ class SettingsViewModel( private set var managerTheme by mutableStateOf(preferenceRepository.managerTheme) private set - + fun saveManagerUseCustomTabs(value: Boolean) { managerUseCustomTabs = value preferenceRepository.managerUseCustomTabs = value } - + fun saveManagerMode(value: ManagerMode) { managerMode = value preferenceRepository.managerMode = value } - + fun saveManagerTheme(value: ManagerTheme) { managerTheme = value preferenceRepository.managerTheme = value diff --git a/app/src/main/java/com/vanced/manager/ui/widget/AppCard.kt b/app/src/main/java/com/vanced/manager/ui/widget/AppCard.kt index 63a79eccd9..a38bc5f2a1 100644 --- a/app/src/main/java/com/vanced/manager/ui/widget/AppCard.kt +++ b/app/src/main/java/com/vanced/manager/ui/widget/AppCard.kt @@ -5,7 +5,10 @@ import androidx.compose.foundation.layout.* import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Info -import androidx.compose.material.icons.rounded.* +import androidx.compose.material.icons.rounded.DeleteForever +import androidx.compose.material.icons.rounded.GetApp +import androidx.compose.material.icons.rounded.Launch +import androidx.compose.material.icons.rounded.Update import androidx.compose.material3.* import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment diff --git a/app/src/main/java/com/vanced/manager/core/util/AppHelper.kt b/app/src/main/java/com/vanced/manager/util/AppHelper.kt similarity index 86% rename from app/src/main/java/com/vanced/manager/core/util/AppHelper.kt rename to app/src/main/java/com/vanced/manager/util/AppHelper.kt index cfcdd85692..7d4369d5ea 100644 --- a/app/src/main/java/com/vanced/manager/core/util/AppHelper.kt +++ b/app/src/main/java/com/vanced/manager/util/AppHelper.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.core.util +package com.vanced.manager.util fun getLatestOrProvidedAppVersion( version: String, diff --git a/app/src/main/java/com/vanced/manager/util/Arch.kt b/app/src/main/java/com/vanced/manager/util/Arch.kt new file mode 100644 index 0000000000..df160cebf2 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/util/Arch.kt @@ -0,0 +1,10 @@ +package com.vanced.manager.util + +import android.os.Build + +val arch + get() = when { + Build.SUPPORTED_ABIS.contains("x86") -> "x86" + Build.SUPPORTED_ABIS.contains("arm64-v8a") -> "arm64_v8a" + else -> "armeabi_v7a" + } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/core/util/Coroutines.kt b/app/src/main/java/com/vanced/manager/util/Coroutines.kt similarity index 90% rename from app/src/main/java/com/vanced/manager/core/util/Coroutines.kt rename to app/src/main/java/com/vanced/manager/util/Coroutines.kt index 6339e3f96b..2ca647eec7 100644 --- a/app/src/main/java/com/vanced/manager/core/util/Coroutines.kt +++ b/app/src/main/java/com/vanced/manager/util/Coroutines.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.core.util +package com.vanced.manager.util import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch diff --git a/app/src/main/java/com/vanced/manager/core/io/Util.kt b/app/src/main/java/com/vanced/manager/util/IO.kt similarity index 96% rename from app/src/main/java/com/vanced/manager/core/io/Util.kt rename to app/src/main/java/com/vanced/manager/util/IO.kt index df387453ae..0271bce5fb 100644 --- a/app/src/main/java/com/vanced/manager/core/io/Util.kt +++ b/app/src/main/java/com/vanced/manager/util/IO.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.core.io +package com.vanced.manager.util import okhttp3.ResponseBody import java.io.FileOutputStream diff --git a/app/src/main/java/com/vanced/manager/core/util/SuShell.kt b/app/src/main/java/com/vanced/manager/util/SuShell.kt similarity index 93% rename from app/src/main/java/com/vanced/manager/core/util/SuShell.kt rename to app/src/main/java/com/vanced/manager/util/SuShell.kt index 6a6324d427..38a5945cd9 100644 --- a/app/src/main/java/com/vanced/manager/core/util/SuShell.kt +++ b/app/src/main/java/com/vanced/manager/util/SuShell.kt @@ -1,4 +1,4 @@ -package com.vanced.manager.core.util +package com.vanced.manager.util import com.topjohnwu.superuser.Shell import kotlin.coroutines.resume From a1662bab5ad7115f41e12c79a34b19afd2457bcc Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Sat, 5 Mar 2022 12:39:07 +0400 Subject: [PATCH 116/118] start migrating packagemanager to di --- .../com/vanced/manager/ManagerApplication.kt | 1 + .../com/vanced/manager/di/DatasourceModule.kt | 11 - .../com/vanced/manager/di/InstallerModuke.kt | 30 +- .../com/vanced/manager/di/ManagerModule.kt | 25 + .../com/vanced/manager/di/RepositoryModule.kt | 11 +- .../manager/installer/base/AppInstaller.kt | 6 +- .../manager/installer/impl/MicrogInstaller.kt | 17 +- .../manager/installer/impl/MusicInstaller.kt | 28 +- .../manager/installer/impl/VancedInstaller.kt | 24 +- .../vanced/manager/installer/util/PMRoot.kt | 85 ++- .../vanced/manager/installer/util/Patcher.kt | 50 +- .../manager/installer/util/RootPatchHelper.kt | 21 +- .../manager/repository/AppRepository.kt | 37 +- .../repository/manager/PackageManager.kt | 486 ++++++++++++++++++ .../repository/source/PkgInfoDatasource.kt | 50 -- .../manager/ui/viewmodel/InstallViewModel.kt | 8 +- .../java/com/vanced/manager/util/SuShell.kt | 25 +- 17 files changed, 702 insertions(+), 213 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/di/ManagerModule.kt create mode 100644 app/src/main/java/com/vanced/manager/repository/manager/PackageManager.kt delete mode 100644 app/src/main/java/com/vanced/manager/repository/source/PkgInfoDatasource.kt diff --git a/app/src/main/java/com/vanced/manager/ManagerApplication.kt b/app/src/main/java/com/vanced/manager/ManagerApplication.kt index b22a632e69..647ab8f9ec 100644 --- a/app/src/main/java/com/vanced/manager/ManagerApplication.kt +++ b/app/src/main/java/com/vanced/manager/ManagerApplication.kt @@ -19,6 +19,7 @@ class ManagerApplication : Application() { datasourceModule, downloaderModule, installerModule, + managerModule, networkModule, repositoryModule, serviceModule, diff --git a/app/src/main/java/com/vanced/manager/di/DatasourceModule.kt b/app/src/main/java/com/vanced/manager/di/DatasourceModule.kt index 65164f05cc..d5eafe56d8 100644 --- a/app/src/main/java/com/vanced/manager/di/DatasourceModule.kt +++ b/app/src/main/java/com/vanced/manager/di/DatasourceModule.kt @@ -1,8 +1,6 @@ package com.vanced.manager.di import android.content.Context -import com.vanced.manager.repository.source.PkgInfoDatasource -import com.vanced.manager.repository.source.PkgInfoDatasourceImpl import com.vanced.manager.repository.source.PreferenceDatasource import com.vanced.manager.repository.source.PreferenceDatasourceImpl import org.koin.android.ext.koin.androidContext @@ -10,14 +8,6 @@ import org.koin.dsl.module val datasourceModule = module { - fun providePkgInfoDatasource( - context: Context - ): PkgInfoDatasource { - return PkgInfoDatasourceImpl( - packageManager = context.packageManager - ) - } - fun providePreferenceDatasource( context: Context ): PreferenceDatasource { @@ -29,6 +19,5 @@ val datasourceModule = module { ) } - single { providePkgInfoDatasource(androidContext()) } single { providePreferenceDatasource(androidContext()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt b/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt index 2fa146aa4b..005b4a3425 100644 --- a/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt +++ b/app/src/main/java/com/vanced/manager/di/InstallerModuke.kt @@ -4,36 +4,48 @@ import android.content.Context import com.vanced.manager.installer.impl.MicrogInstaller import com.vanced.manager.installer.impl.MusicInstaller import com.vanced.manager.installer.impl.VancedInstaller +import com.vanced.manager.repository.manager.NonrootPackageManager +import com.vanced.manager.repository.manager.RootPackageManager import org.koin.android.ext.koin.androidContext import org.koin.dsl.module val installerModule = module { fun provideVancedInstaller( - context: Context + context: Context, + nonrootPackageManager: NonrootPackageManager, + rootPackageManager: RootPackageManager ): VancedInstaller { return VancedInstaller( - context = context + context = context, + nonrootPackageManager = nonrootPackageManager, + rootPackageManager = rootPackageManager ) } fun provideMusicInstaller( - context: Context + context: Context, + nonrootPackageManager: NonrootPackageManager, + rootPackageManager: RootPackageManager ): MusicInstaller { return MusicInstaller( - context = context + context = context, + nonrootPackageManager = nonrootPackageManager, + rootPackageManager = rootPackageManager ) } fun provideMicrogInstaller( - context: Context + context: Context, + nonrootPackageManager: NonrootPackageManager, ): MicrogInstaller { return MicrogInstaller( - context = context + context = context, + nonrootPackageManager = nonrootPackageManager ) } - single { provideVancedInstaller(androidContext()) } - single { provideMusicInstaller(androidContext()) } - single { provideMicrogInstaller(androidContext()) } + single { provideVancedInstaller(androidContext(), get(), get()) } + single { provideMusicInstaller(androidContext(), get(), get()) } + single { provideMicrogInstaller(androidContext(), get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/ManagerModule.kt b/app/src/main/java/com/vanced/manager/di/ManagerModule.kt new file mode 100644 index 0000000000..604f6e49bb --- /dev/null +++ b/app/src/main/java/com/vanced/manager/di/ManagerModule.kt @@ -0,0 +1,25 @@ +package com.vanced.manager.di + +import android.content.Context +import com.vanced.manager.repository.manager.NonrootPackageManager +import com.vanced.manager.repository.manager.RootPackageManager +import org.koin.android.ext.koin.androidContext +import org.koin.dsl.module + +val managerModule = module { + + fun provideNonrootPackageManager( + context: Context + ): NonrootPackageManager { + return NonrootPackageManager( + context = context + ) + } + + fun provideRootPackageManager(): RootPackageManager { + return RootPackageManager() + } + + single { provideNonrootPackageManager(androidContext()) } + single { provideRootPackageManager() } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt b/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt index 103ad99446..c9dc67e7f1 100644 --- a/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt +++ b/app/src/main/java/com/vanced/manager/di/RepositoryModule.kt @@ -5,7 +5,8 @@ import com.vanced.manager.repository.AppRepository import com.vanced.manager.repository.AppRepositoryImpl import com.vanced.manager.repository.PreferenceRepository import com.vanced.manager.repository.PreferenceRepositoryImpl -import com.vanced.manager.repository.source.PkgInfoDatasource +import com.vanced.manager.repository.manager.NonrootPackageManager +import com.vanced.manager.repository.manager.RootPackageManager import com.vanced.manager.repository.source.PreferenceDatasource import org.koin.dsl.module @@ -13,11 +14,13 @@ val repositoryModule = module { fun provideGithubRepository( githubService: GithubService, - pkgInfoDatasource: PkgInfoDatasource + nonrootPackageManager: NonrootPackageManager, + rootPackageManager: RootPackageManager, ): AppRepository { return AppRepositoryImpl( githubService = githubService, - pkgInfoDatasource = pkgInfoDatasource + nonrootPackageManager = nonrootPackageManager, + rootPackageManager = rootPackageManager ) } @@ -29,6 +32,6 @@ val repositoryModule = module { ) } - single { provideGithubRepository(get(), get()) } + single { provideGithubRepository(get(), get(), get()) } single { providePreferenceRepository(get()) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/installer/base/AppInstaller.kt b/app/src/main/java/com/vanced/manager/installer/base/AppInstaller.kt index e5de5b53e5..771bf97bf4 100644 --- a/app/src/main/java/com/vanced/manager/installer/base/AppInstaller.kt +++ b/app/src/main/java/com/vanced/manager/installer/base/AppInstaller.kt @@ -1,11 +1,11 @@ package com.vanced.manager.installer.base -import com.vanced.manager.installer.util.PMRootResult +import com.vanced.manager.repository.manager.PackageManagerResult abstract class AppInstaller { - abstract fun install(appVersions: List<String>?) + abstract suspend fun install(appVersions: List<String>?) - abstract fun installRoot(appVersions: List<String>?): PMRootResult<Nothing> + abstract suspend fun installRoot(appVersions: List<String>?): PackageManagerResult<Nothing> } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/installer/impl/MicrogInstaller.kt b/app/src/main/java/com/vanced/manager/installer/impl/MicrogInstaller.kt index 6334dc7700..599a0361e6 100644 --- a/app/src/main/java/com/vanced/manager/installer/impl/MicrogInstaller.kt +++ b/app/src/main/java/com/vanced/manager/installer/impl/MicrogInstaller.kt @@ -3,23 +3,22 @@ package com.vanced.manager.installer.impl import android.content.Context import com.vanced.manager.downloader.util.getMicrogPath import com.vanced.manager.installer.base.AppInstaller -import com.vanced.manager.installer.util.PM -import com.vanced.manager.installer.util.PMRootResult +import com.vanced.manager.repository.manager.NonrootPackageManager +import com.vanced.manager.repository.manager.PackageManagerResult import java.io.File class MicrogInstaller( - private val context: Context + private val context: Context, + private val nonrootPackageManager: NonrootPackageManager, ) : AppInstaller() { - override fun install( - appVersions: List<String>? - ) { - val musicApk = File(getMicrogPath(context) + "/microg.apk") + override suspend fun install(appVersions: List<String>?) { + val musicApk = File(getMicrogPath(context), "microg.apk") - PM.installApp(musicApk, context) + nonrootPackageManager.installApp(musicApk) } - override fun installRoot(appVersions: List<String>?): PMRootResult<Nothing> { + override suspend fun installRoot(appVersions: List<String>?): PackageManagerResult<Nothing> { throw IllegalAccessException("Vanced microG does not have a root installer") } diff --git a/app/src/main/java/com/vanced/manager/installer/impl/MusicInstaller.kt b/app/src/main/java/com/vanced/manager/installer/impl/MusicInstaller.kt index 3572b7507d..e2444fb944 100644 --- a/app/src/main/java/com/vanced/manager/installer/impl/MusicInstaller.kt +++ b/app/src/main/java/com/vanced/manager/installer/impl/MusicInstaller.kt @@ -5,23 +5,23 @@ import com.vanced.manager.domain.model.AppData import com.vanced.manager.downloader.util.getStockYoutubeMusicPath import com.vanced.manager.downloader.util.getVancedYoutubeMusicPath import com.vanced.manager.installer.base.AppInstaller -import com.vanced.manager.installer.util.PM -import com.vanced.manager.installer.util.PMRoot -import com.vanced.manager.installer.util.PMRootResult import com.vanced.manager.installer.util.RootPatchHelper import com.vanced.manager.preferences.holder.managerVariantPref import com.vanced.manager.preferences.holder.musicVersionPref import com.vanced.manager.preferences.holder.vancedVersionPref +import com.vanced.manager.repository.manager.NonrootPackageManager +import com.vanced.manager.repository.manager.PackageManagerResult +import com.vanced.manager.repository.manager.RootPackageManager import com.vanced.manager.util.getLatestOrProvidedAppVersion import java.io.File class MusicInstaller( - private val context: Context + private val context: Context, + private val rootPackageManager: RootPackageManager, + private val nonrootPackageManager: NonrootPackageManager, ) : AppInstaller() { - override fun install( - appVersions: List<String>? - ) { + override suspend fun install(appVersions: List<String>?) { val absoluteVersion = getLatestOrProvidedAppVersion(musicVersionPref, appVersions) val musicApk = File( @@ -32,33 +32,33 @@ class MusicInstaller( ) + "/music.apk" ) - PM.installApp(musicApk, context) + nonrootPackageManager.installApp(musicApk) } - override fun installRoot(appVersions: List<String>?): PMRootResult<Nothing> { + override suspend fun installRoot(appVersions: List<String>?): PackageManagerResult<Nothing> { val absoluteVersion = getLatestOrProvidedAppVersion(vancedVersionPref, appVersions) - val stockPath = getStockYoutubeMusicPath(absoluteVersion, context) + "/base.apk" - val vancedPath = getVancedYoutubeMusicPath(absoluteVersion, "root", context) + "/base.apk" + val stock = File(getStockYoutubeMusicPath(absoluteVersion, context), "base.apk") + val vanced = File(getVancedYoutubeMusicPath(absoluteVersion, "root", context), "base.apk") val prepareStock = RootPatchHelper.prepareStock( stockPackage = AppData.PACKAGE_ROOT_VANCED_YOUTUBE_MUSIC, stockVersion = absoluteVersion ) { - PMRoot.installApp(stockPath) + rootPackageManager.installApp(stock) } if (prepareStock.isError) return prepareStock val patchStock = RootPatchHelper.patchStock( - patchPath = vancedPath, + patchPath = vanced.absolutePath, stockPackage = AppData.PACKAGE_ROOT_VANCED_YOUTUBE_MUSIC, app = APP_KEY ) if (patchStock.isError) return patchStock - return PMRootResult.Success() + return PackageManagerResult.Success(null) } companion object { diff --git a/app/src/main/java/com/vanced/manager/installer/impl/VancedInstaller.kt b/app/src/main/java/com/vanced/manager/installer/impl/VancedInstaller.kt index e1763e38dd..cdbdf5afe7 100644 --- a/app/src/main/java/com/vanced/manager/installer/impl/VancedInstaller.kt +++ b/app/src/main/java/com/vanced/manager/installer/impl/VancedInstaller.kt @@ -5,41 +5,41 @@ import com.vanced.manager.domain.model.AppData import com.vanced.manager.downloader.util.getStockYoutubePath import com.vanced.manager.downloader.util.getVancedYoutubePath import com.vanced.manager.installer.base.AppInstaller -import com.vanced.manager.installer.util.PM -import com.vanced.manager.installer.util.PMRoot -import com.vanced.manager.installer.util.PMRootResult import com.vanced.manager.installer.util.RootPatchHelper import com.vanced.manager.preferences.holder.vancedVersionPref +import com.vanced.manager.repository.manager.NonrootPackageManager +import com.vanced.manager.repository.manager.PackageManagerResult +import com.vanced.manager.repository.manager.RootPackageManager import com.vanced.manager.util.getLatestOrProvidedAppVersion import java.io.File class VancedInstaller( - private val context: Context + private val context: Context, + private val rootPackageManager: RootPackageManager, + private val nonrootPackageManager: NonrootPackageManager, ) : AppInstaller() { - override fun install( - appVersions: List<String>? - ) { + override suspend fun install(appVersions: List<String>?) { val absoluteVersion = getLatestOrProvidedAppVersion(vancedVersionPref, appVersions) val apks = File(getVancedYoutubePath(absoluteVersion, "nonroot", context)) .listFiles() - PM.installSplitApp(apks!!, context) + nonrootPackageManager.installSplitApp(apks!!) } - override fun installRoot(appVersions: List<String>?): PMRootResult<Nothing> { + override suspend fun installRoot(appVersions: List<String>?): PackageManagerResult<Nothing> { val absoluteVersion = getLatestOrProvidedAppVersion(vancedVersionPref, appVersions) val stockApks = File(getStockYoutubePath(absoluteVersion, context)) - .listFiles()?.map { it.absolutePath } + .listFiles() val vancedBaseApk = getVancedYoutubePath(absoluteVersion, "root", context) + "/base.apk" val prepareStock = RootPatchHelper.prepareStock( stockPackage = AppData.PACKAGE_ROOT_VANCED_YOUTUBE, stockVersion = absoluteVersion, ) { - PMRoot.installSplitApp(stockApks!!) + rootPackageManager.installSplitApp(stockApks!!) } if (prepareStock.isError) return prepareStock @@ -52,7 +52,7 @@ class VancedInstaller( if (patchStock.isError) return patchStock - return PMRootResult.Success() + return PackageManagerResult.Success(null) } companion object { diff --git a/app/src/main/java/com/vanced/manager/installer/util/PMRoot.kt b/app/src/main/java/com/vanced/manager/installer/util/PMRoot.kt index 8e95a5297e..75a46b6bb1 100644 --- a/app/src/main/java/com/vanced/manager/installer/util/PMRoot.kt +++ b/app/src/main/java/com/vanced/manager/installer/util/PMRoot.kt @@ -3,6 +3,9 @@ package com.vanced.manager.installer.util import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.io.SuFile import com.topjohnwu.superuser.io.SuFileOutputStream +import com.vanced.manager.repository.manager.PackageManagerResult +import com.vanced.manager.repository.manager.PackageManagerStatus +import com.vanced.manager.repository.manager.getEnumForInstallFailed import com.vanced.manager.util.errString import com.vanced.manager.util.outString import java.io.File @@ -10,11 +13,11 @@ import java.io.IOException object PMRoot { - fun installApp(apkPath: String): PMRootResult<Nothing> { + fun installApp(apkPath: String): PackageManagerResult<Nothing> { val apk = File(apkPath) val tmpApk = copyApkToTemp(apk).getOrElse { exception -> - return PMRootResult.Error( - PMRootStatus.SESSION_FAILED_COPY, + return PackageManagerResult.Error( + PackageManagerStatus.SESSION_FAILED_COPY, exception.stackTraceToString() ) } @@ -25,28 +28,28 @@ object PMRoot { if (!install.isSuccess) { val errString = install.errString - return PMRootResult.Error(getEnumForInstallFailed(errString), errString) + return PackageManagerResult.Error(getEnumForInstallFailed(errString), errString) } - return PMRootResult.Success() + return PackageManagerResult.Success(null) } - fun installSplitApp(apkPaths: List<String>): PMRootResult<Nothing> { + fun installSplitApp(apkPaths: List<String>): PackageManagerResult<Nothing> { val installCreate = Shell.su("pm", "install-create", "-r").exec() if (!installCreate.isSuccess) - return PMRootResult.Error(PMRootStatus.SESSION_FAILED_CREATE, installCreate.errString) + return PackageManagerResult.Error(PackageManagerStatus.SESSION_FAILED_CREATE, installCreate.errString) val sessionId = installCreate.outString if (sessionId.toIntOrNull() == null) - return PMRootResult.Error(PMRootStatus.SESSION_INVALID_ID, installCreate.errString) + return PackageManagerResult.Error(PackageManagerStatus.SESSION_INVALID_ID, installCreate.errString) for (apkPath in apkPaths) { val apk = File(apkPath) val tmpApk = copyApkToTemp(apk).getOrElse { exception -> - return PMRootResult.Error( - PMRootStatus.SESSION_FAILED_COPY, + return PackageManagerResult.Error( + PackageManagerStatus.SESSION_FAILED_COPY, exception.stackTraceToString() ) } @@ -58,87 +61,87 @@ object PMRoot { tmpApk.delete() if (!installWrite.isSuccess) - return PMRootResult.Error(PMRootStatus.SESSION_FAILED_WRITE, installWrite.errString) + return PackageManagerResult.Error(PackageManagerStatus.SESSION_FAILED_WRITE, installWrite.errString) } val installCommit = Shell.su("pm", "install-commit", sessionId).exec() if (!installCommit.isSuccess) { val errString = installCommit.errString - return PMRootResult.Error(getEnumForInstallFailed(errString), errString) + return PackageManagerResult.Error(getEnumForInstallFailed(errString), errString) } - return PMRootResult.Success() + return PackageManagerResult.Success(null) } - fun uninstallApp(pkg: String): PMRootResult<Nothing> { + fun uninstallApp(pkg: String): PackageManagerResult<Nothing> { val uninstall = Shell.su("pm", "uninstall", pkg).exec() if (!uninstall.isSuccess) - return PMRootResult.Error(PMRootStatus.UNINSTALL_FAILED, uninstall.errString) + return PackageManagerResult.Error(PackageManagerStatus.UNINSTALL_FAILED, uninstall.errString) - return PMRootResult.Success() + return PackageManagerResult.Success(null) } - fun setInstallerPackage(targetPkg: String, installerPkg: String): PMRootResult<Nothing> { + fun setInstallerPackage(targetPkg: String, installerPkg: String): PackageManagerResult<Nothing> { val setInstaller = Shell.su("pm", "set-installer", targetPkg, installerPkg) .exec() if (!setInstaller.isSuccess) - return PMRootResult.Error( - PMRootStatus.ACTION_FAILED_SET_INSTALLER, + return PackageManagerResult.Error( + PackageManagerStatus.SET_FAILED_INSTALLER, setInstaller.errString ) - return PMRootResult.Success() + return PackageManagerResult.Success(null) } - fun forceStopApp(pkg: String): PMRootResult<Nothing> { + fun forceStopApp(pkg: String): PackageManagerResult<Nothing> { val stopApp = Shell.su("am", "force-stop", pkg).exec() if (!stopApp.isSuccess) - return PMRootResult.Error(PMRootStatus.ACTION_FAILED_FORCE_STOP_APP, stopApp.errString) + return PackageManagerResult.Error(PackageManagerStatus.APP_FAILED_FORCE_STOP, stopApp.errString) - return PMRootResult.Success() + return PackageManagerResult.Success(null) } - fun getPackageVersionName(pkg: String): PMRootResult<String> { + fun getPackageVersionName(pkg: String): PackageManagerResult<String> { val keyword = "versionName=" val dumpsys = Shell.su("dumpsys", "package", pkg, "|", "grep", keyword).exec() if (!dumpsys.isSuccess) - return PMRootResult.Error( - PMRootStatus.ACTION_FAILED_GET_PACKAGE_VERSION_NAME, + return PackageManagerResult.Error( + PackageManagerStatus.GET_FAILED_PACKAGE_VERSION_NAME, dumpsys.errString ) - return PMRootResult.Success(dumpsys.outString.removePrefix(keyword)) + return PackageManagerResult.Success(dumpsys.outString.removePrefix(keyword)) } - fun getPackageVersionCode(pkg: String): PMRootResult<Long> { + fun getPackageVersionCode(pkg: String): PackageManagerResult<Long> { val keyword = "versionCode=" val dumpsys = Shell.su("dumpsys", "package", pkg, "|", "grep", keyword).exec() if (!dumpsys.isSuccess) - return PMRootResult.Error( - PMRootStatus.ACTION_FAILED_GET_PACKAGE_VERSION_CODE, + return PackageManagerResult.Error( + PackageManagerStatus.GET_FAILED_PACKAGE_VERSION_CODE, dumpsys.errString ) - return PMRootResult.Success( + return PackageManagerResult.Success( dumpsys.outString.removePrefix(keyword).substringAfter("minSdk") .toLong() ) } - fun getPackageDir(pkg: String): PMRootResult<String> { + fun getPackageDir(pkg: String): PackageManagerResult<String> { val keyword = "path: " val dumpsys = Shell.su("dumpsys", "package", pkg, "|", "grep", keyword).exec() if (!dumpsys.isSuccess) - return PMRootResult.Error(PMRootStatus.ACTION_FAILED_GET_PACKAGE_DIR, dumpsys.errString) + return PackageManagerResult.Error(PackageManagerStatus.GET_FAILED_PACKAGE_DIR, dumpsys.errString) - return PMRootResult.Success(dumpsys.outString.removePrefix(keyword)) + return PackageManagerResult.Success(dumpsys.outString.removePrefix(keyword)) } } @@ -159,16 +162,4 @@ private fun copyApkToTemp(apk: File): Result<SuFile> { } return Result.success(tmpApk) -} - -private fun getEnumForInstallFailed(outString: String) = - when { - outString.contains("INSTALL_FAILED_ABORTED") -> PMRootStatus.INSTALL_FAILED_ABORTED - outString.contains("INSTALL_FAILED_ALREADY_EXISTS") -> PMRootStatus.INSTALL_FAILED_ALREADY_EXISTS - outString.contains("INSTALL_FAILED_CPU_ABI_INCOMPATIBLE") -> PMRootStatus.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE - outString.contains("INSTALL_FAILED_INSUFFICIENT_STORAGE") -> PMRootStatus.INSTALL_FAILED_INSUFFICIENT_STORAGE - outString.contains("INSTALL_FAILED_INVALID_APK") -> PMRootStatus.INSTALL_FAILED_INVALID_APK - outString.contains("INSTALL_FAILED_VERSION_DOWNGRADE") -> PMRootStatus.INSTALL_FAILED_VERSION_DOWNGRADE - outString.contains("INSTALL_PARSE_FAILED_NO_CERTIFICATES") -> PMRootStatus.INSTALL_FAILED_PARSE_NO_CERTIFICATES - else -> PMRootStatus.INSTALL_FAILED_UNKNOWN - } \ No newline at end of file +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/installer/util/Patcher.kt b/app/src/main/java/com/vanced/manager/installer/util/Patcher.kt index f9bfb13df9..af523990d2 100644 --- a/app/src/main/java/com/vanced/manager/installer/util/Patcher.kt +++ b/app/src/main/java/com/vanced/manager/installer/util/Patcher.kt @@ -5,6 +5,8 @@ import com.topjohnwu.superuser.io.SuFile import com.topjohnwu.superuser.io.SuFileOutputStream import com.vanced.manager.io.ManagerSuFile import com.vanced.manager.io.SUIOException +import com.vanced.manager.repository.manager.PackageManagerResult +import com.vanced.manager.repository.manager.PackageManagerStatus import com.vanced.manager.util.errString import java.io.File import java.io.IOException @@ -15,7 +17,7 @@ object Patcher { app: String, stockPackage: String, stockPath: String, - ): PMRootResult<Nothing> { + ): PackageManagerResult<Nothing> { val postFsDataScriptPath = getAppPostFsScriptPath(app) val serviceDScriptPath = getAppServiceDScriptPath(app) @@ -24,22 +26,22 @@ object Patcher { val copyServiceDScript = copyScriptToDestination(postFsDataScript, postFsDataScriptPath) if (copyServiceDScript.isFailure) - return PMRootResult.Error( - PMRootStatus.SCRIPT_FAILED_SETUP_POST_FS, + return PackageManagerResult.Error( + PackageManagerStatus.SCRIPT_FAILED_SETUP_POST_FS, copyServiceDScript.exceptionOrNull()!!.stackTraceToString() ) val copyPostFsDataScript = copyScriptToDestination(serviceDScript, serviceDScriptPath) if (copyPostFsDataScript.isFailure) - return PMRootResult.Error( - PMRootStatus.SCRIPT_FAILED_SETUP_SERVICE_D, + return PackageManagerResult.Error( + PackageManagerStatus.SCRIPT_FAILED_SETUP_SERVICE_D, copyPostFsDataScript.exceptionOrNull()!!.stackTraceToString() ) - return PMRootResult.Success() + return PackageManagerResult.Success(null) } - fun movePatchToDataAdb(patchPath: String, app: String): PMRootResult<Nothing> { + fun movePatchToDataAdb(patchPath: String, app: String): PackageManagerResult<Nothing> { val newPatchPath = getAppPatchPath(app) val patchApk = File(patchPath) @@ -53,42 +55,42 @@ object Patcher { try { patchApk.copyTo(newPatchApk) } catch (e: IOException) { - return PMRootResult.Error(PMRootStatus.PATCH_FAILED_COPY, e.stackTraceToString()) + return PackageManagerResult.Error(PackageManagerStatus.PATCH_FAILED_COPY, e.stackTraceToString()) } val chmod = Shell.su("chmod", "644", newPatchPath).exec() if (!chmod.isSuccess) - return PMRootResult.Error(PMRootStatus.PATCH_FAILED_CHMOD, chmod.errString) + return PackageManagerResult.Error(PackageManagerStatus.PATCH_FAILED_CHMOD, chmod.errString) val chown = Shell.su("chown", "system:system", newPatchPath).exec() if (!chmod.isSuccess) - return PMRootResult.Error(PMRootStatus.PATCH_FAILED_CHOWN, chown.errString) + return PackageManagerResult.Error(PackageManagerStatus.PATCH_FAILED_CHOWN, chown.errString) - return PMRootResult.Success() + return PackageManagerResult.Success(null) } - fun chconPatch(app: String): PMRootResult<Nothing> { + fun chconPatch(app: String): PackageManagerResult<Nothing> { val chcon = Shell.su("chcon u:object_r:apk_data_file:s0 ${getAppPatchPath(app)}").exec() if (!chcon.isSuccess) - return PMRootResult.Error(PMRootStatus.PATCH_FAILED_CHCON, chcon.errString) + return PackageManagerResult.Error(PackageManagerStatus.PATCH_FAILED_CHCON, chcon.errString) - return PMRootResult.Success() + return PackageManagerResult.Success(null) } - fun linkPatch(app: String, stockPackage: String, stockPath: String): PMRootResult<Nothing> { + fun linkPatch(app: String, stockPackage: String, stockPath: String): PackageManagerResult<Nothing> { val umount = Shell.su("""for i in ${'$'}(ls /data/app/ | grep $stockPackage | tr " "); do umount -l "/data/app/${"$"}i/base.apk"; done """) .exec() if (!umount.isSuccess) - return PMRootResult.Error(PMRootStatus.LINK_FAILED_UNMOUNT, umount.errString) + return PackageManagerResult.Error(PackageManagerStatus.LINK_FAILED_UNMOUNT, umount.errString) val mount = Shell.su("su", "-mm", "-c", """"mount -o bind ${getAppPatchPath(app)} $stockPath"""") .exec() if (!mount.isSuccess) - return PMRootResult.Error(PMRootStatus.LINK_FAILED_MOUNT, mount.errString) + return PackageManagerResult.Error(PackageManagerStatus.LINK_FAILED_MOUNT, mount.errString) - return PMRootResult.Success() + return PackageManagerResult.Success(null) } fun destroyPatch(app: String) = @@ -132,11 +134,11 @@ private fun cleanPatchFiles( postFsPath: String, serviceDPath: String, patchPath: String, -): PMRootResult<Nothing> { +): PackageManagerResult<Nothing> { val files = mapOf( - postFsPath to PMRootStatus.SCRIPT_FAILED_DESTROY_POST_FS, - serviceDPath to PMRootStatus.SCRIPT_FAILED_DESTROY_SERVICE_D, - patchPath to PMRootStatus.PATCH_FAILED_DESTROY, + postFsPath to PackageManagerStatus.SCRIPT_FAILED_DESTROY_POST_FS, + serviceDPath to PackageManagerStatus.SCRIPT_FAILED_DESTROY_SERVICE_D, + patchPath to PackageManagerStatus.PATCH_FAILED_DESTROY, ) for ((filePath, errorStatusType) in files) { @@ -145,11 +147,11 @@ private fun cleanPatchFiles( if (exists()) delete() } } catch (e: SUIOException) { - return PMRootResult.Error(errorStatusType, e.stackTraceToString()) + return PackageManagerResult.Error(errorStatusType, e.stackTraceToString()) } } - return PMRootResult.Success() + return PackageManagerResult.Success(null) } private fun copyScriptToDestination( diff --git a/app/src/main/java/com/vanced/manager/installer/util/RootPatchHelper.kt b/app/src/main/java/com/vanced/manager/installer/util/RootPatchHelper.kt index a7c3b6b5cd..04ec578a2c 100644 --- a/app/src/main/java/com/vanced/manager/installer/util/RootPatchHelper.kt +++ b/app/src/main/java/com/vanced/manager/installer/util/RootPatchHelper.kt @@ -1,8 +1,11 @@ package com.vanced.manager.installer.util +import com.vanced.manager.repository.manager.PackageManagerResult +import com.vanced.manager.repository.manager.getOrElse + object RootPatchHelper { - fun cleanPatches(app: String): PMRootResult<Nothing> { + fun cleanPatches(app: String): PackageManagerResult<Nothing> { val cleanOldPatches = Patcher.destroyOldPatch(app) if (cleanOldPatches.isError) return cleanOldPatches @@ -11,14 +14,14 @@ object RootPatchHelper { if (cleanOldPatches.isError) return cleanPatches - return PMRootResult.Success() + return PackageManagerResult.Success(null) } inline fun prepareStock( stockPackage: String, stockVersion: String, - install: () -> PMRootResult<Nothing> - ): PMRootResult<Nothing> { + install: () -> PackageManagerResult<Nothing> + ): PackageManagerResult<Nothing> { val stockYoutubeVersion = PMRoot.getPackageVersionName(stockPackage) .getOrElse { null } if (stockYoutubeVersion != stockVersion) { @@ -31,14 +34,14 @@ object RootPatchHelper { return installStock } - return PMRootResult.Success() + return PackageManagerResult.Success(null) } fun patchStock( patchPath: String, stockPackage: String, app: String - ): PMRootResult<Nothing> { + ): PackageManagerResult<Nothing> { val movePatch = Patcher.movePatchToDataAdb(patchPath, app) if (movePatch.isError) return movePatch @@ -51,14 +54,14 @@ object RootPatchHelper { .getOrElse { error -> return error }!! val setupScript = Patcher.setupScript(app, stockPackage, stockPackageDir) - if (setupScript is PMRootResult.Error) + if (setupScript is PackageManagerResult.Error) return setupScript val linkPatch = Patcher.linkPatch(app, stockPackage, stockPackageDir) - if (linkPatch is PMRootResult.Error) + if (linkPatch is PackageManagerResult.Error) return linkPatch - return PMRootResult.Success() + return PackageManagerResult.Success(null) } } \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/repository/AppRepository.kt b/app/src/main/java/com/vanced/manager/repository/AppRepository.kt index 964e1663c5..5c96efce77 100644 --- a/app/src/main/java/com/vanced/manager/repository/AppRepository.kt +++ b/app/src/main/java/com/vanced/manager/repository/AppRepository.kt @@ -6,7 +6,9 @@ import com.vanced.manager.domain.model.AppState import com.vanced.manager.domain.model.AppType import com.vanced.manager.network.GithubService import com.vanced.manager.network.dto.GithubReleaseDto -import com.vanced.manager.repository.source.PkgInfoDatasource +import com.vanced.manager.repository.manager.NonrootPackageManager +import com.vanced.manager.repository.manager.PackageManager +import com.vanced.manager.repository.manager.RootPackageManager interface AppRepository { @@ -26,15 +28,18 @@ interface AppRepository { class AppRepositoryImpl( private val githubService: GithubService, - private val pkgInfoDatasource: PkgInfoDatasource, + private val nonrootPackageManager: NonrootPackageManager, + private val rootPackageManager: RootPackageManager, ) : AppRepository { override suspend fun getVancedYoutubeNonroot(): App { val githubRelease = githubService.getVancedYoutubeRelease() val remoteVersionCode = githubRelease.getVersionCode() val remoteVersionName = githubRelease.getVersionName() - val installedVersionCode = pkgInfoDatasource.getVersionCode(AppData.PACKAGE_VANCED_YOUTUBE) - val installedVersionName = pkgInfoDatasource.getVersionName(AppData.PACKAGE_VANCED_YOUTUBE) + val installedVersionCode = + nonrootPackageManager.getVersionCode(AppData.PACKAGE_VANCED_YOUTUBE).getValueOrNull() + val installedVersionName = + nonrootPackageManager.getVersionName(AppData.PACKAGE_VANCED_YOUTUBE).getValueOrNull() return App( name = AppData.NAME_VANCED_YOUTUBE, iconResId = AppData.ICON_VANCED_YOUTUBE, @@ -55,9 +60,9 @@ class AppRepositoryImpl( val remoteVersionCode = githubRelease.getVersionCode() val remoteVersionName = githubRelease.getVersionName() val installedVersionCode = - pkgInfoDatasource.getVersionCode(AppData.PACKAGE_ROOT_VANCED_YOUTUBE) + rootPackageManager.getVersionCode(AppData.PACKAGE_ROOT_VANCED_YOUTUBE).getValueOrNull() val installedVersionName = - pkgInfoDatasource.getVersionName(AppData.PACKAGE_ROOT_VANCED_YOUTUBE) + rootPackageManager.getVersionName(AppData.PACKAGE_ROOT_VANCED_YOUTUBE).getValueOrNull() return App( name = AppData.NAME_VANCED_YOUTUBE, iconResId = AppData.ICON_VANCED_YOUTUBE, @@ -78,9 +83,9 @@ class AppRepositoryImpl( val remoteVersionCode = githubRelease.getVersionCode() val remoteVersionName = githubRelease.getVersionName() val installedVersionCode = - pkgInfoDatasource.getVersionCode(AppData.PACKAGE_VANCED_YOUTUBE_MUSIC) + nonrootPackageManager.getVersionCode(AppData.PACKAGE_VANCED_YOUTUBE_MUSIC).getValueOrNull() val installedVersionName = - pkgInfoDatasource.getVersionName(AppData.PACKAGE_VANCED_YOUTUBE_MUSIC) + nonrootPackageManager.getVersionName(AppData.PACKAGE_VANCED_YOUTUBE_MUSIC).getValueOrNull() return App( name = AppData.NAME_VANCED_YOUTUBE_MUSIC, iconResId = AppData.ICON_VANCED_YOUTUBE_MUSIC, @@ -101,9 +106,9 @@ class AppRepositoryImpl( val remoteVersionCode = githubRelease.getVersionCode() val remoteVersionName = githubRelease.getVersionName() val installedVersionCode = - pkgInfoDatasource.getVersionCode(AppData.PACKAGE_ROOT_VANCED_YOUTUBE_MUSIC) + rootPackageManager.getVersionCode(AppData.PACKAGE_ROOT_VANCED_YOUTUBE_MUSIC).getValueOrNull() val installedVersionName = - pkgInfoDatasource.getVersionName(AppData.PACKAGE_ROOT_VANCED_YOUTUBE_MUSIC) + rootPackageManager.getVersionName(AppData.PACKAGE_ROOT_VANCED_YOUTUBE_MUSIC).getValueOrNull() return App( name = AppData.NAME_VANCED_YOUTUBE_MUSIC, iconResId = AppData.ICON_VANCED_YOUTUBE_MUSIC, @@ -123,8 +128,10 @@ class AppRepositoryImpl( val githubRelease = githubService.getVancedMicrogRelease() val remoteVersionCode = githubRelease.getVersionCode() val remoteVersionName = githubRelease.getVersionName() - val installedVersionCode = pkgInfoDatasource.getVersionCode(AppData.PACKAGE_VANCED_MICROG) - val installedVersionName = pkgInfoDatasource.getVersionName(AppData.PACKAGE_VANCED_MICROG) + val installedVersionCode = + nonrootPackageManager.getVersionCode(AppData.PACKAGE_VANCED_MICROG).getValueOrNull() + val installedVersionName = + nonrootPackageManager.getVersionName(AppData.PACKAGE_VANCED_MICROG).getValueOrNull() return App( name = AppData.NAME_VANCED_MICROG, iconResId = AppData.ICON_VANCED_MICROG, @@ -144,8 +151,10 @@ class AppRepositoryImpl( val githubRelease = githubService.getVancedManagerRelease() val remoteVersionCode = githubRelease.getVersionCode() val remoteVersionName = githubRelease.getVersionName() - val installedVersionCode = pkgInfoDatasource.getVersionCode(AppData.PACKAGE_VANCED_MANAGER) - val installedVersionName = pkgInfoDatasource.getVersionName(AppData.PACKAGE_VANCED_MANAGER) + val installedVersionCode = + nonrootPackageManager.getVersionCode(AppData.PACKAGE_VANCED_MANAGER).getValueOrNull() + val installedVersionName = + nonrootPackageManager.getVersionName(AppData.PACKAGE_VANCED_MANAGER).getValueOrNull() return App( name = AppData.NAME_VANCED_MANAGER, iconResId = AppData.ICON_VANCED_MANAGER, diff --git a/app/src/main/java/com/vanced/manager/repository/manager/PackageManager.kt b/app/src/main/java/com/vanced/manager/repository/manager/PackageManager.kt new file mode 100644 index 0000000000..3928afe5bd --- /dev/null +++ b/app/src/main/java/com/vanced/manager/repository/manager/PackageManager.kt @@ -0,0 +1,486 @@ +package com.vanced.manager.repository.manager + +import android.annotation.SuppressLint +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.content.pm.PackageInstaller +import android.os.Build +import com.topjohnwu.superuser.Shell +import com.topjohnwu.superuser.io.SuFile +import com.topjohnwu.superuser.io.SuFileInputStream +import com.topjohnwu.superuser.io.SuFileOutputStream +import com.vanced.manager.installer.service.AppInstallService +import com.vanced.manager.installer.service.AppUninstallService +import com.vanced.manager.util.SuException +import com.vanced.manager.util.awaitOutputOrThrow +import java.io.File +import java.io.FileNotFoundException +import java.io.IOException +import kotlin.jvm.Throws + +interface PackageManager { + + suspend fun getVersionCode(packageName: String): PackageManagerResult<Int> + + suspend fun getVersionName(packageName: String): PackageManagerResult<String> + + suspend fun getInstallationDir(packageName: String): PackageManagerResult<String> + + suspend fun setInstaller(targetPackage: String, installerPackage: String): PackageManagerResult<Nothing> + + suspend fun forceStop(packageName: String): PackageManagerResult<Nothing> + + suspend fun installApp(apk: File): PackageManagerResult<Nothing> + + suspend fun installSplitApp(apks: Array<File>): PackageManagerResult<Nothing> + + suspend fun uninstallApp(packageName: String): PackageManagerResult<Nothing> + +} + +class NonrootPackageManager( + private val context: Context +) : PackageManager { + + @SuppressLint("WrongConstant") + @Suppress("DEPRECATION") + override suspend fun getVersionCode(packageName: String): PackageManagerResult<Int> { + return try { + val packageInfo = context.packageManager.getPackageInfo(packageName, FLAG_NOTHING) + val versionCode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + packageInfo.longVersionCode.and(VERSION_IGNORE_MAJOR).toInt() + } else { + packageInfo.versionCode + } + PackageManagerResult.Success(versionCode) + } catch (e: android.content.pm.PackageManager.NameNotFoundException) { + PackageManagerResult.Error( + status = PackageManagerStatus.GET_FAILED_PACKAGE_VERSION_CODE, + message = e.stackTraceToString() + ) + } + } + + @SuppressLint("WrongConstant") + override suspend fun getVersionName(packageName: String): PackageManagerResult<String> { + return try { + val versionName = context.packageManager + .getPackageInfo(packageName, FLAG_NOTHING) + .versionName + PackageManagerResult.Success(versionName) + } catch (e: android.content.pm.PackageManager.NameNotFoundException) { + PackageManagerResult.Error( + status = PackageManagerStatus.GET_FAILED_PACKAGE_VERSION_NAME, + message = e.stackTraceToString() + ) + } + } + + @SuppressLint("WrongConstant") + override suspend fun getInstallationDir(packageName: String): PackageManagerResult<String> { + return try { + val installationDir = context.packageManager + .getPackageInfo(packageName, FLAG_NOTHING) + .applicationInfo + .sourceDir + PackageManagerResult.Success(installationDir) + } catch (e: android.content.pm.PackageManager.NameNotFoundException) { + PackageManagerResult.Error( + status = PackageManagerStatus.GET_FAILED_PACKAGE_DIR, + message = e.stackTraceToString() + ) + } + } + + override suspend fun setInstaller( + targetPackage: String, + installerPackage: String + ): PackageManagerResult<Nothing> { + return PackageManagerResult.Error( + status = PackageManagerStatus.SET_FAILED_INSTALLER, + message = "Unsupported" + ) + } + + override suspend fun forceStop(packageName: String): PackageManagerResult<Nothing> { + return PackageManagerResult.Error( + status = PackageManagerStatus.APP_FAILED_FORCE_STOP, + message = "Unsupported" + ) + } + + override suspend fun installApp(apk: File): PackageManagerResult<Nothing> { + return createInstallationSession { + writeApkToSession(apk) + } + } + + override suspend fun installSplitApp(apks: Array<File>): PackageManagerResult<Nothing> { + return createInstallationSession { + for (apk in apks) { + writeApkToSession(apk) + } + } + } + + override suspend fun uninstallApp(packageName: String): PackageManagerResult<Nothing> { + val packageInstaller = context.packageManager.packageInstaller + val pendingIntent = PendingIntent.getService( + context, + 0, + Intent(context, AppUninstallService::class.java), + intentFlags + ).intentSender + packageInstaller.uninstall(packageName, pendingIntent) + return PackageManagerResult.Success(null) + } + + private inline fun createInstallationSession( + block: PackageInstaller.Session.() -> Unit + ): PackageManagerResult<Nothing> { + val packageInstaller = context.packageManager.packageInstaller + val sessionParams = PackageInstaller.SessionParams( + PackageInstaller.SessionParams.MODE_FULL_INSTALL + ).apply { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + setInstallReason(android.content.pm.PackageManager.INSTALL_REASON_USER) + } + } + val pendingIntent = PendingIntent.getService( + context, + 0, + Intent(context, AppInstallService::class.java), + intentFlags + ).intentSender + + val sessionId: Int + try { + sessionId = packageInstaller.createSession(sessionParams) + } catch (e: IOException) { + return PackageManagerResult.Error( + status = PackageManagerStatus.SESSION_FAILED_CREATE, + message = e.stackTraceToString() + ) + } + + val session: PackageInstaller.Session + try { + session = packageInstaller.openSession(sessionId) + } catch (e: IOException) { + return PackageManagerResult.Error( + status = PackageManagerStatus.SESSION_FAILED_OPEN, + message = e.stackTraceToString() + ) + } catch (e: SecurityException) { + return PackageManagerResult.Error( + status = PackageManagerStatus.SESSION_FAILED_OPEN, + message = e.stackTraceToString() + ) + } + + try { + session.use { + it.block() + it.commit(pendingIntent) + } + } catch (e: IOException) { + return PackageManagerResult.Error( + status = PackageManagerStatus.SESSION_FAILED_WRITE, + message = e.stackTraceToString() + ) + } catch (e: SecurityException) { + return PackageManagerResult.Error( + status = PackageManagerStatus.SESSION_FAILED_COMMIT, + message = e.stackTraceToString() + ) + } + + return PackageManagerResult.Success(null) + } + + private fun PackageInstaller.Session.writeApkToSession(apk: File) { + apk.inputStream().use { inputStream -> + openWrite(apk.name, 0, apk.length()).use { outputStream -> + inputStream.copyTo(outputStream, byteArraySize) + fsync(outputStream) + } + } + } + + private val intentFlags: Int + get() { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) + PendingIntent.FLAG_MUTABLE + else + 0 + } + + private companion object { + const val byteArraySize = 1024 * 1024 + + const val FLAG_NOTHING = 0 + const val VERSION_IGNORE_MAJOR = 0xFFFFFFFF + } + +} + +class RootPackageManager : PackageManager { + + override suspend fun getVersionCode(packageName: String): PackageManagerResult<Int> { + return try { + val keyword = "versionCode=" + val dumpsys = Shell.su("dumpsys", "package", packageName, "|", "grep", keyword).awaitOutputOrThrow() + val versionCode = dumpsys.removePrefix(keyword).substringAfter("minSdk").toInt() + + PackageManagerResult.Success(versionCode) + } catch (e: SuException) { + PackageManagerResult.Error( + status = PackageManagerStatus.GET_FAILED_PACKAGE_VERSION_CODE, + message = e.stderrOut + ) + } catch (e: java.lang.NumberFormatException) { + PackageManagerResult.Error( + status = PackageManagerStatus.GET_FAILED_PACKAGE_VERSION_CODE, + message = e.stackTraceToString() + ) + } + } + + override suspend fun getVersionName(packageName: String): PackageManagerResult<String> { + return try { + val keyword = "versionName=" + val dumpsys = Shell.su("dumpsys", "package", packageName, "|", "grep", keyword).awaitOutputOrThrow() + val versionName = dumpsys.removePrefix(keyword) + + PackageManagerResult.Success(versionName) + } catch (e: SuException) { + PackageManagerResult.Error( + status = PackageManagerStatus.GET_FAILED_PACKAGE_VERSION_NAME, + message = e.stderrOut + ) + } + } + + override suspend fun getInstallationDir(packageName: String): PackageManagerResult<String> { + return try { + val keyword = "path: " + val dumpsys = Shell.su("dumpsys", "package", packageName, "|", "grep", keyword).awaitOutputOrThrow() + val installationDir = dumpsys.removePrefix(keyword) + + PackageManagerResult.Success(installationDir) + } catch (e: SuException) { + PackageManagerResult.Error( + status = PackageManagerStatus.GET_FAILED_PACKAGE_DIR, + message = e.stderrOut + ) + } + } + + override suspend fun setInstaller( + targetPackage: String, + installerPackage: String + ): PackageManagerResult<Nothing> { + try { + Shell.su("pm", "set-installer", targetPackage, installerPackage).awaitOutputOrThrow() + } catch (e: SuException) { + return PackageManagerResult.Error( + status = PackageManagerStatus.SET_FAILED_INSTALLER, + message = e.stderrOut + ) + } + + return PackageManagerResult.Success(null) + } + + override suspend fun forceStop(packageName: String): PackageManagerResult<Nothing> { + return try { + Shell.su("am", "force-stop", packageName).awaitOutputOrThrow() + PackageManagerResult.Success(null) + } catch (e: SuException) { + PackageManagerResult.Error( + status = PackageManagerStatus.APP_FAILED_FORCE_STOP, + message = e.stderrOut + ) + } + } + + override suspend fun installApp(apk: File): PackageManagerResult<Nothing> { + var tempApk: File? = null + try { + tempApk = copyApkToTemp(apk) + Shell.su("pm", "install", "-r", tempApk.absolutePath).awaitOutputOrThrow() + } catch (e: IOException) { + return PackageManagerResult.Error( + status = PackageManagerStatus.SESSION_FAILED_COPY, + message = e.stackTraceToString() + ) + } catch (e: SuException) { + return PackageManagerResult.Error( + status = getEnumForInstallFailed(e.stderrOut), + message = e.stderrOut + ) + } finally { + tempApk?.delete() + } + return PackageManagerResult.Success(null) + } + + override suspend fun installSplitApp(apks: Array<File>): PackageManagerResult<Nothing> { + val sessionId: Int + try { + val installCreate = Shell.su("pm", "install-create", "-r").awaitOutputOrThrow() + sessionId = installCreate.toInt() + } catch (e: SuException) { + return PackageManagerResult.Error( + status = PackageManagerStatus.SESSION_FAILED_CREATE, + message = e.stderrOut + ) + } catch (e: NumberFormatException) { + return PackageManagerResult.Error( + status = PackageManagerStatus.SESSION_INVALID_ID, + message = e.stackTraceToString() + ) + } + + for (apk in apks) { + var tempApk: File? = null + try { + tempApk = copyApkToTemp(apk) + Shell.su("pm", "install-write", sessionId.toString(), tempApk.name, tempApk.absolutePath).awaitOutputOrThrow() + } catch (e: SuException) { + return PackageManagerResult.Error( + status = PackageManagerStatus.SESSION_FAILED_WRITE, + message = e.stderrOut + ) + } catch (e: IOException) { + return PackageManagerResult.Error( + status = PackageManagerStatus.SESSION_FAILED_COPY, + message = e.stackTraceToString() + ) + } finally { + tempApk?.delete() + } + } + + try { + Shell.su("pm", "install-commit", sessionId.toString()).awaitOutputOrThrow() + } catch (e: SuException) { + return PackageManagerResult.Error( + status = getEnumForInstallFailed(e.stderrOut), + message = e.stderrOut + ) + } + return PackageManagerResult.Success(null) + } + + override suspend fun uninstallApp(packageName: String): PackageManagerResult<Nothing> { + return try { + Shell.su("pm", "uninstall", packageName).awaitOutputOrThrow() + PackageManagerResult.Success(null) + } catch (e: SuException) { + PackageManagerResult.Error( + status = PackageManagerStatus.UNINSTALL_FAILED, + message = e.stderrOut + ) + } + } + + @Throws( + IOException::class, + FileNotFoundException::class + ) + private fun copyApkToTemp(apk: File): SuFile { + val tmpPath = "/data/local/tmp/${apk.name}" + + val tmpApk = SuFile(tmpPath).apply { + createNewFile() + } + + SuFileInputStream.open(tmpApk).use { inputStream -> + SuFileOutputStream.open(tmpApk).use { outputStream -> + inputStream.copyTo(outputStream) + outputStream.flush() + } + } + + return tmpApk + } + +} + +enum class PackageManagerStatus { + SET_FAILED_INSTALLER, + GET_FAILED_PACKAGE_DIR, + GET_FAILED_PACKAGE_VERSION_NAME, + GET_FAILED_PACKAGE_VERSION_CODE, + + APP_FAILED_FORCE_STOP, + + SESSION_FAILED_CREATE, + SESSION_FAILED_COMMIT, + SESSION_FAILED_WRITE, + SESSION_FAILED_COPY, + SESSION_FAILED_OPEN, + SESSION_INVALID_ID, + + INSTALL_FAILED_ABORTED, + INSTALL_FAILED_ALREADY_EXISTS, + INSTALL_FAILED_CPU_ABI_INCOMPATIBLE, + INSTALL_FAILED_INSUFFICIENT_STORAGE, + INSTALL_FAILED_INVALID_APK, + INSTALL_FAILED_VERSION_DOWNGRADE, + INSTALL_FAILED_PARSE_NO_CERTIFICATES, + INSTALL_FAILED_UNKNOWN, + + UNINSTALL_FAILED, + + LINK_FAILED_UNMOUNT, + LINK_FAILED_MOUNT, + + PATCH_FAILED_COPY, + PATCH_FAILED_CHMOD, + PATCH_FAILED_CHOWN, + PATCH_FAILED_CHCON, + PATCH_FAILED_DESTROY, + + SCRIPT_FAILED_SETUP_POST_FS, + SCRIPT_FAILED_SETUP_SERVICE_D, + SCRIPT_FAILED_DESTROY_POST_FS, + SCRIPT_FAILED_DESTROY_SERVICE_D, +} + +fun getEnumForInstallFailed(outString: String): PackageManagerStatus { + return when { + outString.contains("INSTALL_FAILED_ABORTED") -> PackageManagerStatus.INSTALL_FAILED_ABORTED + outString.contains("INSTALL_FAILED_ALREADY_EXISTS") -> PackageManagerStatus.INSTALL_FAILED_ALREADY_EXISTS + outString.contains("INSTALL_FAILED_CPU_ABI_INCOMPATIBLE") -> PackageManagerStatus.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE + outString.contains("INSTALL_FAILED_INSUFFICIENT_STORAGE") -> PackageManagerStatus.INSTALL_FAILED_INSUFFICIENT_STORAGE + outString.contains("INSTALL_FAILED_INVALID_APK") -> PackageManagerStatus.INSTALL_FAILED_INVALID_APK + outString.contains("INSTALL_FAILED_VERSION_DOWNGRADE") -> PackageManagerStatus.INSTALL_FAILED_VERSION_DOWNGRADE + outString.contains("INSTALL_PARSE_FAILED_NO_CERTIFICATES") -> PackageManagerStatus.INSTALL_FAILED_PARSE_NO_CERTIFICATES + else -> PackageManagerStatus.INSTALL_FAILED_UNKNOWN + } +} + +sealed class PackageManagerResult<out V> { + data class Success<out V>(val value: V?) : PackageManagerResult<V>() + data class Error(val status: PackageManagerStatus, val message: String) : PackageManagerResult<Nothing>() + + fun getValueOrNull(): V? = getOrElse { null } + + val isError + get() = this is Error + + val isSuccess + get() = this is Success +} + +inline fun <R, T : R> PackageManagerResult<T>.getOrElse( + onError: (PackageManagerResult.Error) -> R? +): R? { + return when (this) { + is PackageManagerResult.Success -> this.value + is PackageManagerResult.Error -> onError(this) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/repository/source/PkgInfoDatasource.kt b/app/src/main/java/com/vanced/manager/repository/source/PkgInfoDatasource.kt deleted file mode 100644 index b9e57d6ba4..0000000000 --- a/app/src/main/java/com/vanced/manager/repository/source/PkgInfoDatasource.kt +++ /dev/null @@ -1,50 +0,0 @@ -package com.vanced.manager.repository.source - -import android.annotation.SuppressLint -import android.content.pm.PackageManager -import android.os.Build - -interface PkgInfoDatasource { - - fun getVersionCode(packageName: String): Int? - - fun getVersionName(packageName: String): String? - -} - -class PkgInfoDatasourceImpl( - private val packageManager: PackageManager -) : PkgInfoDatasource { - - private companion object { - const val FLAG_NOTHING = 0 - const val VERSION_IGNORE_MAJOR = 0xFFFFFFFF - } - - @SuppressLint("WrongConstant") - override fun getVersionCode(packageName: String): Int? { - return try { - val packageInfo = packageManager.getPackageInfo(packageName, FLAG_NOTHING) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - packageInfo.longVersionCode.and(VERSION_IGNORE_MAJOR).toInt() - } else { - @Suppress("DEPRECATION") - packageInfo.versionCode - } - } catch (e: PackageManager.NameNotFoundException) { - null - } - } - - @Suppress("DEPRECATION") - @SuppressLint("WrongConstant") - override fun getVersionName(packageName: String): String? { - return try { - packageManager - .getPackageInfo(packageName, FLAG_NOTHING) - .versionName - } catch (e: PackageManager.NameNotFoundException) { - null - } - } -} \ No newline at end of file diff --git a/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt b/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt index e04ba03e3d..859a0513d8 100644 --- a/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt +++ b/app/src/main/java/com/vanced/manager/ui/viewmodel/InstallViewModel.kt @@ -14,11 +14,11 @@ import com.vanced.manager.downloader.impl.VancedDownloader import com.vanced.manager.installer.impl.MicrogInstaller import com.vanced.manager.installer.impl.MusicInstaller import com.vanced.manager.installer.impl.VancedInstaller -import com.vanced.manager.installer.util.PMRootResult import com.vanced.manager.network.util.MICROG_NAME import com.vanced.manager.network.util.MUSIC_NAME import com.vanced.manager.network.util.VANCED_NAME import com.vanced.manager.preferences.holder.managerVariantPref +import com.vanced.manager.repository.manager.PackageManagerResult import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch @@ -117,7 +117,7 @@ class InstallViewModel( } } - private fun installApp( + private suspend fun installApp( appName: String, appVersions: List<String>?, ) { @@ -127,11 +127,11 @@ class InstallViewModel( if (isRoot) { when (val installStatus = installer.installRoot(appVersions)) { - is PMRootResult.Success -> { + is PackageManagerResult.Success -> { status = Status.Installed log(Log.Success("Successfully installed")) } - is PMRootResult.Error -> { + is PackageManagerResult.Error -> { status = Status.Failure log(Log.Error("Failed to install app", installStatus.message)) } diff --git a/app/src/main/java/com/vanced/manager/util/SuShell.kt b/app/src/main/java/com/vanced/manager/util/SuShell.kt index 38a5945cd9..73b6f072bb 100644 --- a/app/src/main/java/com/vanced/manager/util/SuShell.kt +++ b/app/src/main/java/com/vanced/manager/util/SuShell.kt @@ -2,6 +2,7 @@ package com.vanced.manager.util import com.topjohnwu.superuser.Shell import kotlin.coroutines.resume +import kotlin.coroutines.resumeWithException import kotlin.coroutines.suspendCoroutine val Shell.Result.outString @@ -13,8 +14,26 @@ val Shell.Result.errString val isMagiskInstalled get() = Shell.rootAccess() && Shell.su("magisk", "-c").exec().isSuccess -suspend fun Shell.Job.await() = - suspendCoroutine<Shell.Result> { continuation -> - submit(/*continuation.context.asExecutor(),*/ continuation::resume) +suspend fun Shell.Job.await(): Shell.Result { + return suspendCoroutine { continuation -> + submit { + continuation.resume(it) + } } +} + +class SuException(val stderrOut: String) : Exception(stderrOut) + +@Throws(SuException::class) +suspend fun Shell.Job.awaitOutputOrThrow(): String { + return suspendCoroutine { continuation -> + submit { + if (it.isSuccess) { + continuation.resume(it.outString) + } else { + continuation.resumeWithException(SuException(it.errString)) + } + } + } +} From 9b217519573a7c78b048a981d95a95509974eb15 Mon Sep 17 00:00:00 2001 From: X1nto <burtkni@yandex.ru> Date: Fri, 11 Mar 2022 19:53:34 +0400 Subject: [PATCH 117/118] packagemanager code cleanup --- .../vanced/manager/installer/util/PMRoot.kt | 24 +-- .../vanced/manager/installer/util/Patcher.kt | 24 +-- .../repository/manager/PackageManager.kt | 141 +++++++++--------- .../java/com/vanced/manager/util/Safety.kt | 32 ++++ 4 files changed, 128 insertions(+), 93 deletions(-) create mode 100644 app/src/main/java/com/vanced/manager/util/Safety.kt diff --git a/app/src/main/java/com/vanced/manager/installer/util/PMRoot.kt b/app/src/main/java/com/vanced/manager/installer/util/PMRoot.kt index 75a46b6bb1..3332d69229 100644 --- a/app/src/main/java/com/vanced/manager/installer/util/PMRoot.kt +++ b/app/src/main/java/com/vanced/manager/installer/util/PMRoot.kt @@ -4,7 +4,7 @@ import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.io.SuFile import com.topjohnwu.superuser.io.SuFileOutputStream import com.vanced.manager.repository.manager.PackageManagerResult -import com.vanced.manager.repository.manager.PackageManagerStatus +import com.vanced.manager.repository.manager.PackageManagerError import com.vanced.manager.repository.manager.getEnumForInstallFailed import com.vanced.manager.util.errString import com.vanced.manager.util.outString @@ -17,7 +17,7 @@ object PMRoot { val apk = File(apkPath) val tmpApk = copyApkToTemp(apk).getOrElse { exception -> return PackageManagerResult.Error( - PackageManagerStatus.SESSION_FAILED_COPY, + PackageManagerError.SESSION_FAILED_COPY, exception.stackTraceToString() ) } @@ -38,18 +38,18 @@ object PMRoot { val installCreate = Shell.su("pm", "install-create", "-r").exec() if (!installCreate.isSuccess) - return PackageManagerResult.Error(PackageManagerStatus.SESSION_FAILED_CREATE, installCreate.errString) + return PackageManagerResult.Error(PackageManagerError.SESSION_FAILED_CREATE, installCreate.errString) val sessionId = installCreate.outString if (sessionId.toIntOrNull() == null) - return PackageManagerResult.Error(PackageManagerStatus.SESSION_INVALID_ID, installCreate.errString) + return PackageManagerResult.Error(PackageManagerError.SESSION_INVALID_ID, installCreate.errString) for (apkPath in apkPaths) { val apk = File(apkPath) val tmpApk = copyApkToTemp(apk).getOrElse { exception -> return PackageManagerResult.Error( - PackageManagerStatus.SESSION_FAILED_COPY, + PackageManagerError.SESSION_FAILED_COPY, exception.stackTraceToString() ) } @@ -61,7 +61,7 @@ object PMRoot { tmpApk.delete() if (!installWrite.isSuccess) - return PackageManagerResult.Error(PackageManagerStatus.SESSION_FAILED_WRITE, installWrite.errString) + return PackageManagerResult.Error(PackageManagerError.SESSION_FAILED_WRITE, installWrite.errString) } val installCommit = Shell.su("pm", "install-commit", sessionId).exec() @@ -78,7 +78,7 @@ object PMRoot { val uninstall = Shell.su("pm", "uninstall", pkg).exec() if (!uninstall.isSuccess) - return PackageManagerResult.Error(PackageManagerStatus.UNINSTALL_FAILED, uninstall.errString) + return PackageManagerResult.Error(PackageManagerError.UNINSTALL_FAILED, uninstall.errString) return PackageManagerResult.Success(null) } @@ -89,7 +89,7 @@ object PMRoot { if (!setInstaller.isSuccess) return PackageManagerResult.Error( - PackageManagerStatus.SET_FAILED_INSTALLER, + PackageManagerError.SET_FAILED_INSTALLER, setInstaller.errString ) @@ -100,7 +100,7 @@ object PMRoot { val stopApp = Shell.su("am", "force-stop", pkg).exec() if (!stopApp.isSuccess) - return PackageManagerResult.Error(PackageManagerStatus.APP_FAILED_FORCE_STOP, stopApp.errString) + return PackageManagerResult.Error(PackageManagerError.APP_FAILED_FORCE_STOP, stopApp.errString) return PackageManagerResult.Success(null) } @@ -111,7 +111,7 @@ object PMRoot { if (!dumpsys.isSuccess) return PackageManagerResult.Error( - PackageManagerStatus.GET_FAILED_PACKAGE_VERSION_NAME, + PackageManagerError.GET_FAILED_PACKAGE_VERSION_NAME, dumpsys.errString ) @@ -124,7 +124,7 @@ object PMRoot { if (!dumpsys.isSuccess) return PackageManagerResult.Error( - PackageManagerStatus.GET_FAILED_PACKAGE_VERSION_CODE, + PackageManagerError.GET_FAILED_PACKAGE_VERSION_CODE, dumpsys.errString ) @@ -139,7 +139,7 @@ object PMRoot { val dumpsys = Shell.su("dumpsys", "package", pkg, "|", "grep", keyword).exec() if (!dumpsys.isSuccess) - return PackageManagerResult.Error(PackageManagerStatus.GET_FAILED_PACKAGE_DIR, dumpsys.errString) + return PackageManagerResult.Error(PackageManagerError.GET_FAILED_PACKAGE_DIR, dumpsys.errString) return PackageManagerResult.Success(dumpsys.outString.removePrefix(keyword)) } diff --git a/app/src/main/java/com/vanced/manager/installer/util/Patcher.kt b/app/src/main/java/com/vanced/manager/installer/util/Patcher.kt index af523990d2..4e01a583fd 100644 --- a/app/src/main/java/com/vanced/manager/installer/util/Patcher.kt +++ b/app/src/main/java/com/vanced/manager/installer/util/Patcher.kt @@ -6,7 +6,7 @@ import com.topjohnwu.superuser.io.SuFileOutputStream import com.vanced.manager.io.ManagerSuFile import com.vanced.manager.io.SUIOException import com.vanced.manager.repository.manager.PackageManagerResult -import com.vanced.manager.repository.manager.PackageManagerStatus +import com.vanced.manager.repository.manager.PackageManagerError import com.vanced.manager.util.errString import java.io.File import java.io.IOException @@ -27,14 +27,14 @@ object Patcher { val copyServiceDScript = copyScriptToDestination(postFsDataScript, postFsDataScriptPath) if (copyServiceDScript.isFailure) return PackageManagerResult.Error( - PackageManagerStatus.SCRIPT_FAILED_SETUP_POST_FS, + PackageManagerError.SCRIPT_FAILED_SETUP_POST_FS, copyServiceDScript.exceptionOrNull()!!.stackTraceToString() ) val copyPostFsDataScript = copyScriptToDestination(serviceDScript, serviceDScriptPath) if (copyPostFsDataScript.isFailure) return PackageManagerResult.Error( - PackageManagerStatus.SCRIPT_FAILED_SETUP_SERVICE_D, + PackageManagerError.SCRIPT_FAILED_SETUP_SERVICE_D, copyPostFsDataScript.exceptionOrNull()!!.stackTraceToString() ) @@ -55,16 +55,16 @@ object Patcher { try { patchApk.copyTo(newPatchApk) } catch (e: IOException) { - return PackageManagerResult.Error(PackageManagerStatus.PATCH_FAILED_COPY, e.stackTraceToString()) + return PackageManagerResult.Error(PackageManagerError.PATCH_FAILED_COPY, e.stackTraceToString()) } val chmod = Shell.su("chmod", "644", newPatchPath).exec() if (!chmod.isSuccess) - return PackageManagerResult.Error(PackageManagerStatus.PATCH_FAILED_CHMOD, chmod.errString) + return PackageManagerResult.Error(PackageManagerError.PATCH_FAILED_CHMOD, chmod.errString) val chown = Shell.su("chown", "system:system", newPatchPath).exec() if (!chmod.isSuccess) - return PackageManagerResult.Error(PackageManagerStatus.PATCH_FAILED_CHOWN, chown.errString) + return PackageManagerResult.Error(PackageManagerError.PATCH_FAILED_CHOWN, chown.errString) return PackageManagerResult.Success(null) } @@ -72,7 +72,7 @@ object Patcher { fun chconPatch(app: String): PackageManagerResult<Nothing> { val chcon = Shell.su("chcon u:object_r:apk_data_file:s0 ${getAppPatchPath(app)}").exec() if (!chcon.isSuccess) - return PackageManagerResult.Error(PackageManagerStatus.PATCH_FAILED_CHCON, chcon.errString) + return PackageManagerResult.Error(PackageManagerError.PATCH_FAILED_CHCON, chcon.errString) return PackageManagerResult.Success(null) } @@ -82,13 +82,13 @@ object Patcher { Shell.su("""for i in ${'$'}(ls /data/app/ | grep $stockPackage | tr " "); do umount -l "/data/app/${"$"}i/base.apk"; done """) .exec() if (!umount.isSuccess) - return PackageManagerResult.Error(PackageManagerStatus.LINK_FAILED_UNMOUNT, umount.errString) + return PackageManagerResult.Error(PackageManagerError.LINK_FAILED_UNMOUNT, umount.errString) val mount = Shell.su("su", "-mm", "-c", """"mount -o bind ${getAppPatchPath(app)} $stockPath"""") .exec() if (!mount.isSuccess) - return PackageManagerResult.Error(PackageManagerStatus.LINK_FAILED_MOUNT, mount.errString) + return PackageManagerResult.Error(PackageManagerError.LINK_FAILED_MOUNT, mount.errString) return PackageManagerResult.Success(null) } @@ -136,9 +136,9 @@ private fun cleanPatchFiles( patchPath: String, ): PackageManagerResult<Nothing> { val files = mapOf( - postFsPath to PackageManagerStatus.SCRIPT_FAILED_DESTROY_POST_FS, - serviceDPath to PackageManagerStatus.SCRIPT_FAILED_DESTROY_SERVICE_D, - patchPath to PackageManagerStatus.PATCH_FAILED_DESTROY, + postFsPath to PackageManagerError.SCRIPT_FAILED_DESTROY_POST_FS, + serviceDPath to PackageManagerError.SCRIPT_FAILED_DESTROY_SERVICE_D, + patchPath to PackageManagerError.PATCH_FAILED_DESTROY, ) for ((filePath, errorStatusType) in files) { diff --git a/app/src/main/java/com/vanced/manager/repository/manager/PackageManager.kt b/app/src/main/java/com/vanced/manager/repository/manager/PackageManager.kt index 3928afe5bd..c795c80521 100644 --- a/app/src/main/java/com/vanced/manager/repository/manager/PackageManager.kt +++ b/app/src/main/java/com/vanced/manager/repository/manager/PackageManager.kt @@ -12,8 +12,7 @@ import com.topjohnwu.superuser.io.SuFileInputStream import com.topjohnwu.superuser.io.SuFileOutputStream import com.vanced.manager.installer.service.AppInstallService import com.vanced.manager.installer.service.AppUninstallService -import com.vanced.manager.util.SuException -import com.vanced.manager.util.awaitOutputOrThrow +import com.vanced.manager.util.* import java.io.File import java.io.FileNotFoundException import java.io.IOException @@ -53,10 +52,11 @@ class NonrootPackageManager( } else { packageInfo.versionCode } + PackageManagerResult.Success(versionCode) } catch (e: android.content.pm.PackageManager.NameNotFoundException) { PackageManagerResult.Error( - status = PackageManagerStatus.GET_FAILED_PACKAGE_VERSION_CODE, + error = PackageManagerError.GET_FAILED_PACKAGE_VERSION_CODE, message = e.stackTraceToString() ) } @@ -68,10 +68,11 @@ class NonrootPackageManager( val versionName = context.packageManager .getPackageInfo(packageName, FLAG_NOTHING) .versionName + PackageManagerResult.Success(versionName) } catch (e: android.content.pm.PackageManager.NameNotFoundException) { PackageManagerResult.Error( - status = PackageManagerStatus.GET_FAILED_PACKAGE_VERSION_NAME, + error = PackageManagerError.GET_FAILED_PACKAGE_VERSION_NAME, message = e.stackTraceToString() ) } @@ -84,10 +85,11 @@ class NonrootPackageManager( .getPackageInfo(packageName, FLAG_NOTHING) .applicationInfo .sourceDir + PackageManagerResult.Success(installationDir) } catch (e: android.content.pm.PackageManager.NameNotFoundException) { PackageManagerResult.Error( - status = PackageManagerStatus.GET_FAILED_PACKAGE_DIR, + error = PackageManagerError.GET_FAILED_PACKAGE_DIR, message = e.stackTraceToString() ) } @@ -98,14 +100,14 @@ class NonrootPackageManager( installerPackage: String ): PackageManagerResult<Nothing> { return PackageManagerResult.Error( - status = PackageManagerStatus.SET_FAILED_INSTALLER, + error = PackageManagerError.SET_FAILED_INSTALLER, message = "Unsupported" ) } override suspend fun forceStop(packageName: String): PackageManagerResult<Nothing> { return PackageManagerResult.Error( - status = PackageManagerStatus.APP_FAILED_FORCE_STOP, + error = PackageManagerError.APP_FAILED_FORCE_STOP, message = "Unsupported" ) } @@ -154,29 +156,26 @@ class NonrootPackageManager( intentFlags ).intentSender - val sessionId: Int - try { - sessionId = packageInstaller.createSession(sessionParams) - } catch (e: IOException) { - return PackageManagerResult.Error( - status = PackageManagerStatus.SESSION_FAILED_CREATE, - message = e.stackTraceToString() - ) + val sessionId = tripleUnionTryCatch<IOException, SecurityException, IllegalArgumentException, Int>( + onCatch = { + return PackageManagerResult.Error( + error = PackageManagerError.SESSION_FAILED_CREATE, + message = it.stackTraceToString() + ) + } + ) { + packageInstaller.createSession(sessionParams) } - val session: PackageInstaller.Session - try { - session = packageInstaller.openSession(sessionId) - } catch (e: IOException) { - return PackageManagerResult.Error( - status = PackageManagerStatus.SESSION_FAILED_OPEN, - message = e.stackTraceToString() - ) - } catch (e: SecurityException) { - return PackageManagerResult.Error( - status = PackageManagerStatus.SESSION_FAILED_OPEN, - message = e.stackTraceToString() - ) + val session = doubleUnionTryCatch<IOException, SecurityException, PackageInstaller.Session>( + onCatch = { + return PackageManagerResult.Error( + error = PackageManagerError.SESSION_FAILED_CREATE, + message = it.stackTraceToString() + ) + } + ) { + packageInstaller.openSession(sessionId) } try { @@ -186,12 +185,12 @@ class NonrootPackageManager( } } catch (e: IOException) { return PackageManagerResult.Error( - status = PackageManagerStatus.SESSION_FAILED_WRITE, + error = PackageManagerError.SESSION_FAILED_WRITE, message = e.stackTraceToString() ) } catch (e: SecurityException) { return PackageManagerResult.Error( - status = PackageManagerStatus.SESSION_FAILED_COMMIT, + error = PackageManagerError.SESSION_FAILED_COMMIT, message = e.stackTraceToString() ) } @@ -236,12 +235,12 @@ class RootPackageManager : PackageManager { PackageManagerResult.Success(versionCode) } catch (e: SuException) { PackageManagerResult.Error( - status = PackageManagerStatus.GET_FAILED_PACKAGE_VERSION_CODE, + error = PackageManagerError.GET_FAILED_PACKAGE_VERSION_CODE, message = e.stderrOut ) } catch (e: java.lang.NumberFormatException) { PackageManagerResult.Error( - status = PackageManagerStatus.GET_FAILED_PACKAGE_VERSION_CODE, + error = PackageManagerError.GET_FAILED_PACKAGE_VERSION_CODE, message = e.stackTraceToString() ) } @@ -256,7 +255,7 @@ class RootPackageManager : PackageManager { PackageManagerResult.Success(versionName) } catch (e: SuException) { PackageManagerResult.Error( - status = PackageManagerStatus.GET_FAILED_PACKAGE_VERSION_NAME, + error = PackageManagerError.GET_FAILED_PACKAGE_VERSION_NAME, message = e.stderrOut ) } @@ -271,7 +270,7 @@ class RootPackageManager : PackageManager { PackageManagerResult.Success(installationDir) } catch (e: SuException) { PackageManagerResult.Error( - status = PackageManagerStatus.GET_FAILED_PACKAGE_DIR, + error = PackageManagerError.GET_FAILED_PACKAGE_DIR, message = e.stderrOut ) } @@ -281,25 +280,26 @@ class RootPackageManager : PackageManager { targetPackage: String, installerPackage: String ): PackageManagerResult<Nothing> { - try { + return try { Shell.su("pm", "set-installer", targetPackage, installerPackage).awaitOutputOrThrow() + + PackageManagerResult.Success(null) } catch (e: SuException) { - return PackageManagerResult.Error( - status = PackageManagerStatus.SET_FAILED_INSTALLER, + PackageManagerResult.Error( + error = PackageManagerError.SET_FAILED_INSTALLER, message = e.stderrOut ) } - - return PackageManagerResult.Success(null) } override suspend fun forceStop(packageName: String): PackageManagerResult<Nothing> { return try { Shell.su("am", "force-stop", packageName).awaitOutputOrThrow() + PackageManagerResult.Success(null) } catch (e: SuException) { PackageManagerResult.Error( - status = PackageManagerStatus.APP_FAILED_FORCE_STOP, + error = PackageManagerError.APP_FAILED_FORCE_STOP, message = e.stderrOut ) } @@ -307,38 +307,39 @@ class RootPackageManager : PackageManager { override suspend fun installApp(apk: File): PackageManagerResult<Nothing> { var tempApk: File? = null - try { + return try { tempApk = copyApkToTemp(apk) Shell.su("pm", "install", "-r", tempApk.absolutePath).awaitOutputOrThrow() + + PackageManagerResult.Success(null) } catch (e: IOException) { - return PackageManagerResult.Error( - status = PackageManagerStatus.SESSION_FAILED_COPY, + PackageManagerResult.Error( + error = PackageManagerError.SESSION_FAILED_COPY, message = e.stackTraceToString() ) } catch (e: SuException) { - return PackageManagerResult.Error( - status = getEnumForInstallFailed(e.stderrOut), + PackageManagerResult.Error( + error = getEnumForInstallFailed(e.stderrOut), message = e.stderrOut ) } finally { tempApk?.delete() } - return PackageManagerResult.Success(null) } override suspend fun installSplitApp(apks: Array<File>): PackageManagerResult<Nothing> { - val sessionId: Int - try { + val sessionId = try { val installCreate = Shell.su("pm", "install-create", "-r").awaitOutputOrThrow() - sessionId = installCreate.toInt() + + installCreate.toInt() } catch (e: SuException) { return PackageManagerResult.Error( - status = PackageManagerStatus.SESSION_FAILED_CREATE, + error = PackageManagerError.SESSION_FAILED_CREATE, message = e.stderrOut ) } catch (e: NumberFormatException) { return PackageManagerResult.Error( - status = PackageManagerStatus.SESSION_INVALID_ID, + error = PackageManagerError.SESSION_INVALID_ID, message = e.stackTraceToString() ) } @@ -350,12 +351,12 @@ class RootPackageManager : PackageManager { Shell.su("pm", "install-write", sessionId.toString(), tempApk.name, tempApk.absolutePath).awaitOutputOrThrow() } catch (e: SuException) { return PackageManagerResult.Error( - status = PackageManagerStatus.SESSION_FAILED_WRITE, + error = PackageManagerError.SESSION_FAILED_WRITE, message = e.stderrOut ) } catch (e: IOException) { return PackageManagerResult.Error( - status = PackageManagerStatus.SESSION_FAILED_COPY, + error = PackageManagerError.SESSION_FAILED_COPY, message = e.stackTraceToString() ) } finally { @@ -363,24 +364,26 @@ class RootPackageManager : PackageManager { } } - try { + return try { Shell.su("pm", "install-commit", sessionId.toString()).awaitOutputOrThrow() + + PackageManagerResult.Success(null) } catch (e: SuException) { - return PackageManagerResult.Error( - status = getEnumForInstallFailed(e.stderrOut), + PackageManagerResult.Error( + error = getEnumForInstallFailed(e.stderrOut), message = e.stderrOut ) } - return PackageManagerResult.Success(null) } override suspend fun uninstallApp(packageName: String): PackageManagerResult<Nothing> { return try { Shell.su("pm", "uninstall", packageName).awaitOutputOrThrow() + PackageManagerResult.Success(null) } catch (e: SuException) { PackageManagerResult.Error( - status = PackageManagerStatus.UNINSTALL_FAILED, + error = PackageManagerError.UNINSTALL_FAILED, message = e.stderrOut ) } @@ -409,7 +412,7 @@ class RootPackageManager : PackageManager { } -enum class PackageManagerStatus { +enum class PackageManagerError { SET_FAILED_INSTALLER, GET_FAILED_PACKAGE_DIR, GET_FAILED_PACKAGE_VERSION_NAME, @@ -450,22 +453,22 @@ enum class PackageManagerStatus { SCRIPT_FAILED_DESTROY_SERVICE_D, } -fun getEnumForInstallFailed(outString: String): PackageManagerStatus { +fun getEnumForInstallFailed(outString: String): PackageManagerError { return when { - outString.contains("INSTALL_FAILED_ABORTED") -> PackageManagerStatus.INSTALL_FAILED_ABORTED - outString.contains("INSTALL_FAILED_ALREADY_EXISTS") -> PackageManagerStatus.INSTALL_FAILED_ALREADY_EXISTS - outString.contains("INSTALL_FAILED_CPU_ABI_INCOMPATIBLE") -> PackageManagerStatus.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE - outString.contains("INSTALL_FAILED_INSUFFICIENT_STORAGE") -> PackageManagerStatus.INSTALL_FAILED_INSUFFICIENT_STORAGE - outString.contains("INSTALL_FAILED_INVALID_APK") -> PackageManagerStatus.INSTALL_FAILED_INVALID_APK - outString.contains("INSTALL_FAILED_VERSION_DOWNGRADE") -> PackageManagerStatus.INSTALL_FAILED_VERSION_DOWNGRADE - outString.contains("INSTALL_PARSE_FAILED_NO_CERTIFICATES") -> PackageManagerStatus.INSTALL_FAILED_PARSE_NO_CERTIFICATES - else -> PackageManagerStatus.INSTALL_FAILED_UNKNOWN + outString.contains("INSTALL_FAILED_ABORTED") -> PackageManagerError.INSTALL_FAILED_ABORTED + outString.contains("INSTALL_FAILED_ALREADY_EXISTS") -> PackageManagerError.INSTALL_FAILED_ALREADY_EXISTS + outString.contains("INSTALL_FAILED_CPU_ABI_INCOMPATIBLE") -> PackageManagerError.INSTALL_FAILED_CPU_ABI_INCOMPATIBLE + outString.contains("INSTALL_FAILED_INSUFFICIENT_STORAGE") -> PackageManagerError.INSTALL_FAILED_INSUFFICIENT_STORAGE + outString.contains("INSTALL_FAILED_INVALID_APK") -> PackageManagerError.INSTALL_FAILED_INVALID_APK + outString.contains("INSTALL_FAILED_VERSION_DOWNGRADE") -> PackageManagerError.INSTALL_FAILED_VERSION_DOWNGRADE + outString.contains("INSTALL_PARSE_FAILED_NO_CERTIFICATES") -> PackageManagerError.INSTALL_FAILED_PARSE_NO_CERTIFICATES + else -> PackageManagerError.INSTALL_FAILED_UNKNOWN } } sealed class PackageManagerResult<out V> { data class Success<out V>(val value: V?) : PackageManagerResult<V>() - data class Error(val status: PackageManagerStatus, val message: String) : PackageManagerResult<Nothing>() + data class Error(val error: PackageManagerError, val message: String) : PackageManagerResult<Nothing>() fun getValueOrNull(): V? = getOrElse { null } diff --git a/app/src/main/java/com/vanced/manager/util/Safety.kt b/app/src/main/java/com/vanced/manager/util/Safety.kt new file mode 100644 index 0000000000..b629550b64 --- /dev/null +++ b/app/src/main/java/com/vanced/manager/util/Safety.kt @@ -0,0 +1,32 @@ +package com.vanced.manager.util + +//Dear reader, welcome to HELL. +//We don't kink-shame here. + +inline fun <reified E1 : Exception, reified E2 : Exception, R> doubleUnionTryCatch( + onCatch: (Exception) -> R, + onTry: () -> R +): R { + return try { + onTry() + } catch (e: Exception) { + when (e) { + is E1, is E2 -> onCatch(e) + else -> throw e + } + } +} + +inline fun <reified E1 : Exception, reified E2 : Exception, reified E3 : Exception, R> tripleUnionTryCatch( + onCatch: (Exception) -> R, + onTry: () -> R +): R { + return try { + onTry() + } catch (e: Exception) { + when (e) { + is E1, is E2, is E3 -> onCatch(e) + else -> throw e + } + } +} \ No newline at end of file From 1c219ea3e0d09899c9cced8e4ae7dbed35f87c7d Mon Sep 17 00:00:00 2001 From: KevinX8 <pgnmaster24@gmail.com> Date: Mon, 14 Mar 2022 13:59:14 +0000 Subject: [PATCH 118/118] last readme edit --- README.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0c2f9fb947..fd35c5f894 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,8 @@ # Vanced Manager [![Github All Releases](https://img.shields.io/github/downloads/YTVanced/VancedManager/total.svg?style=for-the-badge)](https://github.com/YTVanced/VancedManager/releases/latest) [![Github All Releases](https://img.shields.io/github/release/YTVanced/VancedManager.svg?style=for-the-badge)](https://github.com/YTVanced/VancedManager/releases/latest) +# **Now discontinued https://twitter.com/YTVanced/status/1503052250268286980** + Hi, when we released Vanced 15.05.54, people were upset because it used the .apks format, which was way harder to install than a traditional .apk file. Even though we wrote clear instructions on how to install the new Vanced build, people still couldn't figure it out. Then we thought, "why don't we make a manager for vanced, which will download, update and uninstall Vanced and MicroG, have an easy and understandable UI and be less than 10mb?" and that's how Vanced Manager was born. @@ -11,7 +13,7 @@ After 3 months of development, we are finally ready to introduce Vanced Manager ## Contributions Pull requests should be made to the Dev branch as that is the working branch, master is for release code. -For anyone who wants to provide translations please submit them to https://crowdin.com/project/vanced-manager as we also use it for YouTube Vanced. Any issues with translations should be posted there too. +For anyone who wants to provide translations please submit them to https://crowdin.com/project/vanced-manager as we also use it for Vanced. Any issues with translations should be posted there too. ## Building @@ -34,8 +36,3 @@ Clone the repo, open it in Android Studio and build the app. chmod +x gradlew ./gradlew assembleDebug ``` - -## Vanced Guide -[Vanced Guide](https://github.com/YTVanced/VancedGuide/) now available on the playstore! - -<a href='https://play.google.com/store/apps/details?id=com.vanced.faq&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' height="85" src='https://play.google.com/intl/en_us/badges/static/images/badges/en_badge_web_generic.png'/></a>

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 O%ke+Hk#uwF^`r$y0*FdIgrS*NT^-DR-`CVSC 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/font/inter_light.ttf b/app/src/main/res/font/inter_light.ttf new file mode 100644 index 0000000000000000000000000000000000000000..a5f073690d3ffe5c251c690e4488af8a4fb441e4 GIT binary patch literal 288088 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/font/inter_medium.ttf b/app/src/main/res/font/inter_medium.ttf new file mode 100644 index 0000000000000000000000000000000000000000..721147d8311f1bed1bab5e39c18254beedcaf0ab GIT binary patch literal 292140 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%0DAB`*{C?!~6Pr26rI zH#az(q9P7L-wnWNiipH6Ogxe^5VLenJYqrlGh$ts$Bc|uZr^1`C%tz%G*Qxfl4eog zqlaDXN(~zfZyGzZo3(cF#-}MR8|a<=sV_DG*Nv*=W@a5Eq~9W7d+7?`dW!|Us>5}a zm5vF(^wm!u6ZQp(;%VzDBXURF{-5x!rxLzT%M>0)?(+RlrhK+f%jMxDP8X?-^;)j} zSVc;?`fT5l>qjUebrIa(*N?<4)XX#{w_jF2O0ln8ea83YcH)Q?%$I^9QCp~V10S^G zQFxA)vN~TEW&=lUxEt5Cw?`^gxYWaA$ka|+wT{{ZFZPHDUA5~>dh)uqu7m{mjJx)i z(}=l)siovm3{Ala?ZRmnFH9Rg?^g%sO(RD>9zLyO;&1hO{9@OVRLW1jaqQ@5ArGo< z=90?Om~hPkwg7!BT)DJ1Ja_P~=FX2dt$dBNxSN&+Wew5gu8Cg&+w!4r@05is4=x7J zTjOk{r;e?>=R%WQ&X6vbhY6M(xj&YN!zqU$@yGJ9iUZ~9GvvzcL?E>V6M}xMA4zJJ zYp1M!l;TraeJ(7>?TjOVW$l+Mk0#B^%DK=a*N-C}TxdG0^+sA2{kZBHcvWYjV%g~a z?P=K<|LtknNZC_8uBtxxNLg&*r!gp=b_C z2FKFAb|T+zlIf_;bK2@^>vG!4{c{TBtr&*Ey2`}=l?<+O<>9bq zV`Y_O{!l&^_IcDVS;os5y~*uF(Bpii)I@nexppE;TJUzBqTG$sr(8d(#E8`|DPrw# z>XOUHAqfd<|I82N(IwqEoRwHPrzp98TuC5XStYqB=Q(Y4Bf0$qIX7-e7|I73{!>~WOAFx5EGPz)yizqbu!kPL zCKG@lI1+pN#w=ondoAHg7N*l;yJ8)JY@Nyt17{Amr8`HqwC^_|psUS@wy}FAHzZn1 zhgQZm6&!5bie?IfmbRr+tvV!liMuq5{X?v)eKWS`yDGA1gHtb&d^9k$Rt?a;DP}66 zJS`$F)$ifS-ws5r=6W<9Y{mqz+PV-+xUiJUV+hBD@Bjrqz{3^{ND+EvR$JM?p~Z+1 zE)%oe_gp*o#|?U9$2#J0vHR3$`tZ`JtosoGS%Vjk-8f9}PHefogPT{7N80nX-WSOj z^>&R(72~!e+eXbl7=Cv0iu=)(Z8UH94cMAGX5k>Kn$@bunrST3RRD>4w%~z?8R(FVmC3h)7decb&JAYmGkYkU`FqVO^E&P?!Vb} zw5U6#+v>9ftD~5Eaj)#`_KUGpT*3OlQ!KB8I4Imye&IU-hu8fjJ zd@f;|AIu@O4y^s0({~YlePqq884kHMJ!b|dW_0b5nUuJ~O@#)%-x9ZVF?Z;nc{Vrc zo_(`Q@|JhaN*k1VJHck|$MpFHVMW`qf_T@Q@|l%}arH`^Vt*_TC!6_-m?VP=ijwQ^ zrKgI`FoZO%MwyCRQ0f6IO(iQPEOSWN@dUGHT{e46<-w*;Y`m3JUP>>|Ta=vBJLE!o z^sZn+yc1ik@8~+j?;$Oin?V{X-%S3tC3ai-CY z^AS?@VAFG?-$hJFE;MOllvlti?U`n!FYCe)9fNZ8ho(B;os}4P1e2GWMVj8O*LiUF z==_nZ=+#?y>BVf)xm#w+gymhjWK5j6vb&V5c`n?xy+pbnF?4mW)_Cj3c{cm#(c@=` z*JsVwW=hIU!G}4afy7&ab9YyM09Y2l$9EJWOPWr~?nUp(Gh*MUW377a ze`(PvzRR`)$`7=JkmA+7yO>uoe%|nxD=(Sof~GcroQOT;;2nEAQOAoGDCLIh>Y5O0mQFv)syf z#r$%uGyW`>CzNl6^Jlp{7LJLz3Zhtv>@K&E{sDySida~kow|#pr4n5c{z*&qZ=8vC}D#?=XrWmJY(4oBEw&^6z zd5}RLJexfAHEFtGIWfE6^RU~RBV$(3kJ%Z;vuFP`)79ZyZIJLB05cvsX%-_0Ww~Bw z>EdW5XP{HFRRsMwS3p2nsm7`kr@Wz?^7oMbg`WyZfB44a6+&HHqt2o`QBijmUBe$j z@S%$3B{JZC0qJ|m-24*VRPcc2UbN8OHuC+HDH>JI_?({pVOgb0%RZ#1f6l0kb#+!7 zu6}{VP=oDTY&pn|qE3xPdpqVbgfqJxvn{X_#92}&o0w!hAyp>{RU5UcNow1+Zd}dx z23UaBY@F(-D2Nk(TlGb+sCj)P>)OtW5BsAH$XwD8RnIZYA7504J)u7XotGgU5e z>lNL4YQgIF^c{IgmPPtUI;ut$#gopSqot;izV7i|pT<7R%Dk7_ii}fUNu7wWBo{BX1R9C>PHDf z%IfoVD7Q0CxK!4Dx$ z^Zp<2#fyzNf0O5vaV#0%2?G2XOW)I%m%+=QgL937`@bJ{K3l93U1oEf=ZOkgO4uS{ z;v2s5>>4UDApTIOMV%_5DQTkJUz9p$V^_bVfCQB+FbV~VYYn-|E~O6 zw0PP2cJ*7gsn<3yOX*u=+&8s;*bdzIR46?L4g zoQZ4!gKWb2r!pj=^OmOza&AVNn)e_T*6kxT*KMK4Z{4Ctw~!bT9eZdFHJh-@-+%YS zq3OXbgnI_954Llvs8mj&+T(N5HqgCq-qAG&kCP-)b%{_}uuzMl<=4{_|5~-;Zlr7C zu5oYab8yhJaLPCUwq*j_Q!Q@%x0P6G1FjNN)v5!B3Z`0uFsU=p*_{<85Q#W!Obgl= zocJ!6wjw9P5);GlH>h8%>->pyg-Y?~!Ko{&84u5ijN2bv6f!6@{+`3YHUmds640Nt z3jHbB_5oICDy`Cb&^syxrNsiu!AMbKyE+lD8On7S4@bT2^bs*;b=8U5Bq52W$Zz1N z5`{cUXcGj1qX_p^yjfBe0>HTvXM7hFjQyW`rH`-Y^)F>|Z(LA9|v8e69Zc|01vz8wJKr=9yASloup3+mHWlKX4b2+p)OT}dn?VqYA1_to1flmYSe{d5IChD2Ar(}h$#jj}5SoT6G zMI{WKb4f9Y&~AblJDWB+hMh4%n5?zbycPnr%NWtnsVW1!Y0mw(K&)*4hbxIa_I_O0 zUCvPwsmkU)Cf-M;yvZ0oVsU>Gb7Qu4zrOtj^o|htbrpTFZ=QC0oyXN8GX{j``D&NR z{b|q_rsga)RSi@zAEABn)JV(mmlLikhC>g>&qzjHAPM}3j}naK7z0^?6c66C4tWeW z*JZTzw7Yk|ABZ$va|I1WLVCT3hD5AN*+r&2U5Nv=RfUFnh|4g-9O~Es?mNs7MQ^ON zlN>XONcfmB!!4UDM)VL8`Vg1)1De-RSCbs*J!(|NuvPfhL?XIOezi@=#mrId=R@@A z!66uSZ%p1bKJ3GM*w3Wgk`=uCv+7N`^5@FNCC_BeqMnJ4^;c^E6SasVTNeaBl0A73 z7q1ETwKGck!b@Tm9!5xMYyf3H4B6U05mCjE4Yd>_71bD!ip;n2IF7jArYo9+&7A*} z?rM(oqxYo8v_MQ|SP>@bo7BzTCEg(PUuf{T5-y7hiLo8^`O*fVO+u3_-Ct?5>hszK zWJ+n%jALN{KXkwvg6A}YtTKp^N2K_H5}6rLmz@PyCzds;%qw~LyGLV-YTi{mV*8dh z9`unK7*j)aLS)dt4FNN;uiOxxNol3ahw(YJj{MNiS?L+p;&2|G3DaqmVJ76YuD{GBRFzci@vhHhaY&&Zb7POG4;+|pMKjJcR#U`!;#3hgEg zuG7u)cM_$&1BwExR+;eNygZqrB)Il*o@A=?C^r{ZBXxuoLJzj_G1_EE zFZ!gl5uWn*%#~~!Mdo1{fS1@i?4OWB?4h_Zkl!A!U7;@2zbvyKVWP@;+cN6d1tx zagr+ihhvjqF8_QD1=2)G%YKSvWOp_6$1DHgVQT0P57Wcng37mm)$2y~5TL$XOI$)x zZbwT@Jz{68;M*q$K_>~34df81N*t!qq61n#>~V3)IXTI+gZQ4l{B!Q}DQq^U28YeY zl=KDnyU%BmY2+{vf(D^wDRmv?q802r!-N#MQ9^!f7JLRQO#4IQY<56dh-Ss?+)&`7 zkfl71zXH_H3YDqB3(S*F4ahnzKMH2yw38%FUHGQ6ku;fJZX|@Tv8b;jW3i1q9)lNO ztLet`|Bt3sCtkkPHu|aQNsuEB0ad1OF(|)L$=ehg!cTac%=Rvq8V1$G3bbOi3a!Gn zBuan$7aH|@8rAP;|1w>`sNq<^pa#b)=LX9K;?gPO*aIbswuqFD`w@XDYYADKLOX!6 zccQCa;+3y@nn(=^ABE{*=E-=K6;cE+eI&T29qfu+i=x*BI)`BI567KYx zJA^*>&AC1P4*6}x3VQ9%X8K_%sp>VyD|vn2zUxVVcBaylbdBjb>d5?l*J$>YrdMdz z)pWq(IjcV*%U(q{jeohA20ed{4QhDFBZFXwkW5o-&D180GTEl2_l?v0uKaYz?Iq2{ zkGQa^-A#IA>sHbpPHyeCZKFqT&D-nky?5T+ecs;t#AvD^k}!iU?r)FIkbpODNxKP{O5&jMg$G*)ahP|ltG{g{U>^I@>Vy==OKhFE#v<&jFYWLNBR%3kT zkc3?$#DubA3XL~}R0}o%V$rn^SAp*&P5^JJv?6mKkbx&!CZ3%eI(BJql5{(zsFu7f z3sZ@>oZh+K>+rt0HDA__Ts~~#u3_5P(%o86w1K!E$LFdxdSO;JC3m2Z{g81aLk>JH z-m^^^UOAGLI8xh7Izb=W<-DY6 z&*1H()2aJcNzlWKxkSBqEq%82{4KivG)f*#-AC;6z?*}%jG4OVpZU{Y%(=Y$c>cW0 ztLc2uZW8UP2Cv1ZAA(Lw#lV3Yd$qC}y*u=_ykW|mw78V(m)ko#mpoEuW2kDxxRtpA z>wUZtERQkc2rS!!)cV14+;{$*oK7|Ln{@sO-LrKYY0K~0E^Z}e5?r>OxIci5Ig#Qu zE3g`=R&xveDs7mt>>;A4>;DfI(XZ9Q0~dmYT7rh1veRE5@OFQ|iMsXEY(<9iF{Kd|xnO!Oyl_*4GclYACSR->w6spOF z42N)yafL%C(GwT+q}E(($z8gj!DKGSOcTIdAryLAvlbg0955jLOkQqH+!N4wY)b1h z{+G6n-a$9Le@?d^G9u1~6HkwybTJxJ_~A2sbcA$;FH*ZbQi;L{;p(dAX&Jqz59k)s z<@d_Xs(7ZJngO=9Vm_(3H*7(dz6(bTit1UtLq{Ur+(rx*%r9BXxhI0-RV+B3tp}Xp z?Mo-==Tvqsc32z2`@9|x=;4jvS9i7$v-KwQPdQs%;QopIXAUzbwM??;-z5t5KVOX> z{g|09_n*{u(R~;Gl?u56>{^M?LUhdpIwsxY*sErNiHzcupby5YkQP5!;;f z!fZE7`oPF@u1Ei+!-$bk1+M4On$^kYTlW@6&Tb(FT_si1{MX+e-`GE;L!UJut+r62 z^f4IB@rr16EADlqJG0oE!ZpgtS;2@+&HGndig%!o8GU)-Z+#nCSPioD8cIHVKz!uY z)~OAhty|O!A5WB53XAfy{*1&)#=sycT-mK~&R3$es8p;n93L|W8&Mh<42$$)XABE2 zt(amLv*SS@NNEcncc|Z3k*RPMPTy^a%T+q9*lUdw`F-)*>B*XA;ss4J7U)^Qph9sv zJw=CHGc+hkA@D4e0w7X9QVu^n|q2FA(26THvO7YNzgnng`dCbBRZb| zV#X!Z`1I4!M`}#Zi@UyERyDzo*S8HSFZvZh5F6NUP{gB>N5(9=%UaO`iVHtrk=zj>I;t z@6|fcvq|q(W-Y9H2B-82+%(ZG;&5bpx1g5IyqmY_VqdA9Z9-n~w9Ao~_kaCLx)vpP z52$V+eKD*uBtI4STmmvK(P5T_Q0SRXIV|C089|qPU8)ZHx>P(%P00I2J9_oru>>hg zE(ljXkaig>VSf!TD4<6R3bZSTYIJ^h#I6uV*<0!L1N-UK?U)dEbjVVzu&J!Xb7!G> z!n%OH7P?Mz+$pQx_;s}qLeHxPYbw{JN4tr!Cfa64#3bn){X{B=&MX+a_^cycO{jSO zt3o_*t9UdTgu9VZlCEj!WlP6`ZH;YhOzcAx95IUc^wOxxru)Wdz32uAo5b{q2&f>9>n2$FB+{En<|H>9@wsEQD&RHKb<#0a9T$z3DfAFLySkHv=pZwBo*h)__`)A&ZTEMO+9vuE;x1!Lv{l;N9%?R4HL^iO4tt@ zD@Hq9Rrt+ZRan%P?vYc~&^_9NCgSBYXK4E~XS9FwEH1M!qJ3aB*%*-(993#4ngMyG zYF`Y5={@T>JKHV<`L4MmlLVpy*(j$84C{!q_eo1-d0=8j!AzzGwk}}HseM% z=-GT+$Km6(eLrePzSlI>ylN94T&roDvVP0f`SKtP`}XQUOF)cZv>4HQMT%7_&SFAC99z$rWD9zWxoYm7#36rY(rRD{0qJOQCgcDGpP z9-a7={zZrUHSG)OeHz~NkJ76eLQ*kOXkrJ=3v%90*MI#+bGJ|Xw!U)7D_Jv$s*ReL zlSPY%{I_t9o-y-J+v2~CzCtdcDqC;?&Tw`a10WpYTbGZi%P= zKSQMn{9gfjs*V9wTQE{_mD7Hx_^s3OjXYK^%Krm_R;myFrk$EZto9P<3-U{4tFUEW zt-}zeWfd@IlkZ0QCKH?J#$lV%0<1_=+hq@E;d1(wjwmcd_9lZB#Qfn>DS~PYtz-81 z()p6&bI;f=w%^Q#FA8e5i6XHr&D-c0xX9mZ<=4D{W!vq*P2g!P{#v!EY-zh& zStZz|asqOQUC}sD?0nD}Ur?U7PLnR!uwT+p#HAx~mFhE^@zFfZ{AvJ zbLHgar+riD)5nwGR(WLSdvf`~6EghE#JzN#cFOOe`O`1I`)g0!&V}jQVpc!RPK@g0 z+Pg<9k8Y}-Ye{YHl72{o`4HISi%pitbv|Bfr_xc6 zwIe?*S;_a^a#r78^AECUnHbPp^Tzj?Q%Oh%J!Ro%F(3S#NDG)ZcL;%`X{!V zvrP5yYm|DH=8>kI_;A(C{;MN2&`-W<7u9{?=yv0Kjw?E;u@#?>PIB1^cwT_f1>`PdR3i>TgQ#HQP((}M8ubs- zgH(-+f^yhM^L6Y5u|$LHmgwLVwvoQ*KvtUIGIky}jYBv>Rk=`U#N>2N7e$b}o);WzR>CsQ;r! zT3gjv%}uJMsTZ%4m``6w>@|9gO#OS+(!Xb>k_u$#WV&lOH`x1#5afgsswP8%FH6j z9D{TMw;6L&M*0+;Z?b4&W+kQ-(yiNf5RccdNuM3t>DD(_UWcBZe)$avJyjFQW$waM z;7)FX^Vg?4=r(HqjZ{F&uA~y;myeW2$?#-bwF^h6EMNzj#DE~|M$G(+i?%P(bH>z) zKxjjTlyme5{My)!0#Mbe3;`X4IOJf|nM-i2V__%kSir280%UVL)04ukuz6j5b4HF? z<4x~uB#jOqCH6V}ukNS8;ksuATbn62_U9jq6hb@ zNlR7O&M~q3LxRtyZQ2yE$-n>d;1QcfNzf7QC(RC=B)=kB=V<1IM}!=t`)ty*>jq8f z+HdjjpbQ_4=YrwGX7}kfb!d(zZ7E&6@qK-hUun^?_4J>mm_5*(YB^A8i1~w@1lgb# zLk2N*0b-Yl<4#V{PL&R7&k4}K&n;3$)43We6XfCxCj}A8?O&O$*>+?!J`hw4LQ(~K8utBHOpO%Tc3`AJsa5_ zcG06Y^JwvUIc>yysoaw@$ zWHkyTwx2){s?ttkwf_|iWa{`r48J`6zoA)M@>n&%zz){2rhF|Rd!31#z0OJwc@sp= z9A&4uGPSR4+Y{$br(bR-hn^!fw&xR@ZB^*yU-zUxDkhbkmLCn>PV6>rqepHal85Ip(X`JK6GvrBPZ z>OvFhRJShvvejb+TLE)@utsVG7S_$;q(I5=^RY7j{;L>!i{|70h|ve4mhM674pQ&n zeqxVUzI_WL_lDsQ&A%~mUmz;%i-|oj3V}Wck^)x_A_Nznhph4@#AlTaZr8|3xwpW= zxDH*L@g;4}mlbPi9b=0H_fm4GCSBWqX;A2zp+nb%1}*I`?)9AS?>o15@43GI^F2W) z>o67{gPQWpxLQF5G&kaIK{{eFGl$nAPkRHtP?`%!XI~Y^OeaRSk_ibtN1yD-r%$(A zktQ|vE_kFNCe4-~8NCe-*4s$C+vE0QYNEZDjCBp&XJAMCAJA0#40#uZ(1(lWmgG#% zCew+ZS3;-F#NosV(q=C$#@viQHnvmj^8RdY7|I`jnO4Uqb7o?7wMHa8i}cVl{GV8= zba@^$9X(0%tl8(Is zF;2{%L0m}BnVLlI7&mr(bX$ot+F>=^n$bRE11v#Tx;zF}TKdizQ3^;_uW<45WF z?WB?K#_+H_Kfk=N@QuDg+K4OvEEl$D6%{IPq&JVAq*piQ5yvC3`$B^Ej*s0ta%8>? zzVaECm)yT@J7U*?01l=U{JH;Sn@N-7M~Tx8fizDTNge23p;Db*^$yU2TvE?BFFb6c zpWntXIMOI5oFt7m=Fy867$8~?kr-FrNE)2tU61ErV9VN8avv#CY$TOZX$FY|-u(&* zsf{FD{6pXwgc1q6LpNSS-JZ!Te_$2iXusU=U;h6YxO z_A-BijPLA%GreqG;l>|pOh>7LiyivmKVNDUGJ_2fwk~i%ob#(+qPH?f?u#Sc`wdMP z*>!Xq_qdK?KHaP-9KInq`Q?h0PvYlIqyaHQ2CWT?xU+2}spK=UxtXomNP4IGA|kGt za6G5qE0_2|T_?MZZta$~*rRxkm@)41jfC0v65`Lt%zrS1{^6bH;JwIaIBqRkeTu%z zb1<qZ zC2KL-gSGB5=pN0lN-R~za=XoaoWB$*cgSrU!~yU6wj1f%9)mvHVG-2go|{fsg=I2Y zsX)XvEm#LMDr3_?)Q5i*hvdS(#F4|0sJ%3JZS=%?Z zhxeo|uBjnAza~%roHZ81X%@LWl3ASfcxA!1kVRa1kN+ZT!otV^w5$b^`5wD%>xcM9 z1`nLwTZh~A#De2?=hTsY)gL+#sj7P!dQC>3T<_X*+eE+APBM09e_Oqie(K*LFy7BZ zjMU67hhacBU3*W5vBn&_rffn>amMs&WlO9a(##lfI5~pq#OivyWy@fu^6`8I=;FHq&I(soV|>&?%i6-o7QxF3Q|VD)jFd06;af#YhDqw$w}9ZQ#zS z-Nek?PG!V2U1rvHfcNGW=5bDJD6Pf)nV8xSUUj^#c$M00lB%`9D%>TlYoxPYsg|NH|NKpmR0%WI!N_`mayzoOU-o zD#fvJ!gFD7`rWk7sq6EfCp30UiPFp^mSWFEGgp&em;RC1ys*=pFq-Z@$=A8qsCnWa zONnjftc6Z~liX?gm^q!riI~TS00l!7Php5UP+S242Y}yx#DO9@2mqW6lkCPSo+=NE zw##?0h~f0LIAGzdO!|<+(s|ApGRl3DpOf^N!9pLcp1H``cal396*i}nCWSsEP>m`U zXs;R7R-Z%K)uBM7ZEa{vP0SRv?QA8598AKl0<(uC%EKGMAlR)Ij!x_*NbnDyHn?tW zrg>!qso=U-76rr)60+zGe{y)AouhVi&xVbp8+4J4$ggBKX}F|b=-JHvnc>F9Rl+w# zB%Yho(`(_eQNdfsRj&BCult~&h8`JD>7QHQ(OD&vQjuUiMH7B|eFL|)7vEh;S=EK~ z$cP`isxKiOmuj!Ahko-eali@tHgVs&6ZXK6$1CZzkMl&aaZsOD0j-qEk$W`D(qHF| zsAycfd!ulTZ|^aw#OlrxQt{qOuLblCo%rq>ok+hB{)g565@)ItGon?d0xk>L6f!+?Mrwp@0uZyavd+Wv z2Zv5w27KsrApKj5u>2@>eEjJjo$bVC`?uS~W;1=ceLJbLS$vNI`V{=k8OGro2EJHS%n_Z4H?*VZCn4Ry_wy*j zbg-$x+EKztqjdfpYgrgc|1nDcaJynXFefvbB-Ga7lv^9wYA0qWN3MJNR%op8G)&TX z;lAeY`hoX_oio^JI{n1D!NXI+L&;NoqVGiV)I^C-nCl*h@*N)a}0>DgUg3qU>1(BvUBu18uTr=%Xj=17Y(qQkL|R=}+|0E|9up z3FWWYGvmjfiH$owe*9??qyH3#QedR)MR=Y3_$p4*Iu9QUE1`Tdae?#Z1qRNa|9x{u z=LH7Mof{N54*-P=o2B96_EH25*H#p_GiNb8+e*Tvbm=`<5%@TB?s`hX#U$Du1!oj5 zmHEmT+4>lO(+77x0jI}5W;YU@57SpmmJsX1LI>(VuG}WpFJ}-X68S4fhlb9THpJi88~&MU))bzQSEz%~;V`jYvV^`mteuFKh(ef46fiI;RQD^a)SB|XYYDkyjfn;^V}Y^PnNEae`wgM8OWs93(F zx2_}{eGTVt_0g4V71~SbO5~bSddMY;Gh~l4U)2>Q%<&lQDDI);953n1N*!9?H0@AXjWm@|P_w+Vi%A_Ox4{U4`GVoZ$anx=DIIFa?&ioGnI{M|a~_+^t|QFh^-T z65$sB0oD&tsg-^L-at8ElWG{WL^-w}ln*6vc0xJe5Kr^^I1{0K7}4@_XX+-NBJhh+ zjwqquSWPGDMotrU02@}K#aW6d(v=m3$}$*zk-ILvD{;(4(MN4XRL4Vh8#g)(;tdB0 zw!C4Kvy_Lra(g8&N5?@@d;N2Ru%Diz9(&H}A)@7n&RrqF3YD+rB1s~8|E}*){!Zvm zeY0|VB`-&tp}cLP*dg5|Kqbd3gkoaQpLFgg-4*Lh0np^r~FBOOGnoD>iOa!H85D9Yc#Bc4&KzNK?asyHhx{c|rYe z%yt9WzQp+kNn_HjXS9otdHHk6S)4x{NCL1n7L#tT94ox#FpO2+92HsuGEL=C>qwtaDkObQvd@F)f_68 zo^L1KnIOLdsudJF6$N5nWiGa5nCk-Upi6>**NKRI=_fi0vP}}joew0vK=8H@e6{Ho zf;V2;gqM2iUm8y!E)%95+JqpzUnw>%*cH<0qXJ=+1-!8?Xmc%C$BF{wWMwYU3k@ld zktj6bXhmDfBwjv|mroR!yg_jFXj4@ORaFL-E9{TN#nK+X&6EzBMuvvsbz%2IVKNMG zu4WBQX$N}ghc{4F?PQJLst!e0#Op>znnp?oVYfB``@$j9hGxiG-$a|Bz{aWYK{w4n zkI-`QD239_*sDqh_M?d~G7{5#h)QVxknE)I>3g$AX6(;T4S)edyRYk;L5tpJ8yadN zl@53vRysG@lb8?_ywCp7o@k*y2~#zY?gIp!#f307USCOyN|Z#rMbz}0b_x5fK&E>| zdsPG6JSUs4u+tMe97DLBOzMiP=DX;->+*}LibalyiYt3rASy+Qs+W@a>7kJkwP=q}gH)s+flDhPQ`J`7gsSXBVybFebX(j+Kaz@o*H|%K)kS$i*Njen zQqCw&IVdIaUk9g46As}Mz8?b2Rtk4jTNPXKm321+56$m#5H#!vhAP9~j3Xp8-tZBT`Yu zzXLPI(FDn;_%jIkk>ar`N*MwRCp<^{Lgm6VI^4iw@2GPfbh=Q6Oe z`@%1(aZ)F4iT!_rL<&1FcEpC!oxGep`~T2O&rvc}SE3@`s$Qy0luSd(P1Lax<5X>>RFq8D)iEahR9(O|)yf$t zInU~lx*#70;Y?i}GtxuVL5*ENISVBpz+4`Y1F9%hCzQ;V>i}b~RO6J4^QEEW3g-Hp zASpehelppz^Scs+t@J34m8Q~HQolEEMo}9AIlM$$B0yuyw?Dv9k@h_j$$2ar4nX3A;O%l7)|16>S!{;{Ej&pF`A~5 zxY2ZlxtK(9o*g=R^w2YsLw)2=)Q7QcaztsUY7acFhVyoN>=Uy|f$Abxtp5V#LmSQ@ zbP_q@tC`aV)DDoC%xghQ`frCYB+o8)RfaI1jCCH}t!G3FT6DX1mo9d5NYxz&H&)1@ z_X`pd3P{bI98!~gqWAI1G%Jg~%gLc{v$BYpm@Yha3hmt|yye8UZQ46%Gl&n(AwHV7 zKfcDAI+aaKSp&GAjWzHt8~A-u^3brpfi29}jyzYP&ecRVCYI{RkY|(Iu3#!sKxY7r z0<0JcGixiP2N#>xb~dwz=K|9kAU(Ls%t{i@t|W%5XT4ovN;PKdLIyAK@mVrBWRW?M zOw*swT1~&K6x!XT$@EVaWJ79_#Jl&%M5Izj1T(!)lkTk{ws+!4{2lsuO*VaeCjlSf zK&Dttj51=cP8u@aXYmlUIey5btFalxNRzyV)FO%Z?ja($)|xf+PnvS?9-_+sTtkfF z@M1P^F77UUv?hx_x)c8|!`5d(k^`~1T^IHkwHxR8#@Q}qm(L>p=>F45h|DT7gCtPy`3xVBZP0ET< zo-b1-+W(1QcM-3U`AfoH-~P?DU86ZY|3^ZdJvJh3vYWGWH*E&(`o9sVQW37SRrSGg zmV=MY;3)~!fTOuN{7QM?za#jGqbYrUPOvFkKS5{Ry8K{AdhKiD8Cqf*YJj3Ib5|ahz z>B%|QZ_J@5E-X-1jR|*Z_FLmRjVn|%4eRG0PDo_9b7NAkew_w}mCPas1V*WJ(3V23 z;J8o^2QFl#kv<-ZYhd+AFb5)7wir80u_M9F&bT$AB}c;p((Fh&X~D3ONNo}Y9S-R2 z_;?DfhIVBlI!IF5s;{F1L!BSL4MYN_;|r2fw=~fj=+8fK&cnhtZQ*WNOsF}aa5^(1c01azh`S+dQOFTmAu`Dj|d9r z*572V$%>!hQ0?2lf8WgHuAO6I6DGKJnm83(>qg068fZ`%0^+Zn3b_eKujlzOqrH#< zhqj3~kPU3&#G5Id#<;qU>C}<^mi+O(^x4x6V>Bga| zwr5_4@TIe`Vgod1*_GuXIy=dBI4Bt$MaSNrg96{ZKDp~bC9BVs&Dxxc8ROo+c~q|| zzh?(XGWs>V&K5iY%XYM|HkoIXG-_~IaIh8rMb@TR)U2CrHkeoMrX%0Zh74xMK zfWV!(xcLJj#lx+;MjnJVXYkn+qOM&4;+y=%{hA(Xq-Ep>qlnY2nS# zw7V0C327f1zj}3iXv|s`R1^jkRFdH(FnH!{1j;FIaZ3Cc)7;aeg|ml;q>$PdACZpt zadzs{+qs21q=tBu5rdvA9*ZeE94)y&5ztagMiUwH@ug9%tgsa)K8_hOBu2Gd8z8mc z?j3l3yS9mt6BreX-WR~{7RS{ z(LdK|;q=d&SwQ`iIS^4gu+U{!eWE-Tj;gF7G9Li=kMmW;jD-kOb>R#TVHb@>*uarv7*DUMs$LGuwPqI=o#C!ljoFIi&qz>OcxwH9qG*aBf1J=XfHCdZm@^SB0SyM zyGe839#yVcbRD(O-+j8jrPN_#;No)uNrhP{GlXIOorbvna@n%$=taYO&IqtnbzB>i za$#KRUz%T0qn363G4-jWzTr#dTF`iVMSlz)V_ElseB0*b9L%w8PA-!nufpOIzADt77$g?Eys0%OvXM zJ}a-rL>yk)($3N9mu9vtmL81AqD3nPuDX`*Iiugum7N;4wXWi7-#%+-zZstD<{s1f zwvP&E@LQ+KzqGC2ag|@+X&%b89fF(JXj#3wi(UV;Wt*TdVZR;G+ zVHr_oj=#Kep!Rs*X?^;&uivw#ZSUIc26#;M!2f!k8Z;PSR;x$-_Wk-y0~tMpTS6-X z2Zb%RHEvR`%N;pYJo_fUiNs7!TEx>Na(^T&J~ldBN77gjLn3eWu}-@h-z7GxT^;w6 zSwukwZ$%jGg*$iY<<(0_&Ce-WJ>Vall-a}BW07*QcmJKlV4kV1^=G>_^fe_kyAQm5 z0^T1c-7ni7Cyv`GjX4ofBjH-|5~5fU^;-nHAa?u0;1~ z(&&Em_0OLSDt!55h$OQmYqh!JA%h|87}=S78R(OFm^LdH6lX0slafacUJb0R+gBSF zL@K^<405rn+PXnRG#UT-bp_*Ml~HJv>h2dJnpFItQYGUMuE04^wGbdMJrXo2uGk@K zi7c}zTm51)p*g9q?fl1b1U#LgBlaMNkee#)Ya^+V){GvL8nGc!Et*LwIiNODb;2iW z=9)VImKn&OKUs1_o$Htyc{`Xp+}lwqn^Br0Yw4rAadCIauWPeNjoS$cx9Q`opq(>% zPk%f;c+X6CLZ&|NgqkCZjN?&hO*W~1CmwS4lk7EkF`n4=o{>Lt#*=Bpea7yfna>y{ zjRsd^I%GBHsl*XBD(hM-1`U>~TBC&qkA9=$$=sTE`;Zwl%v70vOk8*@b#Ht!E~Jk3^vL$L_$KA;s*HD2BA(@SUDh?Mom+I5*(u9xTh_Ih zvKm8cCMkr2hAddz9KE3jbDpqLAH!;CD$LMsn7?;w%MrgcsnDca2i&){Z=XgXd1qvp ztM-XTt}Ti;GYko1rC&J64jgFx+W#3<%p$H*!R)P@b__&tKK!iu1FNyVK~pN4xsUgZ zIv575c|~_OtN0<|?u@aC36aA8kg~$4^vR-dN&+85 zgdxrk;2L0OA*4EO=R(JPB-81>Y;sK5meeLIsY+X<>{qmr{INkhMaB*pgLb(36}pr$ z9}V$T*-w6?s)}ipm#j`wv;F~lrIMSaY5YqgyZIqO>Ax8Nx+W}b>xU6Ny#4<2?cFPs zv8gTn14j<@4&Jp++eb(pG9NT%3*zDm7N!@(#ulWzk8aUoRIlEnTC^A~zM1kiBjfE9`S&58CBA;ke0-Mq z`7ZGRWhV$pQd{()=VQ7^8J&p7_?YSUd@SK_L(3k~UNRr^itb@)AWewS^D!YwnUoJU z7V~=J+QLMzG3`|`X~90u$NHx8g_I;&^6u(jA=NVdiPbpiSdE^iIZKuw3@v(%^C;sr z72kr_V8zJHMo1DGI}B_-;f;>ldG`ZicD~cSg#(X#mS>J(dRD+P zf9sX;;@StsK3;Aio!ocKnip{@@!$)KLes#0eMfcZxn8ea@LP14ckFtO*5-ivbn0pkmGnn2DkwB7ztI6%$~>oO4<+=Ljn1 zob&1$F|IiRGpD(4_nAR=f$#hO`~3I0j{-B*sk*wmy1KfnYHFze+-_@TShs4`(zQxs zD~GakhtB$A8HiO&{3Imlzy4%iuBPWU+&fd|{U`Q(5R66@@yggD~tWl?h2$mG(9+Hc}C~2##tYl>J@s6~c>wa>i^C(w^pb z>}JeM0(*78(Oju4+*PUwcZ?d`Gqpn< z*h9qUsDo*7naYOg51`8>?pH5SdY!l$AWafidK+rv1TvZuC7X<(Qw2h@8Mffo3|pqi zQ&}z-pu;-AixK>vYHEdw1^K zy?f`@eIPOfvv{HYqAI0U)Yf%`=4i78qENSZ2^1fme}2PI2iZo0n03%RQ@@yOirA^V zVjZYmRoO(R1OD;kzI*Q)6MchX-x2xJ)XR}AXAOHLv;zYo3+wmxuHC~gq}Q&S{>dRd zX3gt;(&8Ly4ii60eNgl7oTg5=;$d@#ZE`s(K&U+{n(XUvcVMfwC-}{LG(j|qGX{nx z&5s*4EO=^^kKa`BoiOh95qoq9kPSp*Uiv36&E^DSue7b% zu4q;T{nFB}DjKjAA#6a(Jg@N|{y6i^>T}T%o-^m`YaAL1?icf5POFF(&4;ya6Xh-l zQ^k*NNzd0`BvsemUeKn~{i8kl1?`B4JvJn*agbZn0gW03dvs&FVP{N_kLtwfZkoWG zg;q*`akX*;Nm&->E*S|pj6V?e!T6TJ>9?UuA?)M79_MlBHxKHsC_})p`6=Zxai{;B z7n4@RhbE4?I%)FNk@3ONo8n*1Z8y9{%i(R?M7mE8cMGT=KO1uk&D`nsdim?R~3vtli!Zv<(KTy+PaZ z%u|m$dm(9d{a~7uDud&Ch~n%~rz%T=I}6ZH6_U5!xoIxhT!lKXC_f7k=N?&u9I>4jmsJ?dB7-D>CM2*fCJI|F~uY8U&03 zarX-kh1C`#xdc_m8say9{b-Fr7WR)H|H@-WwpFJUOQK;XU(p61S~FVq4Kzitb(S4Jzh;5Cs+AMd+zQBUkgp41!_uc z`|qPYQNd;5v2Y0C>A;tnx|OM)E|a&PKMRlLWj73#INxfVkj2WB1;S}XypVN*o0h+Y z$2X+!H!=f3&`nZzskUwpW&uA0t4eV}e@(e2CQ98!KjTW$?$RaHwMn~Nsx60b(F(G( zRNFX84nc~bIU!w@O6uyVRhXR`oDjW?n?x@;57M}#f75j(8WWUT@u zk0e6O@lt1gLP!{goc#%rOYyeO{e(z_ zL+}cR_Z0n-DsadJ6C_qCFE!CUWezoXM%*$SyCSk!3!Z?vp@1o z`8s633(Fzf6$Mz~>{+^Dw8LS&|R0`H=|{j8eUMsmCVBer2q% zS}Kluo|qs_0jbO(Pfd`^aKwB_DvdnPOb{nPtT-gy1c9eyskYDqd7hggnkG_hVhP9# z6XZm8xKxtd2IM7!V6pVfekGNax~M{eM}9&=qbE>ViI1NUcw~JNK50_;(D=zE@MgLo zv0y$xafuB_d`Azb?oCbEmvRKFvoACyUXmMI#C}#L8DXde0vnWgDtd2wvd@r)Od+_N zzm2v_ajRpqb^;QD>C7f`0U?^~=-F$ymv_X&_eYMTH=YoDMkts}{M&{!Y3JFe)5>Ef zX0{tQsmn5pRMhB~{Zaga8nMygso4KQGN?TH(s1&Y#P;nUJ1HzEs9#L5SC5gx6CvVw zOmu4Sgy8s@Bd!$nTHxEXvuCsBU6VUEYtpq#)BbaMbe-niH>R*f(J6ub=5z-+z3^zP z6#C5tgOM;4#;reu9Bo}D7E?x9}ZL!6ze z2=1x$nRA0)D+dkT>dz2GTc7ZXqAZJ?;lWSf`9 z?Z!^DaNHUYy3s%UTw?#YxV}w;8VO=_(MEBX=IkK)IY*{8X>sh2_TGI~1cq)7*c0BZ z%McguI$hbbJ`arkY;}r6nxuinf>zlec7Pkz7>m>+#<5`G-oVp<5iJ8eaoNl0@?T{E zrt(%r0Tpj12vkeB5xpcLc*M}7qemVI8xcHm{^;wI-2>~#^=lf`Bz8czp+mcQh7Kv( zZF*1tMOJ#7>7LyucI-H@yXSNpz0D%up3}P}S8emVNB^qrYP9G}UU)ZY>gn0Ei8lz@ z8wh^mgk;xITms;sEX-1A{sKUWew!0Ifs(tPfs#S($4#)PlpMqoQ%K^zXCXz;_8CT*vU`;ZmK zu2HbB^@R73vO<=ulc9KGo40#@LNQs<0OK?)8sJWyG;(?lH^E_DRyp%Ue8Fh@x<;x1QXi1bfNaY?D5jA6fWSy0iy1PkqjiK(aX2858?#aY zsSk*TLmHVNJwG3v(QG-K5AdcSVc|Z*g@dIc7!Xcmrhj`%( zP>PoVH8=$467dm-fEsEZKtAcglNmKQ!~-?Y=6OI34)I1F1Fsp>;E>*ceB-4+4Te=9f&rZJYfM0-TMCbNaZHH_jl<2iXOQUuL5 zZ2>Vw=d4y?mWsBCg^XXsLULGI8eM+$C@NSdjuJxk2Xe$n)hv%mk?SHyK5QJ&u%5sB z!%-1(37B)tZg*E1KPvN4mpO!KwCba%MlH%ENYzA<3y>O=ZR+2kzMtE}k&$wV6uM=0 z`}@k67{h~3bLn0TK~FImgHlu-6cNwYG=0T142nh_6b=ay(=aG34+e!p{KOp?6b8Yd zaEO255|ihEn`jPUjyzW*XHe)l&ACZ z*o$<`P?@!C&&xSyv2q^SA1x-Ra3PJCtHaCv#vb@FypaAT54?WUzUS$z-OYKl`{;fsF%CLcm;TFu+++winnyxrRem|GLpRbb z5C77Qt{NXr0PBkB$~hlgwf_fQ{Scfsar6!!pBYB3kaJi|2Ndr*YVpqDu>u7LF)iQ0zvKX!^|`5|A?+x zoAMb6y9WpJBL*;k7GP9 zUzeAEqpQrzBi-_kJkqn|zlpDg2$keZQV0DKzGFfuD^z+z8qxFeC31f%ib^8GW1Y-Iie+u?!9~ju)BiQ^G z8}M!U0B{`&+T*bd&K@{Tfa3Tef)8{O5G|w-3x6vN~+YY z>W#W?>YSx1s`SZb9^%Hd*K4j{N6J-sy3`!cc?tm~7u9%OeV8bA`2OL-`S;&?4i4_4 z*KfRWV`KZs2+-#S3V7)CvMl>Th9R0Q@;kvv-;FEZf1wBo?lg30C;Z6og4?zW4sO>r z7=slhZxS0>bjKRNuKmm1G}oe5$~j;bvm<{7uJQ3%6Bw|nfB#hhoq~cobsjK4-qdT6 zPyglp@!w}ruT^Al%T_~&wra_&DSxG`4b-z(SanJIxa^>@Et;XlH?+o zDaYmg+8!2_@kvDl247n9nHIMlj@;n{b~=0(mUxibo0Y!3yLRc% zw}8x{Va;0f@86<%pFYhzeEPR)(VNXM3uTdT7lVvDjR7v~1(cm!5n50d7o4;^S=4(1 z`TLjrv zjgz8w^^JF~U&XChsft6CoeASRESXxjf1^n~oa@+G9`lw+BZPCMt zV~XNSC>64^mHRSOM*1a^PVQ;g!(;+u1^E*7vs?mMq-UmqtxvgUmaTvRHk6mwC~Nov zRm6y;bwHY^}9`8XK_##JWq%H1TP^wS3KTg>@$?tVr9}aB%&>qh`UPz!0wNRAMy!QGQ?+ z6Hkf3s4P*gl%+;pIUyIV~?I{QXB zOV?z_p{9OWwm+=c@F>|dJbME3t>gi=!S4uFzM;f?3q6%^{v!w;+;?omwt)M|oraIZ z46{?-E3>k@@eYRkz}=rAO_7zx+1$p|gUOXVC~{q;ajm}1x7KcbdQhj0%Nh)Bziwb8 zP-vyRrwvfLk{nBG@c9|5*~kcI=&f9*_L^8urWZe|Ag?oZ&2E`p57wQ_vubC|E z@zHmaMkU>iW`Abfjk!B}lkJhf+JQje$3c0i{J~0g76}<6wzp3a4dH#g_S}i1{PGG zKyzLX$Mt_uPXVW|e-e$QQy%pY2uJrVLQH+G#AyWHdTNg_Ec2mUL7BNnT<^F`7)B%^ ze7BKpJIG&X)4%dtYLWlj3QK=A|85~1`G@T?=P&*5`b)6-Upy>ns{fb#Vh%p$epP}m z2?9>1Wj_ot7)t}GAK&E{*_y0U+80Cv1iuKMfgVlFA&(i&JgZ^&s?~hiSHLM-^X*Sd zr@X2mLTB<--wP86|J|+Zi!=Y?HbQ5uRxoapJog(m2||`uRty^tNIi|)m>7xtwM_Xz zO;8!$w6bGfXhgzF?dRv7Jht z{fvx2iAZaWk>ZR!$_D*OWy2nEhB0!F(CbHIp;sYshB#xFvO(yz%NWU^-pWR`BI~OE zv7$mPe^&H4HJ^$kHuL$+(Q#!2HU5 zAoSW}8W!1s6;WpCFIm*#at6z8YK9cox|v1>BWE5hWtKP{`o=;XWoMGauFT0aITO zt=(d5HgPHhjF3T={DgohGsx1P5L2mTKOv@4%S{kp)EvS~tzZxg0w9>M>-qZRYX=*M zrB+;T?32UpbogTIV`7j%21UT_SktR=RlE8pgjI_?YfKP3O(Y;Q0NL;pf_cm!$vF^? z3?L9l%pFG_R?j8|0m6=&%lbR=WXyhzJ61c!)$s($l4_hb6cFRj&_YtRGlrrXK@c^U zbz9{KNbL}&2bkRD2$IVQ^zgKyBBcB|*>OzOhdrGI_?cr_ zGV6<8^8+m+TD!(_i$0E}L=rMbTS!|-AIDRYvNaYC7QBo*4l52nLi7u=ff;avHvl9i zn-bw!#hN8qYH%VDerXFiyW3lcygB23v8~vSHL8otiqy_v8PW7+-ZU~svWPcxv<0<= zer%HG8uu|IuywM0KM`SMu|TYIGcsAhDndUF%kjp;n8ZKPVp**$V2rL`kP)I?$Z|6L zjEBV*VhhmC4UOOB9pLdN&^#A#G20=uiE#AirtP5ZkhRBjJgrM)D~kL-G(-;T)Hy7y zbEh!DQ&6`Bn#*Q*qPA}QXj!*uD}w0Nx{72Y4%uhNYBI*+$^384puNra&q!_sDA9}AWmb< z02EJu5uXEt!Aza(F&wZ36WT0Ww{Dp>j{VM>r|ns?QGkYKX+?^cfjv^Jz^x>!rc_|GdeGI*W`Sr}Al1^nR(#`VUPK%?z4W zppXSqY_YXbpitJ?tOMFMk|rxn>!x+nz&<=DgUP*@yG3Dr8RdYoL+GNdkG}_mHpW59 z4*uOuh07lqROphG#-KtQ6)LpBcMiw&{Iy!NESp;vuNZ3@9mEG_46<<9W2|bdioyT2 zh`PJ8xJl(0;)NY8Wc(NY;_Y=&5LSz((PNUUxqZ?AQQwY9HF*2Lhcu(dkOMhY{M2-~ zc;eX7qr{!%$Vy|qPfhqDR}OQA8RFJ}ExN0w z5pxNhOB01RYL(2^1+aP%*@YgnkYSg4Oj`TpJBw(eeH?o^I{I?#m`l;om&P;?bti72 z&6|h15%*Asi)7m@vSSuKEBMkjv|Y;5&+ggvL3gQPXX=A?_%RI^2i2 ziP3Nevx;W$0(cl@T*GSXLfbGfsm#D++r^9I4F}`s^0TLEJmH`H&DGEURllD7zvzk7 z<$r~|0B2N>EyMNIVSvGSBXJU}VNNF%FV27Cp_`7tw=wi$PH*Fx z6=U?>ff}}mFVYR^rZU~&CSHqvO9{RL4rCQ?dz&l;gNWdGQ*63lxD0W++&`@Sfxrm(w|Hh z+!<2JQR6ycw32Z4wJ=g}7cMAuH8N?DecfV(-Wlt^ErOp7K$z>1Y%}JMSL$);*z}Pb zg4^dPf|#z0iReF#x9Wl^01E98)I(;W+QtQ%BBp-irU~{?+%qkk3NXEZg{TjS#Ey|s zB+(Z~jk*~9;DP!#=E7(aFzP}~%=uBH&d1!pul|MaWV(Fxg_tG*jUO})Y}6@TZuMf8Q3 z=nJEf2aR7Co!$_&HVQdWuE@5weV+v=wtk0!PCd2`1MX0rt%B zK>{6_>d@4I%-$n6f1}~Y2~mf6YO&&OS$>klo)L;zF*Fzf(DRZc^43cF z_w|t@t`j@fts5gu4b#s;gxc+!AY7@HRAD4S%o$_`4eVB^l#!_PK$!#ffM*T`eK93e z8(3Iw_;KdICIyDd)e2j+^vWoUS-MdfU*tlWUld8VZi`XBWs8`xg_)3KfSDoWvWEKZ z5I^oP@ZZ1|6Q*DUuU8NAdRDKMy#+K!+<7Tu#r8y_8zp8LWy2Cy6{}Lr$owuNoS`CR zerA>}Mh)4)Dm516zwqLeNpM`@Y{@)~s1C)Tfrr8w!7CZcs$=t?g&j zZxu86FL;Spam`Zev~tl2;-*4R(5qz%BFebPX!`Hy;j zt>u>*{#_d7N}$~Roc1wui54xx(T9~TScv%1gl6ap6KgiIajZRaYgmK#ptVr3Hn+wE zmS0*E1ApS0wN37pxsA1llJ|cpiBl{q^^f+%K-ONCGb^I)W@@rT_G5iVyTb`jUSeaouJK8|XN{j3I^ z=0dKi9?_3=-0(|9O@#>3?d@CTA+P2A+qWP=d1Gvm$^|CjcICU6#V;NLjcJ9`3%CLD zgF!Tc(a9KFz`4LA+-Bphg}IDYeMYNJqctqZ5*7)9LTOB&9qh|X<~$PI(j8Nd(sFd= z@#DmgJP~jPAkFam3GqX)#FexhQjcMVenb42I?2iOB4U*kKw!Q%)DoXAZQO{v_O;}@ zG4?+c&uJpdl$+S1M%ZGQYV41?-oWXAS|hp?VobAqQ^1WMDVS*ej{~UVzfQW!@#Gyl zk_%jAzrWfPv?%M~Q1;7@GLDYMv>b5FaOYVDVnaSDO~sIWQikIpao)AX!Cr^F}J4cZyak;hAS%SZifzT|Ox~ z$vvMG3kiaMp0!zu^Yck5AXUvLrH}-%DbLypOZ)OkDI!(NC#7h9>ql#qFAc0E_D~=X zT5E0c#k!byEuS*B5}v2#S(}{{lut@!+zjVkraGKy=bh4As+dno4=uLZJTaIlUe70G zR=%S!H@}&vou6;Yf_zgJ=9{u8zZ7}1kPqGDEka=4{lQzYsrjVr72NVkIU@X}>75td zAt?w`9% ztORuo#x!?|nfvEXF?0XiDQ51UJH^cXbElZOf9@1B_s^YT=Ki@;%-la$N)GqWonq$x zxl_#CKX-~nest4XipTP%sMgH=bJtc#vd*VWVQFJNDQ51UyEZfT&z)lC{<%}k+&_1U zjcG5*onq$xxl_#CKX;0m`{zzEbN}2aX6~Om#mxP4rlym&(t&6J5X=o9(aD~#GLkNbmR>jCE~Rhi;S!5%3hOc`sDr&eEtAF z!*q{TeEjTl+zv9laPZ_8tadK)FhxqIM>lOE?&)N!(NoGo1l;cD_I62*UqMPBZj03- zK_FI{)rDOrrs9P!Dne)YQe<5EZjW*39>>9m3mkohe+8xwvRyvu=K~zMopJJNhkR9KQnk6Aqz|CQ8oG(i+@f(M@( z$cSeuO6Ovh36JUh zO?&D2R}=P-#z2KPZ8=nS(nWFB6-cabdd7{Ra$3i(ZyoV;0I?ewZA`EFTytVqn&RCv z+nsu@$UW&1y}vP)UVJbj_!MHsE6ubw4X1?o?fdEL6|t{ZPkugIKWPc2DFY|GBK7ue zB94y}EQ<*{AJfl8m836=>8IVR>9(+BnrzjgUd-H(8 z1+qk3nHvUt&>}!N)1Epx5!Y`dcKI?VD5BxGS~qUP7T;xEFbDkt?%u>kBqIJN|=)QOG3tLumeS?XXxEu^*L5C7r*+SZYo z1M@ZFi1nwna+GgX-bDX=mP${*980=Jeb_fti?zDCb(tJb)butV5rye$YP$~3CncPFLmhmr7f zG9Y6@;MD8iKI-?(#5*7mE)|bUeSmaj+?ybnH{z(lsRXxCfNw|ccU;zqO+}aTlC>3I z22x@AipHmDPZ*{V|0ikd(?^b?-|z3s>f~V;xbS2YsX>vS!h3W~;JRYFG!N-ty-wKzx$;ANHot7(mn zh1M3C?YcWC1cqq}hzc}WOm&reiuOiDNEIrl6E~=h($W>&FOqYU4*1+Ut=we{6n?)? zn^`DcJE%+)yjKnOVX!L0hafjydKZcR0K zdS84hjfcw2a|dp~cwg{fT4yhsx`HPaOqGo2AoEB!x>ZPfNm_0UyPV{&BoT69{5J2d zTc*&tbgOnMZiW1W*Sa>O1bsDq8vSx=Zu;`7zmtN!7W)P-^~!8aZM9KZ%dF7g)9iGM zrrgzJ2{?M;WVE+&1xI6c5j-Y6w*jo@m)Vq0^0JKT!XD`=J$QHovH4pYn>8tEMYGYDdH{*E?L{y%D8?IbaeY>B9XC%XxFGilcygJ zFVXewJcSIuK*%Y&fLf_x0e;jXg=#;B+Pvqc4%2SW>oEApSi#<-OB%u+zi4Bi&FK6e zXnHG}4nxzbb8vgSV!_rV>8zMxB&HStGIAI_&Wx*-O?32gIy*B;@7C z+9T7#hYwp#H1n^~KQ7h2OgCIzKr|~OB8DE7u1=-zFW;umW+su+H?NXnQ-7qU9NN9- z@cvX{;~X_OJft*kO@`c0KJqj$@ad7{`$ObxP3e&Ekf<6U&j|3mrRYf+J~A9n)1V;! zsVPQ1WBL^7s zxKHI!GAN_E9GW>#cM}W)FWL04KV~c&oIwW$Jphb@J)}$5p4UB4@B8fd#*O_GUVt#Q z5c=HJ2H|I!qe;$-*^VW;3|*ClNc8uwZ=hSe1McD)z51#TD?0fs?-w$^bDt$ri>w-# z=%elD=>3)B|01OpcYa0^NWCjn==XAo*Xh&!$*Uejc&;5j^~4w`;>UuSE;eC1i7xYGkA{GR>>%u@O0{w^u(FZ$4`BlKuXv0YaKeYmVcX&p`gY2 z?B{X=m&gu(t)bu3?$W&n4-k**H%RHFMd)>#gDc_6 zA?$eEzy-d=={!-dT(23?J(*NH`S>`g{KvQ#OUI87*&FdBa{u58zgu1Xgh9QM{an{a z?u6aA9vZI*Igt6mvgJ4D@HqcJL#ENYBZn$>u2{_3#wS#CT1$T%yG!>SI!HXO-6W-# z6a`|3R*pClHsr*(K?{6})A{1tZP%X`w74T``wpjJ{|!k|13N}>1>EPTS9vO5#GGdH zT3n%&6N=DO!A>csy~^AOXVuhR&51Y?k4ugjrjnWgu*9=L8EJ;`aX$)Q2-(s#mK!5* z4vXm`^g8Uu8*H6jmNDxT?M3=T@wBG*5FPQL4SRSezBLw;HAYcXa9MX9{94AinXecj zN|@VVxWU@6E`0p*8I7UDR&9%^#pjWEECDGjSjfhO{b-7KS1Bq6V;#M}N6&27KwR%M ziySr8D{|8U@3HGTbzV2#bKa&%@2Mk)zL$tbJXS>koO{B7cOR$ow`U9ix! zXOqe&JWVWEFdN@7&Y9S^%X31&#NXW>lO21S%F*z=Lw&J{K8vN{=WZw6YOF3K943X5 zrcnf5YC#T9j+rzYBFtgm=I8htx)^0m>Q6T5bsW?-x+kIESVO|_zWwIyjN-AZz69#OI$%~8 zDjE@XA+CC$vi$(6zFX&jvR#a&X@aj9&RrfRGTYmiN?Tz+I8i);g3m_CFqx~VPPmSz@DwWi;~!Cs}LFFGzH%m{kwA$J}U|8LwfP*jmXUi8S-*&es#{ z>?ZuZJB7$oXiD>iak2Bem$2@!IA-kPmP&j2H)-^{rH!t9wH~$SZxTzCeo2>HJV-h| zY4wn_*?Wi{`cQhzjq!0;M|U3ocuLWC!W}Z$%$|SE_=z6TqpM?NE8XU-6d9 z3dPHc%v_R%#|3Ld)K|_~$7pJ<7^WAuN z^ngvX$2VQI-B915>aZn2^NtR#+IaD)>W!<19+?}ocvw}3`iAYRnoO9zX~5{a8-1Do zwFyeHHVKI18o-?$e(X)mq>`1oJ=x`OHXH-&#H!sBduT~bX#;(~?j^l8kB|k#`T0Ja z%p^qUUNvLZ;)V?t(@o8Xx0~^L`UTSCq7ZhT^td$3uzK{)c~2viIZ;pMGIA+K?L)L` zubyq|+B*w)y=Gp6kQ>-A;}u)QvT$K-9$>c7z?Bc%M70&*=F-!uS7^=IkH)PgweS5& zT-Gvy)XJ(z{n#^2EF2O0Rm|NH34S3EGUr?zaS3vPXB|36)$;`&^D#Ws5hq zrX4^LzMQja{9$Tx-AP|X2Qi4 zi>sK1ydb2+mzqAm7yPY-Q^a`XTMeJ8`cfW_QDYI(m%fsHGKjX21(oG7qcT@3$^7HE z5im1d{exzqu@RU9Gtrm>Ut!GoGTY-#yA07`WK7}~CURq`78cmA{@QKD>@H__O*){9bwCd5RQP-Z#$riEr;@rPRL7+2iCWPPmqi;?0-7sXwiN2mR_4w0} z=#KT9wDD?TJ8JPvA9|FdTF{cC3Z}ANIi=mB59U;0qPC;yC~C_v6zUQ+78y5_W*BQ# zUZ!e8#IB^JZy(#br5yaL-g>Bb672p{pHG?cd@3XXlIb~WlxGu20NTg%GdoNUlVw`4 z0MY)C_e_13knn8klxK+v=^a9cgbbcM1YHnC^_s4+)nXXf#N=LO zaYz=c&?9kCjxB%FSNHk-D=AKokmlnfoLZJH;OtZL3wDYS#)5@t){p+iVxz{O zeTzawn*k0uDf_MVvs?~dyT?KXgDF2)%X>Zx8?ZHMS{z&w#yME4Zc;3CIv2fxQd5D{ zb>v4*6&=i6;rv6=Y|DOn<=|iR#T2QfQE4(Gs>g(0HGKEQjZba9yVlaj!fi6WSk*2a z$~zXRTFtM{=xJ?jwQmp8l#31D(&W^mq~k5mCmD+!dafGSHa<0?VcfNtAg{HpCv;Ps zGCGetI6x3i+m;U67=#Y2SJLIqGBjq=bAImU-}O+;u6aD9Ys0&VQ#$`@3t$Bhf93+73VT0cg+KDsd$V*Y^4uGxw)N4GY6id4^tvf_JV0FK7yTj|gIB=bOG%l4j_ms&+ZB|pmrihovN7Ns(c5w2g z_CxB@jeCe^v#7R>8g{PQZTzfe8*aQ28WzR+-;Iv+2ZG>@159j@t@dBlM(Xi`u_RZy zzvT&f?9@%VFLfy?by&GCWg3@~cl$Tq@E?*gB5ZfKh21t|;!y1`eWipj@(J4>D}g?i8?t(d-aGi z?F0$SO6)P<_aVM9Pv=Bjm~`;EYsot88npNRG9-1>fH^^}OI9Atwq<24bY~bHVG^H| z6R_PgmQflz9y^~wabTW*_Vv_IAMkXVbFT4NGksaphD&G1ZnvOUbO?jC?j@-)pOE?V z#)~zi72PdlB|VCsH}cWUSwm;Mo_2w5J3kM zA+`Qn%Vg85SES2-YF*H*#zrt)*8tm#Uu<5kw72d(4XF|xN3&ZC; zkMS8=qh@z$_`7$YIO}nezAx07TiL3yIH*~ml)(&vqyfsinJCX5-AdLfsWCGunPaH2 z!C+Ff@UoYenbg-`?xCNT=twP#6*FcnZPai{8JeQ)K!l5Q%Y}J3MDksF$ATxr=3$c- zzABaii&1I9!+e6}fpwVh_3vX(S%Ez!6RV=Vyyb#&9i}xS&4mmK&mvtfEVw|rUq~{n zjoCi`QRD)z%}HL0UdU2pw745rhgMR%-7+>~`^T%NOez5#(t zT_w#M_%|t5)5gAM^?n=T+Tc)grgPs)TIrt7vi9J0%rl5-C&xH4Q$CDiHZ`)40nmoZ zwYjXXMl1pGAnxO(Av2v2Dr0D>DV6Cm=M3_!gktz0?9^Umat1 zchT`E%-*^4iSvt5rxw(rsg8b4p^@pdT=JtwFmDrH+LtCTl`GKOUBdjW&1BnFksiup z3v$Wcan9qBwdda-CB6RfRi3b#3^@Xn_CdkE9VnI2u-)6LyaXM;i6Zbc%(aH96H5nz zM5bY32y1Lu5DYHrGNrM!i)PU)6KY5Lc8qD0KKl8ZRrli?jm#ty;m5Q98J{_-QT+YY zU*It(eR-sBl*>eVN&A-4RfvHUetBY#)MXHCp3pOE$6U!AvzAnUH?R;me4;iX93Vj{(vZ*${F`g0Xk5ON83$SN0B`GlA5Sdn9z9y|iKZ zPSZnYtY92|2`RkiC2{5){@TlR2zg0fw~J~q8wB#+GShqK=+%ZSqKV3sVp9moy zuE7YHRO{srBdG6>f?SIUR)pVX?=r2XOL!}i9v zZ8LdaRzJ(wZ<8=;H>5y7ChvmSPN2JQ0ed7=+LLzqq!Kr#x1dj^S}se_rm4#%UW7&No8 z3Qh)rKD-R5(lTeGz+Tux54Vd;?pM7>Me7>HU|E5f(0hPxpXL?ai&YxZCUi@n_WoZH z>w;?+u)L$yIrZ)Q>fJkU!<1p2EJZ^>n_j0@V$2q2ztWxnL#@CybdI2ry$G?a9=AyW zr@=CFeip}0D3(eyb81QOOgu;&k~h$Y2PY@{m6|Tj z>9c=I!Y;3#JL41g^)sZ9>cM{Wf!+;{i}Xp#TjycjQ|XG#Ot`}A5#cOUUGiz#luyf6 ze4C#1UAxq{gL=~P^ghNW7~9WxNHGPui66#>jRLcH#|UWI0o=jWNxeKXo%tE3Dh@S< zEZKvYwd-+J*+9~=r^oQS!CMDvI}_)G_-y(oAv1`u^AIU8lVCDWNthhlYD!S*_h>@s zKKem9B{Z9oMC%yhbPclRhIOT1dY@0OS)-HNZ?&)N8+CEa*gKQFXO3*&sBKNV%28Wl z&O9ZBT1av4-T`AQLwO!1|NrD30HbQs0avQaE>eHq0$`Px#B?zR*8siFo~6lumb-_m z?z5y)kCaZw(@$4!(exQJ z$Zt2U607(RM-Cl4nwGL3HZl!n#wE_H_C=bUwf9;^XlTZ@Jz4S6mumA8<7PI%RG0_t zBjal}*p#XwTybYC3iC`*l~_3F z!{M1XW_uMa>N)GijAKNOr-$7Z#*bXoqo{TF#iPe9YHqARJm@`Rf!Ub+?Am?f=+Z>9gFn@$BECq@2fw~iD(9&(IsGM1i%0A^c* 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