diff --git a/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons.d.ts b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons.d.ts
new file mode 100644
index 00000000000..8e196020402
--- /dev/null
+++ b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons.d.ts
@@ -0,0 +1,8 @@
+// Support importing SVG files as strings
+
+declare module '*.svg' {
+
+ const content: string;
+
+ export default content;
+}
\ No newline at end of file
diff --git a/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/LICENSE.md b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/LICENSE.md
new file mode 100644
index 00000000000..518ad472680
--- /dev/null
+++ b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/LICENSE.md
@@ -0,0 +1,7 @@
+The mimetype icons originate from the Elementary icon theme:
+
+Link: https://github.com/elementary/icons
+Author: Members of the Elementary OS team (https://github.com/orgs/elementary/people)
+License: GPLv3 (https://choosealicense.com/licenses/gpl-3.0/)
+
+https://github.com/linuxmint/mint-l-icons/tree/master/src/mimetypes
\ No newline at end of file
diff --git a/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/application-json.svg b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/application-json.svg
new file mode 100644
index 00000000000..2cb871fa372
--- /dev/null
+++ b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/application-json.svg
@@ -0,0 +1,95 @@
+
+
diff --git a/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/application-pdf.svg b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/application-pdf.svg
new file mode 100644
index 00000000000..c6a0a6caa68
--- /dev/null
+++ b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/application-pdf.svg
@@ -0,0 +1,73 @@
+
+
diff --git a/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/audio-x-generic.svg b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/audio-x-generic.svg
new file mode 100644
index 00000000000..81cde3317a3
--- /dev/null
+++ b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/audio-x-generic.svg
@@ -0,0 +1,60 @@
+
+
diff --git a/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/image-loading.svg b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/image-loading.svg
new file mode 100644
index 00000000000..3d587eb2f71
--- /dev/null
+++ b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/image-loading.svg
@@ -0,0 +1,64 @@
+
+
diff --git a/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/image-x-generic.svg b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/image-x-generic.svg
new file mode 100644
index 00000000000..5bed5a1f4dc
--- /dev/null
+++ b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/image-x-generic.svg
@@ -0,0 +1,247 @@
+
+
diff --git a/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/model.svg b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/model.svg
new file mode 100644
index 00000000000..5d5a22d2a4b
--- /dev/null
+++ b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/model.svg
@@ -0,0 +1,38 @@
+
+
diff --git a/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/package-x-generic.svg b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/package-x-generic.svg
new file mode 100644
index 00000000000..26146f7c1f6
--- /dev/null
+++ b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/package-x-generic.svg
@@ -0,0 +1,167 @@
+
+
diff --git a/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/text-html.svg b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/text-html.svg
new file mode 100644
index 00000000000..11d468de20c
--- /dev/null
+++ b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/text-html.svg
@@ -0,0 +1,69 @@
+
+
diff --git a/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/text-x-generic.svg b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/text-x-generic.svg
new file mode 100644
index 00000000000..c866c5c01e5
--- /dev/null
+++ b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/text-x-generic.svg
@@ -0,0 +1,60 @@
+
+
diff --git a/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/text-x-makefile.svg b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/text-x-makefile.svg
new file mode 100644
index 00000000000..0c049bbf450
--- /dev/null
+++ b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/text-x-makefile.svg
@@ -0,0 +1,69 @@
+
+
diff --git a/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/video-x-generic.svg b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/video-x-generic.svg
new file mode 100644
index 00000000000..c1888ad11d4
--- /dev/null
+++ b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/video-x-generic.svg
@@ -0,0 +1,120 @@
+
+
diff --git a/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/x-office-document.svg b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/x-office-document.svg
new file mode 100644
index 00000000000..2924227d253
--- /dev/null
+++ b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/x-office-document.svg
@@ -0,0 +1,93 @@
+
+
diff --git a/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/x-office-presentation.svg b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/x-office-presentation.svg
new file mode 100644
index 00000000000..cf448d97b26
--- /dev/null
+++ b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/x-office-presentation.svg
@@ -0,0 +1,276 @@
+
+
diff --git a/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/x-office-spreadsheet.svg b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/x-office-spreadsheet.svg
new file mode 100644
index 00000000000..dcc998d3740
--- /dev/null
+++ b/specifyweb/frontend/js_src/lib/components/Attachments/MimetypeIcons/x-office-spreadsheet.svg
@@ -0,0 +1,46 @@
+
+
diff --git a/specifyweb/frontend/js_src/lib/components/Attachments/attachments.ts b/specifyweb/frontend/js_src/lib/components/Attachments/attachments.ts
index 17220ed6e45..88f3e34d038 100644
--- a/specifyweb/frontend/js_src/lib/components/Attachments/attachments.ts
+++ b/specifyweb/frontend/js_src/lib/components/Attachments/attachments.ts
@@ -10,9 +10,22 @@ import type { SpecifyResource } from '../DataModel/legacyTypes';
import { tables } from '../DataModel/tables';
import type { Attachment } from '../DataModel/types';
import { load } from '../InitialContext';
-import { getIcon, unknownIcon } from '../InitialContext/icons';
import { getPref } from '../InitialContext/remotePrefs';
import { formatUrl } from '../Router/queryString';
+// Import SVG icons, but better than in Icons.tsx
+import applicationJsonIcon from './MimetypeIcons/application-json.svg';
+import applicationPdfIcon from './MimetypeIcons/application-pdf.svg';
+import audioXGenericIcon from './MimetypeIcons/audio-x-generic.svg';
+import imageXGenericIcon from './MimetypeIcons/image-x-generic.svg';
+import modelIcon from './MimetypeIcons/model.svg';
+import packageXgeneric from './MimetypeIcons/package-x-generic.svg';
+import textHtmlIcon from './MimetypeIcons/text-html.svg';
+import textXGenericIcon from './MimetypeIcons/text-x-generic.svg';
+import textXMakefileIcon from './MimetypeIcons/text-x-makefile.svg';
+import videoXGenericIcon from './MimetypeIcons/video-x-generic.svg';
+import xOfficeDocumentIcon from './MimetypeIcons/x-office-document.svg';
+import xOfficePresentationIcon from './MimetypeIcons/x-office-presentation.svg';
+import xOfficeSpreadsheetIcon from './MimetypeIcons/x-office-spreadsheet.svg';
type AttachmentSettings = {
readonly collection: string;
@@ -48,31 +61,34 @@ function iconForMimeType(mimeType: string): {
readonly alt: string;
readonly src: string;
} {
- if (mimeType === 'text/plain')
- return { alt: 'text', src: getIcon('text') ?? unknownIcon };
- if (mimeType === 'text/html')
- return { alt: 'html', src: getIcon('html') ?? unknownIcon };
-
- const parts = mimeType.split('/');
- const type = parts[0];
- const subtype = parts[1];
-
- if (['audio', 'video', 'image', 'text'].includes(type))
- return { alt: type, src: getIcon(type) ?? unknownIcon };
-
- if (type === 'application') {
- const iconName = {
- pdf: 'pdf',
- 'vnd.ms-excel': 'MSExcel',
- 'vnd.ms-word': 'MSWord',
- 'vnd.ms-powerpoint': 'MSPowerPoint',
- }[subtype];
-
- if (typeof iconName === 'string')
- return { alt: iconName, src: getIcon(iconName) ?? unknownIcon };
- }
+ const iconMap: Record = {
+ 'application/json': { alt: 'json', src: applicationJsonIcon },
+ 'application/pdf': { alt: 'pdf', src: applicationPdfIcon },
+ 'audio/x-generic': { alt: 'audio', src: audioXGenericIcon },
+ 'image/x-generic': { alt: 'image', src: imageXGenericIcon },
+ 'model': { alt: 'model', src: modelIcon },
+ 'text/html': { alt: 'html', src: textHtmlIcon },
+ 'text/xml': { alt: 'html', src: textHtmlIcon },
+ 'text/plain': { alt: 'text', src: textXGenericIcon },
+ 'text/x-makefile': { alt: 'makefile', src: textXMakefileIcon },
+ 'application/x-yaml': { alt: 'yaml', src: textXMakefileIcon },
+ 'video/x-generic': { alt: 'video', src: videoXGenericIcon },
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': { alt: 'MSWord', src: xOfficeDocumentIcon },
+ 'application/vnd.openxmlformats-officedocument.presentationml.presentation': { alt: 'MSPowerPoint', src: xOfficePresentationIcon },
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': { alt: 'MSExcel', src: xOfficeSpreadsheetIcon },
+ 'application/zip': { alt: 'zip', src: packageXgeneric },
+ };
- return { alt: commonText.unknown(), src: getIcon('unknown') ?? unknownIcon };
+ return (
+ iconMap[mimeType]
+ ?? (mimeType.startsWith('video/') ? { alt: 'video', src: videoXGenericIcon } : null)
+ ?? (mimeType.startsWith('audio/') ? { alt: 'audio', src: audioXGenericIcon } : null)
+ ?? (mimeType.startsWith('image/') ? { alt: 'image', src: imageXGenericIcon } : null)
+ ?? (mimeType.endsWith('presentation') || mimeType.includes('powerpoint') ? { alt: 'presentation', src: xOfficePresentationIcon } : null)
+ ?? (mimeType.includes('wordprocessing') || mimeType.endsWith('word') ? { alt: 'document', src: xOfficeDocumentIcon } : null)
+ ?? (mimeType == null ? { alt: 'image', src: textXGenericIcon } : null)
+ ?? { alt: commonText.unknown(), src: textXGenericIcon }
+ );
}
export const fetchAssetToken = async (
@@ -108,7 +124,7 @@ export async function fetchThumbnail(
: iconForMimeType(mimeType);
// Display an icon for resources that don't have a custom thumbnail
- if (typeof thumbnail === 'object' && thumbnail?.src !== unknownIcon)
+ if (typeof thumbnail === 'object')
return {
...thumbnail,
width: scale,
diff --git a/specifyweb/frontend/js_src/lib/components/Preferences/UserDefinitions.tsx b/specifyweb/frontend/js_src/lib/components/Preferences/UserDefinitions.tsx
index 044bbd9fc25..78e891d0dff 100644
--- a/specifyweb/frontend/js_src/lib/components/Preferences/UserDefinitions.tsx
+++ b/specifyweb/frontend/js_src/lib/components/Preferences/UserDefinitions.tsx
@@ -65,9 +65,10 @@ const isDarkMode = ({
}: PreferencesVisibilityContext): boolean => isDarkMode || isRedirecting;
// Navigator may not be defined in some environments, like non-browser environments
-const altKeyName = typeof navigator !== 'undefined' && navigator?.userAgent?.includes('Mac')
- ? 'Option'
- : 'Alt';
+const altKeyName =
+ typeof navigator !== 'undefined' && navigator?.userAgent?.includes('Mac')
+ ? 'Option'
+ : 'Alt';
/**
* Have to be careful as preferences may be used before schema is loaded
diff --git a/specifyweb/frontend/js_src/lib/components/RouterCommands/SwitchCollection.tsx b/specifyweb/frontend/js_src/lib/components/RouterCommands/SwitchCollection.tsx
index aeb54a2407e..ef201ec09d8 100644
--- a/specifyweb/frontend/js_src/lib/components/RouterCommands/SwitchCollection.tsx
+++ b/specifyweb/frontend/js_src/lib/components/RouterCommands/SwitchCollection.tsx
@@ -42,8 +42,8 @@ export function SwitchCollectionCommand(): null {
body: collectionId!.toString(),
errorMode: 'dismissible',
})
- .then(clearAllCache)
- .then(() => globalThis.location.replace(nextUrl)),
+ .then(clearAllCache)
+ .then(() => globalThis.location.replace(nextUrl)),
[collectionId, nextUrl]
),
true