mirror of
https://github.com/wahyd4/hey-search.git
synced 2026-08-08 21:05:14 +10:00
feat: show image dimensions + lock horizontal scroll on mobile
- Add width/height fields to ImageResult model - Extract dimensions from DuckDuckGo and Bing engine responses - Show size (e.g. 1920×1080) on card hover overlay and in lightbox details - Prevent horizontal scrolling/panning on mobile (overflow-x: hidden + overscroll-behavior) - Allow pinch-to-zoom via viewport meta (user-scalable=yes, maximum-scale=5) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -213,6 +213,8 @@ class BingEngine(SearchEngine):
|
||||
thumbnail_src=thumb_url or img_url,
|
||||
source="Bing",
|
||||
engine=self.name,
|
||||
width=int(data.get("mw", 0) or 0),
|
||||
height=int(data.get("mh", 0) or 0),
|
||||
)
|
||||
)
|
||||
except _json.JSONDecodeError:
|
||||
|
||||
@@ -104,6 +104,8 @@ class DuckDuckGoEngine(SearchEngine):
|
||||
thumbnail_src=item.get("thumbnail", ""),
|
||||
source=item.get("source", ""),
|
||||
engine=self.name,
|
||||
width=int(item.get("width", 0) or 0),
|
||||
height=int(item.get("height", 0) or 0),
|
||||
))
|
||||
|
||||
return results
|
||||
|
||||
@@ -28,6 +28,8 @@ class ImageResult(BaseModel):
|
||||
source: str = ""
|
||||
engine: str = ""
|
||||
rank: int = 0
|
||||
width: int = 0
|
||||
height: int = 0
|
||||
|
||||
|
||||
class EngineError(BaseModel):
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, user-scalable=yes" />
|
||||
<title>Hey Search</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -2,6 +2,11 @@ import { useState, useEffect, useCallback, type MouseEvent } from "react";
|
||||
import type { ImageResult } from "@/lib/api";
|
||||
import { X, ChevronLeft, ChevronRight } from "lucide-react";
|
||||
|
||||
function formatSize(w: number, h: number): string | null {
|
||||
if (w > 0 && h > 0) return `${w}×${h}`;
|
||||
return null;
|
||||
}
|
||||
|
||||
interface ImageResultsProps {
|
||||
results: ImageResult[];
|
||||
}
|
||||
@@ -71,7 +76,14 @@ export function ImageResults({ results }: ImageResultsProps) {
|
||||
{/* Hover overlay with title */}
|
||||
<div className="absolute inset-x-0 bottom-0 bg-gradient-to-t from-black/70 to-transparent p-2 opacity-0 transition-opacity group-hover:opacity-100">
|
||||
<p className="truncate text-xs text-white">{img.title}</p>
|
||||
<p className="truncate text-[10px] text-white/60">{img.source}</p>
|
||||
<div className="flex items-center gap-1">
|
||||
<p className="truncate text-[10px] text-white/60">{img.source}</p>
|
||||
{formatSize(img.width, img.height) && (
|
||||
<span className="ml-auto shrink-0 text-[10px] tabular-nums text-white/60">
|
||||
{formatSize(img.width, img.height)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
))}
|
||||
@@ -127,6 +139,9 @@ export function ImageResults({ results }: ImageResultsProps) {
|
||||
<h3 className="font-medium">{selected.title}</h3>
|
||||
<p className="mt-1 text-sm text-muted-foreground">
|
||||
Source: {selected.source} • Engine: {selected.engine}
|
||||
{formatSize(selected.width, selected.height) && (
|
||||
<> • {formatSize(selected.width, selected.height)}px</>
|
||||
)}
|
||||
<span className="ml-2 tabular-nums opacity-60">
|
||||
{selectedIndex + 1} / {results.length}
|
||||
</span>
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
html, body {
|
||||
overflow-x: hidden;
|
||||
overscroll-behavior-x: none;
|
||||
}
|
||||
|
||||
:root {
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.145 0 0);
|
||||
|
||||
@@ -18,6 +18,8 @@ export interface ImageResult {
|
||||
source: string;
|
||||
engine: string;
|
||||
rank: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface EngineError {
|
||||
|
||||
Reference in New Issue
Block a user