Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 6 additions & 1 deletion apps/app/src/channel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,12 @@ export function Channel(

const opener = useRef<() => void>(undefined);
useEffect(() => {
publish(channel.id, { diff: () => opener.current?.() });
publish(channel.id, {
diff: (file) => {
if (file) publish(channel.id, { reveal: { chat, file, key: Date.now() } });
opener.current?.();
},
});
return () => forget(channel.id);
}, [channel.id]);

Expand Down
6 changes: 5 additions & 1 deletion apps/app/src/conversation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Composer } from "./composer";
import { DeleteMessage } from "./delete-message";
import { desktop } from "./desktop";
import { EditMessage } from "./edit-message";
import { publish } from "./details";
import { publish, useDetails } from "./details";
import { host } from "./host";
import { MessageQueue } from "./message-queue";
import { OfflineHost } from "./onboarding";
Expand Down Expand Up @@ -54,6 +54,7 @@ export function Conversation(
// until then is not the user's to retry.
const failed = !offline && !transition && transcript.error;
const chat = transcript.info?.chats.find((value) => value.id === id);
const { diff } = useDetails(channel.id);
const model = chat?.model || channel.model;
const people = useSyncExternalStore(host.subscribe, () => host.people);
// This app's own host, or the peer host relaying this channel to it, stopped answering.
Expand Down Expand Up @@ -217,6 +218,9 @@ export function Conversation(
return source && (() => onOpen(source));
}}
intro={{ name: channel.name, createdAt: Math.floor(channel.created / 1000) }}
onFileOpen={diff}
onDiffFileOpen={diff}
onReviewChanges={diff && (() => diff())}
/>
)
: offline
Expand Down
6 changes: 4 additions & 2 deletions apps/app/src/details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ export type Details = {
sharedLive?: boolean;
desktop?: boolean;
desktopLive?: boolean;
/** Shows the chat's Diff tab, opening one when none is open. */
diff?: () => void;
/** Shows the chat's Diff tab, opening one when none is open, at `file` when it changed. */
diff?: (file?: string) => void;
/** A file the chat's Diff should show once its changes list it; `null` once shown. */
reveal?: { chat: number; file: string; key: number } | null;
};

const EMPTY: Details = {};
Expand Down
14 changes: 13 additions & 1 deletion apps/app/src/panels/diff.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,15 @@ function Note({ children }: { children: string }) {
/** The chat's changes, polled while the tab is visible and the window focused. */
export function Diff({ channel: listing, chat, user, active }: Props) {
const channel = listing.id;
const { pull } = useDetails(channel);
const { pull, reveal } = useDetails(channel);
const git = useGit(listing, chat, user);
const status = useSyncExternalStore(host.subscribe, () => host.status);
const focused = useSyncExternalStore(subscribe, () => document.hasFocus());
const [changes, setChanges] = useState<Changes>();
const [error, setError] = useState<string>();
const [loaded, setLoaded] = useState(new Map<string, Loaded>());
const [first, setFirst] = useState<string>();
const [selected, setSelected] = useState<{ file?: string; key?: number }>({});
const inflight = useRef(new Set<string>());

useEffect(() => {
Expand All @@ -121,6 +122,14 @@ export function Diff({ channel: listing, chat, user, active }: Props) {
};
}, [channel, chat, active, focused, status]);

// A turn's file card asks for its file before this tab may have read the changes listing it.
useEffect(() => {
if (!reveal || reveal.chat !== chat || !changes) return;
const change = changes.files.find((change) => change.file === reveal.file);
if (change) setSelected({ file: key(change.file, group(change)), key: reveal.key });
publish(channel, { reveal: null });
}, [channel, chat, changes, reveal]);

// Git actions read the details' changes, so a fetch's new behind count reaches them from here.
useEffect(() => {
if (changes) publish(channel, { changes });
Expand Down Expand Up @@ -229,6 +238,9 @@ export function Diff({ channel: listing, chat, user, active }: Props) {
onCreateDraftPr={git.createDraftPr}
actions={git.actions}
onFileOpen={open}
selected={selected.file}
selectedKey={selected.key}
onSelectedChange={(file) => setSelected({ file })}
className="rounded-none border-0"
/>
);
Expand Down