/// /// /// /// import { scrapbox } from "jsr:@cosense/types@0.10/userscript"; import { getImages, type Image } from "jsr:@takker/gyazo@0.4"; import type { React } from "./react-event.ts"; export type { Image, React }; export interface AddGyazoMenuInit { /** Gyazo Access token */ accessToken: string; /** Max is `100` * Note that free users cannot get more than 10 images. * * @default {10} */ maxCount?: number; onClick?: (image: Image, event: React.MouseEvent) => void; } interface UnsafeWindow { GM_fetch?: (typeof globalThis.fetch); } const id = "Gyazo Viewer"; export const addGyazoMenu = (init: AddGyazoMenuInit):void => { let job: Promise = Promise.resolve(); const GM_fetch = (globalThis as unknown as UnsafeWindow).GM_fetch; scrapbox.PageMenu.addMenu({ title: !GM_fetch ? "Open Gyazo" : id, icon: "kamon kamon-gyazo", onClick: !GM_fetch ? ()=> globalThis.open("https://gyazo.com/captures") : () => { job = job.then( () => loadImages({ per: init.maxCount ?? 10, accessToken: init.accessToken, fetch: GM_fetch, onClick: init.onClick, }) ); }, }); }; interface LoadImagesInit { per: number; accessToken: string; fetch?: typeof fetch; onClick?: (image: Image, event: React.MouseEvent) => void; } const loadImages = async (init: LoadImagesInit): Promise => { let timer: number | undefined; try { const promise = getImages({ page: 0, ...init }); // 読み込みに時間がかかるようであれば、読み込み中の表示を出す timer = setTimeout(() => { scrapbox.PageMenu(id).addItem({ title: "Loading...", icon: "fas fa-spinner", onClick: () => {}, }) }, 100); const res = await promise; if (!res.ok) throw new Error(`${res.status} ${res.statusText}`); const images = await res.json(); clearTimeout(timer); scrapbox.PageMenu(id).removeAllItems(); for (const image of images) { if (!image.image_id) continue; scrapbox.PageMenu(id).addItem({ title: image.metadata?.title || "Untitled", image: image.url, onClick: (event) => init.onClick?.(image, event) ?? navigator ?.clipboard ?.writeText?.(image.permalink_url) ?.catch?.((e) => { alert(`${e}`); console.error(e); }), }); } } catch(e) { clearTimeout(timer); scrapbox.PageMenu(id).removeAllItems(); scrapbox.PageMenu(id).addItem({ title: "Failed to load the image list.", icon: "fas fa-exclamation-triangle", onClick: () => {}, }); console.error("Failed to load the image list", e); } };