mirror of
https://github.com/YTVanced/VancedManager
synced 2024-11-25 20:55:12 +00:00
refactor
This commit is contained in:
parent
c6017fe248
commit
e6214a1734
172 changed files with 3123 additions and 2161 deletions
|
@ -1,3 +1,9 @@
|
|||
import Dependencies.accompanistVersion
|
||||
import Dependencies.composeVersion
|
||||
import Dependencies.koinVersion
|
||||
import Dependencies.orchestraVersion
|
||||
import Dependencies.retrofitVersion
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
kotlin("android")
|
||||
|
@ -47,13 +53,16 @@ android {
|
|||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion = composeVersion
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
useIR = true
|
||||
freeCompilerArgs = freeCompilerArgs + "-Xopt-in=kotlin.RequiresOptIn"
|
||||
freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,39 +90,36 @@ dependencies {
|
|||
implementation("com.google.android.material:material:1.3.0")
|
||||
implementation("androidx.browser:browser:1.3.0")
|
||||
|
||||
val composeVersion = "1.0.0-beta07"
|
||||
implementation("androidx.compose.ui:ui:$composeVersion")
|
||||
implementation("androidx.compose.material:material:$composeVersion")
|
||||
implementation("androidx.compose.ui:ui-tooling:$composeVersion")
|
||||
implementation("androidx.compose.ui:ui-util:$composeVersion")
|
||||
implementation("androidx.compose.compiler:compiler:$composeVersion")
|
||||
implementation("androidx.compose.foundation:foundation:$composeVersion")
|
||||
implementation("androidx.compose.material:material:$composeVersion")
|
||||
implementation("androidx.compose.material:material-icons-core:$composeVersion")
|
||||
implementation("androidx.compose.material:material-icons-extended:$composeVersion")
|
||||
implementation("androidx.compose.material:material:$composeVersion")
|
||||
implementation("androidx.compose.material:material:$composeVersion")
|
||||
implementation("androidx.compose.runtime:runtime-livedata:$composeVersion")
|
||||
implementation("androidx.compose.ui:ui-tooling:$composeVersion")
|
||||
implementation("androidx.compose.ui:ui-util:$composeVersion")
|
||||
implementation("androidx.compose.ui:ui:$composeVersion")
|
||||
|
||||
implementation("androidx.activity:activity-compose:1.3.0-alpha08")
|
||||
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.3.1")
|
||||
implementation("androidx.navigation:navigation-compose:2.4.0-alpha01")
|
||||
implementation("androidx.preference:preference-ktx:1.1.1")
|
||||
implementation("androidx.activity:activity-compose:1.3.0-beta02")
|
||||
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.4.0-alpha02")
|
||||
implementation("androidx.navigation:navigation-compose:2.4.0-alpha03")
|
||||
|
||||
val accompanistVersion = "0.10.0"
|
||||
implementation("com.google.accompanist:accompanist-glide:$accompanistVersion")
|
||||
implementation("com.google.accompanist:accompanist-swiperefresh:$accompanistVersion")
|
||||
implementation("com.google.accompanist:accompanist-systemuicontroller:$accompanistVersion")
|
||||
implementation("com.google.accompanist:accompanist-placeholder-material:$accompanistVersion")
|
||||
|
||||
implementation("com.github.madrapps:pikolo:2.0.1")
|
||||
implementation("com.github.skydoves:orchestra-colorpicker:$orchestraVersion")
|
||||
|
||||
implementation("androidx.datastore:datastore-preferences:1.0.0-beta02")
|
||||
|
||||
val koinVersion = "3.0.1"
|
||||
implementation("io.insert-koin:koin-android:$koinVersion")
|
||||
implementation("io.insert-koin:koin-androidx-compose:$koinVersion")
|
||||
|
||||
val retrofitVersion = "2.9.0"
|
||||
implementation("com.squareup.retrofit2:retrofit:$retrofitVersion")
|
||||
implementation("com.squareup.retrofit2:converter-gson:$retrofitVersion")
|
||||
|
||||
implementation("dev.burnoo:compose-remember-preference:0.3.0")
|
||||
|
||||
implementation("com.github.x1nto:apkhelper:1.1.0")
|
||||
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:name=".ui.MainActivity"
|
||||
android:theme="@style/Theme.MaterialComponents.NoActionBar"
|
||||
android:label="@string/app_name"/>
|
||||
|
||||
|
|
|
@ -14,13 +14,15 @@ class ManagerApplication : Application() {
|
|||
androidContext(this@ManagerApplication)
|
||||
|
||||
modules(
|
||||
apiModule,
|
||||
downloaderModule,
|
||||
mapperModule,
|
||||
viewModelModule,
|
||||
serviceModule,
|
||||
repositoryModule,
|
||||
packageManagerModule,
|
||||
networkModule,
|
||||
downloaderModule
|
||||
packageManagerModule,
|
||||
preferenceModule,
|
||||
repositoryModule,
|
||||
serviceModule,
|
||||
viewModelModule,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.vanced.manager
|
|||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.activity.ComponentActivity
|
||||
import com.vanced.manager.ui.MainActivity
|
||||
|
||||
class SplashScreenActivity : ComponentActivity() {
|
||||
|
||||
|
|
21
app/src/main/java/com/vanced/manager/di/APIModule.kt
Normal file
21
app/src/main/java/com/vanced/manager/di/APIModule.kt
Normal file
|
@ -0,0 +1,21 @@
|
|||
package com.vanced.manager.di
|
||||
|
||||
import com.vanced.manager.downloader.api.VancedAPI
|
||||
import com.vanced.manager.network.util.BASE
|
||||
import okhttp3.OkHttpClient
|
||||
import org.koin.dsl.module
|
||||
import retrofit2.Retrofit
|
||||
|
||||
val apiModule = module {
|
||||
|
||||
fun provideVancedAPI(
|
||||
okHttpClient: OkHttpClient
|
||||
): VancedAPI = Retrofit.Builder()
|
||||
.baseUrl(BASE)
|
||||
.client(okHttpClient)
|
||||
.build()
|
||||
.create(VancedAPI::class.java)
|
||||
|
||||
single { provideVancedAPI(get()) }
|
||||
|
||||
}
|
|
@ -1,29 +1,17 @@
|
|||
package com.vanced.manager.di
|
||||
|
||||
import com.vanced.manager.downloader.impl.VancedDownloader
|
||||
import com.vanced.manager.downloader.api.VancedAPI
|
||||
import com.vanced.manager.network.util.BASE
|
||||
import okhttp3.OkHttpClient
|
||||
import com.vanced.manager.downloader.impl.VancedDownloader
|
||||
import org.koin.dsl.module
|
||||
import retrofit2.Retrofit
|
||||
|
||||
val downloaderModule = module {
|
||||
|
||||
fun provideVancedAPI(
|
||||
okHttpClient: OkHttpClient
|
||||
): VancedAPI = Retrofit.Builder()
|
||||
.baseUrl(BASE)
|
||||
.client(okHttpClient)
|
||||
.build()
|
||||
.create(VancedAPI::class.java)
|
||||
|
||||
fun provideVancedDownloader(
|
||||
vancedAPI: VancedAPI
|
||||
): VancedDownloader = VancedDownloader(
|
||||
vancedAPI = vancedAPI
|
||||
)
|
||||
vancedAPI: VancedAPI,
|
||||
): VancedDownloader = VancedDownloader(vancedAPI)
|
||||
|
||||
single { provideVancedAPI(get()) }
|
||||
single { provideVancedDownloader(get()) }
|
||||
single {
|
||||
provideVancedDownloader(get())
|
||||
}
|
||||
|
||||
}
|
15
app/src/main/java/com/vanced/manager/di/InstallerModuke.kt
Normal file
15
app/src/main/java/com/vanced/manager/di/InstallerModuke.kt
Normal file
|
@ -0,0 +1,15 @@
|
|||
package com.vanced.manager.di
|
||||
|
||||
import android.content.Context
|
||||
import com.vanced.manager.installer.AppInstaller
|
||||
import com.vanced.manager.ui.viewmodel.HomeViewModel
|
||||
import org.koin.dsl.module
|
||||
|
||||
val installerModule = module {
|
||||
fun provideAppInstaller(
|
||||
context: Context,
|
||||
homeViewModel: HomeViewModel
|
||||
) = AppInstaller(context, homeViewModel)
|
||||
|
||||
single { provideAppInstaller(get(), get()) }
|
||||
}
|
15
app/src/main/java/com/vanced/manager/di/PreferenceModule.kt
Normal file
15
app/src/main/java/com/vanced/manager/di/PreferenceModule.kt
Normal file
|
@ -0,0 +1,15 @@
|
|||
package com.vanced.manager.di
|
||||
|
||||
import android.content.Context
|
||||
import androidx.datastore.preferences.preferencesDataStore
|
||||
import org.koin.dsl.module
|
||||
|
||||
val Context.dataStore by preferencesDataStore("manager_settings")
|
||||
|
||||
val preferenceModule = module {
|
||||
fun provideDatastore(
|
||||
context: Context
|
||||
) = context.dataStore
|
||||
|
||||
single { provideDatastore(get()) }
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package com.vanced.manager.domain.model
|
||||
|
||||
import com.vanced.manager.downloader.base.BaseDownloader
|
||||
import com.vanced.manager.ui.widgets.home.installation.InstallationOption
|
||||
|
||||
data class App(
|
||||
val name: String? = null,
|
||||
|
@ -17,7 +18,9 @@ data class App(
|
|||
val packageNameRoot: String? = null,
|
||||
val changelog: String? = null,
|
||||
val url: String? = null,
|
||||
val versions: List<String>? = null,
|
||||
val themes: List<String>? = null,
|
||||
val languages: List<String>? = null,
|
||||
val downloader: BaseDownloader? = null
|
||||
val downloader: BaseDownloader? = null,
|
||||
val installationOptions: List<InstallationOption>? = null
|
||||
)
|
|
@ -4,6 +4,4 @@ interface EntityMapper <T, Model> {
|
|||
|
||||
suspend fun mapToModel(entity: T): Model
|
||||
|
||||
suspend fun mapFromModel(model: Model): T
|
||||
|
||||
}
|
|
@ -8,7 +8,7 @@ import retrofit2.http.Streaming
|
|||
|
||||
interface VancedAPI {
|
||||
|
||||
@GET("apks/v{version}/{variant}/{type}/{apkName}.apk")
|
||||
@GET("apks/{version}/{variant}/{type}/{apkName}.apk")
|
||||
@Streaming
|
||||
fun getApk(
|
||||
@Path("version") version: String,
|
||||
|
|
|
@ -4,17 +4,19 @@ import android.content.Context
|
|||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import com.vanced.manager.ui.composables.InstallationOption
|
||||
import com.vanced.manager.installer.AppInstaller
|
||||
import com.vanced.manager.util.log
|
||||
import okhttp3.ResponseBody
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
import retrofit2.Call
|
||||
import retrofit2.awaitResponse
|
||||
import java.io.*
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
|
||||
abstract class BaseDownloader(
|
||||
private val appName: String
|
||||
val appName: String
|
||||
) : KoinComponent {
|
||||
|
||||
var downloadProgress by mutableStateOf(0f)
|
||||
|
@ -27,14 +29,13 @@ abstract class BaseDownloader(
|
|||
|
||||
private lateinit var call: Call<ResponseBody>
|
||||
|
||||
private val context: Context by inject()
|
||||
private val tag = this::class.simpleName!!
|
||||
|
||||
val context: Context by inject()
|
||||
val appInstaller: AppInstaller by inject()
|
||||
|
||||
abstract suspend fun download()
|
||||
|
||||
abstract val installationOptions: List<InstallationOption>
|
||||
|
||||
private val tag = this::class.simpleName!!
|
||||
|
||||
suspend fun downloadFile(
|
||||
call: Call<ResponseBody>,
|
||||
folderStructure: String,
|
||||
|
@ -61,7 +62,6 @@ abstract class BaseDownloader(
|
|||
val error = response.errorBody()?.toString()
|
||||
if (error != null) {
|
||||
error(error)
|
||||
log(tag, error)
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.vanced.manager.downloader.impl
|
||||
|
||||
import com.vanced.manager.downloader.base.BaseDownloader
|
||||
import com.vanced.manager.ui.composables.InstallationOption
|
||||
|
||||
object MicrogDownloader : BaseDownloader("") {
|
||||
|
||||
|
@ -9,7 +8,4 @@ object MicrogDownloader : BaseDownloader("") {
|
|||
|
||||
}
|
||||
|
||||
override val installationOptions: List<InstallationOption>
|
||||
get() = TODO("Not yet implemented")
|
||||
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
package com.vanced.manager.downloader.impl
|
||||
|
||||
import com.vanced.manager.downloader.base.BaseDownloader
|
||||
import com.vanced.manager.ui.composables.InstallationOption
|
||||
|
||||
object MusicDownloader : BaseDownloader("") {
|
||||
|
||||
|
@ -9,7 +8,4 @@ object MusicDownloader : BaseDownloader("") {
|
|||
|
||||
}
|
||||
|
||||
override val installationOptions: List<InstallationOption>
|
||||
get() = TODO("Not yet implemented")
|
||||
|
||||
}
|
|
@ -2,110 +2,71 @@ package com.vanced.manager.downloader.impl
|
|||
|
||||
import com.vanced.manager.downloader.api.VancedAPI
|
||||
import com.vanced.manager.downloader.base.BaseDownloader
|
||||
import com.vanced.manager.ui.composables.InstallationOption
|
||||
import com.vanced.manager.ui.composables.InstallationOptionKey
|
||||
|
||||
class VancedDownloader(
|
||||
private val vancedAPI: VancedAPI
|
||||
private val vancedAPI: VancedAPI,
|
||||
) : BaseDownloader(
|
||||
appName = "vanced"
|
||||
) {
|
||||
|
||||
private val themeInstallationOption = InstallationOption(
|
||||
title = "Languages",
|
||||
descriptionKey = InstallationOptionKey(
|
||||
keyName = "vanced_languages",
|
||||
keyDefaultValue = "en"
|
||||
)
|
||||
) { show, preference ->
|
||||
// DialogRadioButtonPreference(
|
||||
// preferenceTitle = "Language",
|
||||
// preferenceKey = ,
|
||||
// defaultValue = ,
|
||||
// buttons =
|
||||
// )
|
||||
}
|
||||
private lateinit var version: String
|
||||
private lateinit var variant: String
|
||||
|
||||
private val versionInstallationOption = InstallationOption(
|
||||
title = "Languages",
|
||||
descriptionKey = InstallationOptionKey(
|
||||
keyName = "vanced_languages",
|
||||
keyDefaultValue = "en"
|
||||
)
|
||||
) { show, preference ->
|
||||
// DialogRadioButtonPreference(
|
||||
// preferenceTitle = "Language",
|
||||
// preferenceKey = ,
|
||||
// defaultValue = ,
|
||||
// buttons =
|
||||
// )
|
||||
}
|
||||
|
||||
private val languageInstallationOption = InstallationOption(
|
||||
title = "Languages",
|
||||
descriptionKey = InstallationOptionKey(
|
||||
keyName = "vanced_languages",
|
||||
keyDefaultValue = "en"
|
||||
)
|
||||
) { show, preference ->
|
||||
// DialogRadioButtonPreference(
|
||||
// preferenceTitle = "Language",
|
||||
// preferenceKey = ,
|
||||
// defaultValue = ,
|
||||
// buttons =
|
||||
// )
|
||||
}
|
||||
|
||||
override val installationOptions: List<InstallationOption> get() = listOf(
|
||||
languageInstallationOption
|
||||
)
|
||||
private lateinit var folderStructure: String
|
||||
|
||||
override suspend fun download() {
|
||||
version = "v16.16.38"
|
||||
variant = "nonroot"
|
||||
folderStructure = "$appName/$version/$variant"
|
||||
downloadTheme()
|
||||
}
|
||||
|
||||
private suspend fun downloadTheme() {
|
||||
downloadFile(
|
||||
vancedAPI.getApk(
|
||||
version = "16.16.38",
|
||||
variant = "nonroot",
|
||||
type = "Theme",
|
||||
apkName = "black.apk"
|
||||
),
|
||||
folderStructure = "vanced/nonroot/v16.16.38",
|
||||
fileName = "black.apk"
|
||||
downloadVancedApk(
|
||||
type = "Theme",
|
||||
apkName = "black.apk"
|
||||
) {
|
||||
downloadArch()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun downloadArch() {
|
||||
downloadFile(
|
||||
vancedAPI.getApk(
|
||||
version = "16.16.38",
|
||||
variant = "nonroot",
|
||||
type = "Arch",
|
||||
apkName = "split_config.x86.apk"
|
||||
),
|
||||
folderStructure = "vanced/nonroot/arch",
|
||||
fileName = "black.apk"
|
||||
downloadVancedApk(
|
||||
type = "Arch",
|
||||
apkName = "split_config.x86.apk"
|
||||
) {
|
||||
downloadLanguage()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun downloadLanguage() {
|
||||
downloadVancedApk(
|
||||
type = "Language",
|
||||
apkName = "split_config.en.apk"
|
||||
) {
|
||||
appInstaller.installVanced(version)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun downloadVancedApk(
|
||||
type: String,
|
||||
apkName: String,
|
||||
onDownload: suspend () -> Unit,
|
||||
) {
|
||||
downloadFile(
|
||||
vancedAPI.getApk(
|
||||
version = "16.16.38",
|
||||
variant = "nonroot",
|
||||
type = "Arch",
|
||||
apkName = "split_config.x86.apk"
|
||||
version = version,
|
||||
variant = variant,
|
||||
type = type,
|
||||
apkName = apkName
|
||||
),
|
||||
folderStructure = "vanced/nonroot/lang",
|
||||
fileName = "black.apk"
|
||||
folderStructure = folderStructure,
|
||||
fileName = apkName,
|
||||
onError = {
|
||||
|
||||
}
|
||||
) {
|
||||
downloadLanguage()
|
||||
onDownload()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
package com.vanced.manager.installer
|
||||
|
||||
import android.content.Context
|
||||
import com.vanced.manager.ui.viewmodel.HomeViewModel
|
||||
import com.xinto.apkhelper.installSplitApks
|
||||
import com.xinto.apkhelper.statusCallback
|
||||
import com.xinto.apkhelper.statusCallbackBuilder
|
||||
import com.vanced.manager.ui.viewmodel.HomeViewModel
|
||||
|
||||
class AppInstaller(
|
||||
private val context: Context,
|
||||
private val viewModel: HomeViewModel
|
||||
) {
|
||||
|
||||
fun installVanced() {
|
||||
|
||||
fun installVanced(version: String) {
|
||||
installSplitApks(context.getExternalFilesDir("vanced/$version")!!.path, context)
|
||||
}
|
||||
|
||||
fun installMusic() {
|
||||
|
|
|
@ -11,6 +11,7 @@ data class AppDto(
|
|||
@SerializedName("package_name_root") val packageNameRoot: String? = null,
|
||||
@SerializedName("icon_url") val iconUrl: String? = null,
|
||||
@SerializedName("url") val url: String? = null,
|
||||
@SerializedName("versions") val versions: List<String>? = null,
|
||||
@SerializedName("themes") val themes: List<String>? = null,
|
||||
@SerializedName("languages") val languages: List<String>? = null
|
||||
)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.vanced.manager.network.model
|
||||
|
||||
import com.vanced.manager.R
|
||||
import com.vanced.manager.domain.datasource.PackageInformationDataSource
|
||||
import com.vanced.manager.domain.model.App
|
||||
import com.vanced.manager.domain.model.AppStatus
|
||||
|
@ -11,6 +12,14 @@ import com.vanced.manager.downloader.impl.VancedDownloader
|
|||
import com.vanced.manager.network.util.MICROG_NAME
|
||||
import com.vanced.manager.network.util.MUSIC_NAME
|
||||
import com.vanced.manager.network.util.VANCED_NAME
|
||||
import com.vanced.manager.ui.preferences.*
|
||||
import com.vanced.manager.ui.preferences.holder.musicVersionPref
|
||||
import com.vanced.manager.ui.preferences.holder.vancedLanguagesPref
|
||||
import com.vanced.manager.ui.preferences.holder.vancedThemePref
|
||||
import com.vanced.manager.ui.preferences.holder.vancedVersionPref
|
||||
import com.vanced.manager.ui.widgets.home.installation.CheckboxInstallationOption
|
||||
import com.vanced.manager.ui.widgets.home.installation.InstallationOption
|
||||
import com.vanced.manager.ui.widgets.home.installation.RadiobuttonInstallationOption
|
||||
|
||||
class AppDtoMapper(
|
||||
private val packageInformationDataSource: PackageInformationDataSource,
|
||||
|
@ -38,25 +47,11 @@ class AppDtoMapper(
|
|||
iconUrl = iconUrl,
|
||||
changelog = changelog,
|
||||
url = url,
|
||||
versions = versions,
|
||||
themes = themes,
|
||||
languages = languages,
|
||||
downloader = getDownloader(name)
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun mapFromModel(model: App): AppDto =
|
||||
with (model) {
|
||||
AppDto(
|
||||
name = name,
|
||||
version = remoteVersion,
|
||||
versionCode = remoteVersionCode,
|
||||
changelog = changelog,
|
||||
url = url,
|
||||
themes = themes,
|
||||
languages = languages,
|
||||
packageName = packageName,
|
||||
packageNameRoot = packageNameRoot,
|
||||
iconUrl = iconUrl
|
||||
downloader = getDownloader(name),
|
||||
installationOptions = getInstallationOptions(entity)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -78,4 +73,53 @@ class AppDtoMapper(
|
|||
MICROG_NAME -> MicrogDownloader
|
||||
else -> null
|
||||
}
|
||||
|
||||
private fun getInstallationOptions(app: AppDto): List<InstallationOption>? =
|
||||
when (app.name) {
|
||||
VANCED_NAME -> listOf(
|
||||
RadiobuttonInstallationOption(
|
||||
title = R.string.app_installation_options_theme,
|
||||
preference = vancedThemePref,
|
||||
buttons = app.versions?.map {
|
||||
RadioButtonPreference(
|
||||
title = it,
|
||||
key = it
|
||||
)
|
||||
} ?: emptyList()
|
||||
),
|
||||
RadiobuttonInstallationOption(
|
||||
title = R.string.app_installation_options_version,
|
||||
preference = vancedVersionPref,
|
||||
buttons = app.versions?.map {
|
||||
RadioButtonPreference(
|
||||
title = it,
|
||||
key = it
|
||||
)
|
||||
} ?: emptyList()
|
||||
),
|
||||
CheckboxInstallationOption(
|
||||
title = R.string.app_installation_options_language,
|
||||
preference = vancedLanguagesPref,
|
||||
buttons = app.versions?.map {
|
||||
CheckboxPreference(
|
||||
title = it,
|
||||
key = it
|
||||
)
|
||||
} ?: emptyList()
|
||||
),
|
||||
)
|
||||
MUSIC_NAME -> listOf(
|
||||
RadiobuttonInstallationOption(
|
||||
title = R.string.app_installation_options_version,
|
||||
preference = musicVersionPref,
|
||||
buttons = app.versions?.map {
|
||||
RadioButtonPreference(
|
||||
title = it,
|
||||
key = it
|
||||
)
|
||||
} ?: emptyList()
|
||||
),
|
||||
)
|
||||
else -> null
|
||||
}
|
||||
}
|
|
@ -18,15 +18,4 @@ class JsonDtoMapper(
|
|||
)
|
||||
}
|
||||
|
||||
override suspend fun mapFromModel(model: Json): JsonDto =
|
||||
with (model) {
|
||||
JsonDto(
|
||||
isMicrogBroken = isMicrogBroken,
|
||||
manager = appDtoMapper.mapFromModel(manager),
|
||||
vanced = appDtoMapper.mapFromModel(vanced),
|
||||
music = appDtoMapper.mapFromModel(music),
|
||||
microg = appDtoMapper.mapFromModel(microg)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
package com.vanced.manager.preference
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import androidx.core.content.edit
|
||||
import androidx.preference.PreferenceManager
|
||||
|
||||
val Context.defPrefs: SharedPreferences get() = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
|
||||
var SharedPreferences.managerTheme
|
||||
get() = getString("manager_theme", "Light")
|
||||
set(value) {
|
||||
edit {
|
||||
putString("manager_theme", value)
|
||||
}
|
||||
}
|
|
@ -1,9 +1,8 @@
|
|||
package com.vanced.manager
|
||||
package com.vanced.manager.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
|
@ -11,37 +10,36 @@ import androidx.compose.material.icons.filled.ArrowBackIos
|
|||
import androidx.compose.material.icons.filled.MoreVert
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import androidx.navigation.NavController
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.compose.currentBackStackEntryAsState
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import com.google.accompanist.systemuicontroller.rememberSystemUiController
|
||||
import com.vanced.manager.preference.defPrefs
|
||||
import com.vanced.manager.preference.managerTheme
|
||||
import com.vanced.manager.ui.composables.*
|
||||
import com.vanced.manager.ui.layouts.*
|
||||
import com.vanced.manager.ui.components.color.managerAnimatedColor
|
||||
import com.vanced.manager.ui.components.color.managerCardColor
|
||||
import com.vanced.manager.ui.components.color.managerSurfaceColor
|
||||
import com.vanced.manager.ui.components.color.managerTextColor
|
||||
import com.vanced.manager.ui.components.menu.ManagerDropdownMenuItem
|
||||
import com.vanced.manager.ui.screens.Screen
|
||||
import com.vanced.manager.ui.theme.ComposeTestTheme
|
||||
import com.vanced.manager.ui.theme.ManagerTheme
|
||||
import com.vanced.manager.ui.theme.isDark
|
||||
import com.vanced.manager.ui.theme.managerTheme
|
||||
import com.vanced.manager.ui.widgets.text.ToolbarTitleText
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
|
||||
@ExperimentalAnimationApi
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContent {
|
||||
managerTheme = defPrefs.managerTheme
|
||||
|
||||
ComposeTestTheme {
|
||||
//ButtonLayoutActivity()
|
||||
ManagerTheme {
|
||||
MainActivityLayout()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ExperimentalAnimationApi
|
||||
@Composable
|
||||
fun MainActivityLayout() {
|
||||
val isMenuExpanded = remember { mutableStateOf(false) }
|
||||
|
@ -50,10 +48,11 @@ class MainActivity : AppCompatActivity() {
|
|||
val isDark = isDark()
|
||||
val navController = rememberNavController()
|
||||
|
||||
val dropdownScreens = listOf(
|
||||
val screens = listOf(
|
||||
Screen.Home,
|
||||
Screen.Settings,
|
||||
Screen.Logs,
|
||||
Screen.About
|
||||
Screen.About,
|
||||
Screen.Logs
|
||||
)
|
||||
|
||||
SideEffect {
|
||||
|
@ -63,9 +62,9 @@ class MainActivity : AppCompatActivity() {
|
|||
Scaffold(
|
||||
topBar = {
|
||||
MainToolbar(
|
||||
navController,
|
||||
dropdownScreens,
|
||||
isMenuExpanded
|
||||
navController = navController,
|
||||
screens = screens,
|
||||
isMenuExpanded = isMenuExpanded
|
||||
)
|
||||
},
|
||||
backgroundColor = managerSurfaceColor()
|
||||
|
@ -74,8 +73,10 @@ class MainActivity : AppCompatActivity() {
|
|||
navController = navController,
|
||||
startDestination = Screen.Home.route
|
||||
) {
|
||||
composable(Screen.Home.route) {
|
||||
HomeLayout()
|
||||
screens.fastForEach { screen ->
|
||||
composable(screen.route) {
|
||||
screen.content()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -84,23 +85,17 @@ class MainActivity : AppCompatActivity() {
|
|||
@Composable
|
||||
fun MainToolbar(
|
||||
navController: NavController,
|
||||
dropdownScreens: List<Screen>,
|
||||
screens: List<Screen>,
|
||||
isMenuExpanded: MutableState<Boolean>
|
||||
) {
|
||||
val currentScreenRoute = navController.currentBackStackEntryAsState().value?.destination?.route
|
||||
TopAppBar(
|
||||
title = {
|
||||
navController.currentDestination
|
||||
Text(
|
||||
//This does not look good at all
|
||||
text = Screen::class.sealedSubclasses.find {
|
||||
it.objectInstance?.route == navController.currentDestination?.route
|
||||
}?.objectInstance?.displayName ?: "",
|
||||
color = managerAnimatedColor(color = MaterialTheme.colors.onSurface)
|
||||
)
|
||||
ToolbarTitleText(screens.find { it.route == currentScreenRoute }?.displayName)
|
||||
},
|
||||
backgroundColor = managerAnimatedColor(color = MaterialTheme.colors.surface),
|
||||
actions = {
|
||||
if (navController.currentDestination?.route == Screen.Home.route) {
|
||||
if (currentScreenRoute == Screen.Home.route) {
|
||||
IconButton(
|
||||
onClick = { isMenuExpanded.value = !isMenuExpanded.value }
|
||||
) {
|
||||
|
@ -118,27 +113,22 @@ class MainActivity : AppCompatActivity() {
|
|||
},
|
||||
modifier = Modifier.background(managerCardColor())
|
||||
) {
|
||||
dropdownScreens.forEach {
|
||||
screens.filter { it.route != currentScreenRoute }.forEach {
|
||||
ManagerDropdownMenuItem(
|
||||
isMenuExpanded = isMenuExpanded,
|
||||
title = it.displayName
|
||||
title = stringResource(id = it.displayName)
|
||||
) {
|
||||
isMenuExpanded.value = !isMenuExpanded.value
|
||||
navController.navigate(it.route) {
|
||||
popUpTo(Screen.Home.route)
|
||||
anim {
|
||||
enter = R.animator.fragment_enter
|
||||
exit = R.animator.fragment_exit
|
||||
popEnter = R.animator.fragment_enter_pop
|
||||
popEnter = R.animator.fragment_exit_pop
|
||||
popUpTo(Screen.Home.route) {
|
||||
saveState = true
|
||||
}
|
||||
restoreState = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
navigationIcon = if (navController.currentDestination?.route != Screen.Home.route) { {
|
||||
navigationIcon = if (currentScreenRoute != Screen.Home.route) { {
|
||||
IconButton(onClick = {
|
||||
navController.popBackStack()
|
||||
}) {
|
|
@ -0,0 +1,46 @@
|
|||
package com.vanced.manager.ui.components
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.em
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.vanced.manager.ui.theme.managerAccentColor
|
||||
import java.util.*
|
||||
|
||||
@Composable
|
||||
fun HeaderView(
|
||||
modifier: Modifier = Modifier,
|
||||
headerName: String,
|
||||
headerPadding: Dp = 11.dp,
|
||||
content: @Composable ColumnScope.() -> Unit
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
) {
|
||||
Header(headerName = headerName, headerPadding = headerPadding)
|
||||
content()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Header(
|
||||
headerName: String,
|
||||
headerPadding: Dp = 11.dp,
|
||||
) {
|
||||
Text(
|
||||
headerName.uppercase(Locale.ROOT),
|
||||
letterSpacing = 0.15.em,
|
||||
color = MaterialTheme.colors.managerAccentColor,
|
||||
modifier = Modifier.padding(horizontal = headerPadding),
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 13.sp
|
||||
)
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.vanced.manager.ui.components.button
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun IconButton(
|
||||
icon: ImageVector,
|
||||
contentDescription: String,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
val interactionSource = remember { MutableInteractionSource() }
|
||||
val buttonSize = 36.dp
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.clickable(
|
||||
onClick = onClick,
|
||||
role = Role.Button,
|
||||
interactionSource = interactionSource,
|
||||
indication = rememberRipple(bounded = false, radius = 18.dp)
|
||||
)
|
||||
.size(buttonSize),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = contentDescription
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package com.vanced.manager.ui.components.button
|
||||
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material.ButtonDefaults
|
||||
import androidx.compose.material.LocalContentColor
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.luminance
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vanced.manager.ui.components.color.managerAccentColor
|
||||
|
||||
@Composable
|
||||
fun ManagerThemedButton(
|
||||
modifier: Modifier = Modifier,
|
||||
onClick: () -> Unit,
|
||||
content: @Composable RowScope.() -> Unit
|
||||
) {
|
||||
val accentColor = managerAccentColor()
|
||||
Button(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
onClick = onClick,
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
backgroundColor = managerAccentColor()
|
||||
),
|
||||
elevation = ButtonDefaults.elevation(0.dp, 0.dp, 0.dp)
|
||||
) {
|
||||
CompositionLocalProvider(LocalContentColor provides if (accentColor.luminance() > 0.7) Color.Black else Color.White) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.vanced.manager.ui.components.button
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.vanced.manager.ui.components.text.ManagerText
|
||||
|
||||
@Composable
|
||||
fun ManagerThemedTextButton(
|
||||
modifier: Modifier = Modifier,
|
||||
@StringRes stringId: Int,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
ManagerThemedButton(
|
||||
modifier = modifier,
|
||||
onClick = onClick
|
||||
) {
|
||||
ManagerText(stringId = stringId)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package com.vanced.manager.ui.components.card
|
||||
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vanced.manager.ui.components.color.managerCardColor
|
||||
|
||||
@Composable
|
||||
fun ManagerCard(
|
||||
modifier: Modifier = Modifier,
|
||||
shape: Shape = MaterialTheme.shapes.medium,
|
||||
backgroundColor: Color = MaterialTheme.colors.surface,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
Card(
|
||||
modifier = modifier,
|
||||
shape = shape,
|
||||
backgroundColor = backgroundColor,
|
||||
elevation = 0.dp,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
fun ManagerCard(
|
||||
modifier: Modifier = Modifier,
|
||||
shape: Shape = MaterialTheme.shapes.medium,
|
||||
backgroundColor: Color = managerCardColor(),
|
||||
onClick: () -> Unit,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
Card(
|
||||
modifier = modifier,
|
||||
shape = shape,
|
||||
backgroundColor = backgroundColor,
|
||||
elevation = 0.dp,
|
||||
content = content,
|
||||
onClick = onClick
|
||||
)
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package com.vanced.manager.ui.components.card
|
||||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.vanced.manager.ui.components.color.ThemedItemContentColorProvider
|
||||
import com.vanced.manager.ui.components.color.managerAccentColor
|
||||
|
||||
private val cardModifier = Modifier.sizeIn(
|
||||
minHeight = 95.dp,
|
||||
minWidth = 95.dp
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun ManagerItemCard(
|
||||
title: String,
|
||||
@DrawableRes icon: Int? = null
|
||||
) {
|
||||
ManagerThemedCard(
|
||||
modifier = cardModifier,
|
||||
) {
|
||||
ManagerItemCardContent(title, icon)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ManagerClickableItemCard(
|
||||
title: String,
|
||||
@DrawableRes icon: Int? = null,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
ManagerClickableThemedCard(
|
||||
modifier = cardModifier,
|
||||
onClick = onClick
|
||||
) {
|
||||
ManagerItemCardContent(title, icon)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ManagerItemCardContent(
|
||||
title: String,
|
||||
@DrawableRes icon: Int? = null,
|
||||
) {
|
||||
Canvas(modifier = Modifier.requiredSize(72.dp)) {
|
||||
drawCircle(
|
||||
color = managerAccentColor(),
|
||||
center = Offset(32f,32f)
|
||||
)
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier.padding(12.dp)
|
||||
) {
|
||||
if (icon != null) {
|
||||
ThemedItemContentColorProvider {
|
||||
Icon(
|
||||
modifier = Modifier
|
||||
.size(28.dp)
|
||||
.align(Alignment.TopStart),
|
||||
painter = painterResource(id = icon),
|
||||
contentDescription = title
|
||||
)
|
||||
}
|
||||
}
|
||||
Text(
|
||||
modifier = Modifier.align(Alignment.BottomStart),
|
||||
text = title,
|
||||
fontSize = 12.sp,
|
||||
fontWeight = FontWeight.Medium,
|
||||
color = MaterialTheme.colors.onSurface
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.vanced.manager.ui.components.card
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.browser.customtabs.CustomTabsIntent
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import com.vanced.manager.ui.preferences.holder.useCustomTabsPref
|
||||
|
||||
@Composable
|
||||
fun ManagerLinkCard(
|
||||
title: String,
|
||||
@DrawableRes icon: Int,
|
||||
link: String
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val customTabs = remember { CustomTabsIntent.Builder().build() }
|
||||
val uri = remember { Uri.parse(link) }
|
||||
val intent = remember { Intent(Intent.ACTION_VIEW, uri) }
|
||||
val useCustomTabs by useCustomTabsPref
|
||||
ManagerClickableItemCard(
|
||||
title = title,
|
||||
icon = icon
|
||||
) {
|
||||
if (useCustomTabs) {
|
||||
customTabs.launchUrl(context, uri)
|
||||
} else {
|
||||
context.startActivity(intent)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package com.vanced.manager.ui.components.card
|
||||
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import com.vanced.manager.ui.components.color.managerThemedCardColor
|
||||
|
||||
@Composable
|
||||
fun ManagerThemedCard(
|
||||
modifier: Modifier = Modifier,
|
||||
shape: Shape = MaterialTheme.shapes.medium,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
ManagerCard(
|
||||
modifier = modifier,
|
||||
shape = shape,
|
||||
backgroundColor = managerThemedCardColor(),
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ManagerClickableThemedCard(
|
||||
modifier: Modifier = Modifier,
|
||||
shape: Shape = MaterialTheme.shapes.medium,
|
||||
onClick: () -> Unit,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
ManagerCard(
|
||||
modifier = modifier,
|
||||
shape = shape,
|
||||
backgroundColor = managerThemedCardColor(),
|
||||
onClick = onClick,
|
||||
) {
|
||||
content()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package com.vanced.manager.ui.components.checkbox
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.compose.animation.core.animateDp
|
||||
import androidx.compose.animation.core.keyframes
|
||||
import androidx.compose.animation.core.updateTransition
|
||||
import androidx.compose.foundation.layout.requiredSize
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.rounded.Close
|
||||
import androidx.compose.material.icons.rounded.Done
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vanced.manager.ui.components.card.ManagerCard
|
||||
import com.vanced.manager.ui.components.color.contentColorForColor
|
||||
import com.vanced.manager.ui.components.color.managerAccentColor
|
||||
import com.vanced.manager.ui.components.color.managerAnimatedColor
|
||||
import com.vanced.manager.ui.components.color.managerThemedCardColor
|
||||
|
||||
@SuppressLint("UnusedTransitionTargetStateParameter")
|
||||
@Composable
|
||||
fun ManagerCheckbox(
|
||||
isChecked: Boolean,
|
||||
onCheckedChange: (isChecked: Boolean) -> Unit
|
||||
) {
|
||||
val transition = updateTransition(targetState = isChecked, label = "Checked")
|
||||
val cardSize by transition.animateDp(
|
||||
transitionSpec = {
|
||||
keyframes {
|
||||
durationMillis = 250
|
||||
32.dp at 50
|
||||
48.dp at 150
|
||||
40.dp at 250
|
||||
}
|
||||
},
|
||||
label = "Checkbox size"
|
||||
) { 40.dp }
|
||||
val iconSize by transition.animateDp(
|
||||
transitionSpec = {
|
||||
keyframes {
|
||||
durationMillis = 250
|
||||
18.dp at 50
|
||||
30.dp at 150
|
||||
24.dp at 250
|
||||
}
|
||||
},
|
||||
label = "Icon size"
|
||||
) { 24.dp }
|
||||
val cardColor = managerAnimatedColor(if (isChecked) managerAccentColor() else managerThemedCardColor())
|
||||
val iconTint = managerAnimatedColor(if (isChecked) contentColorForColor(cardColor) else managerAccentColor())
|
||||
|
||||
ManagerCard(
|
||||
modifier = Modifier.size(cardSize),
|
||||
onClick = { onCheckedChange(!isChecked) },
|
||||
backgroundColor = cardColor
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.requiredSize(iconSize),
|
||||
imageVector = if (isChecked) Icons.Rounded.Done else Icons.Rounded.Close,
|
||||
tint = iconTint,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.vanced.manager.ui.components.color
|
||||
|
||||
import androidx.compose.material.LocalContentColor
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
|
||||
@Composable
|
||||
fun ThemedItemContentColorProvider(
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
CompositionLocalProvider(
|
||||
LocalContentColor provides contentColorForColor(managerAccentColor()),
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ThemedCardContentColorProvider(
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
CompositionLocalProvider(
|
||||
LocalContentColor provides contentColorForColor(managerThemedCardColor()),
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ThemedContentColorProvider(
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
CompositionLocalProvider(
|
||||
LocalContentColor provides managerAccentColor(),
|
||||
content = content
|
||||
)
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package com.vanced.manager.ui.components.color
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.skydoves.colorpickerview.ColorEnvelope
|
||||
import com.skydoves.orchestra.colorpicker.ColorPicker
|
||||
|
||||
@Composable
|
||||
fun ManagerColorPicker(
|
||||
onColorSelected: (color: Long) -> Unit
|
||||
) {
|
||||
val (selectedColor, setColor) = remember { mutableStateOf(ColorEnvelope(0)) }
|
||||
ColorPicker(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(400.dp),
|
||||
onColorListener = { envelope, _ -> setColor(envelope) },
|
||||
children = {}
|
||||
)
|
||||
onColorSelected(selectedColor.color.toLong())
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package com.vanced.manager.ui.components.color
|
||||
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.luminance
|
||||
import com.vanced.manager.ui.preferences.holder.managerAccentColorPref
|
||||
import com.vanced.manager.ui.theme.cardColor
|
||||
|
||||
fun managerAccentColor(): Color = Color(managerAccentColorPref.value.value)
|
||||
|
||||
@Composable
|
||||
fun contentColorForColor(color: Color) =
|
||||
if (color.luminance() > 0.7)
|
||||
Color.Black
|
||||
else
|
||||
Color.White
|
||||
|
||||
@Composable
|
||||
fun managerThemedCardColor() = managerAccentColor().copy(alpha = 0.2f)
|
||||
|
||||
@Composable
|
||||
fun managerTextColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.onSurface)
|
||||
|
||||
@Composable
|
||||
fun managerSurfaceColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.surface)
|
||||
|
||||
@Composable
|
||||
fun managerCardColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.cardColor)
|
||||
|
||||
@Composable
|
||||
fun animatedManagerAccentColor(): Color = managerAnimatedColor(color = managerAccentColor())
|
||||
|
||||
@Composable
|
||||
fun managerAnimatedColor(
|
||||
color: Color
|
||||
): Color {
|
||||
return animateColorAsState(
|
||||
targetValue = color,
|
||||
animationSpec = tween(500)
|
||||
).value
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package com.vanced.manager.ui.components.dialog
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import com.vanced.manager.ui.components.card.ManagerCard
|
||||
import com.vanced.manager.ui.components.text.ManagerText
|
||||
import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal
|
||||
|
||||
@Composable
|
||||
fun ManagerDialog(
|
||||
@StringRes titleId: Int,
|
||||
onDismissRequest: () -> Unit,
|
||||
buttons: @Composable ColumnScope.() -> Unit,
|
||||
content: @Composable ColumnScope.() -> Unit,
|
||||
) {
|
||||
ManagerDialog(
|
||||
title = {
|
||||
ManagerText(
|
||||
modifier = Modifier.align(Alignment.CenterHorizontally),
|
||||
stringId = titleId,
|
||||
textStyle = MaterialTheme.typography.h2
|
||||
)
|
||||
},
|
||||
onDismissRequest = onDismissRequest,
|
||||
buttons = buttons,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ManagerDialog(
|
||||
title: String,
|
||||
onDismissRequest: () -> Unit,
|
||||
buttons: @Composable ColumnScope.() -> Unit,
|
||||
content: @Composable ColumnScope.() -> Unit,
|
||||
) {
|
||||
ManagerDialog(
|
||||
title = {
|
||||
ManagerText(
|
||||
modifier = Modifier.align(Alignment.CenterHorizontally),
|
||||
textStyle = MaterialTheme.typography.h2,
|
||||
text = title
|
||||
)
|
||||
},
|
||||
onDismissRequest = onDismissRequest,
|
||||
buttons = buttons,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ManagerDialog(
|
||||
title: @Composable ColumnScope.() -> Unit,
|
||||
onDismissRequest: () -> Unit,
|
||||
buttons: @Composable ColumnScope.() -> Unit,
|
||||
content: @Composable ColumnScope.() -> Unit,
|
||||
) {
|
||||
Dialog(
|
||||
onDismissRequest = onDismissRequest,
|
||||
content = {
|
||||
ManagerCard {
|
||||
Column(
|
||||
modifier = Modifier.padding(defaultContentPaddingHorizontal),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
title()
|
||||
content()
|
||||
buttons()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.vanced.manager.ui.components.layout
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun ManagerLazyColumn(
|
||||
itemSpacing: Dp = 0.dp,
|
||||
content: LazyListScope.() -> Unit
|
||||
) {
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(12.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(itemSpacing),
|
||||
content = content
|
||||
)
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package com.vanced.manager.ui.components.layout
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vanced.manager.ui.utils.defaultContentPaddingVertical
|
||||
|
||||
@Composable
|
||||
fun ManagerScrollableColumn(
|
||||
contentPaddingVertical: Dp = defaultContentPaddingVertical,
|
||||
itemSpacing: Dp = 0.dp,
|
||||
content: @Composable ColumnScope.() -> Unit
|
||||
) {
|
||||
val scrollState = rememberScrollState()
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.verticalScroll(scrollState)
|
||||
.padding(vertical = contentPaddingVertical),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(itemSpacing),
|
||||
content = content
|
||||
)
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.vanced.manager.ui.components.layout
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.vanced.manager.ui.components.color.managerSurfaceColor
|
||||
|
||||
@Composable
|
||||
fun ManagerSurface(
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
color = managerSurfaceColor(),
|
||||
content = content
|
||||
)
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package com.vanced.manager.ui.components.layout
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun <T> ScrollableItemRow(
|
||||
items: List<T>,
|
||||
content: @Composable (T) -> Unit
|
||||
) {
|
||||
val state = rememberLazyListState()
|
||||
LazyRow(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
state = state
|
||||
) {
|
||||
items(items) { item ->
|
||||
content(item)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.vanced.manager.ui.components.lifecycle
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.vanced.manager.R
|
||||
|
||||
@Composable
|
||||
fun managerString(
|
||||
@StringRes stringId: Int?
|
||||
) = stringResource(id = stringId ?: R.string.dummy_placeholder_text)
|
||||
|
||||
@Composable
|
||||
fun managerString(
|
||||
@StringRes stringId: Int?,
|
||||
vararg formatArgs: Any
|
||||
) = stringResource(id = stringId ?: R.string.dummy_placeholder_text, *formatArgs)
|
|
@ -0,0 +1,54 @@
|
|||
package com.vanced.manager.ui.components.list
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.Checkbox
|
||||
import androidx.compose.material.CheckboxDefaults
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.vanced.manager.ui.components.color.managerTextColor
|
||||
import com.vanced.manager.ui.theme.managerAccentColor
|
||||
|
||||
@Composable
|
||||
fun CheckboxItem(
|
||||
text: String,
|
||||
isChecked: Boolean,
|
||||
onCheck: (Boolean) -> Unit = {}
|
||||
) {
|
||||
fun toggle() {
|
||||
onCheck(isChecked)
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { toggle() }
|
||||
.padding(horizontal = 8.dp, vertical = 6.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Checkbox(
|
||||
checked = isChecked,
|
||||
onCheckedChange = {
|
||||
toggle()
|
||||
},
|
||||
colors = CheckboxDefaults.colors(
|
||||
MaterialTheme.colors.managerAccentColor,
|
||||
Color.LightGray
|
||||
)
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.padding(start = 12.dp),
|
||||
text = text,
|
||||
color = managerTextColor(),
|
||||
fontSize = 18.sp
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package com.vanced.manager.ui.components.list
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.ContentAlpha
|
||||
import androidx.compose.material.LocalContentAlpha
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun ManagerListItem(
|
||||
modifier: Modifier = Modifier,
|
||||
title: @Composable () -> Unit,
|
||||
description: @Composable (() -> Unit)? = null,
|
||||
icon: @Composable (() -> Unit)? = null,
|
||||
trailing: @Composable (() -> Unit)? = null
|
||||
) {
|
||||
Row(modifier = modifier) {
|
||||
if (icon != null) {
|
||||
Box(
|
||||
modifier = Modifier.align(Alignment.CenterVertically)
|
||||
) {
|
||||
icon()
|
||||
}
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(
|
||||
start = if (icon != null) 12.dp else 0.dp,
|
||||
top = if (description != null) 6.dp else 12.dp,
|
||||
bottom = if (description != null) 6.dp else 12.dp,
|
||||
end = if (trailing != null) 12.dp else 0.dp,
|
||||
)
|
||||
.align(Alignment.CenterVertically)
|
||||
) {
|
||||
title()
|
||||
if (description != null) {
|
||||
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
|
||||
description()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (trailing != null) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(56.dp)
|
||||
.align(Alignment.CenterVertically),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
trailing()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package com.vanced.manager.ui.components.list
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.RadioButton
|
||||
import androidx.compose.material.RadioButtonDefaults
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.vanced.manager.ui.components.color.managerTextColor
|
||||
import com.vanced.manager.ui.theme.managerAccentColor
|
||||
|
||||
@Composable
|
||||
fun <T> RadiobuttonItem(
|
||||
text: String,
|
||||
tag: T,
|
||||
selected: Boolean,
|
||||
onSelect: (tag: T) -> Unit
|
||||
) {
|
||||
val onClick = {
|
||||
onSelect(tag)
|
||||
}
|
||||
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick = onClick)
|
||||
.padding(horizontal = 8.dp, vertical = 6.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
RadioButton(
|
||||
selected = selected,
|
||||
onClick = onClick,
|
||||
colors = RadioButtonDefaults.colors(
|
||||
MaterialTheme.colors.managerAccentColor,
|
||||
Color.LightGray
|
||||
)
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.padding(start = 12.dp),
|
||||
text = text,
|
||||
color = managerTextColor(),
|
||||
fontSize = 18.sp
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.vanced.manager.ui.components.menu
|
||||
|
||||
import androidx.compose.material.DropdownMenuItem
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.vanced.manager.ui.components.text.ManagerText
|
||||
|
||||
@Composable
|
||||
fun ManagerDropdownMenuItem(
|
||||
title: String,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
onClick = onClick,
|
||||
) {
|
||||
ManagerText(
|
||||
text = title,
|
||||
textStyle = MaterialTheme.typography.body1
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.vanced.manager.ui.components.placeholder
|
||||
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.composed
|
||||
import com.google.accompanist.placeholder.PlaceholderHighlight
|
||||
import com.google.accompanist.placeholder.material.placeholder
|
||||
import com.google.accompanist.placeholder.material.shimmer
|
||||
|
||||
fun Modifier.managerPlaceholder(
|
||||
visible: Boolean
|
||||
) = composed {
|
||||
then(
|
||||
placeholder(
|
||||
visible = visible,
|
||||
highlight = PlaceholderHighlight.shimmer()
|
||||
)
|
||||
)
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package com.vanced.manager.ui.components.preference
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import com.vanced.manager.ui.components.checkbox.ManagerCheckbox
|
||||
import com.vanced.manager.ui.preferences.ManagerPreference
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun CheckboxPreference(
|
||||
@StringRes preferenceTitle: Int,
|
||||
@StringRes preferenceDescription: Int? = null,
|
||||
preference: ManagerPreference<Boolean>,
|
||||
onCheckedChange: (isChecked: Boolean) -> Unit = {}
|
||||
) {
|
||||
val isChecked by preference
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
val onClick: () -> Unit = {
|
||||
coroutineScope.launch {
|
||||
preference.save(!isChecked)
|
||||
onCheckedChange(isChecked)
|
||||
}
|
||||
}
|
||||
|
||||
Preference(
|
||||
preferenceTitleId = preferenceTitle,
|
||||
preferenceDescriptionId = preferenceDescription,
|
||||
onClick = onClick,
|
||||
trailing = {
|
||||
ManagerCheckbox(
|
||||
isChecked = isChecked,
|
||||
onCheckedChange = { onClick() }
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CheckboxPreference(
|
||||
preferenceTitle: String,
|
||||
preferenceDescription: String? = null,
|
||||
preference: ManagerPreference<Boolean>,
|
||||
onCheckedChange: (isChecked: Boolean) -> Unit = {}
|
||||
) {
|
||||
val isChecked by preference
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
val onClick: () -> Unit = {
|
||||
coroutineScope.launch {
|
||||
preference.save(!isChecked)
|
||||
onCheckedChange(isChecked)
|
||||
}
|
||||
}
|
||||
|
||||
Preference(
|
||||
preferenceTitle = preferenceTitle,
|
||||
preferenceDescription = preferenceDescription,
|
||||
onClick = onClick,
|
||||
trailing = {
|
||||
ManagerCheckbox(
|
||||
isChecked = isChecked,
|
||||
onCheckedChange = { onClick() }
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package com.vanced.manager.ui.components.preference
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import com.vanced.manager.ui.components.dialog.ManagerDialog
|
||||
|
||||
@Composable
|
||||
fun DialogPreference(
|
||||
@StringRes preferenceTitleId: Int,
|
||||
@StringRes preferenceDescriptionId: Int? = null,
|
||||
trailing: @Composable () -> Unit = {},
|
||||
buttons: @Composable ColumnScope.(isShown: MutableState<Boolean>) -> Unit,
|
||||
content: @Composable ColumnScope.() -> Unit
|
||||
) {
|
||||
val isShown = remember { mutableStateOf(false) }
|
||||
Preference(
|
||||
preferenceTitleId = preferenceTitleId,
|
||||
preferenceDescriptionId = preferenceDescriptionId,
|
||||
trailing = trailing
|
||||
) {
|
||||
isShown.value = true
|
||||
}
|
||||
if (isShown.value) {
|
||||
ManagerDialog(
|
||||
titleId = preferenceTitleId,
|
||||
onDismissRequest = {
|
||||
isShown.value = false
|
||||
},
|
||||
buttons = { buttons(isShown) },
|
||||
content = content
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DialogPreference(
|
||||
@StringRes preferenceTitleId: Int,
|
||||
preferenceDescription: String? = null,
|
||||
trailing: @Composable () -> Unit = {},
|
||||
buttons: @Composable ColumnScope.(isShown: MutableState<Boolean>) -> Unit,
|
||||
content: @Composable ColumnScope.() -> Unit
|
||||
) {
|
||||
val isShown = remember { mutableStateOf(false) }
|
||||
Preference(
|
||||
preferenceTitleId = preferenceTitleId,
|
||||
preferenceDescription = preferenceDescription,
|
||||
trailing = trailing
|
||||
) {
|
||||
isShown.value = true
|
||||
}
|
||||
if (isShown.value) {
|
||||
ManagerDialog(
|
||||
titleId = preferenceTitleId,
|
||||
onDismissRequest = {
|
||||
isShown.value = false
|
||||
},
|
||||
buttons = { buttons(isShown) },
|
||||
content = content
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DialogPreference(
|
||||
preferenceTitle: String,
|
||||
preferenceDescription: String? = null,
|
||||
trailing: @Composable () -> Unit = {},
|
||||
buttons: @Composable ColumnScope.(isShown: MutableState<Boolean>) -> Unit,
|
||||
content: @Composable ColumnScope.() -> Unit
|
||||
) {
|
||||
val isShown = remember { mutableStateOf(false) }
|
||||
Preference(
|
||||
preferenceTitle = preferenceTitle,
|
||||
preferenceDescription = preferenceDescription,
|
||||
trailing = trailing
|
||||
) {
|
||||
isShown.value = true
|
||||
}
|
||||
if (isShown.value) {
|
||||
ManagerDialog(
|
||||
title = preferenceTitle,
|
||||
onDismissRequest = {
|
||||
isShown.value = false
|
||||
},
|
||||
buttons = { buttons(isShown) },
|
||||
content = content
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
package com.vanced.manager.ui.components.preference
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.LocalContentColor
|
||||
import androidx.compose.material.LocalTextStyle
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.vanced.manager.ui.components.color.managerAnimatedColor
|
||||
import com.vanced.manager.ui.components.list.ManagerListItem
|
||||
import com.vanced.manager.ui.components.text.ManagerText
|
||||
import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal
|
||||
|
||||
@Composable
|
||||
fun Preference(
|
||||
@StringRes preferenceTitleId: Int,
|
||||
@StringRes preferenceDescriptionId: Int? = null,
|
||||
trailing: @Composable () -> Unit = {},
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
Preference(
|
||||
preferenceTitle = { ManagerText(stringId = preferenceTitleId) },
|
||||
preferenceDescription = if (preferenceDescriptionId != null) {{
|
||||
ManagerText(stringId = preferenceDescriptionId)
|
||||
}} else null,
|
||||
trailing = trailing,
|
||||
onClick = onClick
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Preference(
|
||||
@StringRes preferenceTitleId: Int,
|
||||
preferenceDescription: String? = null,
|
||||
trailing: @Composable () -> Unit = {},
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
Preference(
|
||||
preferenceTitle = { ManagerText(stringId = preferenceTitleId) },
|
||||
preferenceDescription = if (preferenceDescription != null) {{
|
||||
ManagerText(text = preferenceDescription)
|
||||
}} else null,
|
||||
trailing = trailing,
|
||||
onClick = onClick
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Preference(
|
||||
preferenceTitle: String,
|
||||
preferenceDescription: String? = null,
|
||||
trailing: @Composable () -> Unit = {},
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
Preference(
|
||||
preferenceTitle = { ManagerText(text = preferenceTitle) },
|
||||
preferenceDescription = if (preferenceDescription != null) {{
|
||||
ManagerText(text = preferenceDescription)
|
||||
}} else null,
|
||||
trailing = trailing,
|
||||
onClick = onClick
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Preference(
|
||||
preferenceTitle: @Composable () -> Unit,
|
||||
preferenceDescription: @Composable (() -> Unit)? = null,
|
||||
trailing: @Composable () -> Unit = {},
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
val color = managerAnimatedColor(color = MaterialTheme.colors.onSurface)
|
||||
ManagerListItem(
|
||||
modifier = Modifier
|
||||
.clickable(onClick = onClick)
|
||||
.padding(horizontal = defaultContentPaddingHorizontal),
|
||||
title = {
|
||||
CompositionLocalProvider(
|
||||
LocalContentColor provides color,
|
||||
LocalTextStyle provides MaterialTheme.typography.h6
|
||||
) {
|
||||
preferenceTitle()
|
||||
}
|
||||
},
|
||||
description = if (preferenceDescription != null) {{
|
||||
CompositionLocalProvider(
|
||||
LocalContentColor provides color,
|
||||
LocalTextStyle provides MaterialTheme.typography.subtitle1
|
||||
) {
|
||||
preferenceDescription()
|
||||
}
|
||||
}} else null,
|
||||
trailing = trailing,
|
||||
)
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package com.vanced.manager.ui.components.preference
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.vanced.manager.R
|
||||
import com.vanced.manager.ui.components.*
|
||||
import com.vanced.manager.ui.components.button.ManagerThemedButton
|
||||
import com.vanced.manager.ui.components.button.ManagerThemedTextButton
|
||||
import com.vanced.manager.ui.components.list.CheckboxItem
|
||||
import com.vanced.manager.ui.preferences.*
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun CheckboxDialogPreference(
|
||||
@StringRes preferenceTitle: Int,
|
||||
@StringRes preferenceDescription: Int? = null,
|
||||
preference: ManagerPreference<Set<String>>,
|
||||
trailing: @Composable () -> Unit = {},
|
||||
buttons: List<CheckboxPreference>,
|
||||
onSave: (checkedButtons: List<String>) -> Unit = {}
|
||||
) {
|
||||
val selectedButtons = remember { preference.value.value.toMutableStateList() }
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
DialogPreference(
|
||||
preferenceTitleId = preferenceTitle,
|
||||
preferenceDescriptionId = preferenceDescription,
|
||||
trailing = trailing,
|
||||
buttons = { isShown ->
|
||||
ManagerThemedTextButton(
|
||||
stringId = R.string.dialog_button_save,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onClick = {
|
||||
coroutineScope.launch {
|
||||
preference.save(selectedButtons.toSet())
|
||||
onSave(selectedButtons)
|
||||
isShown.value = false
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
) {
|
||||
items(buttons) { button ->
|
||||
val (title, key) = button
|
||||
CheckboxItem(
|
||||
text = title,
|
||||
isChecked = selectedButtons.contains(key),
|
||||
onCheck = { isChecked ->
|
||||
if (isChecked) {
|
||||
selectedButtons.add(key)
|
||||
} else {
|
||||
selectedButtons.remove(key)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package com.vanced.manager.ui.components.preference
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vanced.manager.R
|
||||
import com.vanced.manager.ui.components.button.ManagerThemedTextButton
|
||||
import com.vanced.manager.ui.components.list.RadiobuttonItem
|
||||
import com.vanced.manager.ui.preferences.ManagerPreference
|
||||
import com.vanced.manager.ui.preferences.RadioButtonPreference
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun RadiobuttonDialogPreference(
|
||||
@StringRes preferenceTitle: Int,
|
||||
preference: ManagerPreference<String>,
|
||||
trailing: @Composable () -> Unit = {},
|
||||
buttons: List<RadioButtonPreference>,
|
||||
onSave: (newPref: String?) -> Unit = {}
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
var currentSelection by remember { mutableStateOf(preference.value.value) }
|
||||
DialogPreference(
|
||||
preferenceTitleId = preferenceTitle,
|
||||
preferenceDescription = currentSelection,
|
||||
trailing = trailing,
|
||||
buttons = { isShown ->
|
||||
ManagerThemedTextButton(
|
||||
stringId = R.string.dialog_button_save,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onClick = {
|
||||
coroutineScope.launch {
|
||||
preference.save(currentSelection)
|
||||
onSave(currentSelection)
|
||||
isShown.value = false
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier.heightIn(max = 400.dp)
|
||||
) {
|
||||
items(buttons) { button ->
|
||||
val (title, key) = button
|
||||
RadiobuttonItem(
|
||||
text = title,
|
||||
tag = key,
|
||||
selected = currentSelection == key,
|
||||
onSelect = {
|
||||
currentSelection = it
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.vanced.manager.ui.components.text
|
||||
|
||||
import androidx.compose.material.LocalTextStyle
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import com.vanced.manager.ui.components.lifecycle.managerString
|
||||
|
||||
@Composable
|
||||
fun ManagerText(
|
||||
vararg formatArgs: Any,
|
||||
modifier: Modifier = Modifier,
|
||||
color: Color = Color.Unspecified,
|
||||
textStyle: TextStyle = LocalTextStyle.current,
|
||||
stringId: Int?,
|
||||
) {
|
||||
ManagerText(
|
||||
modifier = modifier,
|
||||
color = color,
|
||||
textStyle = textStyle,
|
||||
text = managerString(stringId, *formatArgs),
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ManagerText(
|
||||
modifier: Modifier = Modifier,
|
||||
color: Color = Color.Unspecified,
|
||||
textStyle: TextStyle = LocalTextStyle.current,
|
||||
text: String,
|
||||
) {
|
||||
Text(
|
||||
modifier = modifier,
|
||||
text = text,
|
||||
color = color,
|
||||
style = textStyle
|
||||
)
|
||||
}
|
|
@ -1,226 +0,0 @@
|
|||
package com.vanced.manager.ui.composables
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.DeleteForever
|
||||
import androidx.compose.material.icons.filled.Download
|
||||
import androidx.compose.material.icons.filled.Launch
|
||||
import androidx.compose.material.icons.outlined.Info
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.google.accompanist.glide.rememberGlidePainter
|
||||
import com.vanced.manager.R
|
||||
import com.vanced.manager.domain.model.App
|
||||
import com.vanced.manager.downloader.base.BaseDownloader
|
||||
import com.vanced.manager.ui.theme.managerAccentColor
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Composable
|
||||
fun AppCard(
|
||||
app: App,
|
||||
installationOptions: List<InstallationOption>? = null
|
||||
) {
|
||||
val showDownloadDialog = remember { mutableStateOf(false) }
|
||||
val showAppInfo = remember { mutableStateOf(false) }
|
||||
val showInstallationOptions = remember { mutableStateOf(false) }
|
||||
val icon = rememberGlidePainter(
|
||||
request = app.iconUrl ?: "",
|
||||
requestBuilder = {
|
||||
placeholder(R.drawable.ic_app_icon_placeholder)
|
||||
},
|
||||
fadeIn = true
|
||||
)
|
||||
ManagerCard {
|
||||
Column {
|
||||
AppInfoCard(
|
||||
appName = app.name,
|
||||
icon = icon
|
||||
)
|
||||
AppActionCard(
|
||||
appInstalledVersion = app.installedVersion,
|
||||
appRemoteVersion = app.remoteVersion,
|
||||
showDownloadDialog = showDownloadDialog,
|
||||
showAppInfo = showAppInfo,
|
||||
showInstallationOptions = showInstallationOptions
|
||||
)
|
||||
if (installationOptions != null) {
|
||||
AnimatedVisibility(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
visible = showInstallationOptions.value
|
||||
) {
|
||||
installationOptions.forEach {
|
||||
it.Content()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (app.name != null && app.downloader != null) {
|
||||
AppDownloadDialog(
|
||||
app = app.name,
|
||||
downloader = app.downloader,
|
||||
showDialog = showDownloadDialog
|
||||
)
|
||||
}
|
||||
|
||||
if (app.name != null && app.changelog != null) {
|
||||
ChangeLogDialog(
|
||||
appName = app.name,
|
||||
changelog = app.changelog,
|
||||
icon = icon,
|
||||
show = showAppInfo
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AppInfoCard(
|
||||
appName: String?,
|
||||
icon: Painter
|
||||
) {
|
||||
ManagerListItem(
|
||||
title = appName ?: "",
|
||||
icon = {
|
||||
Image(
|
||||
painter = icon,
|
||||
contentDescription = "",
|
||||
modifier = Modifier.size(48.dp, 48.dp),
|
||||
)
|
||||
},
|
||||
topPadding = 8.dp,
|
||||
bottomPadding = 8.dp
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AppActionCard(
|
||||
appRemoteVersion: String?,
|
||||
appInstalledVersion: String?,
|
||||
showDownloadDialog: MutableState<Boolean>,
|
||||
showAppInfo: MutableState<Boolean>,
|
||||
showInstallationOptions: MutableState<Boolean>
|
||||
) {
|
||||
CompositionLocalProvider(LocalContentColor provides MaterialTheme.colors.managerAccentColor) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 12.dp, vertical = 4.dp)
|
||||
.background(managerAccentColor().copy(alpha = 0.15f)),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.wrapContentWidth(Alignment.Start)
|
||||
) {
|
||||
Text(
|
||||
text = "Latest: ${appRemoteVersion ?: "Unavailable"}",
|
||||
fontSize = 12.sp
|
||||
)
|
||||
Text(
|
||||
text = "Installed: ${appInstalledVersion ?: "Unavailable"}",
|
||||
fontSize = 12.sp
|
||||
)
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(start = 4.dp)
|
||||
.wrapContentWidth(Alignment.End)
|
||||
) {
|
||||
IconButton(icon = Icons.Outlined.Info, contentDescription = "App Info") {
|
||||
showAppInfo.value = true
|
||||
}
|
||||
IconButton(icon = Icons.Default.DeleteForever, contentDescription = "Uninstall") {}
|
||||
IconButton(icon = Icons.Default.Launch, contentDescription = "Launch") {}
|
||||
IconButton(icon = Icons.Default.Download, contentDescription = "Install") {
|
||||
showInstallationOptions.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AppDownloadDialog(
|
||||
app: String,
|
||||
downloader: BaseDownloader,
|
||||
showDialog: MutableState<Boolean>
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
val rememberProgress = remember { downloader.downloadProgress }
|
||||
val rememberFile = remember { downloader.downloadFile }
|
||||
val rememberInstalling = remember { downloader.installing }
|
||||
|
||||
val showProgress = remember { mutableStateOf(false) }
|
||||
ManagerDialog(title = app, isShown = showDialog, buttons = {
|
||||
AppDownloadDialogButtons(
|
||||
showProgress = showProgress,
|
||||
showDialog = showDialog,
|
||||
downloader = downloader,
|
||||
coroutineScope = coroutineScope
|
||||
)
|
||||
}) {
|
||||
AppDownloadDialogProgress(
|
||||
progress = rememberProgress,
|
||||
file = rememberFile,
|
||||
showProgress = showProgress.value,
|
||||
installing = rememberInstalling
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ChangeLogDialog(
|
||||
appName: String,
|
||||
changelog: String,
|
||||
icon: Painter,
|
||||
show: MutableState<Boolean>
|
||||
) {
|
||||
if (show.value) {
|
||||
ManagerDialog(
|
||||
title = "About $appName",
|
||||
isShown = show,
|
||||
buttons = {
|
||||
ManagerThemedButton(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onClick = { show.value = false }
|
||||
) {
|
||||
Text(text = "Close")
|
||||
}
|
||||
}
|
||||
) {
|
||||
Image(
|
||||
painter = icon,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.size(64.dp)
|
||||
.align(Alignment.CenterHorizontally)
|
||||
)
|
||||
HeaderView(
|
||||
modifier = Modifier.padding(horizontal = 8.dp),
|
||||
headerName = "Changelog",
|
||||
headerPadding = 0.dp
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.padding(top = 4.dp),
|
||||
text = changelog,
|
||||
fontSize = 14.sp
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1,105 +0,0 @@
|
|||
package com.vanced.manager.ui.composables
|
||||
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.gestures.detectDragGestures
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.drawscope.DrawScope
|
||||
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||
import androidx.compose.ui.graphics.drawscope.inset
|
||||
import androidx.compose.ui.input.pointer.PointerInputChange
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.graphics.ColorUtils
|
||||
|
||||
//TODO
|
||||
@Composable
|
||||
fun HSLColorPicker(
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val hslColors = floatArrayOf(0f, 1f, 0.5f)
|
||||
val hueColors = getColors(hslColors, length = 360, index = 0) { it }
|
||||
val saturationColors = getColors(hslColors, length = 11, index = 1) { it / 10 }
|
||||
val lightnessColors = getColors(hslColors, length = 11, index = 2) { it / 10 }
|
||||
|
||||
val hueCircle by remember { mutableStateOf(Offset(0f, 0f)) }
|
||||
val saturationCircle by remember { mutableStateOf(Offset(0f, 0f)) }
|
||||
val lightnessCircle by remember { mutableStateOf(Offset(0f, 0f)) }
|
||||
Canvas(modifier = modifier
|
||||
.size(250.dp, 250.dp)
|
||||
.pointerInput(Unit) {
|
||||
detectDragGestures { change: PointerInputChange, dragAmount: Offset ->
|
||||
val (changeX, changeY) = change.position
|
||||
}
|
||||
}
|
||||
) {
|
||||
colorArc(
|
||||
brush = Brush.sweepGradient(hueColors),
|
||||
startAngle = 0f,
|
||||
sweepAngle = 360f,
|
||||
circleOffset = hueCircle
|
||||
)
|
||||
inset(
|
||||
inset = 60f
|
||||
) {
|
||||
colorArc(
|
||||
brush = Brush.linearGradient(
|
||||
colors = saturationColors,
|
||||
start = Offset.Infinite,
|
||||
end = Offset.Zero
|
||||
),
|
||||
startAngle = 100f,
|
||||
sweepAngle = 155f,
|
||||
circleOffset = saturationCircle
|
||||
)
|
||||
colorArc(
|
||||
brush = Brush.linearGradient(lightnessColors),
|
||||
startAngle = 280f,
|
||||
sweepAngle = 155f,
|
||||
circleOffset = lightnessCircle
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun DrawScope.colorArc(
|
||||
brush: Brush,
|
||||
startAngle: Float,
|
||||
sweepAngle: Float,
|
||||
circleOffset: Offset
|
||||
) {
|
||||
drawArc(
|
||||
brush = brush,
|
||||
startAngle = startAngle,
|
||||
sweepAngle = sweepAngle,
|
||||
useCenter = false,
|
||||
style = Stroke(width = 15f)
|
||||
)
|
||||
|
||||
inset(circleOffset.x, circleOffset.y) {
|
||||
drawCircle(
|
||||
brush = brush,
|
||||
radius = 50f
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun getColors(
|
||||
hslColors: FloatArray,
|
||||
length: Int,
|
||||
index: Int,
|
||||
calculate: (Float) -> Float
|
||||
): List<Color> {
|
||||
val colorsCopy = hslColors.copyOf()
|
||||
return List(length) {
|
||||
colorsCopy[index] = calculate(it.toFloat())
|
||||
Color(ColorUtils.HSLToColor(colorsCopy))
|
||||
}
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
package com.vanced.manager.ui.composables
|
||||
|
|
@ -1,111 +0,0 @@
|
|||
package com.vanced.manager.ui.composables
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.wrapContentWidth
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.LinearProgressIndicator
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowForwardIos
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.vanced.manager.downloader.base.BaseDownloader
|
||||
import dev.burnoo.compose.rememberpreference.rememberStringPreference
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
data class InstallationOptionKey(
|
||||
val keyName: String,
|
||||
val keyDefaultValue: String = "",
|
||||
val keyInitialValue: String = keyDefaultValue
|
||||
)
|
||||
|
||||
data class InstallationOption(
|
||||
val title: String,
|
||||
val descriptionKey: InstallationOptionKey,
|
||||
val dialog: @Composable (show: MutableState<Boolean>, preference: MutableState<String>) -> Unit
|
||||
) {
|
||||
|
||||
@Composable
|
||||
fun Content() {
|
||||
val showDialog = remember { mutableStateOf(false) }
|
||||
val preference = rememberStringPreference(
|
||||
keyName = descriptionKey.keyName,
|
||||
defaultValue = descriptionKey.keyDefaultValue,
|
||||
initialValue = descriptionKey.keyInitialValue
|
||||
)
|
||||
ManagerListItem(
|
||||
modifier = Modifier.clickable {
|
||||
showDialog.value = true
|
||||
},
|
||||
title = title,
|
||||
description = preference.value,
|
||||
trailing = {
|
||||
Icon(imageVector = Icons.Default.ArrowForwardIos, contentDescription = null)
|
||||
}
|
||||
)
|
||||
if (showDialog.value) {
|
||||
dialog(showDialog, preference)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AppDownloadDialogButtons(
|
||||
showProgress: MutableState<Boolean>,
|
||||
showDialog: MutableState<Boolean>,
|
||||
downloader: BaseDownloader,
|
||||
coroutineScope: CoroutineScope
|
||||
) {
|
||||
when(showProgress.value) {
|
||||
true -> ManagerThemedButton(onClick = {
|
||||
downloader.cancelDownload()
|
||||
showDialog.value = false
|
||||
showProgress.value = false
|
||||
}) {
|
||||
Text(text = "Cancel")
|
||||
}
|
||||
false -> ManagerThemedButton(onClick = {
|
||||
coroutineScope.launch {
|
||||
showProgress.value = true
|
||||
downloader.download()
|
||||
}
|
||||
}) {
|
||||
Text(text = "Download")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AppDownloadDialogProgress(
|
||||
progress: Float,
|
||||
file: String,
|
||||
showProgress: Boolean,
|
||||
installing: Boolean
|
||||
) {
|
||||
if (showProgress) {
|
||||
when (installing) {
|
||||
true -> LinearProgressIndicator(color = managerAccentColor())
|
||||
false -> LinearProgressIndicator(
|
||||
progress = progress,
|
||||
color = managerAccentColor()
|
||||
)
|
||||
}
|
||||
Row {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.wrapContentWidth(Alignment.Start),
|
||||
text = "Downloading $file"
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.wrapContentWidth(Alignment.End),
|
||||
text = "$progress"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
package com.vanced.manager.ui.composables
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.em
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.vanced.manager.ui.theme.managerAccentColor
|
||||
|
||||
@ExperimentalStdlibApi
|
||||
@Composable
|
||||
fun HeaderCard(
|
||||
headerName: String,
|
||||
headerPadding: Dp = 11.dp,
|
||||
content: @Composable ColumnScope.() -> Unit
|
||||
) {
|
||||
ManagerCard(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
) {
|
||||
Column {
|
||||
Spacer(modifier = Modifier.size(height = 4.dp, width = 0.dp))
|
||||
HeaderView(
|
||||
headerName = headerName,
|
||||
content = content,
|
||||
headerPadding = headerPadding
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun HeaderView(
|
||||
modifier: Modifier = Modifier,
|
||||
headerName: String,
|
||||
headerPadding: Dp = 11.dp,
|
||||
content: @Composable ColumnScope.() -> Unit
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier
|
||||
) {
|
||||
Header(headerName = headerName, headerPadding = headerPadding)
|
||||
content()
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
@Composable
|
||||
fun Header(
|
||||
headerName: String,
|
||||
headerPadding: Dp = 11.dp,
|
||||
) {
|
||||
Text(
|
||||
headerName.uppercase(),
|
||||
letterSpacing = 0.15.em,
|
||||
color = MaterialTheme.colors.managerAccentColor,
|
||||
modifier = Modifier.padding(horizontal = headerPadding),
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 13.sp
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun IconButton(
|
||||
icon: ImageVector,
|
||||
contentDescription: String,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
val interactionSource = remember { MutableInteractionSource() }
|
||||
val buttonSize = 36.dp
|
||||
val enabled = true
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.clickable(
|
||||
onClick = onClick,
|
||||
enabled = enabled,
|
||||
role = Role.Button,
|
||||
interactionSource = interactionSource,
|
||||
indication = rememberRipple(bounded = false, radius = 18.dp)
|
||||
)
|
||||
.size(buttonSize),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
val contentAlpha = if (enabled) LocalContentAlpha.current else ContentAlpha.disabled
|
||||
CompositionLocalProvider(LocalContentAlpha provides contentAlpha) {
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = contentDescription
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun RadiobuttonItem(
|
||||
currentSelection: MutableState<String?>,
|
||||
text: String,
|
||||
preferenceValue: String,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
currentSelection.value = preferenceValue
|
||||
}
|
||||
.padding(horizontal = 8.dp, vertical = 6.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
RadioButton(
|
||||
selected = preferenceValue == currentSelection.value,
|
||||
onClick = {
|
||||
currentSelection.value = preferenceValue
|
||||
},
|
||||
colors = RadioButtonDefaults.colors(
|
||||
MaterialTheme.colors.managerAccentColor,
|
||||
Color.LightGray
|
||||
)
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.padding(start = 4.dp),
|
||||
text = text,
|
||||
color = managerTextColor(),
|
||||
fontSize = 18.sp
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
package com.vanced.manager.ui.composables
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.browser.customtabs.CustomTabsIntent
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.LocalContentColor
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun LinkCard(
|
||||
@DrawableRes icon: Int,
|
||||
title: String,
|
||||
link: String
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val customTabs = remember { CustomTabsIntent.Builder().build() }
|
||||
ManagerCard(
|
||||
modifier = Modifier
|
||||
.clip(RoundedCornerShape(12.dp))
|
||||
.clickable {
|
||||
customTabs.launchUrl(context, Uri.parse(link))
|
||||
}
|
||||
.size(width = 120.dp, height = 100.dp)
|
||||
) {
|
||||
CompositionLocalProvider(LocalContentColor provides managerTextColor()) {
|
||||
Column(
|
||||
modifier = Modifier.padding(all = 16.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.size(36.dp),
|
||||
painter = painterResource(id = icon),
|
||||
contentDescription = null,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Text(
|
||||
text = title,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun <T> ScrollableLinkRow(
|
||||
items: List<T>,
|
||||
content: @Composable (T) -> Unit
|
||||
) {
|
||||
val state = rememberLazyListState()
|
||||
LazyRow(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
state = state
|
||||
) {
|
||||
itemsIndexed(items) { index, item ->
|
||||
content(item)
|
||||
if (index < items.size - 1) {
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,229 +0,0 @@
|
|||
package com.vanced.manager.ui.composables
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListScope
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.graphics.luminance
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import com.vanced.manager.ui.theme.cardColor
|
||||
import com.vanced.manager.ui.theme.managerAccentColor
|
||||
import java.util.*
|
||||
|
||||
@Composable
|
||||
fun managerShape() = RoundedCornerShape(12.dp)
|
||||
|
||||
@Composable
|
||||
fun ManagerCard(
|
||||
modifier: Modifier = Modifier,
|
||||
shape: Shape = managerShape(),
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
Card(
|
||||
modifier = modifier,
|
||||
shape = shape,
|
||||
backgroundColor = managerCardColor(),
|
||||
elevation = 0.dp,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ManagerThemedButton(
|
||||
modifier: Modifier = Modifier,
|
||||
onClick: () -> Unit,
|
||||
content: @Composable RowScope.() -> Unit
|
||||
) {
|
||||
val accentColor = managerAccentColor()
|
||||
Button(
|
||||
modifier = modifier,
|
||||
onClick = onClick,
|
||||
shape = managerShape(),
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
backgroundColor = managerAccentColor()
|
||||
),
|
||||
elevation = ButtonDefaults.elevation(0.dp)
|
||||
) {
|
||||
CompositionLocalProvider(LocalContentColor provides if (accentColor.luminance() > 0.7) Color.Black else Color.White) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ManagerDialog(
|
||||
title: String,
|
||||
isShown: MutableState<Boolean>,
|
||||
buttons: @Composable ColumnScope.() -> Unit,
|
||||
content: @Composable ColumnScope.() -> Unit,
|
||||
) {
|
||||
Dialog(
|
||||
onDismissRequest = { isShown.value = false },
|
||||
content = {
|
||||
ManagerCard {
|
||||
Column(
|
||||
modifier = Modifier.padding(all = 8.dp)
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
text = title,
|
||||
letterSpacing = 2.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = managerTextColor().copy(alpha = 0.8f),
|
||||
fontSize = 24.sp,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
Spacer(Modifier.height(8.dp))
|
||||
content()
|
||||
Spacer(Modifier.height(8.dp))
|
||||
buttons()
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ManagerSurface(
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
color = managerSurfaceColor(),
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ManagerLazyColumn(
|
||||
content: LazyListScope.() -> Unit
|
||||
) {
|
||||
LazyColumn(
|
||||
contentPadding = PaddingValues(12.dp),
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ManagerScrollableColumn(
|
||||
content: @Composable ColumnScope.() -> Unit
|
||||
) {
|
||||
val scrollState = rememberScrollState()
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.verticalScroll(scrollState)
|
||||
.padding(12.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ManagerDropdownMenuItem(
|
||||
isMenuExpanded: MutableState<Boolean>,
|
||||
title: String,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
onClick = {
|
||||
isMenuExpanded.value = false
|
||||
onClick()
|
||||
},
|
||||
) {
|
||||
Text(text = title)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun animateManagerColor(
|
||||
color: Color
|
||||
): State<Color> {
|
||||
return animateColorAsState(
|
||||
targetValue = color,
|
||||
animationSpec = tween(500)
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun HomeHeaderView(
|
||||
modifier: Modifier = Modifier,
|
||||
headerName: String,
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
HeaderView(
|
||||
modifier = modifier,
|
||||
headerName = headerName,
|
||||
headerPadding = 4.dp
|
||||
) {
|
||||
ManagerHomeHeaderSeparator()
|
||||
content()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun managerAnimatedColor(
|
||||
color: Color
|
||||
): Color {
|
||||
val animColor by animateColorAsState(
|
||||
targetValue = color,
|
||||
animationSpec = tween(500)
|
||||
)
|
||||
return animColor
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun managerAnimatedText(
|
||||
@StringRes stringId: Int
|
||||
): String {
|
||||
var text by remember { mutableStateOf("") }
|
||||
CompositionLocalProvider(
|
||||
LocalConfiguration provides LocalConfiguration.current.apply {
|
||||
setLocale(Locale("ru"))
|
||||
}
|
||||
) {
|
||||
text = stringResource(id = stringId)
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ManagerCardSeparator() {
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ManagerHomeHeaderSeparator() {
|
||||
Spacer(modifier = Modifier.height(4.dp))
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun managerTextColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.onSurface)
|
||||
|
||||
@Composable
|
||||
fun managerSurfaceColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.surface)
|
||||
|
||||
@Composable
|
||||
fun managerCardColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.cardColor)
|
||||
|
||||
@Composable
|
||||
fun managerAccentColor(): Color = MaterialTheme.colors.managerAccentColor
|
||||
|
||||
@Composable
|
||||
fun animatedManagerAccentColor(): Color = managerAnimatedColor(color = MaterialTheme.colors.managerAccentColor)
|
|
@ -1,95 +0,0 @@
|
|||
package com.vanced.manager.ui.composables
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
||||
const val defaultPadding = 12
|
||||
|
||||
@Composable
|
||||
fun ManagerListItem(
|
||||
modifier: Modifier = Modifier,
|
||||
title: String,
|
||||
description: String? = null,
|
||||
startPadding: Dp = defaultPadding.dp,
|
||||
endPadding: Dp = defaultPadding.dp,
|
||||
topPadding: Dp = defaultPadding.dp,
|
||||
bottomPadding: Dp = defaultPadding.dp,
|
||||
icon: @Composable (() -> Unit)? = null,
|
||||
trailing: @Composable (() -> Unit)? = null
|
||||
) {
|
||||
val typography = MaterialTheme.typography
|
||||
val textColor by animateManagerColor(color = MaterialTheme.colors.onBackground)
|
||||
Box(
|
||||
modifier = modifier
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(top = topPadding, bottom = bottomPadding)
|
||||
) {
|
||||
if (icon != null) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(start = startPadding)
|
||||
.align(Alignment.CenterVertically)
|
||||
) {
|
||||
icon()
|
||||
}
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(
|
||||
start = startPadding,
|
||||
end = endPadding
|
||||
)
|
||||
.weight(1f)
|
||||
.align(Alignment.CenterVertically)
|
||||
) {
|
||||
if (description == null) {
|
||||
Spacer(modifier = Modifier.size(6.dp))
|
||||
}
|
||||
Text(
|
||||
text = title,
|
||||
fontSize = 16.sp,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
style = typography.subtitle1,
|
||||
color = textColor
|
||||
)
|
||||
if (description != null) {
|
||||
CompositionLocalProvider(
|
||||
LocalContentAlpha provides ContentAlpha.medium,
|
||||
LocalContentColor provides textColor
|
||||
) {
|
||||
Text(
|
||||
text = description,
|
||||
fontSize = 12.sp,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
}
|
||||
if (description == null) {
|
||||
Spacer(modifier = Modifier.size(6.dp))
|
||||
}
|
||||
|
||||
}
|
||||
if (trailing != null) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(end = endPadding)
|
||||
.align(Alignment.CenterVertically)
|
||||
) {
|
||||
CompositionLocalProvider(LocalContentColor provides textColor) {
|
||||
trailing()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,148 +0,0 @@
|
|||
package com.vanced.manager.ui.composables
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.content.edit
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.vanced.manager.ui.preferences.RadioButtonPreference
|
||||
|
||||
@Composable
|
||||
fun SwitchPreference(
|
||||
preferenceTitle: String,
|
||||
preferenceDescription: String?,
|
||||
preferenceKey: String,
|
||||
defaultValue: Boolean = true,
|
||||
onCheckedChange: (isChecked: Boolean) -> Unit = {}
|
||||
) {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(LocalContext.current)
|
||||
var isChecked by remember { mutableStateOf(prefs.getBoolean(preferenceKey, defaultValue)) }
|
||||
|
||||
fun savePreference() {
|
||||
isChecked = !isChecked
|
||||
prefs.edit {
|
||||
putBoolean(preferenceKey, isChecked)
|
||||
}
|
||||
onCheckedChange(isChecked)
|
||||
}
|
||||
|
||||
Preference(
|
||||
preferenceTitle = preferenceTitle,
|
||||
preferenceDescription = preferenceDescription,
|
||||
onClick = { savePreference() },
|
||||
trailing = {
|
||||
Switch(
|
||||
checked = isChecked,
|
||||
onCheckedChange = { savePreference() },
|
||||
colors = SwitchDefaults.colors(
|
||||
checkedThumbColor = managerAccentColor(),
|
||||
checkedTrackColor = managerAccentColor(),
|
||||
uncheckedThumbColor = Color.Gray,
|
||||
uncheckedTrackColor = Color.Gray
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Preference(
|
||||
preferenceTitle: String,
|
||||
preferenceDescription: String? = null,
|
||||
trailing: @Composable (() -> Unit)? = null,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
ManagerListItem(
|
||||
modifier = Modifier.clickable(onClick = onClick),
|
||||
title = preferenceTitle,
|
||||
description = preferenceDescription,
|
||||
trailing = trailing,
|
||||
bottomPadding = 4.dp,
|
||||
topPadding = 4.dp
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DialogPreference(
|
||||
preferenceTitle: String,
|
||||
preferenceDescription: String? = null,
|
||||
trailing: @Composable (() -> Unit)? = null,
|
||||
buttons: @Composable ColumnScope.(isShown: MutableState<Boolean>) -> Unit,
|
||||
content: @Composable ColumnScope.() -> Unit
|
||||
) {
|
||||
val isShown = remember { mutableStateOf(false) }
|
||||
Preference(
|
||||
preferenceTitle = preferenceTitle,
|
||||
preferenceDescription = preferenceDescription,
|
||||
trailing = trailing
|
||||
) {
|
||||
isShown.value = true
|
||||
}
|
||||
if (isShown.value) {
|
||||
ManagerDialog(
|
||||
title = preferenceTitle,
|
||||
isShown = isShown,
|
||||
buttons = { buttons(isShown) },
|
||||
content = content
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DialogRadioButtonPreference(
|
||||
preferenceTitle: String,
|
||||
preferenceKey: String,
|
||||
defaultValue: String,
|
||||
preferenceDescription: String? = null,
|
||||
trailing: @Composable (() -> Unit)? = null,
|
||||
buttons: List<RadioButtonPreference>,
|
||||
onSave: (newPref: String?) -> Unit = {}
|
||||
) {
|
||||
val prefs = PreferenceManager.getDefaultSharedPreferences(LocalContext.current)
|
||||
val currentSelection = remember { mutableStateOf(prefs.getString(preferenceKey, defaultValue)) }
|
||||
DialogPreference(
|
||||
preferenceTitle = preferenceTitle,
|
||||
preferenceDescription = preferenceDescription,
|
||||
trailing = trailing,
|
||||
buttons = { isShown ->
|
||||
ManagerThemedButton(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onClick = {
|
||||
prefs.edit {
|
||||
putString(preferenceKey, currentSelection.value)
|
||||
}
|
||||
onSave(currentSelection.value)
|
||||
isShown.value = false
|
||||
}
|
||||
) {
|
||||
Text(text = "Save")
|
||||
}
|
||||
}
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.weight(
|
||||
weight = 1f,
|
||||
fill = false
|
||||
)
|
||||
|
||||
) {
|
||||
items(buttons) { button ->
|
||||
val (title, key) = button
|
||||
RadiobuttonItem(
|
||||
currentSelection = currentSelection,
|
||||
text = title,
|
||||
preferenceValue = key
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,193 +1,205 @@
|
|||
package com.vanced.manager.ui.layouts
|
||||
|
||||
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Circle
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.vanced.manager.ui.composables.HeaderCard
|
||||
import com.vanced.manager.ui.composables.ManagerCard
|
||||
import com.vanced.manager.ui.composables.ManagerLazyColumn
|
||||
import com.vanced.manager.ui.composables.managerTextColor
|
||||
import com.vanced.manager.ui.theme.ComposeTestTheme
|
||||
import com.vanced.manager.ui.theme.vancedBlue
|
||||
import com.vanced.manager.ui.theme.vancedRed
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import com.vanced.manager.R
|
||||
import com.vanced.manager.ui.components.card.ManagerLinkCard
|
||||
import com.vanced.manager.ui.components.card.ManagerThemedCard
|
||||
import com.vanced.manager.ui.components.layout.ManagerScrollableColumn
|
||||
import com.vanced.manager.ui.components.layout.ScrollableItemRow
|
||||
import com.vanced.manager.ui.components.lifecycle.managerString
|
||||
import com.vanced.manager.ui.components.list.ManagerListItem
|
||||
import com.vanced.manager.ui.components.text.ManagerText
|
||||
import com.vanced.manager.ui.widgets.layout.CategoryLayout
|
||||
|
||||
data class Person(
|
||||
val name: String,
|
||||
val contribution: String
|
||||
)
|
||||
|
||||
data class Credit(
|
||||
val creditName: String,
|
||||
val persons: List<String>
|
||||
@StringRes val nameId: Int,
|
||||
val persons: List<Person>
|
||||
)
|
||||
|
||||
data class Source(
|
||||
val sourceLink: String
|
||||
@StringRes val nameId: Int,
|
||||
@DrawableRes val iconId: Int,
|
||||
val link: String
|
||||
)
|
||||
|
||||
private val credits = listOf(
|
||||
Credit(
|
||||
creditName = "Vanced Team",
|
||||
nameId = R.string.about_category_credits_vanced_team,
|
||||
persons = listOf(
|
||||
"xfileFIN",
|
||||
"ZaneZam",
|
||||
"Laura Almeida",
|
||||
"KevinX8"
|
||||
Person(
|
||||
name = "xfileFIN",
|
||||
contribution = "Mods, Theming, Support"
|
||||
),
|
||||
Person(
|
||||
name = "Laura",
|
||||
contribution = "Theming, Support"
|
||||
),
|
||||
Person(
|
||||
name = "ZaneZam",
|
||||
contribution = "Publishing, Support"
|
||||
),
|
||||
Person(
|
||||
name = "KevinX8",
|
||||
contribution = "Overlord, Support"
|
||||
)
|
||||
)
|
||||
),
|
||||
Credit(
|
||||
creditName = "Manager Team",
|
||||
nameId = R.string.about_category_credits_manager_devs,
|
||||
persons = listOf(
|
||||
"Xinto",
|
||||
"Koopah",
|
||||
"Logan"
|
||||
Person(
|
||||
name = "Xinto",
|
||||
contribution = "Manager Core"
|
||||
),
|
||||
Person(
|
||||
name = "Koopah",
|
||||
contribution = "Root installer"
|
||||
),
|
||||
Person(
|
||||
name = "Logan",
|
||||
contribution = "UI"
|
||||
),
|
||||
Person(
|
||||
name = "HaliksaR",
|
||||
contribution = "Refactoring, UI"
|
||||
),
|
||||
)
|
||||
),
|
||||
Credit(
|
||||
creditName = "Other Contributors",
|
||||
nameId = R.string.about_category_credits_other,
|
||||
persons = listOf(
|
||||
"bhatVikrant",
|
||||
"bawm",
|
||||
"AioiLight",
|
||||
"HaliksaR"
|
||||
Person(
|
||||
name = "bhatVikrant",
|
||||
contribution = "Website"
|
||||
),
|
||||
Person(
|
||||
name = "bawm",
|
||||
contribution = "Sponsorblock"
|
||||
),
|
||||
Person(
|
||||
name = "cane",
|
||||
contribution = "Sponsorblock"
|
||||
),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
private val sources = listOf(
|
||||
Source(
|
||||
""
|
||||
nameId = R.string.about_sources_source_code,
|
||||
iconId = R.drawable.ic_github,
|
||||
link = "https://github.com/YTVanced/VancedManager"
|
||||
),
|
||||
Source(
|
||||
""
|
||||
nameId = R.string.about_sources_license,
|
||||
iconId = R.drawable.ic_round_assignment_24,
|
||||
link = "https://raw.githubusercontent.com/YTVanced/VancedManager/dev/LICENSE"
|
||||
)
|
||||
)
|
||||
|
||||
@ExperimentalStdlibApi
|
||||
@Composable
|
||||
@Preview(
|
||||
showSystemUi = true,
|
||||
uiMode = UI_MODE_NIGHT_YES
|
||||
)
|
||||
fun AboutDarkMode() {
|
||||
ComposeTestTheme {
|
||||
AboutLayout()
|
||||
}
|
||||
}
|
||||
|
||||
@ExperimentalStdlibApi
|
||||
@Composable
|
||||
@Preview(
|
||||
showSystemUi = true
|
||||
)
|
||||
fun AboutLightMode() {
|
||||
MaterialTheme {
|
||||
AboutLayout()
|
||||
}
|
||||
}
|
||||
|
||||
@ExperimentalStdlibApi
|
||||
@Composable
|
||||
fun AboutLayout() {
|
||||
ManagerLazyColumn {
|
||||
item {
|
||||
ManagerCard {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.background(
|
||||
Brush.horizontalGradient(
|
||||
colors = listOf(
|
||||
vancedBlue,
|
||||
vancedRed
|
||||
),
|
||||
)
|
||||
)
|
||||
) {
|
||||
Spacer(modifier = Modifier.size(width = 0.dp, height = 8.dp))
|
||||
Text(
|
||||
text = "Vanced Manager",
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
fontSize = 30.sp,
|
||||
color = Color.White
|
||||
)
|
||||
Text(
|
||||
text = buildAnnotatedString {
|
||||
append("Re")
|
||||
withStyle(style = SpanStyle(Color(0xFFBBB529))) {
|
||||
append("@Compose")
|
||||
ManagerScrollableColumn(
|
||||
itemSpacing = 12.dp
|
||||
) {
|
||||
AboutManagerCard()
|
||||
credits.fastForEach { credit ->
|
||||
CategoryLayout(
|
||||
categoryNameId = credit.nameId,
|
||||
categoryNameSpacing = 4.dp
|
||||
) {
|
||||
Column {
|
||||
credit.persons.fastForEach { person ->
|
||||
ManagerListItem(
|
||||
title = {
|
||||
ManagerText(
|
||||
text = person.name,
|
||||
textStyle = MaterialTheme.typography.h6
|
||||
)
|
||||
},
|
||||
description = {
|
||||
ManagerText(
|
||||
text = person.contribution,
|
||||
textStyle = MaterialTheme.typography.subtitle1
|
||||
)
|
||||
}
|
||||
append("d")
|
||||
},
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
fontSize = 16.sp,
|
||||
color = Color.White
|
||||
)
|
||||
Spacer(modifier = Modifier.size(width = 0.dp, height = 8.dp))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
items(credits) { credit ->
|
||||
Spacer(modifier = Modifier.size(width = 0.dp, height = 12.dp))
|
||||
CreditsCard(creditName = credit.creditName, persons = credit.persons)
|
||||
}
|
||||
|
||||
item {
|
||||
Spacer(modifier = Modifier.size(width = 0.dp, height = 12.dp))
|
||||
HeaderCard(
|
||||
headerName = "Sources"
|
||||
) {
|
||||
Row(modifier = Modifier.fillMaxWidth()) {
|
||||
sources.forEach { _ ->
|
||||
Box(
|
||||
modifier = Modifier.weight(1f),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(imageVector = Icons.Default.Circle, contentDescription = null, modifier = Modifier.size(36.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.size(8.dp))
|
||||
CategoryLayout(categoryNameId = R.string.about_category_sources) {
|
||||
ScrollableItemRow(items = sources) { source ->
|
||||
ManagerLinkCard(
|
||||
title = managerString(source.nameId),
|
||||
icon = source.iconId,
|
||||
link = source.link
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@ExperimentalStdlibApi
|
||||
fun CreditsCard(
|
||||
creditName: String,
|
||||
persons: List<String>
|
||||
) {
|
||||
HeaderCard(
|
||||
headerName = creditName
|
||||
) {
|
||||
CompositionLocalProvider(
|
||||
LocalContentAlpha provides ContentAlpha.medium,
|
||||
LocalContentColor provides managerTextColor()
|
||||
fun AboutManagerCard() {
|
||||
ManagerThemedCard {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
// .clip(managerShape())
|
||||
// .background(
|
||||
// Brush.horizontalGradient(
|
||||
// colors = listOf(
|
||||
// vancedBlue,
|
||||
// vancedRed
|
||||
// )
|
||||
// )
|
||||
// )
|
||||
) {
|
||||
Text(
|
||||
text = persons.joinToString("\n"),
|
||||
text = "Vanced Manager",
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 12.dp),
|
||||
fontSize = 13.sp
|
||||
.padding(top = 8.dp),
|
||||
fontSize = 30.sp,
|
||||
color = Color.White
|
||||
)
|
||||
Text(
|
||||
text = buildAnnotatedString {
|
||||
append("Re")
|
||||
withStyle(style = SpanStyle(Color(0xFFBBB529))) {
|
||||
append("@Compose")
|
||||
}
|
||||
append("d")
|
||||
},
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(bottom = 8.dp),
|
||||
fontSize = 16.sp,
|
||||
color = Color.White
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.size(width = 0.dp, height = 2.dp))
|
||||
}
|
||||
}
|
|
@ -1,28 +1,31 @@
|
|||
package com.vanced.manager.ui.layouts
|
||||
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.livedata.observeAsState
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEachIndexed
|
||||
import androidx.compose.ui.util.fastForEach
|
||||
import com.google.accompanist.swiperefresh.SwipeRefresh
|
||||
import com.google.accompanist.swiperefresh.SwipeRefreshIndicator
|
||||
import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
|
||||
import com.vanced.manager.R
|
||||
import com.vanced.manager.domain.model.App
|
||||
import com.vanced.manager.ui.composables.*
|
||||
import com.vanced.manager.ui.components.*
|
||||
import com.vanced.manager.ui.components.card.ManagerLinkCard
|
||||
import com.vanced.manager.ui.components.color.managerAccentColor
|
||||
import com.vanced.manager.ui.components.layout.ManagerScrollableColumn
|
||||
import com.vanced.manager.ui.components.layout.ScrollableItemRow
|
||||
import com.vanced.manager.ui.utils.defaultContentPaddingVertical
|
||||
import com.vanced.manager.ui.viewmodel.HomeViewModel
|
||||
import com.vanced.manager.ui.widgets.home.apps.card.AppCard
|
||||
import com.vanced.manager.ui.widgets.layout.CategoryLayout
|
||||
import com.vanced.manager.util.socialMedia
|
||||
import com.vanced.manager.util.sponsors
|
||||
import org.koin.androidx.compose.getViewModel
|
||||
|
||||
@ExperimentalAnimationApi
|
||||
@Composable
|
||||
@Preview
|
||||
fun HomeLayout() {
|
||||
|
@ -41,39 +44,38 @@ fun HomeLayout() {
|
|||
)
|
||||
}
|
||||
) {
|
||||
ManagerScrollableColumn {
|
||||
HomeHeaderView(headerName = "Apps") {
|
||||
viewModel.apps.fastForEachIndexed { index, app ->
|
||||
val rememberedApp by app.observeAsState(initial = App())
|
||||
AppCard(rememberedApp)
|
||||
if (index != viewModel.apps.size - 1) {
|
||||
Spacer(modifier = Modifier.size(height = 8.dp, width = 0.dp))
|
||||
ManagerScrollableColumn(
|
||||
contentPaddingVertical = defaultContentPaddingVertical,
|
||||
itemSpacing = 18.dp
|
||||
) {
|
||||
CategoryLayout(
|
||||
categoryNameId = R.string.home_category_apps,
|
||||
contentPaddingHorizontal = 0.dp
|
||||
) {
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
viewModel.apps.fastForEach { app ->
|
||||
val observedApp by app.observeAsState(initial = App())
|
||||
AppCard(observedApp, isFetching)
|
||||
}
|
||||
}
|
||||
}
|
||||
ManagerCardSeparator()
|
||||
HomeHeaderView(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
headerName = "Support Us"
|
||||
) {
|
||||
ScrollableLinkRow(items = sponsors) { sponsor ->
|
||||
LinkCard(
|
||||
icon = R.drawable.ic_android_black_24dp,
|
||||
CategoryLayout(categoryNameId = R.string.home_category_support_us) {
|
||||
ScrollableItemRow(items = sponsors) { sponsor ->
|
||||
ManagerLinkCard(
|
||||
icon = sponsor.icon,
|
||||
title = sponsor.title,
|
||||
link = "https://m.youtube.com"
|
||||
link = sponsor.link
|
||||
)
|
||||
}
|
||||
}
|
||||
ManagerCardSeparator()
|
||||
HomeHeaderView(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
headerName = "Social media"
|
||||
) {
|
||||
ScrollableLinkRow(items = socialMedia) { socialMedia ->
|
||||
LinkCard(
|
||||
icon = R.drawable.ic_android_black_24dp,
|
||||
CategoryLayout(categoryNameId = R.string.home_category_social_media) {
|
||||
ScrollableItemRow(items = socialMedia) { socialMedia ->
|
||||
ManagerLinkCard(
|
||||
icon = socialMedia.icon,
|
||||
title = socialMedia.title,
|
||||
link = "https://m.youtube.com"
|
||||
link = socialMedia.link
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@ import androidx.compose.material.icons.Icons
|
|||
import androidx.compose.material.icons.filled.Share
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.vanced.manager.ui.composables.ManagerLazyColumn
|
||||
import com.vanced.manager.ui.composables.managerAccentColor
|
||||
import com.vanced.manager.ui.composables.managerSurfaceColor
|
||||
import com.vanced.manager.ui.components.color.managerAccentColor
|
||||
import com.vanced.manager.ui.components.color.managerSurfaceColor
|
||||
import com.vanced.manager.ui.components.layout.ManagerLazyColumn
|
||||
import com.vanced.manager.util.logs
|
||||
|
||||
@Composable
|
||||
|
|
|
@ -1,13 +1,23 @@
|
|||
package com.vanced.manager.ui.layouts
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vanced.manager.ui.composables.*
|
||||
import androidx.datastore.preferences.core.booleanPreferencesKey
|
||||
import com.vanced.manager.R
|
||||
import com.vanced.manager.ui.components.*
|
||||
import com.vanced.manager.ui.components.layout.ManagerScrollableColumn
|
||||
import com.vanced.manager.ui.components.preference.CheckboxPreference
|
||||
import com.vanced.manager.ui.components.preference.Preference
|
||||
import com.vanced.manager.ui.components.preference.RadiobuttonDialogPreference
|
||||
import com.vanced.manager.ui.preferences.RadioButtonPreference
|
||||
import com.vanced.manager.ui.theme.managerTheme
|
||||
import com.vanced.manager.ui.preferences.holder.managerVariantPref
|
||||
import com.vanced.manager.ui.preferences.holder.useCustomTabsPref
|
||||
import com.vanced.manager.ui.preferences.managerBooleanPreference
|
||||
import com.vanced.manager.ui.utils.defaultContentPaddingVertical
|
||||
import com.vanced.manager.ui.widgets.layout.CategoryLayout
|
||||
import com.vanced.manager.ui.widgets.settings.SettingsAccentColorItem
|
||||
import com.vanced.manager.ui.widgets.settings.ThemeSettingsItem
|
||||
|
||||
data class NotificationPrefModel(
|
||||
val app: String,
|
||||
|
@ -29,89 +39,66 @@ private val notificationApps = arrayOf(
|
|||
)
|
||||
)
|
||||
|
||||
@ExperimentalStdlibApi
|
||||
@ExperimentalMaterialApi
|
||||
@Composable
|
||||
fun SettingsLayout() {
|
||||
var showDialog by remember { mutableStateOf(false) }
|
||||
ManagerScrollableColumn {
|
||||
HeaderCard(headerName = "Behaviour") {
|
||||
SwitchPreference(
|
||||
preferenceTitle = "Use Custom Tabs",
|
||||
preferenceDescription = "Links will open in chrome custom tabs",
|
||||
preferenceKey = "use_custom_tabs"
|
||||
)
|
||||
notificationApps.forEach {
|
||||
with (it) {
|
||||
SwitchPreference(
|
||||
preferenceTitle = "$app Push Notifications",
|
||||
preferenceDescription = "Receive push notifications when an update for $app is released",
|
||||
preferenceKey = "${prefKey}_notifications"
|
||||
)
|
||||
ManagerScrollableColumn(
|
||||
contentPaddingVertical = defaultContentPaddingVertical,
|
||||
itemSpacing = 12.dp
|
||||
) {
|
||||
CategoryLayout(
|
||||
categoryNameId = R.string.settings_category_behaviour,
|
||||
contentPaddingHorizontal = 0.dp,
|
||||
categoryNameSpacing = 4.dp
|
||||
) {
|
||||
Column {
|
||||
CheckboxPreference(
|
||||
preferenceTitle = R.string.settings_preference_use_custom_tabs_title,
|
||||
preferenceDescription = R.string.settings_preference_use_custom_tabs_summary,
|
||||
preference = useCustomTabsPref
|
||||
)
|
||||
notificationApps.forEach {
|
||||
with(it) {
|
||||
CheckboxPreference(
|
||||
preferenceTitle = "$app Push Notifications",
|
||||
preferenceDescription = "Receive push notifications when an update for $app is released",
|
||||
preference = managerBooleanPreference(
|
||||
key = booleanPreferencesKey("${prefKey}_notifications"),
|
||||
defaultValue = true
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Preference(
|
||||
preferenceTitle = "Variant",
|
||||
preferenceDescription = "nonroot",
|
||||
onClick = {}
|
||||
)
|
||||
Preference(
|
||||
preferenceTitle = "Clear downloaded files",
|
||||
onClick = {}
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.size(12.dp))
|
||||
HeaderCard(headerName = "Appearance") {
|
||||
Preference(
|
||||
preferenceTitle = "Accent Color",
|
||||
onClick = {
|
||||
showDialog = true
|
||||
}
|
||||
)
|
||||
DialogRadioButtonPreference(
|
||||
preferenceTitle = "Theme",
|
||||
preferenceKey = "manager_theme",
|
||||
defaultValue = "Light",
|
||||
buttons = listOf(
|
||||
RadioButtonPreference(
|
||||
title = "Light Theme",
|
||||
preferenceValue = "Light"
|
||||
),
|
||||
RadioButtonPreference(
|
||||
title = "Dark Theme",
|
||||
preferenceValue = "Dark"
|
||||
),
|
||||
RadioButtonPreference(
|
||||
title = "System Default",
|
||||
preferenceValue = "System Default"
|
||||
RadiobuttonDialogPreference(
|
||||
preferenceTitle = R.string.settings_preference_variant_title,
|
||||
preference = managerVariantPref,
|
||||
buttons = listOf(
|
||||
RadioButtonPreference(
|
||||
title = "nonroot",
|
||||
key = "nonroot"
|
||||
),
|
||||
RadioButtonPreference(
|
||||
title = "root",
|
||||
key = "root"
|
||||
),
|
||||
)
|
||||
)
|
||||
) {
|
||||
managerTheme = it
|
||||
Preference(
|
||||
preferenceTitleId = R.string.settings_preference_clear_files_title,
|
||||
preferenceDescriptionId = null,
|
||||
onClick = {}
|
||||
)
|
||||
}
|
||||
}
|
||||
CategoryLayout(
|
||||
categoryNameId = R.string.settings_category_appearance,
|
||||
contentPaddingHorizontal = 0.dp,
|
||||
categoryNameSpacing = 4.dp
|
||||
) {
|
||||
Column {
|
||||
SettingsAccentColorItem()
|
||||
ThemeSettingsItem()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (showDialog) {
|
||||
AlertDialog(
|
||||
onDismissRequest = { showDialog = false },
|
||||
text = {
|
||||
HSLColorPicker()
|
||||
// AndroidView(
|
||||
// factory = {
|
||||
// HSLColorPicker(it)
|
||||
// },
|
||||
// update = { view ->
|
||||
// view.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 800)
|
||||
// view.setColorSelectionListener(object : SimpleColorSelectionListener() {
|
||||
// override fun onColorSelected(color: Int) {
|
||||
// accentColorInt = color
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// )
|
||||
},
|
||||
buttons = {}
|
||||
)
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package com.vanced.manager.ui.preferences
|
||||
|
||||
data class CheckboxPreference(
|
||||
val title: String,
|
||||
val key: String,
|
||||
)
|
|
@ -0,0 +1,69 @@
|
|||
package com.vanced.manager.ui.preferences
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.datastore.core.DataStore
|
||||
import androidx.datastore.preferences.core.Preferences
|
||||
import androidx.datastore.preferences.core.edit
|
||||
import kotlinx.coroutines.flow.map
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class ManagerPreference<T>(
|
||||
val key: Preferences.Key<T>,
|
||||
val defaultValue: T,
|
||||
) : KoinComponent {
|
||||
|
||||
private val dataStore: DataStore<Preferences> by inject()
|
||||
|
||||
private val _value = mutableStateOf(defaultValue)
|
||||
val value: State<T> = _value
|
||||
|
||||
@Composable
|
||||
fun rememberValue() = remember { value }
|
||||
|
||||
operator fun getValue(thisRef: Any?, property: KProperty<*>) = value.value
|
||||
|
||||
suspend fun save(newValue: T) {
|
||||
_value.value = newValue
|
||||
dataStore.edit {
|
||||
it[key] = value.value
|
||||
}
|
||||
}
|
||||
|
||||
//It's Chewsday innit - © Bri'ish ppl
|
||||
init {
|
||||
dataStore.data.map {
|
||||
_value.value = it[key] ?: defaultValue
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun managerStringPreference(
|
||||
key: Preferences.Key<String>,
|
||||
defaultValue: String = ""
|
||||
) = ManagerPreference(key, defaultValue)
|
||||
|
||||
fun managerStringSetPreference(
|
||||
key: Preferences.Key<Set<String>>,
|
||||
defaultValue: Set<String> = setOf()
|
||||
) = ManagerPreference(key, defaultValue)
|
||||
|
||||
fun managerBooleanPreference(
|
||||
key: Preferences.Key<Boolean>,
|
||||
defaultValue: Boolean = false
|
||||
) = ManagerPreference(key, defaultValue)
|
||||
|
||||
fun managerIntPreference(
|
||||
key: Preferences.Key<Int>,
|
||||
defaultValue: Int = 0
|
||||
) = ManagerPreference(key, defaultValue)
|
||||
|
||||
fun managerLongPreference(
|
||||
key: Preferences.Key<Long>,
|
||||
defaultValue: Long = 0
|
||||
) = ManagerPreference(key, defaultValue)
|
|
@ -2,5 +2,5 @@ package com.vanced.manager.ui.preferences
|
|||
|
||||
data class RadioButtonPreference(
|
||||
val title: String,
|
||||
val preferenceValue: String
|
||||
val key: String
|
||||
)
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package com.vanced.manager.ui.preferences.holder
|
||||
|
||||
const val MANAGER_VARIANT_DEFAULT_VALUE = "nonroot"
|
||||
|
||||
const val VANCED_ENABLED_DEFAULT_VALUE = true
|
||||
const val MUSIC_ENABLED_DEFAULT_VALUE = true
|
|
@ -0,0 +1,23 @@
|
|||
package com.vanced.manager.ui.preferences.holder
|
||||
|
||||
import com.vanced.manager.ui.preferences.managerBooleanPreference
|
||||
import com.vanced.manager.ui.preferences.managerLongPreference
|
||||
import com.vanced.manager.ui.preferences.managerStringPreference
|
||||
import com.vanced.manager.ui.preferences.managerStringSetPreference
|
||||
import com.vanced.manager.ui.theme.defAccentColor
|
||||
|
||||
val useCustomTabsPref = managerBooleanPreference(useCustomTabsKey)
|
||||
|
||||
val managerVariantPref = managerStringPreference(managerVariantKey, MANAGER_VARIANT_DEFAULT_VALUE)
|
||||
|
||||
val managerThemePref = managerStringPreference(managerThemeKey, "System Default")
|
||||
val managerAccentColorPref = managerLongPreference(managerAccentColorKey, defAccentColor)
|
||||
|
||||
val vancedThemePref = managerStringPreference(vancedThemeKey, "Dark")
|
||||
val vancedVersionPref = managerStringPreference(vancedVersionKey, "latest")
|
||||
val vancedLanguagesPref = managerStringSetPreference(vancedLanguageKey, setOf("en"))
|
||||
|
||||
val musicVersionPref = managerStringPreference(musicVersionKey, "latest")
|
||||
|
||||
val vancedEnabled = managerBooleanPreference(vancedEnabledKey, VANCED_ENABLED_DEFAULT_VALUE)
|
||||
val musicEnabled = managerBooleanPreference(musicEnabledKey, MUSIC_ENABLED_DEFAULT_VALUE)
|
|
@ -0,0 +1,19 @@
|
|||
package com.vanced.manager.ui.preferences.holder
|
||||
|
||||
import androidx.datastore.preferences.core.booleanPreferencesKey
|
||||
import androidx.datastore.preferences.core.longPreferencesKey
|
||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||
import androidx.datastore.preferences.core.stringSetPreferencesKey
|
||||
|
||||
val useCustomTabsKey = booleanPreferencesKey(USE_CUSTOM_TABS_KEY)
|
||||
val managerVariantKey = stringPreferencesKey(MANAGER_VARIANT_KEY)
|
||||
val managerThemeKey = stringPreferencesKey("manager_theme")
|
||||
val managerAccentColorKey = longPreferencesKey("manager_accent_color")
|
||||
|
||||
val vancedThemeKey = stringPreferencesKey(APP_VANCED_THEME_KEY)
|
||||
val vancedVersionKey = stringPreferencesKey(APP_VANCED_VERSION_KEY)
|
||||
val vancedLanguageKey = stringSetPreferencesKey(APP_VANCED_LANGUAGE_KEY)
|
||||
val musicVersionKey = stringPreferencesKey(APP_MUSIC_VERSION_KEY)
|
||||
|
||||
val vancedEnabledKey = booleanPreferencesKey(VANCED_ENABLED_KEY)
|
||||
val musicEnabledKey = booleanPreferencesKey(MUSIC_ENABLED_KEY)
|
|
@ -0,0 +1,13 @@
|
|||
package com.vanced.manager.ui.preferences.holder
|
||||
|
||||
const val USE_CUSTOM_TABS_KEY = "use_custom_tabs"
|
||||
const val MANAGER_VARIANT_KEY = "manager_variant"
|
||||
|
||||
const val APP_VANCED_THEME_KEY = "app_vanced_theme"
|
||||
const val APP_VANCED_VERSION_KEY = "app_vanced_version"
|
||||
const val APP_VANCED_LANGUAGE_KEY = "app_vanced_language"
|
||||
|
||||
const val APP_MUSIC_VERSION_KEY = "app_music_version"
|
||||
|
||||
const val VANCED_ENABLED_KEY = "manager_vanced_enabled"
|
||||
const val MUSIC_ENABLED_KEY = "manager_music_enabled"
|
|
@ -1,8 +1,48 @@
|
|||
package com.vanced.manager.ui.screens
|
||||
|
||||
sealed class Screen(val route: String, val displayName: String) {
|
||||
object Home : Screen("home", "Manager")
|
||||
object Settings : Screen("settings", "Settings")
|
||||
object About : Screen("about", "About")
|
||||
object Logs : Screen("logs", "Logs")
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.vanced.manager.R
|
||||
import com.vanced.manager.ui.layouts.AboutLayout
|
||||
import com.vanced.manager.ui.layouts.HomeLayout
|
||||
import com.vanced.manager.ui.layouts.LogLayout
|
||||
import com.vanced.manager.ui.layouts.SettingsLayout
|
||||
|
||||
sealed class Screen(
|
||||
val route: String,
|
||||
@StringRes val displayName: Int,
|
||||
val content: @Composable () -> Unit
|
||||
) {
|
||||
|
||||
object Home : Screen(
|
||||
route = "home",
|
||||
displayName = R.string.toolbar_home,
|
||||
content = {
|
||||
HomeLayout()
|
||||
}
|
||||
)
|
||||
|
||||
object Settings : Screen(
|
||||
route = "settings",
|
||||
displayName = R.string.toolbar_settings,
|
||||
content = {
|
||||
SettingsLayout()
|
||||
}
|
||||
)
|
||||
|
||||
object About : Screen(
|
||||
route = "about",
|
||||
displayName = R.string.toolbar_about,
|
||||
content = {
|
||||
AboutLayout()
|
||||
}
|
||||
)
|
||||
|
||||
object Logs : Screen(
|
||||
route = "logs",
|
||||
displayName = R.string.toolbar_logs,
|
||||
content = {
|
||||
LogLayout()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import androidx.compose.material.Shapes
|
|||
import androidx.compose.ui.unit.dp
|
||||
|
||||
val shapes = Shapes(
|
||||
small = RoundedCornerShape(4.dp),
|
||||
medium = RoundedCornerShape(4.dp),
|
||||
large = RoundedCornerShape(0.dp)
|
||||
small = RoundedCornerShape(8.dp),
|
||||
medium = RoundedCornerShape(12.dp),
|
||||
large = RoundedCornerShape(8.dp)
|
||||
)
|
|
@ -6,12 +6,11 @@ import androidx.compose.material.MaterialTheme
|
|||
import androidx.compose.material.darkColors
|
||||
import androidx.compose.material.lightColors
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import com.vanced.manager.ui.preferences.holder.managerAccentColorPref
|
||||
import com.vanced.manager.ui.preferences.holder.managerThemePref
|
||||
|
||||
var managerTheme by mutableStateOf<String?>("")
|
||||
const val defAccentColor = 0xFF0477E1
|
||||
|
||||
private val DarkColorPalette = darkColors(
|
||||
primary = purple200,
|
||||
|
@ -28,10 +27,10 @@ private val LightColorPalette = lightColors(
|
|||
|
||||
val Colors.cardColor: Color get() = if (isLight) Color(0xFFF7F7F7) else Color(0xFF191919)
|
||||
|
||||
val Colors.managerAccentColor: Color get() = Color(0xFF2E73FF)
|
||||
val Colors.managerAccentColor: Color get() = Color(managerAccentColorPref.value.value)
|
||||
|
||||
@Composable
|
||||
fun isDark(): Boolean = when (managerTheme) {
|
||||
fun isDark(): Boolean = when (managerThemePref.value.value) {
|
||||
"Dark" -> true
|
||||
"Light" -> false
|
||||
"System Default" -> isSystemInDarkTheme()
|
||||
|
@ -39,7 +38,7 @@ fun isDark(): Boolean = when (managerTheme) {
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun ComposeTestTheme(
|
||||
fun ManagerTheme(
|
||||
content: @Composable () -> Unit
|
||||
) {
|
||||
val colors = if (isDark()) DarkColorPalette else LightColorPalette
|
||||
|
|
|
@ -2,27 +2,53 @@ package com.vanced.manager.ui.theme
|
|||
|
||||
import androidx.compose.material.Typography
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.Font
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.vanced.manager.R
|
||||
|
||||
private val light = Font(R.font.inter_light, FontWeight.Light)
|
||||
private val regular = Font(R.font.inter_regular, FontWeight.Normal)
|
||||
private val medium = Font(R.font.inter_medium, FontWeight.Medium)
|
||||
private val semibold = Font(R.font.inter_semibold, FontWeight.SemiBold)
|
||||
private val bold = Font(R.font.inter_bold, FontWeight.Bold)
|
||||
|
||||
private val interFontFamily = FontFamily(light, regular, medium, semibold, bold)
|
||||
|
||||
// Set of Material typography styles to start with
|
||||
val typography = Typography(
|
||||
body1 = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 16.sp
|
||||
)
|
||||
/* Other default text styles to override
|
||||
button = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.W500,
|
||||
fontSize = 14.sp
|
||||
defaultFontFamily = interFontFamily,
|
||||
h1 = TextStyle(
|
||||
fontSize = 24.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
),
|
||||
caption = TextStyle(
|
||||
fontFamily = FontFamily.Default,
|
||||
fontWeight = FontWeight.Normal,
|
||||
h2 = TextStyle(
|
||||
fontSize = 20.sp,
|
||||
fontWeight = FontWeight.SemiBold
|
||||
),
|
||||
h5 = TextStyle(
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
),
|
||||
h6 = TextStyle(
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
),
|
||||
body1 = TextStyle(
|
||||
fontWeight = FontWeight.Medium,
|
||||
fontSize = 12.sp
|
||||
),
|
||||
body2 = TextStyle(
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 10.sp,
|
||||
),
|
||||
subtitle1 = TextStyle(
|
||||
fontWeight = FontWeight.Normal,
|
||||
fontSize = 12.sp,
|
||||
),
|
||||
button = TextStyle(
|
||||
fontSize = 14.sp,
|
||||
fontWeight = FontWeight.Medium
|
||||
)
|
||||
*/
|
||||
)
|
6
app/src/main/java/com/vanced/manager/ui/utils/Const.kt
Normal file
6
app/src/main/java/com/vanced/manager/ui/utils/Const.kt
Normal file
|
@ -0,0 +1,6 @@
|
|||
package com.vanced.manager.ui.utils
|
||||
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
val defaultContentPaddingHorizontal = 16.dp
|
||||
val defaultContentPaddingVertical = 12.dp
|
|
@ -7,9 +7,11 @@ import androidx.lifecycle.LiveData
|
|||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.preference.PreferenceManager.getDefaultSharedPreferences
|
||||
import com.vanced.manager.domain.model.App
|
||||
import com.vanced.manager.repository.JsonRepository
|
||||
import com.vanced.manager.ui.preferences.holder.managerVariantPref
|
||||
import com.vanced.manager.ui.preferences.holder.musicEnabled
|
||||
import com.vanced.manager.ui.preferences.holder.vancedEnabled
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class HomeViewModel(
|
||||
|
@ -45,26 +47,10 @@ class HomeViewModel(
|
|||
}
|
||||
|
||||
init {
|
||||
|
||||
|
||||
val prefs = getDefaultSharedPreferences(context)
|
||||
val variant = prefs.getString("manager_variant", "nonroot")
|
||||
val vancedEnabled = prefs.getBoolean("manager_vanced_enabled", true)
|
||||
val musicEnabled = prefs.getBoolean("manager_music_enabled", true)
|
||||
|
||||
apps.apply {
|
||||
if (vancedEnabled) {
|
||||
add(vanced)
|
||||
}
|
||||
|
||||
if (musicEnabled) {
|
||||
add(music)
|
||||
}
|
||||
|
||||
if (variant == "nonroot") {
|
||||
add(microg)
|
||||
}
|
||||
|
||||
if (vancedEnabled.value.value) add(vanced)
|
||||
if (musicEnabled.value.value) add(music)
|
||||
if (managerVariantPref.value.value == "nonroot") add(microg)
|
||||
}
|
||||
|
||||
fetch()
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
package com.vanced.manager.ui.widgets.home.apps.card
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Info
|
||||
import androidx.compose.material.icons.rounded.DeleteForever
|
||||
import androidx.compose.material.icons.rounded.Download
|
||||
import androidx.compose.material.icons.rounded.Launch
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vanced.manager.R
|
||||
import com.vanced.manager.ui.components.button.IconButton
|
||||
import com.vanced.manager.ui.components.color.ThemedCardContentColorProvider
|
||||
import com.vanced.manager.ui.components.text.ManagerText
|
||||
import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal
|
||||
import com.vanced.manager.ui.widgets.text.AppVersionText
|
||||
|
||||
@Composable
|
||||
fun AppActionCard(
|
||||
appRemoteVersion: String?,
|
||||
appInstalledVersion: String?,
|
||||
showDownloadDialog: MutableState<Boolean>,
|
||||
showAppInfo: MutableState<Boolean>,
|
||||
showInstallationOptions: MutableState<Boolean>,
|
||||
hasInstallationOptions: Boolean
|
||||
) {
|
||||
ThemedCardContentColorProvider {
|
||||
Row(
|
||||
modifier = Modifier.padding(horizontal = defaultContentPaddingHorizontal, vertical = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.wrapContentWidth(Alignment.Start),
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp)
|
||||
) {
|
||||
ManagerText(stringId = R.string.app_versions)
|
||||
AppVersionText(
|
||||
stringId = R.string.app_version_latest,
|
||||
version = appRemoteVersion
|
||||
)
|
||||
AppVersionText(
|
||||
stringId = R.string.app_version_installed,
|
||||
version = appInstalledVersion
|
||||
)
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.padding(start = 4.dp)
|
||||
.wrapContentWidth(Alignment.End)
|
||||
) {
|
||||
IconButton(icon = Icons.Outlined.Info, contentDescription = "App Info") {
|
||||
showAppInfo.value = true
|
||||
}
|
||||
IconButton(icon = Icons.Rounded.DeleteForever, contentDescription = "Uninstall") {}
|
||||
IconButton(icon = Icons.Rounded.Launch, contentDescription = "Launch") {}
|
||||
IconButton(icon = Icons.Rounded.Download, contentDescription = "Install") {
|
||||
if (hasInstallationOptions) {
|
||||
showInstallationOptions.value = true
|
||||
} else {
|
||||
showDownloadDialog.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
package com.vanced.manager.ui.widgets.home.apps.card
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.ExperimentalAnimationApi
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.google.accompanist.glide.rememberGlidePainter
|
||||
import com.vanced.manager.domain.model.App
|
||||
import com.vanced.manager.ui.components.button.ManagerThemedButton
|
||||
import com.vanced.manager.ui.components.card.ManagerThemedCard
|
||||
import com.vanced.manager.ui.widgets.home.apps.dialog.AppChangelogDialog
|
||||
import com.vanced.manager.ui.widgets.home.apps.dialog.AppDownloadDialog
|
||||
|
||||
@OptIn(ExperimentalAnimationApi::class)
|
||||
@Composable
|
||||
fun AppCard(
|
||||
app: App,
|
||||
fetching: Boolean
|
||||
) {
|
||||
val showDownloadDialog = remember { mutableStateOf(false) }
|
||||
val showAppInfo = remember { mutableStateOf(false) }
|
||||
val showInstallationOptions = remember { mutableStateOf(false) }
|
||||
val icon = rememberGlidePainter(
|
||||
request = app.iconUrl ?: "",
|
||||
fadeIn = true
|
||||
)
|
||||
val hasInstallationOption = app.installationOptions != null
|
||||
|
||||
ManagerThemedCard {
|
||||
Column {
|
||||
AppInfoCard(
|
||||
appName = app.name ?: "",
|
||||
icon = icon,
|
||||
fetching = fetching
|
||||
)
|
||||
AppActionCard(
|
||||
appInstalledVersion = app.installedVersion,
|
||||
appRemoteVersion = app.remoteVersion,
|
||||
showDownloadDialog = showDownloadDialog,
|
||||
showAppInfo = showAppInfo,
|
||||
showInstallationOptions = showInstallationOptions,
|
||||
hasInstallationOptions = hasInstallationOption
|
||||
)
|
||||
if (hasInstallationOption) {
|
||||
AnimatedVisibility(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
visible = showInstallationOptions.value
|
||||
) {
|
||||
app.installationOptions?.forEach {
|
||||
it.item()
|
||||
}
|
||||
ManagerThemedButton(onClick = {
|
||||
showDownloadDialog.value = true
|
||||
}) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (app.name != null && app.downloader != null) {
|
||||
AppDownloadDialog(
|
||||
app = app.name,
|
||||
downloader = app.downloader,
|
||||
showDialog = showDownloadDialog
|
||||
)
|
||||
}
|
||||
|
||||
if (app.name != null && app.changelog != null) {
|
||||
AppChangelogDialog(
|
||||
appName = app.name,
|
||||
changelog = app.changelog,
|
||||
showDialog = showAppInfo
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.vanced.manager.ui.widgets.home.apps.card
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.google.accompanist.imageloading.ImageLoadState
|
||||
import com.google.accompanist.imageloading.LoadPainter
|
||||
import com.vanced.manager.ui.components.card.ManagerCard
|
||||
import com.vanced.manager.ui.components.list.ManagerListItem
|
||||
import com.vanced.manager.ui.components.placeholder.managerPlaceholder
|
||||
import com.vanced.manager.ui.components.text.ManagerText
|
||||
import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal
|
||||
|
||||
@Composable
|
||||
fun AppInfoCard(
|
||||
appName: String,
|
||||
icon: LoadPainter<Any>,
|
||||
fetching: Boolean
|
||||
) {
|
||||
ManagerCard {
|
||||
ManagerListItem(
|
||||
modifier = Modifier.padding(
|
||||
horizontal = defaultContentPaddingHorizontal,
|
||||
vertical = 12.dp
|
||||
),
|
||||
title = {
|
||||
ManagerText(
|
||||
modifier = Modifier.managerPlaceholder(fetching),
|
||||
text = appName,
|
||||
textStyle = MaterialTheme.typography.h5
|
||||
)
|
||||
},
|
||||
icon = {
|
||||
Image(
|
||||
painter = icon,
|
||||
contentDescription = "",
|
||||
modifier = Modifier
|
||||
.size(48.dp, 48.dp)
|
||||
.managerPlaceholder(icon.loadState is ImageLoadState.Loading)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package com.vanced.manager.ui.widgets.home.apps.dialog
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.vanced.manager.R
|
||||
import com.vanced.manager.ui.components.button.ManagerThemedTextButton
|
||||
import com.vanced.manager.ui.components.dialog.ManagerDialog
|
||||
import com.vanced.manager.ui.components.lifecycle.managerString
|
||||
import com.vanced.manager.ui.components.text.ManagerText
|
||||
|
||||
@Composable
|
||||
fun AppChangelogDialog(
|
||||
appName: String,
|
||||
changelog: String,
|
||||
showDialog: MutableState<Boolean>
|
||||
) {
|
||||
if (showDialog.value) {
|
||||
ManagerDialog(
|
||||
title = managerString(R.string.app_info_title, appName),
|
||||
onDismissRequest = { showDialog.value = false },
|
||||
buttons = {
|
||||
ManagerThemedTextButton(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
stringId = R.string.dialog_button_close
|
||||
) {
|
||||
showDialog.value = false
|
||||
}
|
||||
}
|
||||
) {
|
||||
ManagerText(
|
||||
modifier = Modifier.padding(top = 4.dp),
|
||||
text = changelog,
|
||||
textStyle = MaterialTheme.typography.subtitle1
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package com.vanced.manager.ui.widgets.home.apps.dialog
|
||||
|
||||
import androidx.compose.runtime.*
|
||||
import com.vanced.manager.downloader.base.BaseDownloader
|
||||
import com.vanced.manager.ui.components.dialog.ManagerDialog
|
||||
import com.vanced.manager.ui.widgets.home.download.AppDownloadDialogButtons
|
||||
import com.vanced.manager.ui.widgets.home.download.AppDownloadDialogProgress
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
fun AppDownloadDialog(
|
||||
app: String,
|
||||
downloader: BaseDownloader,
|
||||
showDialog: MutableState<Boolean>
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
|
||||
val rememberProgress = remember { downloader.downloadProgress }
|
||||
val rememberFile = remember { downloader.downloadFile }
|
||||
val rememberInstalling = remember { downloader.installing }
|
||||
|
||||
val showProgress = remember { mutableStateOf(false) }
|
||||
|
||||
if (showDialog.value) {
|
||||
ManagerDialog(
|
||||
title = app,
|
||||
onDismissRequest = { showDialog.value = false },
|
||||
buttons = {
|
||||
AppDownloadDialogButtons(
|
||||
showProgress = showProgress,
|
||||
onDownloadClick = {
|
||||
coroutineScope.launch {
|
||||
showProgress.value = true
|
||||
downloader.download()
|
||||
}
|
||||
},
|
||||
onCancelClick = {
|
||||
downloader.cancelDownload()
|
||||
showDialog.value = false
|
||||
showProgress.value = false
|
||||
}
|
||||
)
|
||||
}
|
||||
) {
|
||||
AppDownloadDialogProgress(
|
||||
progress = rememberProgress,
|
||||
file = rememberFile,
|
||||
showProgress = showProgress.value,
|
||||
installing = rememberInstalling
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.vanced.manager.ui.widgets.home.download
|
||||
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.vanced.manager.R
|
||||
import com.vanced.manager.ui.components.button.ManagerThemedTextButton
|
||||
|
||||
@Composable
|
||||
fun AppDownloadDialogButtons(
|
||||
showProgress: MutableState<Boolean>,
|
||||
onDownloadClick: () -> Unit,
|
||||
onCancelClick: () -> Unit,
|
||||
) {
|
||||
when (showProgress.value) {
|
||||
true -> ManagerThemedTextButton(
|
||||
stringId = R.string.dialog_button_cancel,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onClick = onCancelClick
|
||||
)
|
||||
false -> ManagerThemedTextButton(
|
||||
stringId = R.string.app_download_dialog_confirm,
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
onClick = onDownloadClick
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package com.vanced.manager.ui.widgets.home.download
|
||||
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.wrapContentWidth
|
||||
import androidx.compose.material.LinearProgressIndicator
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.vanced.manager.ui.components.color.managerAccentColor
|
||||
|
||||
@Composable
|
||||
fun AppDownloadDialogProgress(
|
||||
progress: Float,
|
||||
file: String,
|
||||
showProgress: Boolean,
|
||||
installing: Boolean
|
||||
) {
|
||||
if (showProgress) {
|
||||
when (installing) {
|
||||
true -> LinearProgressIndicator(color = managerAccentColor())
|
||||
false -> LinearProgressIndicator(
|
||||
progress = progress,
|
||||
color = managerAccentColor()
|
||||
)
|
||||
}
|
||||
Row {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.wrapContentWidth(Alignment.Start),
|
||||
text = "Downloading $file"
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.wrapContentWidth(Alignment.End),
|
||||
text = "$progress"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.vanced.manager.ui.widgets.home.installation
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import com.vanced.manager.ui.components.preference.CheckboxDialogPreference
|
||||
import com.vanced.manager.ui.preferences.CheckboxPreference
|
||||
import com.vanced.manager.ui.preferences.ManagerPreference
|
||||
|
||||
data class CheckboxInstallationOption(
|
||||
@StringRes val title: Int,
|
||||
val preference: ManagerPreference<Set<String>>,
|
||||
val buttons: List<CheckboxPreference>
|
||||
) : InstallationOption(
|
||||
item = {
|
||||
CheckboxDialogPreference(
|
||||
preferenceTitle = title,
|
||||
preference = preference,
|
||||
buttons = buttons
|
||||
)
|
||||
}
|
||||
)
|
|
@ -0,0 +1,7 @@
|
|||
package com.vanced.manager.ui.widgets.home.installation
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
|
||||
open class InstallationOption(
|
||||
val item: @Composable () -> Unit
|
||||
)
|
|
@ -0,0 +1,20 @@
|
|||
package com.vanced.manager.ui.widgets.home.installation
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import com.vanced.manager.ui.components.preference.RadiobuttonDialogPreference
|
||||
import com.vanced.manager.ui.preferences.ManagerPreference
|
||||
import com.vanced.manager.ui.preferences.RadioButtonPreference
|
||||
|
||||
data class RadiobuttonInstallationOption(
|
||||
@StringRes val title: Int,
|
||||
val preference: ManagerPreference<String>,
|
||||
val buttons: List<RadioButtonPreference>
|
||||
) : InstallationOption(
|
||||
item = {
|
||||
RadiobuttonDialogPreference(
|
||||
preferenceTitle = title,
|
||||
preference = preference,
|
||||
buttons = buttons
|
||||
)
|
||||
}
|
||||
)
|
|
@ -0,0 +1,30 @@
|
|||
package com.vanced.manager.ui.widgets.layout
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal
|
||||
import com.vanced.manager.ui.utils.defaultContentPaddingVertical
|
||||
import com.vanced.manager.ui.widgets.text.CategoryTitleText
|
||||
|
||||
@Composable
|
||||
fun CategoryLayout(
|
||||
@StringRes categoryNameId: Int,
|
||||
contentPaddingHorizontal: Dp = defaultContentPaddingHorizontal,
|
||||
categoryNameSpacing: Dp = defaultContentPaddingVertical,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalArrangement = Arrangement.spacedBy(categoryNameSpacing),
|
||||
) {
|
||||
CategoryTitleText(stringId = categoryNameId)
|
||||
Box(
|
||||
modifier = Modifier.padding(horizontal = contentPaddingHorizontal)
|
||||
) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.vanced.manager.ui.widgets.settings
|
||||
|
||||
import androidx.compose.runtime.*
|
||||
import com.vanced.manager.R
|
||||
import com.vanced.manager.ui.components.color.ManagerColorPicker
|
||||
import com.vanced.manager.ui.components.preference.DialogPreference
|
||||
import com.vanced.manager.ui.preferences.holder.managerAccentColorPref
|
||||
|
||||
@Composable
|
||||
fun SettingsAccentColorItem() {
|
||||
var localAccentColor by remember { mutableStateOf(managerAccentColorPref.value.value) }
|
||||
DialogPreference(
|
||||
preferenceTitleId = R.string.settings_preference_accent_color_title,
|
||||
preferenceDescription = localAccentColor.toString(),
|
||||
buttons = {
|
||||
|
||||
}
|
||||
) {
|
||||
ManagerColorPicker {
|
||||
localAccentColor = it
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package com.vanced.manager.ui.widgets.settings
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.vanced.manager.R
|
||||
import com.vanced.manager.ui.components.preference.RadiobuttonDialogPreference
|
||||
import com.vanced.manager.ui.preferences.RadioButtonPreference
|
||||
import com.vanced.manager.ui.preferences.holder.managerThemePref
|
||||
|
||||
@Composable
|
||||
fun ThemeSettingsItem() {
|
||||
RadiobuttonDialogPreference(
|
||||
preferenceTitle = R.string.settings_preference_theme_title,
|
||||
preference = managerThemePref,
|
||||
buttons = listOf(
|
||||
RadioButtonPreference(
|
||||
title = "Light Theme",
|
||||
key = "Light"
|
||||
),
|
||||
RadioButtonPreference(
|
||||
title = "Dark Theme",
|
||||
key = "Dark"
|
||||
),
|
||||
RadioButtonPreference(
|
||||
title = "System Default",
|
||||
key = "System Default"
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.vanced.manager.ui.widgets.text
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.vanced.manager.R
|
||||
import com.vanced.manager.ui.components.lifecycle.managerString
|
||||
import com.vanced.manager.ui.components.text.ManagerText
|
||||
|
||||
@Composable
|
||||
fun AppVersionText(
|
||||
@StringRes stringId: Int,
|
||||
version: String?
|
||||
) {
|
||||
ManagerText(
|
||||
version ?: managerString(stringId = R.string.app_content_unavailable),
|
||||
stringId = stringId,
|
||||
textStyle = MaterialTheme.typography.body2,
|
||||
)
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package com.vanced.manager.ui.widgets.text
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.vanced.manager.ui.components.text.ManagerText
|
||||
import com.vanced.manager.ui.utils.defaultContentPaddingHorizontal
|
||||
|
||||
@Composable
|
||||
fun CategoryTitleText(
|
||||
@StringRes stringId: Int
|
||||
) {
|
||||
ManagerText(
|
||||
modifier = Modifier.padding(start = defaultContentPaddingHorizontal),
|
||||
stringId = stringId,
|
||||
textStyle = MaterialTheme.typography.h2
|
||||
)
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.vanced.manager.ui.widgets.text
|
||||
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import com.vanced.manager.ui.components.text.ManagerText
|
||||
|
||||
@Composable
|
||||
fun ToolbarTitleText(
|
||||
stringId: Int?
|
||||
) {
|
||||
ManagerText(
|
||||
stringId = stringId,
|
||||
textStyle = MaterialTheme.typography.h1
|
||||
)
|
||||
}
|
|
@ -1,16 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="33.408dp"
|
||||
android:height="34.294dp"
|
||||
android:viewportWidth="33.408"
|
||||
android:viewportHeight="34.294">
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M16.7,0.5A36.932,36.932 0,0 0,0.5 4.292c0,5.689 -0.057,19.767 16.2,29.42 16.261,-9.653 16.2,-23.789 16.2,-29.42A36.932,36.932 0,0 0,16.7 0.5Z"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="?colorLinkImage"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M16.13,22.678l9.826,-13.216a1.223,1.223 0,0 0,-1.724 0.172h0l-8.159,8.5 -3.1,-3.735c-1.494,-1.724 -3.448,-0.4 -3.907,-0.057L16.13,22.678"
|
||||
android:fillColor="?colorLinkImage"
|
||||
android:fillType="evenOdd"/>
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M11.7,2.1c3.6,0.1 6.7,0.7 9.7,2.1c0.3,0.1 0.4,0.3 0.4,0.6c0,3.2 -0.5,6.3 -1.9,9.2c-1.7,3.4 -4.3,6 -7.5,7.9c-0.1,0.1 -0.3,0.1 -0.4,0c-4.8,-3 -8.1,-7.1 -9.1,-12.7c-0.3,-1.5 -0.2,-3 -0.4,-4.5c0,-0.3 0.1,-0.4 0.3,-0.5c2,-1 4.2,-1.6 6.4,-1.9C10.1,2.2 11.1,2.1 11.7,2.1zM7.6,10.5c1.4,1.7 2.8,3.3 4.2,5c2,-2.7 3.9,-5.3 5.8,-7.9c-0.5,-0.3 -0.7,-0.2 -1.2,0.2c-1.5,1.6 -3,3.1 -4.4,4.7c-0.1,0.1 -0.2,0.2 -0.3,0.3c-0.6,-0.7 -1.1,-1.4 -1.7,-2.1C9.3,9.8 8.4,9.8 7.6,10.5z"/>
|
||||
</vector>
|
||||
|
|
|
@ -1,14 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="37.319dp"
|
||||
android:height="43.642dp"
|
||||
android:viewportWidth="37.319"
|
||||
android:viewportHeight="43.642">
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:strokeWidth="1"
|
||||
android:pathData="M36.796,14.32l-1.329,-3.587 0.93,-2.059a0.707,0.707 0,0 0,-0.133 -0.8L33.807,5.352a4.063,4.063 0,0 0,-4.185 -1l-0.664,0.266L25.171,0.502l-6.51,0.066L12.216,0.635 8.43,4.754l-0.664,-0.266a3.933,3.933 0,0 0,-4.185 1L1.055,8.009A0.637,0.637 0,0 0,0.924 8.602l0.93,2.126L0.524,14.32l4.717,17.8a7.7,7.7 0,0 0,2.857 4.185l9.3,6.311a2.1,2.1 0,0 0,2.591 0l9.3,-6.311a7.162,7.162 0,0 0,2.857 -4.185l3.853,-14.615Z"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="?colorLinkImage"/>
|
||||
<path
|
||||
android:pathData="M19.723,26.942a3.239,3.239 0,0 0,-0.731 -0.266h-0.465a2.38,2.38 0,0 0,-0.731 0.266l-1.129,0.465 -1.329,0.6L13.209,29.135a0.441,0.441 0,0 0,-0.266 0.332,0.473 0.473,0 0,0 0.2,0.4l1.86,1.262c0.4,0.266 0.8,0.6 1.129,0.864l0.531,0.465 1.063,0.93 0.465,0.465a0.807,0.807 0,0 0,1.063 0l2.126,-1.86 1.129,-0.864 1.86,-1.329a0.418,0.418 0,0 0,0.2 -0.531c-0.066,-0.133 -0.133,-0.2 -0.266,-0.2L22.181,28.004l-1.329,-0.6ZM32.744,15.117l0.066,-0.2a2.491,2.491 0,0 0,-0.066 -0.731,7.572 7.572,0 0,0 -0.664,-1.262l-1.2,-1.727 -0.864,-1.129 -1.594,-1.993a3.8,3.8 0,0 0,-0.465 -0.531h0l-0.731,0.133L23.709,8.341a5.815,5.815 0,0 1,-1.063 -0.133l-1.927,-0.6 -1.4,-0.531a3.612,3.612 0,0 0,-1.2 0l-1.4,0.4 -1.927,0.6a1.894,1.894 0,0 1,-1.063 0.133l-3.521,-0.664 -0.731,-0.133h0a3.327,3.327 0,0 0,-0.465 0.531l-1.594,1.993c-0.266,0.4 -0.6,0.731 -0.864,1.129l-1.2,1.86 -0.531,0.93A2.926,2.926 0,0 0,4.709 14.918l0.066,0.2a0.507,0.507 0,0 0,0.133 0.332l0.93,1.063 4.185,4.451a1.288,1.288 0,0 1,0.2 1.2l-0.731,1.661a1.831,1.831 0,0 0,0 1.329l0.133,0.4a3.193,3.193 0,0 0,1.129 1.528l0.664,0.531a1.116,1.116 0,0 0,1.2 0.133l2.325,-1.129a6.239,6.239 0,0 0,1.2 -0.8l1.86,-1.661a0.82,0.82 0,0 0,0.266 -0.531,0.754 0.754,0 0,0 -0.2,-0.531l-4.185,-2.857a0.833,0.833 0,0 1,-0.266 -1.063l1.661,-3.056a1.5,1.5 0,0 0,0.066 -1.2,1.959 1.959,0 0,0 -0.93,-0.864l-5.115,-1.927c-0.4,-0.133 -0.332,-0.332 0.066,-0.332l2.989,-0.332a4.974,4.974 0,0 1,1.4 0.133l2.591,0.731a0.777,0.777 0,0 1,0.531 0.864l-1,5.58a4.386,4.386 0,0 0,-0.066 0.93,1.252 1.252,0 0,0 0.8,0.4l1.594,0.332a4.908,4.908 0,0 0,1.4 0l1.462,-0.332a1.252,1.252 0,0 0,0.8 -0.4,2.133 2.133,0 0,0 -0.066,-0.93L20.719,13.124a0.762,0.762 0,0 1,0.531 -0.864l2.591,-0.731a4.974,4.974 0,0 1,1.4 -0.133l2.989,0.266c0.4,0.066 0.4,0.2 0.066,0.332l-5.115,1.927a1.687,1.687 0,0 0,-0.93 0.864,1.487 1.487,0 0,0 0.066,1.2l1.661,3.056A0.851,0.851 0,0 1,23.709 20.104l-4.185,2.857a0.807,0.807 0,0 0,0 1.063h0l1.86,1.661a4.7,4.7 0,0 0,1.2 0.8L24.909,27.604a1.271,1.271 0,0 0,1.2 -0.133l0.664,-0.531a3.685,3.685 0,0 0,1.129 -1.528l0.066,-0.266a2.261,2.261 0,0 0,0 -1.329l-0.664,-1.594a1.288,1.288 0,0 1,0.2 -1.2l4.185,-4.451 0.93,-1.063a0.712,0.712 0,0 1,0.133 -0.4Z"
|
||||
android:fillColor="?colorLinkImage"/>
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M5.4,2.7c0.3,0 0.6,0.1 1,0.1c0,0 0.1,0 0.1,0c0.6,-0.7 1.2,-1.4 1.8,-2.1c0.1,-0.1 0.2,-0.1 0.3,-0.1c2.2,0 4.4,0 6.7,0c0.3,0 0.4,0.1 0.6,0.3c0.4,0.4 0.7,0.8 1.1,1.3c0.2,0.2 0.4,0.5 0.6,0.7c0,0 0.1,0.1 0.2,0c0.5,-0.1 1,-0.2 1.5,-0.1c0.4,0.1 0.8,0.2 1.2,0.5c0.3,0.4 0.7,0.7 1,1c0.1,0.1 0.2,0.2 0.4,0.4c0.1,0.1 0.1,0.1 0,0.2c-0.2,0.4 -0.3,0.7 -0.5,1.1c0,0.1 0,0.2 0,0.3c0.2,0.6 0.4,1.1 0.6,1.7c0,0.1 0,0.2 0,0.3c-0.1,0.4 -0.2,0.9 -0.3,1.3c-0.5,1.8 -0.9,3.5 -1.4,5.3c-0.3,1 -0.5,2 -0.8,3c-0.1,0.5 -0.3,0.9 -0.6,1.3c-0.3,0.3 -0.6,0.7 -1,0.9c-0.6,0.4 -1.2,0.8 -1.8,1.2c-0.5,0.3 -1,0.7 -1.5,1c-0.5,0.3 -1,0.7 -1.5,1c-0.2,0.1 -0.4,0.2 -0.6,0.3c-0.2,0.1 -0.5,0.1 -0.7,0c-0.2,-0.1 -0.4,-0.2 -0.5,-0.3c-0.8,-0.6 -1.7,-1.1 -2.5,-1.7c-0.5,-0.3 -1,-0.6 -1.4,-1c-0.4,-0.3 -0.8,-0.6 -1.2,-0.8c-0.7,-0.5 -1.1,-1.3 -1.4,-2.2c-0.1,-0.4 -0.2,-0.8 -0.3,-1.2c-0.3,-1.2 -0.6,-2.3 -1,-3.5c-0.2,-0.7 -0.4,-1.4 -0.5,-2.1C2.6,9.9 2.4,9 2.1,8.2c0,-0.1 0,-0.2 0,-0.3c0.2,-0.6 0.4,-1.1 0.6,-1.6c0,-0.1 0,-0.2 0,-0.3C2.6,5.6 2.4,5.2 2.3,4.9c0,-0.1 0,-0.1 0,-0.2c0.5,-0.5 1,-1 1.5,-1.5c0.3,-0.3 0.6,-0.3 1,-0.4C5,2.7 5.1,2.7 5.4,2.7zM6.7,6.7C6.7,6.7 6.7,6.7 6.7,6.7C6.8,6.7 6.9,6.6 7,6.6c0.3,0 0.5,-0.1 0.8,-0.1c0.4,0 0.9,-0.1 1.3,0c0.5,0.1 1.1,0.3 1.6,0.4C11,7.1 11.1,7.2 11,7.5c-0.1,0.7 -0.3,1.4 -0.4,2.1c-0.1,0.4 -0.1,0.7 -0.2,1.1c0,0.2 0.1,0.3 0.3,0.4c0.3,0.1 0.6,0.1 1,0.2c0.2,0 0.4,0 0.5,0c0.4,-0.1 0.8,-0.1 1.1,-0.2c0.3,-0.1 0.3,-0.2 0.3,-0.4c-0.1,-0.5 -0.2,-1 -0.2,-1.5c-0.1,-0.6 -0.2,-1.2 -0.3,-1.7c0,-0.3 0,-0.4 0.3,-0.5c0.2,-0.1 0.4,-0.1 0.6,-0.2c0.6,-0.2 1.1,-0.3 1.7,-0.3c0.5,0 0.9,0.1 1.4,0.1c0.1,0 0.2,0 0.2,0.1c0,0 0,0 0,0c0,0 -0.1,0 -0.1,0.1c-1,0.4 -1.9,0.7 -2.9,1.1C14,8 13.8,8.4 13.9,8.7c0.1,0.4 0.3,0.7 0.4,1c0.2,0.3 0.4,0.6 0.5,0.9c0.1,0.3 0.1,0.4 -0.2,0.6c-0.4,0.3 -0.8,0.5 -1.2,0.8c-0.3,0.2 -0.7,0.4 -1,0.7c-0.2,0.2 -0.2,0.3 0,0.5c0.2,0.2 0.4,0.4 0.6,0.6c0.7,0.6 1.5,1 2.3,1.4c0.3,0.1 0.5,0.1 0.7,-0.1c0.3,-0.2 0.6,-0.5 0.8,-0.8c0.2,-0.4 0.3,-0.8 0.2,-1.2c-0.1,-0.3 -0.2,-0.5 -0.3,-0.8c-0.1,-0.3 -0.1,-0.6 0.2,-0.9c0.1,-0.1 0.3,-0.2 0.4,-0.4c0.7,-0.7 1.3,-1.4 2,-2.1c0.4,-0.4 0.5,-0.9 0.2,-1.4c-0.3,-0.5 -0.6,-0.9 -1,-1.4c-0.4,-0.6 -0.8,-1.1 -1.3,-1.7c-0.1,-0.1 -0.1,-0.2 -0.3,-0.2c-0.6,0.1 -1.2,0.2 -1.8,0.3c-0.4,0.1 -0.8,0.1 -1.2,0c-0.3,-0.1 -0.6,-0.2 -0.9,-0.3c-0.6,-0.2 -1.2,-0.3 -1.8,-0.1c-0.4,0.1 -0.7,0.2 -1.1,0.4C9.9,4.6 9.6,4.7 9.3,4.7C8.6,4.6 7.9,4.4 7.1,4.3c-0.1,0 -0.2,0 -0.3,0.1C6.4,4.9 6,5.4 5.6,5.9C5.2,6.5 4.9,7.1 4.5,7.6c-0.3,0.5 -0.1,1 0.2,1.3c0.5,0.6 1.1,1.1 1.6,1.7c0.3,0.3 0.6,0.6 0.8,0.9c0.2,0.2 0.3,0.5 0.2,0.8c0,0.1 -0.1,0.2 -0.1,0.3C7.1,12.8 7,13 7,13.3c-0.1,0.3 0,0.7 0.2,1c0.2,0.3 0.4,0.6 0.7,0.8c0.3,0.2 0.6,0.3 1,0.1c0.4,-0.2 0.7,-0.3 1.1,-0.5c0.7,-0.3 1.2,-0.8 1.7,-1.4c0.2,-0.3 0.2,-0.4 0,-0.6c0,0 -0.1,-0.1 -0.1,-0.1c-0.3,-0.2 -0.6,-0.4 -0.9,-0.6c-0.4,-0.3 -0.8,-0.5 -1.2,-0.8c-0.3,-0.2 -0.3,-0.3 -0.2,-0.7c0.1,-0.3 0.3,-0.6 0.5,-0.9c0.2,-0.3 0.3,-0.6 0.4,-0.9c0.1,-0.2 0.1,-0.4 -0.1,-0.6C9.9,8 9.8,7.9 9.7,7.9C8.8,7.6 8,7.2 7.1,6.9C7,6.9 6.8,6.8 6.7,6.7zM12.1,14.8c-0.1,0 -0.1,0 -0.1,0c-0.2,0.1 -0.5,0.1 -0.7,0.2c-0.7,0.3 -1.4,0.7 -2.2,1.1c-0.2,0.1 -0.2,0.3 0,0.4c0,0 0.1,0.1 0.1,0.1c0.5,0.4 1,0.7 1.5,1.1c0.4,0.3 0.8,0.6 1.2,0.9c0.3,0.2 0.4,0.2 0.6,0c0.2,-0.2 0.4,-0.3 0.6,-0.5c0.7,-0.5 1.4,-1.1 2.1,-1.6c0.3,-0.2 0.2,-0.3 0,-0.5c-0.3,-0.2 -0.6,-0.3 -0.9,-0.5c-0.5,-0.2 -1,-0.5 -1.6,-0.7C12.4,14.9 12.2,14.9 12.1,14.8z"/>
|
||||
</vector>
|
||||
|
|
|
@ -1,18 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="38dp"
|
||||
android:height="38dp"
|
||||
android:viewportWidth="35"
|
||||
android:viewportHeight="35">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M27.1,1.1H6.7c-2.3,0 -4,1.8 -4,4v20.7c0,2.3 1.8,4 4,4h18.5L25,29l1.3,1.2l4.9,4.2V5.2C31.2,2.9 29.4,1.1 27.1,1.1zM30.2,32.6l-3.3,-2.9L25.1,28l-2,-1.8l0.8,2.8H6.6c-1.7,0 -3.1,-1.4 -3.1,-3.1V5.2c0,-1.7 1.4,-3.1 3.1,-3.1H27c1.7,0 3.1,1.4 3.1,3.1L30.2,32.6L30.2,32.6z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M24.5,10.4l-0.1,-0.2l-0.2,-0.1c-2.3,-1.7 -4.4,-1.8 -4.9,-1.8h-0.4L18.3,9c-0.5,-0.1 -0.9,-0.1 -1.4,-0.1S16,8.9 15.5,9l-0.3,-0.4l-0.3,-0.4h-0.4c-0.4,0 -2.5,0.1 -4.8,1.8l-0.3,0.3C9.3,10.5 7,14.5 7,19.6V20l0.1,0.2c0.1,0.1 1.6,2.6 5.5,2.8h0.5l0.3,-0.4c0,0 0.6,-0.7 1,-1.3c0.1,0 1.9,0.3 2.6,0.3s2.3,-0.2 2.4,-0.3c0.5,0.6 1,1.2 1,1.2l0.3,0.4h0.5c3.9,-0.1 5.4,-2.6 5.5,-2.8l0.1,-0.2v-0.3C26.9,14.6 24.6,10.5 24.5,10.4zM21.2,22c0,0 -0.6,-0.7 -1,-1.2c1.9,-0.6 2.6,-1.7 2.7,-1.8c-0.7,0.4 -1.2,0.7 -1.8,0.9c-0.8,0.3 -1.5,0.6 -2.2,0.7c-1.5,0.3 -2.8,0.2 -4,0c-0.8,-0.2 -1.6,-0.4 -2.3,-0.7c-0.2,0 -1.6,-0.8 -1.6,-0.9c0.1,0.1 0.8,1.2 2.6,1.8c-0.5,0.6 -1,1.2 -1,1.2c-3.4,-0.1 -4.7,-2.4 -4.7,-2.4c0,-4.9 2.2,-8.9 2.2,-8.9c2.2,-1.7 4.3,-1.6 4.3,-1.6l0.2,0.2L15,9.9c0,0 2.3,-0.2 3.4,0c0.1,0 0.4,0.1 0.5,0.1l0.4,-0.5l0.2,-0.3c0,0 2.1,0 4.3,1.6c0,0 2.2,4 2.2,8.9C25.9,19.7 24.6,21.8 21.2,22z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M14.1,16.6m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M19.7,16.6m-1.5,0a1.5,1.5 0,1 1,3 0a1.5,1.5 0,1 1,-3 0"/>
|
||||
<vector
|
||||
android:height="18.591549dp"
|
||||
android:viewportHeight="55"
|
||||
android:viewportWidth="71"
|
||||
android:width="24dp"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M60.1045,4.8978C55.5792,2.8214 50.7265,1.2916 45.6527,0.4154C45.5603,0.3985 45.468,0.4408 45.4204,0.5253C44.7963,1.6353 44.105,3.0834 43.6209,4.2216C38.1637,3.4046 32.7345,3.4046 27.3892,4.2216C26.905,3.0581 26.1886,1.6353 25.5617,0.5253C25.5141,0.4436 25.4218,0.4013 25.3294,0.4154C20.2584,1.2888 15.4057,2.8186 10.8776,4.8978C10.8384,4.9147 10.8048,4.9429 10.7825,4.9795C1.578,18.7309 -0.9436,32.1443 0.2934,45.3914C0.299,45.4562 0.3354,45.5182 0.3858,45.5576C6.4587,50.0174 12.3413,52.7249 18.1147,54.5195C18.2071,54.5477 18.305,54.5139 18.3638,54.4378C19.7295,52.5728 20.9469,50.6063 21.9907,48.5383C22.0523,48.4172 21.9935,48.2735 21.8676,48.2256C19.9366,47.4931 18.0979,46.6 16.3292,45.5858C16.1893,45.5041 16.1781,45.304 16.3068,45.2082C16.679,44.9293 17.0513,44.6391 17.4067,44.3461C17.471,44.2926 17.5606,44.2813 17.6362,44.3151C29.2558,49.6202 41.8354,49.6202 53.3179,44.3151C53.3935,44.2785 53.4831,44.2898 53.5502,44.3433C53.9057,44.6363 54.2779,44.9293 54.6529,45.2082C54.7816,45.304 54.7732,45.5041 54.6333,45.5858C52.8646,46.6197 51.0259,47.4931 49.0921,48.2228C48.9662,48.2707 48.9102,48.4172 48.9718,48.5383C50.038,50.6034 51.2554,52.5699 52.5959,54.435C52.6519,54.5139 52.7526,54.5477 52.845,54.5195C58.6464,52.7249 64.529,50.0174 70.6019,45.5576C70.6551,45.5182 70.6887,45.459 70.6943,45.3942C72.1747,30.0791 68.2147,16.7757 60.1968,4.9823C60.1772,4.9429 60.1437,4.9147 60.1045,4.8978ZM23.7259,37.3253C20.2276,37.3253 17.3451,34.1136 17.3451,30.1693C17.3451,26.225 20.1717,23.0133 23.7259,23.0133C27.308,23.0133 30.1626,26.2532 30.1066,30.1693C30.1066,34.1136 27.28,37.3253 23.7259,37.3253ZM47.3178,37.3253C43.8196,37.3253 40.9371,34.1136 40.9371,30.1693C40.9371,26.225 43.7636,23.0133 47.3178,23.0133C50.9,23.0133 53.7545,26.2532 53.6986,30.1693C53.6986,34.1136 50.9,37.3253 47.3178,37.3253Z"/>
|
||||
</vector>
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
<vector android:height="36.508373dp" android:viewportHeight="35.5"
|
||||
android:viewportWidth="36.367" android:width="37.4dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#00000000" android:fillType="evenOdd"
|
||||
android:pathData="M18.183,0.5a17.687,17.687 0,0 0,-5.59 34.466c0.879,0.163 1.2,-0.38 1.2,-0.858 0,-0.423 -0.011,-1.531 -0.022,-3.007 -4.917,1.064 -5.96,-2.366 -5.96,-2.366a4.67,4.67 0,0 0,-1.965 -2.584c-1.607,-1.1 0.119,-1.075 0.119,-1.075a3.758,3.758 0,0 1,2.714 1.824,3.758 3.758,0 0,0 5.145,1.465 3.843,3.843 0,0 1,1.118 -2.366c-3.93,-0.445 -8.055,-1.965 -8.055,-8.739a6.8,6.8 0,0 1,1.824 -4.744,6.321 6.321,0 0,1 0.174,-4.679s1.487,-0.478 4.863,1.813a16.727,16.727 0,0 1,8.858 0c3.376,-2.29 4.863,-1.813 4.863,-1.813a6.321,6.321 0,0 1,0.174 4.679,6.836 6.836,0 0,1 1.813,4.744c0,6.8 -4.136,8.283 -8.076,8.728a4.243,4.243 0,0 1,1.2 3.278c0,2.366 -0.022,4.266 -0.022,4.852 0,0.478 0.315,1.02 1.216,0.847a17.689,17.689 0,0 0,-5.6 -34.466Z"
|
||||
android:strokeColor="#000000" android:strokeWidth="1"/>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,0c-6.626,0 -12,5.373 -12,12 0,5.302 3.438,9.8 8.207,11.387 0.599,0.111 0.793,-0.261 0.793,-0.577v-2.234c-3.338,0.726 -4.033,-1.416 -4.033,-1.416 -0.546,-1.387 -1.333,-1.756 -1.333,-1.756 -1.089,-0.745 0.083,-0.729 0.083,-0.729 1.205,0.084 1.839,1.237 1.839,1.237 1.07,1.834 2.807,1.304 3.492,0.997 0.107,-0.775 0.418,-1.305 0.762,-1.604 -2.665,-0.305 -5.467,-1.334 -5.467,-5.931 0,-1.311 0.469,-2.381 1.236,-3.221 -0.124,-0.303 -0.535,-1.524 0.117,-3.176 0,0 1.008,-0.322 3.301,1.23 0.957,-0.266 1.983,-0.399 3.003,-0.404 1.02,0.005 2.047,0.138 3.006,0.404 2.291,-1.552 3.297,-1.23 3.297,-1.23 0.653,1.653 0.242,2.874 0.118,3.176 0.77,0.84 1.235,1.911 1.235,3.221 0,4.609 -2.807,5.624 -5.479,5.921 0.43,0.372 0.823,1.102 0.823,2.222v3.293c0,0.319 0.192,0.694 0.801,0.576 4.765,-1.589 8.199,-6.086 8.199,-11.386 0,-6.627 -5.373,-12 -12,-12z"/>
|
||||
</vector>
|
||||
|
|
|
@ -1,15 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="33.543dp"
|
||||
android:height="33.543dp"
|
||||
android:viewportWidth="33.543"
|
||||
android:viewportHeight="33.543">
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M24.522,1.086a7.945,7.945 0,0 1,7.935 7.935v15.5a7.945,7.945 0,0 1,-7.935 7.935h-15.5a7.945,7.945 0,0 1,-7.935 -7.935v-15.5a7.945,7.945 0,0 1,7.935 -7.935h15.5m0,-1.086h-15.5a9.02,9.02 0,0 0,-9.021 9.021v15.5a9.02,9.02 0,0 0,9.021 9.021h15.5a9.02,9.02 0,0 0,9.021 -9.021v-15.5a9.02,9.02 0,0 0,-9.021 -9.021Z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M16.674,9.282a7.686,7.686 0,1 1,-7.686 7.686,7.7 7.7,0 0,1 7.686,-7.686m0,-1.086a8.771,8.771 0,1 0,8.771 8.771,8.775 8.775,0 0,0 -8.771,-8.771Z"
|
||||
android:fillColor="#000000"/>
|
||||
<path
|
||||
android:pathData="M25.879,7.794m-1.541,0a1.541,1.541 0,1 1,3.082 0a1.541,1.541 0,1 1,-3.082 0"
|
||||
android:fillColor="#000000"/>
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,2.163c3.204,0 3.584,0.012 4.85,0.07 3.252,0.148 4.771,1.691 4.919,4.919 0.058,1.265 0.069,1.645 0.069,4.849 0,3.205 -0.012,3.584 -0.069,4.849 -0.149,3.225 -1.664,4.771 -4.919,4.919 -1.266,0.058 -1.644,0.07 -4.85,0.07 -3.204,0 -3.584,-0.012 -4.849,-0.07 -3.26,-0.149 -4.771,-1.699 -4.919,-4.92 -0.058,-1.265 -0.07,-1.644 -0.07,-4.849 0,-3.204 0.013,-3.583 0.07,-4.849 0.149,-3.227 1.664,-4.771 4.919,-4.919 1.266,-0.057 1.645,-0.069 4.849,-0.069zM12,0c-3.259,0 -3.667,0.014 -4.947,0.072 -4.358,0.2 -6.78,2.618 -6.98,6.98 -0.059,1.281 -0.073,1.689 -0.073,4.948 0,3.259 0.014,3.668 0.072,4.948 0.2,4.358 2.618,6.78 6.98,6.98 1.281,0.058 1.689,0.072 4.948,0.072 3.259,0 3.668,-0.014 4.948,-0.072 4.354,-0.2 6.782,-2.618 6.979,-6.98 0.059,-1.28 0.073,-1.689 0.073,-4.948 0,-3.259 -0.014,-3.667 -0.072,-4.947 -0.196,-4.354 -2.617,-6.78 -6.979,-6.98 -1.281,-0.059 -1.69,-0.073 -4.949,-0.073zM12,5.838c-3.403,0 -6.162,2.759 -6.162,6.162s2.759,6.163 6.162,6.163 6.162,-2.759 6.162,-6.163c0,-3.403 -2.759,-6.162 -6.162,-6.162zM12,16c-2.209,0 -4,-1.79 -4,-4 0,-2.209 1.791,-4 4,-4s4,1.791 4,4c0,2.21 -1.791,4 -4,4zM18.406,4.155c-0.796,0 -1.441,0.645 -1.441,1.44s0.645,1.44 1.441,1.44c0.795,0 1.439,-0.645 1.439,-1.44s-0.644,-1.44 -1.439,-1.44z"/>
|
||||
</vector>
|
||||
|
|
|
@ -1,21 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="38dp"
|
||||
android:height="38dp"
|
||||
android:viewportWidth="35"
|
||||
android:viewportHeight="35">
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M17.5,0.4c-9.4,0 -17,7.6 -17,17c0,9.4 7.6,17 17,17c9.4,0 17,-7.6 17,-17C34.5,8 26.9,0.4 17.5,0.4zM17.5,33.4c-8.8,0 -16,-7.2 -16,-16c0,-8.9 7.2,-16 16,-16c8.9,0 16,7.2 16,16C33.5,26.2 26.3,33.4 17.5,33.4z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M27.8,17.2c0,-1.7 -1.4,-3.1 -3.1,-3.1c-0.5,0 -1,0.1 -1.5,0.4c-1.2,-0.6 -2.6,-1.1 -4.1,-1.3l0.5,-1.6l1.6,0.4c0.3,1.1 1.4,1.9 2.6,1.9c1.5,0 2.7,-1.2 2.7,-2.7c0,-1.5 -1.2,-2.7 -2.7,-2.7c-0.8,0 -1.5,0.4 -2,0.9l-2.7,-0.6l-0.2,0h-0.1c-0.6,0 -1.1,0.4 -1.2,0.9l-1.1,3.4c-1.8,0.1 -3.5,0.6 -4.9,1.4c-0.4,-0.2 -0.9,-0.4 -1.4,-0.4c-1.7,0 -3.1,1.4 -3.1,3.1c0,0.8 0.4,1.6 1,2.2v0.2c0,3.6 4.2,6.5 9.4,6.5c5.1,0 9.3,-2.9 9.3,-6.5c0,-0.1 0,-0.1 0,-0.2C27.5,18.9 27.8,18.1 27.8,17.2zM25.8,19.6c0,3 -3.8,5.5 -8.3,5.5c-4.6,0 -8.4,-2.5 -8.4,-5.5c0,-0.2 0,-0.4 0.1,-0.7c-0.6,-0.4 -1,-1 -1,-1.8c0,-1.1 0.9,-2.1 2.1,-2.1c0.5,0 1,0.2 1.4,0.6c1.5,-1 3.5,-1.6 5.7,-1.6l1.3,-4c0,-0.2 0.2,-0.2 0.3,-0.2l3.4,0.8c0.2,-0.6 0.9,-1.1 1.6,-1.1c0.9,0 1.7,0.8 1.7,1.7S24.8,13 23.9,13c-0.9,0 -1.7,-0.8 -1.7,-1.7v0l-3.1,-0.7l-1.1,3.6c2.1,0.1 4,0.7 5.4,1.6c0.4,-0.4 0.9,-0.6 1.4,-0.6c1.1,0 2.1,0.9 2.1,2.1c0,0.8 -0.4,1.5 -1.1,1.8C25.8,19.2 25.8,19.4 25.8,19.6z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M20.5,22.3c-0.6,0.6 -1.6,0.9 -3,0.9h0c-1.4,0 -2.3,-0.3 -3,-0.9c-0.1,-0.1 -0.1,-0.3 0,-0.4c0.1,-0.1 0.3,-0.1 0.4,0c0.5,0.5 1.3,0.8 2.6,0.8h0c1.2,0 2.1,-0.2 2.6,-0.8c0.1,-0.1 0.3,-0.1 0.4,0C20.6,22 20.6,22.1 20.5,22.3z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M15.9,18.6c0,0.7 -0.5,1.2 -1.2,1.2c-0.7,0 -1.2,-0.5 -1.2,-1.2c0,-0.7 0.5,-1.2 1.2,-1.2C15.3,17.4 15.9,18 15.9,18.6z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M21.6,18.6c0,0.7 -0.5,1.2 -1.2,1.2s-1.2,-0.5 -1.2,-1.2c0,-0.7 0.6,-1.2 1.2,-1.2S21.6,18 21.6,18.6z"/>
|
||||
android:pathData="M14.238,15.348c0.085,0.084 0.085,0.221 0,0.306 -0.465,0.462 -1.194,0.687 -2.231,0.687l-0.008,-0.002 -0.008,0.002c-1.036,0 -1.766,-0.225 -2.231,-0.688 -0.085,-0.084 -0.085,-0.221 0,-0.305 0.084,-0.084 0.222,-0.084 0.307,0 0.379,0.377 1.008,0.561 1.924,0.561l0.008,0.002 0.008,-0.002c0.915,0 1.544,-0.184 1.924,-0.561 0.085,-0.084 0.223,-0.084 0.307,0zM10.798,12.93c0,-0.507 -0.414,-0.919 -0.922,-0.919 -0.509,0 -0.923,0.412 -0.923,0.919 0,0.506 0.414,0.918 0.923,0.918 0.508,0.001 0.922,-0.411 0.922,-0.918zM24,12c0,6.627 -5.373,12 -12,12s-12,-5.373 -12,-12 5.373,-12 12,-12 12,5.373 12,12zM19,11.871c0,-0.851 -0.695,-1.543 -1.55,-1.543 -0.417,0 -0.795,0.167 -1.074,0.435 -1.056,-0.695 -2.485,-1.137 -4.066,-1.194l0.865,-2.724 2.343,0.549 -0.003,0.034c0,0.696 0.569,1.262 1.268,1.262 0.699,0 1.267,-0.566 1.267,-1.262s-0.568,-1.262 -1.267,-1.262c-0.537,0 -0.994,0.335 -1.179,0.804l-2.525,-0.592c-0.11,-0.027 -0.223,0.037 -0.257,0.145l-0.965,3.038c-1.656,0.02 -3.155,0.466 -4.258,1.181 -0.277,-0.255 -0.644,-0.415 -1.05,-0.415 -0.854,0.001 -1.549,0.693 -1.549,1.544 0,0.566 0.311,1.056 0.768,1.325 -0.03,0.164 -0.05,0.331 -0.05,0.5 0,2.281 2.805,4.137 6.253,4.137s6.253,-1.856 6.253,-4.137c0,-0.16 -0.017,-0.317 -0.044,-0.472 0.486,-0.261 0.82,-0.766 0.82,-1.353zM14.128,12.012c-0.509,0 -0.922,0.412 -0.922,0.919 0,0.506 0.414,0.918 0.922,0.918s0.922,-0.412 0.922,-0.918c0,-0.507 -0.413,-0.919 -0.922,-0.919z"/>
|
||||
</vector>
|
||||
|
|
11
app/src/main/res/drawable/ic_round_assignment_24.xml
Normal file
11
app/src/main/res/drawable/ic_round_assignment_24.xml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal"
|
||||
android:autoMirrored="true">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M19,3h-4.18C14.4,1.84 13.3,1 12,1s-2.4,0.84 -2.82,2L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM12,3c0.55,0 1,0.45 1,1s-0.45,1 -1,1 -1,-0.45 -1,-1 0.45,-1 1,-1zM13,17L8,17c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1h5c0.55,0 1,0.45 1,1s-0.45,1 -1,1zM16,13L8,13c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1h8c0.55,0 1,0.45 1,1s-0.45,1 -1,1zM16,9L8,9c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1h8c0.55,0 1,0.45 1,1s-0.45,1 -1,1z"/>
|
||||
</vector>
|
10
app/src/main/res/drawable/ic_round_close_24.xml
Normal file
10
app/src/main/res/drawable/ic_round_close_24.xml
Normal file
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M18.3,5.71L18.3,5.71c-0.39,-0.39 -1.02,-0.39 -1.41,0L12,10.59L7.11,5.7c-0.39,-0.39 -1.02,-0.39 -1.41,0l0,0c-0.39,0.39 -0.39,1.02 0,1.41L10.59,12L5.7,16.89c-0.39,0.39 -0.39,1.02 0,1.41l0,0c0.39,0.39 1.02,0.39 1.41,0L12,13.41l4.89,4.89c0.39,0.39 1.02,0.39 1.41,0l0,0c0.39,-0.39 0.39,-1.02 0,-1.41L13.41,12l4.89,-4.89C18.68,6.73 18.68,6.09 18.3,5.71z"/>
|
||||
</vector>
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue