From 33aa1fb2ff4db6f0ac528b21ff50dc76ae1be2d4 Mon Sep 17 00:00:00 2001 From: Zhang Minghan Date: Tue, 30 Jul 2024 12:29:40 +0800 Subject: [PATCH] feat: save file and bump version --- package.json | 2 +- src/lib/env.ts | 2 +- src/lib/utils.ts | 29 +++++++++++++++++++++++++++++ src/pages/[query].tsx | 16 ++++++++++++++++ 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b971503..f37a305 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "next-whois-ui", - "version": "0.0.2", + "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", diff --git a/src/lib/env.ts b/src/lib/env.ts index 49a8d05..37c8b6a 100644 --- a/src/lib/env.ts +++ b/src/lib/env.ts @@ -1,4 +1,4 @@ -export const VERSION = "0.0.2"; +export const VERSION = "0.1.0"; export const HISTORY_LIMIT: number = intEnv("NEXT_PUBLIC_HISTORY_LIMIT", 6); // The maximum number of history items to keep in the local storage diff --git a/src/lib/utils.ts b/src/lib/utils.ts index a0ad127..4b6919a 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -12,6 +12,22 @@ export function isEnter(e: React.KeyboardEvent) { return e.key === "Enter" && e.keyCode !== 229; } +export function saveAsFile(filename: string, content: string) { + /** + * Save text as file + * @param filename Filename + * @param content File content + * @example + * saveAsFile("hello.txt", "Hello world!"); + * @see https://developer.mozilla.org/en-US/docs/Web/API/Blob + */ + + const a = document.createElement("a"); + a.href = URL.createObjectURL(new Blob([content])); + a.download = filename; + a.click(); +} + async function copyClipboard(text: string) { if (navigator.clipboard && navigator.clipboard.writeText) { return await navigator.clipboard.writeText(text); @@ -51,6 +67,19 @@ export function useClipboard() { }; } +export function useSaver() { + return (filename: string, content: string) => { + try { + saveAsFile(filename, content); + toast("Saved!"); + } catch (e) { + console.error(e); + + toast(`Failed to save: ${toErrorMessage(e)}`); + } + }; +} + export function toSearchURI(query: string) { const q = query.trim(); return q ? `/${encodeURIComponent(q)}` : "/"; diff --git a/src/pages/[query].tsx b/src/pages/[query].tsx index 86199dc..4f40020 100644 --- a/src/pages/[query].tsx +++ b/src/pages/[query].tsx @@ -5,6 +5,7 @@ import { toReadableISODate, toSearchURI, useClipboard, + useSaver, } from "@/lib/utils"; import { NextPageContext } from "next"; import { Input } from "@/components/ui/input"; @@ -14,6 +15,7 @@ import { CircleX, CopyIcon, CornerDownRight, + DownloadIcon, ExternalLink, Link2, Loader2, @@ -379,6 +381,7 @@ function ResultTable({ result, target }: ResultTableProps) { function ResultComp({ data, target }: Props) { const copy = useClipboard(); + const save = useSaver(); const { status, result, error, time } = data; return ( @@ -416,10 +419,23 @@ function ResultComp({ data, target }: Props) { +