xiaolongmr commited on
Commit
b254df8
·
1 Parent(s): 9b99184

Revert "Switch image previews to loaded URLs"

Browse files

This reverts commit 9b99184ceea9451f3a8ab1f877ae6e67b0d83a26.

web/src/app/image/components/image-results.tsx CHANGED
@@ -24,7 +24,6 @@ type ImageResultsProps = {
24
  onReuseTurnConfig: (conversationId: string, turnId: string) => void | Promise<void>;
25
  onRegenerateTurn: (conversationId: string, turnId: string) => void | Promise<void>;
26
  onRetryImage: (conversationId: string, turnId: string, imageId: string) => void | Promise<void>;
27
- onImageUrlReady: (conversationId: string, turnId: string, imageId: string) => void | Promise<void>;
28
  formatConversationTime: (value: string) => string;
29
  };
30
 
@@ -65,7 +64,6 @@ export function ImageResults({
65
  onReuseTurnConfig,
66
  onRegenerateTurn,
67
  onRetryImage,
68
- onImageUrlReady,
69
  formatConversationTime,
70
  }: ImageResultsProps) {
71
  const [imageDimensions, setImageDimensions] = useState<Record<string, string>>({});
@@ -83,6 +81,42 @@ export function ImageResults({
83
  return () => window.clearInterval(timer);
84
  }, [hasPendingTurns]);
85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  const updateImageDimensions = (id: string, width: number, height: number) => {
87
  const dimensions = formatImageDimensions(width, height);
88
  setImageDimensions((current) => {
@@ -93,11 +127,6 @@ export function ImageResults({
93
  });
94
  };
95
 
96
- const markImageUrlReady = (conversationId: string, turnId: string, imageId: string) => {
97
- setUrlReadyImageIds((current) => (current[imageId] ? current : { ...current, [imageId]: true }));
98
- void onImageUrlReady(conversationId, turnId, imageId);
99
- };
100
-
101
  if (!selectedConversation) {
102
  return (
103
  <div className="flex h-full min-h-[260px] items-center justify-center text-center sm:min-h-[420px]">
@@ -229,23 +258,13 @@ export function ImageResults({
229
  const currentIndex = successfulTurnImages.findIndex((item) => item.id === image.id);
230
  const sizeLabel = image.b64_json ? formatBase64ImageSize(image.b64_json) : "";
231
  const dimensions = imageDimensions[image.id];
232
- const urlSrc = normalizeImageUrl(image.url || "");
233
  const imageMeta = [sizeLabel, dimensions].filter(Boolean).join(" · ");
234
 
235
  return (
236
  <div
237
  key={image.id}
238
- className="relative break-inside-avoid"
239
  >
240
- {image.b64_json && urlSrc && !urlReadyImageIds[image.id] ? (
241
- <img
242
- src={urlSrc}
243
- alt=""
244
- aria-hidden="true"
245
- className="pointer-events-none absolute size-px opacity-0"
246
- onLoad={() => markImageUrlReady(selectedConversation.id, turn.id, image.id)}
247
- />
248
- ) : null}
249
  <button
250
  type="button"
251
  onClick={() => onOpenLightbox(successfulTurnImages, currentIndex)}
 
24
  onReuseTurnConfig: (conversationId: string, turnId: string) => void | Promise<void>;
25
  onRegenerateTurn: (conversationId: string, turnId: string) => void | Promise<void>;
26
  onRetryImage: (conversationId: string, turnId: string, imageId: string) => void | Promise<void>;
 
27
  formatConversationTime: (value: string) => string;
28
  };
29
 
 
64
  onReuseTurnConfig,
65
  onRegenerateTurn,
66
  onRetryImage,
 
67
  formatConversationTime,
68
  }: ImageResultsProps) {
69
  const [imageDimensions, setImageDimensions] = useState<Record<string, string>>({});
 
81
  return () => window.clearInterval(timer);
82
  }, [hasPendingTurns]);
83
 
84
+ useEffect(() => {
85
+ const pendingImages =
86
+ selectedConversation?.turns.flatMap((turn) =>
87
+ turn.images.flatMap((image) => {
88
+ const url = normalizeImageUrl(image.url || "");
89
+ if (image.status !== "success" || !image.b64_json || !url || urlReadyImageIds[image.id]) {
90
+ return [];
91
+ }
92
+ return [{ id: image.id, url }];
93
+ }),
94
+ ) || [];
95
+ if (pendingImages.length === 0) {
96
+ return;
97
+ }
98
+
99
+ let cancelled = false;
100
+ const loaders = pendingImages.map(({ id, url }) => {
101
+ const loader = new Image();
102
+ loader.onload = () => {
103
+ if (cancelled) {
104
+ return;
105
+ }
106
+ setUrlReadyImageIds((current) => (current[id] ? current : { ...current, [id]: true }));
107
+ };
108
+ loader.src = url;
109
+ return loader;
110
+ });
111
+
112
+ return () => {
113
+ cancelled = true;
114
+ loaders.forEach((loader) => {
115
+ loader.onload = null;
116
+ });
117
+ };
118
+ }, [selectedConversation, urlReadyImageIds]);
119
+
120
  const updateImageDimensions = (id: string, width: number, height: number) => {
121
  const dimensions = formatImageDimensions(width, height);
122
  setImageDimensions((current) => {
 
127
  });
128
  };
129
 
 
 
 
 
 
130
  if (!selectedConversation) {
131
  return (
132
  <div className="flex h-full min-h-[260px] items-center justify-center text-center sm:min-h-[420px]">
 
258
  const currentIndex = successfulTurnImages.findIndex((item) => item.id === image.id);
259
  const sizeLabel = image.b64_json ? formatBase64ImageSize(image.b64_json) : "";
260
  const dimensions = imageDimensions[image.id];
 
261
  const imageMeta = [sizeLabel, dimensions].filter(Boolean).join(" · ");
262
 
263
  return (
264
  <div
265
  key={image.id}
266
+ className="break-inside-avoid"
267
  >
 
 
 
 
 
 
 
 
 
268
  <button
269
  type="button"
270
  onClick={() => onOpenLightbox(successfulTurnImages, currentIndex)}
web/src/app/image/page.tsx CHANGED
@@ -759,39 +759,6 @@ function ImagePageContent({ session }: { session: StoredAuthSession }) {
759
  clearComposerInputs();
760
  }, [clearComposerInputs]);
761
 
762
- const handleImageUrlReady = useCallback(
763
- async (conversationId: string, turnId: string, imageId: string) => {
764
- const snapshot = conversationsRef.current.find((item) => item.id === conversationId);
765
- if (!snapshot) {
766
- return;
767
- }
768
-
769
- await updateConversation(conversationId, (current) => {
770
- const conversation = current ?? snapshot;
771
- let changed = false;
772
- const turns = conversation.turns.map((turn) => {
773
- if (turn.id !== turnId) {
774
- return turn;
775
- }
776
- const images = turn.images.map((image) => {
777
- if (image.id !== imageId || !image.b64_json || !image.url) {
778
- return image;
779
- }
780
- changed = true;
781
- return {
782
- ...image,
783
- b64_json: undefined,
784
- };
785
- });
786
- return changed ? { ...turn, images } : turn;
787
- });
788
-
789
- return changed ? { ...conversation, turns } : conversation;
790
- });
791
- },
792
- [updateConversation],
793
- );
794
-
795
  const handleCreateDraft = () => {
796
  setSelectedConversationId(null);
797
  resetComposer();
@@ -1571,7 +1538,6 @@ function ImagePageContent({ session }: { session: StoredAuthSession }) {
1571
  onReuseTurnConfig={handleReuseTurnConfig}
1572
  onRegenerateTurn={handleRegenerateTurn}
1573
  onRetryImage={handleRetryImage}
1574
- onImageUrlReady={handleImageUrlReady}
1575
  formatConversationTime={formatConversationTime}
1576
  />
1577
  </div>
 
759
  clearComposerInputs();
760
  }, [clearComposerInputs]);
761
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
762
  const handleCreateDraft = () => {
763
  setSelectedConversationId(null);
764
  resetComposer();
 
1538
  onReuseTurnConfig={handleReuseTurnConfig}
1539
  onRegenerateTurn={handleRegenerateTurn}
1540
  onRetryImage={handleRetryImage}
 
1541
  formatConversationTime={formatConversationTime}
1542
  />
1543
  </div>