Add hotkeys

This commit is contained in:
kwaroran
2025-03-20 14:37:12 +09:00
parent 4c67ce4410
commit f5f05bdf99
6 changed files with 377 additions and 77 deletions

View File

@@ -1079,4 +1079,33 @@ export const languageEnglish = {
axModelsDef: "Ax Models Definition",
doNotChangeSeperateModels: "Do Not Change Seperate Models",
tools: "Tools",
action: "Action",
hotkey: "Hotkey",
hotkeyDesc: {
reroll: "Reroll",
unreroll: "Undo Reroll",
translate: "Translate",
remove: "Remove",
edit: "Edit",
copy: "Copy",
send: "Send",
settings: "Settings",
home: "Home",
presets: "Quick Presets Select",
persona: "Quick Persona Select",
modelSelect: "Quick Model Select",
toggleCSS: "Toggle CSS",
prevChar: "Previous Character",
nextChar: "Next Character",
quickMenu: "Quick Menu",
quickSettings: "Quick Settings",
toggleVoice: "Toggle Voice",
toggleLog: "Toggle Log",
previewRequest: "Preview Request",
import: "Import",
export: "Export",
webcam: "Toggle Webcam",
focusInput: "Focus Input",
},
screenTooSmall: "Screen is too small to show the interface.",
}

View File

@@ -0,0 +1,73 @@
<script lang="ts">
import { language } from "src/lang";
import { DBState } from "src/ts/stores.svelte";
</script>
{#if window.innerWidth < 768}
<span class="text-red-500">
{language.screenTooSmall}
</span>
{:else}
<table>
<thead>
<tr>
<th>{language.hotkey}</th>
</tr>
</thead>
<tbody>
{#each DBState.db.hotkeys as hotkey}
<tr>
<td>{language.hotkeyDesc[hotkey.action]}</td>
<td>
<button
class:text-textcolor={hotkey.ctrl}
class:text-textcolor2={!hotkey.ctrl}
onclick={() => {
hotkey.ctrl = !hotkey.ctrl;
}}
>
Ctrl
</button>
</td>
<td>
<button
class:text-textcolor={hotkey.shift}
class:text-textcolor2={!hotkey.shift}
onclick={() => {
hotkey.shift = !hotkey.shift;
}}
>
Shift
</button>
</td>
<td>
<button
class:text-textcolor={hotkey.alt}
class:text-textcolor2={!hotkey.alt}
onclick={() => {
hotkey.alt = !hotkey.alt;
}}
>
Alt
</button>
</td>
<td>
<input
value={hotkey.key === ' ' ? "SPACE" : hotkey.key?.toLocaleUpperCase()}
class="bg-bgcolor border-none w-16"
onkeydown={(e) => {
e.preventDefault();
hotkey.key = e.key;
}}
>
</td>
</tr>
{/each}
</tbody>
</table>
{/if}

View File

@@ -21,6 +21,7 @@
import ThanksPage from "./Pages/ThanksPage.svelte";
import ModuleSettings from "./Pages/Module/ModuleSettings.svelte";
import { isLite } from "src/ts/lite";
import HotkeySettings from "./Pages/HotkeySettings.svelte";
let openLoreList = $state(false)
if(window.innerWidth >= 900 && $SettingsMenuIndex === -1 && !$MobileGUI){
@@ -122,6 +123,15 @@
<UserIcon />
<span>{language.account} & {language.files}</span>
</button>
<button class="flex gap-2 items-center hover:text-textcolor"
class:text-textcolor={$SettingsMenuIndex === 15}
class:text-textcolor2={$SettingsMenuIndex !== 15}
onclick={() => {
$SettingsMenuIndex = 15
}}>
<ActivityIcon />
<span>{language.hotkey}</span>
</button>
{#if !$isLite}
<button class="flex gap-2 items-center hover:text-textcolor"
class:text-textcolor={$SettingsMenuIndex === 6}
@@ -186,6 +196,8 @@
<PromptSettings onGoBack={() => {
$SettingsMenuIndex = 1
}}/>
{:else if $SettingsMenuIndex === 15}
<HotkeySettings/>
{:else if $SettingsMenuIndex === 77}
<ThanksPage/>
{/if}

141
src/ts/defaulthotkeys.ts Normal file
View File

@@ -0,0 +1,141 @@
export interface Hotkey{
key: string
ctrl?: boolean
shift?: boolean
alt?: boolean
action: string
}
export const defaultHotkeys: Hotkey[] = [
{
key: 'r',
ctrl: true,
alt: true,
action: 'reroll'
},
{
key: 'f',
ctrl: true,
alt: true,
action: 'unreroll'
},
{
key: 't',
ctrl: true,
alt: true,
action: 'translate'
},
{
key: 'd',
ctrl: true,
alt: true,
action: 'remove'
},
{
key: 'e',
ctrl: true,
alt: true,
action: 'edit'
},
{
key: 'c',
ctrl: true,
alt: true,
action: 'copy'
},
{
key: 'Enter',
ctrl: true,
alt: true,
action: 'send'
},
{
key: 's',
ctrl: true,
action: 'settings'
},
{
key: 'h',
ctrl: true,
action: 'home'
},
{
key: 'p',
ctrl: true,
action: 'presets'
},
{
key: 'e',
ctrl: true,
action: 'persona'
},
{
key: 'm',
ctrl: true,
action: 'modelSelect'
},
{
key: '.',
ctrl: true,
action: 'toggleCSS'
},
//Needs to implement after this
{
key: '[',
ctrl: true,
action: 'prevChar'
},
{
key: ']',
ctrl: true,
action: 'nextChar'
},
{
key: '`',
ctrl: true,
action: 'quickMenu'
},
{
key: 'q',
ctrl: true,
action: 'quickSettings'
},
{
key: 'v',
ctrl: true,
action: 'toggleVoice'
},
{
key: 'l',
ctrl: true,
action: 'toggleLog'
},
{
key: 'u',
ctrl: true,
action: 'previewRequest'
},
{
key: 'i',
ctrl: true,
action: 'import'
},
{
key: 'x',
ctrl: true,
action: 'export'
},
{
key: 'w',
ctrl: true,
action: 'webcam'
},
{
key: ' ',
action: 'focusInput'
},
]

View File

@@ -4,59 +4,132 @@ import { changeToPreset as changeToPreset2, getDatabase } from "./storage/datab
import { alertStore, MobileGUIStack, MobileSideBar, openPersonaList, openPresetList, SafeModeStore, selectedCharID, settingsOpen } from "./stores.svelte"
import { language } from "src/lang"
import { updateTextThemeAndCSS } from "./gui/colorscheme"
import { defaultHotkeys } from "./defaulthotkeys"
export function initHotkey(){
document.addEventListener('keydown', (ev) => {
if(ev.ctrlKey){
if(
!ev.ctrlKey &&
!ev.altKey &&
!ev.shiftKey &&
['INPUT', 'TEXTAREA'].includes(document.activeElement.tagName)
){
return
}
if(ev.altKey){
switch(ev.key){
case "r":{
ev.preventDefault()
clickQuery('.button-icon-reroll')
return
}
case "f":{
ev.preventDefault()
clickQuery('.button-icon-unreroll')
return
}
case "t":{
ev.preventDefault()
clickQuery('.button-icon-translate')
return
}
case "d":{
ev.preventDefault()
clickQuery('.button-icon-remove')
return
}
case 'e':{
ev.preventDefault()
clickQuery('.button-icon-edit')
setTimeout(() => {
focusQuery('.message-edit-area')
}, 100)
return
}
case 'c':{
ev.preventDefault()
clickQuery('.button-icon-copy')
return
}
case 'i':{
ev.preventDefault()
focusQuery('.text-input-area')
return
}
case 'Enter':{
ev.preventDefault()
clickQuery('.button-icon-send')
return
}
const database = getDatabase()
const hotKeys = database?.hotkeys ?? defaultHotkeys
let hotkeyRan = false
for(const hotkey of hotKeys){
let hotKeyRanThisTime = true
hotkey.ctrl = hotkey.ctrl ?? false
hotkey.alt = hotkey.alt ?? false
hotkey.shift = hotkey.shift ?? false
if(hotkey.key === ev.key){
console.log(`Hotkey: "${hotkey.key}" ${hotkey.ctrl} ${hotkey.alt} ${hotkey.shift}`)
console.log(`Event: "${ev.key}" ${ev.ctrlKey} ${ev.altKey} ${ev.shiftKey}`)
}
if(hotkey.ctrl !== ev.ctrlKey){
continue
}
if(hotkey.alt !== ev.altKey){
continue
}
if(hotkey.shift !== ev.shiftKey){
continue
}
if(hotkey.key !== ev.key){
continue
}
if(!hotkey.ctrl && !hotkey.alt && !hotkey.shift){
if(['INPUT', 'TEXTAREA'].includes(document.activeElement.tagName)){
continue
}
}
switch(hotkey.action){
case 'reroll':{
clickQuery('.button-icon-reroll')
break
}
case 'unreroll':{
clickQuery('.button-icon-unreroll')
break
}
case 'translate':{
clickQuery('.button-icon-translate')
break
}
case 'remove':{
clickQuery('.button-icon-remove')
break
}
case 'edit':{
clickQuery('.button-icon-edit')
setTimeout(() => {
focusQuery('.message-edit-area')
}, 100)
break
}
case 'copy':{
clickQuery('.button-icon-copy')
break
}
case 'focusInput':{
focusQuery('.text-input-area')
break
}
case 'send':{
clickQuery('.button-icon-send')
break
}
case 'settings':{
settingsOpen.set(!get(settingsOpen))
break
}
case 'home':{
selectedCharID.set(-1)
break
}
case 'presets':{
openPresetList.set(!get(openPresetList))
break
}
case 'persona':{
openPersonaList.set(!get(openPersonaList))
break
}
case 'toggleCSS':{
SafeModeStore.set(!get(SafeModeStore))
updateTextThemeAndCSS()
break
}
default:{
hotKeyRanThisTime = false
}
}
if(hotKeyRanThisTime){
hotkeyRan = true
break
}
}
if(hotkeyRan){
ev.preventDefault()
ev.stopPropagation()
return
}
if(ev.ctrlKey){
switch (ev.key){
case "1":{
changeToPreset(0)
@@ -112,37 +185,6 @@ export function initHotkey(){
ev.stopPropagation()
break
}
case 's':{
settingsOpen.set(!get(settingsOpen))
ev.preventDefault()
ev.stopPropagation()
break
}
case 'h':{
selectedCharID.set(-1)
ev.preventDefault()
ev.stopPropagation()
break
}
case 'p':{
openPresetList.set(!get(openPresetList))
ev.preventDefault()
ev.stopPropagation()
break
}
case 'e':{
openPersonaList.set(!get(openPersonaList))
ev.preventDefault()
ev.stopPropagation()
break
}
case '.':{
SafeModeStore.set(!get(SafeModeStore))
updateTextThemeAndCSS()
ev.preventDefault()
ev.stopPropagation()
break
}
}
}
if(ev.key === 'Escape'){

View File

@@ -497,6 +497,7 @@ export function setDatabase(data:Database){
}
data.doNotChangeSeperateModels ??= false
data.modelTools ??= []
data.hotkeys ??= structuredClone(defaultHotkeys)
changeLanguage(data.language)
setDatabaseLite(data)
}
@@ -943,6 +944,7 @@ export interface Database{
}
doNotChangeSeperateModels:boolean
modelTools: string[]
hotkeys:Hotkey[]
}
interface SeparateParameters{
@@ -1743,6 +1745,7 @@ import { LLMFlags, LLMFormat } from '../model/modellist';
import type { Parameter } from '../process/request';
import type { HypaModel } from '../process/memory/hypamemory';
import type { SerializableHypaV3Data } from '../process/memory/hypav3';
import { defaultHotkeys, type Hotkey } from '../defaulthotkeys';
export async function downloadPreset(id:number, type:'json'|'risupreset'|'return' = 'json'){
saveCurrentPreset()