Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sg/wizard with steps #1572

Draft
wants to merge 95 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
4b148d3
wizard host
StageGuard Jan 18, 2025
be94435
fix
StageGuard Jan 18, 2025
2b55d6b
remove TestOnly
StageGuard Jan 18, 2025
9d720ae
update
StageGuard Jan 18, 2025
0494491
box states
StageGuard Jan 18, 2025
f6c85c2
Don't handle wizard data at controller.
StageGuard Jan 19, 2025
acdbb4b
rename builder to scope
StageGuard Jan 19, 2025
5e9a142
remember
StageGuard Jan 19, 2025
24a7eb3
remove flow extension
StageGuard Jan 19, 2025
ae75a1d
add doc
StageGuard Jan 19, 2025
70bb7c6
Don't handle any data
StageGuard Jan 19, 2025
074d7f8
add transition animation
StageGuard Jan 19, 2025
9cf51dd
extract scaffold bars
StageGuard Jan 19, 2025
adc8574
fix
StageGuard Jan 21, 2025
70bdbaf
add content to disposable key
StageGuard Jan 21, 2025
e0d0637
scrollable
StageGuard Jan 21, 2025
e3c40d2
replace `scrollable` to `verticalScroll`
StageGuard Jan 22, 2025
d63d3f9
commit current
StageGuard Jan 22, 2025
9222034
add UI test for WizardNavHost
StageGuard Jan 22, 2025
a87c6ff
Merge branch 'sg/wizard' into sg/wizard-with-steps
StageGuard Jan 22, 2025
aed018d
remove WizardHostTest
StageGuard Jan 22, 2025
d5067c9
Merge branch 'main' into sg/wizard-with-steps
StageGuard Jan 22, 2025
380337f
derive `currentProxyTestMode` from `proxyConfig`
StageGuard Jan 22, 2025
80f0955
Merge branch 'main' into sg/wizard-with-steps
StageGuard Jan 22, 2025
4d40857
apply theme
StageGuard Jan 22, 2025
8879dca
commonize `SystemBarColorEffect`
StageGuard Jan 22, 2025
34c9869
adapt status bar color
StageGuard Jan 22, 2025
9dc0c27
optimize
StageGuard Jan 22, 2025
57087ef
bit torrent step
StageGuard Jan 22, 2025
4104c82
bit torrent step
StageGuard Jan 22, 2025
446178d
fix jdk usage
StageGuard Jan 22, 2025
0b7f926
do not depend on WindowAdaptiveInfo
StageGuard Jan 23, 2025
cdf1834
combine states
StageGuard Jan 23, 2025
8fc8c90
immediately apply settings in wizard.
StageGuard Jan 23, 2025
44bbf73
missing param
StageGuard Jan 23, 2025
dbda25d
bangumi authorize page
StageGuard Jan 23, 2025
2a3a140
contact actions
StageGuard Jan 23, 2025
2f94acc
adjust icon color
StageGuard Jan 23, 2025
0b5215f
handle vertical scroll by step-self
StageGuard Jan 23, 2025
7b75879
logic for authorize
StageGuard Jan 23, 2025
906aad9
Merge branch 'main' into sg/wizard-with-steps
StageGuard Jan 24, 2025
c561c3d
update
StageGuard Jan 24, 2025
fa901bd
auto scroll down after waiting for 60s to get authorization result
StageGuard Jan 24, 2025
93d4d28
add skip button
StageGuard Jan 24, 2025
6c3fbf1
㱇 guest session
StageGuard Jan 24, 2025
7a12fc4
emit guest session branch
StageGuard Jan 24, 2025
fff28c2
click item
StageGuard Jan 24, 2025
c7568f5
auth via token
StageGuard Jan 24, 2025
b04b4ce
optimize
StageGuard Jan 24, 2025
166521f
move icon to foundation
StageGuard Jan 24, 2025
fc2468c
stateInBackground
StageGuard Jan 24, 2025
04fd1f1
New wizard host: remove pinned bottom control bar
StageGuard Jan 26, 2025
300ea35
adapt large top app bar
StageGuard Jan 26, 2025
346462a
restore
StageGuard Jan 26, 2025
b74d0a6
Merge branch 'main' into sg/wizard-with-steps
StageGuard Jan 27, 2025
66c5487
adapt new client provider
StageGuard Jan 27, 2025
9d3786a
adapt new client provider
StageGuard Jan 27, 2025
f8b407e
Merge branch 'main' into sg/wizard-with-steps
StageGuard Jan 27, 2025
b21cb03
Merge branch 'main' into sg/wizard-with-steps
StageGuard Jan 31, 2025
ac3f15f
use local navigation motion scheme
StageGuard Jan 31, 2025
8d27ed4
don't show dynamic color settings on non-Android
StageGuard Jan 31, 2025
e51b7c6
provide list state via `WizardStepScope` for steps
StageGuard Jan 31, 2025
5655e89
optimize BangumiAuthorize page
StageGuard Jan 31, 2025
a673691
optimize token authorize
StageGuard Jan 31, 2025
e144b77
move QA expand button to right
StageGuard Jan 31, 2025
c83ae9e
group
StageGuard Jan 31, 2025
7e4943e
remove `HeroScaffold`
StageGuard Feb 2, 2025
5010c66
refactor colors
StageGuard Feb 2, 2025
a4be0f3
rename
StageGuard Feb 2, 2025
778cd89
fix theme panel indicator
StageGuard Feb 2, 2025
8131da7
change order of theme panel
StageGuard Feb 2, 2025
40cfa57
extract ColorSchemePreviewItem
StageGuard Feb 2, 2025
c3cce5b
fix role of theme panel
StageGuard Feb 2, 2025
8921cda
max 4 items
StageGuard Feb 2, 2025
e8eb7b8
Merge branch 'main' into sg/wizard-with-steps
StageGuard Feb 2, 2025
0de9577
use AniMotionScheme
StageGuard Feb 2, 2025
b1ccc3f
migrate all UI state in ConfigureProxy step to ConfigureProxyUIState
StageGuard Feb 2, 2025
defebe4
add data layer of UI for ConfigureProxy step
StageGuard Feb 2, 2025
17c15ec
add missing content description for icons
StageGuard Feb 2, 2025
6f9403f
fix param name
StageGuard Feb 2, 2025
0f2b843
Switch Item
StageGuard Feb 2, 2025
67b0943
remove color changes
StageGuard Feb 2, 2025
2df1e64
optimize ui
StageGuard Feb 2, 2025
e80ccb4
optimize clickable
StageGuard Feb 2, 2025
6972c76
optimize first splash screen
StageGuard Feb 2, 2025
110e0d1
rename itemVerticalSpace to itemVerticalSpacing
StageGuard Feb 2, 2025
72de4a8
remove crossfade
StageGuard Feb 2, 2025
9bdb875
rearrange
StageGuard Feb 2, 2025
c0d1aff
lambda argument name
StageGuard Feb 2, 2025
4100ca5
fix scroll
StageGuard Feb 2, 2025
da73e85
fix
StageGuard Feb 2, 2025
c07100c
todo
StageGuard Feb 2, 2025
89031fa
todo
StageGuard Feb 2, 2025
a27edcd
todo
StageGuard Feb 2, 2025
a4493ee
move ThemePreviewPanel and ColorButton to `ui-settings`
StageGuard Feb 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ import androidx.compose.runtime.Stable
import androidx.compose.ui.graphics.Color
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient

val DEFAULT_SEED_COLOR = Color(0xFF4F378B)
import me.him188.ani.app.ui.theme.DefaultSeedColor

@Serializable
enum class DarkMode {
Expand All @@ -29,13 +28,13 @@ data class ThemeSettings(
val useDynamicTheme: Boolean = false, // only supported on Android with Build.VERSION.SDK_INT >= 31
// TODO: Default "true" if supported (on Android, Build.VERSION.SDK_INT >= 31)
val useBlackBackground: Boolean = false,
val seedColorValue: ULong = DEFAULT_SEED_COLOR.value,
val seedColorValue: ULong = DefaultSeedColor.value,
@Suppress("PropertyName") @Transient val _placeholder: Int = 0,
) {
@Transient
val seedColor: Color = Color(seedColorValue).let {
// 4.4.0-alpha01 的默认是 Color.Unspecified, 4.4.0-alpha02 默认是 DEFAULT_SEED_COLOR. 所以要替换一下
if (it == Color.Unspecified) DEFAULT_SEED_COLOR else it
if (it == Color.Unspecified) DefaultSeedColor else it
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import kotlinx.coroutines.flow.transformLatest
import kotlinx.coroutines.isActive
import me.him188.ani.app.data.models.preference.ProxyConfig
import me.him188.ani.app.data.models.preference.ProxyMode
import me.him188.ani.app.data.models.preference.ProxySettings
import me.him188.ani.app.data.repository.user.SettingsRepository
import me.him188.ani.app.domain.media.fetch.toClientProxyConfig
import me.him188.ani.app.platform.SystemProxyDetector
Expand Down Expand Up @@ -87,9 +88,16 @@ class SystemProxyProvider(
class SettingsBasedProxyProvider(
private val settingsRepository: SettingsRepository,
backgroundScope: CoroutineScope,
) : ProxyProvider by ProxySettingsFlowProxyProvider(
settingsRepository.proxySettings.flow, backgroundScope,
)
Comment on lines 88 to +93
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use a constructor-like a function to construct a ProxySettingsFlowProxyProvider instead of making a type.


class ProxySettingsFlowProxyProvider(
private val flow: Flow<ProxySettings>,
backgroundScope: CoroutineScope,
) : ProxyProvider {
override val proxy: Flow<ProxyConfig?> by lazy {
settingsRepository.proxySettings.flow.map { it.default }
flow.map { it.default }
.distinctUntilChanged()
.transformLatest { settings ->
coroutineScope {
Expand All @@ -104,5 +112,4 @@ class SettingsBasedProxyProvider(
}
.shareIn(backgroundScope, started = SharingStarted.WhileSubscribed(), replay = 1)
}

}
Original file line number Diff line number Diff line change
@@ -1,19 +1,51 @@
/*
* Copyright (C) 2024-2025 OpenAni and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license, which can be found at the following link.
*
* https://github.com/open-ani/ani/blob/main/LICENSE
*/

package me.him188.ani.app.platform

interface PermissionManager {
/**
* 检查应用是否有通知权限
*/
fun checkNotificationPermission(context: ContextMP): Boolean

/**
* 请求应用通知权限
*
* @return `true` 成功授权, `false` 拒绝授权或保持现状
*/
suspend fun requestNotificationPermission(context: ContextMP): Boolean

/**
* 打开系统设置手动授权通知权限
*/
fun openSystemNotificationSettings(context: ContextMP)

/**
* Android only. 请求一个完全授予可读写权限的外部共享空间路径,返回其 URL string
*/
suspend fun requestExternalDocumentTree(context: ContextMP): String?
}

object GrantedPermissionManager : PermissionManager {
override fun checkNotificationPermission(context: ContextMP): Boolean {
return true
}

override suspend fun requestNotificationPermission(context: ContextMP): Boolean {
return true
}

override fun openSystemNotificationSettings(context: ContextMP) {

}

override suspend fun requestExternalDocumentTree(context: ContextMP): String? {
return null
}
Expand Down
22 changes: 22 additions & 0 deletions app/shared/app-platform/src/commonMain/kotlin/ui/theme/Color.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
@file:JvmName("ColorKt_platform")
/*
* Copyright (C) 2024-2025 OpenAni and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license, which can be found at the following link.
*
* https://github.com/open-ani/ani/blob/main/LICENSE
*/

package me.him188.ani.app.ui.theme

import androidx.compose.ui.graphics.Color
import kotlin.jvm.JvmName

// region Note: You should only add UI properties when it is accessed both `ui-foundation` and `app-data`

val DefaultSeedColor = Color(0xFF4F378B)
val AnimekoIconColor = Color(0, 88, 160)
val BangumiNextIconColor = Color(240, 145, 153)

// endregion
Original file line number Diff line number Diff line change
@@ -1,23 +1,51 @@
/*
* Copyright (C) 2024-2025 OpenAni and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license, which can be found at the following link.
*
* https://github.com/open-ani/ani/blob/main/LICENSE
*/

package me.him188.ani.app.platform

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.provider.Settings
import androidx.core.app.NotificationManagerCompat
import me.him188.ani.utils.logging.info
import me.him188.ani.utils.logging.logger

class AndroidPermissionManager : PermissionManager {
private val logger = logger<AndroidPermissionManager>()

override fun checkNotificationPermission(context: ContextMP): Boolean {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) return true
val activity = context.findActivity() as? BaseComponentActivity ?: return false
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
activity.checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) ==
PackageManager.PERMISSION_GRANTED
} else {
NotificationManagerCompat.from(activity).areNotificationsEnabled()
}
}

override suspend fun requestNotificationPermission(context: ContextMP): Boolean {
// To send notifications on API levels below 32, you don't need to request the POST_NOTIFICATIONS permission,
// as it is only required for API level 33 (Android 13) and above.
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) return true

return requestPermission(context, Manifest.permission.POST_NOTIFICATIONS)
val activity = context.findActivity() as? BaseComponentActivity ?: return false
return activity.requestPermission(Manifest.permission.POST_NOTIFICATIONS)
}

private suspend fun requestPermission(context: ContextMP, permission: String): Boolean {
val activity = context.findActivity() as? BaseComponentActivity ?: return false
return activity.requestPermission(permission)
override fun openSystemNotificationSettings(context: ContextMP) {
val openSystemNotificationIntent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
}
context.startActivity(openSystemNotificationIntent)
}

override suspend fun requestExternalDocumentTree(context: ContextMP): String? {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
/*
* Copyright (C) 2024-2025 OpenAni and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license, which can be found at the following link.
*
* https://github.com/open-ani/ani/blob/main/LICENSE
*/

package me.him188.ani.app.ui.settings.tabs.media

import android.content.Context
Expand Down Expand Up @@ -208,6 +217,14 @@ private fun createTestPermissionManager(
return object : PermissionManager {
var requested = false

override fun checkNotificationPermission(context: ContextMP): Boolean {
error("unreachable test")
}

override fun openSystemNotificationSettings(context: ContextMP) {
error("unreachable test")
}

override suspend fun requestNotificationPermission(context: ContextMP): Nothing {
error("unreachable test")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

package me.him188.ani.app.ui.wizard.navigation

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
Expand Down Expand Up @@ -51,29 +50,6 @@ class WizardNavHostTest {
WizardNavHost(
wizardController,
modifier = Modifier.fillMaxSize(),
indicatorBar = {
WizardDefaults.StepTopAppBar(
currentStep = it.currentStepIndex + 1,
totalStep = it.stepCount,
indicatorStepTextTestTag = TAG_INDICATOR_TEXT,
) {
it.currentStep.stepName.invoke()
}
},
controlBar = {
WizardDefaults.StepControlBar(
forwardAction = {
Box(Modifier.testTag(TAG_BUTTON_NEXT_STEP)) {
it.currentStep.forwardButton.invoke()
}
},
backwardAction = {
Box(Modifier.testTag(TAG_BUTTON_PREV_STEP)) {
it.currentStep.backwardButton.invoke()
}
},
)
},
) {
step(
"step_1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import android.os.Build
import androidx.activity.ComponentActivity
import androidx.activity.SystemBarStyle
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.ColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
Expand All @@ -23,7 +22,6 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import com.materialkolor.PaletteStyle
import com.materialkolor.dynamicColorScheme
import me.him188.ani.app.data.models.preference.DarkMode
import me.him188.ani.app.platform.findActivity

@Composable
Expand Down Expand Up @@ -57,13 +55,7 @@ actual fun appColorScheme(
}

@Composable
fun SystemBarColorEffect(
isDark: Boolean = when (LocalThemeSettings.current.darkMode) {
DarkMode.LIGHT -> false
DarkMode.DARK -> true
DarkMode.AUTO -> isSystemInDarkTheme()
},
) {
actual fun SystemBarColorEffect(isDark: Boolean) {
// Set statusBarStyle & navigationBarStyle
val activity = LocalContext.current.findActivity() as? ComponentActivity
if (activity != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (C) 2024-2025 OpenAni and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license, which can be found at the following link.
*
* https://github.com/open-ani/ani/blob/main/LICENSE
*/

package me.him188.ani.app.ui.theme

import androidx.compose.foundation.layout.FlowRow
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.tooling.preview.Preview
import me.him188.ani.app.ui.foundation.ProvideFoundationCompositionLocalsForPreview
import me.him188.ani.app.ui.foundation.theme.AniThemeDefaults

@Preview
@Composable
fun PreviewColorButton() {
ProvideFoundationCompositionLocalsForPreview {
FlowRow {
var currentColor by remember { mutableStateOf(AniThemeDefaults.themeColorOptions[0]) }
AniThemeDefaults.themeColorOptions.forEach {
me.him188.ani.app.ui.settings.tabs.theme.ColorButton(
onClick = { currentColor = it },
baseColor = it,
selected = currentColor == it,
)
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (C) 2024-2025 OpenAni and contributors.
*
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license, which can be found at the following link.
*
* https://github.com/open-ani/ani/blob/main/LICENSE
*/

package me.him188.ani.app.ui.theme

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import me.him188.ani.app.ui.foundation.ProvideFoundationCompositionLocalsForPreview
import me.him188.ani.app.ui.foundation.theme.appColorScheme

@Preview
@Composable
fun PreviewThemePreviewPanel() {
ProvideFoundationCompositionLocalsForPreview {
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
me.him188.ani.app.ui.settings.tabs.theme.ThemePreviewPanel(
colorScheme = appColorScheme(isDark = false),
modifier = Modifier.size(96.dp, 146.dp),
)
me.him188.ani.app.ui.settings.tabs.theme.ThemePreviewPanel(
colorScheme = appColorScheme(isDark = true),
modifier = Modifier.size(96.dp, 146.dp),
)
me.him188.ani.app.ui.settings.tabs.theme.DiagonalMixedThemePreviewPanel(
leftTopColorScheme = appColorScheme(isDark = false),
rightBottomColorScheme = appColorScheme(isDark = true),
modifier = Modifier.size(96.dp, 146.dp),
)
}
}
}
Loading
Loading