[android] 风格包 ZIP 选中文件后未导入,刷新无效

Fechada
#1,320 4 comentários 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 1 dia

Um pull request relacionado já foi integrado.

  • #1322 de @HKLHaoBin — integrado

Avaliação

Dificuldade
4/5
Tempo estimado
3-5 dias
Facilidade para iniciantes
22/100
Tipo de issue
Bug
Clareza
Precisa de esclarecimento
Status de atividade
Ativa
Stack de tecnologia
android, rust, tauri, typescript
Domínio
frontend, mobile

Direção de pesquisa

Start with the import handler in src/pages/Style.tsx (handleImportZip, around lines 586-613) and the error toast in components/SavedToast.tsx, then check mobile_runtime.rs and capabilities/mobile.json for the dialog plugin setup. The backend path is commands/style_packs.rs, which reads content:// URIs. Nothing is reproduced yet, so the first step is adding the four observation points on one known build. Done means the root cause is confirmed on a device and the import succeeds without a broader storage permission.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

area:style bug needs-repro P2 platform:android

**2026-10-31 新证据更新:**用户已确认文件选择器正常打开,选中文件并点击“选择”后仍未导入,刷新无效。新日志含 3 次 source_kind=content-uri 后端导入入口记录,排查重点应移至 URI 读取、ZIP 校验/持久化及前端结果链路;具体根因仍未确认。完整脱敏证据与更新后的假设见补充调研。以下正文保留首次调研历史,其中“选择器是否出现尚未区分”的描述已由本更新澄清。

现象

用户反馈:在荣耀 Android 环境进入「风格包」,点击「导入 ZIP」没有可见反应,无法完成本地 ZIP 风格包导入。

本 issue 是用户日志审阅与当前上游源码调研的结果,没有在该设备真机复现,根因未确认;不应把静态候选原因当成已证实的设备缺陷。

环境与复现步骤
  • 平台:Android;应用包名 com.openless.app。
  • 用户提供的环境描述为「荣耀 Magic 11」。日志中的相关口述转写为「系统是荣耀 Magic 11」,因此它可能指系统版本,而非硬件型号;保留原始描述,具体机型、MagicOS 完整版本及 Android API level 待确认,不据此推定型号。
  • 当前安装的 OpenLess 版本、build SHA、系统 WebView 版本未知。日志中的 v2.0.1+build.20261016 是此前更新器尝试安装的目标,且安装失败,不能用它确定当前安装版本。
  • 日志:openless-2026-10-31T11-40-09.log.txt,包含 2026-10-23、10-30、10-31 多次启动,主要相关窗口为 2026-10-31 11:26–11:39 UTC。

复现步骤(来自用户报告,非本次真机验证):

  1. 在上述荣耀 Android 环境打开 OpenLess。
  2. 进入「风格包」。
  3. 点击「导入 ZIP」。
  4. 观察系统文件选择器是否出现、按钮是否一直显示加载、是否出现错误,以及风格列表是否变化。

实际:用户感知为点击没有反应,未完成导入。尚未区分「选择器完全没弹出」「选中文件后不返回」「报错短暂闪过」三种子情况,也没有可验证的失败 ZIP 样本。

期望:点击后打开文件选择器;选择合法 ZIP 后导入并在列表中显示;取消应恢复可操作状态;异常应有清晰、可读、可再次显示的反馈。

日志证据与覆盖边界

原日志只读审阅。以下是最小脱敏摘录,行号对应原文件;完整日志包含无关语音转写和会话标识,故不直接公开。

L130 2026-10-31T11:27:22.500136706Z [INFO] [style-pack] command export requested id=builtin.light target_path=content://<已脱敏>
L131 2026-10-31T11:27:24.057395039Z [INFO] [style-pack] command create_from_template name=<已脱敏> base_mode=Light
L132 2026-10-31T11:27:24.328323112Z [INFO] [style-pack] command preview_runtime id=<已脱敏> base_mode=Light prompt_chars=370
L139 2026-10-31T11:28:08.683321064Z [INFO] [style-pack] command create_from_template name=<已脱敏> base_mode=Light
L140 2026-10-31T11:28:08.876978199Z [INFO] [style-pack] command preview_runtime id=<已脱敏> base_mode=Light prompt_chars=370
  • 原文件 L365–367 的语音转写包含用户当时所述「点击导入 zip 没反应」;L989 包含上述系统环境口述。这里只提取问题相关信息,不公开其余转写。
  • 全文检索未找到 [style-pack] command import requested。这只能说明未采集到该事件,不能证明按钮没有执行或后端绝对没有被调用:用户 APK 与所审源码版本未对应,且前端点击、插件异常、Activity 返回均无完整记录。
  • L130 说明至少一次导出命令收到了 Android content:// URI,不代表导出成功,也不能证明导入选择器正常;导入与导出使用不同 Intent 路径。
  • 创建模板、预览能到达后端,不能将本次现象归结为整个风格页 IPC 均失效。
  • 日志中的更新签名错误、加密同步初始化阶段 ERROR、悬浮窗销毁和录音空输入等没有证据与此次 ZIP 导入相关,不作为根因。
行为契约检查
契约 预期与来源 结论
N1 点击导入后出现选择器或可读错误 用户期望及 handleImportZip 调用链 用户报告违反可见结果契约;日志不足以判定选择器启动/返回的具体失败边界
N2 用户选择合法 ZIP 后导入并刷新列表 importStylePackFromZip → loadPacks(imported.id) 证据不足:没有选中文件、URI 读取或归档解析的可关联记录
N3 错误反馈可读,取消后恢复按钮 页面错误处理及按钮 busy 状态 静态发现提示可见期不一致;该设备是否因此漏看错误待验证

当前上游源码调研

审阅基线:beta 的 2b89ecdd727f842443bded33d8dfcf1a21efe598。这不是用户 APK 的已知 SHA。

  1. Style.tsx L586–613:先置 busy=importing,动态加载 @tauri-apps/plugin-dialog,调用带 zip filter 的 open({ multiple:false });仅返回字符串后才调用导入 IPC。null 会静默返回;异常只交给 showSaveStatus,此处没有记录到应用日志。若 open() Promise 一直 pending,finally 不执行,按钮持续加载/禁用。
  2. mobile_runtime.rs 已初始化 dialog 插件;mobile.json 对 main/qa 授予 dialog:default。目前没有源码依据认定是漏初始化/漏 capability,但用户实际 APK 仍需核对。
  3. commands/style_packs.rs 已针对 Android content:// 通过受限 ContentResolver reader 读取,再进行字节导入。不能泛化成「Android URI 被当普通路径读取」;该支持来自已合并 #942。
  4. Style.tsx L218–235 将失败状态保留 6000ms,但页面传入 SavedToast 时,普通失败未传 durationMs;SavedToast.tsx 内部仍默认 800ms 隐藏,且 whiteSpace: nowrap。因此页面的 6 秒计时不等于错误实际可见 6 秒。此项是静态可确认的反馈风险,不是本次导入失败根因的确认。
  5. 当前 Cargo.lock 的 dialog 为 2.8.3。其 Android 实现 使用 ACTION_GET_CONTENT、CATEGORY_OPENABLE、扩展名到 MIME 的映射,以及 EXTRA_MIME_TYPES;保存对话框另用 ACTION_CREATE_DOCUMENT。

Android 官方说明通过 Storage Access Framework 由用户选择文档的访问不需要通用存储权限。因此「设置里无法授予存储权限」本身不能证明失败原因,不建议以增加所有文件访问权限作为默认修复。

待验证假设(均未确认)

ID 假设 / 对应契约 可证伪预测 若成立的修复方向 观测点
H1 Android 文件选择器 Intent/MIME 处理失败(N1) 点击后调用到插件,启动阶段抛出异常;不带 filter 的受控对照可打开,而当前 ZIP filter 不可打开 修复已证实的 Intent/MIME 兼容分支,必要时提供明确的用户触发兜底;保留归档内容校验 P1/P2/P3
H2 Activity 结果或跨层 Promise 未完成(N1/N3) Intent 已启动或已返回,但前端没有终态;按钮持续加载;需按 APK 版本定位具体桥接边界 修复结果回调/桥接生命周期,确保成功、取消、失败均结算一次 P1/P2/P3
H3 插件/读取/归档错误确已返回,但短提示使用户感知无响应(N1/N2/N3) 记录到稳定错误类别,busy 已恢复;UI 错误很快消失或窄屏不可读 对应真实失败修复,并让失败信息持续可读、可重复触发;不能仅延长 toast 就声称导入已修复 P1/P3/P4

相关线索而非结论:

  • tauri-apps/plugins-workspace#3366 是尚未关闭的 Android dialog Promise 首次不完成报告,但涉及不同应用/插件版本,不能认定与本次相同;不采用该讨论中的定时 no-op 轮询作为修复。
  • tauri-apps/plugins-workspace#2826 是历史 Android filters 不弹选择器报告,已关闭且旧实现涉及 ACTION_PICK,当前 2.8.3 为 ACTION_GET_CONTENT;只能帮助设计 MIME 对照,不能套用旧根因。
  • #878 / 已合并 #879 是市场「安装到本地」临时目录问题,与本 issue 的本地「导入 ZIP」入口不同,不按重复 issue 处理。

建议下一步

  1. 补齐实际 APK 版本/SHA、设备型号、完整系统与 WebView 版本;确认选择器出现与否、按钮是否一直加载,以及失败发生在选择文件之前还是之后。
  2. 对同一已知构建做 4 个有界、安全观测点:P1 前端点击与 busy;P2 Android Intent 启动/结果回调;P3 前端 dialog 成功/取消/错误终态;P4 后端导入入口、受限读取与解析结果。仅记录阶段、枚举错误类别、字节数等,禁止记录完整 URI、ZIP 内容、提示词或凭据;必要时同步采集脱敏 logcat。
  3. 在观测证明 MIME 问题后才对照 ZIP filter 与通用文档选择;在观测证明结果丢失后才调整回调/生命周期。不要通过延迟、周期轮询或扩大存储权限掩盖问题。
  4. 在不改变导入安全边界的前提下改善可读错误反馈,并验证重复同一错误仍可见。

影响

受影响环境无法通过本地 ZIP 导入/分享风格包;缺少文件选择器阶段诊断及短暂错误反馈,使问题难以定位。是否涉及其他荣耀机型或其他 Android 系统尚未知。

建议接受标准

  • 原反馈荣耀环境点击「导入 ZIP」能打开选择器,合法 ZIP 成功导入并显示在风格列表中;记录实际构建与真机证据。
  • 取消、选取失败、读取失败和损坏 ZIP 均能结束 busy 状态;取消不被误报为导入失败,重复操作不挂起。
  • 失败提示在窄屏可读且可再次触发;若约定保留 6 秒,组件实际可见期与其一致。
  • 不增加不必要的通用存储/所有文件权限;保留 content URI 的受限读取及 ZIP 大小、解压和内容安全校验。
  • Android 文档提供器场景、桌面本地 ZIP 导入无回归。

TODO / 不确定项

  • 用户 APK 版本、设备型号与系统版本、点击后选择器及 busy 的具体状态、失败 ZIP 样本均待确认。
  • 本次只调研并提交 issue,未修改产品代码、构建 APK 或声称已修复。
Linguagem predominante
Rust
Estrelas
3.7k
Forks
349
Merge médio
1d 12h
PRs com merge (30d)
99

Preparar o ambiente

Este projeto não oferece contêiner de desenvolvimento, Dockerfile nem guia de contribuição, então a configuração fica por sua conta: comece pelo README e veja nosso guia da primeira contribuição para os passos gerais.

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de Open-Less/openless

Todas as issues de Open-Less/openless

Issues semelhantes

Mais issues de Rust

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.