Commit 4bd120bcd4b2fd7f95515adfb9dcb0f4aa72d16e

Authored by yibo
1 parent 5f7b1265

refactor(lifelog): 录音/时间轴/声纹/纪要 四 tab 合并到「录音」菜单

删掉底部「纪要」菜单,把它的声纹/纪要两个子页并入「录音」。
录音菜单顶部子 tab 从 2 个(录音/时间轴)扩到 4 个(录音/时间轴/声纹/纪要)。
底部导航 6→5:人物/录音/对话/相册/设置。
跨子页联动保留:声纹点人→时间轴按 TA 筛选;纪要点时间戳→跳时间轴对应段。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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 }