diff --git a/app.vue b/app.vue index 7309924..40f7e2a 100644 --- a/app.vue +++ b/app.vue @@ -1,25 +1,28 @@ \ No newline at end of file + diff --git a/pages/index.vue b/pages/index.vue index c902e9b..50a57c3 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -65,10 +65,17 @@ YouTube Thumbnail -
- Image +
+ Image
{{ selectedItem?.content || "" }} @@ -135,9 +146,7 @@

{{ row.label }}

- + {{ row.value }}
@@ -158,7 +167,15 @@ import { listen } from "@tauri-apps/api/event"; import { useNuxtApp } from "#app"; import { invoke } from "@tauri-apps/api/core"; import { HistoryItem, ContentType } from "~/types/types"; -import type { InfoText, InfoImage, InfoFile, InfoLink, InfoColor, InfoCode } from "~/types/types"; +import type { + InfoText, + InfoImage, + InfoFile, + InfoLink, + InfoColor, + InfoCode, +} from "~/types/types"; +import { Key } from "wrdu-keyboard/key"; interface GroupedHistory { label: string; @@ -188,8 +205,8 @@ const imageSizes = shallowRef>({}); const lastUpdateTime = ref(Date.now()); const imageLoadError = ref(false); const imageLoading = ref(false); -const pageTitle = ref(''); -const pageOgImage = ref(''); +const pageTitle = ref(""); +const pageOgImage = ref(""); const keyboard = useKeyboard(); @@ -583,41 +600,35 @@ const setupEventListeners = async (): Promise => { searchInput.value?.blur(); }); - keyboard.down("ArrowDown", (event) => { - event.preventDefault(); + keyboard.prevent.down([Key.DownArrow], (event) => { selectNext(); }); - keyboard.down("ArrowUp", (event) => { - event.preventDefault(); + keyboard.prevent.down([Key.UpArrow], (event) => { selectPrevious(); }); - keyboard.down("Enter", (event) => { - event.preventDefault(); + keyboard.prevent.down([Key.Enter], (event) => { pasteSelectedItem(); }); - keyboard.down("Escape", (event) => { - event.preventDefault(); + keyboard.prevent.down([Key.Escape], (event) => { hideApp(); }); - keyboard.down("all", (event) => { - const isMacActionCombo = - os.value === "macos" && - (event.code === "MetaLeft" || event.code === "MetaRight") && - event.key === "k"; + switch (os.value) { + case "macos": + keyboard.prevent.down([Key.LeftMeta, Key.K], (event) => {}); - const isOtherOsActionCombo = - os.value !== "macos" && - (event.code === "ControlLeft" || event.code === "ControlRight") && - event.key === "k"; + keyboard.prevent.down([Key.RightMeta, Key.K], (event) => {}); + break; - if (isMacActionCombo || isOtherOsActionCombo) { - event.preventDefault(); - } - }); + case "linux" || "windows": + keyboard.prevent.down([Key.LeftControl, Key.K], (event) => {}); + + keyboard.prevent.down([Key.RightControl, Key.K], (event) => {}); + break; + } }; const hideApp = async (): Promise => { @@ -646,7 +657,7 @@ watch(searchQuery, () => { onMounted(async () => { try { - os.value = await platform(); + os.value = platform(); await loadHistoryChunk(); resultsContainer.value @@ -686,27 +697,33 @@ const formatFileSize = (bytes: number): string => { const fetchPageMeta = async (url: string) => { try { - const [title, ogImage] = await invoke('fetch_page_meta', { url }) as [string, string | null]; + const [title, ogImage] = (await invoke("fetch_page_meta", { url })) as [ + string, + string | null + ]; pageTitle.value = title; if (ogImage) { pageOgImage.value = ogImage; } } catch (error) { - console.error('Error fetching page meta:', error); - pageTitle.value = 'Error loading title'; + console.error("Error fetching page meta:", error); + pageTitle.value = "Error loading title"; } }; -watch(() => selectedItem.value, (newItem) => { - if (newItem?.content_type === ContentType.Link) { - pageTitle.value = 'Loading...'; - pageOgImage.value = ''; - fetchPageMeta(newItem.content); - } else { - pageTitle.value = ''; - pageOgImage.value = ''; +watch( + () => selectedItem.value, + (newItem) => { + if (newItem?.content_type === ContentType.Link) { + pageTitle.value = "Loading..."; + pageOgImage.value = ""; + fetchPageMeta(newItem.content); + } else { + pageTitle.value = ""; + pageOgImage.value = ""; + } } -}); +); const getInfo = computed(() => { if (!selectedItem.value) return null; @@ -716,7 +733,10 @@ const getInfo = computed(() => { copied: selectedItem.value.timestamp, }; - const infoMap: Record InfoText | InfoImage | InfoFile | InfoLink | InfoColor | InfoCode> = { + const infoMap: Record< + ContentType, + () => InfoText | InfoImage | InfoFile | InfoLink | InfoColor | InfoCode + > = { [ContentType.Text]: () => ({ ...baseInfo, content_type: ContentType.Text, @@ -747,20 +767,21 @@ const getInfo = computed(() => { const r = parseInt(hex.slice(1, 3), 16); const g = parseInt(hex.slice(3, 5), 16); const b = parseInt(hex.slice(5, 7), 16); - + const rNorm = r / 255; const gNorm = g / 255; const bNorm = b / 255; - + const max = Math.max(rNorm, gNorm, bNorm); const min = Math.min(rNorm, gNorm, bNorm); - let h = 0, s = 0; + let h = 0, + s = 0; const l = (max + min) / 2; if (max !== min) { const d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - + switch (max) { case rNorm: h = (gNorm - bNorm) / d + (gNorm < bNorm ? 6 : 0); @@ -780,14 +801,16 @@ const getInfo = computed(() => { content_type: ContentType.Color, hex: hex, rgb: `rgb(${r}, ${g}, ${b})`, - hsl: `hsl(${Math.round(h * 360)}, ${Math.round(s * 100)}%, ${Math.round(l * 100)}%)`, + hsl: `hsl(${Math.round(h * 360)}, ${Math.round(s * 100)}%, ${Math.round( + l * 100 + )}%)`, }; }, [ContentType.Code]: () => ({ ...baseInfo, content_type: ContentType.Code, language: selectedItem.value!.language ?? "Unknown", - lines: selectedItem.value!.content.split('\n').length, + lines: selectedItem.value!.content.split("\n").length, }), }; @@ -799,24 +822,37 @@ const infoRows = computed(() => { const commonRows = [ { label: "Source", value: getInfo.value.source, isUrl: false }, - { label: "Content Type", value: getInfo.value.content_type.charAt(0).toUpperCase() + getInfo.value.content_type.slice(1), isUrl: false }, + { + label: "Content Type", + value: + getInfo.value.content_type.charAt(0).toUpperCase() + + getInfo.value.content_type.slice(1), + isUrl: false, + }, ]; - const typeSpecificRows: Record> = { + const typeSpecificRows: Record< + ContentType, + Array<{ label: string; value: string | number; isUrl?: boolean }> + > = { [ContentType.Text]: [ { label: "Characters", value: (getInfo.value as InfoText).characters }, { label: "Words", value: (getInfo.value as InfoText).words }, ], [ContentType.Image]: [ { label: "Dimensions", value: (getInfo.value as InfoImage).dimensions }, - { label: "Image size", value: formatFileSize((getInfo.value as InfoImage).size) }, + { + label: "Image size", + value: formatFileSize((getInfo.value as InfoImage).size), + }, ], [ContentType.File]: [ { label: "Path", value: (getInfo.value as InfoFile).path }, ], [ContentType.Link]: [ - ...((getInfo.value as InfoLink).title && (getInfo.value as InfoLink).title !== 'Loading...' - ? [{ label: "Title", value: (getInfo.value as InfoLink).title || '' }] + ...((getInfo.value as InfoLink).title && + (getInfo.value as InfoLink).title !== "Loading..." + ? [{ label: "Title", value: (getInfo.value as InfoLink).title || "" }] : []), { label: "URL", value: (getInfo.value as InfoLink).url, isUrl: true }, { label: "Characters", value: (getInfo.value as InfoLink).characters }, @@ -832,8 +868,9 @@ const infoRows = computed(() => { ], }; - const specificRows = typeSpecificRows[getInfo.value.content_type] - .filter(row => row.value !== ""); + const specificRows = typeSpecificRows[getInfo.value.content_type].filter( + (row) => row.value !== "" + ); return [ ...commonRows, diff --git a/patches/wrdu-keyboard@3.0.0.patch b/patches/wrdu-keyboard@3.0.0.patch new file mode 100644 index 0000000..e973647 --- /dev/null +++ b/patches/wrdu-keyboard@3.0.0.patch @@ -0,0 +1,123 @@ +diff --git a/node_modules/wrdu-keyboard/.DS_Store b/.DS_Store +new file mode 100644 +index 0000000000000000000000000000000000000000..fabbd951c2d14c46fd10fa167b8836d116bc0db6 +Binary files /dev/null and b/.DS_Store differ +diff --git a/dist/runtime/keyboard.d.ts b/dist/runtime/keyboard.d.ts +index aeae40f3d2bc3efd459cce04c29c21c43884154d..6131bab4895ebb3048a5225f366430d23c5f1f13 100644 +--- a/dist/runtime/keyboard.d.ts ++++ b/dist/runtime/keyboard.d.ts +@@ -1,15 +1,16 @@ +-import { Key } from './types/keys.js'; +-import { type Plugin } from '#app'; ++import { Key } from "./types/keys.js"; ++import { type Plugin } from "#app"; + type Handler = (event: KeyboardEvent) => void; + type Config = { + once?: boolean; + prevent?: boolean; + }; +-type PublicConfig = Omit; ++type PublicConfig = Omit; + type New = (keys: Key[], handler: Handler, config?: PublicConfig) => void; + export interface Keyboard { + init: () => void; + stop: () => void; ++ unregisterAll: () => void; + down: New; + up: New; + prevent: { +diff --git a/dist/runtime/keyboard.js b/dist/runtime/keyboard.js +index e16f600258cee90d185ffc52777bed95c14bd93e..e4ce2678db649ec82e5a67fcdb74f5cdb37820aa 100644 +--- a/dist/runtime/keyboard.js ++++ b/dist/runtime/keyboard.js +@@ -1,13 +1,14 @@ + import { Key } from "./types/keys.js"; + import { defineNuxtPlugin } from "#app"; +-const getKeyString = (keys) => keys[0] == Key.All ? keys.sort().join("+") : "All"; ++const getKeyString = (keys) => keys.includes(Key.All) ? "All" : keys.sort().join("+"); + const handlers = { + down: {}, + up: {} + }; + const pressedKeys = /* @__PURE__ */ new Set(); + const onKeydown = (event) => { +- pressedKeys.add(event.code); ++ const key = event.code; ++ pressedKeys.add(key); + const pressedArray = Array.from(pressedKeys); + const keyString = getKeyString(pressedArray); + if (handlers.down[keyString]) { +@@ -17,13 +18,16 @@ const onKeydown = (event) => { + } + eventHandler.handler(event); + if (eventHandler.once) { +- handlers.down[keyString] = handlers.down[keyString].filter((h) => h !== eventHandler); ++ handlers.down[keyString] = handlers.down[keyString].filter( ++ (h) => h !== eventHandler ++ ); + } + }); + } + }; + const onKeyup = (event) => { +- pressedKeys.delete(event.code); ++ const key = event.code; ++ pressedKeys.delete(key); + const releasedArray = Array.from(pressedKeys); + const keyString = getKeyString(releasedArray); + if (handlers.up[keyString]) { +@@ -33,13 +37,16 @@ const onKeyup = (event) => { + } + eventHandler.handler(event); + if (eventHandler.once) { +- handlers.up[keyString] = handlers.up[keyString].filter((h) => h !== eventHandler); ++ handlers.up[keyString] = handlers.up[keyString].filter( ++ (h) => h !== eventHandler ++ ); + } + }); + } + }; + const init = () => { + stop(); ++ pressedKeys.clear(); + window.addEventListener("keydown", onKeydown); + window.addEventListener("keyup", onKeyup); + }; +@@ -47,6 +54,20 @@ const stop = () => { + window.removeEventListener("keydown", onKeydown); + window.removeEventListener("keyup", onKeyup); + }; ++const unregisterAll = () => { ++ Object.keys(handlers.down).forEach((key) => { ++ handlers.down[key].forEach((handler) => { ++ console.log(`Unregistering ${key} ${handler.handler.toString()}`); ++ }); ++ }); ++ Object.keys(handlers.up).forEach((key) => { ++ handlers.up[key].forEach((handler) => { ++ console.log(`Unregistering ${key} ${handler.handler.toString()}`); ++ }); ++ }); ++ handlers.down = {}; ++ handlers.up = {}; ++}; + const down = (keys, handler, config = {}) => { + if (keys.includes(Key.All)) { + keys = [Key.All]; +@@ -59,6 +80,7 @@ const down = (keys, handler, config = {}) => { + handlers.down[key] = []; + } + const { once = false, prevent = false } = config; ++ console.log(key, handler.toString()); + handlers.down[key].push({ handler, prevent, once }); + }; + const up = (keys, handler, config = {}) => { +@@ -84,6 +106,7 @@ const keyboard = defineNuxtPlugin((nuxtApp) => { + keyboard: { + init, + stop, ++ unregisterAll, + down: (keys, handler, config = {}) => down(keys, handler, config), + up: (keys, handler, config = {}) => up(keys, handler, config), + prevent: {