[feat] added license

This commit is contained in:
kwaroran
2023-07-19 22:01:23 +09:00
parent dfc27df7c7
commit 07f6117a01
13 changed files with 269 additions and 106 deletions

View File

@@ -8,6 +8,8 @@
import { User } from 'lucide-svelte';
import { hubURL } from 'src/ts/characterCards';
import TextInput from '../UI/GUI/TextInput.svelte';
import { openURL } from 'src/ts/storage/globalApi';
import Button from '../UI/GUI/Button.svelte';
let btn
let input = ''
@@ -56,49 +58,70 @@
{@html msg}
{/await}
</span>
{:else if $alertStore.type === 'tos'}
<!-- svelte-ignore a11y-missing-attribute -->
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="text-white">You should accept RisuRealm's <a class="text-green-600 hover:text-green-500 transition-colors duration-200 cursor-pointer" on:click={() => {
openURL('https://sv.risuai.xyz/hub/tos')
}}>Terms of Service</a> to continue</div>
{:else if $alertStore.type !== 'select'}
<span class="text-gray-300">{$alertStore.msg}</span>
{/if}
{#if $alertStore.type === 'ask'}
<div class="flex gap-2 w-full">
<button bind:this={btn} class="mt-4 border-borderc bg-transparent outline-none border-solid border-1 p-2 text-lg text-neutral-200 hover:bg-green-500 transition-colors flex-1 focus:border-3" on:click={() => {
<Button className="mt-4 flex-grow" on:click={() => {
alertStore.set({
type: 'none',
msg: 'yes'
})
}}>YES</button>
<button class="mt-4 border-borderc bg-transparent outline-none border-solid border-1 p-2 text-lg text-neutral-200 hover:bg-red-500 transition-colors focus:border-3 flex-1" on:click={() => {
}}>YES</Button>
<Button className="mt-4 flex-grow" on:click={() => {
alertStore.set({
type: 'none',
msg: 'no'
})
}}>NO</button>
}}>NO</Button>
</div>
{:else if $alertStore.type === 'tos'}
<div class="flex gap-2 w-full">
<Button className="mt-4 flex-grow" on:click={() => {
alertStore.set({
type: 'none',
msg: 'yes'
})
}}>Accept</Button>
<Button className="mt-4 flex-grow" on:click={() => {
alertStore.set({
type: 'none',
msg: 'no'
})
}}>Do not Accept</Button>
</div>
{:else if $alertStore.type === 'select'}
{#each $alertStore.msg.split('||') as n, i}
<button bind:this={btn} class="mt-4 border-borderc bg-transparent outline-none border-solid border-1 p-2 text-lg text-neutral-200 hover:bg-green-500 transition-colors focus:border-3" on:click={() => {
<Button className="mt-4" on:click={() => {
alertStore.set({
type: 'none',
msg: i.toString()
})
}}>{n}</button>
}}>{n}</Button>
{/each}
{:else if $alertStore.type === 'error' || $alertStore.type === 'normal' || $alertStore.type === 'markdown'}
<button bind:this={btn} class="mt-4 border-borderc bg-transparent outline-none border-solid border-1 p-2 text-lg text-neutral-200 hover:bg-green-500 transition-colors focus:border-3" on:click={() => {
<Button bind:this={btn} className="mt-4" on:click={() => {
alertStore.set({
type: 'none',
msg: ''
})
}}>OK</button>
}}>OK</Button>
{:else if $alertStore.type === 'input'}
<TextInput value="" id="alert-input" autocomplete="off"/>
<button bind:this={btn} class="mt-4 border-borderc bg-transparent outline-none border-solid border-1 p-2 text-lg text-neutral-200 hover:bg-green-500 transition-colors focus:border-3" on:click={() => {
<TextInput value="" id="alert-input" autocomplete="off" marginTop />
<Button className="mt-4" on:click={() => {
alertStore.set({
type: 'none',
//@ts-ignore
msg: document.querySelector('#alert-input')?.value
})
}}>OK</button>
}}>OK</Button>
{:else if $alertStore.type === 'login'}
<div class="fixed top-0 left-0 bg-black bg-opacity-50 w-full h-full flex justify-center items-center">
<iframe src={hubURL + '/hub/login'} title="login" class="w-full h-full">

View File

@@ -37,7 +37,7 @@
import { v4 } from "uuid";
import { checkCharOrder } from "src/ts/storage/globalApi";
import { doingChat } from "src/ts/process";
import { BotCreator } from "src/ts/creator/creator";
import { BotCreator } from "src/ts/copyright/creator";
import Button from "../UI/GUI/Button.svelte";
let openPresetList = false;
let sideBarMode = 0;

View File

@@ -7,6 +7,7 @@
class:px-4={padding}
class:py-2={padding}
class:mb-4={marginBottom}
class:mt-4={marginTop}
class:w-full={fullwidth}
class:h-full={fullh}
{autocomplete}
@@ -26,6 +27,7 @@
export let id:string = undefined
export let padding = true
export let marginBottom = false
export let marginTop = false
export let onInput = () => {}
export let fullwidth = false
export let fullh = false

View File

@@ -0,0 +1,30 @@
<script lang="ts">
import { CCLicenseData, tooltip } from "src/ts/copyright/license";
import { openURL } from "src/ts/storage/globalApi";
export let license = ""
</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]} on:click|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-gray-500">
Licensed with {license}
</span>
</div>
</div>
{/if}
<style>
.cc{
width: 88px;
height: 31px;
border-width: 0;
}
</style>

View File

@@ -7,6 +7,7 @@
import RisuHubIcon from "./RealmHubIcon.svelte";
import { DataBase } from "src/ts/storage/database";
import TextInput from "../GUI/TextInput.svelte";
import RealmPopUp from "./RealmPopUp.svelte";
let openedData:null|hubType = null
@@ -104,93 +105,11 @@
</div>
</div>
{#if openedData}
<!-- 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={() => {
openedData = null
}}>
<div class="p-6 max-w-full bg-darkbg rounded-md flex flex-col gap-4 w-2xl overflow-y-auto">
<div class="w-full flex flex-col">
<h1 class="text-2xl font-bold max-w-full overflow-hidden whitespace-nowrap text-ellipsis">{openedData.name}</h1>
<div class="flex justify-start gap-4 mt-4">
<img class="h-36 w-36 rounded-md object-top object-cover" alt={openedData.name} src={`${hubURL}/resource/` + openedData.img}>
<span class="text-gray-400 break-words text-base chattext prose prose-invert">
{#await parseMarkdownSafe(openedData.desc) then msg}
{@html msg}
{/await}
</span>
</div>
<div class="flex justify-start gap-2 mt-4">
{#each openedData.tags as tag, i}
<div class="text-xs p-1 text-blue-400">{tag}</div>
{/each}
</div>
<div class="flex flex-wrap w-full flex-row gap-1 mt-2">
<span class="text-gray-500">
{language.chatAssumed.replace('{}', openedData.download.toString())}
</span>
<div class="border-l-selected border-l ml-1 mr-1"></div>
{#if openedData.viewScreen === 'emotion'}
<button class="text-gray-500 hover:text-green-500 transition-colors" on:click|stopPropagation={() => {alertNormal("This character includes emotion images")}}><SmileIcon /></button>
{/if}
{#if openedData.hasLore}
<button class="text-gray-500 hover:text-green-500 transition-colors" on:click|stopPropagation={() => {alertNormal("This character includes lorebook")}}><BookIcon /></button>
{/if}
</div>
</div>
<div class="flex flex-row-reverse gap-2">
<button class="text-gray-400 hover:text-red-500" on:click|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')
const da = await fetch(hubURL + '/hub/report', {
method: "POST",
body: JSON.stringify({
id: openedData.id,
report: report
})
})
alertNormal(await da.text())
}
}}>
<FlagIcon />
</button>
{#if ($DataBase.account?.token?.split('-') ?? [])[1] === openedData.creator}
<button class="text-gray-400 hover:text-red-500" on:click|stopPropagation={async () => {
const conf = await alertConfirm('Do you want to remove this character from Realm?')
if(conf){
const da = await fetch(hubURL + '/hub/remove', {
method: "POST",
body: JSON.stringify({
id: openedData.id,
token: $DataBase.account?.token
})
})
alertNormal(await da.text())
}
}}>
<TrashIcon />
</button>
{/if}
<button class="text-gray-400 hover:text-green-500" on:click|stopPropagation={async () => {
await navigator.clipboard.writeText(`https://risuai.xyz/?realm=${openedData.id}`)
alertNormal("Copied to clipboard")
}}>
<PaperclipIcon />
</button>
<button class="bg-selected hover:ring flex-grow p-2 font-bold rounded-md mr-2" on:click={() => {
downloadRisuHub(openedData.id)
openedData = null
}}>
Download
</button>
</div>
</div>
</div>
<RealmPopUp bind:openedData={openedData} />
{/if}
{#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={() => {

View File

@@ -0,0 +1,98 @@
<script lang="ts">
import { BookIcon, FlagIcon, PaperclipIcon, SmileIcon, TrashIcon } from "lucide-svelte";
import { language } from "src/lang";
import { alertConfirm, alertInput, alertNormal } from "src/ts/alert";
import { hubURL, type hubType, downloadRisuHub } from "src/ts/characterCards";
import { parseMarkdownSafe } from "src/ts/parser";
import { DataBase } from "src/ts/storage/database";
import RealmLicense from "./RealmLicense.svelte";
export let openedData:hubType
</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" on:click={() => {
openedData = null
}}>
<div class="p-6 max-w-full bg-darkbg rounded-md flex flex-col gap-4 w-2xl overflow-y-auto">
<div class="w-full flex flex-col">
<h1 class="text-2xl font-bold max-w-full overflow-hidden whitespace-nowrap text-ellipsis">{openedData.name}</h1>
<div class="flex justify-start gap-4 mt-4">
<img class="h-36 w-36 rounded-md object-top object-cover" alt={openedData.name} src={`${hubURL}/resource/` + openedData.img}>
<span class="text-gray-400 break-words text-base chattext prose prose-invert">
{@html parseMarkdownSafe(openedData.desc)}
</span>
</div>
<RealmLicense license={openedData.license}/>
<div class="flex justify-start gap-2 mt-2">
{#each openedData.tags as tag, i}
<div class="text-xs p-1 text-blue-400">{tag}</div>
{/each}
</div>
<div class="flex flex-wrap w-full flex-row gap-1 mt-2">
<span class="text-gray-500">
{language.chatAssumed.replace('{}', openedData.download.toString())}
</span>
<div class="border-l-selected border-l ml-1 mr-1"></div>
{#if openedData.viewScreen === 'emotion'}
<button class="text-gray-500 hover:text-green-500 transition-colors" on:click|stopPropagation={() => {alertNormal("This character includes emotion images")}}><SmileIcon /></button>
{/if}
{#if openedData.hasLore}
<button class="text-gray-500 hover:text-green-500 transition-colors" on:click|stopPropagation={() => {alertNormal("This character includes lorebook")}}><BookIcon /></button>
{/if}
</div>
</div>
<div class="flex flex-row-reverse gap-2">
<button class="text-gray-400 hover:text-red-500" on:click|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')
const da = await fetch(hubURL + '/hub/report', {
method: "POST",
body: JSON.stringify({
id: openedData.id,
report: report
})
})
alertNormal(await da.text())
}
}}>
<FlagIcon />
</button>
{#if ($DataBase.account?.token?.split('-') ?? [])[1] === openedData.creator}
<button class="text-gray-400 hover:text-red-500" on:click|stopPropagation={async () => {
const conf = await alertConfirm('Do you want to remove this character from Realm?')
if(conf){
const da = await fetch(hubURL + '/hub/remove', {
method: "POST",
body: JSON.stringify({
id: openedData.id,
token: $DataBase.account?.token
})
})
alertNormal(await da.text())
}
}}>
<TrashIcon />
</button>
{/if}
<button class="text-gray-400 hover:text-green-500" on:click|stopPropagation={async () => {
await navigator.clipboard.writeText(`https://risuai.xyz/?realm=${openedData.id}`)
alertNormal("Copied to clipboard")
}}>
<PaperclipIcon />
</button>
<button class="bg-selected hover:ring flex-grow p-2 font-bold rounded-md mr-2" on:click={() => {
downloadRisuHub(openedData.id)
openedData = null
}}>
Download
</button>
</div>
</div>
</div>

View File

@@ -25,10 +25,19 @@
<TextAreaInput autocomplete="off" bind:value={char.creatorNotes} height={"20"} />
<span class="text-neutral-200">{language.tags}</span>
<span class="text-gray-400 text-sm">Tags to search your character easily. latin alphabets only. seperate by comma.</span>
<TextInput marginBottom placeholder="" bind:value={tags} on:input={() => {
<TextInput placeholder="" bind:value={tags} on:input={() => {
tags = tags.replace(/[^a-zA-Z,]/g, '').toLocaleLowerCase()
}} />
<div class="flex items-center flex-wrap">
<span class="text-neutral-200 mt-4">License</span>
<span class="text-gray-400 text-sm">You can choose license for the downloaders to limit the usages of your card.</span>
<SelectInput bind:value={license}>
<OptionInput value="">None</OptionInput>
{#each Object.keys(CCLicenseData) as ccl}
<OptionInput value={ccl}>{ccl} ({CCLicenseData[ccl][1]})</OptionInput>
{/each}
</SelectInput>
<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}}>🌏 Public</button>
<!-- <button class="bg-bgcolor p-2 rounded-lg ml-2" class:ring-1={privateMode} on:click={() => {privateMode = true}}>🔒 Private</button> -->
</div>
@@ -64,16 +73,21 @@
<script lang="ts">
import { XIcon } from "lucide-svelte";
import { language } from "src/lang";
import { alertError } from "src/ts/alert";
import { shareRisuHub } from "src/ts/characterCards";
import { alertError } from "src/ts/alert";
import { shareRisuHub } from "src/ts/characterCards";
import { DataBase, type character } from "src/ts/storage/database";
import TextInput from "../GUI/TextInput.svelte";
import TextAreaInput from "../GUI/TextAreaInput.svelte";
import Button from "../GUI/Button.svelte";
import TextInput from "../GUI/TextInput.svelte";
import TextAreaInput from "../GUI/TextAreaInput.svelte";
import Button from "../GUI/Button.svelte";
import SelectInput from "../GUI/SelectInput.svelte";
import { CCLicenseData } from "src/ts/copyright/license";
import { key } from "localforage";
import OptionInput from "../GUI/OptionInput.svelte";
export let close = () => {}
export let char:character
let tags=""
let privateMode = false
let nsfwMode = false
let license = ""
</script>