Migrate to svelte 5
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
<script>
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
|
||||
export let width = 800;
|
||||
export let height = 600;
|
||||
/** @type {{width?: number, height?: number}} */
|
||||
let { width = 800, height = 600 } = $props();
|
||||
|
||||
let canvas;
|
||||
let canvas = $state();
|
||||
let animationFrameId;
|
||||
|
||||
onMount(async () => {
|
||||
|
||||
@@ -2,20 +2,31 @@
|
||||
import type { language } from "src/lang";
|
||||
import Help from "../Others/Help.svelte";
|
||||
|
||||
export let name = ""
|
||||
let open = false
|
||||
export let styled = false
|
||||
export let help: (keyof (typeof language.help))|'' = ''
|
||||
export let disabled = false
|
||||
let open = $state(false)
|
||||
interface Props {
|
||||
name?: string;
|
||||
styled?: boolean;
|
||||
help?: (keyof (typeof language.help))|'';
|
||||
disabled?: boolean;
|
||||
children?: import('svelte').Snippet;
|
||||
}
|
||||
|
||||
let {
|
||||
name = "",
|
||||
styled = false,
|
||||
help = '',
|
||||
disabled = false,
|
||||
children
|
||||
}: Props = $props();
|
||||
</script>
|
||||
{#if disabled}
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
{:else if styled}
|
||||
<div class="flex flex-col mt-2">
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg rounded-t-md border-selected border"
|
||||
class:bg-selected={open}
|
||||
class:rounded-b-md={!open}
|
||||
on:click={() => {
|
||||
onclick={() => {
|
||||
open = !open
|
||||
}}
|
||||
>
|
||||
@@ -25,18 +36,18 @@
|
||||
{/if}</button>
|
||||
{#if open}
|
||||
<div class="flex flex-col border border-selected p-2 rounded-b-md">
|
||||
<slot></slot>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex flex-col">
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" class:bg-selected={open} on:click={() => {
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" class:bg-selected={open} onclick={() => {
|
||||
open = !open
|
||||
}}>{name}</button>
|
||||
{#if open}
|
||||
<div class="flex flex-col bg-darkbg">
|
||||
<slot></slot>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
<script lang="ts">
|
||||
export let isDisabled: boolean = false;
|
||||
export let onClick: () => void;
|
||||
interface Props {
|
||||
isDisabled?: boolean;
|
||||
onClick: () => void;
|
||||
children?: import('svelte').Snippet;
|
||||
}
|
||||
|
||||
let { isDisabled = false, onClick, children }: Props = $props();
|
||||
</script>
|
||||
|
||||
<button
|
||||
disabled={isDisabled}
|
||||
on:click={onClick}
|
||||
onclick={onClick}
|
||||
class="flex h-[56px] w-[56px] cursor-pointer select-none items-center justify-center
|
||||
transition-colors rounded-full
|
||||
border border-textcolor2 text-gray-300
|
||||
hover:border-gray-300
|
||||
{isDisabled ? '!cursor-not-allowed' : ''}"
|
||||
>
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
</button>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<button
|
||||
on:click
|
||||
onclick={onclick}
|
||||
class="{
|
||||
styled === 'primary' ? ((selected ? 'bg-bg-selected' : 'bg-darkbutton') + " hover:bg-selected focus:ring-selected border-darkborderc")
|
||||
: styled === 'outlined' ? 'bg-transparent hover:bg-darkbg focus:ring-selected border-darkborderc text-textcolor2'
|
||||
@@ -14,11 +14,27 @@
|
||||
class:text-md = {size == "md"}
|
||||
class:text-sm = {size == "sm"}
|
||||
class:text-lg = {size == "lg"}>
|
||||
<slot></slot>
|
||||
{@render children?.()}
|
||||
</button>
|
||||
<script lang="ts">
|
||||
export let selected = false
|
||||
export let styled:'primary'|'danger'|'outlined' = 'primary'
|
||||
export let className = ""
|
||||
export let size: "sm" | "md" | "lg" = "md"
|
||||
|
||||
interface Props {
|
||||
selected?: boolean;
|
||||
styled?: 'primary'|'danger'|'outlined';
|
||||
className?: string;
|
||||
size?: "sm" | "md" | "lg";
|
||||
children?: import('svelte').Snippet;
|
||||
onclick?: (event: MouseEvent & {
|
||||
currentTarget: EventTarget & HTMLButtonElement;
|
||||
}) => any
|
||||
}
|
||||
|
||||
let {
|
||||
selected = false,
|
||||
styled = 'primary',
|
||||
className = "",
|
||||
size = "md",
|
||||
children,
|
||||
onclick
|
||||
}: Props = $props();
|
||||
</script>
|
||||
@@ -1,14 +1,29 @@
|
||||
<script lang="ts">
|
||||
import { CheckIcon } from "lucide-svelte";
|
||||
|
||||
export let check = false
|
||||
export let onChange = (check:boolean) => {}
|
||||
export let margin = true
|
||||
export let name = ''
|
||||
export let hiddenName = false
|
||||
export let reverse = false
|
||||
export let className = ""
|
||||
export let grayText = false
|
||||
interface Props {
|
||||
check?: boolean;
|
||||
onChange?: any;
|
||||
margin?: boolean;
|
||||
name?: string;
|
||||
hiddenName?: boolean;
|
||||
reverse?: boolean;
|
||||
className?: string;
|
||||
grayText?: boolean;
|
||||
children?: import('svelte').Snippet;
|
||||
}
|
||||
|
||||
let {
|
||||
check = $bindable(),
|
||||
onChange = (check:boolean) => {},
|
||||
margin = true,
|
||||
name = '',
|
||||
hiddenName = false,
|
||||
reverse = false,
|
||||
className = "",
|
||||
grayText = false,
|
||||
children
|
||||
}: Props = $props();
|
||||
</script>
|
||||
|
||||
<label
|
||||
@@ -18,14 +33,14 @@
|
||||
aria-labelledby="{name} {check ? 'abled' : 'disabled'}"
|
||||
>
|
||||
{#if reverse}
|
||||
<span>{name}<slot /></span>
|
||||
<span>{name}{@render children?.()}</span>
|
||||
{/if}
|
||||
<input
|
||||
class="hidden"
|
||||
type="checkbox"
|
||||
alt={name}
|
||||
bind:checked={check}
|
||||
on:change={() => {
|
||||
onchange={() => {
|
||||
onChange(check)
|
||||
}}
|
||||
aria-describedby="{name} {check ? 'abled' : 'disabled'}"
|
||||
@@ -44,6 +59,6 @@
|
||||
{/if}
|
||||
</span>
|
||||
{#if !hiddenName && !reverse}
|
||||
<span>{name}<slot /></span>
|
||||
<span>{name}{@render children?.()}</span>
|
||||
{/if}
|
||||
</label>
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
<script lang="ts">
|
||||
import ColorPicker from 'svelte-awesome-color-picker';
|
||||
export let value = '#000000';
|
||||
export let nullable = false;
|
||||
interface Props {
|
||||
value?: string;
|
||||
nullable?: boolean;
|
||||
oninput?: () => void;
|
||||
}
|
||||
|
||||
let { value = $bindable('#000000'), nullable = false, oninput }: Props = $props();
|
||||
|
||||
$effect(() => {
|
||||
//this is for updating
|
||||
value
|
||||
|
||||
oninput?.()
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="cl rounded-full bg-white">
|
||||
<ColorPicker
|
||||
label="" bind:hex={value} on:input
|
||||
label="" bind:hex={value}
|
||||
nullable={nullable}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,25 +1,33 @@
|
||||
<script lang="ts">
|
||||
import { run, stopPropagation } from 'svelte/legacy';
|
||||
|
||||
import { ColorSchemeTypeStore } from "src/ts/gui/colorscheme";
|
||||
import { ParseMarkdown } from "src/ts/parser";
|
||||
import { parseMultilangString, toLangName } from "src/ts/util";
|
||||
|
||||
export let value: string
|
||||
export let markdown: boolean = false
|
||||
let valueObject: {[code:string]:string} = parseMultilangString(value)
|
||||
let selectedLang = "en"
|
||||
interface Props {
|
||||
value: string;
|
||||
markdown?: boolean;
|
||||
}
|
||||
|
||||
let { value, markdown = false }: Props = $props();
|
||||
let valueObject: {[code:string]:string} = $state(parseMultilangString(value))
|
||||
let selectedLang = $state("en")
|
||||
if(valueObject["en"] === undefined){
|
||||
selectedLang = "xx"
|
||||
}
|
||||
$: valueObject = parseMultilangString(value)
|
||||
run(() => {
|
||||
valueObject = parseMultilangString(value)
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-wrap max-w-fit p-1 gap-2">
|
||||
{#each Object.keys(valueObject) as lang}
|
||||
{#if lang !== 'xx' || Object.keys(valueObject).length === 1}
|
||||
<button class="bg-bgcolor py-2 rounded-lg px-4" class:ring-1={selectedLang === lang} on:click|stopPropagation={() => {
|
||||
<button class="bg-bgcolor py-2 rounded-lg px-4" class:ring-1={selectedLang === lang} onclick={stopPropagation(() => {
|
||||
selectedLang = lang
|
||||
}}>{toLangName(lang)}</button>
|
||||
})}>{toLangName(lang)}</button>
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
<script lang="ts">
|
||||
import { run } from 'svelte/legacy';
|
||||
|
||||
import { encodeMultilangString, languageCodes, parseMultilangString, toLangName } from "src/ts/util";
|
||||
import TextAreaInput from "./TextAreaInput.svelte";
|
||||
export let value: string
|
||||
let addingLang = false
|
||||
let valueObject: {[code:string]:string} = parseMultilangString(value)
|
||||
let selectedLang = "en"
|
||||
export let className = ""
|
||||
export let onInput = () => {}
|
||||
let addingLang = $state(false)
|
||||
let selectedLang = $state("en")
|
||||
interface Props {
|
||||
value: string;
|
||||
className?: string;
|
||||
onInput?: any;
|
||||
}
|
||||
|
||||
let { value = $bindable(), className = "", onInput = () => {} }: Props = $props();
|
||||
let valueObject: {[code:string]:string} = $state(parseMultilangString(value))
|
||||
const updateValue = () => {
|
||||
for(let lang in valueObject){
|
||||
if(valueObject[lang] === "" && lang !== selectedLang && lang!=="en" ){
|
||||
@@ -27,25 +33,27 @@
|
||||
delete valueObject["xx"]
|
||||
updateValue()
|
||||
}
|
||||
$: valueObject = parseMultilangString(value)
|
||||
run(() => {
|
||||
valueObject = parseMultilangString(value)
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="flex flex-wrap max-w-fit p-1 gap-2">
|
||||
{#each Object.keys(valueObject) as lang}
|
||||
{#if lang !== 'xx'}
|
||||
<button class="bg-bgcolor py-2 rounded-lg px-4" class:ring-1={selectedLang === lang} on:click={() => {
|
||||
<button class="bg-bgcolor py-2 rounded-lg px-4" class:ring-1={selectedLang === lang} onclick={() => {
|
||||
selectedLang = lang
|
||||
updateValue()
|
||||
}}>{toLangName(lang)}</button>
|
||||
{/if}
|
||||
{/each}
|
||||
<button class="text-nowrap bg-bgcolor py-2 rounded-lg px-4" class:ring-1={addingLang} on:click={() => {addingLang = !addingLang}}>+</button>
|
||||
<button class="text-nowrap bg-bgcolor py-2 rounded-lg px-4" class:ring-1={addingLang} onclick={() => {addingLang = !addingLang}}>+</button>
|
||||
</div>
|
||||
{#if addingLang}
|
||||
<div class="m-1 p-1 g-2 flex max-w-fit rounded-md border-t-bgcolor flex-wrap gap-1">
|
||||
{#each languageCodes as lang}
|
||||
{#if toLangName(lang).length !== 2}
|
||||
<button class="bg-bgcolor py-2 rounded-lg px-4 text-nowrap" on:click={() => {
|
||||
<button class="bg-bgcolor py-2 rounded-lg px-4 text-nowrap" onclick={() => {
|
||||
valueObject[lang] = ""
|
||||
selectedLang = lang
|
||||
addingLang = false
|
||||
|
||||
@@ -20,23 +20,41 @@
|
||||
id={id}
|
||||
disabled={disabled}
|
||||
bind:value
|
||||
on:change={onChange}
|
||||
onchange={onChange}
|
||||
/>
|
||||
|
||||
<script lang="ts">
|
||||
import type { ChangeEventHandler } from "svelte/elements";
|
||||
export let min:number = undefined
|
||||
export let max:number = undefined
|
||||
export let size: 'sm'|'md'|'lg' = 'sm'
|
||||
export let value:number
|
||||
export let id:string = undefined
|
||||
export let padding = true
|
||||
export let marginBottom = false
|
||||
export let fullwidth = false
|
||||
export let fullh = false
|
||||
export let onChange:ChangeEventHandler<HTMLInputElement> = () => {}
|
||||
export let className = ''
|
||||
export let disabled = false
|
||||
interface Props {
|
||||
min?: number;
|
||||
max?: number;
|
||||
size?: 'sm'|'md'|'lg';
|
||||
value: number;
|
||||
id?: string;
|
||||
padding?: boolean;
|
||||
marginBottom?: boolean;
|
||||
fullwidth?: boolean;
|
||||
fullh?: boolean;
|
||||
onChange?: (event: Event & {
|
||||
currentTarget: EventTarget & HTMLInputElement;
|
||||
}) => any;
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
let {
|
||||
min = undefined,
|
||||
max = undefined,
|
||||
size = 'sm',
|
||||
value = $bindable(),
|
||||
id = undefined,
|
||||
padding = true,
|
||||
marginBottom = false,
|
||||
fullwidth = false,
|
||||
fullh = false,
|
||||
onChange = () => {},
|
||||
className = '',
|
||||
disabled = false
|
||||
}: Props = $props();
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
<option value={value} selected={selected} class="bg-darkbg appearance-none"><slot></slot></option>
|
||||
<option value={value} selected={selected} class="bg-darkbg appearance-none">{@render children?.()}</option>
|
||||
<script lang="ts">
|
||||
export let value:string
|
||||
export let selected:boolean = false
|
||||
interface Props {
|
||||
value: string;
|
||||
selected?: boolean;
|
||||
children?: import('svelte').Snippet;
|
||||
}
|
||||
|
||||
let { value, selected = false, children }: Props = $props();
|
||||
</script>
|
||||
@@ -2,10 +2,19 @@
|
||||
import CheckInput from "./CheckInput.svelte";
|
||||
import NumberInput from "./NumberInput.svelte";
|
||||
import TextInput from "./TextInput.svelte";
|
||||
export let value:string|number|boolean
|
||||
export let numberMode = false
|
||||
export let boolMode = false
|
||||
export let marginBottom = false
|
||||
interface Props {
|
||||
value: string|number|boolean;
|
||||
numberMode?: boolean;
|
||||
boolMode?: boolean;
|
||||
marginBottom?: boolean;
|
||||
}
|
||||
|
||||
let {
|
||||
value = $bindable(),
|
||||
numberMode = false,
|
||||
boolMode = false,
|
||||
marginBottom = false
|
||||
}: Props = $props();
|
||||
const valToggle = () => {
|
||||
value = !value
|
||||
}
|
||||
@@ -38,8 +47,8 @@
|
||||
{:else if typeof(value) === 'number'}
|
||||
<NumberInput bind:value={value} className="flex-1"/>
|
||||
{:else if typeof(value) === 'boolean'}
|
||||
<button class="px-2 py-2 border border-darkborderc flex-1" class:text-textcolor2={!value} on:click={valToggle}>True</button>
|
||||
<button class="px-2 py-2 border border-darkborderc flex-1" class:text-textcolor2={value} on:click={valToggle}>False</button>
|
||||
<button class="px-2 py-2 border border-darkborderc flex-1" class:text-textcolor2={!value} onclick={valToggle}>True</button>
|
||||
<button class="px-2 py-2 border border-darkborderc flex-1" class:text-textcolor2={value} onclick={valToggle}>False</button>
|
||||
{:else}
|
||||
<TextInput value={"Using default"} className="flex-1" disabled/>
|
||||
{/if}
|
||||
|
||||
@@ -11,13 +11,27 @@
|
||||
class:px-6={size === 'lg'}
|
||||
class:py-3={size === 'lg'}
|
||||
bind:value
|
||||
on:change
|
||||
onchange={onchange}
|
||||
>
|
||||
<slot></slot>
|
||||
{@render children?.()}
|
||||
</select>
|
||||
<script lang="ts">
|
||||
export let value:string
|
||||
export let className:string = ""
|
||||
export let size:'sm'|'md'|'lg'|'xl' = 'md'
|
||||
interface Props {
|
||||
value: string;
|
||||
className?: string;
|
||||
size?: 'sm'|'md'|'lg'|'xl';
|
||||
children?: import('svelte').Snippet;
|
||||
onchange?: (event: Event & {
|
||||
currentTarget: EventTarget & HTMLSelectElement;
|
||||
}) => any;
|
||||
}
|
||||
|
||||
let {
|
||||
value = $bindable(),
|
||||
className = "",
|
||||
size = 'md',
|
||||
children,
|
||||
onchange
|
||||
}: Props = $props();
|
||||
|
||||
</script>
|
||||
@@ -6,14 +6,13 @@
|
||||
|
||||
{#if !$MobileGUI}
|
||||
{#if $sideBarStore && !$DynamicGUI}
|
||||
<button on:click={() => {sideBarClosing.set(true)}} class="absolute top-3 left-0 h-12 w-12 border-r border-b border-t border-transparent rounded-r-md bg-darkbg hover:border-neutral-200 transition-colors flex items-center justify-center text-textcolor z-20">
|
||||
<button onclick={() => {sideBarClosing.set(true)}} class="absolute top-3 left-0 h-12 w-12 border-r border-b border-t border-transparent rounded-r-md bg-darkbg hover:border-neutral-200 transition-colors flex items-center justify-center text-textcolor z-20">
|
||||
<ArrowLeft />
|
||||
</button>
|
||||
{:else}
|
||||
<button on:click={() => {
|
||||
<button onclick={() => {
|
||||
sideBarClosing.set(false);
|
||||
sideBarStore.set(true)}
|
||||
} class="absolute top-3 left-0 h-12 w-12 border-r border-b border-t border-borderc rounded-r-md bg-darkbg hover:border-neutral-200 transition-colors flex items-center justify-center text-textcolor opacity-50 hover:opacity-90 z-20">
|
||||
sideBarStore.set(true)}} class="absolute top-3 left-0 h-12 w-12 border-r border-b border-t border-borderc rounded-r-md bg-darkbg hover:border-neutral-200 transition-colors flex items-center justify-center text-textcolor opacity-50 hover:opacity-90 z-20">
|
||||
<ArrowRight />
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
max={max}
|
||||
step={step}
|
||||
bind:value
|
||||
on:change
|
||||
onchange
|
||||
> -->
|
||||
|
||||
<div class="w-full flex" class:mb-4={marginBottom}>
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
<div class="relative h-8 border-darkborderc border rounded-full cursor-pointer rounded-r-none border-r-0 flex justify-center items-center">
|
||||
<CheckInput check={value !== -1000} margin={false} onChange={(c) => {
|
||||
onchange?.()
|
||||
if(c) {
|
||||
value = min;
|
||||
} else {
|
||||
@@ -28,23 +29,23 @@
|
||||
style:background={
|
||||
`linear-gradient(to right, var(--risu-theme-darkbutton) 0%, var(--risu-theme-darkbutton) ${(value - min) / (max - min) * 100}%, var(--risu-theme-darkbg) ${(value - min) / (max - min) * 100}%, var(--risu-theme-darkbg) 100%)`
|
||||
}
|
||||
on:pointerdown={(event) => {
|
||||
onpointerdown={(event) => {
|
||||
mouseDown = true;
|
||||
changeValue(event);
|
||||
}}
|
||||
|
||||
on:pointermove={(event) => {
|
||||
onpointermove={(event) => {
|
||||
if (mouseDown) {
|
||||
changeValue(event);
|
||||
}
|
||||
}}
|
||||
|
||||
|
||||
on:pointerup={() => {
|
||||
onpointerup={() => {
|
||||
mouseDown = false;
|
||||
}}
|
||||
|
||||
on:pointerleave={() => {
|
||||
onpointerleave={() => {
|
||||
mouseDown = false;
|
||||
}}
|
||||
bind:this={slider}
|
||||
@@ -67,17 +68,33 @@
|
||||
import { language } from "src/lang";
|
||||
import CheckInput from "./CheckInput.svelte";
|
||||
|
||||
export let min:number = undefined
|
||||
export let max:number = undefined
|
||||
export let value:number
|
||||
export let marginBottom = false
|
||||
export let step = 1
|
||||
export let fixed = 0
|
||||
export let multiple = 1
|
||||
let slider: HTMLDivElement
|
||||
let mouseDown = false
|
||||
export let disableable = false
|
||||
export let customText: string|undefined = undefined
|
||||
let slider: HTMLDivElement = $state()
|
||||
let mouseDown = $state(false)
|
||||
interface Props {
|
||||
min?: number;
|
||||
max?: number;
|
||||
value: number;
|
||||
marginBottom?: boolean;
|
||||
step?: number;
|
||||
fixed?: number;
|
||||
multiple?: number;
|
||||
disableable?: boolean;
|
||||
customText?: string|undefined;
|
||||
onchange?: Function;
|
||||
}
|
||||
|
||||
let {
|
||||
min = undefined,
|
||||
max = undefined,
|
||||
value = $bindable(),
|
||||
marginBottom = false,
|
||||
step = 1,
|
||||
fixed = 0,
|
||||
multiple = 1,
|
||||
disableable = false,
|
||||
customText = undefined,
|
||||
onchange
|
||||
}: Props = $props();
|
||||
|
||||
function changeValue(event) {
|
||||
const rect = slider.getBoundingClientRect();
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
class:mt-4={margin === 'top'}
|
||||
class:mt-2={margin === 'both'}
|
||||
bind:this={highlightDom}
|
||||
on:focusout={() => {
|
||||
onfocusout={() => {
|
||||
hideAutoComplete()
|
||||
}}
|
||||
>
|
||||
@@ -47,7 +47,7 @@
|
||||
{placeholder}
|
||||
id={id}
|
||||
bind:value={value}
|
||||
on:input={(e) => {
|
||||
oninput={(e) => {
|
||||
if(optimaizedInput){
|
||||
if(inpa++ > 10){
|
||||
value = e.currentTarget.value
|
||||
@@ -60,26 +60,26 @@
|
||||
onInput()
|
||||
}
|
||||
}}
|
||||
on:change={(e) => {
|
||||
onchange={(e) => {
|
||||
if(optimaizedInput){
|
||||
value = e.currentTarget.value
|
||||
onInput()
|
||||
}
|
||||
}}
|
||||
/>
|
||||
></textarea>
|
||||
{:else if isFirefox}
|
||||
<div
|
||||
class="w-full h-full bg-transparent focus-within:outline-none resize-none absolute top-0 left-0 z-50 overflow-y-auto px-4 py-2 break-words whitespace-pre-wrap"
|
||||
contenteditable="true"
|
||||
bind:textContent={value}
|
||||
on:keydown={(e) => {
|
||||
onkeydown={(e) => {
|
||||
handleKeyDown(e)
|
||||
onInput()
|
||||
}}
|
||||
on:input={(e) => {
|
||||
oninput={(e) => {
|
||||
autoComplete()
|
||||
}}
|
||||
on:paste={(e) => {
|
||||
onpaste={(e) => {
|
||||
e.preventDefault()
|
||||
const text = e.clipboardData.getData('text/plain')
|
||||
if(text){
|
||||
@@ -94,11 +94,11 @@
|
||||
class="w-full h-full bg-transparent focus-within:outline-none resize-none absolute top-0 left-0 z-50 overflow-y-auto px-4 py-2 break-words whitespace-pre-wrap"
|
||||
contenteditable="plaintext-only"
|
||||
bind:innerText={value}
|
||||
on:keydown={(e) => {
|
||||
onkeydown={(e) => {
|
||||
handleKeyDown(e)
|
||||
onInput()
|
||||
}}
|
||||
on:input={(e) => {
|
||||
oninput={(e) => {
|
||||
autoComplete()
|
||||
}}
|
||||
bind:this={inputDom}
|
||||
@@ -107,39 +107,59 @@
|
||||
{/if}
|
||||
<div class="hidden absolute z-100 bg-bgcolor border border-darkborderc p-2 flex-col" bind:this={autoCompleteDom}>
|
||||
{#each autocompleteContents as content, i}
|
||||
<button class="w-full text-left py-1 px-2 bg-bgcolor" class:text-blue-500={selectingAutoComplete === i} on:click={() => {
|
||||
<button class="w-full text-left py-1 px-2 bg-bgcolor" class:text-blue-500={selectingAutoComplete === i} onclick={() => {
|
||||
insertContent(content)
|
||||
}}>{content}</button>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
<script lang="ts">
|
||||
import { run } from 'svelte/legacy';
|
||||
|
||||
import { textAreaSize, textAreaTextSize } from 'src/ts/gui/guisize'
|
||||
import { highlighter, getNewHighlightId, removeHighlight, AllCBS } from 'src/ts/gui/highlight'
|
||||
import { isMobile } from 'src/ts/storage/globalApi';
|
||||
import { isFirefox, sleep } from 'src/ts/util';
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
export let size: 'xs'|'sm'|'md'|'lg'|'xl'|'default' = 'default'
|
||||
export let autocomplete: 'on'|'off' = 'off'
|
||||
export let placeholder: string = ''
|
||||
export let value:string
|
||||
export let id:string = undefined
|
||||
export let padding = true
|
||||
export let margin:"none"|"top"|"bottom"|"both" = "none"
|
||||
export let onInput = () => {}
|
||||
export let fullwidth = false
|
||||
export let height:'20'|'24'|'28'|'32'|'36'|'full'|'default' = 'default'
|
||||
export let className = ''
|
||||
export let optimaizedInput = true
|
||||
export let highlight = false
|
||||
let selectingAutoComplete = 0
|
||||
interface Props {
|
||||
size?: 'xs'|'sm'|'md'|'lg'|'xl'|'default';
|
||||
autocomplete?: 'on'|'off';
|
||||
placeholder?: string;
|
||||
value: string;
|
||||
id?: string;
|
||||
padding?: boolean;
|
||||
margin?: "none"|"top"|"bottom"|"both";
|
||||
onInput?: any;
|
||||
fullwidth?: boolean;
|
||||
height?: '20'|'24'|'28'|'32'|'36'|'full'|'default';
|
||||
className?: string;
|
||||
optimaizedInput?: boolean;
|
||||
highlight?: boolean;
|
||||
}
|
||||
|
||||
let {
|
||||
size = 'default',
|
||||
autocomplete = 'off',
|
||||
placeholder = '',
|
||||
value = $bindable(),
|
||||
id = undefined,
|
||||
padding = true,
|
||||
margin = "none",
|
||||
onInput = () => {},
|
||||
fullwidth = false,
|
||||
height = 'default',
|
||||
className = '',
|
||||
optimaizedInput = true,
|
||||
highlight = false
|
||||
}: Props = $props();
|
||||
let selectingAutoComplete = $state(0)
|
||||
let highlightId = highlight ? getNewHighlightId() : 0
|
||||
let inpa = 0
|
||||
let highlightDom: HTMLDivElement
|
||||
let optiValue = value
|
||||
let autoCompleteDom: HTMLDivElement
|
||||
let autocompleteContents:string[] = []
|
||||
let inputDom: HTMLDivElement
|
||||
let inpa = $state(0)
|
||||
let highlightDom: HTMLDivElement = $state()
|
||||
let optiValue = $state(value)
|
||||
let autoCompleteDom: HTMLDivElement = $state()
|
||||
let autocompleteContents:string[] = $state([])
|
||||
let inputDom: HTMLDivElement = $state()
|
||||
|
||||
const autoComplete = () => {
|
||||
if(isMobile){
|
||||
@@ -291,7 +311,11 @@
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
$: optiValue = value
|
||||
$: highlightChange(value, highlightId)
|
||||
run(() => {
|
||||
optiValue = value
|
||||
});
|
||||
run(() => {
|
||||
highlightChange(value, highlightId)
|
||||
});
|
||||
|
||||
</script>
|
||||
@@ -3,10 +3,14 @@
|
||||
import { DataBase } from "../../../ts/storage/database";
|
||||
import { longpress } from 'src/ts/gui/longtouch';
|
||||
|
||||
let textarea;
|
||||
let textarea:HTMLElement = $state();
|
||||
let previousScrollHeight = 0;
|
||||
export let value = ''
|
||||
export let handleLongPress = (e:MouseEvent) => {};
|
||||
interface Props {
|
||||
value?: string;
|
||||
handleLongPress?: any;
|
||||
}
|
||||
|
||||
let { value = $bindable(''), handleLongPress = (e:MouseEvent) => {} }: Props = $props();
|
||||
|
||||
function resize() {
|
||||
textarea.style.height = '0px'; // Reset the textarea height
|
||||
@@ -27,10 +31,10 @@
|
||||
|
||||
<textarea
|
||||
bind:this={textarea}
|
||||
on:input={handleInput}
|
||||
oninput={handleInput}
|
||||
use:longpress={handleLongPress}
|
||||
bind:value={value}
|
||||
class="rounded-md p-2 text-textcolor bg-transparent resize-none overflow-y-hidden border border-darkborderc"
|
||||
style:font-size="{0.875 * ($DataBase.zoomsize / 100)}rem"
|
||||
style:line-height="{($DataBase.lineHeight ?? 1.25) * ($DataBase.zoomsize / 100)}rem"
|
||||
/>
|
||||
></textarea>
|
||||
@@ -29,7 +29,8 @@
|
||||
type="password"
|
||||
bind:value
|
||||
disabled={disabled}
|
||||
on:input={onInput}
|
||||
oninput={oninput}
|
||||
onchange={onchange}
|
||||
/>
|
||||
{:else}
|
||||
|
||||
@@ -60,29 +61,52 @@
|
||||
type="text"
|
||||
bind:value
|
||||
disabled={disabled}
|
||||
on:input={(e) => {
|
||||
onInput(e)
|
||||
}}
|
||||
oninput={oninput}
|
||||
onchange={onchange}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<script lang="ts">
|
||||
export let size: 'sm'|'md'|'lg'|'xl' = 'md'
|
||||
export let autocomplete: 'on'|'off' = 'off'
|
||||
export let placeholder: string = ''
|
||||
export let value:string
|
||||
export let id:string = undefined
|
||||
export let padding = true
|
||||
export let marginBottom = false
|
||||
export let marginTop = false
|
||||
export let onInput = (e:Event & {
|
||||
currentTarget: EventTarget & HTMLInputElement;
|
||||
}) => {}
|
||||
export let fullwidth = false
|
||||
export let fullh = false
|
||||
export let className = ''
|
||||
export let disabled = false
|
||||
export let hideText = false
|
||||
type FormEventHandler<T extends EventTarget> = (event: Event & {
|
||||
currentTarget: EventTarget & T;
|
||||
}) => any
|
||||
|
||||
interface Props {
|
||||
size?: 'sm'|'md'|'lg'|'xl';
|
||||
autocomplete?: 'on'|'off';
|
||||
placeholder?: string;
|
||||
value: string;
|
||||
id?: string;
|
||||
padding?: boolean;
|
||||
marginBottom?: boolean;
|
||||
marginTop?: boolean;
|
||||
oninput?: FormEventHandler<HTMLInputElement>
|
||||
onchange?: FormEventHandler<HTMLInputElement>;
|
||||
fullwidth?: boolean;
|
||||
fullh?: boolean;
|
||||
className?: string;
|
||||
disabled?: boolean;
|
||||
hideText?: boolean;
|
||||
}
|
||||
|
||||
let {
|
||||
size = 'md',
|
||||
autocomplete = 'off',
|
||||
placeholder = '',
|
||||
value = $bindable(),
|
||||
id = undefined,
|
||||
padding = true,
|
||||
marginBottom = false,
|
||||
marginTop = false,
|
||||
oninput,
|
||||
onchange,
|
||||
fullwidth = false,
|
||||
fullh = false,
|
||||
className = '',
|
||||
disabled = false,
|
||||
hideText = false,
|
||||
|
||||
}: Props = $props();
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<div class="w-full flex p-4 flex-col text-textcolor max-w-4xl">
|
||||
{#if !$OpenRealmStore}
|
||||
<div class="mt-4 mb-4 w-full border-t border-t-selected"></div>
|
||||
<h1 class="text-2xl font-bold">Recently Uploaded<button class="text-base font-medium float-right p-1 bg-darkbg rounded-md hover:ring" on:click={() => {
|
||||
<h1 class="text-2xl font-bold">Recently Uploaded<button class="text-base font-medium float-right p-1 bg-darkbg rounded-md hover:ring" onclick={() => {
|
||||
$OpenRealmStore = true
|
||||
}}>Get More</button></h1>
|
||||
{#if !$DataBase.hideRealm}
|
||||
@@ -51,7 +51,7 @@
|
||||
Related Links
|
||||
</h1>
|
||||
<div class="w-full flex gap-4 p-2 flex-wrap justify-center">
|
||||
<button class="bg-darkbg rounded-lg p-4 flex flex-col hover:bg-selected transition-colors relative lg:w-96 w-full items-start text-start" on:click={() => {
|
||||
<button class="bg-darkbg rounded-lg p-4 flex flex-col hover:bg-selected transition-colors relative lg:w-96 w-full items-start text-start" onclick={() => {
|
||||
openURL("https://discord.gg/Exy3NrqkGm")
|
||||
}}>
|
||||
<h2 class="text-xl">Discord</h2>
|
||||
@@ -59,7 +59,7 @@
|
||||
Join our Discord server to chat with other users and the developer.
|
||||
</span>
|
||||
</button>
|
||||
<button class="bg-darkbg rounded-lg p-4 flex flex-col hover:bg-selected transition-colors relative lg:w-96 w-full items-start text-start" on:click={() => {
|
||||
<button class="bg-darkbg rounded-lg p-4 flex flex-col hover:bg-selected transition-colors relative lg:w-96 w-full items-start text-start" onclick={() => {
|
||||
openURL("https://risuai.net")
|
||||
}}>
|
||||
<h2 class="text-xl">
|
||||
@@ -69,7 +69,7 @@
|
||||
See the official website for the project.
|
||||
</span>
|
||||
</button>
|
||||
<button class="bg-darkbg rounded-lg p-4 flex flex-col hover:bg-selected transition-colors relative lg:w-96 w-full items-start text-start" on:click={() => {
|
||||
<button class="bg-darkbg rounded-lg p-4 flex flex-col hover:bg-selected transition-colors relative lg:w-96 w-full items-start text-start" onclick={() => {
|
||||
openURL("https://github.com/kwaroran/RisuAI")
|
||||
}}>
|
||||
<h2 class="text-xl">Github</h2>
|
||||
@@ -77,7 +77,7 @@
|
||||
View the source code and contribute to the project.
|
||||
</span>
|
||||
</button>
|
||||
<button class="bg-darkbg rounded-lg p-4 flex flex-col hover:bg-selected transition-colors relative lg:w-96 w-full items-start text-start" on:click={() => {
|
||||
<button class="bg-darkbg rounded-lg p-4 flex flex-col hover:bg-selected transition-colors relative lg:w-96 w-full items-start text-start" onclick={() => {
|
||||
openURL("mailto:support@risuai.net")
|
||||
}}>
|
||||
<h2 class="text-xl">Email</h2>
|
||||
@@ -89,7 +89,7 @@
|
||||
|
||||
{:else}
|
||||
<div class="flex items-center mt-4">
|
||||
<button class="mr-2 text-textcolor2 hover:text-green-500" on:click={() => ($OpenRealmStore = false)}>
|
||||
<button class="mr-2 text-textcolor2 hover:text-green-500" onclick={() => ($OpenRealmStore = false)}>
|
||||
<ArrowLeft/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { stopPropagation } from 'svelte/legacy';
|
||||
import { DataBase } from "src/ts/storage/database";
|
||||
import { getHordeModels } from "src/ts/horde/getModels";
|
||||
import Arcodion from "./Arcodion.svelte";
|
||||
@@ -9,9 +10,16 @@
|
||||
import {open} from '@tauri-apps/plugin-dialog'
|
||||
import { getModelName } from "src/ts/model/names";
|
||||
|
||||
export let value = ""
|
||||
export let onChange: (v:string) => void = (v) => {}
|
||||
let openOptions = false
|
||||
interface Props {
|
||||
value?: string;
|
||||
onChange?: (v:string) => void;
|
||||
onclick?: (event: MouseEvent & {
|
||||
currentTarget: EventTarget & HTMLDivElement;
|
||||
}) => any
|
||||
}
|
||||
|
||||
let { value = $bindable(""), onChange = (v) => {}, onclick }: Props = $props();
|
||||
let openOptions = $state(false)
|
||||
|
||||
function changeModel(name:string){
|
||||
value = name
|
||||
@@ -19,67 +27,70 @@
|
||||
onChange(name)
|
||||
}
|
||||
|
||||
let showUnrec = false
|
||||
let showUnrec = $state(false)
|
||||
</script>
|
||||
|
||||
{#if openOptions}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div class="fixed top-0 w-full h-full left-0 bg-black bg-opacity-50 z-50 flex justify-center items-center" on:click={() => {
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<div class="fixed top-0 w-full h-full left-0 bg-black bg-opacity-50 z-50 flex justify-center items-center" role="button" tabindex="0" onclick={() => {
|
||||
openOptions = false
|
||||
}}>
|
||||
<div class="w-96 max-w-full max-h-full overflow-y-auto overflow-x-hidden bg-bgcolor p-4 flex flex-col" on:click|stopPropagation>
|
||||
<div class="w-96 max-w-full max-h-full overflow-y-auto overflow-x-hidden bg-bgcolor p-4 flex flex-col" role="button" tabindex="0" onclick={(e)=>{
|
||||
e.stopPropagation()
|
||||
onclick?.(e)
|
||||
}}>
|
||||
<h1 class="font-bold text-xl">{language.model}
|
||||
</h1>
|
||||
<div class="border-t-1 border-y-selected mt-1 mb-1"></div>
|
||||
<Arcodion name="OpenAI GPT">
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt35')}}>GPT-3.5 Turbo</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('instructgpt35')}}>GPT-3.5 Instruct</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt4_turbo')}}>GPT-4 Turbo</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt4o')}}>GPT-4o</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt4om')}}>GPT-4o Mini</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt35')}}>GPT-3.5 Turbo</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('instructgpt35')}}>GPT-3.5 Instruct</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt4_turbo')}}>GPT-4 Turbo</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt4o')}}>GPT-4o</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt4om')}}>GPT-4o Mini</button>
|
||||
{#if showUnrec}
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt4')}}>GPT-4 (Old)</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt4_32k')}}>GPT-4 32K (Old)</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt35_16k')}}>GPT-3.5 Turbo 16K</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt4_0314')}}>GPT-4 0314</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt4_0613')}}>GPT-4 0613</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt4_32k_0613')}}>GPT-4 32K 0613</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt4_1106')}}>GPT-4 Turbo 1106</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt35_0125')}}>GPT-3.5 Turbo 0125</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt35_1106')}}>GPT-3.5 Turbo 1106</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt35_0613')}}>GPT-3.5 Turbo 0613</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt35_16k_0613')}}>GPT-3.5 Turbo 16K 0613</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt35_0301')}}>GPT-3.5 Turbo 0301</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt4_0125')}}>GPT-4 Turbo 0125</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gptvi4_1106')}}>GPT-4 Turbo 1106 Vision</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt4_turbo_20240409')}}>GPT-4 Turbo 20240409</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt4o-2024-05-13')}}>GPT-4o 20240513</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt4o-2024-08-06')}}>GPT-4o 20240806</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt4o-chatgpt')}}>GPT-4o ChatGPT</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt4o1-preview')}}>o1 Preview</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('gpt4o1-mini')}}>o1 Mini</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt4')}}>GPT-4 (Old)</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt4_32k')}}>GPT-4 32K (Old)</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt35_16k')}}>GPT-3.5 Turbo 16K</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt4_0314')}}>GPT-4 0314</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt4_0613')}}>GPT-4 0613</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt4_32k_0613')}}>GPT-4 32K 0613</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt4_1106')}}>GPT-4 Turbo 1106</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt35_0125')}}>GPT-3.5 Turbo 0125</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt35_1106')}}>GPT-3.5 Turbo 1106</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt35_0613')}}>GPT-3.5 Turbo 0613</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt35_16k_0613')}}>GPT-3.5 Turbo 16K 0613</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt35_0301')}}>GPT-3.5 Turbo 0301</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt4_0125')}}>GPT-4 Turbo 0125</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gptvi4_1106')}}>GPT-4 Turbo 1106 Vision</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt4_turbo_20240409')}}>GPT-4 Turbo 20240409</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt4o-2024-05-13')}}>GPT-4o 20240513</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt4o-2024-08-06')}}>GPT-4o 20240806</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt4o-chatgpt')}}>GPT-4o ChatGPT</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt4o1-preview')}}>o1 Preview</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('gpt4o1-mini')}}>o1 Mini</button>
|
||||
{/if}
|
||||
</Arcodion>
|
||||
<Arcodion name="Anthropic Claude">
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('claude-3-5-sonnet-20240620')}}>Claude 3.5 Sonnet (20240620)</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('claude-3-haiku-20240307')}}>Claude 3 Haiku (20240307)</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('claude-3-5-sonnet-20240620')}}>Claude 3.5 Sonnet (20240620)</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('claude-3-haiku-20240307')}}>Claude 3 Haiku (20240307)</button>
|
||||
{#if showUnrec}
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('claude-3-opus-20240229')}}>Claude 3 Opus (20240229)</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('claude-3-sonnet-20240229')}}>Claude 3 Sonnet (20240229)</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('claude-2.1')}}>claude-2.1</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('claude-2')}}>claude-2</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('claude-2-100k')}}>claude-2-100k</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('claude-v1')}}>claude-v1</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('claude-v1-100k')}}>claude-v1-100k</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('claude-instant-v1')}}>claude-instant-v1</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('claude-instant-v1-100k')}}>claude-instant-v1-100k</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('claude-1.2')}}>claude-v1.2</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('claude-1.0')}}>claude-v1.0</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('claude-3-opus-20240229')}}>Claude 3 Opus (20240229)</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('claude-3-sonnet-20240229')}}>Claude 3 Sonnet (20240229)</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('claude-2.1')}}>claude-2.1</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('claude-2')}}>claude-2</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('claude-2-100k')}}>claude-2-100k</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('claude-v1')}}>claude-v1</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('claude-v1-100k')}}>claude-v1-100k</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('claude-instant-v1')}}>claude-instant-v1</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('claude-instant-v1-100k')}}>claude-instant-v1-100k</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('claude-1.2')}}>claude-v1.2</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('claude-1.0')}}>claude-v1.0</button>
|
||||
{/if}
|
||||
</Arcodion>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('reverse_proxy')}}>Custom (OpenAI-compatible)</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('reverse_proxy')}}>Custom (OpenAI-compatible)</button>
|
||||
{#if $DataBase.tpo && isTauri}
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={async () => {
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={async () => {
|
||||
const selected = await open({
|
||||
filters: [{
|
||||
name: 'Model File',
|
||||
@@ -91,84 +102,84 @@
|
||||
}
|
||||
}}>Local GGUF Model <Help key="experimental"/> </button>
|
||||
{/if}
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('ooba')}}>Oobabooga</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('ooba')}}>Oobabooga</button>
|
||||
{#if showUnrec}
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('textgen_webui')}}>Oobabooga Legacy</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('textgen_webui')}}>Oobabooga Legacy</button>
|
||||
{/if}
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('mancer')}}>Mancer</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('openrouter')}}>OpenRouter</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('mancer')}}>Mancer</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('openrouter')}}>OpenRouter</button>
|
||||
<Arcodion name="Mistral API">
|
||||
{#if showUnrec}
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('mistral-small-latest')}}>Mistral Small</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('mistral-medium-latest')}}>Mistral Medium</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('mistral-small-latest')}}>Mistral Small</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('mistral-medium-latest')}}>Mistral Medium</button>
|
||||
{/if}
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('open-mistral-nemo')}}>Mistral Nemo</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('mistral-large-latest')}}>Mistral Large</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('open-mistral-nemo')}}>Mistral Nemo</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('mistral-large-latest')}}>Mistral Large</button>
|
||||
</Arcodion>
|
||||
<Arcodion name="Google Gemini">
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('gemini-1.5-pro-exp-0827')}}>Gemini Pro 1.5 0827</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('gemini-1.5-pro-002')}}>Gemini Pro 1.5 002</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('gemini-1.5-pro-latest')}}>Gemini Pro 1.5</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('gemini-1.5-flash')}}>Gemini Flash 1.5</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('gemini-pro')}}>Gemini Pro</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('gemini-pro-vision')}}>Gemini Pro Vision</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('gemini-ultra')}}>Gemini Ultra</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('gemini-ultra-vision')}}>Gemini Ultra Vision</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('gemini-1.5-pro-exp-0827')}}>Gemini Pro 1.5 0827</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('gemini-1.5-pro-002')}}>Gemini Pro 1.5 002</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('gemini-1.5-pro-latest')}}>Gemini Pro 1.5</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('gemini-1.5-flash')}}>Gemini Flash 1.5</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('gemini-pro')}}>Gemini Pro</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('gemini-pro-vision')}}>Gemini Pro Vision</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('gemini-ultra')}}>Gemini Ultra</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('gemini-ultra-vision')}}>Gemini Ultra Vision</button>
|
||||
</Arcodion>
|
||||
{#if showUnrec}
|
||||
<Arcodion name="Google Palm2">
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('palm2')}}>Bison</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('palm2_unicorn')}}>Unicorn</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('palm2')}}>Bison</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('palm2_unicorn')}}>Unicorn</button>
|
||||
</Arcodion>
|
||||
{/if}
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('kobold')}}>Kobold</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('kobold')}}>Kobold</button>
|
||||
<Arcodion name="Novellist">
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('novellist')}}>SuperTrin</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('novellist_damsel')}}>Damsel</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('novellist')}}>SuperTrin</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('novellist_damsel')}}>Damsel</button>
|
||||
</Arcodion>
|
||||
<Arcodion name="Cohere">
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('cohere-command-r')}}>Command R</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('cohere-command-r-plus')}}>Command R Plus</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('cohere-command-r-08-2024')}}>Command R 08-2024</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('cohere-command-r-03-2024')}}>Command R 03-2024</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('cohere-command-r-plus-08-2024')}}>Command R Plus 08-2024</button>
|
||||
<button class="p-2 hover:text-green-500" on:click={() => {changeModel('cohere-command-r-plus-04-2024')}}>Command R Plus 04-2024</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('cohere-command-r')}}>Command R</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('cohere-command-r-plus')}}>Command R Plus</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('cohere-command-r-08-2024')}}>Command R 08-2024</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('cohere-command-r-03-2024')}}>Command R 03-2024</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('cohere-command-r-plus-08-2024')}}>Command R Plus 08-2024</button>
|
||||
<button class="p-2 hover:text-green-500" onclick={() => {changeModel('cohere-command-r-plus-04-2024')}}>Command R Plus 04-2024</button>
|
||||
</Arcodion>
|
||||
<Arcodion name="NovelAI">
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('novelai')}}>NovelAI Clio</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('novelai_kayra')}}>NovelAI Kayra</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('novelai')}}>NovelAI Clio</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('novelai_kayra')}}>NovelAI Kayra</button>
|
||||
</Arcodion>
|
||||
<Arcodion name="AI21">
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('jamba-1.5-large')}}>Jamba 1.5 Large</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('jamba-1.5-medium')}}>Jamba 1.5 Medium</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('jamba-1.5-large')}}>Jamba 1.5 Large</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('jamba-1.5-medium')}}>Jamba 1.5 Medium</button>
|
||||
</Arcodion>
|
||||
<Arcodion name="Horde">
|
||||
{#await getHordeModels()}
|
||||
<button class="p-2">Loading...</button>
|
||||
{:then models}
|
||||
<button on:click={() => {changeModel("horde:::" + 'auto')}} class="p-2 hover:text-green-500">
|
||||
<button onclick={() => {changeModel("horde:::" + 'auto')}} class="p-2 hover:text-green-500">
|
||||
Auto Model
|
||||
<br><span class="text-textcolor2 text-sm">Performace: Auto</span>
|
||||
</button>
|
||||
{#each models as model}
|
||||
<button on:click={() => {changeModel("horde:::" + model.name)}} class="p-2 hover:text-green-500">
|
||||
<button onclick={() => {changeModel("horde:::" + model.name)}} class="p-2 hover:text-green-500">
|
||||
{model.name.trim()}
|
||||
<br><span class="text-textcolor2 text-sm">Performace: {model.performance.toFixed(1)}</span>
|
||||
</button>
|
||||
{/each}
|
||||
{/await}
|
||||
</Arcodion>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('ollama-hosted')}}>OLlama</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('ollama-hosted')}}>OLlama</button>
|
||||
{#if showUnrec}
|
||||
<Arcodion name="WebLLM Local">
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('hf:::Xenova/opt-350m')}}>opt-350m</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('hf:::Xenova/tiny-random-mistral')}}>tiny-random-mistral</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('hf:::Xenova/gpt2-large-conversational')}}>gpt2-large-conversational</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('hf:::Xenova/opt-350m')}}>opt-350m</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('hf:::Xenova/tiny-random-mistral')}}>tiny-random-mistral</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('hf:::Xenova/gpt2-large-conversational')}}>gpt2-large-conversational</button>
|
||||
</Arcodion>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" on:click={() => {changeModel('risullm-proto')}}>RisuAI LLM (Prototype)</button>
|
||||
<button class="hover:bg-selected px-6 py-2 text-lg" onclick={() => {changeModel('risullm-proto')}}>RisuAI LLM (Prototype)</button>
|
||||
{/if}
|
||||
{#if $DataBase.plugins.length > 0}
|
||||
<button on:click={() => {changeModel('custom')}} class="hover:bg-selected px-6 py-2 text-lg" >Plugin</button>
|
||||
<button onclick={() => {changeModel('custom')}} class="hover:bg-selected px-6 py-2 text-lg" >Plugin</button>
|
||||
{/if}
|
||||
<div class="text-textcolor2 text-xs">
|
||||
<CheckInput name={language.showUnrecommended} grayText bind:check={showUnrec}/>
|
||||
@@ -178,7 +189,7 @@
|
||||
|
||||
{/if}
|
||||
|
||||
<button on:click={() => {openOptions = true}}
|
||||
<button onclick={() => {openOptions = true}}
|
||||
class="mt-4 drop-shadow-lg p-3 flex justify-center items-center ml-2 mr-2 rounded-lg bg-darkbutton mb-4 border-darkborderc border">
|
||||
{getModelName(value)}
|
||||
</button>
|
||||
|
||||
@@ -9,10 +9,19 @@
|
||||
import { ArrowDown, ArrowUp, XIcon } from "lucide-svelte";
|
||||
import TextInput from "./GUI/TextInput.svelte";
|
||||
import { DataBase } from "src/ts/storage/database";
|
||||
export let promptItem:PromptItem
|
||||
export let onRemove:() => void = () => {}
|
||||
export let moveUp:() => void = () => {}
|
||||
export let moveDown:() => void = () => {}
|
||||
interface Props {
|
||||
promptItem: PromptItem;
|
||||
onRemove?: () => void;
|
||||
moveUp?: () => void;
|
||||
moveDown?: () => void;
|
||||
}
|
||||
|
||||
let {
|
||||
promptItem = $bindable(),
|
||||
onRemove = () => {},
|
||||
moveUp = () => {},
|
||||
moveDown = () => {}
|
||||
}: Props = $props();
|
||||
|
||||
const chatPromptChange = () => {
|
||||
const currentprompt = promptItem as PromptItemChat
|
||||
@@ -30,13 +39,13 @@
|
||||
|
||||
<div class="flex flex-col first:mt-0 mt-2 border border-selected p-4 rounded-md bg-darkbg">
|
||||
<span class="mb-2">
|
||||
<button class="float-right" on:click={onRemove}><XIcon /></button>
|
||||
<button class="float-right" on:click={moveDown}><ArrowDown /></button>
|
||||
<button class="float-right" on:click={moveUp}><ArrowUp /></button>
|
||||
<button class="float-right" onclick={onRemove}><XIcon /></button>
|
||||
<button class="float-right" onclick={moveDown}><ArrowDown /></button>
|
||||
<button class="float-right" onclick={moveUp}><ArrowUp /></button>
|
||||
</span>
|
||||
<span>{language.type}
|
||||
</span>
|
||||
<SelectInput bind:value={promptItem.type} on:change={() => {
|
||||
<SelectInput bind:value={promptItem.type} onchange={() => {
|
||||
if(promptItem.type === 'plain' || promptItem.type === 'jailbreak' || promptItem.type === 'cot'){
|
||||
promptItem.text = ""
|
||||
promptItem.role = "system"
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
import { alertMd } from "src/ts/alert";
|
||||
import { shareRealmCardData } from "src/ts/realm";
|
||||
import { DataBase, downloadPreset } from "src/ts/storage/database";
|
||||
import { CurrentCharacter, ShowRealmFrameStore } from "src/ts/stores";
|
||||
import { selectedCharID, ShowRealmFrameStore } from "src/ts/stores";
|
||||
import { sleep } from "src/ts/util";
|
||||
import { onDestroy, onMount } from "svelte";
|
||||
|
||||
const close = () => {
|
||||
$ShowRealmFrameStore = ''
|
||||
}
|
||||
let iframe: HTMLIFrameElement = null
|
||||
let iframe: HTMLIFrameElement = $state(null)
|
||||
const tk = $DataBase?.account?.token;
|
||||
const id = $DataBase?.account?.id
|
||||
let loadingStage = 0
|
||||
let loadingStage = $state(0)
|
||||
let pongGot = false
|
||||
|
||||
const pmfunc = (e:MessageEvent) => {
|
||||
@@ -30,9 +30,9 @@
|
||||
if($ShowRealmFrameStore.startsWith('preset') || $ShowRealmFrameStore.startsWith('module')){
|
||||
//TODO, add preset edit
|
||||
}
|
||||
else if($CurrentCharacter.type === 'character'){
|
||||
else if($DataBase.characters[$selectedCharID].type === 'character'){
|
||||
loadingStage = 0
|
||||
$CurrentCharacter.realmId = e.data.id
|
||||
$DataBase.characters[$selectedCharID].realmId = e.data.id
|
||||
}
|
||||
close()
|
||||
}
|
||||
@@ -96,8 +96,8 @@
|
||||
if($ShowRealmFrameStore.startsWith('preset') || $ShowRealmFrameStore.startsWith('module')){
|
||||
//TODO, add preset edit
|
||||
}
|
||||
else if($CurrentCharacter.type === 'character' && $CurrentCharacter.realmId){
|
||||
url += `&edit=${$CurrentCharacter.realmId}&edit-type=normal`
|
||||
else if($DataBase.characters[$selectedCharID].type === 'character' && $DataBase.characters[$selectedCharID].realmId){
|
||||
url += `&edit=${$DataBase.characters[$selectedCharID].realmId}&edit-type=normal`
|
||||
}
|
||||
url += '#noLayout'
|
||||
return url
|
||||
@@ -111,15 +111,15 @@
|
||||
<div class="top-0 left-0 z-50 fixed w-full h-full flex flex-col justify-center items-center text-textcolor bg-white">
|
||||
<div class="bg-darkbg border-b border-b-darkborderc w-full flex p-2">
|
||||
<h1 class="text-2xl font-bold max-w-full overflow-hidden whitespace-nowrap text-ellipsis">Upload to Realm</h1>
|
||||
<button class="text-textcolor text-lg hover:text-red-500 ml-auto" on:click={close}>×</button>
|
||||
<button class="text-textcolor text-lg hover:text-red-500 ml-auto" onclick={close}>×</button>
|
||||
</div>
|
||||
{#if loadingStage < 1}
|
||||
<div class="w-full flex justify-center items-center p-4 flex-1">
|
||||
<div class="loadmove"/>
|
||||
<div class="loadmove"></div>
|
||||
</div>
|
||||
{/if}
|
||||
<iframe bind:this={iframe}
|
||||
src={getUrl()}
|
||||
title="upload" class="w-full flex-1" class:hidden={loadingStage < 1}
|
||||
/>
|
||||
></iframe>
|
||||
</div>
|
||||
@@ -1,17 +1,23 @@
|
||||
<script lang="ts">
|
||||
import { stopPropagation } from 'svelte/legacy';
|
||||
|
||||
import { BookIcon, ImageIcon, SmileIcon } from "lucide-svelte";
|
||||
import { alertNormal } from "src/ts/alert";
|
||||
import { hubURL, type hubType } from "src/ts/characterCards";
|
||||
import { trimNonLatin } from "src/ts/storage/globalApi";
|
||||
import { parseMultilangString } from "src/ts/util";
|
||||
|
||||
export let onClick = () => {}
|
||||
export let chara:hubType
|
||||
interface Props {
|
||||
onClick?: any;
|
||||
chara: hubType;
|
||||
}
|
||||
|
||||
let { onClick = () => {}, chara }: Props = $props();
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<button class="bg-darkbg rounded-lg p-4 flex flex-col hover:bg-selected transition-colors relative lg:w-96 w-full items-start" on:click={onClick}>
|
||||
<button class="bg-darkbg rounded-lg p-4 flex flex-col hover:bg-selected transition-colors relative lg:w-96 w-full items-start" onclick={onClick}>
|
||||
<div class="flex gap-2 w-full">
|
||||
<img class="w-20 min-w-20 h-20 sm:h-28 sm:w-28 rounded-md object-top object-cover" alt={chara.name} src={`${hubURL}/resource/` + chara.img}>
|
||||
<div class="flex flex-col flex-grow min-w-0">
|
||||
@@ -29,13 +35,13 @@
|
||||
<div class="flex-grow"></div>
|
||||
<div class="flex flex-wrap w-full flex-row-reverse gap-1">
|
||||
{#if chara.hasEmotion}
|
||||
<button class="text-textcolor2 hover:text-green-500 transition-colors" on:click|stopPropagation={() => {alertNormal("This character includes emotion images")}}><SmileIcon /></button>
|
||||
<button class="text-textcolor2 hover:text-green-500 transition-colors" onclick={stopPropagation(() => {alertNormal("This character includes emotion images")})}><SmileIcon /></button>
|
||||
{/if}
|
||||
{#if chara.hasAsset}
|
||||
<button class="text-textcolor2 hover:text-green-500 transition-colors" on:click|stopPropagation={() => {alertNormal("This character includes additional assets")}}><ImageIcon /></button>
|
||||
<button class="text-textcolor2 hover:text-green-500 transition-colors" onclick={stopPropagation(() => {alertNormal("This character includes additional assets")})}><ImageIcon /></button>
|
||||
{/if}
|
||||
{#if chara.hasLore}
|
||||
<button class="text-textcolor2 hover:text-green-500 transition-colors" on:click|stopPropagation={() => {alertNormal("This character includes lorebook")}}><BookIcon /></button>
|
||||
<button class="text-textcolor2 hover:text-green-500 transition-colors" onclick={stopPropagation(() => {alertNormal("This character includes lorebook")})}><BookIcon /></button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,17 +1,23 @@
|
||||
<script lang="ts">
|
||||
import { stopPropagation } from 'svelte/legacy';
|
||||
|
||||
import { CCLicenseData } from "src/ts/creation/license";
|
||||
import { tooltip } from "src/ts/gui/tooltip";
|
||||
import { openURL } from "src/ts/storage/globalApi";
|
||||
|
||||
export let license = ""
|
||||
interface Props {
|
||||
license?: string;
|
||||
}
|
||||
|
||||
let { license = "" }: Props = $props();
|
||||
</script>
|
||||
|
||||
{#if Object.keys(CCLicenseData).includes(license)}
|
||||
<div class="w-full flex flex-row">
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div class="flex flex-wrap flex-row gap-1 mt-2 items-center cursor-pointer" use:tooltip={CCLicenseData[license][1] + ". The License only applys to the text."} on:click|stopPropagation={() => {
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<div class="flex flex-wrap flex-row gap-1 mt-2 items-center cursor-pointer" use:tooltip={CCLicenseData[license][1] + ". The License only applys to the text."} onclick={stopPropagation(() => {
|
||||
openURL(`https://creativecommons.org/licenses/${CCLicenseData[license][0]}/4.0/`)
|
||||
}}>
|
||||
})}>
|
||||
<img alt="creative commons" class="cc" src="https://i.creativecommons.org/l/{CCLicenseData[license][0]}/4.0/88x31.png" />
|
||||
<span class="text-textcolor2">
|
||||
Licensed with {CCLicenseData[license][2]}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { stopPropagation } from 'svelte/legacy';
|
||||
|
||||
import { downloadRisuHub, getRisuHub, hubAdditionalHTML, type hubType } from "src/ts/characterCards";
|
||||
import { ArrowLeft, ArrowRight, MenuIcon, SearchIcon, XIcon } from "lucide-svelte";
|
||||
import { alertInput } from "src/ts/alert";
|
||||
@@ -11,16 +13,16 @@
|
||||
import { googleBuild } from "src/ts/storage/globalApi";
|
||||
import { split } from "lodash";
|
||||
|
||||
let openedData:null|hubType = null
|
||||
let openedData:null|hubType = $state(null)
|
||||
|
||||
let charas:hubType[] = []
|
||||
let charas:hubType[] = $state([])
|
||||
|
||||
let page = 0
|
||||
let sort = ''
|
||||
let page = $state(0)
|
||||
let sort = $state('')
|
||||
|
||||
let search = ''
|
||||
let menuOpen = false
|
||||
let nsfw = false
|
||||
let search = $state('')
|
||||
let menuOpen = $state(false)
|
||||
let nsfw = $state(false)
|
||||
|
||||
async function getHub(){
|
||||
charas = await getRisuHub({
|
||||
@@ -39,7 +41,7 @@
|
||||
<div class="flex items-stretch w-2xl max-w-full">
|
||||
<input bind:value={search} class="peer focus:border-textcolor transition-colors outline-none text-textcolor p-2 min-w-0 border border-r-0 bg-transparent rounded-md rounded-r-none input-text text-xl flex-grow ml-4 border-darkborderc resize-none overflow-y-hidden overflow-x-hidden max-w-full">
|
||||
<button
|
||||
on:click={() => {
|
||||
onclick={() => {
|
||||
page = 0
|
||||
getHub()
|
||||
}}
|
||||
@@ -48,7 +50,7 @@
|
||||
<SearchIcon />
|
||||
</button>
|
||||
<button
|
||||
on:click={(e) => {
|
||||
onclick={(e) => {
|
||||
menuOpen = true
|
||||
}}
|
||||
class="peer-focus:border-textcolor mr-2 flex border-y border-r border-darkborderc justify-center items-center text-gray-100 p-3 rounded-r-md hover:bg-blue-500 transition-colors"
|
||||
@@ -60,14 +62,14 @@
|
||||
{#if $MobileGUI}
|
||||
<div class="ml-4 flex items-start ">
|
||||
<div class="p-2 flex mb-3 overflow-x-auto rounded-lg border-darkborderc border gap-2">
|
||||
<button on:click={() => {
|
||||
<button onclick={() => {
|
||||
nsfw = !nsfw
|
||||
getHub()
|
||||
}}>
|
||||
{nsfw ? 'NSFW' : 'SFW'}
|
||||
</button>
|
||||
<div class="h-full border-r border-r-selected"></div>
|
||||
<button on:click={() => {
|
||||
<button onclick={() => {
|
||||
switch(sort){
|
||||
case '':
|
||||
sort = 'trending'
|
||||
@@ -95,32 +97,32 @@
|
||||
</div>
|
||||
{:else}
|
||||
<div class="w-full p-1 flex mb-3 overflow-x-auto sm:justify-center">
|
||||
<button class="bg-darkbg p-2 rounded-lg ml-2 flex justify-center items-center hover:bg-selected transition-shadow" class:ring={nsfw} on:click={() => {
|
||||
<button class="bg-darkbg p-2 rounded-lg ml-2 flex justify-center items-center hover:bg-selected transition-shadow" class:ring={nsfw} onclick={() => {
|
||||
nsfw = !nsfw
|
||||
getHub()
|
||||
}}>
|
||||
NSFW
|
||||
</button>
|
||||
<div class="ml-2 mr-2 h-full border-r border-r-selected"></div>
|
||||
<button class="bg-darkbg p-2 rounded-lg ml-2 flex justify-center items-center hover:bg-selected transition-shadow" class:ring={sort === ''} on:click={() => {
|
||||
<button class="bg-darkbg p-2 rounded-lg ml-2 flex justify-center items-center hover:bg-selected transition-shadow" class:ring={sort === ''} onclick={() => {
|
||||
sort = ''
|
||||
getHub()
|
||||
}}>
|
||||
{language.recent}
|
||||
</button>
|
||||
<button class="bg-darkbg p-2 rounded-lg ml-2 flex justify-center items-center hover:bg-selected transition-shadow" class:ring={sort === 'trending'} on:click={() => {
|
||||
<button class="bg-darkbg p-2 rounded-lg ml-2 flex justify-center items-center hover:bg-selected transition-shadow" class:ring={sort === 'trending'} onclick={() => {
|
||||
sort = 'trending'
|
||||
getHub()
|
||||
}}>
|
||||
{language.trending}
|
||||
</button>
|
||||
<button class="bg-darkbg p-2 rounded-lg ml-2 flex justify-center items-center hover:bg-selected transition-shadow" class:ring={sort === 'downloads'} on:click={() => {
|
||||
<button class="bg-darkbg p-2 rounded-lg ml-2 flex justify-center items-center hover:bg-selected transition-shadow" class:ring={sort === 'downloads'} onclick={() => {
|
||||
sort = 'downloads'
|
||||
getHub()
|
||||
}}>
|
||||
{language.downloads}
|
||||
</button>
|
||||
<button class="bg-darkbg p-2 rounded-lg ml-2 flex justify-center items-center hover:bg-selected transition-shadow min-w-0 max-w-full" class:ring={sort === 'random'} on:click={() => {
|
||||
<button class="bg-darkbg p-2 rounded-lg ml-2 flex justify-center items-center hover:bg-selected transition-shadow min-w-0 max-w-full" class:ring={sort === 'random'} onclick={() => {
|
||||
sort = 'random'
|
||||
getHub()
|
||||
}}>
|
||||
@@ -139,7 +141,7 @@
|
||||
{#if sort !== 'random'}
|
||||
<div class="w-full flex justify-center">
|
||||
<div class="flex">
|
||||
<button class="bg-darkbg h-14 w-14 min-w-14 rounded-lg flex justify-center items-center hover:ring transition-shadow" on:click={() => {
|
||||
<button class="bg-darkbg h-14 w-14 min-w-14 rounded-lg flex justify-center items-center hover:ring transition-shadow" onclick={() => {
|
||||
if(page > 0){
|
||||
page -= 1
|
||||
getHub()
|
||||
@@ -150,7 +152,7 @@
|
||||
<button class="bg-darkbg h-14 w-14 min-w-14 rounded-lg ml-2 flex justify-center items-center transition-shadow">
|
||||
<span>{page + 1}</span>
|
||||
</button>
|
||||
<button class="bg-darkbg h-14 w-14 min-w-14 rounded-lg ml-2 flex justify-center items-center hover:ring transition-shadow" on:click={() => {
|
||||
<button class="bg-darkbg h-14 w-14 min-w-14 rounded-lg ml-2 flex justify-center items-center hover:ring transition-shadow" onclick={() => {
|
||||
page += 1
|
||||
getHub()
|
||||
}}>
|
||||
@@ -166,8 +168,8 @@
|
||||
|
||||
|
||||
{#if menuOpen}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div class="top-0 left-0 z-50 fixed w-full h-full bg-black bg-opacity-50 flex justify-center items-center" on:click={() => {
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<div class="top-0 left-0 z-50 fixed w-full h-full bg-black bg-opacity-50 flex justify-center items-center" onclick={() => {
|
||||
menuOpen = false
|
||||
}}>
|
||||
<div class="max-w-full bg-darkbg rounded-md flex flex-col gap-4 overflow-y-auto p-4">
|
||||
@@ -175,12 +177,12 @@
|
||||
<span>
|
||||
Menu
|
||||
</span>
|
||||
<button class="float-right text-textcolor2 hover:text-green-500" on:click={() => {menuOpen = false}}>
|
||||
<button class="float-right text-textcolor2 hover:text-green-500" onclick={() => {menuOpen = false}}>
|
||||
<XIcon />
|
||||
</button>
|
||||
</h1>
|
||||
<div class=" mt-2 w-full border-t-2 border-t-bgcolor"></div>
|
||||
<button class="w-full hover:bg-selected p-4" on:click|stopPropagation={async () => {
|
||||
<button class="w-full hover:bg-selected p-4" onclick={stopPropagation(async () => {
|
||||
menuOpen = false
|
||||
const input = await alertInput('Input URL or ID')
|
||||
if(input.startsWith("http")){
|
||||
@@ -194,7 +196,7 @@
|
||||
const id = input.split("?").at(-1)
|
||||
downloadRisuHub(id)
|
||||
|
||||
}}>Import Character from URL or ID</button>
|
||||
})}>Import Character from URL or ID</button>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { stopPropagation } from 'svelte/legacy';
|
||||
|
||||
import { BookIcon, FlagIcon, ImageIcon, PaperclipIcon, SmileIcon, TrashIcon } from "lucide-svelte";
|
||||
import { language } from "src/lang";
|
||||
import { alertConfirm, alertInput, alertNormal } from "src/ts/alert";
|
||||
@@ -9,13 +11,17 @@
|
||||
import MultiLangDisplay from "../GUI/MultiLangDisplay.svelte";
|
||||
import { tooltip } from "src/ts/gui/tooltip";
|
||||
|
||||
export let openedData:hubType
|
||||
interface Props {
|
||||
openedData: hubType;
|
||||
}
|
||||
|
||||
let { openedData = $bindable() }: Props = $props();
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div class="top-0 left-0 z-50 fixed w-full h-full bg-black bg-opacity-50 flex justify-center items-center text-textcolor" on:click={() => {
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<div class="top-0 left-0 z-50 fixed w-full h-full bg-black bg-opacity-50 flex justify-center items-center text-textcolor" onclick={() => {
|
||||
openedData = null
|
||||
}}>
|
||||
<div class="p-6 max-w-full bg-darkbg rounded-md flex flex-col gap-4 w-2xl overflow-y-auto max-h-full">
|
||||
@@ -25,7 +31,7 @@
|
||||
<span class="text-borderc">Made by {openedData.authorname}</span>
|
||||
{/if}
|
||||
{#if openedData.original}
|
||||
<button class="text-blue-400 text-start" on:click={() => {
|
||||
<button class="text-blue-400 text-start" onclick={() => {
|
||||
const original = openedData.original
|
||||
openedData = null
|
||||
getRealmInfo(original)
|
||||
@@ -48,19 +54,19 @@
|
||||
</span>
|
||||
<div class="border-l-selected border-l ml-1 mr-1"></div>
|
||||
{#if openedData.hasEmotion}
|
||||
<button class="text-textcolor2 hover:text-green-500 transition-colors" on:click|stopPropagation={() => {alertNormal("This character includes emotion images")}}><SmileIcon /></button>
|
||||
<button class="text-textcolor2 hover:text-green-500 transition-colors" onclick={stopPropagation(() => {alertNormal("This character includes emotion images")})}><SmileIcon /></button>
|
||||
{/if}
|
||||
{#if openedData.hasAsset}
|
||||
<button class="text-textcolor2 hover:text-green-500 transition-colors" on:click|stopPropagation={() => {alertNormal("This character includes additional Assets")}}><ImageIcon /></button>
|
||||
<button class="text-textcolor2 hover:text-green-500 transition-colors" onclick={stopPropagation(() => {alertNormal("This character includes additional Assets")})}><ImageIcon /></button>
|
||||
{/if}
|
||||
{#if openedData.hasLore}
|
||||
<button class="text-textcolor2 hover:text-green-500 transition-colors" on:click|stopPropagation={() => {alertNormal("This character includes lorebook")}}><BookIcon /></button>
|
||||
<button class="text-textcolor2 hover:text-green-500 transition-colors" onclick={stopPropagation(() => {alertNormal("This character includes lorebook")})}><BookIcon /></button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="flex flex-row-reverse gap-2">
|
||||
<button class="text-textcolor2 hover:text-red-500" on:click|stopPropagation={async () => {
|
||||
<button class="text-textcolor2 hover:text-red-500" onclick={stopPropagation(async () => {
|
||||
const conf = await alertConfirm('Report this character?')
|
||||
if(conf){
|
||||
const report = await alertInput('Write a report text that would be sent to the admin (for copywrite issues, use email)')
|
||||
@@ -73,11 +79,11 @@
|
||||
})
|
||||
alertNormal(await da.text())
|
||||
}
|
||||
}}>
|
||||
})}>
|
||||
<FlagIcon />
|
||||
</button>
|
||||
{#if ($DataBase.account?.token?.split('-') ?? [])[1] === openedData.creator}
|
||||
<button class="text-textcolor2 hover:text-red-500" on:click|stopPropagation={async () => {
|
||||
<button class="text-textcolor2 hover:text-red-500" onclick={stopPropagation(async () => {
|
||||
const conf = await alertConfirm('Do you want to remove this character from Realm?')
|
||||
if(conf){
|
||||
const da = await fetch(hubURL + '/hub/remove', {
|
||||
@@ -89,17 +95,17 @@
|
||||
})
|
||||
alertNormal(await da.text())
|
||||
}
|
||||
}}>
|
||||
})}>
|
||||
<TrashIcon />
|
||||
</button>
|
||||
{/if}
|
||||
<button class="text-textcolor2 hover:text-green-500" on:click|stopPropagation={async () => {
|
||||
<button class="text-textcolor2 hover:text-green-500" onclick={stopPropagation(async () => {
|
||||
await navigator.clipboard.writeText(`https://realm.risuai.net/character/${openedData.id}`)
|
||||
alertNormal(language.clipboardSuccess)
|
||||
}}>
|
||||
})}>
|
||||
<PaperclipIcon />
|
||||
</button>
|
||||
<button class="bg-selected hover:ring flex-grow p-2 font-bold rounded-md mr-2" on:click={() => {
|
||||
<button class="bg-selected hover:ring flex-grow p-2 font-bold rounded-md mr-2" onclick={() => {
|
||||
downloadRisuHub(openedData.id)
|
||||
openedData = null
|
||||
}}>
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div class="fixed top-0 left-0 h-full w-full bg-black bg-opacity-50 flex flex-col z-50 items-center justify-center" on:click={close}>
|
||||
<div class="bg-darkbg rounded-md p-4 max-w-full flex flex-col w-2xl max-h-full overflow-y-auto" on:click|stopPropagation>
|
||||
<!-- svelte-ignore a11y_click_events_have_key_events -->
|
||||
<div class="fixed top-0 left-0 h-full w-full bg-black bg-opacity-50 flex flex-col z-50 items-center justify-center" role="button" tabindex="0" onclick={close}>
|
||||
<div class="bg-darkbg rounded-md p-4 max-w-full flex flex-col w-2xl max-h-full overflow-y-auto" role="button" tabindex="0" onclick={(e)=>{
|
||||
e.stopPropagation()
|
||||
onclick?.(e)
|
||||
}}>
|
||||
|
||||
{#if !$DataBase.account}
|
||||
<span class="font-bold text-2xl w-full">You must login to Risu Account upload to RisuRealm</span>
|
||||
<span class="text-textcolor2">You can login in app settings 🡲 account</span>
|
||||
<button on:click={async () => {
|
||||
<button onclick={async () => {
|
||||
close()
|
||||
}} class="text-textcolor mt-2 text-lg bg-transparent border-solid border-1 border-borderc p-4 hover:bg-green-800 transition-colors cursor-pointer">OK</button>
|
||||
|
||||
@@ -14,7 +17,7 @@
|
||||
<span>
|
||||
Share {char.name} to {language.hub}
|
||||
</span>
|
||||
<button class="float-right text-textcolor2 hover:text-green-500" on:click={close}>
|
||||
<button class="float-right text-textcolor2 hover:text-green-500" onclick={close}>
|
||||
<XIcon />
|
||||
</button>
|
||||
</h1>
|
||||
@@ -28,13 +31,13 @@
|
||||
<MultiLangInput bind:value={char.creatorNotes} />
|
||||
<span class="text-textcolor">{language.tags}</span>
|
||||
<span class="text-textcolor2 text-sm">Tags to search your character easily. latin alphabets only. seperate by comma.</span>
|
||||
<TextInput placeholder="" bind:value={tags} on:input={() => {
|
||||
<TextInput placeholder="" bind:value={tags} oninput={() => {
|
||||
tags = tags.replace(/[^a-zA-Z,\-]/g, '').toLocaleLowerCase().replace(/ /g, '')
|
||||
}} />
|
||||
|
||||
<div class="peer-focus:block hidden hover:block flex-wrap">
|
||||
{#each searchTagList(tags) as tag}
|
||||
<button class="text-textcolor2 text-sm p-2 border border-bgcolor" on:click={() => {
|
||||
<button class="text-textcolor2 text-sm p-2 border border-bgcolor" onclick={() => {
|
||||
const splited = tags.split(',').map(e => e.trim())
|
||||
splited[splited.length - 1] = tag
|
||||
tags = splited.join(',') + ','
|
||||
@@ -56,23 +59,23 @@
|
||||
{/if}
|
||||
{#if !char.realmId}
|
||||
<div class="flex items-center flex-wrap mt-4">
|
||||
<button class="bg-bgcolor p-2 rounded-lg" class:ring-1={!privateMode} on:click={() => {privateMode = false}}>🌏 Show Author ID</button>
|
||||
<button class="bg-bgcolor p-2 rounded-lg ml-2" class:ring-1={privateMode} on:click={() => {privateMode = true}}>🔒 Anonymized</button>
|
||||
<button class="bg-bgcolor p-2 rounded-lg" class:ring-1={!privateMode} onclick={() => {privateMode = false}}>🌏 Show Author ID</button>
|
||||
<button class="bg-bgcolor p-2 rounded-lg ml-2" class:ring-1={privateMode} onclick={() => {privateMode = true}}>🔒 Anonymized</button>
|
||||
</div>
|
||||
<div class="flex items-center flex-wrap mt-2">
|
||||
<button class="bg-bgcolor p-2 rounded-lg" class:ring-1={!nsfwMode} on:click={() => {nsfwMode = false}}>🎖️ Safe</button>
|
||||
<button class="bg-bgcolor p-2 rounded-lg ml-2" class:ring-1={nsfwMode} on:click={() => {nsfwMode = true}}>🔞 NSFW</button>
|
||||
<button class="bg-bgcolor p-2 rounded-lg" class:ring-1={!nsfwMode} onclick={() => {nsfwMode = false}}>🎖️ Safe</button>
|
||||
<button class="bg-bgcolor p-2 rounded-lg ml-2" class:ring-1={nsfwMode} onclick={() => {nsfwMode = true}}>🔞 NSFW</button>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="flex items-center flex-wrap mt-2">
|
||||
<button class="bg-bgcolor p-2 rounded-lg" class:ring-1={!update} on:click={() => {nsfwMode = false}}>🚀 Update</button>
|
||||
<button class="bg-bgcolor p-2 rounded-lg ml-2" class:ring-1={update} on:click={() => {nsfwMode = true}}>⭐ Upload Newly</button>
|
||||
<button class="bg-bgcolor p-2 rounded-lg" class:ring-1={!update} onclick={() => {nsfwMode = false}}>🚀 Update</button>
|
||||
<button class="bg-bgcolor p-2 rounded-lg ml-2" class:ring-1={update} onclick={() => {nsfwMode = true}}>⭐ Upload Newly</button>
|
||||
</div>
|
||||
{/if}
|
||||
{#if nsfwMode}
|
||||
<span class="text-textcolor2 text-sm">Grotesque Contents and non-adult characters with NSFW would be banned.</span>
|
||||
{/if}
|
||||
<Button on:click={async () => {
|
||||
<Button onclick={async () => {
|
||||
await sleep(1) // wait for the input to be updated
|
||||
const enNotes = creatorNotes.en
|
||||
const latin1 = /^[\x00-\xFF]*$/
|
||||
@@ -116,12 +119,19 @@
|
||||
import OptionInput from "../GUI/OptionInput.svelte";
|
||||
import { TagList, parseMultilangString, searchTagList, sleep } from "src/ts/util";
|
||||
import MultiLangInput from "../GUI/MultiLangInput.svelte";
|
||||
export let close = () => {}
|
||||
export let char:character
|
||||
let tags=""
|
||||
let privateMode = false
|
||||
let nsfwMode = false
|
||||
let license = ""
|
||||
interface Props {
|
||||
close?: any;
|
||||
char: character;
|
||||
onclick?: (event: MouseEvent & {
|
||||
currentTarget: EventTarget & HTMLDivElement;
|
||||
}) => any
|
||||
}
|
||||
|
||||
let { close = () => {}, char = $bindable(), onclick }: Props = $props();
|
||||
let tags=$state("")
|
||||
let privateMode = $state(false)
|
||||
let nsfwMode = $state(false)
|
||||
let license = $state("")
|
||||
let creatorNotes: {[code:string]:string} = parseMultilangString(char.creatorNotes)
|
||||
let update = false
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import { openURL } from "src/ts/storage/globalApi";
|
||||
import { sideBarStore } from "src/ts/stores";
|
||||
|
||||
let specialDay = ''
|
||||
let specialDay = $state('')
|
||||
const today = new Date()
|
||||
if (today.getMonth() === 11 && today.getDate() >= 19 && today.getDate() <= 25) {
|
||||
specialDay = 'christmas'
|
||||
@@ -29,11 +29,11 @@
|
||||
specialDay = 'midAutumn'
|
||||
}
|
||||
}
|
||||
let iconAnimation = 0
|
||||
let clicks = 0
|
||||
let score = 0
|
||||
let time = 20
|
||||
let miniGameStart = false
|
||||
let iconAnimation = $state(0)
|
||||
let clicks = $state(0)
|
||||
let score = $state(0)
|
||||
let time = $state(20)
|
||||
let miniGameStart = $state(false)
|
||||
|
||||
const onClick = () => {
|
||||
if(specialDay === 'newYear'){
|
||||
@@ -74,8 +74,8 @@ You've had:
|
||||
|
||||
</script>
|
||||
|
||||
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
|
||||
<h2 class="text-4xl text-textcolor mb-0 mt-6 font-black relative" class:text-bordered={specialDay === 'newYear'} on:click={onClick}>
|
||||
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
||||
<h2 class="text-4xl text-textcolor mb-0 mt-6 font-black relative" class:text-bordered={specialDay === 'newYear'} onclick={onClick}>
|
||||
{#if specialDay === 'midAutumn'}
|
||||
<span class="text-amber-400">🐉RisuAI🐉</span>
|
||||
{:else if specialDay === 'chuseok'}
|
||||
@@ -91,12 +91,12 @@ You've had:
|
||||
RisuAI
|
||||
{/if}
|
||||
{#if specialDay === 'christmas'}
|
||||
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
|
||||
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
||||
{#if clicks < 5}
|
||||
<img src="./santa.png" alt="santa" class="absolute logo-top"
|
||||
style:top={(-20 + iconAnimation).toFixed(0) + 'px'}
|
||||
style:right={'-30px'}
|
||||
on:click={async () => {
|
||||
onclick={async () => {
|
||||
iconAnimation = Math.random() * 300
|
||||
clicks++
|
||||
if(clicks === 5){
|
||||
@@ -107,7 +107,7 @@ You've had:
|
||||
{/if}
|
||||
{/if}
|
||||
{#if specialDay === 'anniversary'}
|
||||
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
|
||||
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
||||
{#if clicks < 5}
|
||||
<img src="./birthday.png" alt="birthday" class="absolute logo-top"
|
||||
style:top={(-28 + iconAnimation).toFixed(0) + 'px'}
|
||||
@@ -116,18 +116,18 @@ You've had:
|
||||
{/if}
|
||||
{/if}
|
||||
{#if specialDay === 'newYear'}
|
||||
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
|
||||
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
||||
<img src="./sun.webp" alt="sun" class="absolute -z-10"
|
||||
style:top={'-50px'}
|
||||
style:right={'0px'}
|
||||
on:click={onClick}
|
||||
onclick={onClick}
|
||||
>
|
||||
{/if}
|
||||
</h2>
|
||||
|
||||
{#if specialDay === 'anniversary'}
|
||||
<h1>
|
||||
<span class="text-2xl font-extralight italic text-amber-400 hover:text-amber-600 cursor-pointer transition" on:click={() => {
|
||||
<span class="text-2xl font-extralight italic text-amber-400 hover:text-amber-600 cursor-pointer transition" onclick={() => {
|
||||
openURL('https://risuai.net')
|
||||
}}>Happy 1st Anniversary!</span>
|
||||
</h1>
|
||||
@@ -136,11 +136,11 @@ You've had:
|
||||
<div class="bg-black w-full p-3 mt-4 mb-4 rounded-md max-w-2xl" id="minigame-div">
|
||||
<span class="font-semibold text-lg">Score: {score}</span><br>
|
||||
<span class="font-semibold text-lg">Time: {time.toFixed(0)}</span>
|
||||
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
|
||||
<!-- svelte-ignore a11y_no_noninteractive_element_interactions -->
|
||||
<img src="./santa.png" alt="santa"
|
||||
style:margin-left={iconAnimation + 'px'}
|
||||
class:grayscale={!miniGameStart}
|
||||
on:click={async () => {
|
||||
onclick={async () => {
|
||||
const miniGameDiv = document.getElementById('minigame-div')
|
||||
const max = miniGameDiv.clientWidth - 70
|
||||
iconAnimation = Math.random() * max
|
||||
|
||||
Reference in New Issue
Block a user