diff --git a/package.json b/package.json index 8287d33e..ed5e058c 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "fflate": "^0.8.0", "gpt-3-encoder": "^1.1.4", "gpt3-tokenizer": "^1.1.5", + "html-to-image": "^1.11.11", "isomorphic-dompurify": "^1.2.0", "localforage": "^1.10.0", "lodash": "^4.17.21", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index abc99609..4428e9c8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,6 +53,9 @@ dependencies: gpt3-tokenizer: specifier: ^1.1.5 version: 1.1.5 + html-to-image: + specifier: ^1.11.11 + version: 1.11.11 isomorphic-dompurify: specifier: ^1.2.0 version: 1.2.0 @@ -1655,6 +1658,10 @@ packages: whatwg-encoding: 2.0.0 dev: false + /html-to-image@1.11.11: + resolution: {integrity: sha512-9gux8QhvjRO/erSnDPv28noDZcPZmYE7e1vFsBLKLlRlKDSqNJYebj6Qz1TGd5lsRV+X+xYyjCKjuZdABinWjA==} + dev: false + /http-errors@2.0.0: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} engines: {node: '>= 0.8'} diff --git a/src/lang/en.ts b/src/lang/en.ts index 10ff1000..93402978 100644 --- a/src/lang/en.ts +++ b/src/lang/en.ts @@ -346,5 +346,7 @@ export const languageEnglish = { createBotInternetAlert: "Please provide the character's name and the corresponding series/game.", able:"Able", assetWidth: "Asset Images Max Width", - animationSpeed: "Animation Speed" + animationSpeed: "Animation Speed", + screenshot: "Screenshot", + screenshotSaved: "Screenshot Saved", } \ No newline at end of file diff --git a/src/lib/ChatScreens/Chat.svelte b/src/lib/ChatScreens/Chat.svelte index cf7fbbbf..046e951b 100644 --- a/src/lib/ChatScreens/Chat.svelte +++ b/src/lib/ChatScreens/Chat.svelte @@ -76,7 +76,7 @@ $: displaya(message) -
+
{#await img}
import Suggestion from './Suggestion.svelte'; - import { DatabaseIcon, DicesIcon, LanguagesIcon, Laugh, MenuIcon, MicOffIcon, RefreshCcwIcon, ReplyIcon, Send } from "lucide-svelte"; + import { CameraIcon, DatabaseIcon, DicesIcon, LanguagesIcon, Laugh, MenuIcon, MicOffIcon, RefreshCcwIcon, ReplyIcon, Send } from "lucide-svelte"; import { selectedCharID } from "../../ts/stores"; import Chat from "./Chat.svelte"; import { DataBase, type Message, type character, type groupChat } from "../../ts/storage/database"; @@ -9,7 +9,7 @@ import { findCharacterbyId, messageForm, sleep } from "../../ts/util"; import { language } from "../../lang"; import { translate } from "../../ts/translator/translator"; - import { alertError } from "../../ts/alert"; + import { alertError, alertNormal, alertWait } from "../../ts/alert"; import sendSound from '../../etc/send.mp3' import {cloneDeep} from 'lodash' import { processScript } from "src/ts/process/scripts"; @@ -18,6 +18,7 @@ import MainMenu from '../UI/MainMenu.svelte'; import Help from '../Others/Help.svelte'; import AssetInput from './AssetInput.svelte'; + import { downloadFile } from 'src/ts/storage/globalApi'; let messageInput:string = '' let messageInputTranslate:string = '' @@ -222,6 +223,59 @@ }) } + async function screenShot(){ + try { + loadPages = Infinity + const html2canvas = await import('html-to-image'); + const chats = document.querySelectorAll('.default-chat-screen .risu-chat') + alertWait("Taking screenShot...") + let canvases:HTMLCanvasElement[] = [] + + for(const chat of chats){ + const cnv = await html2canvas.toCanvas(chat as HTMLElement) + canvases.push(cnv) + } + + canvases.reverse() + + let mergedCanvas = document.createElement('canvas'); + mergedCanvas.width = 0; + mergedCanvas.height = 0; + let mergedCtx = mergedCanvas.getContext('2d'); + + let totalHeight = 0; + let maxWidth = 0; + for(let i = 0; i < canvases.length; i++) { + let canvas = canvases[i]; + totalHeight += canvas.height; + maxWidth = Math.max(maxWidth, canvas.width); + + mergedCanvas.width = maxWidth; + mergedCanvas.height = totalHeight; + } + + mergedCtx.fillStyle = '#282a36' + mergedCtx.fillRect(0, 0, maxWidth, totalHeight); + let indh = 0 + for(let i = 0; i < canvases.length; i++) { + let canvas = canvases[i]; + indh += canvas.height + mergedCtx.drawImage(canvas, 0, indh - canvas.height); + canvases[i].remove(); + } + + if(mergedCanvas){ + await downloadFile("chat.png", Buffer.from(mergedCanvas.toDataURL('png').split(',').at(-1), 'base64')) + mergedCanvas.remove(); + } + alertNormal(language.screenshotSaved) + loadPages = 30 + } catch (error) { + console.error(error) + alertError("Error while taking screenshot") + } + } + $: { currentCharacter = $DataBase.characters[$selectedCharID] } @@ -233,7 +287,7 @@ {#if $selectedCharID < 0} {:else} -
{ +
{ //@ts-ignore const scrolled = (e.target.scrollHeight - e.target.clientHeight + e.target.scrollTop) if(scrolled < 100 && $DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].message.length > loadPages){ @@ -469,7 +523,17 @@ {/if} {/if} - + + {#if $DataBase.useExperimental} +
{ + screenShot() + }}> + + {language.screenshot} +
+ {/if} + +
{ $DataBase.useAutoSuggestions = !$DataBase.useAutoSuggestions }}>