Skip to content

Commit 3aa04d4

Browse files
Refactor API URL handling in ReviewRecentSalesPage and FcAddressRating components to use NEXT_PUBLIC_PONDER_URL consistently. Update IPFSUploader to improve zoom handling and default settings on media load, enhancing user experience during image uploads.
1 parent 2a2d2c0 commit 3aa04d4

File tree

3 files changed

+36
-18
lines changed

3 files changed

+36
-18
lines changed

packages/nextjs/app/user/[address]/review/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ const ReviewRecentSalesPage = () => {
4747
if (!me) return;
4848
setLoading(true);
4949
try {
50-
const base = process.env.NEXT_PUBLIC_PONDER_API_URL || "http://127.0.0.1:42069/graphql";
50+
const base = process.env.NEXT_PUBLIC_PONDER_URL || "http://127.0.0.1:42069/graphql";
5151

5252
const listingsQuery = (role: "buyer" | "seller") => `{
5353
listingss(where: {

packages/nextjs/components/marketplace/FcAddressRating.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,7 @@ export const FcAddressRating: React.FC<Props> = ({ address, size = 16, className
2121
if (!reviewee) return;
2222
setLoading(true);
2323
try {
24-
const base =
25-
process.env.NEXT_PUBLIC_PONDER_URL ||
26-
process.env.NEXT_PUBLIC_PONDER_API_URL ||
27-
"http://localhost:42069/graphql";
24+
const base = process.env.NEXT_PUBLIC_PONDER_URL || "http://localhost:42069/graphql";
2825
const query = `
2926
query ReviewsByReviewee($reviewee: String!) {
3027
reviewss(where: { reviewee: $reviewee }, limit: 500, orderBy: "time", orderDirection: "desc") {

packages/nextjs/components/marketplace/IPFSUploader.tsx

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,17 @@ export const IPFSUploader = ({
3030
const DEST_W = 1200;
3131
const DEST_H = 800;
3232

33-
const minCoverZoom = useMemo(() => {
34-
if (!imgDims) return 1;
35-
const cover = Math.max(DEST_W / imgDims.w, DEST_H / imgDims.h);
36-
return cover;
37-
}, [imgDims]);
33+
// Absolute zoom scales relative to the image's natural size
34+
// containZoom: entire image fits within the crop (furthest edges touch)
35+
// coverZoom: crop fully filled by the image (closest edges touch)
36+
const [coverZoom, setCoverZoom] = useState<number>(1);
3837

3938
const zoomBounds = useMemo(() => {
40-
const min = minCoverZoom * 0.5; // allow zooming out to show black bars
41-
const max = minCoverZoom * 4;
39+
const min = 0.75; // normalized contain
40+
// Give headroom above cover to overcome rounding/clamping and allow precise edge contact
41+
const max = Math.max(coverZoom * 3, min + 0.01);
4242
return { min, max };
43-
}, [minCoverZoom]);
43+
}, [coverZoom]);
4444

4545
// container width not needed with react-easy-crop
4646

@@ -152,9 +152,7 @@ export const IPFSUploader = ({
152152
const w = img.naturalWidth || img.width;
153153
const h = img.naturalHeight || img.height;
154154
setImgDims({ w, h });
155-
// default zoom to cover
156-
const cover = Math.max(DEST_W / w, DEST_H / h);
157-
setZoom(cover);
155+
// Default zoom will be set on media load using the actual container size
158156
setCrop({ x: 0, y: 0 });
159157
setCropOpen(true);
160158
} catch {
@@ -202,14 +200,36 @@ export const IPFSUploader = ({
202200
aspect={3 / 2}
203201
crop={crop}
204202
zoom={zoom}
205-
minZoom={minCoverZoom}
206-
maxZoom={minCoverZoom * 5}
203+
minZoom={zoomBounds.min}
204+
maxZoom={zoomBounds.max}
207205
zoomWithScroll
208206
restrictPosition={false}
209207
showGrid={false}
210208
onCropChange={setCrop}
211209
onZoomChange={setZoom}
212210
onCropComplete={(_: Area, areaPixels: Area) => setCroppedAreaPixels(areaPixels)}
211+
onMediaLoaded={({ naturalWidth, naturalHeight }) => {
212+
const rect = cropRef.current?.getBoundingClientRect();
213+
if (rect && naturalWidth && naturalHeight) {
214+
// Compute absolute scales relative to natural size. Account for 3:2 crop area.
215+
const containerW = rect.width;
216+
const containerH = rect.height;
217+
const containAbs = Math.min(containerW / naturalWidth, containerH / naturalHeight);
218+
const coverAbs = Math.max(containerW / naturalWidth, containerH / naturalHeight);
219+
const coverFactor = coverAbs / containAbs; // normalized units
220+
setCoverZoom(coverFactor);
221+
// Default view = cover and centered
222+
setZoom(coverFactor);
223+
// Center programmatically so the nearest edges are symmetric
224+
// crop in react-easy-crop is percentage based; {x:0,y:0} is centered
225+
// Ensure centered positioning at initial load
226+
setCrop({ x: 0, y: 0 });
227+
} else {
228+
setCoverZoom(1);
229+
setZoom(1);
230+
setCrop({ x: 0, y: 0 });
231+
}
232+
}}
213233
style={{ containerStyle: { width: "100%", height: "100%" } }}
214234
/>
215235
</div>
@@ -232,6 +252,7 @@ export const IPFSUploader = ({
232252
setImgDims(null);
233253
setCrop({ x: 0, y: 0 });
234254
setZoom(1);
255+
setCoverZoom(1);
235256
onSelected?.(null);
236257
setCropOpen(false);
237258
}}

0 commit comments

Comments
 (0)