WIP design and UI features
This commit is contained in:
parent
b07210507e
commit
048c8f1380
13 changed files with 214 additions and 105 deletions
14
package.json
14
package.json
|
@ -20,18 +20,18 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@skeletonlabs/skeleton": "^2.9.0",
|
"@skeletonlabs/skeleton": "^2.9.0",
|
||||||
"@skeletonlabs/tw-plugin": "^0.3.1",
|
"@skeletonlabs/tw-plugin": "^0.3.1",
|
||||||
"@sveltejs/adapter-auto": "^3.1.1",
|
|
||||||
"@sveltejs/adapter-static": "^3.0.1",
|
"@sveltejs/adapter-static": "^3.0.1",
|
||||||
"@sveltejs/kit": "^2.5.4",
|
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.0.2",
|
|
||||||
"@tauri-apps/cli": "^1.5.11",
|
"@tauri-apps/cli": "^1.5.11",
|
||||||
"autoprefixer": "^10.4.18",
|
"autoprefixer": "^10.4.18",
|
||||||
"postcss": "^8.4.35",
|
"postcss": "^8.4.35",
|
||||||
"postcss-load-config": "^5.0.3",
|
"postcss-load-config": "^5.0.3",
|
||||||
"svelte": "^4.2.12",
|
|
||||||
"svelte-check": "^3.6.7",
|
|
||||||
"tailwindcss": "^3.4.1",
|
"tailwindcss": "^3.4.1",
|
||||||
"typescript": "^5.4.2",
|
"@sveltejs/adapter-auto": "^3.0.0",
|
||||||
"vite": "^5.1.6"
|
"@sveltejs/kit": "^2.0.0",
|
||||||
|
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||||
|
"svelte": "^4.2.7",
|
||||||
|
"svelte-check": "^3.6.0",
|
||||||
|
"typescript": "^5.0.0",
|
||||||
|
"vite": "^5.0.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,16 +32,16 @@ devDependencies:
|
||||||
specifier: ^0.3.1
|
specifier: ^0.3.1
|
||||||
version: 0.3.1(tailwindcss@3.4.1)
|
version: 0.3.1(tailwindcss@3.4.1)
|
||||||
'@sveltejs/adapter-auto':
|
'@sveltejs/adapter-auto':
|
||||||
specifier: ^3.1.1
|
specifier: ^3.0.0
|
||||||
version: 3.1.1(@sveltejs/kit@2.5.4)
|
version: 3.1.1(@sveltejs/kit@2.5.4)
|
||||||
'@sveltejs/adapter-static':
|
'@sveltejs/adapter-static':
|
||||||
specifier: ^3.0.1
|
specifier: ^3.0.1
|
||||||
version: 3.0.1(@sveltejs/kit@2.5.4)
|
version: 3.0.1(@sveltejs/kit@2.5.4)
|
||||||
'@sveltejs/kit':
|
'@sveltejs/kit':
|
||||||
specifier: ^2.5.4
|
specifier: ^2.0.0
|
||||||
version: 2.5.4(@sveltejs/vite-plugin-svelte@3.0.2)(svelte@4.2.12)(vite@5.1.6)
|
version: 2.5.4(@sveltejs/vite-plugin-svelte@3.0.2)(svelte@4.2.12)(vite@5.1.6)
|
||||||
'@sveltejs/vite-plugin-svelte':
|
'@sveltejs/vite-plugin-svelte':
|
||||||
specifier: ^3.0.2
|
specifier: ^3.0.0
|
||||||
version: 3.0.2(svelte@4.2.12)(vite@5.1.6)
|
version: 3.0.2(svelte@4.2.12)(vite@5.1.6)
|
||||||
'@tauri-apps/cli':
|
'@tauri-apps/cli':
|
||||||
specifier: ^1.5.11
|
specifier: ^1.5.11
|
||||||
|
@ -56,19 +56,19 @@ devDependencies:
|
||||||
specifier: ^5.0.3
|
specifier: ^5.0.3
|
||||||
version: 5.0.3(postcss@8.4.35)
|
version: 5.0.3(postcss@8.4.35)
|
||||||
svelte:
|
svelte:
|
||||||
specifier: ^4.2.12
|
specifier: ^4.2.7
|
||||||
version: 4.2.12
|
version: 4.2.12
|
||||||
svelte-check:
|
svelte-check:
|
||||||
specifier: ^3.6.7
|
specifier: ^3.6.0
|
||||||
version: 3.6.7(postcss-load-config@5.0.3)(postcss@8.4.35)(svelte@4.2.12)
|
version: 3.6.7(postcss-load-config@5.0.3)(postcss@8.4.35)(svelte@4.2.12)
|
||||||
tailwindcss:
|
tailwindcss:
|
||||||
specifier: ^3.4.1
|
specifier: ^3.4.1
|
||||||
version: 3.4.1
|
version: 3.4.1
|
||||||
typescript:
|
typescript:
|
||||||
specifier: ^5.4.2
|
specifier: ^5.0.0
|
||||||
version: 5.4.2
|
version: 5.4.2
|
||||||
vite:
|
vite:
|
||||||
specifier: ^5.1.6
|
specifier: ^5.0.3
|
||||||
version: 5.1.6
|
version: 5.1.6
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
31
src/lib/PostList.js
Normal file
31
src/lib/PostList.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
import { TAG_TYPES } from '$lib/Tags';
|
||||||
|
|
||||||
|
export default class PostList {
|
||||||
|
|
||||||
|
posts = [];
|
||||||
|
|
||||||
|
constructor(posts) {
|
||||||
|
this.posts = posts;
|
||||||
|
}
|
||||||
|
|
||||||
|
filterPosts(tags = []) {
|
||||||
|
const filteredPosts = [];
|
||||||
|
|
||||||
|
postLoop: for (const post of this.posts) {
|
||||||
|
for (const tagType of Object.keys(TAG_TYPES)) {
|
||||||
|
if (post.tags[tagType].some((postTag) => tags.includes(postTag))) {
|
||||||
|
console.info('Skipping post', post);
|
||||||
|
continue postLoop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filteredPosts.push(post);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.posts = filteredPosts;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPosts() {
|
||||||
|
return this.posts;
|
||||||
|
}
|
||||||
|
}
|
9
src/lib/Tags.js
Normal file
9
src/lib/Tags.js
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
export const TAG_TYPES = {
|
||||||
|
artist: 'Artist',
|
||||||
|
character: 'Character',
|
||||||
|
copyright: 'Copyright',
|
||||||
|
general: 'General',
|
||||||
|
lore: 'Lore',
|
||||||
|
meta: 'Meta',
|
||||||
|
invalid: 'Invalid'
|
||||||
|
};
|
|
@ -1,21 +1,29 @@
|
||||||
<script>
|
<script>
|
||||||
import {RangeSlider, Tab, TabGroup} from "@skeletonlabs/skeleton";
|
import { RangeSlider, Tab, TabGroup, InputChip, SlideToggle } from '@skeletonlabs/skeleton';
|
||||||
import {imageGridColumns, postGridPreviewQuality} from "$lib/stores.js";
|
import { imageGridColumns, postGridPreviewQuality, blacklist, limitImageHeight } from '$lib/settings';
|
||||||
|
|
||||||
let tabPos = 0;
|
let tabPos = 0;
|
||||||
|
let showApikey = false;
|
||||||
|
let apikey = '';
|
||||||
</script>
|
</script>
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<h2 class="h2 mb-2 text-dark-token">Settings</h2>
|
<h2 class="h2 mb-2 text-dark-token">Settings</h2>
|
||||||
<TabGroup>
|
<TabGroup>
|
||||||
<Tab class="text-dark-token" bind:group={tabPos} name="tab1" value={0}>Search Grid</Tab>
|
<Tab class="text-dark-token" bind:group={tabPos} name="tab1" value={0}>Display</Tab>
|
||||||
|
<Tab class="text-dark-token" bind:group={tabPos} name="tab2" value={1}>API</Tab>
|
||||||
|
<Tab class="text-dark-token" bind:group={tabPos} name="tab3" value={2}>User</Tab>
|
||||||
|
|
||||||
<svelte:fragment slot="panel">
|
<svelte:fragment slot="panel">
|
||||||
{#if tabPos === 0}
|
{#if tabPos === 0}
|
||||||
<div class="flex flex-col gap-3">
|
<div class="flex flex-col gap-3">
|
||||||
|
<h3 class="h3 text-dark-token font-bold">Image</h3>
|
||||||
|
<SlideToggle name="image-limit-height" checked={$limitImageHeight}>Limit image height</SlideToggle>
|
||||||
|
|
||||||
|
<h3 class="h3 text-dark-token font-bold">Grid</h3>
|
||||||
<div class="basis-1/2">
|
<div class="basis-1/2">
|
||||||
<RangeSlider name="grid-columns" min={1} max={12} bind:value={$imageGridColumns} ticked={true}>
|
<RangeSlider accent="text-dark-token" name="grid-columns" min={1} max={12} bind:value={$imageGridColumns} ticked={true}>
|
||||||
<div class="flex flex-grow justify-between items-center">
|
<div class="flex flex-grow justify-between items-center dark">
|
||||||
<div class="text-dark-token font-bold">Grid Columns</div>
|
<div class="text-dark-token font-bold mb-1">Grid Columns</div>
|
||||||
<div class="text-xs text-dark-token">{$imageGridColumns} / {12}</div>
|
<div class="text-xs text-dark-token">{$imageGridColumns} / {12}</div>
|
||||||
</div>
|
</div>
|
||||||
</RangeSlider>
|
</RangeSlider>
|
||||||
|
@ -31,6 +39,40 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
{#if tabPos === 1}
|
||||||
|
<div class="flex flex-col gap-3">
|
||||||
|
<div class="">
|
||||||
|
<label class="label">
|
||||||
|
<span class="text-dark-token font-bold">e621 Username</span>
|
||||||
|
<input class="input" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="">
|
||||||
|
<label class="label">
|
||||||
|
<span class="text-dark-token font-bold">e621 Apikey</span>
|
||||||
|
{#if showApikey}
|
||||||
|
<input class="input" type="text" bind:value={apikey} />
|
||||||
|
{:else}
|
||||||
|
<input class="input" type="password" bind:value={apikey} />
|
||||||
|
{/if}
|
||||||
|
</label>
|
||||||
|
<label class="label">
|
||||||
|
<span class="text-dark-token font-bold">Show apikey</span>
|
||||||
|
<input class="checkbox" type="checkbox" bind:checked={showApikey} />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if tabPos === 2}
|
||||||
|
<div class="flex flex-col gap-3">
|
||||||
|
<div class="">
|
||||||
|
<p class="text-dark-token font-bold">Blacklist</p>
|
||||||
|
<InputChip name="blacklist" label="Blacklist" bind:value={$blacklist} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</TabGroup>
|
</TabGroup>
|
||||||
</div>
|
</div>
|
|
@ -1,18 +1,19 @@
|
||||||
<script>
|
<script>
|
||||||
import { showSearch, lastSearch, loading } from '$lib/stores.js';
|
import { showSearch, loading } from '$lib/stores';
|
||||||
|
import { lastSearch } from '$lib/settings';
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
|
|
||||||
let searchValue = $lastSearch;
|
let searchValue = $lastSearch;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $showSearch}
|
{#if $showSearch}
|
||||||
<form class="w-80 pt-2 px-2 flex flex-row gap-2"
|
<form class="flex flex-row gap-2"
|
||||||
on:submit|preventDefault={() => {
|
on:submit|preventDefault={() => {
|
||||||
$loading = true;
|
$loading = true;
|
||||||
goto('/')
|
goto('/')
|
||||||
lastSearch.set(searchValue);
|
lastSearch.set(searchValue);
|
||||||
}}>
|
}}>
|
||||||
<input class="input py-1 px-2" type="text" placeholder="Search" bind:value={searchValue} />
|
<input class="input py-1 px-2 w-96" type="text" placeholder="Search" bind:value={searchValue} />
|
||||||
<button class="btn btn-md variant-filled" type="submit">Sumbit</button>
|
<button class="btn btn-md variant-filled" type="submit">Submit</button>
|
||||||
</form>
|
</form>
|
||||||
{/if}
|
{/if}
|
|
@ -1,5 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import {postGridPreviewQuality, imageGridColumns, showSearch, loading} from '$lib/stores';
|
import { showSearch, loading } from '$lib/stores';
|
||||||
|
import { postGridPreviewQuality, imageGridColumns } from '$lib/settings';
|
||||||
|
|
||||||
export let posts = [];
|
export let posts = [];
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
<script>
|
<script>
|
||||||
|
import { limitImageHeight } from '$lib/settings.js';
|
||||||
|
|
||||||
export let post = null;
|
export let post = null;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{#if post?.preview?.has}
|
{#if post?.preview?.has}
|
||||||
<img class="mb-2" src={post.preview.url} alt={`Post ${post.id}`} />
|
<img class:h-dvh={$limitImageHeight} src={post.preview.url} alt={`Post ${post.id}`} />
|
||||||
{:else}
|
{:else}
|
||||||
{#if ['webm', 'mp4'].includes(post.file.ext)}
|
{#if ['webm', 'mp4'].includes(post.file.ext)}
|
||||||
<video class="mb-2" controls playsinline>
|
<video class:h-dvh={$limitImageHeight} controls playsinline>
|
||||||
<source src={post.file.url} />
|
<source src={post.file.url} />
|
||||||
</video>
|
</video>
|
||||||
{:else}
|
{:else}
|
||||||
<img class="mb-2" src={post.file.url} alt={`Post ${post.id}}`} />
|
<img class:h-dvh={$limitImageHeight} src={post.file.url} alt={`Post ${post.id}}`} />
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
14
src/lib/settings.js
Normal file
14
src/lib/settings.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
import { localStorageStore } from '@skeletonlabs/skeleton';
|
||||||
|
|
||||||
|
export const lastSearch = localStorageStore('lastSearch', '');
|
||||||
|
export const imageGridColumns = localStorageStore('gridColumns', 6);
|
||||||
|
export const postGridPreviewQuality = localStorageStore('gridPreviewQuality', 'preview');
|
||||||
|
export const blacklist = localStorageStore('blacklist', [
|
||||||
|
'gore',
|
||||||
|
'scat',
|
||||||
|
'watersports',
|
||||||
|
'young',
|
||||||
|
'loli',
|
||||||
|
'shota',
|
||||||
|
]);
|
||||||
|
export const limitImageHeight = localStorageStore('limitImageHeight', false);
|
|
@ -1,9 +1,5 @@
|
||||||
import { localStorageStore } from '@skeletonlabs/skeleton';
|
|
||||||
import { writable } from 'svelte/store';
|
import { writable } from 'svelte/store';
|
||||||
|
|
||||||
export const lastSearch = localStorageStore('lastSearch', '');
|
|
||||||
export const imageGridColumns = localStorageStore('gridColumns', 6);
|
|
||||||
export const postSearchResults = writable(null);
|
export const postSearchResults = writable(null);
|
||||||
export const postGridPreviewQuality = localStorageStore('gridPreviewQuality', 'preview');
|
|
||||||
export const loading = writable(false);
|
export const loading = writable(false);
|
||||||
export const showSearch = writable(true);
|
export const showSearch = writable(true);
|
|
@ -1,30 +1,26 @@
|
||||||
<script>
|
<script>
|
||||||
import { Fa } from 'svelte-fa';
|
import { Fa } from 'svelte-fa';
|
||||||
import {GlobalSearch, ImageGrid, SearchAppRailAnchor} from '$lib/components';
|
import { GlobalSearch, ImageGrid, SearchAppRailAnchor} from '$lib/components';
|
||||||
import { faGear } from '@fortawesome/free-solid-svg-icons';
|
import { faGear } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { invoke } from '@tauri-apps/api/tauri'
|
import { invoke } from '@tauri-apps/api/tauri'
|
||||||
import { lastSearch, postSearchResults, loading } from '$lib/stores';
|
import { lastSearch, blacklist } from '$lib/settings';
|
||||||
|
import { postSearchResults, loading, showSearch} from '$lib/stores';
|
||||||
import {
|
import {
|
||||||
|
AppBar,
|
||||||
AppRail,
|
AppRail,
|
||||||
AppRailAnchor,
|
AppRailAnchor,
|
||||||
AppShell,
|
AppShell,
|
||||||
getDrawerStore
|
getDrawerStore
|
||||||
} from '@skeletonlabs/skeleton';
|
} from '@skeletonlabs/skeleton';
|
||||||
import {onMount} from 'svelte';
|
import PostList from '$lib/PostList';
|
||||||
|
|
||||||
const drawerStore = getDrawerStore();
|
const drawerStore = getDrawerStore();
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
$loading = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
function onSearch() {
|
function onSearch() {
|
||||||
$loading = true;
|
$loading = true;
|
||||||
invoke('get_posts', { query: $lastSearch }).then((resPosts) => {
|
invoke('get_posts', { query: $lastSearch }).then((resPosts) => {
|
||||||
postSearchResults.set(resPosts);
|
postSearchResults.set(new PostList(resPosts).filterPosts($blacklist).getPosts());
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => $loading = false);
|
||||||
$loading = false;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,7 +35,11 @@
|
||||||
|
|
||||||
<AppShell>
|
<AppShell>
|
||||||
<svelte:fragment slot="pageHeader">
|
<svelte:fragment slot="pageHeader">
|
||||||
<GlobalSearch />
|
{#if $showSearch}
|
||||||
|
<AppBar>
|
||||||
|
<GlobalSearch />
|
||||||
|
</AppBar>
|
||||||
|
{/if}
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
|
||||||
<svelte:fragment slot="sidebarLeft">
|
<svelte:fragment slot="sidebarLeft">
|
||||||
|
|
|
@ -5,10 +5,8 @@ export const ssr = false;
|
||||||
/** @type {import('./$types').PageLoad} */
|
/** @type {import('./$types').PageLoad} */
|
||||||
export async function load({ params }) {
|
export async function load({ params }) {
|
||||||
// const post = await invoke('get_post', {post_id: params.post_id});
|
// const post = await invoke('get_post', {post_id: params.post_id});
|
||||||
const post = await invoke('get_post', {postId: +params.post_id});
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
postId: params.post_id,
|
postId: params.post_id
|
||||||
post
|
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -1,90 +1,105 @@
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
|
AppBar,
|
||||||
AppRail,
|
AppRail,
|
||||||
AppRailAnchor,
|
AppRailAnchor,
|
||||||
AppShell,
|
AppShell,
|
||||||
getDrawerStore,
|
getDrawerStore,
|
||||||
|
clipboard,
|
||||||
|
getToastStore
|
||||||
} from '@skeletonlabs/skeleton';
|
} from '@skeletonlabs/skeleton';
|
||||||
import { faGear, faCopy } from '@fortawesome/free-solid-svg-icons';
|
import { faGear, faCopy } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { Fa } from 'svelte-fa';
|
import { Fa } from 'svelte-fa';
|
||||||
import { BackAppRailAnchor, GlobalSearch, PostMedia, SearchAppRailAnchor } from '$lib/components';
|
import { BackAppRailAnchor, GlobalSearch, PostMedia, SearchAppRailAnchor } from '$lib/components';
|
||||||
import {onMount} from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import {loading} from '$lib/stores.js';
|
import { loading, showSearch } from '$lib/stores';
|
||||||
|
import { limitImageHeight } from '$lib/settings.js';
|
||||||
|
import { TAG_TYPES } from '$lib/Tags';
|
||||||
|
import { invoke } from '@tauri-apps/api/tauri';
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
let drawerStore = getDrawerStore();
|
const drawerStore = getDrawerStore();
|
||||||
const tagTypes = Object.entries({
|
const tagTypes = Object.entries(TAG_TYPES);
|
||||||
artist: 'Artist',
|
const toastStore = getToastStore();
|
||||||
character: 'Character',
|
|
||||||
copyright: 'Copyright',
|
|
||||||
general: 'General',
|
|
||||||
lore: 'Lore',
|
|
||||||
meta: 'Meta',
|
|
||||||
invalid: 'Invalid'
|
|
||||||
});
|
|
||||||
|
|
||||||
onMount(() => {
|
/** @type any|null */
|
||||||
|
let post = null;
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
$loading = true;
|
||||||
|
const postRequest = await invoke('get_post', {postId: +data.postId});
|
||||||
$loading = false;
|
$loading = false;
|
||||||
|
post = postRequest;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<AppShell>
|
<AppShell>
|
||||||
<svelte:fragment slot="pageHeader">
|
<svelte:fragment slot="pageHeader">
|
||||||
<GlobalSearch />
|
{#if $showSearch}
|
||||||
|
<AppBar>
|
||||||
|
<GlobalSearch />
|
||||||
|
</AppBar>
|
||||||
|
{/if}
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
|
||||||
<svelte:fragment slot="sidebarRight">
|
<svelte:fragment slot="sidebarRight">
|
||||||
<div class="p-2 h-dvh">
|
{#if post}
|
||||||
{#each tagTypes as [name, label]}
|
<div class="p-2 h-dvh">
|
||||||
<div class="mb-2">
|
{#each tagTypes as [name, label]}
|
||||||
<p class="font-bold">{label}</p>
|
<div class="mb-2">
|
||||||
{#each data.post.tags[name] as tag}
|
<p class="font-bold">{label}</p>
|
||||||
<p>{tag}</p>
|
{#each post.tags[name] as tag}
|
||||||
{/each}
|
<p>{tag}</p>
|
||||||
</div>
|
{/each}
|
||||||
{/each}
|
</div>
|
||||||
</div>
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
|
||||||
<svelte:fragment slot="sidebarLeft">
|
<svelte:fragment slot="sidebarLeft">
|
||||||
<div class="h-dvh">
|
<div class="h-dvh">
|
||||||
<AppRail>
|
<AppRail>
|
||||||
<svelte:fragment slot="lead">
|
<svelte:fragment slot="lead">
|
||||||
<BackAppRailAnchor popCount={2} />
|
<BackAppRailAnchor popCount={2} />
|
||||||
<SearchAppRailAnchor />
|
<SearchAppRailAnchor />
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
<svelte:fragment slot="trail">
|
<svelte:fragment slot="trail">
|
||||||
<AppRailAnchor on:click={() => {}}>
|
{#if post}
|
||||||
<div class="flex flex-col gap-2 place-content-center">
|
<AppRailAnchor>
|
||||||
<Fa size={'2x'} icon={faCopy} />
|
<button class="w-full flex flex-col gap-2 place-content-center place-items-center" use:clipboard={`https://e621.net/posts/${post.id}`} on:click={() => toastStore.trigger({message: 'Copied link'})}>
|
||||||
<p>Copy link</p>
|
<Fa size={'2x'} icon={faCopy} />
|
||||||
</div>
|
Copy link
|
||||||
</AppRailAnchor>
|
</button>
|
||||||
<AppRailAnchor on:click={() => drawerStore.open()}>
|
</AppRailAnchor>
|
||||||
<div class="flex flex-col gap-2 place-content-center">
|
{/if}
|
||||||
<Fa size={'2x'} icon={faGear} />
|
<AppRailAnchor on:click={() => drawerStore.open()}>
|
||||||
<p>Settings</p>
|
<button class="w-full flex flex-col gap-2 place-content-center place-items-center">
|
||||||
</div>
|
<Fa size={'2x'} icon={faGear} />
|
||||||
</AppRailAnchor>
|
Settings
|
||||||
</svelte:fragment>
|
</button>
|
||||||
</AppRail>
|
</AppRailAnchor>
|
||||||
</div>
|
</svelte:fragment>
|
||||||
|
</AppRail>
|
||||||
|
</div>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
|
||||||
<svelte:fragment slot="default">
|
<svelte:fragment slot="default">
|
||||||
<div class="container mx-auto p-2">
|
{#if post}
|
||||||
<div class="flex flex-row place-content-center">
|
<div class="container mx-auto p-2">
|
||||||
<PostMedia post={data.post} />
|
<div class="flex flex-row place-content-center" >
|
||||||
|
<PostMedia post={post} />
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<header class="px-3 pt-2">
|
||||||
|
<p class="font-bold" class:font-red={post.description === ''}>Description</p>
|
||||||
|
</header>
|
||||||
|
<section class="p-3">
|
||||||
|
<p>{post.description}</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card">
|
{/if}
|
||||||
<header class="px-3 pt-2">
|
|
||||||
<p class="font-bold">Description</p>
|
|
||||||
</header>
|
|
||||||
<section class="p-3">
|
|
||||||
<p>{data.post.description}</p>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</AppShell>
|
</AppShell>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue