i think i finally fixed the state management awfulness

This commit is contained in:
ari melody 2024-07-01 03:41:02 +01:00
parent 6953b49563
commit 40be540527
Signed by: ari
GPG key ID: CF99829C92678188
18 changed files with 402 additions and 417 deletions

View file

@ -1,10 +1,6 @@
<script>
import Button from './Button.svelte';
import Post from './post/Post.svelte';
import Error from './Error.svelte';
import { Client } from '$lib/client/client.js';
import { parsePost } from '$lib/client/api.js';
import { get } from 'svelte/store';
import { posts, getTimeline } from '$lib/timeline.js';
getTimeline();
@ -15,6 +11,15 @@
});
</script>
<header>
<h1>Home</h1>
<nav>
<Button centered active>Home</Button>
<Button centered disabled>Local</Button>
<Button centered disabled>Federated</Button>
</nav>
</header>
<div id="feed" role="feed">
{#if posts.length <= 0}
<div class="loading throb">

162
src/lib/ui/LoginForm.svelte Normal file
View file

@ -0,0 +1,162 @@
<script>
import { client } from '$lib/client/client.js';
import { get } from 'svelte/store';
import Logo from '$lib/../img/campfire-logo.svg';
let instance_url_error = false;
let logging_in = false;
function log_in(event) {
event.preventDefault();
instance_url_error = false;
logging_in = true;
const host = event.target.host.value;
if (!host || host === "") {
instance_url_error = "Please enter an instance domain.";
logging_in = false;
return;
}
console.log(client);
get(client).init(host).then(res => {
logging_in = false;
if (!res) return;
if (res.constructor === String) {
instance_url_error = res;
return;
};
let oauth_url = get(client).getOAuthUrl();
location = oauth_url;
});
}
</script>
<form on:submit={log_in} id="login-form">
<div class="app-logo">
<Logo />
</div>
<p>Welcome, fediverse user!</p>
<p>Please enter your instance domain to log in.</p>
<div class="input-wrapper">
<input type="text" id="host" aria-label="instance domain" class={logging_in ? "throb" : ""}>
{#if instance_url_error}
<p class="error">{instance_url_error}</p>
{/if}
</div>
<br>
<button type="submit" id="login" class={logging_in ? "disabled" : ""}>Log in</button>
<p><small>
Please note this is
<strong><em>extremely experimental software</em></strong>;
things are likely to break!
<br>
If that's all cool with you, welcome aboard!
</small></p>
<p class="form-footer">made with ❤ by <a href="https://bliss.town">bliss town</a>, 2024</p>
</form>
<style>
form#login-form {
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
}
.input-wrapper {
width: 360px;
margin: 0 auto;
display: flex;
flex-direction: column;
align-items: center;
}
input[type=text] {
width: 100%;
padding: 12px;
display: block;
border-radius: 8px;
border: 1px solid var(--accent);
background-color: var(--bg-800);
font-family: inherit;
font-weight: bold;
font-size: inherit;
color: var(--text);
transition: box-shadow .2s;
}
input[type=text]::placeholder {
opacity: .8;
}
input[type=text]:focus {
outline: none;
box-shadow: 0 0 16px color-mix(in srgb, transparent, var(--accent) 25%);
}
.error {
margin: 6px;
font-style: italic;
font-size: .9em;
color: red;
opacity: .7;
}
button#login {
margin: 8px auto;
padding: 12px 24px;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
font-family: inherit;
font-size: 1rem;
font-weight: 600;
text-align: left;
border-radius: 8px;
border-width: 2px;
border-style: solid;
background-color: var(--bg-700);
color: var(--text);
border-color: transparent;
transition-property: border-color, background-color, color;
transition-timing-function: ease-out;
transition-duration: .1s;
cursor: pointer;
text-align: center;
justify-content: center;
}
button#login:hover {
background-color: color-mix(in srgb, var(--bg-700), var(--accent) 10%);
border-color: color-mix(in srgb, var(--bg-700), var(--accent) 20%);
}
button#login:active {
background-color: color-mix(in srgb, var(--bg-700), var(--bg-800) 50%);
border-color: color-mix(in srgb, var(--bg-700), var(--bg-800) 10%);
}
button#login.disabled {
opacity: .5;
cursor: initial;
}
.form-footer {
opacity: .7;
}
</style>

View file

@ -2,7 +2,7 @@
import Logo from '$lib/../img/campfire-logo.svg';
import Button from './Button.svelte';
import Feed from './Feed.svelte';
import { Client } from '$lib/client/client.js';
import { client } from '$lib/client/client.js';
import { play_sound } from '$lib/sound.js';
import { getTimeline } from '$lib/timeline.js';
import { goto } from '$app/navigation';
@ -22,11 +22,6 @@
const VERSION = APP_VERSION;
let client = false;
Client.get().subscribe(c => {
client = c;
});
let notification_count = 0;
if (notification_count > 99) notification_count = "99+";
@ -44,26 +39,20 @@
async function log_out() {
if (!confirm("This will log you out. Are you sure?")) return;
await get(Client.get()).logout();
await get(client).logout();
goto("/");
}
</script>
<div id="navigation">
{#if client.instance && client.instance.icon_url && client.instance.banner_url}
<header class="instance-header" style="background-image: url({client.instance.banner_url})">
<img src={client.instance.icon_url} class="instance-icon" height="92px" aria-hidden="true">
</header>
{:else}
<header class="instance-header">
<div class="app-logo">
<Logo />
</div>
</header>
{/if}
<header class="instance-header">
<div class="app-logo">
<Logo />
</div>
</header>
<div id="nav-items">
<Button label="Timeline" on:click={() => goTimeline()} active={client.user}>
<Button label="Timeline" on:click={() => goTimeline()} active={!!$client.user}>
<svelte:fragment slot="icon">
<TimelineIcon/>
</svelte:fragment>
@ -117,7 +106,7 @@
</Button>
</div>
{#if (client.user)}
{#if $client.user}
<div id="account-items">
<div class="flex-row">
<Button centered label="Profile information" disabled>
@ -138,11 +127,11 @@
</div>
<div id="account-button">
<img src={client.user.avatar_url} class="account-avatar" height="64px" alt="" aria-hidden="true" on:click={() => play_sound()}>
<img src={$client.user.avatar_url} class="account-avatar" height="64px" alt="" aria-hidden="true" on:click={() => play_sound()}>
<div class="account-name" aria-hidden="true">
<span class="nickname" title={client.user.nickname}>{client.user.nickname}</span>
<span class="username" title={`@${client.user.username}@${client.user.host}`}>
{`@${client.user.username}@${client.user.host}`}
<span class="nickname" title={$client.user.nickname}>{$client.user.nickname}</span>
<span class="username" title={`@${$client.user.username}@${$client.user.host}`}>
{`@${$client.user.username}@${$client.user.host}`}
</span>
</div>
</div>

View file

@ -1,5 +1,5 @@
<script>
import { Client } from '../../client/client.js';
import { client } from '../../client/client.js';
import * as api from '../../client/api.js';
import { get } from 'svelte/store';
@ -16,12 +16,11 @@
export let post;
async function toggleBoost() {
let client = get(Client.get());
let data;
if (post.boosted)
data = await client.unboostPost(post.id);
data = await get(client).unboostPost(post.id);
else
data = await client.boostPost(post.id);
data = await get(client).boostPost(post.id);
if (!data) {
console.error(`Failed to boost post ${post.id}`);
return;
@ -31,12 +30,11 @@
}
async function toggleFavourite() {
let client = get(Client.get());
let data;
if (post.favourited)
data = await client.unfavouritePost(post.id);
data = await get(client).unfavouritePost(post.id);
else
data = await client.favouritePost(post.id);
data = await get(client).favouritePost(post.id);
if (!data) {
console.error(`Failed to favourite post ${post.id}`);
return;
@ -48,13 +46,12 @@
async function toggleReaction(reaction) {
if (reaction.name.includes('@')) return;
let client = get(Client.get());
let data;
if (reaction.me)
data = await client.unreactPost(post.id, reaction.name);
data = await get(client).unreactPost(post.id, reaction.name);
else
data = await client.reactPost(post.id, reaction.name);
data = await get(client).reactPost(post.id, reaction.name);
if (!data) {
console.error(`Failed to favourite post ${post.id}`);
return;

View file

@ -50,7 +50,9 @@
<div class="post-container">
{#if post.reply}
<ReplyContext post={post.reply} />
{#await post.reply then reply}
<ReplyContext post={reply} />
{/await}
{/if}
{#if is_boost && !post_context.text}
<BoostContext post={post_context} />

View file

@ -1,8 +1,6 @@
<script>
import { parseText as parseEmojis, parseOne as parseEmoji } from '../../emoji.js';
import { shorthand as short_time } from '../../time.js';
import { get } from 'svelte/store';
import { Client } from '../../client/client.js';
import * as api from '../../client/api.js';
import { goto } from '$app/navigation';
@ -20,19 +18,20 @@
function gotoPost() {
if (event && event.key && event.key !== "Enter") return;
console.log(`/post/${post.id}`);
goto(`/post/${post.id}`);
}
</script>
{#if post.reply}
<svelte:self post={post.reply} />
{#await post.reply then reply}
<svelte:self post={reply} />
{/await}
{/if}
<article
class="post-reply"
aria-label={aria_label}
on:mousedown={e => {mouse_pos.left = e.pageX; mouse_pos.top = e.pageY; console.log(mouse_pos)}}
on:mousedown={e => {mouse_pos.left = e.pageX; mouse_pos.top = e.pageY}}
on:mouseup={e => {if (e.pageX == mouse_pos.left && e.pageY == mouse_pos.top) gotoPost()}}
on:keydown={gotoPost}>
<div class="line"></div>