Commit 4bd120bcd4b2fd7f95515adfb9dcb0f4aa72d16e
1 parent
5f7b1265
refactor(lifelog): 录音/时间轴/声纹/纪要 四 tab 合并到「录音」菜单
删掉底部「纪要」菜单,把它的声纹/纪要两个子页并入「录音」。 录音菜单顶部子 tab 从 2 个(录音/时间轴)扩到 4 个(录音/时间轴/声纹/纪要)。 底部导航 6→5:人物/录音/对话/相册/设置。 跨子页联动保留:声纹点人→时间轴按 TA 筛选;纪要点时间戳→跳时间轴对应段。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Showing
1 changed file
with
19 additions
and
39 deletions
lifelog-recorder/app/src/main/kotlin/com/lemon/lifelog/MainActivity.kt
| @@ -121,9 +121,8 @@ class MainActivity : ComponentActivity() { | @@ -121,9 +121,8 @@ class MainActivity : ComponentActivity() { | ||
| 121 | 121 | ||
| 122 | private enum class Tab(val label: String, val icon: String) { | 122 | private enum class Tab(val label: String, val icon: String) { |
| 123 | People("人物", "👤"), // 通讯录 + 联系人档案(CRM 核心,放第一位) | 123 | People("人物", "👤"), // 通讯录 + 联系人档案(CRM 核心,放第一位) |
| 124 | - Recording("录音", "⏺"), // 顶部子页:录音 / 时间轴 | 124 | + Recording("录音", "⏺"), // 顶部子页:录音 / 时间轴 / 声纹 / 纪要 |
| 125 | Chat("对话", "💬"), | 125 | Chat("对话", "💬"), |
| 126 | - Memo("纪要", "✎"), // 顶部子页:声纹 / 纪要 | ||
| 127 | Album("相册", "🖼"), | 126 | Album("相册", "🖼"), |
| 128 | Settings("设置", "⚙"), | 127 | Settings("设置", "⚙"), |
| 129 | } | 128 | } |
| @@ -151,9 +150,8 @@ private fun MainScreen() { | @@ -151,9 +150,8 @@ private fun MainScreen() { | ||
| 151 | var filterSpeakerId by remember { mutableStateOf<Long?>(null) } | 150 | var filterSpeakerId by remember { mutableStateOf<Long?>(null) } |
| 152 | // Cross-tab jump: a summary bullet sets an absolute timestamp to scroll the timeline to. | 151 | // Cross-tab jump: a summary bullet sets an absolute timestamp to scroll the timeline to. |
| 153 | var jumpToTs by remember { mutableStateOf<Long?>(null) } | 152 | var jumpToTs by remember { mutableStateOf<Long?>(null) } |
| 154 | - // 合并页的顶部子 tab:录音页 0=录音 1=时间轴;纪要页 0=声纹 1=纪要。 | 153 | + // 录音页顶部子 tab:0=录音 1=时间轴 2=声纹 3=纪要(声纹/纪要原是「纪要」菜单,已并入此处)。 |
| 155 | var recordingSub by remember { mutableStateOf(0) } | 154 | var recordingSub by remember { mutableStateOf(0) } |
| 156 | - var memoSub by remember { mutableStateOf(0) } | ||
| 157 | 155 | ||
| 158 | val speakers by repo.speakers.observeAll().collectAsState(initial = emptyList()) | 156 | val speakers by repo.speakers.observeAll().collectAsState(initial = emptyList()) |
| 159 | 157 | ||
| @@ -181,14 +179,9 @@ private fun MainScreen() { | @@ -181,14 +179,9 @@ private fun MainScreen() { | ||
| 181 | sub = recordingSub, onSub = { recordingSub = it }, | 179 | sub = recordingSub, onSub = { recordingSub = it }, |
| 182 | filterSpeakerId = filterSpeakerId, onFilterSpeakerId = { filterSpeakerId = it }, | 180 | filterSpeakerId = filterSpeakerId, onFilterSpeakerId = { filterSpeakerId = it }, |
| 183 | jumpToTs = jumpToTs, onJumpConsumed = { jumpToTs = null }, | 181 | jumpToTs = jumpToTs, onJumpConsumed = { jumpToTs = null }, |
| 182 | + onJumpTo = { ts -> jumpToTs = ts }, | ||
| 184 | ) | 183 | ) |
| 185 | Tab.Chat -> ChatTab(repo) | 184 | Tab.Chat -> ChatTab(repo) |
| 186 | - Tab.Memo -> MemoScreen( | ||
| 187 | - repo = repo, activity = activity, speakers = speakers, | ||
| 188 | - sub = memoSub, onSub = { memoSub = it }, | ||
| 189 | - onFilterBySpeaker = { id -> filterSpeakerId = id; recordingSub = 1; tab = Tab.Recording }, | ||
| 190 | - onJumpToTime = { ts -> filterSpeakerId = null; jumpToTs = ts; recordingSub = 1; tab = Tab.Recording }, | ||
| 191 | - ) | ||
| 192 | Tab.Album -> AlbumTab(repo) | 185 | Tab.Album -> AlbumTab(repo) |
| 193 | Tab.Settings -> SettingsScreen(activity) | 186 | Tab.Settings -> SettingsScreen(activity) |
| 194 | } | 187 | } |
| @@ -209,17 +202,19 @@ private fun RecordingScreen( | @@ -209,17 +202,19 @@ private fun RecordingScreen( | ||
| 209 | onFilterSpeakerId: (Long?) -> Unit, | 202 | onFilterSpeakerId: (Long?) -> Unit, |
| 210 | jumpToTs: Long?, | 203 | jumpToTs: Long?, |
| 211 | onJumpConsumed: () -> Unit, | 204 | onJumpConsumed: () -> Unit, |
| 205 | + onJumpTo: (Long) -> Unit, | ||
| 212 | ) { | 206 | ) { |
| 213 | Column(modifier = Modifier.fillMaxSize()) { | 207 | Column(modifier = Modifier.fillMaxSize()) { |
| 214 | androidx.compose.material3.TabRow(selectedTabIndex = sub) { | 208 | androidx.compose.material3.TabRow(selectedTabIndex = sub) { |
| 215 | androidx.compose.material3.Tab(selected = sub == 0, onClick = { onSub(0) }, text = { Text("录音") }) | 209 | androidx.compose.material3.Tab(selected = sub == 0, onClick = { onSub(0) }, text = { Text("录音") }) |
| 216 | androidx.compose.material3.Tab(selected = sub == 1, onClick = { onSub(1) }, text = { Text("时间轴") }) | 210 | androidx.compose.material3.Tab(selected = sub == 1, onClick = { onSub(1) }, text = { Text("时间轴") }) |
| 211 | + androidx.compose.material3.Tab(selected = sub == 2, onClick = { onSub(2) }, text = { Text("声纹") }) | ||
| 212 | + androidx.compose.material3.Tab(selected = sub == 3, onClick = { onSub(3) }, text = { Text("纪要") }) | ||
| 217 | } | 213 | } |
| 218 | Box(modifier = Modifier.weight(1f)) { | 214 | Box(modifier = Modifier.weight(1f)) { |
| 219 | - if (sub == 0) { | ||
| 220 | - HomeTab(activity, repo, onOpenTimeline = { onSub(1) }) | ||
| 221 | - } else { | ||
| 222 | - TimelineTab( | 215 | + when (sub) { |
| 216 | + 0 -> HomeTab(activity, repo, onOpenTimeline = { onSub(1) }) | ||
| 217 | + 1 -> TimelineTab( | ||
| 223 | repo = repo, | 218 | repo = repo, |
| 224 | speakers = speakers, | 219 | speakers = speakers, |
| 225 | filterSpeakerId = filterSpeakerId, | 220 | filterSpeakerId = filterSpeakerId, |
| @@ -227,31 +222,16 @@ private fun RecordingScreen( | @@ -227,31 +222,16 @@ private fun RecordingScreen( | ||
| 227 | jumpToTs = jumpToTs, | 222 | jumpToTs = jumpToTs, |
| 228 | onJumpConsumed = onJumpConsumed, | 223 | onJumpConsumed = onJumpConsumed, |
| 229 | ) | 224 | ) |
| 230 | - } | ||
| 231 | - } | ||
| 232 | - } | ||
| 233 | -} | ||
| 234 | - | ||
| 235 | -@Composable | ||
| 236 | -private fun MemoScreen( | ||
| 237 | - repo: Repository, | ||
| 238 | - activity: Context, | ||
| 239 | - speakers: List<SpeakerProfile>, | ||
| 240 | - sub: Int, | ||
| 241 | - onSub: (Int) -> Unit, | ||
| 242 | - onFilterBySpeaker: (Long) -> Unit, | ||
| 243 | - onJumpToTime: (Long) -> Unit, | ||
| 244 | -) { | ||
| 245 | - Column(modifier = Modifier.fillMaxSize()) { | ||
| 246 | - androidx.compose.material3.TabRow(selectedTabIndex = sub) { | ||
| 247 | - androidx.compose.material3.Tab(selected = sub == 0, onClick = { onSub(0) }, text = { Text("声纹") }) | ||
| 248 | - androidx.compose.material3.Tab(selected = sub == 1, onClick = { onSub(1) }, text = { Text("纪要") }) | ||
| 249 | - } | ||
| 250 | - Box(modifier = Modifier.weight(1f)) { | ||
| 251 | - if (sub == 0) { | ||
| 252 | - SpeakersTab(repo = repo, speakers = speakers, onFilterBySpeaker = onFilterBySpeaker) | ||
| 253 | - } else { | ||
| 254 | - SummariesTab(repo = repo, activity = activity, onJumpToTime = onJumpToTime) | 225 | + 2 -> SpeakersTab( |
| 226 | + repo = repo, speakers = speakers, | ||
| 227 | + // 点声纹 → 按 TA 筛选时间轴 | ||
| 228 | + onFilterBySpeaker = { id -> onFilterSpeakerId(id); onSub(1) }, | ||
| 229 | + ) | ||
| 230 | + else -> SummariesTab( | ||
| 231 | + repo = repo, activity = activity, | ||
| 232 | + // 点纪要时间戳 → 跳时间轴对应段 | ||
| 233 | + onJumpToTime = { ts -> onFilterSpeakerId(null); onJumpTo(ts); onSub(1) }, | ||
| 234 | + ) | ||
| 255 | } | 235 | } |
| 256 | } | 236 | } |
| 257 | } | 237 | } |