diff --git a/resources/style/settings.scss b/resources/style/settings.scss index c6908bd21..14b84cc29 100644 --- a/resources/style/settings.scss +++ b/resources/style/settings.scss @@ -85,3 +85,10 @@ overflow: auto; padding: 0.5rem 2rem 0.5rem 1.25rem; } + +.info-icon { + &:hover { + cursor: help; + color: var(--text-color-strong); + } +} diff --git a/src/frontend/Overlay.tsx b/src/frontend/Overlay.tsx index 1d7b6d1d4..a110b7a3d 100644 --- a/src/frontend/Overlay.tsx +++ b/src/frontend/Overlay.tsx @@ -3,12 +3,12 @@ import React from 'react'; import { TooltipLayer } from 'widgets/popovers'; import { useStore } from './contexts/StoreContext'; -const Overlay = observer(() => { +const Overlay = observer(({ document = window.document }: { document?: Document }) => { const { uiStore } = useStore(); return (
- +
); }); diff --git a/src/frontend/components/PopupWindow.tsx b/src/frontend/components/PopupWindow.tsx index 31e39e93b..fac8b7548 100644 --- a/src/frontend/components/PopupWindow.tsx +++ b/src/frontend/components/PopupWindow.tsx @@ -1,5 +1,6 @@ import React, { useState, useEffect } from 'react'; import ReactDOM from 'react-dom'; +import Overlay from '../Overlay'; const PLATFORM = process.platform; interface IPopupWindowProps { @@ -45,7 +46,12 @@ const PopupWindow: React.FC = (props) => { }, []); if (win) { - return ReactDOM.createPortal(props.children, containerEl); + return ReactDOM.createPortal( + <> + {props.children} + , + containerEl, + ); } return null; }; diff --git a/src/frontend/containers/ContentView/GalleryItem.tsx b/src/frontend/containers/ContentView/GalleryItem.tsx index 9547f48fc..5041c212b 100644 --- a/src/frontend/containers/ContentView/GalleryItem.tsx +++ b/src/frontend/containers/ContentView/GalleryItem.tsx @@ -105,7 +105,7 @@ export const Thumbnail = observer(({ file, mounted, forceNoThumbnail }: ItemProp // The thumbnailPath of an image is always set, but may not exist yet. // When the thumbnail is finished generating, the path will be changed to `${thumbnailPath}?v=1`. if (freshlyGenerated) { - await when(() => file.thumbnailPath.endsWith('?v=1'), { timeout: 5000 }); + await when(() => file.thumbnailPath.endsWith('?v=1'), { timeout: 8000 }); if (!getThumbnail(file).endsWith('?v=1')) { throw new Error('Thumbnail generation timeout.'); } diff --git a/src/frontend/containers/Settings/index.tsx b/src/frontend/containers/Settings/index.tsx index 9e871f3ff..9f958c3c0 100644 --- a/src/frontend/containers/Settings/index.tsx +++ b/src/frontend/containers/Settings/index.tsx @@ -2,7 +2,7 @@ import { shell } from 'electron'; import { runInAction } from 'mobx'; import { observer } from 'mobx-react-lite'; import SysPath from 'path'; -import React, { useCallback, useEffect, useState } from 'react'; +import React, { ReactNode, useCallback, useEffect, useState } from 'react'; import { chromeExtensionUrl, getDefaultBackupDirectory, @@ -337,6 +337,23 @@ const ImportExport = observer(() => { ); }); +const imageFormatInts: Partial> = { + exr: ( + + {IconSet.WARNING} + + ), + psd: ( + + {IconSet.INFO} + + ), +}; + const ImageFormatPicker = observer(() => { const { locationStore, fileStore } = useStore(); @@ -389,6 +406,7 @@ const ImageFormatPicker = observer(() => { checked={newEnabledFileExtensions.has(ext)} onChange={() => toggleExtension(ext)} /> + {imageFormatInts[ext] && <> {imageFormatInts[ext]}} ))} diff --git a/src/frontend/stores/LocationStore.ts b/src/frontend/stores/LocationStore.ts index d07a94b31..9560a20e6 100644 --- a/src/frontend/stores/LocationStore.ts +++ b/src/frontend/stores/LocationStore.ts @@ -52,7 +52,10 @@ class LocationStore { const prefs = JSON.parse(localStorage.getItem(PREFERENCES_STORAGE_KEY) || '') as Preferences; (prefs.extensions || IMG_EXTENSIONS).forEach((ext) => this.enabledFileExtensions.add(ext)); } catch (e) { + // If no preferences found, use defaults IMG_EXTENSIONS.forEach((ext) => this.enabledFileExtensions.add(ext)); + // By default, disable EXR for now (experimental) + this.enabledFileExtensions.delete('exr'); } // Get dirs from backend diff --git a/src/main.ts b/src/main.ts index a634913c8..ad38b8348 100644 --- a/src/main.ts +++ b/src/main.ts @@ -461,16 +461,18 @@ if (isDev()) { } autoUpdater.on('error', (error) => { + // Don't show error messages on startup + if (!hasCheckedForUpdateOnStartup) { + hasCheckedForUpdateOnStartup = true; + console.error('Auto-update error', error); + return; + } + let errorMsg: string = (error.stack || error).toString() || 'Reason unknown, try again later.'; // In case of no network connection... if (errorMsg.includes('INTERNET_DISCONNECTED')) { - // no need to show an error dialog on startup - if (!hasCheckedForUpdateOnStartup) { - hasCheckedForUpdateOnStartup = true; - return; - } - // Otherwise this error occured during a manual update check from the user, show a friendlier message + // This error occured during a manual update check from the user, show a friendlier message errorMsg = 'There seems to be an issue with your internet connection.'; } dialog.showErrorBox('Auto-update error: ', errorMsg); diff --git a/widgets/popovers/Tooltip.tsx b/widgets/popovers/Tooltip.tsx index 49b923da1..ac2b5ffc6 100644 --- a/widgets/popovers/Tooltip.tsx +++ b/widgets/popovers/Tooltip.tsx @@ -2,7 +2,7 @@ import { Placement, VirtualElement } from '@popperjs/core'; import React, { useEffect, useRef, useState } from 'react'; import { usePopper } from 'react-popper'; -export const TooltipLayer = () => { +export const TooltipLayer = ({ document }: { document: Document }) => { const popoverElement = useRef(null); const virtualElement = useRef(null); const popperOptions = useRef({ @@ -116,7 +116,7 @@ export const TooltipLayer = () => { document.removeEventListener('blur', handleHide, true); document.removeEventListener('keydown', handleEscape, true); }; - }, [forceUpdate]); + }, [document, forceUpdate]); return (