Skip to content

统一源管理 UI 重构方案

Status: Draft / 待讨论
Scope: 大型重构,预计分 4-5 个阶段实施
Created: 2026-03-22

1. 目标

将目前分散在多处的源管理 UI(内置源、Mihon/Aniyomi 扩展、Legado/TVBox/JS JSON 源)统一为 一个带分页标签的界面,展示风格一致,每个 tab 保留各自的导入方式。

2. 现状分析

当前入口路径(从 Settings → Content Sources 进入)

mermaid
graph TD
    A[SourcesSettingsFragment<br/>Preference 列表] --> B[SourcesManageFragment<br/>已启用源管理]
    A --> C[SourcesCatalogActivity<br/>内置源目录]
    A --> D[ExtensionsRootFragment<br/>Mihon/Aniyomi 扩展]
    A --> E[JsonSourcesRootFragment<br/>Legado/TVBox/JS 源]
    D --> D1[ExtensionsBrowserFragment<br/>Mihon Tab]
    D --> D2[ExtensionsBrowserFragment<br/>Aniyomi Tab]
    E --> E1[JsonSourcesFragment<br/>Legado Tab]
    E --> E2[JsonSourcesFragment<br/>TVBox Tab]
    E --> E3[JsonSourcesFragment<br/>JS Tab]

现有组件清单

区域文件/类UI 风格功能
入口SourcesSettingsFragmentPreference 列表4 个跳转入口 + 全局设置
内置源目录SourcesCatalogActivityActivity + RecyclerView + chips 过滤内容类型/语言过滤、搜索、启用源
源管理SourcesManageFragmentRecyclerView + 拖拽排序启用/禁用、排序、搜索
Mihon/AniyomiExtensionsRootFragmentExtensionsBrowserFragmentViewPager2 + RecyclerView安装/卸载/更新、语言过滤、仓库管理
Legado/TVBox/JSJsonSourcesRootFragmentJsonSourcesFragmentViewPager2 + RecyclerViewJSON 导入/编辑/删除、分组展示

关键差异

内置源Mihon/AniyomiLegado/TVBox/JS
数据来源编译时硬编码APK 包安装 + 仓库索引JSON 配置导入
导入方式无(内置)仓库 URL → APK 下载安装JSON URL/文件 → 导入
列表项样式SourceCatalogItemADExtensionsBrowserAdapterGroupedJsonSourcesAdapter
过滤方式内容类型 + 语言 chips语言 filter dialog分组折叠
管理操作启用/禁用安装/卸载/更新导入/编辑/删除

3. 目标架构

3.1 UI 结构

┌─────────────────────────────────────────────┐
│  [Toolbar] Content Sources               🔍  │
├─────────────────────────────────────────────┤
│  ┌──────┬────────┬─────────┬───────┬──────┐ │
│  │内置源│ Mihon  │ Aniyomi │Legado │TVBox │ │
│  └──────┴────────┴─────────┴───────┴──────┘ │
│  ┌─────────────────────────────────────────┐ │
│  │                                         │ │
│  │   统一风格的源列表                        │ │
│  │   (RecyclerView)                        │ │
│  │                                         │ │
│  │   - 源名称                               │ │
│  │   - 语言标签                              │ │
│  │   - 启用/禁用开关                         │ │
│  │   - 状态指示                              │ │
│  │                                         │ │
│  └─────────────────────────────────────────┘ │
│                                         [+] │
└─────────────────────────────────────────────┘

3.2 分页详情

Tab内容+ 按钮行为已有可复用组件
内置源所有内置源列表,带启用/禁用开关无需(或打开内置源筛选面板)SourcesCatalogViewModel
Mihon已安装 + 可用 Mihon 扩展打开 Mihon 仓库管理ExtensionsBrowserViewModel
Aniyomi已安装 + 可用 Aniyomi 扩展打开 Aniyomi 仓库管理ExtensionsBrowserViewModel
Legado已导入的 Legado 书源打开 JSON 导入 dialogJsonSourcesViewModel
TVBox已导入的 TVBox 源打开 JSON 导入 dialogJsonSourcesViewModel

3.3 统一列表项样式

┌──────────────────────────────────────────┐
│  [Icon]  源名称                    [开关] │
│          语言: zh  ·  类型: Manga         │
│          版本: 1.4.2  ·  10 个子源        │
└──────────────────────────────────────────┘

各 tab 的列表项共享相同的视觉风格(参考现有 SourcesManageFragment 的卡片样式),但数据字段可根据源类型适配:

  • 内置源: 源名、语言、内容类型、启用状态
  • Mihon/Aniyomi: 扩展名、版本、语言、安装状态/进度
  • Legado/TVBox: 源名、URL、类型、来源 JSON

4. 实施阶段

Phase 1: 统一容器框架

目标: 创建顶层 UnifiedSourcesFragment,用 ViewPager2 + TabLayout 承载所有 tab。

新增文件:

  • UnifiedSourcesFragment.kt — 顶层容器
  • UnifiedSourcesPagerAdapter.kt — ViewPager2 适配器
  • fragment_unified_sources.xml — 布局(TabLayout + ViewPager2 + FAB)

修改文件:

  • SourcesSettingsFragment.kt — 将多个入口合并为一个指向 UnifiedSourcesFragment
  • 导航路由 — 更新 AppRouter 添加新目的地

Phase 2: 迁移内置源 Tab

目标: 将 SourcesCatalogActivity 从 Activity 改造为 Fragment,嵌入到 ViewPager2 的第一个 tab。

修改文件:

  • SourcesCatalogActivity.kt → 提取核心逻辑到 BuiltInSourcesTabFragment.kt
  • SourcesCatalogViewModel.kt — 复用,无需大改
  • SourcesCatalogAdapter.kt / SourceCatalogItemAD.kt — 复用

注意: SourcesCatalogActivity 可暂时保留用于兼容,后续移除。

Phase 3: 迁移 Mihon/Aniyomi Tab

目标: 将现有 ExtensionsBrowserFragment 直接嵌入新 ViewPager2(替代 ExtensionsRootFragment)。

修改文件:

  • UnifiedSourcesPagerAdapter.kt — 添加 Mihon/Aniyomi 位置的 Fragment 创建
  • ExtensionsBrowserFragment.kt — 适配 FAB 按钮(+ → 打开仓库管理)
  • 移除 ExtensionsRootFragment.kt(不再需要独立的两层嵌套 ViewPager)

风格统一:

  • 使已安装扩展的列表项样式与内置源卡片保持一致
  • 保留安装状态指示和进度条

Phase 4: 迁移 Legado/TVBox Tab

目标: 将 JsonSourcesFragment 嵌入 ViewPager2 的后两个 tab。

修改文件:

  • UnifiedSourcesPagerAdapter.kt — 添加 Legado/TVBox 位置
  • JsonSourcesFragment.kt — 适配 FAB 按钮(+ → 打开 JSON 导入 dialog)
  • 移除 JsonSourcesRootFragment.kt

考虑: JS 源是否需要单独 tab,还是合入 TVBox。

Phase 5: 清理 & 打磨

  • 移除废弃的 SourcesCatalogActivityExtensionsRootFragmentJsonSourcesRootFragment
  • 统一列表项视觉风格(统一卡片高度、间距、排版)
  • 全局搜索:toolbar 搜索框跨所有 tab 搜索
  • 统一 empty state 样式
  • 迁移全局设置(NSFW 过滤、语言过滤)到 toolbar 菜单

5. 数据流与架构

mermaid
graph LR
    subgraph "UnifiedSourcesFragment"
        VP[ViewPager2]
    end
    subgraph "Tab Fragments"
        BI[BuiltInSourcesTabFragment]
        MI[ExtensionsBrowserFragment<br/>type=MIHON]
        AN[ExtensionsBrowserFragment<br/>type=ANIYOMI]
        LE[JsonSourcesFragment<br/>type=LEGADO]
        TV[JsonSourcesFragment<br/>type=TVBOX]
    end
    subgraph "ViewModels (复用)"
        VM1[SourcesCatalogViewModel]
        VM2[ExtensionsBrowserViewModel]
        VM3[JsonSourcesViewModel]
    end
    VP --> BI --> VM1
    VP --> MI --> VM2
    VP --> AN --> VM2
    VP --> LE --> VM3
    VP --> TV --> VM3

每个 tab Fragment 保留自己的 ViewModel,数据层无需修改。重构主要在 UI 层。

6. FAB(+ 按钮)行为映射

当前 TabFAB 点击行为
内置源无 FAB(或打开筛选面板)
Mihon打开 ExtensionRepositoriesFragment(Mihon 仓库管理)
Aniyomi打开 ExtensionRepositoriesFragment(Aniyomi 仓库管理)
Legado打开 ImportJsonDialogFragment(JSON 导入,type=LEGADO)
TVBox打开 ImportJsonDialogFragment(JSON 导入,type=TVBOX)

FAB 的 icon 和行为随 tab 切换动态更新。内置源 tab 下 FAB 隐藏。

7. 影响评估

涉及文件(估算 30+)

类别新增修改删除
容器框架320
内置源迁移131
扩展迁移031
JSON 源迁移031
清理打磨15+3
布局 XML1-23-52-3
导航/路由02-30
合计~6~20+~8

风险点

  1. ViewPager2 嵌套: 现有 Extensions 和 JSON 已各自用了 ViewPager2,迁移后变成单层,降低复杂度
  2. Fragment 状态保存: ViewPager2 中 Fragment 的 lifecycle 需要正确处理
  3. Menu 冲突: 每个 tab Fragment 有不同的 toolbar menu,切换时需清理
  4. 性能: 5 个 tab 的 offscreen limit 需要合理设置,避免同时加载过多
  5. 回归测试: 所有源管理功能(安装/卸载/导入/编辑/删除/搜索/过滤)需逐一验证

8. 时间估算

阶段预计工作量
Phase 1: 容器框架1 个会话
Phase 2: 内置源 Tab1 个会话
Phase 3: Mihon/Aniyomi Tab1 个会话
Phase 4: Legado/TVBox Tab1 个会话
Phase 5: 清理打磨1-2 个会话
总计5-6 个会话

9. 备选方案

方案 B: 渐进式统一

不创建全新容器,而是:

  1. 保留现有 SourcesSettingsFragment 作为入口
  2. 统一各子页面的列表项样式
  3. SourcesManageFragment 中合并展示所有已启用源(跨类型混合)

优点: 工作量小(~2 会话),风险低
缺点: 入口仍分散,不如方案 A 统一

方案 C: 二级 Tab 混合

保留当前的两层结构,但将 Extensions 和 JSON 源合并:

内置源管理(现有页面优化)
├── Mihon  ─┐
├── Aniyomi ─┤── 扩展 Tab(现有 ExtensionsRootFragment 扩展)
├── Legado  ─┤
├── TVBox   ─┤── JSON Tab(现有 JsonSourcesRootFragment 扩展)
└── JS      ─┘

优点: 改动最小(~1 会话)
缺点: 仍然是分散的入口

Documentation for Kototoro