feat(tui): Phase 2 detail screens — Issue Detail, MR Detail, discussion tree, cross-refs
Implements the remaining Phase 2 Core Screens: - Discussion tree widget (view/common/discussion_tree.rs): DiscussionNode/NoteNode types, expand/collapse state, visual row flattening, format_relative_time with Clock trait - Cross-reference widget (view/common/cross_ref.rs): CrossRefKind enum, navigable refs, badge rendering ([MR]/[REL]/[REF]) - Issue Detail (state + action + view): progressive hydration (metadata Phase 1, discussions Phase 2), section cycling, description scroll, sanitized GitLab content - MR Detail (state + action + view): tab bar (Overview/Files/Discussions), file changes with change type indicators, branch info, draft/merge status, diff note support - Message + update wiring: IssueDetailLoaded, MrDetailLoaded, DiscussionsLoaded handlers with TaskSupervisor stale-result guards Closes bd-1d6z, bd-8ab7, bd-3t1b, bd-1cl9 (Phase 2 epic). 389 tests passing, clippy clean, fmt clean.
This commit is contained in:
@@ -332,6 +332,58 @@ impl LoreApp {
|
||||
Cmd::none()
|
||||
}
|
||||
|
||||
// --- Issue detail ---
|
||||
Msg::IssueDetailLoaded {
|
||||
generation,
|
||||
key,
|
||||
data,
|
||||
} => {
|
||||
let screen = Screen::IssueDetail(key.clone());
|
||||
if self
|
||||
.supervisor
|
||||
.is_current(&TaskKey::LoadScreen(screen.clone()), generation)
|
||||
{
|
||||
self.state.issue_detail.apply_metadata(*data);
|
||||
self.state.set_loading(screen.clone(), LoadState::Idle);
|
||||
self.supervisor
|
||||
.complete(&TaskKey::LoadScreen(screen), generation);
|
||||
}
|
||||
Cmd::none()
|
||||
}
|
||||
Msg::DiscussionsLoaded {
|
||||
generation,
|
||||
key,
|
||||
discussions,
|
||||
} => {
|
||||
let screen = Screen::IssueDetail(key.clone());
|
||||
if self
|
||||
.supervisor
|
||||
.is_current(&TaskKey::LoadScreen(screen.clone()), generation)
|
||||
{
|
||||
self.state.issue_detail.apply_discussions(discussions);
|
||||
}
|
||||
Cmd::none()
|
||||
}
|
||||
|
||||
// --- MR detail ---
|
||||
Msg::MrDetailLoaded {
|
||||
generation,
|
||||
key,
|
||||
data,
|
||||
} => {
|
||||
let screen = Screen::MrDetail(key.clone());
|
||||
if self
|
||||
.supervisor
|
||||
.is_current(&TaskKey::LoadScreen(screen.clone()), generation)
|
||||
{
|
||||
self.state.mr_detail.apply_metadata(*data);
|
||||
self.state.set_loading(screen.clone(), LoadState::Idle);
|
||||
self.supervisor
|
||||
.complete(&TaskKey::LoadScreen(screen), generation);
|
||||
}
|
||||
Cmd::none()
|
||||
}
|
||||
|
||||
// All other message variants: no-op for now.
|
||||
// Future phases will fill these in as screens are implemented.
|
||||
_ => Cmd::none(),
|
||||
|
||||
Reference in New Issue
Block a user