From 9d3529e8a5546a565f3e8875d6f733d1a892ff6f Mon Sep 17 00:00:00 2001 From: X1nto Date: Sun, 31 Oct 2021 12:52:51 +0400 Subject: [PATCH] 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 | 139 ++++++------- .../com/vanced/manager/ui/MainActivity.kt | 63 ++++-- .../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, 1305 insertions(+), 1187 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 870ffb16..f16a92b4 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 e379b85c..14c99d62 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 9eece8b5..0eaec89f 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 27ae1e30..1e44b268 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 00000000..4628b30b --- /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 + +abstract class AppDownloader { + + data class DownloadFile( + val fileName: String, + val call: DownloadCall, + ) + + private lateinit var call: DownloadCall + + abstract suspend fun download( + appVersions: List, + onStatus: (DownloadStatus) -> Unit + ) + + abstract fun getSavedFilePath(): String + + suspend fun downloadFiles( + downloadFiles: Array, + 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 00000000..7d017e40 --- /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, + 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 00000000..20fdb1e8 --- /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, + 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 00000000..dacad593 --- /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, + 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 00000000..ee01c5d0 --- /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 3c1d2c9c..21ed7984 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 b756275c..fc3f4ad6 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 3b7d1d28..5da7a7db 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 699f3427..56cf82a5 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 f966ec98..ceb47e2f 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 c79028eb..162a72f1 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 bdf36b4f..491b4fbf 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 cb209aa5..9972b2d0 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 38ddf036..e537e2ee 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 c2488680..42dbbc64 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 00000000..bbb46a78 --- /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 { + 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 c3737f29..221bf3db 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 5724ba8a..4c2247f5 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 00000000..fdfa563a --- /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() \ 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 e2e06318..5476699f 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 bea81631..06cbd82a 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 326d183c..850f40cf 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 49b4b89b..04477c78 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 3f64a5e2..050c6c33 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 109c57f1..907e3cdf 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 c55cc79b..2c0560bd 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 e762624a..a93d7dc0 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? = null, - val themes: List? = null, - val languages: List? = null, - val downloader: AppDownloader? = null, - val installationOptions: List? = 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?, + val themes: List?, + val languages: List?, + val installationOptions: List? ) \ 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 00000000..c5bfd46d --- /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, + val getOption: () -> Set, + val addOption: (String) -> Unit, + val removeOption: (String) -> Unit + ) : InstallationOption(titleId) + + @Parcelize + data class SingleSelect( + @StringRes val titleId: Int, + val items: List, + 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 076a48c6..3e01ad1b 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 03b7433d..00000000 --- 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, - 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 - - 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, - 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 0dc5ef00..00000000 --- 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 9fbcb16c..00000000 --- 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 7e119808..00000000 --- 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 bf15a476..00000000 --- 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 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/network/model/AppDto.kt b/app/src/main/java/com/vanced/manager/network/model/AppDto.kt index bb6b00c1..ed504212 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? = null, @SerializedName("themes") val themes: List? = null, @SerializedName("langs") val languages: List? = 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 712b6ae6..bf3f1520 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, KoinComponent { - - private val packageInformationDataSource: PackageInformationDataSource by inject() - private val context: Context by inject() +class AppDtoMapper( + private val packageInformationDataSource: PackageInformationDataSource, + context: Context +) : EntityMapper { 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, 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, KoinComponent { AppStatus.Install } - private fun getInstallationOptions(app: AppDto): List? = - when (app.name) { + private fun getInstallationOptions( + appName: String, + appThemes: List?, + appVersions: List?, + appLanguages: List?, + ) = 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()) }, + getOption = { vancedThemePref.value.value }, + setOption = { + vancedThemePref.save(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.value.value }, + setOption = { + vancedVersionPref.save(it) + }, + items = appVersions?.map { version -> + InstallationOptionItem( + displayText = version, key = version ) - } ?: emptyList() + }?.plus(latestVersionRadioButton)?.reversed() ?: emptyList(), ), - RadiobuttonInstallationOption( - titleId = R.string.app_installation_options_version, - preference = vancedVersionPref, - buttons = app.versions?.map { - RadioButtonPreference( - title = it, - key = it - ) - }?.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() - MUSIC_NAME -> get() - MICROG_NAME -> get() - 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 cce3d45b..181b58de 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 navController = rememberAnimatedNavController() - val screens = listOf( - Screen.Home, - Screen.Settings, - Screen.About, - Screen.Logs - ) + val isDark = isDark() + + val navController = rememberAnimatedNavController() + val systemUiController = rememberSystemUiController() + + SideEffect { + systemUiController.setSystemBarsColor( + color = surfaceColor, + darkIcons = !isDark + ) + } + 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, isMenuExpanded: MutableState ) { 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 dee1b46f..27a808e3 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 4cc2a5e4..3acd2e9b 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 f2762ad1..081f83e6 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 bf9174ad..1dbd8b4b 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 4ef62a25..48e1f840 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 339ee39f..0c77f78c 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 aec175e2..be7f89c0 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 203e357d..c58dbd1d 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 abe2a156..b4533436 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 04013eee..bad3c9cd 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 a2d666c1..ceffad77 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 fe1277d8..ab25f2c4 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 ff0bbe9e..5684a59f 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 188676f1..25870bd2 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 8ac5454a..8ac94406 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 ab8eedd3..66640272 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 00000000..5fa3e27e --- /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 +) { + 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 00000000..5e7eb379 --- /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 +) { + val logs = rememberSaveable { mutableStateListOf() } + + var progress by rememberSaveable { mutableStateOf(0f) } + var installing by rememberSaveable { mutableStateOf(false) } + + val viewModel: MainViewModel = getViewModel() + + val downloader = when (appName) { + VANCED_NAME -> get() + MUSIC_NAME -> get() + MICROG_NAME -> get() + else -> throw IllegalArgumentException("$appName is not a valid app") + } + + val installer = when (appName) { + VANCED_NAME -> get() + MUSIC_NAME -> get() + MICROG_NAME -> get() + 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 ebaa7abc..5632b6bd 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 92371309..7ee69359 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 3005ccaf..226f435d 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 8ae73648..abd4c2d6 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 769139ac..573fe61b 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 569de474..992186fd 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 = _isFetching + data class Fetching(val placeholderAppsCount: Int) : AppState() - val apps = mutableListOf>() + data class Success(val apps: List) : AppState() + + data class Error(val error: String) : AppState() + + } + + private val _appState = MutableStateFlow(AppState.Fetching(3)) + val appState: StateFlow = _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() + + 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 00000000..3b77e17f --- /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 00000000..3a6e67d6 --- /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 00000000..c85789ff --- /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 b3ee9ab2..f314532c 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 dc3206d7..cb2c6037 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 5846aee9..afdc1563 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 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 b5c7980a..00000000 --- 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 015a09c8..00000000 --- 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 b3a775b6..00000000 --- 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(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 f765ed09..00000000 --- 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 aeaec0b0..00000000 --- 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 4b6a0b80..00000000 --- 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 dd7636cd..00000000 --- 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 bc7d703a..00000000 --- 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>, - val buttons: List -) : 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 1a3a6fa1..00000000 --- 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 58bd6166..00000000 --- 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, - val buttons: List -) : 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 3b96427c..00000000 --- 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 45332625..00000000 --- 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 570f5113..d93c2757 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 8cc6d31a..db01f791 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 bf5cc30d..a0121c15 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 86f11ae4..342ff63a 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 c77ec514..11038023 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 bd7abb3c..00000000 --- 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 38a4d1c2..fe927437 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -71,6 +71,8 @@ Manager Logs Settings + Install + Installation Preferences Update Manager diff --git a/build.gradle.kts b/build.gradle.kts index 54564af2..a057b512 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") } }