From c4e14fad8d5a1e93993a8349d6337bdaa3b1ba50 Mon Sep 17 00:00:00 2001 From: Linho Date: Sat, 26 Apr 2025 22:51:36 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E5=8A=A8=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/editor/import.vue | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/editor/import.vue b/src/editor/import.vue index b84ea63..aadf466 100644 --- a/src/editor/import.vue +++ b/src/editor/import.vue @@ -60,10 +60,13 @@ function handleImport() { try { const parsed = JSON5.parse(importStr.value); if (typeof parsed !== "object" || parsed === null) throw null; - if(typeof parsed.data !== "object" || !Array.isArray(parsed.data)) throw null; - profile.data = toInternalDatum( + if (typeof parsed.data !== "object" || !Array.isArray(parsed.data)) + throw null; + const newData = toInternalDatum( (JSON5.parse(importStr.value).data as FunctionPlotDatum[]) ?? [] ); + profile.data = []; + profile.data = newData; Snackbar.builder({ text: t("title.importSuccess"), type: "success", From cf4d0f6a7f20d9c81665bb3c5081dd770d8befb7 Mon Sep 17 00:00:00 2001 From: Linho Date: Sat, 26 Apr 2025 23:01:57 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E8=B0=83=E6=95=B4=E6=96=87=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/i18n.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n.ts b/src/i18n.ts index a637f0f..e9aa627 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -24,7 +24,7 @@ export default { undo: "撤销", }, graphType: { - interval: "默认", + interval: "微矩形", polyline: "多段线", scatter: "散点", text: "文本", From 9900a5e7d1f86199e0168eaaa55359bce072cfeb Mon Sep 17 00:00:00 2001 From: Linho Date: Sat, 26 Apr 2025 23:21:54 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=86=99=E5=85=A5=20URL?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/editor/import.vue | 29 +++++++++++++++-------------- src/editor/output.vue | 11 ++++++++++- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/editor/import.vue b/src/editor/import.vue index aadf466..db4256d 100644 --- a/src/editor/import.vue +++ b/src/editor/import.vue @@ -33,25 +33,26 @@ import SIconImport from "@/ui/icons/import.vue"; import { useProfile } from "@/consts"; const profile = useProfile(); -import { onMounted, ref } from "vue"; +import { ref } from "vue"; import JSON5 from "json5"; import base64 from "base-64"; import utf8 from "utf8"; import type { FunctionPlotDatum } from "function-plot"; import { toInternalDatum } from "@/consts"; -onMounted(() => { - const rawCode = window.location.search.match(/\?code=(.+)$/)?.[1]; - if (rawCode) - try { - const code = utf8.decode(base64.decode(decodeURIComponent(rawCode))); - const data = toInternalDatum( - (JSON5.parse(code).data as FunctionPlotDatum[]) ?? [] - ); - profile.data = toInternalDatum(data); - console.log(code); - console.log(data); - } catch (e) {} -}); + +const rawCode = window?.location.search.match(/\?code=(.+)$/)?.[1]; +if (rawCode) + try { + const code = utf8.decode(base64.decode(decodeURIComponent(rawCode))); + const data = toInternalDatum( + (JSON5.parse(code).data as FunctionPlotDatum[]) ?? [] + ); + profile.data = toInternalDatum(data); + console.log(code); + console.log(data); + } catch (e) { + if (e instanceof Error) console.error(e); + } const importStr = ref(""); import { Snackbar } from "sober"; diff --git a/src/editor/output.vue b/src/editor/output.vue index ce0841d..6157e64 100644 --- a/src/editor/output.vue +++ b/src/editor/output.vue @@ -32,6 +32,9 @@ const { t } = useI18n(); import SIconCopy from "@/ui/icons/copy.vue"; import JSON5 from "json5"; +import base64 from "base-64"; +import utf8 from "utf8"; + import prettier from "prettier/standalone"; import prettierPluginBabel from "prettier/plugins/babel"; import prettierPluginEstree from "prettier/plugins/estree"; @@ -43,8 +46,14 @@ const formatted = ref(""); watch( profile, () => { + const code = JSON5.stringify({ data: profile.getOriginalCopy(true) }); + const url = + window.location.href.match(/https?:\/\/[^/]+\//) + + "?code=" + + encodeURIComponent(base64.encode(utf8.encode(code)).replace(/=+$/, "")); + window.history.replaceState(null, "", url); prettier - .format(JSON5.stringify({ data: profile.getOriginalCopy(true) }), { + .format(code, { parser: "json5", printWidth: 40, plugins: [prettierPluginBabel, prettierPluginEstree], From 5f9960186e51370ed892bff45c04a8f9c02484b3 Mon Sep 17 00:00:00 2001 From: Linho Date: Sat, 26 Apr 2025 23:55:12 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E7=8A=B6=E6=80=81=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E7=8B=AC=E7=AB=8B=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.vue | 2 +- src/consts.ts | 31 -------------------------- src/editor/datum.vue | 2 +- src/editor/datumList.vue | 2 +- src/editor/import.vue | 18 +-------------- src/editor/output.vue | 2 +- src/graph/index.vue | 2 +- src/states.ts | 47 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 53 insertions(+), 53 deletions(-) create mode 100644 src/states.ts diff --git a/src/App.vue b/src/App.vue index 9a5f72b..3504b31 100644 --- a/src/App.vue +++ b/src/App.vue @@ -24,7 +24,7 @@ import Graph from "./graph/index.vue"; import Editor from "./editor/index.vue"; import { computed, ref, watch, watchEffect } from "vue"; -import { useTheme } from "@/consts"; +import { useTheme } from "@/states"; const theme = useTheme(); const soberPage = ref(); watchEffect(() => diff --git a/src/consts.ts b/src/consts.ts index 15f4561..f31878f 100644 --- a/src/consts.ts +++ b/src/consts.ts @@ -392,34 +392,3 @@ export const fnTypeArr = [ }, ] as const satisfies FnType[]; -// Datum define -import { defineStore } from "pinia"; -import { computed, ref } from "vue"; -export const useProfile = defineStore("profile", () => { - const data = ref([ - { fnType: "linear", graphType: "polyline", fn: "x^2", key: 1 }, - ]); - const getOriginalCopy = (forExport?: boolean) => - toOriginalDatum(data.value, forExport); - return { data, getOriginalCopy }; -}); - -// Theme define -export const useTheme = defineStore("theme", () => { - const themeValues = ["auto", "dark", "light"] as const; - const initialIndex = (() => { - if (typeof localStorage !== "undefined") { - const savedTheme = Number(localStorage.getItem("theme")); - if ([0, 1, 2].includes(savedTheme)) return savedTheme as 0 | 1 | 2; - } - return 0; - })(); - const index = ref(initialIndex); - const initialValue = themeValues[initialIndex]; - const value = computed(() => themeValues[index.value]); - const toogle = () => { - index.value = ((index.value + 1) % themeValues.length) as 0 | 1 | 2; - localStorage.setItem("theme", index.value.toString()); - }; - return { initialIndex,initialValue, index, value, toogle }; -}); diff --git a/src/editor/datum.vue b/src/editor/datum.vue index bdb9e44..f494094 100644 --- a/src/editor/datum.vue +++ b/src/editor/datum.vue @@ -142,7 +142,7 @@ const blockFolded = ref(true); const foldShell = ref(); import { Snackbar } from "sober"; -import { useProfile } from "../consts"; +import { useProfile } from "@/states"; const profile = useProfile(); function deleteDatum() { const backup = cloneDeep(dataItem.value)!; diff --git a/src/editor/datumList.vue b/src/editor/datumList.vue index cc4071d..7efe928 100644 --- a/src/editor/datumList.vue +++ b/src/editor/datumList.vue @@ -34,7 +34,7 @@ import AnimatedListItem from "@/ui/animatedList/animatedListItem.vue"; import Datum from "./datum.vue"; import { getNewDatum } from "@/consts"; -import { useProfile } from "@/consts"; +import { useProfile } from "@/states"; const profile = useProfile(); diff --git a/src/editor/import.vue b/src/editor/import.vue index db4256d..346ef93 100644 --- a/src/editor/import.vue +++ b/src/editor/import.vue @@ -30,30 +30,14 @@ const { t } = useI18n(); import SIconImport from "@/ui/icons/import.vue"; -import { useProfile } from "@/consts"; +import { useProfile } from "@/states"; const profile = useProfile(); import { ref } from "vue"; import JSON5 from "json5"; -import base64 from "base-64"; -import utf8 from "utf8"; import type { FunctionPlotDatum } from "function-plot"; import { toInternalDatum } from "@/consts"; -const rawCode = window?.location.search.match(/\?code=(.+)$/)?.[1]; -if (rawCode) - try { - const code = utf8.decode(base64.decode(decodeURIComponent(rawCode))); - const data = toInternalDatum( - (JSON5.parse(code).data as FunctionPlotDatum[]) ?? [] - ); - profile.data = toInternalDatum(data); - console.log(code); - console.log(data); - } catch (e) { - if (e instanceof Error) console.error(e); - } - const importStr = ref(""); import { Snackbar } from "sober"; function handleImport() { diff --git a/src/editor/output.vue b/src/editor/output.vue index 6157e64..5cbdc99 100644 --- a/src/editor/output.vue +++ b/src/editor/output.vue @@ -39,7 +39,7 @@ import prettier from "prettier/standalone"; import prettierPluginBabel from "prettier/plugins/babel"; import prettierPluginEstree from "prettier/plugins/estree"; import { ref, watch } from "vue"; -import { useProfile } from "@/consts"; +import { useProfile } from "@/states"; const profile = useProfile(); const formatted = ref(""); diff --git a/src/graph/index.vue b/src/graph/index.vue index 001340a..4a86174 100644 --- a/src/graph/index.vue +++ b/src/graph/index.vue @@ -14,7 +14,7 @@ import Graph from "./graph.vue"; import { computed, onMounted, ref } from "vue"; import { throttle } from "lodash-es"; -import { useProfile } from "@/consts"; +import { useProfile } from "@/states"; const graphWidth = ref(0), graphHeight = ref(0); diff --git a/src/states.ts b/src/states.ts new file mode 100644 index 0000000..1903990 --- /dev/null +++ b/src/states.ts @@ -0,0 +1,47 @@ +import JSON5 from "json5"; +import base64 from "base-64"; +import utf8 from "utf8"; +import { defineStore } from "pinia"; +import { computed, ref } from "vue"; +import { InternalDatum, toInternalDatum, toOriginalDatum } from "./consts"; +import { FunctionPlotDatum } from "function-plot"; + +// Datum define +export const useProfile = defineStore("profile", () => { + const data = ref( + (() => { + const rawCode = window?.location.search.match(/\?code=(.+)$/)?.[1]; + if (rawCode) + try { + const code = utf8.decode(base64.decode(decodeURIComponent(rawCode))); + const data = toInternalDatum( + (JSON5.parse(code).data as FunctionPlotDatum[]) ?? [] + ); + return toInternalDatum(data); + } catch (e) {} + })() ?? [{ fnType: "linear", graphType: "polyline", fn: "x^2", key: 1 }] + ); + const getOriginalCopy = (forExport?: boolean) => + toOriginalDatum(data.value, forExport); + return { data, getOriginalCopy }; +}); + +// Theme define +export const useTheme = defineStore("theme", () => { + const themeValues = ["auto", "dark", "light"] as const; + const initialIndex = (() => { + if (typeof localStorage !== "undefined") { + const savedTheme = Number(localStorage.getItem("theme")); + if ([0, 1, 2].includes(savedTheme)) return savedTheme as 0 | 1 | 2; + } + return 0; + })(); + const index = ref(initialIndex); + const initialValue = themeValues[initialIndex]; + const value = computed(() => themeValues[index.value]); + const toogle = () => { + index.value = ((index.value + 1) % themeValues.length) as 0 | 1 | 2; + localStorage.setItem("theme", index.value.toString()); + }; + return { initialIndex, initialValue, index, value, toogle }; +}); From 70f28608e8e4a6c9eb9be85da5b03dad2d707cca Mon Sep 17 00:00:00 2001 From: Linho Date: Sat, 26 Apr 2025 23:55:24 +0800 Subject: [PATCH 5/6] =?UTF-8?q?i18n=20=E5=88=9D=E5=A7=8B=E5=8C=96=E6=8F=90?= =?UTF-8?q?=E5=89=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/i18n.ts | 15 ++++++++++++++- src/ui/navbar.vue | 19 ++++++------------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/src/i18n.ts b/src/i18n.ts index e9aa627..9871056 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -1,9 +1,22 @@ import type { createI18n } from "vue-i18n"; type I18nOpt = Parameters[0]; +const locale = (() => { + if (localStorage) { + const localLocale = localStorage.getItem("lang"); + const langStr = localLocale ?? navigator.language; + if (langStr.startsWith("zh")) return "zh-CN"; + if (langStr.startsWith("en")) return "en-US"; + } + return "en-US"; +})(); + +if (localStorage && !localStorage.getItem("lang")) + localStorage.setItem("lang", locale); + export default { legacy: false, - locale: "zh-CN", + locale, messages: { "zh-CN": { buttons: { diff --git a/src/ui/navbar.vue b/src/ui/navbar.vue index a58a5f3..8117d24 100644 --- a/src/ui/navbar.vue +++ b/src/ui/navbar.vue @@ -46,33 +46,26 @@ From 057ee861a93944e9d851b7966a7beb62950fba63 Mon Sep 17 00:00:00 2001 From: Linho Date: Sun, 27 Apr 2025 00:37:18 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E6=9A=97=E8=89=B2=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E5=8A=A0=E8=BD=BD=E9=97=AA=E7=99=BD=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/public.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/public.css b/src/public.css index 1dcf8eb..e5c1c37 100644 --- a/src/public.css +++ b/src/public.css @@ -44,3 +44,9 @@ input[type="number"] { .monospace::part(input) { font-family: "Jetbrains Mono", monospace; } + +@media (prefers-color-scheme: dark) { + :root { + background-color: #111415; + } +}