diff --git a/src/lang/en.ts b/src/lang/en.ts index 0b3f54ec..3e2178d0 100644 --- a/src/lang/en.ts +++ b/src/lang/en.ts @@ -19,7 +19,8 @@ export const languageEnglish = { httpError: 'Error: error in request:', noData: 'There is no data in file, or the file is corrupted', onlyOneChat: 'There must be least one chat', - alreadyCharInGroup: "There is already a character with the same name in the group." + alreadyCharInGroup: "There is already a character with the same name in the group.", + noUserIcon: "You must set your icon first.", }, showHelp: "Show Help", help:{ @@ -421,4 +422,8 @@ export const languageEnglish = { translatorType: "Translator Type", deeplKey: "deepL API Key", deeplFreeKey: "deepL Free API Key", + exportPersona: "Export Persona", + importPersona: "Import Persona", + export: "Export", + import: "Import", } \ No newline at end of file diff --git a/src/lib/Setting/Pages/PersonaSettings.svelte b/src/lib/Setting/Pages/PersonaSettings.svelte index 8ee99460..9a557f0a 100644 --- a/src/lib/Setting/Pages/PersonaSettings.svelte +++ b/src/lib/Setting/Pages/PersonaSettings.svelte @@ -1,12 +1,14 @@

{language.persona}

@@ -29,7 +31,11 @@ {/each}
{ + onClick={async () => { + const sel = parseInt(await alertSelect([language.createfromScratch, language.importCharacter])) + if(sel === 1){ + return + } let db = get(DataBase) db.personas.push({ name: 'New Persona', @@ -57,8 +63,8 @@
-
-
+
+
-
+
{language.name} {language.description} is a 20 year old girl.]`} /> -
- + + + + }}>{language.remove}
\ No newline at end of file diff --git a/src/lib/Setting/Pages/UserSettings.svelte b/src/lib/Setting/Pages/UserSettings.svelte index 55b42db5..ec8da89a 100644 --- a/src/lib/Setting/Pages/UserSettings.svelte +++ b/src/lib/Setting/Pages/UserSettings.svelte @@ -1,14 +1,13 @@ \ No newline at end of file diff --git a/src/ts/characters.ts b/src/ts/characters.ts index 9a0cac2c..573116df 100644 --- a/src/ts/characters.ts +++ b/src/ts/characters.ts @@ -77,46 +77,6 @@ export async function selectCharImg(charId:number) { setDatabase(db) } -export async function selectUserImg() { - const selected = await selectSingleFile(['png']) - if(!selected){ - return - } - const img = selected.data - let db = get(DataBase) - const imgp = await saveImage(img) - db.userIcon = imgp - db.personas[db.selectedPersona] = { - name: db.username, - icon: db.userIcon, - personaPrompt: db.personaPrompt - } - setDatabase(db) -} - -export function saveUserPersona() { - let db = get(DataBase) - db.personas[db.selectedPersona] = { - name: db.username, - icon: db.userIcon, - personaPrompt: db.personaPrompt - } - setDatabase(db) -} - -export function changeUserPersona(id:number, save:'save'|'noSave' = 'save') { - if(save === 'save'){ - saveUserPersona() - } - let db = get(DataBase) - const pr = db.personas[id] - db.personaPrompt = pr.personaPrompt - db.username = pr.name, - db.userIcon = pr.icon - db.selectedPersona = id - setDatabase(db) - -} export const addingEmotion = writable(false) diff --git a/src/ts/persona.ts b/src/ts/persona.ts new file mode 100644 index 00000000..2d49bfa1 --- /dev/null +++ b/src/ts/persona.ts @@ -0,0 +1,118 @@ +import { get } from "svelte/store" +import { DataBase, saveImage, setDatabase } from "./storage/database" +import { selectSingleFile, sleep } from "./util" +import { alertError, alertNormal, alertStore } from "./alert" +import * as yuso from 'yuso' +import { downloadFile, readImage } from "./storage/globalApi" +import { language } from "src/lang" +import { cloneDeep } from "lodash" + +export async function selectUserImg() { + const selected = await selectSingleFile(['png']) + if(!selected){ + return + } + const img = selected.data + let db = get(DataBase) + const imgp = await saveImage(img) + db.userIcon = imgp + db.personas[db.selectedPersona] = { + name: db.username, + icon: db.userIcon, + personaPrompt: db.personaPrompt + } + setDatabase(db) +} + +export function saveUserPersona() { + let db = get(DataBase) + db.personas[db.selectedPersona] = { + name: db.username, + icon: db.userIcon, + personaPrompt: db.personaPrompt + } + setDatabase(db) +} + +export function changeUserPersona(id:number, save:'save'|'noSave' = 'save') { + if(save === 'save'){ + saveUserPersona() + } + let db = get(DataBase) + const pr = db.personas[id] + db.personaPrompt = pr.personaPrompt + db.username = pr.name, + db.userIcon = pr.icon + db.selectedPersona = id + setDatabase(db) +} + + + +interface PersonaCard { + name: string + personaPrompt: string +} + +export async function exportUserPersona(){ + let db = get(DataBase) + if(!db.userIcon){ + alertError(language.errors.noUserIcon) + return + } + if((!db.username) || (!db.personaPrompt)){ + alertError("username or persona prompt is empty") + return + } + + + let img = await readImage(db.userIcon) + + let card:PersonaCard = cloneDeep({ + name: db.username, + personaPrompt: db.personaPrompt, + }) + + alertStore.set({ + type: 'wait', + msg: 'Loading... (Writing Exif)' + }) + + await sleep(10) + + img = yuso.encode(yuso.trim(img), "persona",Buffer.from(JSON.stringify(card)).toString('base64')) + + alertStore.set({ + type: 'wait', + msg: 'Loading... (Writing)' + }) + + await sleep(10) + await downloadFile(`${db.username.replace(/[<>:"/\\|?*\.\,]/g, "")}_export.png`, img) + + alertNormal(language.successExport) +} + +export async function importUserPersona(){ + + try { + const v = await selectSingleFile(['png']) + const data:PersonaCard = JSON.parse(Buffer.from(yuso.decode(v.data, "persona"), 'base64').toString('utf-8')) + if(data.name && data.personaPrompt){ + let db = get(DataBase) + db.personas.push({ + name: data.name, + icon: await saveImage(yuso.trim(v.data)), + personaPrompt: data.personaPrompt + }) + setDatabase(db) + alertNormal(language.successImport) + }else{ + alertError(language.errors.noData) + } + + } catch (error) { + alertError(`${error}`) + return + } +} \ No newline at end of file diff --git a/vite.config.ts.timestamp-1692264018459-ef682a6846638.mjs b/vite.config.ts.timestamp-1692264018459-ef682a6846638.mjs new file mode 100644 index 00000000..1de89fa4 --- /dev/null +++ b/vite.config.ts.timestamp-1692264018459-ef682a6846638.mjs @@ -0,0 +1,70 @@ +// vite.config.ts +import { defineConfig } from "file:///C:/Users/blueb/OneDrive/Documents/VSC/_Risu/kakuna/RisuAI/node_modules/.pnpm/vite@4.4.5_@types+node@18.16.19/node_modules/vite/dist/node/index.js"; +import { svelte } from "file:///C:/Users/blueb/OneDrive/Documents/VSC/_Risu/kakuna/RisuAI/node_modules/.pnpm/@sveltejs+vite-plugin-svelte@2.4.2_svelte@4.1.0_vite@4.4.5/node_modules/@sveltejs/vite-plugin-svelte/src/index.js"; +import sveltePreprocess from "file:///C:/Users/blueb/OneDrive/Documents/VSC/_Risu/kakuna/RisuAI/node_modules/.pnpm/svelte-preprocess@5.0.4_postcss@8.4.26_svelte@4.1.0_typescript@5.1.6/node_modules/svelte-preprocess/dist/index.js"; +import wasm from "file:///C:/Users/blueb/OneDrive/Documents/VSC/_Risu/kakuna/RisuAI/node_modules/.pnpm/vite-plugin-wasm@3.2.2_vite@4.4.5/node_modules/vite-plugin-wasm/exports/import.mjs"; +import { internalIpV4 } from "file:///C:/Users/blueb/OneDrive/Documents/VSC/_Risu/kakuna/RisuAI/node_modules/.pnpm/internal-ip@7.0.0/node_modules/internal-ip/index.js"; +import topLevelAwait from "file:///C:/Users/blueb/OneDrive/Documents/VSC/_Risu/kakuna/RisuAI/node_modules/.pnpm/vite-plugin-top-level-await@1.3.1_rollup@3.26.3_vite@4.4.5/node_modules/vite-plugin-top-level-await/exports/import.mjs"; +var vite_config_default = defineConfig(async () => { + const host = await internalIpV4(); + return { + plugins: [ + svelte({ + preprocess: [ + sveltePreprocess({ + typescript: true + }) + ], + onwarn: (warning, handler) => { + if (warning.code.startsWith("a11y-")) + return; + handler(warning); + } + }), + wasm(), + topLevelAwait() + ], + // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build` + // prevent vite from obscuring rust errors + clearScreen: false, + // tauri expects a fixed port, fail if that port is not available + server: { + host: "0.0.0.0", + // listen on all addresses + port: 5174, + strictPort: true, + hmr: { + protocol: "ws", + host, + port: 5184 + } + }, + // to make use of `TAURI_DEBUG` and other env variables + // https://tauri.studio/v1/api/config#buildconfig.beforedevcommand + envPrefix: ["VITE_", "TAURI_"], + build: { + // Tauri supports es2021 + target: "es2021", + // don't minify for debug builds + minify: process.env.TAURI_DEBUG ? false : "esbuild", + // produce sourcemaps for debug builds + sourcemap: !!process.env.TAURI_DEBUG, + chunkSizeWarningLimit: 2e3 + }, + optimizeDeps: { + needsInterop: [ + "@mlc-ai/web-tokenizers" + ] + }, + resolve: { + alias: { + "src": "/src", + "modules": "/modules" + } + } + }; +}); +export { + vite_config_default as default +}; +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJDOlxcXFxVc2Vyc1xcXFxibHVlYlxcXFxPbmVEcml2ZVxcXFxEb2N1bWVudHNcXFxcVlNDXFxcXF9SaXN1XFxcXGtha3VuYVxcXFxSaXN1QUlcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIkM6XFxcXFVzZXJzXFxcXGJsdWViXFxcXE9uZURyaXZlXFxcXERvY3VtZW50c1xcXFxWU0NcXFxcX1Jpc3VcXFxca2FrdW5hXFxcXFJpc3VBSVxcXFx2aXRlLmNvbmZpZy50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vQzovVXNlcnMvYmx1ZWIvT25lRHJpdmUvRG9jdW1lbnRzL1ZTQy9fUmlzdS9rYWt1bmEvUmlzdUFJL3ZpdGUuY29uZmlnLnRzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSBcInZpdGVcIjtcclxuaW1wb3J0IHsgc3ZlbHRlIH0gZnJvbSBcIkBzdmVsdGVqcy92aXRlLXBsdWdpbi1zdmVsdGVcIjtcclxuaW1wb3J0IHN2ZWx0ZVByZXByb2Nlc3MgZnJvbSBcInN2ZWx0ZS1wcmVwcm9jZXNzXCI7XHJcbmltcG9ydCB3YXNtIGZyb20gXCJ2aXRlLXBsdWdpbi13YXNtXCI7XHJcbmltcG9ydCB7IGludGVybmFsSXBWNCB9IGZyb20gJ2ludGVybmFsLWlwJ1xyXG5pbXBvcnQgdG9wTGV2ZWxBd2FpdCBmcm9tIFwidml0ZS1wbHVnaW4tdG9wLWxldmVsLWF3YWl0XCI7XHJcblxyXG4vLyBodHRwczovL3ZpdGVqcy5kZXYvY29uZmlnL1xyXG5leHBvcnQgZGVmYXVsdCBkZWZpbmVDb25maWcoYXN5bmMgKCkgPT4ge1xyXG4gIFxyXG4gIGNvbnN0IGhvc3QgPSBhd2FpdCBpbnRlcm5hbElwVjQoKVxyXG5cclxuICByZXR1cm4ge1xyXG4gICAgcGx1Z2luczogW1xyXG4gICAgICBcclxuICAgICAgc3ZlbHRlKHtcclxuICAgICAgICBwcmVwcm9jZXNzOiBbXHJcbiAgICAgICAgICBzdmVsdGVQcmVwcm9jZXNzKHtcclxuICAgICAgICAgICAgdHlwZXNjcmlwdDogdHJ1ZSxcclxuICAgICAgICAgIH0pLFxyXG4gICAgICAgIF0sXHJcbiAgICAgICAgb253YXJuOiAod2FybmluZywgaGFuZGxlcikgPT4ge1xyXG4gICAgICAgICAgLy8gZGlzYWJsZSBhMTF5IHdhcm5pbmdzXHJcbiAgICAgICAgICBpZiAod2FybmluZy5jb2RlLnN0YXJ0c1dpdGgoXCJhMTF5LVwiKSkgcmV0dXJuO1xyXG4gICAgICAgICAgaGFuZGxlcih3YXJuaW5nKTtcclxuICAgICAgICB9LFxyXG4gICAgICB9KSxcclxuICAgICAgd2FzbSgpLFxyXG4gICAgICB0b3BMZXZlbEF3YWl0KCksXHJcbiAgICBdLFxyXG5cclxuICAgIC8vIFZpdGUgb3B0aW9ucyB0YWlsb3JlZCBmb3IgVGF1cmkgZGV2ZWxvcG1lbnQgYW5kIG9ubHkgYXBwbGllZCBpbiBgdGF1cmkgZGV2YCBvciBgdGF1cmkgYnVpbGRgXHJcbiAgICAvLyBwcmV2ZW50IHZpdGUgZnJvbSBvYnNjdXJpbmcgcnVzdCBlcnJvcnNcclxuICAgIGNsZWFyU2NyZWVuOiBmYWxzZSxcclxuICAgIC8vIHRhdXJpIGV4cGVjdHMgYSBmaXhlZCBwb3J0LCBmYWlsIGlmIHRoYXQgcG9ydCBpcyBub3QgYXZhaWxhYmxlXHJcbiAgICBzZXJ2ZXI6IHtcclxuICAgICAgaG9zdDogJzAuMC4wLjAnLCAvLyBsaXN0ZW4gb24gYWxsIGFkZHJlc3Nlc1xyXG4gICAgICBwb3J0OiA1MTc0LFxyXG4gICAgICBzdHJpY3RQb3J0OiB0cnVlLFxyXG4gICAgICBobXI6IHtcclxuICAgICAgICBwcm90b2NvbDogJ3dzJyxcclxuICAgICAgICBob3N0LFxyXG4gICAgICAgIHBvcnQ6IDUxODQsXHJcbiAgICAgIH0sXHJcbiAgICB9LFxyXG4gICAgLy8gdG8gbWFrZSB1c2Ugb2YgYFRBVVJJX0RFQlVHYCBhbmQgb3RoZXIgZW52IHZhcmlhYmxlc1xyXG4gICAgLy8gaHR0cHM6Ly90YXVyaS5zdHVkaW8vdjEvYXBpL2NvbmZpZyNidWlsZGNvbmZpZy5iZWZvcmVkZXZjb21tYW5kXHJcbiAgICBlbnZQcmVmaXg6IFtcIlZJVEVfXCIsIFwiVEFVUklfXCJdLFxyXG4gICAgYnVpbGQ6IHtcclxuICAgICAgLy8gVGF1cmkgc3VwcG9ydHMgZXMyMDIxXHJcbiAgICAgIHRhcmdldDpcImVzMjAyMVwiLFxyXG4gICAgICAvLyBkb24ndCBtaW5pZnkgZm9yIGRlYnVnIGJ1aWxkc1xyXG4gICAgICBtaW5pZnk6IHByb2Nlc3MuZW52LlRBVVJJX0RFQlVHID8gZmFsc2UgOiAnZXNidWlsZCcsXHJcbiAgICAgIC8vIHByb2R1Y2Ugc291cmNlbWFwcyBmb3IgZGVidWcgYnVpbGRzXHJcbiAgICAgIHNvdXJjZW1hcDogISFwcm9jZXNzLmVudi5UQVVSSV9ERUJVRyxcclxuICAgICAgY2h1bmtTaXplV2FybmluZ0xpbWl0OiAyMDAwXHJcbiAgICB9LFxyXG4gICAgXHJcbiAgICBvcHRpbWl6ZURlcHM6e1xyXG4gICAgICBuZWVkc0ludGVyb3A6W1xyXG4gICAgICAgIFwiQG1sYy1haS93ZWItdG9rZW5pemVyc1wiXHJcbiAgICAgIF1cclxuICAgIH0sXHJcblxyXG4gICAgcmVzb2x2ZTp7XHJcbiAgICAgIGFsaWFzOntcclxuICAgICAgICAnc3JjJzonL3NyYycsXHJcbiAgICAgICAgJ21vZHVsZXMnOiAnL21vZHVsZXMnXHJcbiAgICAgIH1cclxuICAgIH1cclxufX0pO1xyXG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQStXLFNBQVMsb0JBQW9CO0FBQzVZLFNBQVMsY0FBYztBQUN2QixPQUFPLHNCQUFzQjtBQUM3QixPQUFPLFVBQVU7QUFDakIsU0FBUyxvQkFBb0I7QUFDN0IsT0FBTyxtQkFBbUI7QUFHMUIsSUFBTyxzQkFBUSxhQUFhLFlBQVk7QUFFdEMsUUFBTSxPQUFPLE1BQU0sYUFBYTtBQUVoQyxTQUFPO0FBQUEsSUFDTCxTQUFTO0FBQUEsTUFFUCxPQUFPO0FBQUEsUUFDTCxZQUFZO0FBQUEsVUFDVixpQkFBaUI7QUFBQSxZQUNmLFlBQVk7QUFBQSxVQUNkLENBQUM7QUFBQSxRQUNIO0FBQUEsUUFDQSxRQUFRLENBQUMsU0FBUyxZQUFZO0FBRTVCLGNBQUksUUFBUSxLQUFLLFdBQVcsT0FBTztBQUFHO0FBQ3RDLGtCQUFRLE9BQU87QUFBQSxRQUNqQjtBQUFBLE1BQ0YsQ0FBQztBQUFBLE1BQ0QsS0FBSztBQUFBLE1BQ0wsY0FBYztBQUFBLElBQ2hCO0FBQUE7QUFBQTtBQUFBLElBSUEsYUFBYTtBQUFBO0FBQUEsSUFFYixRQUFRO0FBQUEsTUFDTixNQUFNO0FBQUE7QUFBQSxNQUNOLE1BQU07QUFBQSxNQUNOLFlBQVk7QUFBQSxNQUNaLEtBQUs7QUFBQSxRQUNILFVBQVU7QUFBQSxRQUNWO0FBQUEsUUFDQSxNQUFNO0FBQUEsTUFDUjtBQUFBLElBQ0Y7QUFBQTtBQUFBO0FBQUEsSUFHQSxXQUFXLENBQUMsU0FBUyxRQUFRO0FBQUEsSUFDN0IsT0FBTztBQUFBO0FBQUEsTUFFTCxRQUFPO0FBQUE7QUFBQSxNQUVQLFFBQVEsUUFBUSxJQUFJLGNBQWMsUUFBUTtBQUFBO0FBQUEsTUFFMUMsV0FBVyxDQUFDLENBQUMsUUFBUSxJQUFJO0FBQUEsTUFDekIsdUJBQXVCO0FBQUEsSUFDekI7QUFBQSxJQUVBLGNBQWE7QUFBQSxNQUNYLGNBQWE7QUFBQSxRQUNYO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFBQSxJQUVBLFNBQVE7QUFBQSxNQUNOLE9BQU07QUFBQSxRQUNKLE9BQU07QUFBQSxRQUNOLFdBQVc7QUFBQSxNQUNiO0FBQUEsSUFDRjtBQUFBLEVBQ0o7QUFBQyxDQUFDOyIsCiAgIm5hbWVzIjogW10KfQo=