From 26d461674f3e93a1edddf93918be033516f1d36d Mon Sep 17 00:00:00 2001 From: Lendruk Date: Wed, 22 May 2024 21:18:45 +0100 Subject: [PATCH 01/55] Add sidebar entry --- frontend/src/lib/Sidebar.svelte | 7 +++++++ frontend/src/lib/icons/InfoIcon.svelte | 2 +- frontend/src/lib/icons/PaletteIcon.svelte | 8 ++++++++ frontend/src/routes/stablediffusion/+page.svelte | 3 +++ 4 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 frontend/src/lib/icons/PaletteIcon.svelte create mode 100644 frontend/src/routes/stablediffusion/+page.svelte diff --git a/frontend/src/lib/Sidebar.svelte b/frontend/src/lib/Sidebar.svelte index 4ac2579..dbe0026 100644 --- a/frontend/src/lib/Sidebar.svelte +++ b/frontend/src/lib/Sidebar.svelte @@ -8,6 +8,7 @@ import UploadIcon from './icons/UploadIcon.svelte'; import ArrowRight from './icons/ArrowRight.svelte'; import ArrowLeft from './icons/ArrowLeft.svelte'; + import PaletteIcon from './icons/PaletteIcon.svelte'; let isSidebarOpen = true; @@ -46,6 +47,12 @@ navHref: '/gallery?inbox=true', icon: InboxIcon, }, + { + name: 'Stable Diffusion', + path: '/stablediffusion', + navHref: '/stablediffusion', + icon: PaletteIcon, + }, { name: 'Playlists', path: /\/playlists|playlists\/(\d)/g, diff --git a/frontend/src/lib/icons/InfoIcon.svelte b/frontend/src/lib/icons/InfoIcon.svelte index cfa5ddd..0f6ab35 100644 --- a/frontend/src/lib/icons/InfoIcon.svelte +++ b/frontend/src/lib/icons/InfoIcon.svelte @@ -4,4 +4,4 @@ export { cssClass as class }; let cssClass = ''; - \ No newline at end of file + \ No newline at end of file diff --git a/frontend/src/lib/icons/PaletteIcon.svelte b/frontend/src/lib/icons/PaletteIcon.svelte new file mode 100644 index 0000000..cb9c766 --- /dev/null +++ b/frontend/src/lib/icons/PaletteIcon.svelte @@ -0,0 +1,8 @@ + + + \ No newline at end of file diff --git a/frontend/src/routes/stablediffusion/+page.svelte b/frontend/src/routes/stablediffusion/+page.svelte new file mode 100644 index 0000000..0e35c1f --- /dev/null +++ b/frontend/src/routes/stablediffusion/+page.svelte @@ -0,0 +1,3 @@ +
+ AI +
\ No newline at end of file From 549fa963f44b33efacc14a38fafc14d518acd309 Mon Sep 17 00:00:00 2001 From: Lendruk Date: Fri, 24 May 2024 18:33:59 +0100 Subject: [PATCH 02/55] WIP img gen ui --- frontend/src/routes/stablediffusion/+page.svelte | 13 +++++++++++-- package-lock.json | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/frontend/src/routes/stablediffusion/+page.svelte b/frontend/src/routes/stablediffusion/+page.svelte index 0e35c1f..6b08ca4 100644 --- a/frontend/src/routes/stablediffusion/+page.svelte +++ b/frontend/src/routes/stablediffusion/+page.svelte @@ -1,3 +1,12 @@ -
- AI +
+
+
+
Prompt
+ \ No newline at end of file diff --git a/frontend/src/lib/services/HttpService.ts b/frontend/src/lib/services/HttpService.ts index f49aa96..de0f61f 100644 --- a/frontend/src/lib/services/HttpService.ts +++ b/frontend/src/lib/services/HttpService.ts @@ -1,5 +1,6 @@ import { get } from "svelte/store"; import { vaultStore } from "../../store"; +import type { Vault } from "$lib/types/Vault"; export class HttpService { public static BASE_URL = `http://localhost:8080`; @@ -8,6 +9,13 @@ export class HttpService { const curVault = get(vaultStore); if (curVault) { return curVault.id; + } else { + const storedVault = localStorage.getItem("currentVault"); + + if (storedVault) { + vaultStore.set(JSON.parse(storedVault) as Vault); + return get(vaultStore)?.id; + } } }; diff --git a/frontend/src/lib/types/SD/SDCheckpoint.ts b/frontend/src/lib/types/SD/SDCheckpoint.ts new file mode 100644 index 0000000..dea5e15 --- /dev/null +++ b/frontend/src/lib/types/SD/SDCheckpoint.ts @@ -0,0 +1,8 @@ +export type SDCheckpoint = { + title: string; + model_name: string; + hash: string; + sha256: string; + filename: string; + config: string; +} \ No newline at end of file diff --git a/frontend/src/lib/types/SD/SDPromptRequest.ts b/frontend/src/lib/types/SD/SDPromptRequest.ts new file mode 100644 index 0000000..fea602e --- /dev/null +++ b/frontend/src/lib/types/SD/SDPromptRequest.ts @@ -0,0 +1,57 @@ +export type SDPromptRequest = { + prompt: string; + negative_prompt: string; + styles: string[]; + seed: number; + subseed: number; + subseed_strength: number; + seed_resize_from_h: number; + seed_resize_from_w: number; + sampler_name: string; + scheduler: string; + batch_size: number; + n_iter: number; + steps: number; + cfg_scale: number; + width: number; + height: number; + restore_faces: boolean; + tiling: boolean; + do_not_save_samples: boolean; + do_not_save_grid: boolean; + eta: number; + denoising_strength: number; + s_min_uncond: number; + s_churn: number; + s_tmax: number; + s_tmin: number; + s_noise: number; + override_settings: Record; + override_settings_restore_afterwards: boolean; + refiner_checkpoint: string | null; + refiner_switch_at: number; + disable_extra_networks: boolean; + firstpass_image: string | null; + comments: Record; + enable_hr: boolean; + firstphase_width: number; + firstphase_height: number; + hr_scale: number; + hr_upscaler: string | null; + hr_second_pass_steps: number, + hr_resize_x: number, + hr_resize_y: number, + hr_checkpoint_name: string | null, + hr_sampler_name: string | null, + hr_scheduler: string | null, + hr_prompt: string, + hr_negative_prompt?: string, + force_task_id: string, + sampler_index: string, + script_name: string, + script_args: string[], + send_images: boolean, + save_images: boolean, + alwayson_scripts: Record, + infotext: string +} \ No newline at end of file diff --git a/frontend/src/lib/types/SD/SDPromptResponse.ts b/frontend/src/lib/types/SD/SDPromptResponse.ts new file mode 100644 index 0000000..6f600fe --- /dev/null +++ b/frontend/src/lib/types/SD/SDPromptResponse.ts @@ -0,0 +1,5 @@ +export type SDPromptResponse = { + images: string[]; + parameters: Record; + info: string; +} \ No newline at end of file diff --git a/frontend/src/lib/types/SD/SDSampler.ts b/frontend/src/lib/types/SD/SDSampler.ts new file mode 100644 index 0000000..389c837 --- /dev/null +++ b/frontend/src/lib/types/SD/SDSampler.ts @@ -0,0 +1,5 @@ +export type SDSampler = { + name: string; + aliases: string[]; + options: Record; +} \ No newline at end of file diff --git a/frontend/src/lib/types/SD/SDSchedulers.ts b/frontend/src/lib/types/SD/SDSchedulers.ts new file mode 100644 index 0000000..ba64860 --- /dev/null +++ b/frontend/src/lib/types/SD/SDSchedulers.ts @@ -0,0 +1,7 @@ +export type SDScheduler = { + name: string; + label: string; + alias: string[]; + default_rho: number; + need_inner_model: boolean; +} \ No newline at end of file diff --git a/frontend/src/lib/utils/SDPromptBuilder.ts b/frontend/src/lib/utils/SDPromptBuilder.ts new file mode 100644 index 0000000..7d6cc65 --- /dev/null +++ b/frontend/src/lib/utils/SDPromptBuilder.ts @@ -0,0 +1,82 @@ +import type { SDPromptRequest } from "$lib/types/SD/SDPromptRequest"; + +export class SDPromptBuilder { + private promptRequest: SDPromptRequest; + + public constructor() { + this.promptRequest = { + prompt: "", + negative_prompt: "", + styles: [], + seed: -1, + subseed: -1, + subseed_strength: 0, + seed_resize_from_h: -1, + seed_resize_from_w: -1, + sampler_name: "Euler a", + scheduler: "automatic", + batch_size: 1, + n_iter: 1, + steps: 20, + cfg_scale: 7, + width: 512, + height: 512, + restore_faces: false, + tiling: false, + do_not_save_samples: false, + do_not_save_grid: true, + eta: 0, + denoising_strength: 0.7, + s_min_uncond: 0, + s_churn: 0, + s_tmax: 0, + s_tmin: 0, + s_noise: 0, + override_settings: { + CLIP_stop_at_last_layers: 2, + sd_vae: "sdxl_vae.safetensors" + }, + override_settings_restore_afterwards: true, + refiner_checkpoint: null, + refiner_switch_at: 0, + disable_extra_networks: false, + firstpass_image: null, + comments: {}, + enable_hr: false, + firstphase_height: 0, + firstphase_width: 0, + hr_scale: 2, + hr_upscaler: null, + hr_scheduler: null, + hr_second_pass_steps: 0, + hr_resize_x: 0, + hr_resize_y: 0, + hr_checkpoint_name: null, + hr_sampler_name: null, + hr_prompt: "", + hr_negative_prompt: "", + force_task_id: "", + sampler_index: "", + script_name: "", + script_args: [], + send_images: true, + save_images: false, + alwayson_scripts: {}, + infotext: "", + } + } + + public withPositivePrompt(prompt: string): this { + this.promptRequest.prompt = prompt; + return this; + } + + public withSeed(seed: number): this { + this.promptRequest.seed = seed; + return this; + } + + public build(): SDPromptRequest { + return this.promptRequest; + } +} \ No newline at end of file diff --git a/frontend/src/routes/stablediffusion/generator/+page.svelte b/frontend/src/routes/stablediffusion/generator/+page.svelte index 4e9ff61..4f8bf75 100644 --- a/frontend/src/routes/stablediffusion/generator/+page.svelte +++ b/frontend/src/routes/stablediffusion/generator/+page.svelte @@ -4,12 +4,42 @@ import { onMount } from "svelte"; import { vaultStore } from "../../../store"; import { beforeNavigate } from "$app/navigation"; + import TextArea from "$lib/components/TextArea.svelte"; + import type { SDCheckpoint } from "$lib/types/SD/SDCheckpoint"; + import type { SDSampler } from "$lib/types/SD/SDSampler"; + import type { SDScheduler } from "$lib/types/SD/SDSchedulers"; + import { SDPromptBuilder } from "$lib/utils/SDPromptBuilder"; + import type { SDPromptResponse } from "$lib/types/SD/SDPromptResponse"; + + let checkpoints: SDCheckpoint[] = []; + let samplers: SDSampler[] = []; + let schedulers: SDScheduler[] = []; + + let currentCheckpoint: string; + + let positivePrompt: string = ''; + let negativePrompt: string = ''; + + let generatedImage: string; async function setup() { - await HttpService.post(`/sd/start`, {}); + + samplers = await HttpService.get(`/sd/samplers`); + checkpoints = await HttpService.get(`/sd/checkpoints`); + schedulers = await HttpService.get(`/sd/schedulers`); + + currentCheckpoint = checkpoints[0].model_name; + // await HttpService.post(`/sd/start`, {}); + } + + async function generate() { + const prompt = new SDPromptBuilder(); + prompt.withPositivePrompt(positivePrompt) + const result = await HttpService.post(`/sd/prompt`, prompt.build()); + generatedImage = result.images[0]; } + beforeNavigate(async () => { - console.log("inactive"); await HttpService.post(`/sd/inactive`, {}); }); @@ -19,22 +49,35 @@
+
+
+ Prompt Mode +
+
+ + +
+
Prompt
- \ No newline at end of file + diff --git a/frontend/src/lib/components/toast/Toast.svelte b/frontend/src/lib/components/toast/Toast.svelte index 20c66d5..cd87301 100644 --- a/frontend/src/lib/components/toast/Toast.svelte +++ b/frontend/src/lib/components/toast/Toast.svelte @@ -1,36 +1,40 @@
-
-
- {content} -
- -
-
-
\ No newline at end of file +
+
+ {content} +
+ +
+
+
diff --git a/frontend/src/lib/components/toast/ToastContainer.svelte b/frontend/src/lib/components/toast/ToastContainer.svelte index 894ba19..76ca4eb 100644 --- a/frontend/src/lib/components/toast/ToastContainer.svelte +++ b/frontend/src/lib/components/toast/ToastContainer.svelte @@ -1,29 +1,33 @@
- {#each toasts as toast, i (i) } - removeToast(toast)} content={toast.content} dismissIn={toast.dismissIn} /> - {/each} -
\ No newline at end of file + {#each toasts as toast, i (i)} + removeToast(toast)} + content={toast.content} + dismissIn={toast.dismissIn} + /> + {/each} +
diff --git a/frontend/src/lib/icons/ArchiveIcon.svelte b/frontend/src/lib/icons/ArchiveIcon.svelte index 39b2985..c771d31 100644 --- a/frontend/src/lib/icons/ArchiveIcon.svelte +++ b/frontend/src/lib/icons/ArchiveIcon.svelte @@ -1,6 +1,10 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/ArrowLeft.svelte b/frontend/src/lib/icons/ArrowLeft.svelte index 4046d1c..9eb6602 100644 --- a/frontend/src/lib/icons/ArrowLeft.svelte +++ b/frontend/src/lib/icons/ArrowLeft.svelte @@ -1,6 +1,15 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/ArrowRight.svelte b/frontend/src/lib/icons/ArrowRight.svelte index ac7fb24..a310ac9 100644 --- a/frontend/src/lib/icons/ArrowRight.svelte +++ b/frontend/src/lib/icons/ArrowRight.svelte @@ -1 +1,5 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/CheckIcon.svelte b/frontend/src/lib/icons/CheckIcon.svelte index 7f5a440..41ed8b6 100644 --- a/frontend/src/lib/icons/CheckIcon.svelte +++ b/frontend/src/lib/icons/CheckIcon.svelte @@ -1,6 +1,10 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/ChevronDown.svelte b/frontend/src/lib/icons/ChevronDown.svelte index e6e4337..85342b0 100644 --- a/frontend/src/lib/icons/ChevronDown.svelte +++ b/frontend/src/lib/icons/ChevronDown.svelte @@ -1,6 +1,15 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/ChevronUp.svelte b/frontend/src/lib/icons/ChevronUp.svelte index d7ce5b6..931bfe5 100644 --- a/frontend/src/lib/icons/ChevronUp.svelte +++ b/frontend/src/lib/icons/ChevronUp.svelte @@ -1,6 +1,15 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/DiceEmoji.svelte b/frontend/src/lib/icons/DiceEmoji.svelte index 6c87e99..42bb857 100644 --- a/frontend/src/lib/icons/DiceEmoji.svelte +++ b/frontend/src/lib/icons/DiceEmoji.svelte @@ -1,8 +1,17 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/DoorOpen.svelte b/frontend/src/lib/icons/DoorOpen.svelte index 2338bb6..7540516 100644 --- a/frontend/src/lib/icons/DoorOpen.svelte +++ b/frontend/src/lib/icons/DoorOpen.svelte @@ -1,6 +1,11 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/DownloadIcon.svelte b/frontend/src/lib/icons/DownloadIcon.svelte index 660c471..3758344 100644 --- a/frontend/src/lib/icons/DownloadIcon.svelte +++ b/frontend/src/lib/icons/DownloadIcon.svelte @@ -1,9 +1,18 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/FilterIcon.svelte b/frontend/src/lib/icons/FilterIcon.svelte index a90d9f1..c6cd05f 100644 --- a/frontend/src/lib/icons/FilterIcon.svelte +++ b/frontend/src/lib/icons/FilterIcon.svelte @@ -1 +1,5 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/FolderClosedIcon.svelte b/frontend/src/lib/icons/FolderClosedIcon.svelte index 32f953e..c39d4e4 100644 --- a/frontend/src/lib/icons/FolderClosedIcon.svelte +++ b/frontend/src/lib/icons/FolderClosedIcon.svelte @@ -1,8 +1,13 @@ - \ No newline at end of file + + diff --git a/frontend/src/lib/icons/House.svelte b/frontend/src/lib/icons/House.svelte index 89dae23..b27b190 100644 --- a/frontend/src/lib/icons/House.svelte +++ b/frontend/src/lib/icons/House.svelte @@ -1 +1,5 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/ImageIcon.svelte b/frontend/src/lib/icons/ImageIcon.svelte index 17cc76f..9ccdf8c 100644 --- a/frontend/src/lib/icons/ImageIcon.svelte +++ b/frontend/src/lib/icons/ImageIcon.svelte @@ -1,8 +1,17 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/ImagesIcon.svelte b/frontend/src/lib/icons/ImagesIcon.svelte index 932c66c..84b7786 100644 --- a/frontend/src/lib/icons/ImagesIcon.svelte +++ b/frontend/src/lib/icons/ImagesIcon.svelte @@ -1,5 +1,9 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/InboxIcon.svelte b/frontend/src/lib/icons/InboxIcon.svelte index d291f46..3e3ebf0 100644 --- a/frontend/src/lib/icons/InboxIcon.svelte +++ b/frontend/src/lib/icons/InboxIcon.svelte @@ -1,6 +1,15 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/InfoIcon.svelte b/frontend/src/lib/icons/InfoIcon.svelte index 0f6ab35..d9a5d62 100644 --- a/frontend/src/lib/icons/InfoIcon.svelte +++ b/frontend/src/lib/icons/InfoIcon.svelte @@ -1,7 +1,17 @@ - \ No newline at end of file + + diff --git a/frontend/src/lib/icons/PaletteIcon.svelte b/frontend/src/lib/icons/PaletteIcon.svelte index cb9c766..873e61f 100644 --- a/frontend/src/lib/icons/PaletteIcon.svelte +++ b/frontend/src/lib/icons/PaletteIcon.svelte @@ -1,8 +1,17 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/PauseIcon.svelte b/frontend/src/lib/icons/PauseIcon.svelte index 968d283..49ab9d8 100644 --- a/frontend/src/lib/icons/PauseIcon.svelte +++ b/frontend/src/lib/icons/PauseIcon.svelte @@ -1,5 +1,10 @@ - \ No newline at end of file + + diff --git a/frontend/src/lib/icons/PenIcon.svelte b/frontend/src/lib/icons/PenIcon.svelte index e37e0bc..4399c09 100644 --- a/frontend/src/lib/icons/PenIcon.svelte +++ b/frontend/src/lib/icons/PenIcon.svelte @@ -1,8 +1,13 @@ - \ No newline at end of file + + diff --git a/frontend/src/lib/icons/PlayIcon.svelte b/frontend/src/lib/icons/PlayIcon.svelte index d9e0f70..7e49152 100644 --- a/frontend/src/lib/icons/PlayIcon.svelte +++ b/frontend/src/lib/icons/PlayIcon.svelte @@ -1,9 +1,13 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/SaveIcon.svelte b/frontend/src/lib/icons/SaveIcon.svelte index 27af8a4..39b65ee 100644 --- a/frontend/src/lib/icons/SaveIcon.svelte +++ b/frontend/src/lib/icons/SaveIcon.svelte @@ -1,8 +1,17 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/SearchIcon.svelte b/frontend/src/lib/icons/SearchIcon.svelte index d71ff4c..2dc159a 100644 --- a/frontend/src/lib/icons/SearchIcon.svelte +++ b/frontend/src/lib/icons/SearchIcon.svelte @@ -1,8 +1,17 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/SeedIcon.svelte b/frontend/src/lib/icons/SeedIcon.svelte index be7b1d9..8d60c07 100644 --- a/frontend/src/lib/icons/SeedIcon.svelte +++ b/frontend/src/lib/icons/SeedIcon.svelte @@ -1,8 +1,17 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/SettingsIcon.svelte b/frontend/src/lib/icons/SettingsIcon.svelte index f3878f6..c8866d1 100644 --- a/frontend/src/lib/icons/SettingsIcon.svelte +++ b/frontend/src/lib/icons/SettingsIcon.svelte @@ -1,8 +1,17 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/TableColumnsIcon.svelte b/frontend/src/lib/icons/TableColumnsIcon.svelte index ad4912b..6ddeb03 100644 --- a/frontend/src/lib/icons/TableColumnsIcon.svelte +++ b/frontend/src/lib/icons/TableColumnsIcon.svelte @@ -1,5 +1,9 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/TagIcon.svelte b/frontend/src/lib/icons/TagIcon.svelte index 7e3e665..a16a074 100644 --- a/frontend/src/lib/icons/TagIcon.svelte +++ b/frontend/src/lib/icons/TagIcon.svelte @@ -1,6 +1,10 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/TrashIcon.svelte b/frontend/src/lib/icons/TrashIcon.svelte index 2b863dc..7e855fe 100644 --- a/frontend/src/lib/icons/TrashIcon.svelte +++ b/frontend/src/lib/icons/TrashIcon.svelte @@ -1,8 +1,17 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/UploadIcon.svelte b/frontend/src/lib/icons/UploadIcon.svelte index 8aef381..44d5418 100644 --- a/frontend/src/lib/icons/UploadIcon.svelte +++ b/frontend/src/lib/icons/UploadIcon.svelte @@ -1,8 +1,17 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/XIcon.svelte b/frontend/src/lib/icons/XIcon.svelte index d3148d3..2d0a9bd 100644 --- a/frontend/src/lib/icons/XIcon.svelte +++ b/frontend/src/lib/icons/XIcon.svelte @@ -1 +1,5 @@ - \ No newline at end of file + diff --git a/frontend/src/lib/icons/editIcon.svelte b/frontend/src/lib/icons/editIcon.svelte index e65c182..149ea46 100644 --- a/frontend/src/lib/icons/editIcon.svelte +++ b/frontend/src/lib/icons/editIcon.svelte @@ -1,7 +1,15 @@ - + diff --git a/frontend/src/lib/index.ts b/frontend/src/lib/index.ts index c7ab773..856f2b6 100644 --- a/frontend/src/lib/index.ts +++ b/frontend/src/lib/index.ts @@ -1 +1 @@ -// place files you want to import through the `$lib` alias in this folder. \ No newline at end of file +// place files you want to import through the `$lib` alias in this folder. diff --git a/frontend/src/lib/services/HttpService.ts b/frontend/src/lib/services/HttpService.ts index 4e5ea18..4136ef9 100644 --- a/frontend/src/lib/services/HttpService.ts +++ b/frontend/src/lib/services/HttpService.ts @@ -1,119 +1,118 @@ -import { get } from "svelte/store"; -import { vaultStore } from "../../store"; -import type { Vault } from "$lib/types/Vault"; +import { get } from 'svelte/store'; +import { vaultStore } from '../../store'; +import type { Vault } from '$lib/types/Vault'; export class HttpService { - public static BASE_URL = `http://localhost:8080`; - - public static getVaultId(): string | undefined { - const curVault = get(vaultStore); - if (curVault) { - return curVault.id; - } else { - const storedVault = localStorage.getItem("currentVault"); - if (storedVault) { - return (JSON.parse(storedVault) as Vault).id; - } - } - }; - - public static clearVault(): void { - localStorage.removeItem('currentVault'); - vaultStore.set(undefined); - } - - public static async get(url: string): Promise { - const response = await fetch(`${HttpService.BASE_URL}${url}`, { - method: "GET", - headers: { - "Content-Type": "application/json", - "vault": this.getVaultId() || "", - }, - }); - - if (response.status >= 400) { - throw new Error(`Error during request status: ${response.status}`); - } - - return response.json() as Promise; - }; - - public static async post(url: string, body?: Record | FormData): Promise { - - const headers: Record = { - "vault": this.getVaultId() || "", - }; - - if (!(body instanceof FormData)) { - headers["Content-Type"] = "application/json"; - } - const response = await fetch(`${HttpService.BASE_URL}${url}`, { - method: "POST", - headers, - body: body instanceof FormData ? body : JSON.stringify(body ?? {}), - }); - - if (response.status >= 400) { - let errorBody: { message: string } = { message: '' }; - try { - errorBody = await response.json() as { message: string }; - } catch { - throw new Error(`Error during request status: ${response.status}`); - } - throw new Error(errorBody.message); - } - - return response.json() as Promise; - } - - public static async put(url: string, body: Record): Promise { - const response = await fetch(`${HttpService.BASE_URL}${url}`, { - method: "PUT", - headers: { - "Content-Type": "application/json", - "vault": this.getVaultId() || "", - }, - body: JSON.stringify(body), - }); - - if (response.status >= 400) { - throw new Error(`Error during request status: ${response.status}`); - } - - return response.json() as Promise; - } - - public static async delete(url: string, body?: Record): Promise { - const response = await fetch(`${HttpService.BASE_URL}${url}`, { - method: "DELETE", - headers: { - "Content-Type": "application/json", - "vault": this.getVaultId() || "", - }, - body: JSON.stringify(body), - }); - - if (response.status >= 400) { - throw new Error(`Error during request status: ${response.status}`); - } - - return response.json() as Promise; - } - - public static async patch(url: string, body: Record): Promise { - const response = await fetch(`${HttpService.BASE_URL}${url}`, { - method: "PATCH", - headers: { - "Content-Type": "application/json", - "vault": this.getVaultId() || "", - }, - body: JSON.stringify(body), - }); - - if (response.status >= 400) { - throw new Error(`Error during request status: ${response.status}`); - } - - return response.json() as Promise; - } -} \ No newline at end of file + public static BASE_URL = `http://localhost:8080`; + + public static getVaultId(): string | undefined { + const curVault = get(vaultStore); + if (curVault) { + return curVault.id; + } else { + const storedVault = localStorage.getItem('currentVault'); + if (storedVault) { + return (JSON.parse(storedVault) as Vault).id; + } + } + } + + public static clearVault(): void { + localStorage.removeItem('currentVault'); + vaultStore.set(undefined); + } + + public static async get(url: string): Promise { + const response = await fetch(`${HttpService.BASE_URL}${url}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + vault: this.getVaultId() || '' + } + }); + + if (response.status >= 400) { + throw new Error(`Error during request status: ${response.status}`); + } + + return response.json() as Promise; + } + + public static async post(url: string, body?: Record | FormData): Promise { + const headers: Record = { + vault: this.getVaultId() || '' + }; + + if (!(body instanceof FormData)) { + headers['Content-Type'] = 'application/json'; + } + const response = await fetch(`${HttpService.BASE_URL}${url}`, { + method: 'POST', + headers, + body: body instanceof FormData ? body : JSON.stringify(body ?? {}) + }); + + if (response.status >= 400) { + let errorBody: { message: string } = { message: '' }; + try { + errorBody = (await response.json()) as { message: string }; + } catch { + throw new Error(`Error during request status: ${response.status}`); + } + throw new Error(errorBody.message); + } + + return response.json() as Promise; + } + + public static async put(url: string, body: Record): Promise { + const response = await fetch(`${HttpService.BASE_URL}${url}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + vault: this.getVaultId() || '' + }, + body: JSON.stringify(body) + }); + + if (response.status >= 400) { + throw new Error(`Error during request status: ${response.status}`); + } + + return response.json() as Promise; + } + + public static async delete(url: string, body?: Record): Promise { + const response = await fetch(`${HttpService.BASE_URL}${url}`, { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + vault: this.getVaultId() || '' + }, + body: JSON.stringify(body) + }); + + if (response.status >= 400) { + throw new Error(`Error during request status: ${response.status}`); + } + + return response.json() as Promise; + } + + public static async patch(url: string, body: Record): Promise { + const response = await fetch(`${HttpService.BASE_URL}${url}`, { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json', + vault: this.getVaultId() || '' + }, + body: JSON.stringify(body) + }); + + if (response.status >= 400) { + throw new Error(`Error during request status: ${response.status}`); + } + + return response.json() as Promise; + } +} diff --git a/frontend/src/lib/types/MediaItem.ts b/frontend/src/lib/types/MediaItem.ts index a61ac8b..a709739 100644 --- a/frontend/src/lib/types/MediaItem.ts +++ b/frontend/src/lib/types/MediaItem.ts @@ -1,19 +1,19 @@ -import type { PopulatedTag } from "./PopulatedTag"; +import type { PopulatedTag } from './PopulatedTag'; type BaseMediaItem = { - id: number; - fileName: string; - type: string; - extension: string; - fileSize: number; - createdAt: number; - updatedAt: number | null; - isArchived: boolean; - exif: string; -} + id: number; + fileName: string; + type: string; + extension: string; + fileSize: number; + createdAt: number; + updatedAt: number | null; + isArchived: boolean; + exif: string; +}; export type MediaItem = BaseMediaItem & { - tags: number[]; + tags: number[]; }; -export type MediaItemWithTags = BaseMediaItem & { tags: PopulatedTag[] }; \ No newline at end of file +export type MediaItemWithTags = BaseMediaItem & { tags: PopulatedTag[] }; diff --git a/frontend/src/lib/types/Playlist.ts b/frontend/src/lib/types/Playlist.ts index e49bf5b..2bbd39e 100644 --- a/frontend/src/lib/types/Playlist.ts +++ b/frontend/src/lib/types/Playlist.ts @@ -1,4 +1,4 @@ -import type { MediaItem } from "./MediaItem"; -import type { SimplePlaylist } from "./SimplePlaylist"; +import type { MediaItem } from './MediaItem'; +import type { SimplePlaylist } from './SimplePlaylist'; -export type Playlist = SimplePlaylist & { items: MediaItem[] }; \ No newline at end of file +export type Playlist = SimplePlaylist & { items: MediaItem[] }; diff --git a/frontend/src/lib/types/PopulatedTag.ts b/frontend/src/lib/types/PopulatedTag.ts index fc7bd44..4bbe587 100644 --- a/frontend/src/lib/types/PopulatedTag.ts +++ b/frontend/src/lib/types/PopulatedTag.ts @@ -1,10 +1,10 @@ type TagDef = { - id: number; - name: string; - mediaCount: number; - color: string; - parentTagId: number | null; -} + id: number; + name: string; + mediaCount: number; + color: string; + parentTagId: number | null; +}; type SimpleTag = Omit; -export type PopulatedTag = SimpleTag & { parent: SimpleTag | null, subTags: PopulatedTag[] }; \ No newline at end of file +export type PopulatedTag = SimpleTag & { parent: SimpleTag | null; subTags: PopulatedTag[] }; diff --git a/frontend/src/lib/types/SD/SDCheckpoint.ts b/frontend/src/lib/types/SD/SDCheckpoint.ts index dea5e15..1b64c5a 100644 --- a/frontend/src/lib/types/SD/SDCheckpoint.ts +++ b/frontend/src/lib/types/SD/SDCheckpoint.ts @@ -1,8 +1,8 @@ export type SDCheckpoint = { - title: string; - model_name: string; - hash: string; - sha256: string; - filename: string; - config: string; -} \ No newline at end of file + title: string; + model_name: string; + hash: string; + sha256: string; + filename: string; + config: string; +}; diff --git a/frontend/src/lib/types/SD/SDLora.ts b/frontend/src/lib/types/SD/SDLora.ts index b43cc8a..e2550e4 100644 --- a/frontend/src/lib/types/SD/SDLora.ts +++ b/frontend/src/lib/types/SD/SDLora.ts @@ -1,17 +1,17 @@ -import type { PopulatedTag } from "../PopulatedTag"; +import type { PopulatedTag } from '../PopulatedTag'; export type SDLora = { - name: string; - id: string; - alias: string; - path: string; - previewImage: string; - tags: PopulatedTag[]; - metadata: { - ss_sd_model_name: string; - ss_resolution: string; - ss_clip_skip: string; - ss_num_train_images: string; - ss_tag_frequency: Record>; - } -} \ No newline at end of file + name: string; + id: string; + alias: string; + path: string; + previewImage: string; + tags: PopulatedTag[]; + metadata: { + ss_sd_model_name: string; + ss_resolution: string; + ss_clip_skip: string; + ss_num_train_images: string; + ss_tag_frequency: Record>; + }; +}; diff --git a/frontend/src/lib/types/SD/SDPromptRequest.ts b/frontend/src/lib/types/SD/SDPromptRequest.ts index fea602e..bf63c52 100644 --- a/frontend/src/lib/types/SD/SDPromptRequest.ts +++ b/frontend/src/lib/types/SD/SDPromptRequest.ts @@ -1,57 +1,57 @@ export type SDPromptRequest = { - prompt: string; - negative_prompt: string; - styles: string[]; - seed: number; - subseed: number; - subseed_strength: number; - seed_resize_from_h: number; - seed_resize_from_w: number; - sampler_name: string; - scheduler: string; - batch_size: number; - n_iter: number; - steps: number; - cfg_scale: number; - width: number; - height: number; - restore_faces: boolean; - tiling: boolean; - do_not_save_samples: boolean; - do_not_save_grid: boolean; - eta: number; - denoising_strength: number; - s_min_uncond: number; - s_churn: number; - s_tmax: number; - s_tmin: number; - s_noise: number; - override_settings: Record; - override_settings_restore_afterwards: boolean; - refiner_checkpoint: string | null; - refiner_switch_at: number; - disable_extra_networks: boolean; - firstpass_image: string | null; - comments: Record; - enable_hr: boolean; - firstphase_width: number; - firstphase_height: number; - hr_scale: number; - hr_upscaler: string | null; - hr_second_pass_steps: number, - hr_resize_x: number, - hr_resize_y: number, - hr_checkpoint_name: string | null, - hr_sampler_name: string | null, - hr_scheduler: string | null, - hr_prompt: string, - hr_negative_prompt?: string, - force_task_id: string, - sampler_index: string, - script_name: string, - script_args: string[], - send_images: boolean, - save_images: boolean, - alwayson_scripts: Record, - infotext: string -} \ No newline at end of file + prompt: string; + negative_prompt: string; + styles: string[]; + seed: number; + subseed: number; + subseed_strength: number; + seed_resize_from_h: number; + seed_resize_from_w: number; + sampler_name: string; + scheduler: string; + batch_size: number; + n_iter: number; + steps: number; + cfg_scale: number; + width: number; + height: number; + restore_faces: boolean; + tiling: boolean; + do_not_save_samples: boolean; + do_not_save_grid: boolean; + eta: number; + denoising_strength: number; + s_min_uncond: number; + s_churn: number; + s_tmax: number; + s_tmin: number; + s_noise: number; + override_settings: Record; + override_settings_restore_afterwards: boolean; + refiner_checkpoint: string | null; + refiner_switch_at: number; + disable_extra_networks: boolean; + firstpass_image: string | null; + comments: Record; + enable_hr: boolean; + firstphase_width: number; + firstphase_height: number; + hr_scale: number; + hr_upscaler: string | null; + hr_second_pass_steps: number; + hr_resize_x: number; + hr_resize_y: number; + hr_checkpoint_name: string | null; + hr_sampler_name: string | null; + hr_scheduler: string | null; + hr_prompt: string; + hr_negative_prompt?: string; + force_task_id: string; + sampler_index: string; + script_name: string; + script_args: string[]; + send_images: boolean; + save_images: boolean; + alwayson_scripts: Record; + infotext: string; +}; diff --git a/frontend/src/lib/types/SD/SDSampler.ts b/frontend/src/lib/types/SD/SDSampler.ts index 389c837..2f1ade1 100644 --- a/frontend/src/lib/types/SD/SDSampler.ts +++ b/frontend/src/lib/types/SD/SDSampler.ts @@ -1,5 +1,5 @@ export type SDSampler = { - name: string; - aliases: string[]; - options: Record; -} \ No newline at end of file + name: string; + aliases: string[]; + options: Record; +}; diff --git a/frontend/src/lib/types/SD/SDSchedulers.ts b/frontend/src/lib/types/SD/SDSchedulers.ts index ba64860..dff5328 100644 --- a/frontend/src/lib/types/SD/SDSchedulers.ts +++ b/frontend/src/lib/types/SD/SDSchedulers.ts @@ -1,7 +1,7 @@ export type SDScheduler = { - name: string; - label: string; - alias: string[]; - default_rho: number; - need_inner_model: boolean; -} \ No newline at end of file + name: string; + label: string; + alias: string[]; + default_rho: number; + need_inner_model: boolean; +}; diff --git a/frontend/src/lib/types/SD/SDUpscaler.ts b/frontend/src/lib/types/SD/SDUpscaler.ts index a07b519..51e178b 100644 --- a/frontend/src/lib/types/SD/SDUpscaler.ts +++ b/frontend/src/lib/types/SD/SDUpscaler.ts @@ -1,7 +1,7 @@ export type SDUpscaler = { - name: string; - model_name: string | null; - model_path: string | null; - model_url: string | null; - scale: number; -} \ No newline at end of file + name: string; + model_name: string | null; + model_path: string | null; + model_url: string | null; + scale: number; +}; diff --git a/frontend/src/lib/types/SavedPrompt.ts b/frontend/src/lib/types/SavedPrompt.ts index 8707185..db00f57 100644 --- a/frontend/src/lib/types/SavedPrompt.ts +++ b/frontend/src/lib/types/SavedPrompt.ts @@ -1,20 +1,20 @@ export type SavedPrompt = { - id?: string, - name: string, - previewImage: string, - positivePrompt: string, - negativePrompt: string, - sampler: string, - steps: number, - width: number, - height: number, - checkpoint: string, - cfgScale: number, - highRes: { - upscaler: string, - steps: number, - denoisingStrength: number, - upscaleBy: number - } | null, - createdAt: number -} \ No newline at end of file + id?: string; + name: string; + previewImage: string; + positivePrompt: string; + negativePrompt: string; + sampler: string; + steps: number; + width: number; + height: number; + checkpoint: string; + cfgScale: number; + highRes: { + upscaler: string; + steps: number; + denoisingStrength: number; + upscaleBy: number; + } | null; + createdAt: number; +}; diff --git a/frontend/src/lib/types/SimplePlaylist.ts b/frontend/src/lib/types/SimplePlaylist.ts index 5eb91c5..798dc8c 100644 --- a/frontend/src/lib/types/SimplePlaylist.ts +++ b/frontend/src/lib/types/SimplePlaylist.ts @@ -1,9 +1,9 @@ export type SimplePlaylist = { - id: number; - name: string; - createdAt: number; - updatedAt: number | null; - randomizeOrder: number; - timePerItem: number | null; - items: number; + id: number; + name: string; + createdAt: number; + updatedAt: number | null; + randomizeOrder: number; + timePerItem: number | null; + items: number; }; diff --git a/frontend/src/lib/types/Vault.ts b/frontend/src/lib/types/Vault.ts index 02e3a48..fe4f140 100644 --- a/frontend/src/lib/types/Vault.ts +++ b/frontend/src/lib/types/Vault.ts @@ -1,6 +1,6 @@ export type Vault = { - id: string; - name: string; - path: string; - hasInstalledSD: boolean; -} \ No newline at end of file + id: string; + name: string; + path: string; + hasInstalledSD: boolean; +}; diff --git a/frontend/src/lib/utils/SDPromptBuilder.ts b/frontend/src/lib/utils/SDPromptBuilder.ts index 5efbdaf..97264fd 100644 --- a/frontend/src/lib/utils/SDPromptBuilder.ts +++ b/frontend/src/lib/utils/SDPromptBuilder.ts @@ -1,142 +1,142 @@ -import type { SDPromptRequest } from "$lib/types/SD/SDPromptRequest"; +import type { SDPromptRequest } from '$lib/types/SD/SDPromptRequest'; type HighResOptions = { - upscaler: string; - steps: number; - denoisingStrength: number; - upscaleBy: number; -} + upscaler: string; + steps: number; + denoisingStrength: number; + upscaleBy: number; +}; type RefinerOptions = { - refinerCheckpoint: string; - switchAt: number; + refinerCheckpoint: string; + switchAt: number; }; export class SDPromptBuilder { - private promptRequest: SDPromptRequest; - - public constructor() { - this.promptRequest = { - prompt: "", - negative_prompt: "", - styles: [], - seed: -1, - subseed: -1, - subseed_strength: 0, - seed_resize_from_h: -1, - seed_resize_from_w: -1, - sampler_name: "Euler a", - scheduler: "automatic", - batch_size: 1, - n_iter: 1, - steps: 20, - cfg_scale: 7, - width: 512, - height: 512, - restore_faces: false, - tiling: false, - do_not_save_samples: false, - do_not_save_grid: true, - eta: 0, - denoising_strength: 0.7, - s_min_uncond: 0, - s_churn: 0, - s_tmax: 0, - s_tmin: 0, - s_noise: 0, - override_settings: { - CLIP_stop_at_last_layers: 2, - sd_vae: "None", - sd_model_checkpoint: "v1-5-pruned-emaonly", - }, - override_settings_restore_afterwards: true, - refiner_checkpoint: null, - refiner_switch_at: 0, - disable_extra_networks: false, - firstpass_image: null, - comments: {}, - enable_hr: false, - firstphase_height: 0, - firstphase_width: 0, - hr_scale: 2, - hr_upscaler: null, - hr_scheduler: null, - hr_second_pass_steps: 0, - hr_resize_x: 0, - hr_resize_y: 0, - hr_checkpoint_name: null, - hr_sampler_name: null, - hr_prompt: "", - hr_negative_prompt: "", - force_task_id: "", - sampler_index: "", - script_name: "", - script_args: [], - send_images: true, - save_images: false, - alwayson_scripts: {}, - infotext: "", - } - } - - public withCheckpoint(checkpoint: string): this { - this.promptRequest.override_settings[`sd_model_checkpoint`] = checkpoint; - return this; - } - - public withPositivePrompt(prompt: string): this { - this.promptRequest.prompt = prompt; - return this; - } - - public withNegativePrompt(prompt: string): this { - this.promptRequest.negative_prompt = prompt; - return this; - } - - public withSteps(steps: number): this { - this.promptRequest.steps = steps; - return this; - } - - public withSampler(sampler: string): this { - this.promptRequest.sampler_name = sampler; - return this; - } - - public withSize(width: number, height: number): this { - this.promptRequest.width = width; - this.promptRequest.height = height; - return this; - } - - public withSeed(seed: number): this { - this.promptRequest.seed = seed; - return this; - } - - public withCfgScale(cfgScale: number): this { - this.promptRequest.cfg_scale = cfgScale; - return this; - } - - public withHighResOptions(options: HighResOptions ): this { - this.promptRequest.hr_upscaler = options.upscaler; - this.promptRequest.hr_scale = options.upscaleBy; - this.promptRequest.hr_second_pass_steps = options.steps; - this.promptRequest.denoising_strength = options.denoisingStrength; - - this.promptRequest.enable_hr = true; - return this; - } - - public withRefiner(options: RefinerOptions): this { - this.promptRequest.refiner_checkpoint = options.refinerCheckpoint; - this.promptRequest.refiner_switch_at = options.switchAt; - return this; - } - - public build(): SDPromptRequest { - return this.promptRequest; - } -} \ No newline at end of file + private promptRequest: SDPromptRequest; + + public constructor() { + this.promptRequest = { + prompt: '', + negative_prompt: '', + styles: [], + seed: -1, + subseed: -1, + subseed_strength: 0, + seed_resize_from_h: -1, + seed_resize_from_w: -1, + sampler_name: 'Euler a', + scheduler: 'automatic', + batch_size: 1, + n_iter: 1, + steps: 20, + cfg_scale: 7, + width: 512, + height: 512, + restore_faces: false, + tiling: false, + do_not_save_samples: false, + do_not_save_grid: true, + eta: 0, + denoising_strength: 0.7, + s_min_uncond: 0, + s_churn: 0, + s_tmax: 0, + s_tmin: 0, + s_noise: 0, + override_settings: { + CLIP_stop_at_last_layers: 2, + sd_vae: 'None', + sd_model_checkpoint: 'v1-5-pruned-emaonly' + }, + override_settings_restore_afterwards: true, + refiner_checkpoint: null, + refiner_switch_at: 0, + disable_extra_networks: false, + firstpass_image: null, + comments: {}, + enable_hr: false, + firstphase_height: 0, + firstphase_width: 0, + hr_scale: 2, + hr_upscaler: null, + hr_scheduler: null, + hr_second_pass_steps: 0, + hr_resize_x: 0, + hr_resize_y: 0, + hr_checkpoint_name: null, + hr_sampler_name: null, + hr_prompt: '', + hr_negative_prompt: '', + force_task_id: '', + sampler_index: '', + script_name: '', + script_args: [], + send_images: true, + save_images: false, + alwayson_scripts: {}, + infotext: '' + }; + } + + public withCheckpoint(checkpoint: string): this { + this.promptRequest.override_settings[`sd_model_checkpoint`] = checkpoint; + return this; + } + + public withPositivePrompt(prompt: string): this { + this.promptRequest.prompt = prompt; + return this; + } + + public withNegativePrompt(prompt: string): this { + this.promptRequest.negative_prompt = prompt; + return this; + } + + public withSteps(steps: number): this { + this.promptRequest.steps = steps; + return this; + } + + public withSampler(sampler: string): this { + this.promptRequest.sampler_name = sampler; + return this; + } + + public withSize(width: number, height: number): this { + this.promptRequest.width = width; + this.promptRequest.height = height; + return this; + } + + public withSeed(seed: number): this { + this.promptRequest.seed = seed; + return this; + } + + public withCfgScale(cfgScale: number): this { + this.promptRequest.cfg_scale = cfgScale; + return this; + } + + public withHighResOptions(options: HighResOptions): this { + this.promptRequest.hr_upscaler = options.upscaler; + this.promptRequest.hr_scale = options.upscaleBy; + this.promptRequest.hr_second_pass_steps = options.steps; + this.promptRequest.denoising_strength = options.denoisingStrength; + + this.promptRequest.enable_hr = true; + return this; + } + + public withRefiner(options: RefinerOptions): this { + this.promptRequest.refiner_checkpoint = options.refinerCheckpoint; + this.promptRequest.refiner_switch_at = options.switchAt; + return this; + } + + public build(): SDPromptRequest { + return this.promptRequest; + } +} diff --git a/frontend/src/lib/utils/time.ts b/frontend/src/lib/utils/time.ts index d9724c2..a9fc50d 100644 --- a/frontend/src/lib/utils/time.ts +++ b/frontend/src/lib/utils/time.ts @@ -1 +1 @@ -export const pause = (ms: number) => new Promise(resolve => setTimeout(resolve, ms)); \ No newline at end of file +export const pause = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte index e51a7a6..e63edcb 100644 --- a/frontend/src/routes/+layout.svelte +++ b/frontend/src/routes/+layout.svelte @@ -1,66 +1,66 @@
- {#if !$page.url.pathname.includes("/vaults")} - -
- -
- -
-
- {:else} - - {/if} + {#if !$page.url.pathname.includes('/vaults')} + +
+ +
+ +
+
+ {:else} + + {/if}
\ No newline at end of file + :global(input) { + background-color: rgb(54, 59, 61); + } + diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte index ef1f96d..199e707 100644 --- a/frontend/src/routes/+page.svelte +++ b/frontend/src/routes/+page.svelte @@ -1,83 +1,89 @@ -
-

Media Upload

-
-
-
- - -
- -
- {#if previewFiles.length > 0} -
-
- {#each previewFiles as file, i (i)} -
-
- removeImage(i)}> - - -
- {#if file.originalFile.type.includes("video")} -
- {/each} -
- -
- {/if} -
-
- - NoriBooru - Upload - \ No newline at end of file +
+

Media Upload

+
+
+
+ + +
+ +
+ {#if previewFiles.length > 0} +
+
+ {#each previewFiles as file, i (i)} +
+
+ removeImage(i)}> + + +
+ {#if file.originalFile.type.includes('video')} +
+ {/each} +
+ +
+ {/if} +
+
+ + + NoriBooru - Upload + diff --git a/frontend/src/routes/components/LabeledComponent.svelte b/frontend/src/routes/components/LabeledComponent.svelte index 5ae996c..b8ddb71 100644 --- a/frontend/src/routes/components/LabeledComponent.svelte +++ b/frontend/src/routes/components/LabeledComponent.svelte @@ -1,11 +1,11 @@
-
- -
- -
\ No newline at end of file +
+ +
+ +
diff --git a/frontend/src/routes/components/MassTagEditModal.svelte b/frontend/src/routes/components/MassTagEditModal.svelte index fb9d8d8..65f27ee 100644 --- a/frontend/src/routes/components/MassTagEditModal.svelte +++ b/frontend/src/routes/components/MassTagEditModal.svelte @@ -1,47 +1,49 @@ - -
-
-
- You're adding tags to {itemsInEdit.size} item{itemsInEdit.size > 1 ? 's' : ''} -
- { - const index = appliedTags.findIndex(t => t.id === tag.id); + +
+
+
+ You're adding tags to {itemsInEdit.size} item{itemsInEdit.size > 1 ? 's' : ''} +
+ { + const index = appliedTags.findIndex((t) => t.id === tag.id); - if(index !== -1) { - appliedTags.splice(index, 1); - appliedTags = appliedTags; - } - }} - onTagSearchSubmit={(tag) => { - appliedTags.push(tag); - appliedTags = appliedTags; - }} - /> -
- -
-
\ No newline at end of file + if (index !== -1) { + appliedTags.splice(index, 1); + appliedTags = appliedTags; + } + }} + onTagSearchSubmit={(tag) => { + appliedTags.push(tag); + appliedTags = appliedTags; + }} + /> +
+ +
+
diff --git a/frontend/src/routes/components/TagEditModal.svelte b/frontend/src/routes/components/TagEditModal.svelte index 6933aa0..b6568bf 100644 --- a/frontend/src/routes/components/TagEditModal.svelte +++ b/frontend/src/routes/components/TagEditModal.svelte @@ -1,29 +1,27 @@ - -
-
- Modify media item tags -
- -
-
\ No newline at end of file + + +
+
Modify media item tags
+ +
+
diff --git a/frontend/src/routes/gallery/+page.svelte b/frontend/src/routes/gallery/+page.svelte index 0690f34..2a7605e 100644 --- a/frontend/src/routes/gallery/+page.svelte +++ b/frontend/src/routes/gallery/+page.svelte @@ -20,349 +20,413 @@ import Link from '$lib/Link.svelte'; import { goto } from '$app/navigation'; - let mediaItems: MediaItem[] = []; - let appliedPositiveTags: PopulatedTag[] = []; - let positiveQueryType: "AND" | "OR" = "AND"; - let appliedNegativeTags: PopulatedTag[] = []; - let negativeQueryType: "AND" | "OR" = "AND"; - let tags: PopulatedTag[] = []; - let sortMethod: 'newest' | 'oldest' = 'newest'; - let showMediaTagEditModal = false; - let showMassTagEditModal = false; - let currentPage = 0; - let hasMoreItems = true; - let fetchingItems = false; - let isFilterSelectionVisible = false; - let mediaItemInTagEdit: { id: number; tags: PopulatedTag[] } | undefined; - - let oldHeight = 0; - - let galleryDiv: HTMLDivElement; - - let selectedItems: Map = new Map(); - let isSelectionModeActive = false; - let isInbox = false; - - $: isSelectionModeActive = selectedItems.size > 0; - $: isInbox = $page.url.searchParams.has("inbox"); + let mediaItems: MediaItem[] = []; + let appliedPositiveTags: PopulatedTag[] = []; + let positiveQueryType: 'AND' | 'OR' = 'AND'; + let appliedNegativeTags: PopulatedTag[] = []; + let negativeQueryType: 'AND' | 'OR' = 'AND'; + let tags: PopulatedTag[] = []; + let sortMethod: 'newest' | 'oldest' = 'newest'; + let showMediaTagEditModal = false; + let showMassTagEditModal = false; + let currentPage = 0; + let hasMoreItems = true; + let fetchingItems = false; + let isFilterSelectionVisible = false; + let mediaItemInTagEdit: { id: number; tags: PopulatedTag[] } | undefined; + + let oldHeight = 0; + + let galleryDiv: HTMLDivElement; + + let selectedItems: Map = new Map(); + let isSelectionModeActive = false; + let isInbox = false; + + $: isSelectionModeActive = selectedItems.size > 0; + $: isInbox = $page.url.searchParams.has('inbox'); onMount(async () => { - isInbox = $page.url.searchParams.has("inbox"); - page.subscribe(async (val) => { - if (val.url.searchParams.has("inbox")) { - isInbox = true; - } else { - isInbox = false; - } - - selectedItems = new Map(); - await search(); - }); - await search(); - tags = await HttpService.get('/tags'); + isInbox = $page.url.searchParams.has('inbox'); + page.subscribe(async (val) => { + if (val.url.searchParams.has('inbox')) { + isInbox = true; + } else { + isInbox = false; + } + + selectedItems = new Map(); + await search(); + }); + await search(); + tags = await HttpService.get('/tags'); }); - async function applyPositiveTagFilter(tag: PopulatedTag) { - appliedPositiveTags = [...appliedPositiveTags, tag]; - currentPage = 0; - hasMoreItems = true; - oldHeight = 0; - await search(); - } - - async function applyNegativeTagFilter(tag: PopulatedTag) { - appliedNegativeTags = [...appliedNegativeTags, tag]; - currentPage = 0; - hasMoreItems = true; - oldHeight = 0; - await search(); - } - - async function removeTagFromMediaItem(tag: PopulatedTag, mediaItemId: number) { - await HttpService.delete(`/mediaItems/${mediaItemId}/tags`, { ...tag }); - const tagIndex = mediaItemInTagEdit!.tags.findIndex(mediaTag => mediaTag.id === tag.id); - mediaItemInTagEdit!.tags.splice(tagIndex, 1); - mediaItemInTagEdit!.tags = mediaItemInTagEdit!.tags; - } - - async function addTagToMediaItem(tag: PopulatedTag, mediaItemId: number) { - await HttpService.put(`/mediaItems/${JSON.stringify([mediaItemId])}/tags`, { ...tag }); - mediaItemInTagEdit!.tags.push(tag); - mediaItemInTagEdit!.tags = mediaItemInTagEdit!.tags; - } - - async function search(appendResults: boolean = false) { - fetchingItems = true; - const res = await HttpService.get<{ mediaItems: MediaItem[] }>('/mediaItems?' + new URLSearchParams( - { - negativeTags: JSON.stringify(appliedNegativeTags.map(tag => tag.id)), - positiveTags: JSON.stringify(appliedPositiveTags.map(tag => tag.id )), - positiveQueryType, - negativeQueryType, - sortMethod, - archived: isInbox ? 'false' : 'true', - page: currentPage.toString(), - })); - - if (appendResults) { - if(res.mediaItems.length > 0) { - mediaItems = mediaItems.concat(res.mediaItems); - } else { - hasMoreItems = false; - } - } else { - mediaItems = res.mediaItems; - } - await pause(1000); - fetchingItems = false; - } - - async function removePositiveTagFilter(tag: PopulatedTag) { - appliedPositiveTags = appliedPositiveTags.filter(t => t.id !== tag.id); - currentPage = 0; - hasMoreItems = true; - await search(); - } - - async function removeNegativeTagFilter(tag: PopulatedTag) { - appliedNegativeTags = appliedNegativeTags.filter(t => t.id !== tag.id); - currentPage = 0; - hasMoreItems = true; - await search(); - } - - async function deleteItems(mediaItemIds: number[]) { - await HttpService.delete(`/mediaItems/${JSON.stringify(mediaItemIds)}`); - mediaItems = mediaItems.filter(item => !mediaItemIds.includes(item.id)); - } - - async function deleteSelectedItems() { - let itemIds: number[] = []; - for(const id of selectedItems.keys()) { - itemIds.push(id); - } - await deleteItems(itemIds); - selectedItems = new Map(); - } - - async function toggleArchivedStatus(mediaItemIds: number[], isArchived: boolean) { - await HttpService.patch(`/mediaItems/${JSON.stringify(mediaItemIds)}`, { isArchived }); - mediaItems = mediaItems.map(item => mediaItemIds.includes(item.id) ? { ...item, isArchived } : item); - } - - async function toggleSelectedItems() { - let itemIds: number[] = []; - for(const id of selectedItems.keys()) { - itemIds.push(id); - } - await toggleArchivedStatus(itemIds, isInbox ? true : false); - selectedItems = new Map(); - await search(); - } - - async function fetchMediaItemTags(mediaItemId: number) { - const tags = await HttpService.get(`/mediaItems/${mediaItemId}/tags`); - mediaItemInTagEdit = { id: mediaItemId, tags }; - } - - function onPositiveTagSearchSubmit(tag: PopulatedTag) { - applyPositiveTagFilter(tag); - } - - function onNegativeTagSearchSubmit(tag: PopulatedTag) { - applyNegativeTagFilter(tag); - } - - async function onTagButtonClick(mediaItemId: number) { - await fetchMediaItemTags(mediaItemId); - showMediaTagEditModal = !showMediaTagEditModal; - } - - function onMediaItemSelect(mediaItem: MediaItem) { - if (selectedItems.has(mediaItem.id)) { - selectedItems.delete(mediaItem.id); - } else { - selectedItems.set(mediaItem.id, mediaItem); - } - selectedItems = selectedItems; - } - - function onKeyPress(event: KeyboardEvent) { - if (!showMassTagEditModal && !showMediaTagEditModal) { - if(event.key === "f" || event.key === "F") { - isFilterSelectionVisible = !isFilterSelectionVisible; - } - } - } - - async function onWindowScroll(e: UIEvent & { - currentTarget: EventTarget & Window; - }) { - if (e.currentTarget.scrollY + e.currentTarget.innerHeight >= document.documentElement.scrollHeight -50) { - if(hasMoreItems && !fetchingItems) { - currentPage = currentPage + 1; - oldHeight = galleryDiv.clientHeight; - await search(true); - } - } - } - - function goToGenerator(inputExif: string) { - goto(`/stablediffusion/generator?inputExif=${inputExif}`); - } - - $: { - if (mediaItems.length > 0 && oldHeight !== 0) { - tick().then(() => { - window.scrollBy({ top: -(galleryDiv.clientHeight - oldHeight), behavior: 'instant'}); - }) - } - } + async function applyPositiveTagFilter(tag: PopulatedTag) { + appliedPositiveTags = [...appliedPositiveTags, tag]; + currentPage = 0; + hasMoreItems = true; + oldHeight = 0; + await search(); + } + + async function applyNegativeTagFilter(tag: PopulatedTag) { + appliedNegativeTags = [...appliedNegativeTags, tag]; + currentPage = 0; + hasMoreItems = true; + oldHeight = 0; + await search(); + } + + async function removeTagFromMediaItem(tag: PopulatedTag, mediaItemId: number) { + await HttpService.delete(`/mediaItems/${mediaItemId}/tags`, { ...tag }); + const tagIndex = mediaItemInTagEdit!.tags.findIndex((mediaTag) => mediaTag.id === tag.id); + mediaItemInTagEdit!.tags.splice(tagIndex, 1); + mediaItemInTagEdit!.tags = mediaItemInTagEdit!.tags; + } + + async function addTagToMediaItem(tag: PopulatedTag, mediaItemId: number) { + await HttpService.put(`/mediaItems/${JSON.stringify([mediaItemId])}/tags`, { ...tag }); + mediaItemInTagEdit!.tags.push(tag); + mediaItemInTagEdit!.tags = mediaItemInTagEdit!.tags; + } + + async function search(appendResults: boolean = false) { + fetchingItems = true; + const res = await HttpService.get<{ mediaItems: MediaItem[] }>( + '/mediaItems?' + + new URLSearchParams({ + negativeTags: JSON.stringify(appliedNegativeTags.map((tag) => tag.id)), + positiveTags: JSON.stringify(appliedPositiveTags.map((tag) => tag.id)), + positiveQueryType, + negativeQueryType, + sortMethod, + archived: isInbox ? 'false' : 'true', + page: currentPage.toString() + }) + ); + + if (appendResults) { + if (res.mediaItems.length > 0) { + mediaItems = mediaItems.concat(res.mediaItems); + } else { + hasMoreItems = false; + } + } else { + mediaItems = res.mediaItems; + } + await pause(1000); + fetchingItems = false; + } + + async function removePositiveTagFilter(tag: PopulatedTag) { + appliedPositiveTags = appliedPositiveTags.filter((t) => t.id !== tag.id); + currentPage = 0; + hasMoreItems = true; + await search(); + } + + async function removeNegativeTagFilter(tag: PopulatedTag) { + appliedNegativeTags = appliedNegativeTags.filter((t) => t.id !== tag.id); + currentPage = 0; + hasMoreItems = true; + await search(); + } + + async function deleteItems(mediaItemIds: number[]) { + await HttpService.delete(`/mediaItems/${JSON.stringify(mediaItemIds)}`); + mediaItems = mediaItems.filter((item) => !mediaItemIds.includes(item.id)); + } + + async function deleteSelectedItems() { + let itemIds: number[] = []; + for (const id of selectedItems.keys()) { + itemIds.push(id); + } + await deleteItems(itemIds); + selectedItems = new Map(); + } + + async function toggleArchivedStatus(mediaItemIds: number[], isArchived: boolean) { + await HttpService.patch(`/mediaItems/${JSON.stringify(mediaItemIds)}`, { isArchived }); + mediaItems = mediaItems.map((item) => + mediaItemIds.includes(item.id) ? { ...item, isArchived } : item + ); + } + + async function toggleSelectedItems() { + let itemIds: number[] = []; + for (const id of selectedItems.keys()) { + itemIds.push(id); + } + await toggleArchivedStatus(itemIds, isInbox ? true : false); + selectedItems = new Map(); + await search(); + } + + async function fetchMediaItemTags(mediaItemId: number) { + const tags = await HttpService.get(`/mediaItems/${mediaItemId}/tags`); + mediaItemInTagEdit = { id: mediaItemId, tags }; + } + + function onPositiveTagSearchSubmit(tag: PopulatedTag) { + applyPositiveTagFilter(tag); + } + + function onNegativeTagSearchSubmit(tag: PopulatedTag) { + applyNegativeTagFilter(tag); + } + + async function onTagButtonClick(mediaItemId: number) { + await fetchMediaItemTags(mediaItemId); + showMediaTagEditModal = !showMediaTagEditModal; + } + + function onMediaItemSelect(mediaItem: MediaItem) { + if (selectedItems.has(mediaItem.id)) { + selectedItems.delete(mediaItem.id); + } else { + selectedItems.set(mediaItem.id, mediaItem); + } + selectedItems = selectedItems; + } + + function onKeyPress(event: KeyboardEvent) { + if (!showMassTagEditModal && !showMediaTagEditModal) { + if (event.key === 'f' || event.key === 'F') { + isFilterSelectionVisible = !isFilterSelectionVisible; + } + } + } + + async function onWindowScroll( + e: UIEvent & { + currentTarget: EventTarget & Window; + } + ) { + if ( + e.currentTarget.scrollY + e.currentTarget.innerHeight >= + document.documentElement.scrollHeight - 50 + ) { + if (hasMoreItems && !fetchingItems) { + currentPage = currentPage + 1; + oldHeight = galleryDiv.clientHeight; + await search(true); + } + } + } + + function goToGenerator(inputExif: string) { + goto(`/stablediffusion/generator?inputExif=${inputExif}`); + } + + $: { + if (mediaItems.length > 0 && oldHeight !== 0) { + tick().then(() => { + window.scrollBy({ top: -(galleryDiv.clientHeight - oldHeight), behavior: 'instant' }); + }); + } + }
- {#if mediaItems.length > 0} -
- {#if isSelectionModeActive} -
-
-
- Selecting {selectedItems.size} Items - -
- -
- - - -
-
-
- {/if} -
- - - {#if isInbox} - 0 ? '/gallery/review' : ''} class={`${mediaItems.length > 0 ? 'cursor-pointer' : 'cursor-not-allowed'} ml-2`}>Start review - {/if} -
-
- {/if} -
- {#if isFilterSelectionVisible} -
-
Filters
-
-
-
Positive Tags
-
- - -
-
- -
-
-
-
Negative Tags
-
- - -
-
- -
-
- Sort by: - -
-
- {/if} -
- {#each mediaItems as mediaItem} - toggleArchivedStatus([mediaItem.id], !mediaItem.isArchived)} - onMoveToInbox={() => toggleArchivedStatus([mediaItem.id], !mediaItem.isArchived)} - onConfirmDelete={() => deleteItems([mediaItem.id])} - onTagButtonClick={() => onTagButtonClick(mediaItem.id)} - onSelectClick={() => onMediaItemSelect(mediaItem)} - onGotoGeneratorClick={() => goToGenerator(mediaItem.exif)} - isSelected={selectedItems.has(mediaItem.id)} - isSelectionModeActive={isSelectionModeActive} - href={`/gallery/${mediaItem.id}`} - > - {#if mediaItem.type === "image"} - gallery-img - {/if} - {#if mediaItem.type === "video"} - - {/each} - {#if mediaItems.length === 0} -
- No items in {isInbox ? 'inbox' : 'gallery'} -
- {/if} -
-
+ {#if mediaItems.length > 0} +
+ {#if isSelectionModeActive} +
+
+
+ Selecting {selectedItems.size} Items + +
+ +
+ + + +
+
+
+ {/if} +
+ + + {#if isInbox} + 0 ? '/gallery/review' : ''} + class={`${mediaItems.length > 0 ? 'cursor-pointer' : 'cursor-not-allowed'} ml-2`} + >Start review + {/if} +
+
+ {/if} +
+ {#if isFilterSelectionVisible} +
+
Filters
+
+
+
Positive Tags
+
+ + +
+
+ +
+
+
+
Negative Tags
+
+ + +
+
+ +
+
+ Sort by: + +
+
+ {/if} +
+ {#each mediaItems as mediaItem} + toggleArchivedStatus([mediaItem.id], !mediaItem.isArchived)} + onMoveToInbox={() => toggleArchivedStatus([mediaItem.id], !mediaItem.isArchived)} + onConfirmDelete={() => deleteItems([mediaItem.id])} + onTagButtonClick={() => onTagButtonClick(mediaItem.id)} + onSelectClick={() => onMediaItemSelect(mediaItem)} + onGotoGeneratorClick={() => goToGenerator(mediaItem.exif)} + isSelected={selectedItems.has(mediaItem.id)} + {isSelectionModeActive} + href={`/gallery/${mediaItem.id}`} + > + {#if mediaItem.type === 'image'} + gallery-img + {/if} + {#if mediaItem.type === 'video'} + + {/each} + {#if mediaItems.length === 0} +
+ No items in {isInbox ? 'inbox' : 'gallery'} +
+ {/if} +
+
-
-
- Modify media item tags -
- {#if mediaItemInTagEdit} - removeTagFromMediaItem(tag, mediaItemInTagEdit!.id)} - onTagSearchSubmit={(tag) => addTagToMediaItem(tag, mediaItemInTagEdit!.id)} - /> - {/if} -
+
+
Modify media item tags
+ {#if mediaItemInTagEdit} + removeTagFromMediaItem(tag, mediaItemInTagEdit!.id)} + onTagSearchSubmit={(tag) => addTagToMediaItem(tag, mediaItemInTagEdit!.id)} + /> + {/if} +
- - NoriBooru - Gallery - \ No newline at end of file + NoriBooru - Gallery + diff --git a/frontend/src/routes/gallery/GalleryItem.svelte b/frontend/src/routes/gallery/GalleryItem.svelte index 35df196..2541c2c 100644 --- a/frontend/src/routes/gallery/GalleryItem.svelte +++ b/frontend/src/routes/gallery/GalleryItem.svelte @@ -1,91 +1,121 @@ - showOptions = true} on:mouseleave={() => { showOptions = false; reset()}} style={style} class={`flex justify-center h-64 items-center ${ isSelected ? 'border-red-900 bg-red-900' : 'border-zinc-900 bg-zinc-900'} border-2 rounded-md relative group ${className}`} href={isSelectionModeActive ? '' : href}> -
- -
-
-
-
- -
-
- {#if isArchived} - - - - {:else} - - - - {/if} -
-
-
- {#if $vaultStore?.hasInstalledSD && isAiGen} - - - - {/if} - - - - - {#if confirmingDelete} - - - - {/if} - {#if !confirmingDelete} - confirmingDelete = true}> - - - {/if} -
-
-
- -
\ No newline at end of file + (showOptions = true)} + on:mouseleave={() => { + showOptions = false; + reset(); + }} + {style} + class={`flex justify-center h-64 items-center ${isSelected ? 'border-red-900 bg-red-900' : 'border-zinc-900 bg-zinc-900'} border-2 rounded-md relative group ${className}`} + href={isSelectionModeActive ? '' : href} +> +
+ +
+
+
+
+ +
+
+ {#if isArchived} + + + + {:else} + + + + {/if} +
+
+
+ {#if $vaultStore?.hasInstalledSD && isAiGen} + + + + {/if} + + + + + {#if confirmingDelete} + + + + {/if} + {#if !confirmingDelete} + (confirmingDelete = true)}> + + + {/if} +
+
+
+ +
diff --git a/frontend/src/routes/gallery/[id]/+page.svelte b/frontend/src/routes/gallery/[id]/+page.svelte index 3028cf0..7e466ca 100644 --- a/frontend/src/routes/gallery/[id]/+page.svelte +++ b/frontend/src/routes/gallery/[id]/+page.svelte @@ -1,97 +1,118 @@
- -
-
- {#if mediaItem?.type === "image"} - gallery-img - {/if} - {#if mediaItem?.type === "video"} - - {/if} -
-
-

Tags

- {#if mediaItem} - - {/if} -
-
- - {JSON.stringify(parsedExif)} -
-
- + +
+
+ {#if mediaItem?.type === 'image'} + gallery-img + {/if} + {#if mediaItem?.type === 'video'} + + {/if} +
+
+

Tags

+ {#if mediaItem} + + {/if} +
+
+ + {JSON.stringify(parsedExif)} +
+
+
- NoriBooru - Media Item - \ No newline at end of file + NoriBooru - Media Item + diff --git a/frontend/src/routes/gallery/review/+page.svelte b/frontend/src/routes/gallery/review/+page.svelte index ae4e1ea..58b1cc3 100644 --- a/frontend/src/routes/gallery/review/+page.svelte +++ b/frontend/src/routes/gallery/review/+page.svelte @@ -1,257 +1,286 @@
- {currentMediaIndex + 1} / {mediaIds.length} + {currentMediaIndex + 1} / {mediaIds.length}
-
- +
+
- - {#if currentMediaItem} -
- {#if currentMediaItem.type === "image"} - gallery-img - {/if} - {#if currentMediaItem.type === "video"} - - {/if} + + {#if currentMediaItem} +
+ {#if currentMediaItem.type === 'image'} + gallery-img + {/if} + {#if currentMediaItem.type === 'video'} + + {/if} - -
- -
-
-
- D - mark for current item for deletion -
-
- Spacebar - mark current item for archival -
-
- Escape - exit review mode -
-
-
+ +
+ +
+
+
D - mark for current item for deletion
+
Spacebar - mark current item for archival
+
Escape - exit review mode
+
+
-
- - - -
-
- {/if} - +
+ + + +
+
+ {/if} +
-
-
Finish Review
-
- You will be archiving / deleting {actionMap.size} item{actionMap.size > 1 ? 's' : ''} -
- +
+
Finish Review
+
+ You will be archiving / deleting {actionMap.size} item{actionMap.size > 1 ? 's' : ''}
+ +
{#if currentMediaItem} - + {/if} - \ No newline at end of file + diff --git a/frontend/src/routes/playlists/+page.svelte b/frontend/src/routes/playlists/+page.svelte index bfb4ee6..dc3e680 100644 --- a/frontend/src/routes/playlists/+page.svelte +++ b/frontend/src/routes/playlists/+page.svelte @@ -16,10 +16,10 @@ }); async function deletePlaylist(playlistId?: number) { - if(playlistId !== undefined) { - await HttpService.delete(`/playlists/${playlistId}`); - playlists = playlists.filter((playlist) => playlist.id !== playlistId); - } + if (playlistId !== undefined) { + await HttpService.delete(`/playlists/${playlistId}`); + playlists = playlists.filter((playlist) => playlist.id !== playlistId); + } } @@ -34,17 +34,15 @@
{#if playlists.length > 0} - { goto(`/playlists/${id}`)}}, { icon: PlayIcon, name: 'Play', onClick: (id) => { goto(`/playlists/view/${id}`)}, condition: (row) => (row as SimplePlaylist).items > 0}, { icon: TrashIcon, name: 'Delete', onClick: (id) => { deletePlaylist(id as number)} } ]} - /> + /> {:else}
No playlists
{/if} @@ -53,4 +51,4 @@ NoriBooru - Playlists - \ No newline at end of file + diff --git a/frontend/src/routes/playlists/[id]/+page.svelte b/frontend/src/routes/playlists/[id]/+page.svelte index b2b5ee3..0e83c25 100644 --- a/frontend/src/routes/playlists/[id]/+page.svelte +++ b/frontend/src/routes/playlists/[id]/+page.svelte @@ -1,165 +1,185 @@
- -
-
-
- - -
-
- - -
- -
- -
-
-
Media Items
- -
-
- ($page.params.id !== 'new' ? updatePlaylist() : createPlaylist())} + >{$page.params.id !== 'new' ? 'Update' : 'Create'} +
+
+
+ + +
+
+ + +
+ +
+ +
+
+
Media Items
+ +
+
+ new Date(val as number).toDateString(), }, ]} - rows={playlistItems} - actions={[ + rows={playlistItems} + actions={[ { icon: TrashIcon, name: 'Delete', onClick: (id) => { removePlaylistItem(id as number)} } ]} - orderable={{ - onMoveDown:moveMediaItemDown, - onMoveUp:moveMediaItemUp, - }} - /> -
-
-
- -
- { - filterTags.push(tag); - - if (filterTags.length > 0) { - await searchMedia(); - } - }} - onAppliedTagClick={(tag) => { - const index = filterTags.findIndex(t => t.id === tag.id); - - if(index !== -1) { - filterTags.splice(index, 1); - } - }} - /> -
- {#each sidebarMediaItems as mediaItem} - { selectedSidebarMediaItems = selectedSidebarMediaItems.filter(t => t.id !== mediaItem.id) }} - onAddClick={() => { selectedSidebarMediaItems.push(mediaItem); }} - > - {#if mediaItem.type === "image"} - gallery-img - {/if} - {#if mediaItem.type === "video"} - - {/each} -
- - -
-
+ orderable={{ + onMoveDown: moveMediaItemDown, + onMoveUp: moveMediaItemUp + }} + /> +
+
+
+ +
+ { + filterTags.push(tag); + + if (filterTags.length > 0) { + await searchMedia(); + } + }} + onAppliedTagClick={(tag) => { + const index = filterTags.findIndex((t) => t.id === tag.id); + + if (index !== -1) { + filterTags.splice(index, 1); + } + }} + /> +
+ {#each sidebarMediaItems as mediaItem} + { + selectedSidebarMediaItems = selectedSidebarMediaItems.filter( + (t) => t.id !== mediaItem.id + ); + }} + onAddClick={() => { + selectedSidebarMediaItems.push(mediaItem); + }} + > + {#if mediaItem.type === 'image'} + gallery-img + {/if} + {#if mediaItem.type === 'video'} + + {/each} +
+ + +
+
- NoriBooru - Playlist Edit - \ No newline at end of file + NoriBooru - Playlist Edit + diff --git a/frontend/src/routes/playlists/[id]/SidebarMediaItem.svelte b/frontend/src/routes/playlists/[id]/SidebarMediaItem.svelte index a1459f4..8c3d538 100644 --- a/frontend/src/routes/playlists/[id]/SidebarMediaItem.svelte +++ b/frontend/src/routes/playlists/[id]/SidebarMediaItem.svelte @@ -1,26 +1,33 @@ -
showOptions = true} on:mouseleave={() => showOptions = false}> - - {`${isAdded ? '-' : '+'}`} - - -
\ No newline at end of file +
(showOptions = true)} + on:mouseleave={() => (showOptions = false)} +> + + {`${isAdded ? '-' : '+'}`} + + +
diff --git a/frontend/src/routes/playlists/[id]/TableImage.svelte b/frontend/src/routes/playlists/[id]/TableImage.svelte index e1339ad..5757e95 100644 --- a/frontend/src/routes/playlists/[id]/TableImage.svelte +++ b/frontend/src/routes/playlists/[id]/TableImage.svelte @@ -1,13 +1,21 @@
- {#if row.type === "image"} - gallery-img - {:else} -
\ No newline at end of file + {#if row.type === 'image'} + gallery-img + {:else} +
diff --git a/frontend/src/routes/playlists/view/[id]/+page.svelte b/frontend/src/routes/playlists/view/[id]/+page.svelte index b9bf178..d47c3e6 100644 --- a/frontend/src/routes/playlists/view/[id]/+page.svelte +++ b/frontend/src/routes/playlists/view/[id]/+page.svelte @@ -1,112 +1,131 @@
- - {#if currentMediaItem} -
- {#if currentMediaItem.type === "image"} - gallery-img - {/if} - {#if currentMediaItem.type === "video"} - - {/if} + + {#if currentMediaItem} +
+ {#if currentMediaItem.type === 'image'} + gallery-img + {/if} + {#if currentMediaItem.type === 'video'} + + {/if} - -
- {/if} - + +
+ {/if} +
- NoriBooru - Playlist View - \ No newline at end of file + NoriBooru - Playlist View + diff --git a/frontend/src/routes/rapidFire/+page.svelte b/frontend/src/routes/rapidFire/+page.svelte index 8a07ff3..a4fad5e 100644 --- a/frontend/src/routes/rapidFire/+page.svelte +++ b/frontend/src/routes/rapidFire/+page.svelte @@ -1,25 +1,19 @@
-
- Test1 -
-
- Test2 -
-
- Test3 -
+
Test1
+
Test2
+
Test3
\ No newline at end of file + .pane { + display: flex; + width: 33%; + height: 100%; + } + diff --git a/frontend/src/routes/stablediffusion/generator/+page.svelte b/frontend/src/routes/stablediffusion/generator/+page.svelte index 924e34a..92ca4f5 100644 --- a/frontend/src/routes/stablediffusion/generator/+page.svelte +++ b/frontend/src/routes/stablediffusion/generator/+page.svelte @@ -1,469 +1,490 @@
-
-
-
- Prompt -
- - -
- Search saved prompts -
-
-
-
-
- - -
- Save current prompt & Settings -
-
- - {#if areSaveOptionsExpanded} -
- -
- {/if} -
- {#if isGeneratingImage} - - {:else} - - {/if} -
-
-
-
-
Prompt
-