Skip to content

Miuix theme#61

Open
yixing233 wants to merge 17 commits into1812z:mainfrom
yixing233:miuix-theme
Open

Miuix theme#61
yixing233 wants to merge 17 commits into1812z:mainfrom
yixing233:miuix-theme

Conversation

@yixing233
Copy link
Copy Markdown

基于Compose重构软件界面, 引入miuix设计风格.

Copilot AI review requested due to automatic review settings April 9, 2026 10:08
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

基于 PR 描述,本次改动旨在在现有 Flutter 工程内引入/对齐 MiuiX 设计风格,并开始推进 Android 端 Compose 化(新增 Compose 页面、ViewModel/Repository 与构建配置),同时对部分 Flutter 页面交互/样式做适配。

Changes:

  • Flutter 侧:引入统一 SectionLabel、调整部分页面布局/样式,并新增卡片式 push 动画路由。
  • Android 侧:启用 Compose + 引入 miuix kmp 依赖,新增 Apps/Channels/Blacklist/AI/Settings 等 Compose UI 与数据层。
  • 工程侧:更新 manifest、主题样式与 Gradle 配置以支持 Compose 入口与构建。

Reviewed changes

Copilot reviewed 42 out of 46 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
lib/widgets/batch_channel_settings_sheet.dart 使用公共 SectionLabel、调整底部弹窗交互与按钮样式
lib/widgets/app_list_widgets.dart SearchHeader 支持自定义搜索框背景色
lib/routes/card_push_route.dart 新增卡片式转场的 RouteBuilder
lib/pages/whitelist_page.dart 拆分说明文本与吸顶搜索栏;进入渠道页改用卡片式转场
lib/pages/settings_page.dart 页面跳转改用卡片式转场;部分 slider 文案样式调整
lib/pages/blacklist_page.dart AppBar 改为 pinned 的 SliverAppBar
lib/pages/app_channels_page.dart AppBar 改 pinned;渠道列表 UI 结构调整为卡片容器
lib/pages/ai_config_page.dart AppBar 改 pinned;超时显示样式调整
lib/main.dart MaterialApp builder 中禁用 Hero 控制器作用域
compose_migration_plan.md 新增 Compose 迁移计划文档
android/settings.gradle.kts 增加 Kotlin Compose 插件声明
android/gradle.properties 新增 Gradle/JDK 与 compileSdk 抑制相关配置
android/build.gradle.kts Windows 跨盘构建目录处理逻辑调整
android/app/src/main/res/values/styles.xml 新增 ComposeTheme(亮色)
android/app/src/main/res/values-night/styles.xml 新增 ComposeTheme(夜间)
android/app/src/main/kotlin/io/github/hyperisland/ui/settings/SettingsViewModel.kt 新增 Settings Compose 侧 ViewModel(含导入导出/桌面图标)
android/app/src/main/kotlin/io/github/hyperisland/ui/home/HomeViewModel.kt 新增 Home Compose 侧状态与重启作用域逻辑
android/app/src/main/kotlin/io/github/hyperisland/ui/home/HomeUiState.kt 新增 Home UI 状态模型
android/app/src/main/kotlin/io/github/hyperisland/ui/FaIcon.kt 新增 FontAwesome 字体图标封装
android/app/src/main/kotlin/io/github/hyperisland/ui/blacklist/GamePresets.kt 新增游戏包名预置列表
android/app/src/main/kotlin/io/github/hyperisland/ui/blacklist/BlacklistViewModel.kt 新增黑名单 ViewModel(筛选/批量操作/预置)
android/app/src/main/kotlin/io/github/hyperisland/ui/blacklist/BlacklistUiState.kt 新增黑名单 UI 状态模型
android/app/src/main/kotlin/io/github/hyperisland/ui/blacklist/BlacklistScreen.kt 新增黑名单 Compose UI(含下拉刷新/空态)
android/app/src/main/kotlin/io/github/hyperisland/ui/blacklist/BlacklistRepository.kt 新增黑名单数据读写与应用列表加载
android/app/src/main/kotlin/io/github/hyperisland/ui/app/AppsViewModel.kt 新增 Apps Compose 侧 ViewModel(含图标后台加载)
android/app/src/main/kotlin/io/github/hyperisland/ui/app/AppsUiState.kt 新增 Apps UI 状态与 AppItem 模型
android/app/src/main/kotlin/io/github/hyperisland/ui/app/AppsScreens.kt 新增 Apps/Channels/ChannelSettings Compose UI(含批量弹窗等)
android/app/src/main/kotlin/io/github/hyperisland/ui/app/AppFiltering.kt 新增应用筛选排序逻辑
android/app/src/main/kotlin/io/github/hyperisland/ui/app/AppChannelsViewModel.kt 新增渠道页 ViewModel(模板/超时/扩展项)
android/app/src/main/kotlin/io/github/hyperisland/ui/app/AppChannelsUiState.kt 新增渠道 UI 状态与 extras 模型
android/app/src/main/kotlin/io/github/hyperisland/ui/app/AppAdaptationRepository.kt 新增适配仓库(应用/图标/渠道/偏好读写)
android/app/src/main/kotlin/io/github/hyperisland/ui/ai/AiConfigViewModel.kt 新增 AI 配置 ViewModel(测试连接/日志)
android/app/src/main/kotlin/io/github/hyperisland/ui/ai/AiConfigState.kt 新增 AI 配置状态模型
android/app/src/main/kotlin/io/github/hyperisland/ui/ai/AiConfigScreen.kt 新增 AI 配置 Compose UI
android/app/src/main/kotlin/io/github/hyperisland/ui/ai/AiConfigRepository.kt 新增 AI 配置偏好读写
android/app/src/main/kotlin/io/github/hyperisland/NotificationChannelReader.kt 新增 Root 读取并解析通知渠道的实现
android/app/src/main/kotlin/io/github/hyperisland/data/prefs/SettingsState.kt 新增 SettingsState 数据模型
android/app/src/main/kotlin/io/github/hyperisland/data/prefs/SettingsRepository.kt 新增设置仓库(与 FlutterSharedPreferences 兼容)
android/app/src/main/kotlin/io/github/hyperisland/data/prefs/PrefKeys.kt 新增偏好 key 常量集合
android/app/src/main/kotlin/io/github/hyperisland/data/config/ConfigIoManager.kt 新增配置导入导出(文件/剪贴板/Uri)
android/app/src/main/AndroidManifest.xml 新增 ComposeMainActivity 入口;alias 指向 Compose;保留 Flutter MainActivity
android/app/build.gradle.kts 启用 Compose、引入 Compose/Miuix 依赖并调整 SDK 配置
.gitignore 忽略 tmp_* 文件

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread android/gradle.properties
Comment on lines 1 to 3
org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
org.gradle.java.home=C:/Program Files/Eclipse Adoptium/jdk-21.0.10.7-hotspot
org.gradle.caching=true
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

org.gradle.java.home points to a developer-specific absolute path. Committing this will break builds on other machines/CI. Move this to a local (unversioned) ~/.gradle/gradle.properties or rely on JAVA_HOME / toolchains instead.

Copilot uses AI. Check for mistakes.
Comment thread android/gradle.properties
Comment on lines 6 to +8
android.useAndroidX=true
android.enableJetifier=true
android.suppressUnsupportedCompileSdk=35
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

android.suppressUnsupportedCompileSdk is set to 35, but the app module is compiling with compileSdk = 36. If this flag is needed, it should match the compileSdk being used (or be removed if no longer needed), otherwise the intended suppression may not apply and CI may still warn/fail.

Copilot uses AI. Check for mistakes.
Comment on lines +19 to +26
<style name="ComposeTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">@android:color/white</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
<item name="android:enforceStatusBarContrast">false</item>
<item name="android:enforceNavigationBarContrast">false</item>
</style>
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

ComposeTheme in values-night uses a Light parent theme and a white windowBackground, which will make dark mode show a light window background (and can cause a white flash on launch). Use a dark parent (e.g. Theme.Black.NoTitleBar or a dark Material theme) and a dark windowBackground for night resources.

Copilot uses AI. Check for mistakes.
Comment on lines 59 to 63
defaultConfig {
applicationId = "io.github.hyperisland"
minSdk = 27
targetSdk = flutter.targetSdkVersion
minSdk = 31
targetSdk = 36
versionCode = flutter.versionCode
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

minSdk was raised to 31. This drops support for Android 8.1–11 devices and is a breaking distribution change. If this isn’t strictly required, consider keeping the previous minSdk (or gate Compose-only features behind API checks) and document the rationale in release notes/README.

Copilot uses AI. Check for mistakes.
Comment on lines +103 to +107
tasks.configureEach {
if (name.contains("AarMetadata", ignoreCase = true)) {
enabled = false
}
}
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

Disabling all tasks whose name contains AarMetadata is very broad and can mask dependency minSdk/metadata issues (and make builds harder to diagnose). Prefer fixing the underlying metadata/minSdk mismatch or narrowly disabling the specific failing task/variant with a clear comment and condition.

Copilot uses AI. Check for mistakes.
Comment on lines 452 to +505
SliverPadding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 32),
sliver: SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
final ch = channels[index];
final isFirst = index == 0;
final isLast = index == channels.length - 1;
final channelEnabled = _isEnabled(ch.id);
final template =
_channelTemplates[ch.id] ?? kTemplateNotificationIsland;
final extras = _channelExtras[ch.id] ?? {};

return _ChannelTile(
channel: ch,
channelEnabled: channelEnabled,
appEnabled: _appEnabled,
template: template,
templateLabels: _templateLabels,
renderer:
extras['renderer'] ?? kRendererImageTextWithButtons4,
rendererLabels: _rendererLabels,
importanceLabel: _importanceLabel(ch.importance, l10n),
isFirst: isFirst,
isLast: isLast,
iconMode: extras['icon'] ?? kIconModeAuto,
focusIconMode: extras['focus_icon'] ?? kIconModeAuto,
focusNotif: extras['focus'] ?? kTriOptDefault,
preserveSmallIcon:
extras['preserve_small_icon'] ?? kTriOptDefault,
showIslandIcon:
extras['show_island_icon'] ?? kTriOptDefault,
firstFloat: extras['first_float'] ?? kTriOptDefault,
enableFloat: extras['enable_float'] ?? kTriOptDefault,
islandTimeout: extras['timeout'] ?? '5',
marquee: extras['marquee'] ?? kTriOptDefault,
restoreLockscreen:
extras['restore_lockscreen'] ?? kTriOptDefault,
highlightColor: extras['highlight_color'] ?? '',
showLeftHighlight:
extras['show_left_highlight'] ?? kTriOptOff,
showRightHighlight:
extras['show_right_highlight'] ?? kTriOptOff,
onToggle: (v) => _toggle(ch.id, v),
onSettingsApplied: (s) => _applyChannelSettings(ch.id, s),
);
},
childCount: channels.length,
addAutomaticKeepAlives: false,
sliver: SliverToBoxAdapter(
child: Material(
color: cs.surfaceContainerHighest,
borderRadius: BorderRadius.circular(16),
clipBehavior: Clip.antiAlias,
child: Column(
mainAxisSize: MainAxisSize.min,
children: List.generate(channels.length, (index) {
final ch = channels[index];
final isLast = index == channels.length - 1;
final channelEnabled = _isEnabled(ch.id);
final template =
_channelTemplates[ch.id] ??
kTemplateNotificationIsland;
final extras = _channelExtras[ch.id] ?? {};

return _ChannelTile(
channel: ch,
channelEnabled: channelEnabled,
appEnabled: _appEnabled,
template: template,
templateLabels: _templateLabels,
renderer:
extras['renderer'] ??
kRendererImageTextWithButtons4,
rendererLabels: _rendererLabels,
importanceLabel: _importanceLabel(ch.importance, l10n),
isLast: isLast,
iconMode: extras['icon'] ?? kIconModeAuto,
focusIconMode: extras['focus_icon'] ?? kIconModeAuto,
focusNotif: extras['focus'] ?? kTriOptDefault,
preserveSmallIcon:
extras['preserve_small_icon'] ?? kTriOptDefault,
showIslandIcon:
extras['show_island_icon'] ?? kTriOptDefault,
firstFloat: extras['first_float'] ?? kTriOptDefault,
enableFloat: extras['enable_float'] ?? kTriOptDefault,
islandTimeout: extras['timeout'] ?? '5',
marquee: extras['marquee'] ?? kTriOptDefault,
restoreLockscreen:
extras['restore_lockscreen'] ?? kTriOptDefault,
highlightColor: extras['highlight_color'] ?? '',
showLeftHighlight:
extras['show_left_highlight'] ?? kTriOptOff,
showRightHighlight:
extras['show_right_highlight'] ?? kTriOptOff,
onToggle: (v) => _toggle(ch.id, v),
onSettingsApplied: (s) =>
_applyChannelSettings(ch.id, s),
);
}),
),
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

This replaces a SliverList with a Column(List.generate(...)) inside a SliverToBoxAdapter, which eagerly builds all channel rows and loses sliver/lazy list virtualization. This can cause jank for apps with many channels. Consider keeping a SliverList/SliverChildBuilderDelegate and styling via a wrapping card + per-row dividers instead.

Copilot uses AI. Check for mistakes.
Comment on lines +10 to +24
val normalizedQuery = query.trim().lowercase()
return apps
.filter { app ->
val matchSystem =
showSystemApps || !app.isSystem || alwaysVisiblePackages.contains(app.packageName)
val matchQuery =
normalizedQuery.isBlank() ||
app.appName.lowercase().contains(normalizedQuery) ||
app.packageName.lowercase().contains(normalizedQuery)
matchSystem && matchQuery
}
.sortedWith(
compareByDescending<AppItem> { prioritizedPackages.contains(it.packageName) }
.thenBy { it.appName.lowercase() },
)
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

lowercase() without an explicit locale is locale-sensitive (e.g. Turkish casing rules) and can make search/sort behavior inconsistent across devices. For deterministic filtering/sorting, use lowercase(Locale.ROOT) (and import java.util.Locale).

Copilot uses AI. Check for mistakes.
Comment on lines +40 to +44
)
}.getOrNull()
}
.sortedBy { it.appName.lowercase() }
.toList()
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

This sorts apps using it.appName.lowercase() which is locale-sensitive and can produce inconsistent ordering across locales. Prefer lowercase(Locale.ROOT) (import java.util.Locale) to keep ordering stable.

Copilot uses AI. Check for mistakes.
Comment on lines +80 to +110
),
verticalArrangement = Arrangement.spacedBy(12.dp),
) {
Text("AI 增强", style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.SemiBold)
MiuixCard(modifier = Modifier.fillMaxWidth()) {
Row(
modifier = Modifier.fillMaxWidth().clip(RoundedCornerShape(18.dp)).padding(16.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
Column(modifier = Modifier.weight(1f).padding(end = 12.dp)) {
Text("启用 AI 摘要")
Spacer(modifier = Modifier.height(4.dp))
Text("由 AI 生成超级岛左右文本,超时或失败时自动回退", style = MaterialTheme.typography.bodySmall)
}
MiuixSwitch(
checked = state.enabled,
onCheckedChange = { onUpdate(state.copy(enabled = it)) },
)
}
}
Spacer(modifier = Modifier.height(4.dp))

if (state.enabled) {
Text("API 参数", style = MaterialTheme.typography.titleMedium, fontWeight = FontWeight.SemiBold)
MiuixCard(modifier = Modifier.fillMaxWidth()) {
Column(modifier = Modifier.fillMaxWidth().clip(RoundedCornerShape(18.dp)).padding(16.dp), verticalArrangement = Arrangement.spacedBy(12.dp)) {
MiuixTextField(
value = state.url,
onValueChange = { onUpdate(state.copy(url = it)) },
label = "API 地址(必须完整)",
Copy link

Copilot AI Apr 9, 2026

Choose a reason for hiding this comment

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

New Compose UI strings are hardcoded in code. This makes localization difficult and diverges from existing Android code that uses R.string resources (e.g. MainActivity.kt). Please move user-visible text into res/values/strings.xml and use stringResource(...) / context.getString(...) so translations can be added consistently.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants