HomePilot Deploy Bot commited on
Commit
ab844dd
·
unverified ·
1 Parent(s): a12d1c8

fix(community): real persona thumbnails + proxy-route gallery previews

Browse files
.gitattributes CHANGED
@@ -1,9 +1,9 @@
1
  *.png filter=lfs diff=lfs merge=lfs -text
2
  *.webp filter=lfs diff=lfs merge=lfs -text
3
- *.ico filter=lfs diff=lfs merge=lfs -text
 
4
  *.hpersona filter=lfs diff=lfs merge=lfs -text
5
  *.jpg filter=lfs diff=lfs merge=lfs -text
6
  *.jpeg filter=lfs diff=lfs merge=lfs -text
7
- *.svg filter=lfs diff=lfs merge=lfs -text
8
- *.woff filter=lfs diff=lfs merge=lfs -text
9
  *.woff2 filter=lfs diff=lfs merge=lfs -text
 
 
1
  *.png filter=lfs diff=lfs merge=lfs -text
2
  *.webp filter=lfs diff=lfs merge=lfs -text
3
+ *.svg filter=lfs diff=lfs merge=lfs -text
4
+ *.woff filter=lfs diff=lfs merge=lfs -text
5
  *.hpersona filter=lfs diff=lfs merge=lfs -text
6
  *.jpg filter=lfs diff=lfs merge=lfs -text
7
  *.jpeg filter=lfs diff=lfs merge=lfs -text
 
 
8
  *.woff2 filter=lfs diff=lfs merge=lfs -text
9
+ *.ico filter=lfs diff=lfs merge=lfs -text
community/sample/david/assets/thumb_avatar_david.webp CHANGED

Git LFS Details

  • SHA256: 67b3f356aa7e23926643917bd26df530cdc28f59022e587a1c9f0a284293f839
  • Pointer size: 129 Bytes
  • Size of remote file: 1.77 kB

Git LFS Details

  • SHA256: d7af9ed9e2efcc021dfdabf91055c49e84866da1007b837e3749162d7b20323d
  • Pointer size: 130 Bytes
  • Size of remote file: 11.4 kB
community/sample/diana/assets/thumb_avatar_diana.webp CHANGED

Git LFS Details

  • SHA256: b2ad2b6d0dd3d2182dfa88ed8c33f8ec63e701f94c0731e822d8f90822feb998
  • Pointer size: 129 Bytes
  • Size of remote file: 1.92 kB

Git LFS Details

  • SHA256: eb04e12e7acc45b1c91ba93a273b40c411f6173793495e13bd692832234841c1
  • Pointer size: 129 Bytes
  • Size of remote file: 8.77 kB
community/sample/elena/assets/thumb_avatar_elena.webp CHANGED

Git LFS Details

  • SHA256: 6db3bbe071dffcfad307d0da85a3db12f5694c1bf62d79bb727cd450cc375934
  • Pointer size: 128 Bytes
  • Size of remote file: 984 Bytes

Git LFS Details

  • SHA256: 91f4f5082237117887d56b827693cc6bc268055efff50fe70501cd95b397344a
  • Pointer size: 130 Bytes
  • Size of remote file: 10.1 kB
community/sample/felix/assets/thumb_avatar_felix.webp CHANGED

Git LFS Details

  • SHA256: 33031176a8955d7170bf266e85b923bf41a2a27ec27429ba234de8b8aee3ac27
  • Pointer size: 128 Bytes
  • Size of remote file: 978 Bytes

Git LFS Details

  • SHA256: 087d63b7536713951cd0e5153b081c3b0f7ecc1118cefe89a67dccbf66fe1cb7
  • Pointer size: 129 Bytes
  • Size of remote file: 7.63 kB
community/sample/kai/assets/thumb_avatar_kai.webp CHANGED

Git LFS Details

  • SHA256: 1c82c487921b662e067a0389f0e0827f26269c8ab1d0fb474b9f578273cc8417
  • Pointer size: 129 Bytes
  • Size of remote file: 1.32 kB

Git LFS Details

  • SHA256: 0b72dc45c9a849c21acb8264bc20069a87fda0bacf4307c4e9eb36aa5a821c28
  • Pointer size: 129 Bytes
  • Size of remote file: 8.89 kB
community/sample/luca/assets/thumb_avatar_luca.webp CHANGED

Git LFS Details

  • SHA256: 2b639e69bb1b5590bc09fad909d8a0cb58b0a5d812f03bdaa654248bce8cb89f
  • Pointer size: 129 Bytes
  • Size of remote file: 1.34 kB

Git LFS Details

  • SHA256: 524abae5352ba4fcb252d9edfcd420de7e11b9ab981064da816cd00f5a6b87c1
  • Pointer size: 129 Bytes
  • Size of remote file: 8.46 kB
community/sample/maya/assets/thumb_avatar_maya.webp CHANGED

Git LFS Details

  • SHA256: dc36c40d367170634bea8ee62755926f2cf81822571bef1b9391388457e71cd4
  • Pointer size: 129 Bytes
  • Size of remote file: 1.89 kB

Git LFS Details

  • SHA256: d6f1012273884f2fad055e55498e2fcc1573cb24d4d08f052d8806d451d17da4
  • Pointer size: 129 Bytes
  • Size of remote file: 9.61 kB
community/sample/nora/assets/thumb_avatar_nora.webp CHANGED

Git LFS Details

  • SHA256: f31a1bb9a0cc35d9a103ca5f424277ce5127a5b5cb3a8de0ec0b832f33fdc3ba
  • Pointer size: 129 Bytes
  • Size of remote file: 1.86 kB

Git LFS Details

  • SHA256: 121546432a775940892b22cc1b85205df4f6a6c15045fea74f1c911cf0d504b4
  • Pointer size: 130 Bytes
  • Size of remote file: 10.1 kB
community/sample/priya/assets/thumb_avatar_priya.webp CHANGED

Git LFS Details

  • SHA256: d52b93105d0e96f6f903af25c1e9eb800e4e6948216070e77ecbea924a3fed9e
  • Pointer size: 129 Bytes
  • Size of remote file: 1.82 kB

Git LFS Details

  • SHA256: 776884409bae15cfd322436f7eace9b1207bfa47b932139e51e09b6da9a22d07
  • Pointer size: 129 Bytes
  • Size of remote file: 9.59 kB
community/sample/raven/assets/thumb_avatar_raven.webp CHANGED

Git LFS Details

  • SHA256: 4b6add0114278d8ebba599353ca5773f744932d4879ccf03803267eb0978fd45
  • Pointer size: 129 Bytes
  • Size of remote file: 1.55 kB

Git LFS Details

  • SHA256: 1337381a736f4c0dc746c30116eb6aedab7141f25b9753cd01afc6f175323477
  • Pointer size: 129 Bytes
  • Size of remote file: 9.97 kB
community/sample/soren/assets/thumb_avatar_soren.webp CHANGED

Git LFS Details

  • SHA256: 7128bafee6920ff875c78f41773bd28db71225728900755b59fa24ce57af7514
  • Pointer size: 129 Bytes
  • Size of remote file: 1.31 kB

Git LFS Details

  • SHA256: 628e25866d9178b443442ced77c11de42576da220aa2a878ebd182f2a42cfd06
  • Pointer size: 129 Bytes
  • Size of remote file: 9.98 kB
frontend/.cache-bust CHANGED
@@ -1 +1 @@
1
- 1783158664
 
1
+ 1783159161
frontend/src/ui/CommunityGallery.tsx CHANGED
@@ -64,17 +64,45 @@ type CommunityGalleryProps = {
64
  onInstalled?: () => void // refresh project list after install
65
  }
66
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
  // ---------------------------------------------------------------------------
68
  // Gallery Card
69
  // ---------------------------------------------------------------------------
70
 
71
  function GalleryCard({
72
  item,
 
73
  installing,
74
  onInstall,
75
  onDetail,
76
  }: {
77
  item: CommunityPersonaItem
 
78
  installing: boolean
79
  onInstall: () => void
80
  onDetail: () => void
@@ -90,13 +118,20 @@ function GalleryCard({
90
  <div className="relative w-full max-w-[340px] bg-white/[0.04] border border-white/[0.08] rounded-xl overflow-hidden hover:border-white/[0.16] transition-all group">
91
  {/* Preview */}
92
  <div className="relative aspect-[4/5] bg-black/20 overflow-hidden">
93
- {item.latest?.preview_url ? (
94
  <img
95
- src={item.latest.preview_url}
96
  alt={item.name}
97
  loading="lazy"
98
  className="block w-full h-full object-cover"
99
  onError={(e) => {
 
 
 
 
 
 
 
100
  ;(e.target as HTMLImageElement).style.display = 'none'
101
  }}
102
  />
@@ -849,6 +884,7 @@ export function CommunityGallery({ backendUrl, apiKey, onInstalled }: CommunityG
849
  <GalleryCard
850
  key={item.id}
851
  item={item}
 
852
  installing={
853
  (install.kind === 'downloading' || install.kind === 'previewing' || install.kind === 'installing')
854
  && install.personaId === item.id
@@ -876,7 +912,7 @@ export function CommunityGallery({ backendUrl, apiKey, onInstalled }: CommunityG
876
  <DetailModal
877
  card={detail.card}
878
  item={detail.item}
879
- previewUrl={detail.item.latest?.preview_url}
880
  onClose={() => setDetail(null)}
881
  onInstall={() => handleInstall(detail.item)}
882
  />
 
64
  onInstalled?: () => void // refresh project list after install
65
  }
66
 
67
+ // ---------------------------------------------------------------------------
68
+ // Preview URL resolution
69
+ // ---------------------------------------------------------------------------
70
+
71
+ /**
72
+ * Resolve the thumbnail URL for a community persona.
73
+ *
74
+ * Always prefer the backend proxy route `/community/preview/{id}/{version}`:
75
+ * the backend serves the bundled local asset first and transparently falls
76
+ * back to the remote gallery, so the frontend never depends on (or leaks) an
77
+ * external Worker/R2 URL that may be missing, stale, or blocked. Only when we
78
+ * can't build the proxy route (no id/version) do we fall back to the raw
79
+ * `preview_url` from the registry.
80
+ */
81
+ function resolvePreviewUrl(
82
+ backendUrl: string,
83
+ item: CommunityPersonaItem,
84
+ ): string | undefined {
85
+ const version = item.latest?.version
86
+ if (item.id && version) {
87
+ const base = backendUrl.replace(/\/+$/, '')
88
+ return `${base}/community/preview/${encodeURIComponent(item.id)}/${encodeURIComponent(version)}`
89
+ }
90
+ return item.latest?.preview_url || undefined
91
+ }
92
+
93
  // ---------------------------------------------------------------------------
94
  // Gallery Card
95
  // ---------------------------------------------------------------------------
96
 
97
  function GalleryCard({
98
  item,
99
+ previewUrl,
100
  installing,
101
  onInstall,
102
  onDetail,
103
  }: {
104
  item: CommunityPersonaItem
105
+ previewUrl?: string
106
  installing: boolean
107
  onInstall: () => void
108
  onDetail: () => void
 
118
  <div className="relative w-full max-w-[340px] bg-white/[0.04] border border-white/[0.08] rounded-xl overflow-hidden hover:border-white/[0.16] transition-all group">
119
  {/* Preview */}
120
  <div className="relative aspect-[4/5] bg-black/20 overflow-hidden">
121
+ {previewUrl ? (
122
  <img
123
+ src={previewUrl}
124
  alt={item.name}
125
  loading="lazy"
126
  className="block w-full h-full object-cover"
127
  onError={(e) => {
128
+ if (import.meta.env.DEV) {
129
+ console.warn(
130
+ `[CommunityGallery] preview failed for ${item.id}@${item.latest?.version}:`,
131
+ previewUrl,
132
+ )
133
+ }
134
+ // Last-resort: hide the broken image so the initials placeholder shows.
135
  ;(e.target as HTMLImageElement).style.display = 'none'
136
  }}
137
  />
 
884
  <GalleryCard
885
  key={item.id}
886
  item={item}
887
+ previewUrl={resolvePreviewUrl(cleanUrl, item)}
888
  installing={
889
  (install.kind === 'downloading' || install.kind === 'previewing' || install.kind === 'installing')
890
  && install.personaId === item.id
 
912
  <DetailModal
913
  card={detail.card}
914
  item={detail.item}
915
+ previewUrl={resolvePreviewUrl(cleanUrl, detail.item)}
916
  onClose={() => setDetail(null)}
917
  onInstall={() => handleInstall(detail.item)}
918
  />