From 42e8421ab4320b095fa650df29877cd4e7d1956a Mon Sep 17 00:00:00 2001 From: arkohut <39525455+arkohut@users.noreply.github.com> Date: Wed, 16 Oct 2024 00:22:31 +0800 Subject: [PATCH] feat(web): ui update --- web/src/lib/Figure.svelte | 104 ++++++++++++++--------- web/src/lib/components/Logo.svelte | 58 ++++++++++++- web/src/lib/components/LucideIcon.svelte | 6 ++ web/src/lib/utils.ts | 30 ++++++- web/src/routes/+page.svelte | 38 ++++++--- web/static/favicon.png | Bin 1571 -> 18932 bytes 6 files changed, 184 insertions(+), 52 deletions(-) create mode 100644 web/src/lib/components/LucideIcon.svelte diff --git a/web/src/lib/Figure.svelte b/web/src/lib/Figure.svelte index b3c229b..f7e262d 100644 --- a/web/src/lib/Figure.svelte +++ b/web/src/lib/Figure.svelte @@ -4,7 +4,9 @@ import CopyToClipboard from "$lib/components/CopyToClipboard.svelte" import OCRTable from './OCRTable.svelte'; import { marked } from 'marked'; - import { ChevronLeft, ChevronRight, X } from 'lucide-svelte'; + import { ChevronLeft, ChevronRight, X, Hash, Library, Folder, FileClock } from 'lucide-svelte'; + import { appIconMap } from '$lib/utils'; + import LucideIcon from '$lib/components/LucideIcon.svelte'; /** * @type {string} @@ -38,6 +40,7 @@ * @type {string} */ export let title; + export let app_name; /** * @type {Array} */ @@ -47,6 +50,16 @@ * @type {Array<{key: string, source: string, value: any}>} */ export let metadata_entries = []; + + // Remove items with key "timestamp" or "sequence" and sort metadata_entries, placing "ocr_result" at the end + $: sortedMetadataEntries = [...metadata_entries] + .filter(entry => entry.key !== "timestamp" && entry.key !== "sequence" && entry.key !== "active_app" && entry.key !== "active_window") + .sort((a, b) => { + if (a.key === "ocr_result") return 1; + if (b.key === "ocr_result") return -1; + return 0; + }); + /** * @type {any} */ @@ -111,55 +124,68 @@
-
- - {title} - -
- - +
+
+
+ +

{title}

+
+
- ID - {id} - - Library ID - - {library_id} - - Folder ID - - {folder_id} - - DATETIME - - {new Date(created_at).toLocaleString()} + + + {library_id} + + + + + {folder_id} + + + + + {id} + + + + + {new Date(created_at).toLocaleString()} + +
{filepath}
-
Image Title
-

- {title} -

-
TAGS
-
- {#each tags as tag} - {tag} - {/each} + +
+ + + + {#if tags.length > 0} +
+
TAGS
+
+ {#each tags as tag} + {tag} + {/each} +
+
+ {/if}
METADATA
- {#each metadata_entries as entry} + {#each sortedMetadataEntries as entry}
{entry.key} @@ -195,4 +221,4 @@
-
\ No newline at end of file +
diff --git a/web/src/lib/components/Logo.svelte b/web/src/lib/components/Logo.svelte index 31cece2..578f461 100644 --- a/web/src/lib/components/Logo.svelte +++ b/web/src/lib/components/Logo.svelte @@ -8,7 +8,61 @@ export let class_ = ''; export let withBorder = true; - function prepareMatrixFromRandomColors(withBorder: boolean): string[][] { + function prepareMatrixFromFixedIndexAndLittleRadom(withBorder: boolean): string[][] { + const bgColors = ['#f2f2f2', '#e9e9e9', '#d8d8d8'] + // const colors = ['#d0e8ff', '#F2295F', '#E0A0F2', '#F2B705']; + const colors = ['#d0e8ff', '#BF244E', '#8C2685', '#21A650']; + const mShape = withBorder + ? [ + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0], + [0, 1, 1, 1, 0, 0, 0, 0, 0, 3, 3, 3, 0], + [0, 1, 1, 1, 2, 0, 0, 0, 2, 3, 3, 3, 0], + [0, 1, 1, 1, 2, 2, 0, 2, 2, 3, 3, 3, 0], + [0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 0], + [0, 1, 1, 1, 0, 2, 2, 2, 0, 3, 3, 3, 0], + [0, 1, 1, 1, 0, 0, 0, 0, 0, 3, 3, 3, 0], + [0, 1, 1, 1, 0, 0, 0, 0, 0, 3, 3, 3, 0], + [0, 1, 1, 1, 0, 0, 0, 0, 0, 3, 3, 3, 0], + [0, 1, 1, 1, 0, 0, 0, 0, 0, 3, 3, 3, 0], + [0, 1, 1, 1, 0, 0, 0, 0, 0, 3, 3, 3, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + ] + : [ + [1, 1, 0, 0, 0, 0, 0, 0, 0, 3, 3], + [1, 1, 1, 0, 0, 0, 0, 0, 3, 3, 3], + [1, 1, 1, 2, 0, 0, 0, 2, 3, 3, 3], + [1, 1, 1, 2, 2, 0, 2, 2, 3, 3, 3], + [1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3], + [1, 1, 1, 0, 2, 2, 2, 0, 3, 3, 3], + [1, 1, 1, 0, 0, 0, 0, 0, 3, 3, 3], + [1, 1, 1, 0, 0, 0, 0, 0, 3, 3, 3], + [1, 1, 1, 0, 0, 0, 0, 0, 3, 3, 3], + [1, 1, 1, 0, 0, 0, 0, 0, 3, 3, 3], + [1, 1, 1, 0, 0, 0, 0, 0, 3, 3, 3] + ]; + + const gridSize = withBorder ? 13 : 11; + let seed = 42; + const matrix: string[][] = []; + + for (let row = 0; row < gridSize; row++) { + const rowColors: string[] = []; + const bgSize = bgColors.length; + for (let col = 0; col < gridSize; col++) { + if (mShape[row][col] === 0) { + rowColors.push(bgColors[Math.floor(seededRandom(seed++) * bgSize)]); + } else { + rowColors.push(colors[mShape[row][col]]); + } + } + matrix.push(rowColors); + } + + return matrix; + } + + function prepareMatrixFromRandomColors(withBorder: boolean): string[][] { const colors = ['#d0e8ff', '#a1d2ff', '#64b5f6', '#1565c0', '#0d47a1']; const mShape = withBorder ? [ @@ -83,7 +137,7 @@ } function generateMemosLogo(size: number, withBorder: boolean): string { - const matrix = prepareMatrixFromRandomColors(withBorder); + const matrix = prepareMatrixFromFixedIndexAndLittleRadom(withBorder); return generateSvg(matrix, size); } diff --git a/web/src/lib/components/LucideIcon.svelte b/web/src/lib/components/LucideIcon.svelte new file mode 100644 index 0000000..1b4e468 --- /dev/null +++ b/web/src/lib/components/LucideIcon.svelte @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/web/src/lib/utils.ts b/web/src/lib/utils.ts index 8871245..153466f 100644 --- a/web/src/lib/utils.ts +++ b/web/src/lib/utils.ts @@ -59,4 +59,32 @@ export const flyAndScale = ( }, easing: cubicOut }; -}; \ No newline at end of file +}; + +export const appIconMap: Record = { + "Cursor": "Code", + "Google Chrome": "Chrome", + "IINA": "Youtube", + "微信": "MessageSquareCode", + "预览": "Eye", + "iTerm2": "SquareTerminal", + "企业微信": "MessageSquareCode", + "IntelliJ IDEA": "Code", + "Microsoft Edge": "Globe", + "腾讯会议": "MessagesSquare", + "访达": "Folder", + "邮件": "Mail", + "备忘录": "NotebookTabs", + "日历": "CalendarFold", + "UserNotificationCenter": "Bell", + "Electron": "Atom", + "Firefox": "Globe", + "Safari浏览器": "Compass", + "熊掌记": "NotebookTabs", + "Alacritty": "SquareTerminal", + "系统设置": "Settings", + "股市": "CircleDollarSign", + "活动监视器": "Activity", + "Brave Browser": "Globe", + "Code": "Code", +}; diff --git a/web/src/routes/+page.svelte b/web/src/routes/+page.svelte index b196076..e2964c6 100644 --- a/web/src/routes/+page.svelte +++ b/web/src/routes/+page.svelte @@ -8,6 +8,8 @@ import { formatDistanceToNow } from 'date-fns'; import Logo from '$lib/components/Logo.svelte'; import { onMount } from 'svelte'; + import { appIconMap } from '$lib/utils'; + import LucideIcon from '$lib/components/LucideIcon.svelte'; let searchString = ''; /** @@ -255,6 +257,24 @@ ); } } + + // Add this function near the top of the @@ -330,11 +350,7 @@ >

- {hit.document.metadata_entries && - hit.document.metadata_entries.some((entry) => entry.key === 'active_window') - ? hit.document.metadata_entries.find((entry) => entry.key === 'active_window') - .value - : filename(hit.document.filepath)} + {getEntityTitle(hit.document)}

{formatDistanceToNow(new Date(hit.document.file_created_at * 1000), { @@ -348,11 +364,12 @@ src={`${apiEndpoint}/files/${hit.document.filepath}`} alt="" /> - {#if hit.document.metadata_entries && hit.document.metadata_entries.some((entry) => entry.key === 'active_app')} + {#if getAppName(hit.document)}

- {hit.document.metadata_entries.find((entry) => entry.key === 'active_app').value} + + {getAppName(hit.document)}
{/if} @@ -376,7 +393,8 @@ video={`${apiEndpoint}/files/video/${searchResult.hits[selectedImage].document.filepath}`} created_at={searchResult.hits[selectedImage].document.file_created_at * 1000} filepath={searchResult.hits[selectedImage].document.filepath} - title={filename(searchResult.hits[selectedImage].document.filepath)} + title={getEntityTitle(searchResult.hits[selectedImage].document)} + app_name={getAppName(searchResult.hits[selectedImage].document)} tags={searchResult.hits[selectedImage].document.tags} metadata_entries={searchResult.hits[selectedImage].document.metadata_entries} onClose={closeModal} @@ -396,4 +414,4 @@ Changelog
- \ No newline at end of file + diff --git a/web/static/favicon.png b/web/static/favicon.png index 825b9e65af7c104cfb07089bb28659393b4f2097..b3c9ebd81907e678d2c97222bcf6805f603d0dc0 100644 GIT binary patch literal 18932 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ἪR;EVn{rx~q* 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