@gperezmz/bb-plugin-thread-glance 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +20 -0
- package/THIRD_PARTY_NOTICES.md +230 -0
- package/app.tsx +12 -0
- package/components/ui/alert-dialog.tsx +142 -0
- package/components/ui/button.tsx +59 -0
- package/components/ui/card.tsx +83 -0
- package/components/ui/coarse-pointer-sizing.ts +66 -0
- package/components/ui/context-menu.tsx +355 -0
- package/components/ui/dialog.tsx +416 -0
- package/components/ui/dropdown-menu.tsx +640 -0
- package/components/ui/hooks/use-compact-viewport.tsx +37 -0
- package/components/ui/hooks/use-media-query.ts +70 -0
- package/components/ui/hooks/use-pointer-coarse.ts +7 -0
- package/components/ui/hover-card.tsx +36 -0
- package/components/ui/icon-extended.tsx +333 -0
- package/components/ui/icon-registry.ts +189 -0
- package/components/ui/icon.tsx +444 -0
- package/components/ui/input.tsx +30 -0
- package/components/ui/menu-item-hover.tsx +93 -0
- package/components/ui/motion.ts +4 -0
- package/components/ui/overlay-trigger.ts +84 -0
- package/components/ui/popover.tsx +223 -0
- package/components/ui/responsive-overlay.tsx +823 -0
- package/components/ui/tooltip.tsx +63 -0
- package/dist/app.css +2 -0
- package/dist/app.js +66 -0
- package/dist/app.meta.json +11 -0
- package/dist/server.js +71 -0
- package/dist/server.js.map +6 -0
- package/dist/server.meta.json +11 -0
- package/features/thread-list/components/Dialogs.tsx +299 -0
- package/features/thread-list/components/FoldRows.tsx +147 -0
- package/features/thread-list/components/GroupSection.tsx +370 -0
- package/features/thread-list/components/ProviderBadge.tsx +57 -0
- package/features/thread-list/components/PullRequestBadge.tsx +50 -0
- package/features/thread-list/components/Rails.tsx +28 -0
- package/features/thread-list/components/RenameEditor.tsx +118 -0
- package/features/thread-list/components/RowMenu.tsx +168 -0
- package/features/thread-list/components/SplitMiniMap.tsx +55 -0
- package/features/thread-list/components/ThreadDetails.tsx +138 -0
- package/features/thread-list/components/ThreadList.tsx +855 -0
- package/features/thread-list/components/ThreadRowView.tsx +631 -0
- package/features/thread-list/components/Toolbar.tsx +296 -0
- package/features/thread-list/components/controller.ts +64 -0
- package/features/thread-list/components/glyphs.tsx +129 -0
- package/features/thread-list/components/row-card.ts +127 -0
- package/features/thread-list/data/storage.ts +18 -0
- package/features/thread-list/data/useAutoExpand.ts +53 -0
- package/features/thread-list/data/useClientPreferences.ts +20 -0
- package/features/thread-list/data/useNotes.ts +41 -0
- package/features/thread-list/data/useNow.ts +19 -0
- package/features/thread-list/data/usePreferences.ts +126 -0
- package/features/thread-list/data/useScheduled.ts +43 -0
- package/features/thread-list/data/useStamps.ts +68 -0
- package/features/thread-list/icons.ts +44 -0
- package/features/thread-list/index.ts +2 -0
- package/features/thread-list/model/attention.ts +89 -0
- package/features/thread-list/model/counters.ts +67 -0
- package/features/thread-list/model/details.ts +79 -0
- package/features/thread-list/model/drag.ts +104 -0
- package/features/thread-list/model/expansion.ts +71 -0
- package/features/thread-list/model/families.ts +297 -0
- package/features/thread-list/model/groups.ts +263 -0
- package/features/thread-list/model/labels.ts +50 -0
- package/features/thread-list/model/layout.ts +61 -0
- package/features/thread-list/model/menu.ts +78 -0
- package/features/thread-list/model/move.ts +46 -0
- package/features/thread-list/model/notes.ts +52 -0
- package/features/thread-list/model/provider-mark.ts +59 -0
- package/features/thread-list/model/share.ts +101 -0
- package/features/thread-list/model/sort.ts +78 -0
- package/features/thread-list/model/state.ts +330 -0
- package/features/thread-list/model/time.ts +107 -0
- package/features/thread-list/model/toggles.ts +99 -0
- package/features/thread-list/model/view.ts +669 -0
- package/features/thread-list/model/windowing.ts +27 -0
- package/features/thread-list/testing/fixtures.ts +162 -0
- package/hooks/useBrowserDimmingModal.ts +5 -0
- package/lib/portal-scope.ts +15 -0
- package/lib/utils.ts +17 -0
- package/package.json +96 -0
- package/server/cli.ts +107 -0
- package/server/failures.ts +136 -0
- package/server/import.ts +144 -0
- package/server/notes.ts +236 -0
- package/server/preference-store.ts +96 -0
- package/server/scheduled.ts +129 -0
- package/server/serial.ts +12 -0
- package/server/stamps.ts +142 -0
- package/server/startup.ts +121 -0
- package/server.ts +126 -0
- package/shared/contract.ts +73 -0
- package/shared/preferences.ts +241 -0
- package/shared/signals.ts +71 -0
- package/skills/thread-glance/SKILL.md +69 -0
- package/tsconfig.json +36 -0
- package/types/global-jsx.d.ts +10 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// What a user's click on a chip, fold or header changes.
|
|
2
|
+
// Pure: returns the preference patch and which auto-expand targets to drop.
|
|
3
|
+
import type { Preferences } from "@/shared/preferences";
|
|
4
|
+
import { ancestorsOf, type Family, type Forest } from "./families";
|
|
5
|
+
import { isGroupCollapsed, toggleGroupCollapse } from "./groups";
|
|
6
|
+
import { isDoneUnseen } from "./state";
|
|
7
|
+
import type { GroupView, OlderRow, ThreadRow } from "./view";
|
|
8
|
+
|
|
9
|
+
export interface ToggleOutcome {
|
|
10
|
+
patch: Partial<Preferences>;
|
|
11
|
+
/** Targets to drop so the collapse sticks until the next transition. */
|
|
12
|
+
drop: ((id: string) => boolean) | null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function without(list: readonly string[], value: string): string[] {
|
|
16
|
+
return list.filter((item) => item !== value);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function under(forest: Forest, parentId: string): (id: string) => boolean {
|
|
20
|
+
return (id) => ancestorsOf(id, forest.infos).includes(parentId);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function toggleChip(row: ThreadRow, prefs: Preferences, forest: Forest): ToggleOutcome {
|
|
24
|
+
const id = row.info.thread.id;
|
|
25
|
+
const expanded = row.chip?.expanded ?? false;
|
|
26
|
+
if (prefs.nesting === "tree") {
|
|
27
|
+
return expanded
|
|
28
|
+
? { patch: { collapsedChildren: [...without(prefs.collapsedChildren, id), id] }, drop: under(forest, id) }
|
|
29
|
+
: { patch: { collapsedChildren: without(prefs.collapsedChildren, id) }, drop: null };
|
|
30
|
+
}
|
|
31
|
+
// Folded: expanding shows every child; collapsing also drops auto-reveals.
|
|
32
|
+
return expanded
|
|
33
|
+
? { patch: { expandedChildren: without(prefs.expandedChildren, id) }, drop: under(forest, id) }
|
|
34
|
+
: { patch: { expandedChildren: [...without(prefs.expandedChildren, id), id] }, drop: null };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function toggleOlder(row: OlderRow, prefs: Preferences, group: GroupView | null, forest: Forest): ToggleOutcome {
|
|
38
|
+
if (row.scope === "reveal") {
|
|
39
|
+
// "+N more" expands the whole family, as the chip does.
|
|
40
|
+
return { patch: { expandedChildren: [...without(prefs.expandedChildren, row.scopeId), row.scopeId] }, drop: null };
|
|
41
|
+
}
|
|
42
|
+
if (!row.expanded) {
|
|
43
|
+
return { patch: { expandedOlder: [...without(prefs.expandedOlder, row.scopeId), row.scopeId] }, drop: null };
|
|
44
|
+
}
|
|
45
|
+
const patch = { expandedOlder: without(prefs.expandedOlder, row.scopeId) };
|
|
46
|
+
if (row.scope === "family") return { patch, drop: under(forest, row.scopeId) };
|
|
47
|
+
// Folding a group's older roots drops the targets that held it open.
|
|
48
|
+
const quietRoots = new Set<string>();
|
|
49
|
+
for (const family of forest.families) if (family.settled) quietRoots.add(family.root.thread.id);
|
|
50
|
+
const inGroup = new Set(group?.rootIds ?? []);
|
|
51
|
+
return {
|
|
52
|
+
patch,
|
|
53
|
+
drop: (id) => {
|
|
54
|
+
const family = forest.familyOf.get(id);
|
|
55
|
+
return family !== undefined && quietRoots.has(family.root.thread.id) && inGroup.has(family.root.thread.id);
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function toggleGroup(group: GroupView, prefs: Preferences, forest: Forest): ToggleOutcome {
|
|
61
|
+
const inGroup = new Set(group.rootIds);
|
|
62
|
+
const dropGroup = (id: string) => {
|
|
63
|
+
const family = forest.familyOf.get(id);
|
|
64
|
+
return family !== undefined && inGroup.has(family.root.thread.id);
|
|
65
|
+
};
|
|
66
|
+
if (group.collapsed) {
|
|
67
|
+
return {
|
|
68
|
+
patch: isGroupCollapsed(group.descriptor, prefs) ? toggleGroupCollapse(group.descriptor, prefs) : {},
|
|
69
|
+
drop: null,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// Open only because a target opened it: collapsing drops the targets.
|
|
73
|
+
if (group.userCollapsed) return { patch: {}, drop: dropGroup };
|
|
74
|
+
return { patch: toggleGroupCollapse(group.descriptor, prefs), drop: dropGroup };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface MarkAllRead {
|
|
78
|
+
/** Threads bb's rule calls unread: `actions.setRead(id, true)`. */
|
|
79
|
+
read: string[];
|
|
80
|
+
/** Done-unseen children: stamp `seenAt`. */
|
|
81
|
+
seen: string[];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Every unread thread in the families, descendants included. */
|
|
85
|
+
export function markAllReadPlan(
|
|
86
|
+
families: readonly Family[],
|
|
87
|
+
context: { activeThreadId: string | null; finishedAt: Readonly<Record<string, number>>; seenAt: Readonly<Record<string, number>> },
|
|
88
|
+
): MarkAllRead {
|
|
89
|
+
const read: string[] = [];
|
|
90
|
+
const seen: string[] = [];
|
|
91
|
+
for (const family of families) {
|
|
92
|
+
for (const info of [family.root, ...family.descendants]) {
|
|
93
|
+
if (!info.unread || info.thread.isArchived) continue;
|
|
94
|
+
read.push(info.thread.id);
|
|
95
|
+
if (isDoneUnseen(info.thread, context)) seen.push(info.thread.id);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return { read, seen };
|
|
99
|
+
}
|