diff --git a/src/lang/cn.ts b/src/lang/cn.ts
index dd14b6a5..658b44b8 100644
--- a/src/lang/cn.ts
+++ b/src/lang/cn.ts
@@ -304,6 +304,7 @@ export const languageChinese = {
tags: "标签",
copied: "已复制",
useChatCopy: "使用聊天复制",
+ useChatSticker: "使用聊天贴纸",
autoTranslateInput: "使用自动翻译输入",
enterMessageForTranslateToEnglish: "输入要翻译为英语的消息",
recent: '最新',
diff --git a/src/lang/en.ts b/src/lang/en.ts
index 51317e85..276d15eb 100644
--- a/src/lang/en.ts
+++ b/src/lang/en.ts
@@ -308,6 +308,7 @@ export const languageEnglish = {
backgroundHTML: "Background Embedding",
copied: "Copied",
useChatCopy: "Use Chat Message Copy",
+ useChatSticker: "Use Chat Sticker",
autoTranslateInput: "Auto Translate Input",
enterMessageForTranslateToEnglish: "Enter Message for Translate to English",
recent: 'Recent',
diff --git a/src/lang/ko.ts b/src/lang/ko.ts
index 266ff153..ae7e32da 100644
--- a/src/lang/ko.ts
+++ b/src/lang/ko.ts
@@ -280,6 +280,7 @@ export const languageKorean = {
backgroundHTML: "백그라운드 임베딩",
copied: "복사됨",
useChatCopy: "채팅 메시지 복사 사용",
+ useChatSticker: "채팅 스티커 사용",
autoTranslateInput: "입력 자동 번역",
enterMessageForTranslateToEnglish: "영어로 번역할 메시지를 입력해주세요",
imageCompression: "이미지 압축",
diff --git a/src/lib/ChatScreens/AssetInput.svelte b/src/lib/ChatScreens/AssetInput.svelte
new file mode 100644
index 00000000..0bf4d097
--- /dev/null
+++ b/src/lib/ChatScreens/AssetInput.svelte
@@ -0,0 +1,75 @@
+
+{#if currentCharacter.type ==='character'}
+
+ {#if currentCharacter.additionalAssets}
+ {#each currentCharacter.additionalAssets as additionalAsset, i}
+
+ {/each}
+ {/if}
+{/if}
\ No newline at end of file
diff --git a/src/lib/ChatScreens/Chat.svelte b/src/lib/ChatScreens/Chat.svelte
index fb6e37bc..be0bf967 100644
--- a/src/lib/ChatScreens/Chat.svelte
+++ b/src/lib/ChatScreens/Chat.svelte
@@ -8,6 +8,7 @@
import { selectedCharID } from "../../ts/stores";
import { translate } from "../../ts/translator/translator";
import { replacePlaceholders } from "../../ts/util";
+
export let message = ''
export let name = ''
export let isLastMemory:boolean
@@ -17,6 +18,7 @@
export let onReroll = () => {}
export let unReroll = () => {}
export let character:character|groupChat|null = null
+ let md:string
let translating = false
let editMode = false
let statusMessage:string = ''
@@ -24,7 +26,8 @@
let msgDisplay = ''
let msgTranslated = ''
- let translated = false;
+ let translated = false
+
async function rm(){
const rm = $DataBase.askRemoval ? await alertConfirm(language.removeChat) : true
if(rm){
@@ -53,7 +56,7 @@
$DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].message = msg
}
- async function displaya(message:string){
+ async function displaya(message:string, isStreaming:boolean = false){
if($DataBase.autoTranslate && $DataBase.translator !== ''){
if(msgTranslated==='')
msgDisplay = replacePlaceholders(message, name)
@@ -64,6 +67,12 @@
else{
msgDisplay = replacePlaceholders(message, name)
}
+
+ if(!md || !isStreaming || isStreaming && idx === $DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].message.length - 1) {
+ ParseMarkdown(msgDisplay, character, 'normal').then(mdNew=>{
+ md = mdNew
+ })
+ }
}
const setStatusMessage = (message:string, timeout:number = 0)=>{
@@ -74,7 +83,7 @@
}, timeout)
}
- $: displaya(message)
+ $: displaya(message, $DataBase.characters[$selectedCharID].chats[$DataBase.characters[$selectedCharID].chatPage].isStreaming)
@@ -161,19 +170,17 @@
{#if editMode}
- {:else}
- {#await ParseMarkdown(msgDisplay, character) then md}
-
-
{
- if($DataBase.clickToEdit && idx > -1){
- editMode = true
- msgTranslated = ""
- }
- }}
- style:font-size="{0.875 * ($DataBase.zoomsize / 100)}rem"
- style:line-height="{1.25 * ($DataBase.zoomsize / 100)}rem"
- >{@html md}
- {/await}
+ {:else if md}
+
+
{
+ if($DataBase.clickToEdit && idx > -1){
+ editMode = true
+ msgTranslated = ""
+ }
+ }}
+ style:font-size="{0.875 * ($DataBase.zoomsize / 100)}rem"
+ style:line-height="{1.25 * ($DataBase.zoomsize / 100)}rem"
+ >{@html md}
{/if}
diff --git a/src/lib/ChatScreens/DefaultChatScreen.svelte b/src/lib/ChatScreens/DefaultChatScreen.svelte
index 30db6bee..8a63394e 100644
--- a/src/lib/ChatScreens/DefaultChatScreen.svelte
+++ b/src/lib/ChatScreens/DefaultChatScreen.svelte
@@ -1,9 +1,9 @@
{
@@ -234,6 +241,12 @@
}
}}>
+ {#if $DataBase.useChatSticker && currentCharacter.type !== 'group'}
+
{toggleStickers = !toggleStickers}}
+ class={"ml-4 bg-gray-500 flex justify-center items-center w-12 h-12 rounded-md hover:bg-green-500 transition-colors "+(toggleStickers ? 'text-green-500':'text-white')}>
+
+
+ {/if}
+
+
+{#if $DataBase.useExperimental}
+
+
+
+
+{/if}
diff --git a/src/lib/SideBars/CharConfig.svelte b/src/lib/SideBars/CharConfig.svelte
index 8045ffb1..2574bd63 100644
--- a/src/lib/SideBars/CharConfig.svelte
+++ b/src/lib/SideBars/CharConfig.svelte
@@ -16,7 +16,7 @@
import RegexData from "./RegexData.svelte";
import { exportChar, shareRisuHub } from "src/ts/characterCards";
import { getElevenTTSVoices, getWebSpeechTTSVoices, getVOICEVOXVoices } from "src/ts/process/tts";
- import { checkCharOrder } from "src/ts/storage/globalApi";
+ import { checkCharOrder, getFileSrc } from "src/ts/storage/globalApi";
import { addGroupChar, rmCharFromGroup } from "src/ts/process/group";
import HubUpload from "../UI/HubUpload.svelte";
@@ -95,7 +95,9 @@
currentChar = currentChar
})
-
+ let assetFileExtensions:string[] = []
+ let assetFilePath:string[] = []
+
$: {
if(database.characters[$selectedCharID].chaId === currentChar.data.chaId){
database.characters[$selectedCharID] = currentChar.data
@@ -106,6 +108,20 @@
emos = currentChar.data.emotionImages
DataBase.set(database)
loadTokenize(currentChar.data)
+
+ if(currentChar.type ==='character'){
+ if(currentChar.data.additionalAssets){
+ for(let i = 0; i < currentChar.data.additionalAssets.length; i++){
+ if(currentChar.data.additionalAssets[i].length > 2 && currentChar.data.additionalAssets[i][2]) {
+ assetFileExtensions[i] = currentChar.data.additionalAssets[i][2]
+ } else
+ assetFileExtensions[i] = currentChar.data.additionalAssets[i][1].split('.').pop()
+ getFileSrc(currentChar.data.additionalAssets[i][1]).then((filePath) => {
+ assetFilePath[i] = filePath
+ })
+ }
+ }
+ }
}
onDestroy(unsub);
@@ -615,9 +631,10 @@
for(const f of da){
console.log(f)
const img = f.data
- const imgp = await saveAsset(img)
const name = f.name
- currentChar.data.additionalAssets.push([name, imgp])
+ const extension = name.split('.').pop().toLowerCase()
+ const imgp = await saveAsset(img,'', extension)
+ currentChar.data.additionalAssets.push([name, imgp, extension])
currentChar.data.additionalAssets = currentChar.data.additionalAssets
}
}
@@ -634,6 +651,16 @@
{#each currentChar.data.additionalAssets as assets, i}
+ {#if assetFilePath[i]}
+ {#if assetFileExtensions[i] === 'mp4'}
+
+
+ {:else if assetFileExtensions[i] === 'mp3'}
+
+ {:else}
+
+ {/if}
+ {/if}
|
diff --git a/src/ts/characterCards.ts b/src/ts/characterCards.ts
index cbf2ba4a..73c70457 100644
--- a/src/ts/characterCards.ts
+++ b/src/ts/characterCards.ts
@@ -329,7 +329,7 @@ async function importSpecv2(card:CharacterCardV2, img?:Uint8Array, mode?:'hub'|'
let customScripts:customscript[] = []
let utilityBot = false
let sdData = defaultSdDataFunc()
- let extAssets:[string,string][] = []
+ let extAssets:[string,string,string][] = []
if(risuext){
if(risuext.emotions){
@@ -350,8 +350,11 @@ async function importSpecv2(card:CharacterCardV2, img?:Uint8Array, mode?:'hub'|'
msg: `Loading... (Getting Assets ${i} / ${risuext.additionalAssets.length})`
})
await sleep(10)
- const imgp = await saveAsset(mode === 'hub' ? (await getHubResources(risuext.additionalAssets[i][1])) :Buffer.from(risuext.additionalAssets[i][1], 'base64'))
- extAssets.push([risuext.additionalAssets[i][0],imgp])
+ let fileName = ''
+ if(risuext.additionalAssets[i].length >= 3)
+ fileName = risuext.additionalAssets[i][2]
+ const imgp = await saveAsset(mode === 'hub' ? (await getHubResources(risuext.additionalAssets[i][1])) :Buffer.from(risuext.additionalAssets[i][1], 'base64'), '', fileName)
+ extAssets.push([risuext.additionalAssets[i][0],imgp,fileName])
}
}
bias = risuext.bias ?? bias
@@ -756,7 +759,7 @@ type CharacterCardV2 = {
customScripts?:customscript[]
utilityBot?: boolean,
sdData?:[string,string][],
- additionalAssets?:[string,string][],
+ additionalAssets?:[string,string,string][],
backgroundHTML?:string
}
}
diff --git a/src/ts/parser.ts b/src/ts/parser.ts
index d9a9a34c..21da61e0 100644
--- a/src/ts/parser.ts
+++ b/src/ts/parser.ts
@@ -64,9 +64,9 @@ export async function ParseMarkdown(data:string, char:(character | groupChat) =
for(const asset of char.additionalAssets){
const assetPath = await getFileSrc(asset[1])
data = data.replaceAll(`{{raw::${asset[0]}}}`, assetPath).
- replaceAll(`{{img::${asset[0]}}}`,` `)
- .replaceAll(`{{video::${asset[0]}}}`,``)
- .replaceAll(`{{audio::${asset[0]}}}`,``)
+ replaceAll(`{{img::${asset[0]}}}`,` `)
+ .replaceAll(`{{video::${asset[0]}}}`,``)
+ .replaceAll(`{{audio::${asset[0]}}}`,``)
if(mode === 'back'){
data = data.replaceAll(`{{bg::${asset[0]}}}`, ``)
}
diff --git a/src/ts/process/index.ts b/src/ts/process/index.ts
index 2f0fb543..83e483cd 100644
--- a/src/ts/process/index.ts
+++ b/src/ts/process/index.ts
@@ -404,6 +404,7 @@ export async function sendChat(chatProcessIndex = -1,arg:{chatAdditonalTokens?:n
else if(req.type === 'streaming'){
const reader = req.result.getReader()
const msgIndex = db.characters[selectedChar].chats[selectedChat].message.length
+ db.characters[selectedChar].chats[selectedChat].isStreaming = true
db.characters[selectedChar].chats[selectedChat].message.push({
role: 'char',
data: "",
@@ -419,6 +420,8 @@ export async function sendChat(chatProcessIndex = -1,arg:{chatAdditonalTokens?:n
setDatabase(db)
}
if(readed.done){
+ db.characters[selectedChar].chats[selectedChat].isStreaming = false
+ setDatabase(db)
break
}
}
diff --git a/src/ts/storage/database.ts b/src/ts/storage/database.ts
index 02eb3a76..80ef6849 100644
--- a/src/ts/storage/database.ts
+++ b/src/ts/storage/database.ts
@@ -339,7 +339,7 @@ export interface character{
VOLUME_SCALE?: number
}
supaMemory?:boolean
- additionalAssets?:[string, string][]
+ additionalAssets?:[string, string, string][]
ttsReadOnlyQuoted?:boolean
replaceGlobalNote:string
backgroundHTML?:string
@@ -522,7 +522,8 @@ export interface Database{
expires_in?: number
}
},
- classicMaxWidth: boolean
+ classicMaxWidth: boolean,
+ useChatSticker:boolean,
}
interface hordeConfig{
@@ -561,6 +562,7 @@ export interface Chat{
supaMemoryData?:string
lastMemory?:string
suggestMessages?:string[]
+ isStreaming?:boolean
}
export interface Message{
diff --git a/src/ts/storage/globalApi.ts b/src/ts/storage/globalApi.ts
index eaf307d6..56384835 100644
--- a/src/ts/storage/globalApi.ts
+++ b/src/ts/storage/globalApi.ts
@@ -170,7 +170,7 @@ export async function readImage(data:string) {
}
}
-export async function saveAsset(data:Uint8Array, customId:string = ''){
+export async function saveAsset(data:Uint8Array, customId:string = '', fileName:string = ''){
let id = ''
if(customId !== ''){
id = customId
@@ -182,13 +182,17 @@ export async function saveAsset(data:Uint8Array, customId:string = ''){
id = uuidv4()
}
}
+ let fileExtension:string = 'png'
+ if(fileName && fileName.split('.').length > 0){
+ fileExtension = fileName.split('.').pop()
+ }
if(isTauri){
- await writeBinaryFile(`assets/${id}.png`, data ,{dir: BaseDirectory.AppData})
- return `assets/${id}.png`
+ await writeBinaryFile(`assets/${id}.${fileExtension}`, data ,{dir: BaseDirectory.AppData})
+ return `assets/${id}.${fileExtension}`
}
else{
- await forageStorage.setItem(`assets/${id}.png`, data)
- return `assets/${id}.png`
+ await forageStorage.setItem(`assets/${id}.${fileExtension}`, data)
+ return `assets/${id}.${fileExtension}`
}
}
|