Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
47109ba
feat: 添加TV遥控器D-pad焦点支持
wdw89 Jun 21, 2026
f84adee
feat: TV遥控器焦点样式优化
wdw89 Jun 22, 2026
b80773a
refactor: 统一动漫源切换为监听+直接刷新模式
wdw89 Jun 25, 2026
76be33b
docs: 添加源切换统一改造spec文档
wdw89 Jun 25, 2026
b101d29
feat: 搜索页重构 & 验证码增强 & TV焦点导航优化
wdw89 Jul 5, 2026
c8e5286
fix: HomeScreen layout and focus — Anime/source button vertical layou…
wdw89 Jul 10, 2026
5f2a47c
feat: TV focus inverse-color — all buttons, dialogs, lists, sliders, …
wdw89 Jul 10, 2026
0d3adae
docs: OpenSpec artifacts for focus inverse-color change — specs, arch…
wdw89 Jul 10, 2026
5425638
chore: 移除搜索页多余的 @Preview 函数(本地调试用,原作者版本无)
wdw89 Jul 10, 2026
21f4dab
chore: remove .github .junie .mimocode .opencode from tracking, add t…
wdw89 Jul 10, 2026
9340436
chore: add .github .junie .mimocode .opencode to .gitignore
wdw89 Jul 10, 2026
f80ebf0
feat: add TV banner icon and LEANBACK_LAUNCHER support
wdw89 Jul 10, 2026
be5c99f
fix: 横屏首页站源上方空白过多
wdw89 Jul 10, 2026
3942d0e
feat(focus): fix detail page & settings page D-pad navigation
wdw89 Jul 10, 2026
92d1501
refactor: 提取共享 focus 工具函数,消除 ~65 处重复样板
wdw89 Jul 11, 2026
7bcc47b
feat(focus): v5 final — FocusRequester function-level + moveFocus for…
wdw89 Jul 11, 2026
a20ccc3
chore: delete empty home-screen-focus-fixes and slider-dpad-support c…
wdw89 Jul 11, 2026
2c04d97
feat(video-player): TV D-pad focus navigation, slider thumb animation…
wdw89 Jul 12, 2026
e5a74a6
fix: player focus bugs + gradient overlay
wdw89 Jul 12, 2026
d6769ee
fix: slider thumb sub-pixel white ring artifact
wdw89 Jul 12, 2026
cda41da
feat: focus highlight unification + TV interaction fixes
wdw89 Jul 25, 2026
bc2a4e0
fix: remove exit confirmation dialog, let Back exit app directly per …
wdw89 Jul 25, 2026
6524af4
fix: search bar status bar padding and edit/non-edit height stability
wdw89 Jul 26, 2026
03b19ce
feat: add pure background toggle (黑白背景) for flat black/white backgrounds
wdw89 Jul 26, 2026
516004f
chore: add openspec/ to gitignore, update tasks.json
wdw89 Jul 26, 2026
e6f44e7
perf: optimize TV card scroll jank with draw-phase focus border
wdw89 Jul 28, 2026
c9728c4
fix: add horizontal edge safe zone to player drag gestures
wdw89 Jul 28, 2026
4b611b2
update ignore
wdw89 Jul 28, 2026
fa60188
feat: darken player gradient overlay & show video resolution/bitrate …
wdw89 Jul 28, 2026
df2ed1a
perf: switch to draw-phase focusBorder using Modifier.composed
wdw89 Jul 28, 2026
630b5ee
feat: player multi-channel episode selection & fixes
wdw89 Aug 2, 2026
88f8d54
refactor: simplify side sheet focus state machine
wdw89 Aug 2, 2026
f4dd71d
fix: focus current channel in detail page channel selector dialog
wdw89 Aug 2, 2026
005ef36
fix: prevent speed side sheet labels from being truncated
wdw89 Aug 2, 2026
77bcdca
feat: prefix Bitrate label to player subtitle bitrate display
wdw89 Aug 2, 2026
9676eda
refactor: consolidate TV focus highlight boilerplate and fix MediaSma…
wdw89 Aug 2, 2026
bb3a92c
chore: stop tracking openspec/ (now ignored)
wdw89 Aug 2, 2026
785e467
gitignore task
wdw89 Aug 3, 2026
ec3b5de
chore: 恢复误删的 CI 工作流,本地文档移出跟踪
wdw89 Sep 14, 2026
0a0186e
ci: 移除已失效的 setup-android 步骤,恢复 CI 绿灯
wdw89 Sep 16, 2026
4dfc4db
fix(focus): 修复相关推荐首项被回收后按 ↓ 崩溃
wdw89 Sep 19, 2026
1f61abc
fix: 修复多线路播放、HLS 播放与次元城登录
wdw89 Sep 12, 2026
8d54b8a
fix: 恢复 Gogoanime 数据源并修复剧集顺序
wdw89 Sep 12, 2026
e4819ba
refactor: 移除已失效数据源与过时测试
wdw89 Sep 12, 2026
39d2476
test: 保留全源播放烟雾测试与次元城登录逻辑测试
wdw89 Sep 12, 2026
09089b0
test: 测试按作者约定归位,纯函数用例下沉到 JVM
wdw89 Sep 12, 2026
61ccec1
feat: 副标题栏增加文件大小与码率
wdw89 Sep 13, 2026
890aab4
feat: HLS 码率改用分片级实测值,拿不到大小就显示「大小未知」
wdw89 Sep 13, 2026
8960d65
feat: 副标题栏把码率的平均口径与峰值口径分开显示
wdw89 Sep 13, 2026
d2f7582
refactor: 清理登录鉴权残留并修复搜索分页
wdw89 Sep 13, 2026
3879f44
style: 移除未使用的 import
wdw89 Sep 13, 2026
ca57787
feat: 次元城详情页展示相关推荐
wdw89 Sep 13, 2026
016a048
refactor: 代码评审整改——收敛 TV 焦点配色与侧栏、修掉鉴权请求竞态
wdw89 Sep 14, 2026
168c518
fix: 修复数据源下线导致收藏/历史/下载页崩溃,并补齐分片码率统计的线程安全
wdw89 Sep 14, 2026
d7e9542
feat: 次元城登录改为过期前主动续期,不再等 7 天掉线
wdw89 Sep 14, 2026
97131da
refactor: 稀饭动漫播放地址解析去掉 4 条从未命中的分支
wdw89 Sep 16, 2026
3529260
fix: 修复次元城登录页在手机/平板上无法触摸唤起键盘
wdw89 Oct 1, 2026
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
9 changes: 6 additions & 3 deletions .github/workflows/android_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@ jobs:

# Set up JDK 17
- name: Set up JDK 17
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: '17'

- name: Set up Android SDK
uses: android-actions/setup-android@v3
# 不再用 android-actions/setup-android:镜像已预装本项目需要的 SDK
# (ANDROID_HOME/cmdline-tools 12.0/platforms;android-36/build-tools 36.0.0)且已接受许可。
# 该 action 会因为版本与本镜像不符而自行下载固定版本的 cmdline-tools,
# 而 Google 已将这些 zip 下架 → 下载 404,整个 job 在构建前就挂掉。
# 即使在最新版 v4 上同样如此,上游 issue:android-actions/setup-android#536。

- name: Set up Gradle
uses: gradle/actions/setup-gradle@v4
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ jobs:

# Set up JDK 17
- name: Set up JDK 17
uses: actions/setup-java@v4
uses: actions/setup-java@v5
with:
distribution: 'temurin'
java-version: '17'

- name: Set up Android SDK
uses: android-actions/setup-android@v3
# 同 android_ci.yml:不用 android-actions/setup-android,
# 它下载的 cmdline-tools 已被 Google 下架(404),镜像自带的本项目需要的 SDK。

- name: Set up Gradle
uses: gradle/actions/setup-gradle@v4
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,9 @@ local.properties
release/
/.kotlin
debug/
nul
.junie
.mimocode
.opencode
openspec/
.vscode/
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ class DownloadDaoTest {
private lateinit var animeDatabase: AnimeDatabase

private var download1 =
DownloadEntity(1, "海贼王1", "/detailUrl1", "/imgUrl1", SourceMode.Yhdm.name, System.currentTimeMillis())
DownloadEntity(1, "海贼王1", "/detailUrl1", "/imgUrl1", SourceMode.Silisili.name, System.currentTimeMillis())
private var download2 =
DownloadEntity(2, "海贼王2", "/detailUrl2", "/imgUrl2", SourceMode.Yhdm.name, System.currentTimeMillis())
DownloadEntity(2, "海贼王2", "/detailUrl2", "/imgUrl2", SourceMode.Silisili.name, System.currentTimeMillis())

@Before
fun createDb() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class DownloadDetailTest {
private lateinit var animeDatabase: AnimeDatabase

private var download =
DownloadEntity(1, "海贼王1", "/detailUrl1", "/imgUrl1", SourceMode.Yhdm.name, System.currentTimeMillis())
DownloadEntity(1, "海贼王1", "/detailUrl1", "/imgUrl1", SourceMode.Silisili.name, System.currentTimeMillis())
private val downloadDetail1 = DownloadDetailEntity(
1, download.downloadId, "第01集", "/imgUrl1",
1, "/downloadUrl1", "/filePath")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class EpisodeDaoTest {
private lateinit var historyDao: HistoryDao
private lateinit var animeDatabase: AnimeDatabase

private var history1 = HistoryEntity(1, "海贼王1", "img1", "/video1", SourceMode.Yhdm.name)
private var history1 = HistoryEntity(1, "海贼王1", "img1", "/video1", SourceMode.Silisili.name)

@Before
fun createDb() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ class FavouriteDaoTest {
private lateinit var favouriteDao: FavouriteDao
private lateinit var animeDatabase: AnimeDatabase

private var favourite1 = FavouriteEntity(1, "海贼王1", "/video1", "img1", SourceMode.Yhdm.name)
private var favourite2 = FavouriteEntity(2, "海贼王2", "/video2", "img2", SourceMode.Yhdm.name)
private var favourite1 = FavouriteEntity(1, "海贼王1", "/video1", "img1", SourceMode.Silisili.name)
private var favourite2 = FavouriteEntity(2, "海贼王2", "/video2", "img2", SourceMode.Silisili.name)

@Before
fun createDb() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ class HistoryDaoTest {
private lateinit var historyDao: HistoryDao
private lateinit var animeDatabase: AnimeDatabase

private var history1 = HistoryEntity(1, "海贼王1", "img1", "/video1", SourceMode.Yhdm.name)
private var history2 = HistoryEntity(2, "海贼王2", "img2", "/video2", SourceMode.Yhdm.name)
private var history1 = HistoryEntity(1, "海贼王1", "img1", "/video1", SourceMode.Silisili.name)
private var history2 = HistoryEntity(2, "海贼王2", "img2", "/video2", SourceMode.Silisili.name)

@Before
fun createDb() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package com.lanlinju.animius.database_test

import android.content.Context
import androidx.room.Room
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.lanlinju.animius.data.local.database.AnimeDatabase
import com.lanlinju.animius.data.local.entity.DownloadEntity
import com.lanlinju.animius.data.local.entity.FavouriteEntity
import com.lanlinju.animius.data.local.entity.HistoryEntity
import com.lanlinju.animius.data.repository.RoomRepositoryImpl
import com.lanlinju.animius.util.SourceMode
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.runBlocking
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import java.io.IOException

/**
* 数据源下线后,库里会留下 source 列是失效枚举名的老记录(收藏/历史/下载都是按名字存的)。
*
* 这些记录必须被跳过,不能直接 `SourceMode.valueOf(source)`——那会抛
* IllegalArgumentException,并且因为异常是从 Flow 里冒出来的,会把整个列表一起打挂,
* 而不仅仅跳过这一行。
*
* 回归背景:SourceMode 从 11 项删到 7 项时移除了 Mxdm / Ntdm / Nyafun / Yhdm,
* 老用户的收藏页、历史页、下载页会直接崩。
*/
@RunWith(AndroidJUnit4::class)
class RemovedSourceRowTest {
private lateinit var db: AnimeDatabase
private lateinit var repository: RoomRepositoryImpl

/** 上游存在过、现已从 [SourceMode] 移除的名字 */
private val removedSource = "Mxdm"

@Before
fun createDb() {
val context: Context = ApplicationProvider.getApplicationContext()
db = Room.inMemoryDatabaseBuilder(context, AnimeDatabase::class.java)
.allowMainThreadQueries()
.build()
repository = RoomRepositoryImpl(db)
}

@After
@Throws(IOException::class)
fun closeDb() {
db.close()
}

@Test
@Throws(Exception::class)
fun getFavourites_skipsRowsWithRemovedSource() = runBlocking {
db.favouriteDao().insertFavourite(
FavouriteEntity(
title = "失效源收藏",
detailUrl = "/dead",
imgUrl = "img",
source = removedSource
)
)
db.favouriteDao().insertFavourite(
FavouriteEntity(
title = "正常收藏",
detailUrl = "/alive",
imgUrl = "img",
source = SourceMode.Silisili.name
)
)

// 先确认两行真的入库了,否则下面的"只剩一行"可能只是插入失败,测不出过滤逻辑
assertEquals(2, db.favouriteDao().getAllFavourites().first().size)

val favourites = repository.getFavourites().first()

assertEquals(listOf("/alive"), favourites.map { it.detailUrl })
}

@Test
@Throws(Exception::class)
fun getHistories_skipsRowsWithRemovedSource() = runBlocking {
db.historyDao().insertHistory(
HistoryEntity(
title = "失效源历史",
imgUrl = "img",
detailUrl = "/dead",
source = removedSource
)
)
db.historyDao().insertHistory(
HistoryEntity(
title = "正常历史",
imgUrl = "img",
detailUrl = "/alive",
source = SourceMode.Silisili.name
)
)

// 先确认两行真的入库了,否则下面的"只剩一行"可能只是插入失败,测不出过滤逻辑
assertEquals(2, db.historyDao().getHistoryWithEpisodes().first().size)

val histories = repository.getHistories().first()

assertEquals(listOf("/alive"), histories.map { it.detailUrl })
}

@Test
@Throws(Exception::class)
fun getDownloads_skipsRowsWithRemovedSource() = runBlocking {
db.downLoadDao().insertDownload(
DownloadEntity(
title = "失效源下载",
detailUrl = "/dead",
imgUrl = "img",
source = removedSource
)
)
db.downLoadDao().insertDownload(
DownloadEntity(
title = "正常下载",
detailUrl = "/alive",
imgUrl = "img",
source = SourceMode.Silisili.name
)
)

// 先确认两行真的入库了,否则下面的"只剩一行"可能只是插入失败,测不出过滤逻辑
assertEquals(2, db.downLoadDao().getDownloads().first().size)

val downloads = repository.getDownloads().first()

assertEquals(listOf("/alive"), downloads.map { it.detailUrl })
}
}
Loading