mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2026-05-18 21:36:56 -04:00
[ENG-1825] Show thumb image if original is not available (#2617)
* show thumb image if original is not available * remove space * formatting
This commit is contained in:
@@ -44,6 +44,9 @@ export interface ThumbProps {
|
||||
}
|
||||
|
||||
type ThumbType = { variant: 'original' } | { variant: 'thumbnail' } | { variant: 'icon' };
|
||||
type LoadState = {
|
||||
[K in 'original' | 'thumbnail' | 'icon']: 'notLoaded' | 'loaded' | 'error';
|
||||
};
|
||||
|
||||
export const FileThumb = forwardRef<HTMLImageElement, ThumbProps>((props, ref) => {
|
||||
const isDark = useIsDark();
|
||||
@@ -55,9 +58,11 @@ export const FileThumb = forwardRef<HTMLImageElement, ThumbProps>((props, ref) =
|
||||
|
||||
const { library } = useLibraryContext();
|
||||
|
||||
const [loadState, setLoadState] = useState<{
|
||||
[K in 'original' | 'thumbnail' | 'icon']: 'notLoaded' | 'loaded' | 'error';
|
||||
}>({ original: 'notLoaded', thumbnail: 'notLoaded', icon: 'notLoaded' });
|
||||
const [loadState, setLoadState] = useState<LoadState>({
|
||||
original: 'notLoaded',
|
||||
thumbnail: 'notLoaded',
|
||||
icon: 'notLoaded'
|
||||
});
|
||||
|
||||
const childClassName = 'max-h-full max-w-full object-contain';
|
||||
const frameClassName = clsx(frame.className, props.frameClassName);
|
||||
|
||||
@@ -7,6 +7,8 @@ import {
|
||||
Plus,
|
||||
SidebarSimple,
|
||||
Slideshow,
|
||||
Warning,
|
||||
WarningCircle,
|
||||
X
|
||||
} from '@phosphor-icons/react';
|
||||
import * as Dialog from '@radix-ui/react-dialog';
|
||||
@@ -15,6 +17,7 @@ import {
|
||||
ButtonHTMLAttributes,
|
||||
createContext,
|
||||
createRef,
|
||||
EventHandler,
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
@@ -87,6 +90,9 @@ export const QuickPreview = () => {
|
||||
const [isContextMenuOpen, setIsContextMenuOpen] = useState<boolean>(false);
|
||||
const [isRenaming, setIsRenaming] = useState<boolean>(false);
|
||||
const [newName, setNewName] = useState<string | null>(null);
|
||||
const [thumbnailLoading, setThumbnailLoading] = useState<'notLoaded' | 'loaded' | 'error'>(
|
||||
'notLoaded'
|
||||
);
|
||||
|
||||
const { t } = useLocale();
|
||||
|
||||
@@ -156,6 +162,7 @@ export const QuickPreview = () => {
|
||||
|
||||
if (open || item) return;
|
||||
|
||||
setThumbnailLoading('notLoaded');
|
||||
getQuickPreviewStore().open = false;
|
||||
getQuickPreviewStore().itemIndex = 0;
|
||||
setShowMetadata(false);
|
||||
@@ -247,7 +254,6 @@ export const QuickPreview = () => {
|
||||
|
||||
const background = !withoutBackgroundKinds.includes(kind);
|
||||
const icon = iconKinds.includes(kind);
|
||||
|
||||
return (
|
||||
<Dialog.Root open={open} onOpenChange={(open) => (getQuickPreviewStore().open = open)}>
|
||||
<QuickPreviewContext.Provider value={{ background }}>
|
||||
@@ -277,21 +283,23 @@ export const QuickPreview = () => {
|
||||
>
|
||||
<div
|
||||
className={clsx(
|
||||
'flex h-full overflow-hidden rounded-md border',
|
||||
'relative flex h-full overflow-hidden rounded-md border',
|
||||
isDark ? 'border-app-line/80' : 'border-app-line/10'
|
||||
)}
|
||||
>
|
||||
<div className="relative flex flex-1 flex-col overflow-hidden bg-app/80 backdrop-blur">
|
||||
{background && (
|
||||
<div className="absolute inset-0 overflow-hidden">
|
||||
<FileThumb
|
||||
data={item}
|
||||
cover={true}
|
||||
childClassName="scale-125"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/50 backdrop-blur-3xl" />
|
||||
</div>
|
||||
)}
|
||||
<div className="relative flex flex-1 flex-col justify-between overflow-hidden bg-app/80 backdrop-blur">
|
||||
{thumbnailLoading !== 'error' &&
|
||||
thumbnailLoading !== 'notLoaded' &&
|
||||
background && (
|
||||
<div className="absolute inset-0 overflow-hidden">
|
||||
<FileThumb
|
||||
data={item}
|
||||
cover
|
||||
childClassName="scale-125"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/50 backdrop-blur-3xl" />
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className={clsx(
|
||||
'z-50 flex items-center p-2',
|
||||
@@ -307,6 +315,21 @@ export const QuickPreview = () => {
|
||||
</Dialog.Close>
|
||||
</Tooltip>
|
||||
|
||||
{thumbnailLoading === 'error' && (
|
||||
<Tooltip label={t('quickpreview_thumbnail_error_tip')}>
|
||||
<div className="ml-1 flex items-center gap-1 rounded-md border border-white/5 bg-app-lightBox/30 p-1.5 backdrop-blur-md">
|
||||
<WarningCircle
|
||||
className="text-red-500"
|
||||
weight="fill"
|
||||
size={14}
|
||||
/>
|
||||
<p className="text-xs text-ink">
|
||||
{t('quickpreview_thumbnail_error_message')}
|
||||
</p>
|
||||
</div>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
{items.length > 1 && (
|
||||
<div className="ml-2 flex">
|
||||
<Tooltip label={t('back')}>
|
||||
@@ -550,33 +573,56 @@ export const QuickPreview = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<FileThumb
|
||||
data={item}
|
||||
onLoad={(type) =>
|
||||
type.variant === 'original' && setThumbErrorToast(undefined)
|
||||
}
|
||||
onError={(type, error) =>
|
||||
type.variant === 'original' &&
|
||||
setThumbErrorToast({
|
||||
title: t('error_loading_original_file'),
|
||||
body: error.message
|
||||
})
|
||||
}
|
||||
loadOriginal
|
||||
frameClassName="!border-0"
|
||||
mediaControls
|
||||
className={clsx(
|
||||
'm-3 !w-auto flex-1 !overflow-hidden rounded',
|
||||
!background && !icon && 'bg-app-box shadow'
|
||||
)}
|
||||
childClassName={clsx(
|
||||
'rounded',
|
||||
kind === 'Text' && 'p-3',
|
||||
!icon && 'h-full',
|
||||
textKinds.includes(kind) && 'select-text'
|
||||
)}
|
||||
magnification={magnification}
|
||||
/>
|
||||
{thumbnailLoading === 'error' ? (
|
||||
<>
|
||||
<FileThumb
|
||||
data={item}
|
||||
frameClassName="!border-0"
|
||||
className={clsx(
|
||||
'mx-auto my-3 !w-auto flex-1 !overflow-hidden rounded',
|
||||
!background && !icon && 'bg-app-box shadow'
|
||||
)}
|
||||
childClassName={clsx(
|
||||
'rounded',
|
||||
kind === 'Text' && 'p-3',
|
||||
!icon && 'h-full',
|
||||
textKinds.includes(kind) && 'select-text'
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<FileThumb
|
||||
data={item}
|
||||
onLoad={(type) => {
|
||||
setThumbnailLoading('loaded');
|
||||
type.variant === 'original' &&
|
||||
setThumbErrorToast(undefined);
|
||||
}}
|
||||
onError={(type, error) => {
|
||||
setThumbnailLoading('error');
|
||||
type.variant === 'original' &&
|
||||
setThumbErrorToast({
|
||||
title: t('error_loading_original_file'),
|
||||
body: error.message
|
||||
});
|
||||
}}
|
||||
loadOriginal
|
||||
frameClassName="!border-0"
|
||||
mediaControls
|
||||
className={clsx(
|
||||
thumbnailLoading === 'notLoaded' && 'hidden',
|
||||
'm-3 !w-auto flex-1 !overflow-hidden rounded',
|
||||
!background && !icon && 'bg-app-box shadow'
|
||||
)}
|
||||
childClassName={clsx(
|
||||
'rounded',
|
||||
kind === 'Text' && 'p-3',
|
||||
!icon && 'h-full',
|
||||
textKinds.includes(kind) && 'select-text'
|
||||
)}
|
||||
magnification={magnification}
|
||||
/>
|
||||
)}
|
||||
|
||||
{explorerLayoutStore.showImageSlider && activeItem && (
|
||||
<ImageSlider activeItem={activeItem} />
|
||||
|
||||
@@ -560,6 +560,8 @@
|
||||
"quick_preview": "معاينة سريعة",
|
||||
"quick_rescan_started": "Quick rescan started",
|
||||
"quick_view": "عرض سريع",
|
||||
"quickpreview_thumbnail_error_message": "غير قادر على تحميل الصورة ذات الدقة الكاملة",
|
||||
"quickpreview_thumbnail_error_tip": "تعذر العثور على الصورة. ولذلك، يتم عرض الصورة المصغرة.",
|
||||
"random": "عشوائي",
|
||||
"receiver": "المتلقي",
|
||||
"receiver_description": "تتلقى هذه العملية العمليات من Spacedrive Cloud وتخزنها.",
|
||||
|
||||
@@ -551,6 +551,8 @@
|
||||
"quick_preview": "Хуткі прагляд",
|
||||
"quick_rescan_started": "Пачата хуткае сканіраванне",
|
||||
"quick_view": "Хуткі прагляд",
|
||||
"quickpreview_thumbnail_error_message": "Немагчыма загрузіць выяву ў поўным раздзяленні",
|
||||
"quickpreview_thumbnail_error_tip": "Выяву не ўдалося знайсці. Такім чынам, паказана мініяцюра.",
|
||||
"random": "Выпадковы",
|
||||
"receiver": "Атрымальнік",
|
||||
"receiver_description": "Гэты працэс атрымлівае і захоўвае аперацыі з Spacedrive Cloud.",
|
||||
|
||||
@@ -170,8 +170,8 @@
|
||||
"dialog": "Dialog",
|
||||
"dialog_shortcut_description": "Um Aktionen und Operationen auszuführen",
|
||||
"direction": "Richtung",
|
||||
"directory": "Verzeichnis",
|
||||
"directories": "Verzeichnisse",
|
||||
"directory": "Verzeichnis",
|
||||
"disabled": "Deaktiviert",
|
||||
"disconnected": "Getrennt",
|
||||
"display_formats": "Anzeigeformate",
|
||||
@@ -548,6 +548,8 @@
|
||||
"quick_preview": "Schnellvorschau",
|
||||
"quick_rescan_started": "Schnellsuche gestartet",
|
||||
"quick_view": "Schnellansicht",
|
||||
"quickpreview_thumbnail_error_message": "Bild in voller Auflösung kann nicht geladen werden",
|
||||
"quickpreview_thumbnail_error_tip": "Das Bild konnte nicht gefunden werden. Daher wird das Miniaturbild angezeigt.",
|
||||
"random": "Zufällig",
|
||||
"receiver": "Empfänger",
|
||||
"receiver_description": "Dieser Prozess empfängt und speichert Vorgänge von Spacedrive Cloud.",
|
||||
@@ -600,8 +602,8 @@
|
||||
"secure_delete": "Sicheres Löschen",
|
||||
"security": "Sicherheit",
|
||||
"security_description": "Halten deinen Client sicher.",
|
||||
"see_more": "Mehr anzeigen",
|
||||
"see_less": "Weniger anzeigen",
|
||||
"see_more": "Mehr anzeigen",
|
||||
"send": "Senden",
|
||||
"send_report": "Send Report",
|
||||
"sender": "Absender",
|
||||
|
||||
@@ -554,6 +554,8 @@
|
||||
"quick_preview": "Quick Preview",
|
||||
"quick_rescan_started": "Quick rescan started",
|
||||
"quick_view": "Quick view",
|
||||
"quickpreview_thumbnail_error_message": "Unable to load full resolution image",
|
||||
"quickpreview_thumbnail_error_tip": "The image was unable to be found. Therefore, the thumbnail is shown.",
|
||||
"random": "Random",
|
||||
"receiver": "Receiver",
|
||||
"receiver_description": "This process receives and stores operations from Spacedrive Cloud.",
|
||||
|
||||
@@ -550,6 +550,8 @@
|
||||
"quick_preview": "Vista rápida",
|
||||
"quick_rescan_started": "Quick rescan started",
|
||||
"quick_view": "Vista rápida",
|
||||
"quickpreview_thumbnail_error_message": "No se puede cargar la imagen en resolución completa",
|
||||
"quickpreview_thumbnail_error_tip": "No se pudo encontrar la imagen. Por lo tanto, se muestra la miniatura.",
|
||||
"random": "Aleatorio",
|
||||
"receiver": "Receptor",
|
||||
"receiver_description": "Este proceso recibe y almacena operaciones de Spacedrive Cloud.",
|
||||
|
||||
@@ -550,6 +550,8 @@
|
||||
"quick_preview": "Aperçu rapide",
|
||||
"quick_rescan_started": "Quick rescan started",
|
||||
"quick_view": "Vue rapide",
|
||||
"quickpreview_thumbnail_error_message": "Impossible de charger l'image en pleine résolution",
|
||||
"quickpreview_thumbnail_error_tip": "L'image n'a pas pu être trouvée. Par conséquent, la vignette est affichée.",
|
||||
"random": "Aléatoire",
|
||||
"receiver": "Destinataire",
|
||||
"receiver_description": "Ce processus reçoit et stocke les opérations de Spacedrive Cloud.",
|
||||
|
||||
@@ -550,6 +550,8 @@
|
||||
"quick_preview": "Anteprima rapida",
|
||||
"quick_rescan_started": "Quick rescan started",
|
||||
"quick_view": "Visualizzazione rapida",
|
||||
"quickpreview_thumbnail_error_message": "Impossibile caricare l'immagine a piena risoluzione",
|
||||
"quickpreview_thumbnail_error_tip": "Impossibile trovare l'immagine. Pertanto, viene mostrata la miniatura.",
|
||||
"random": "Casuale",
|
||||
"receiver": "Ricevitore",
|
||||
"receiver_description": "Questo processo riceve e archivia le operazioni da Spacedrive Cloud.",
|
||||
|
||||
@@ -544,6 +544,8 @@
|
||||
"quick_preview": "クイック プレビュー",
|
||||
"quick_rescan_started": "簡易再スキャンを開始",
|
||||
"quick_view": "クイック プレビュー",
|
||||
"quickpreview_thumbnail_error_message": "フル解像度の画像を読み込めません",
|
||||
"quickpreview_thumbnail_error_tip": "画像が見つかりませんでした。そのため、サムネイルが表示されます。",
|
||||
"random": "ランダム",
|
||||
"receiver": "受信機",
|
||||
"receiver_description": "このプロセスは、Spacedrive Cloud から操作を受信して保存します。",
|
||||
|
||||
@@ -548,6 +548,8 @@
|
||||
"quick_preview": "Snelle Voorvertoning",
|
||||
"quick_rescan_started": "Quick rescan started",
|
||||
"quick_view": "Geef snel weer",
|
||||
"quickpreview_thumbnail_error_message": "Kan afbeelding met volledige resolutie niet laden",
|
||||
"quickpreview_thumbnail_error_tip": "De afbeelding kon niet worden gevonden. Daarom wordt de miniatuur weergegeven.",
|
||||
"random": "Willekeurig",
|
||||
"receiver": "Ontvanger",
|
||||
"receiver_description": "Dit proces ontvangt en bewaart bewerkingen van Spacedrive Cloud.",
|
||||
|
||||
@@ -551,6 +551,8 @@
|
||||
"quick_preview": "Быстрый просмотр",
|
||||
"quick_rescan_started": "Начато быстрое сканирование",
|
||||
"quick_view": "Быстрый просмотр",
|
||||
"quickpreview_thumbnail_error_message": "Невозможно загрузить изображение в полном разрешении.",
|
||||
"quickpreview_thumbnail_error_tip": "Изображение не удалось найти. Поэтому отображается миниатюра.",
|
||||
"random": "Случайный",
|
||||
"receiver": "Получатель",
|
||||
"receiver_description": "Этот процесс получает и сохраняет операции из Spacedrive Cloud.",
|
||||
|
||||
@@ -548,6 +548,8 @@
|
||||
"quick_preview": "Hızlı Önizleme",
|
||||
"quick_rescan_started": "Quick rescan started",
|
||||
"quick_view": "Hızlı bakış",
|
||||
"quickpreview_thumbnail_error_message": "Tam çözünürlüklü resim yüklenemiyor",
|
||||
"quickpreview_thumbnail_error_tip": "Resim bulunamadı. Bu nedenle küçük resim gösterilir.",
|
||||
"random": "Rastgele",
|
||||
"receiver": "Alıcı",
|
||||
"receiver_description": "Bu süreç, işlemleri Spacedrive Cloud'dan alır ve saklar.",
|
||||
|
||||
@@ -544,6 +544,8 @@
|
||||
"quick_preview": "快速预览",
|
||||
"quick_rescan_started": "正在快速重新扫描目录。",
|
||||
"quick_view": "快速查看",
|
||||
"quickpreview_thumbnail_error_message": "无法加载全分辨率图像",
|
||||
"quickpreview_thumbnail_error_tip": "无法找到图像。因此显示缩略图。",
|
||||
"random": "随机的",
|
||||
"receiver": "接收者",
|
||||
"receiver_description": "该进程接收并存储来自 Spacedrive Cloud 的操作。",
|
||||
|
||||
@@ -544,6 +544,8 @@
|
||||
"quick_preview": "快速預覽",
|
||||
"quick_rescan_started": "Quick rescan started",
|
||||
"quick_view": "快速查看",
|
||||
"quickpreview_thumbnail_error_message": "無法載入全解析度影像",
|
||||
"quickpreview_thumbnail_error_tip": "無法找到該圖像。因此,顯示縮圖。",
|
||||
"random": "隨機的",
|
||||
"receiver": "接收者",
|
||||
"receiver_description": "此進程接收並儲存來自 Spacedrive Cloud 的操作。",
|
||||
|
||||
Reference in New Issue
Block a user