Compare commits

...

4 commits

24 changed files with 220 additions and 29 deletions

View file

@ -1,7 +1,7 @@
{
"name": "@yusurko/vigil",
"private": true,
"version": "0.1.0-dev43",
"version": "0.1.0-dev47",
"type": "module",
"scripts": {
"dev": "vite dev",

View file

@ -1,6 +1,6 @@
<script lang="ts">
let { query = $bindable<string>() }: {query?: string} = $props();
let { query }: {query?: string} = $props();
</script>
<input value={query} type="search" name="query" class="bigsearch" />

View file

@ -1,14 +1,15 @@
<script lang="ts">
let { narrow = false, children } : { narrow?: boolean, children: any } = $props();
let { narrow = false, small = false, children } : { narrow?: boolean, small ?: boolean, children: any } = $props();
</script>
<div class="centered" class:narrow={narrow}>
<div class="centered" class:narrow={narrow} class:small={small}>
{@render children () }
</div>
<style>
.centered {text-align: center;}
.centered.narrow { max-width: 400px; margin: auto; }
.centered.small { font-size: smaller; }
</style>

View file

@ -0,0 +1,29 @@
<script lang="ts">
import Centered from "./Centered.svelte";
</script>
<Centered small={true}>
<p>&copy; 2021-2025 Sakuragasaki46.</p>
<ul>
<li><a href="/about">About</a></li>
<li><a href="/terms">Terms</a></li>
<li><a href="/privacy">Privacy</a></li>
<li><a href="https://nekode.yusur.moe/yusur/freak" target="_blank">GitHub</a></li>
</ul>
</Centered>
<style>
ul {
list-style: none;
display: flex;
align-items: center;
justify-content: stretch;
max-width: 640px;
margin: auto;
}
ul > li {
flex: 1;
}
</style>

View file

@ -19,12 +19,11 @@
<style>
ul {
list-style: none;
padding: 0 1em;
padding: 0;
}
ul > li {
margin-top: 3px;
margin-bottom: 3px;
margin: 3px 0;
}
p.big {

View file

@ -30,10 +30,11 @@ let { id, title, content = "", votes, my_vote, comment_count } = post;
.post-frame {
padding-inline-start: 2em;
position: relative;
min-height: 7em;
}
.message-stats {
position: absolute;
inset-inline-start: 0;
inset-inline-start: -6px;
top: 0;
width: 2em;
display: flex;

View file

@ -81,12 +81,13 @@ let { title, id, content = '', to, votes, my_vote, comment_count } = post;
}
.message-stats {
position: absolute;
inset-inline-start: 0;
inset-inline-start: -6px;
top: 0;
width: 2em;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
margin-inline-end: 6px;
}
</style>

View file

@ -27,7 +27,7 @@ let me = $derived(getMe());
<style>
footer {
position: sticky;
position: fixed;
bottom: 0;
left: 0;
width: 100%;

View file

@ -17,4 +17,10 @@ let { post } : {post: PostEntry }= $props();
<style>
ul.post-meta > li { margin-inline-end: 9px; }
@media (max-width:799px) {
ul.post-meta {
font-size: .8em;
}
}
</style>

View file

@ -28,12 +28,12 @@ let mobiRightActive = $state(false);
grid-template-areas:
". title ."
"left center right";
margin: 1em 2em;
padding: 1em 2em;
position: relative;
}
.layout-left { grid-area: left; padding-right: 1em; }
.layout-right { grid-area: right; padding-left: 1em; }
.layout-left { grid-area: left; padding-inline-end: 1em; }
.layout-right { grid-area: right; padding-inline-start: 1em; }
.layout-content { grid-area: center; }
.layout-title { grid-area: title; text-align: center; font-size: 1.4em; }
@ -86,6 +86,8 @@ let mobiRightActive = $state(false);
"center center center";
grid-template-columns: 2em auto 2em;
padding: 1em .5em;
}
.layout-left, .layout-right { display: none; }
@ -107,6 +109,10 @@ let mobiRightActive = $state(false);
right: 0;
}
.layout-content {
font-size: .9em;
}
}

View file

@ -9,6 +9,7 @@ import type { ServerHealth, UserEntry } from '$lib/backend';
import { getFlash } from 'sveltekit-flash-message';
import { page } from "$app/state";
import FlashMessage from '$lib/FlashMessage.svelte';
import DesktopFooter from '$lib/DesktopFooter.svelte';
let { data, children } : {
data: {me: UserEntry},
@ -53,6 +54,8 @@ let colorThemeCls = $derived(`color-scheme-${colorScheme} color-theme-${colorThe
{@render children()}
</main>
<DesktopFooter />
<MobileFooter />
</div>

View file

@ -0,0 +1,43 @@
import { backend } from '$lib/backend.js';
import { redirect } from 'sveltekit-flash-message/server';
export const actions = {
async default (event) {
const { request }= event;
const data = await request.formData();
const guildName = ''+data.get('to');
const title = data.get('title');
const content = data.get('content');
const privacy = +(data.get('privacy') || 0);
const backend2 = await backend.withEvent(event).oath();
const resp = await backend2.submitJson(`guild/@${encodeURIComponent(guildName)}`, {
title, content, privacy
})
const { status } = resp;
const respData = await resp.json();
if ([200, 204].indexOf(status) < 0) {
// error
console.log(`/create: status ${status}`);
switch(status) {
case 403:
case 404:
redirect({
message: respData.error
}, event);
break;
default:
redirect({message: `Unknown error (HTTP ${status})`}, event);
break;
}
} else {
const { id: myId } = respData;
redirect(303, "/=" + myId);
}
}
};

View file

@ -1,4 +1,5 @@
<script lang="ts">
import { enhance } from "$app/forms";
import Centered from "$lib/Centered.svelte";
import EditPost from "$lib/EditPost.svelte";
import { getMe } from "$lib/globals.svelte";
@ -12,14 +13,15 @@
let content = $state("");
let privacy = $state(0);
let guildName = $state("");
//let guildInfo = $state(null);
let enablePost = $derived(!!content && !!guildName && false);
let enablePost = $derived(!!content && !!guildName);
</script>
{#if me}
<SLayout title="New post">
<form method="POST" class="card">
<form method="POST" class="card" use:enhance>
<p>Posting as <strong>@{me.username}</strong></p>
<label>

View file

@ -45,7 +45,7 @@ export const actions = {
// login success
const { id: myId } = respData;
redirect(303, "/user/" + myId);
redirect(303, "/@" + myId);
}
}
} satisfies Actions;

View file

@ -0,0 +1,13 @@
<script lang="ts">
import { SvelteShowdown } from "svelte-showdown";
let { data }: { data: {content: string} } = $props();
let { content } = data;
</script>
<article class="card">
<p class="faint">Privacy Policy</p>
<SvelteShowdown {content} />
</article>

View file

@ -0,0 +1,19 @@
import { backend } from '$lib/backend.js';
import { error } from '@sveltejs/kit';
export async function load(event) {
const resp = await backend.withEvent(event).fetch('about/privacy');
if(resp.status === 404) {
error(404);
}
const respJ = await resp.json();
const { content } = respJ;
return { content };
}

View file

@ -0,0 +1,13 @@
<script lang="ts">
import { SvelteShowdown } from "svelte-showdown";
let { data }: { data: {content: string} } = $props();
let { content } = data;
</script>
<article class="card">
<p class="faint">Community Guidelines</p>
<SvelteShowdown {content} />
</article>

19
src/routes/rules/+page.ts Normal file
View file

@ -0,0 +1,19 @@
import { backend } from '$lib/backend.js';
import { error } from '@sveltejs/kit';
export async function load(event) {
const resp = await backend.withEvent(event).fetch('about/rules');
if(resp.status === 404) {
error(404);
}
const respJ = await resp.json();
const { content } = respJ;
return { content };
}

View file

@ -32,12 +32,9 @@ export const actions = {
event.locals.results = results;
event.locals.query = query;
console.log(event.locals);
}
} satisfies Actions;
export function load (event) {
const { results, query } = event.locals;
return { results, query };
}
} satisfies Actions;

View file

@ -1,23 +1,30 @@
<script lang="ts">
import { enhance } from "$app/forms";
import type { PostEntry } from "$lib/backend";
import BigSearchInput from "$lib/BigSearchInput.svelte";
import Feed from "$lib/Feed.svelte";
import { RiSearchLine } from "svelte-remixicon";
import type { PageProps } from "./$types";
let { data }: PageProps = $props();
console.log(data);
let { data }: {
data: {
query: string,
results: PostEntry[]
}
} = $props();
let { query, results } = $derived(data);
</script>
<form method="POST" use:enhance>
<ul class="row">
<BigSearchInput bind:query />
<button class="inline"><RiSearchLine /></button>
<BigSearchInput {query} />
<button type="submit" class="inline"><RiSearchLine /></button>
</ul>
</form>
{#if query}
<Feed posts={results} />
{:else}
<p>Search function is broken!</p>
{/if}

View file

@ -0,0 +1,13 @@
<script lang="ts">
import { SvelteShowdown } from "svelte-showdown";
let { data }: { data: {content: string} } = $props();
let { content } = data;
</script>
<article class="card">
<p class="faint">Terms of Service</p>
<SvelteShowdown {content} />
</article>

19
src/routes/terms/+page.ts Normal file
View file

@ -0,0 +1,19 @@
import { backend } from '$lib/backend.js';
import { error } from '@sveltejs/kit';
export async function load(event) {
const resp = await backend.withEvent(event).fetch('about/terms');
if(resp.status === 404) {
error(404);
}
const respJ = await resp.json();
const { content } = respJ;
return { content };
}

View file

@ -11,8 +11,6 @@ export async function load(event) {
error(404);
}
const respJ = await resp.json();
let { users } = respJ;

View file

@ -4,6 +4,8 @@ import { configDotenv } from 'dotenv';
configDotenv();
console.info(`server name is ${process.env.SERVER_NAME}`);
export default defineConfig({
plugins: [sveltekit()],
server: {