Compare commits
No commits in common. "5183f73006c66e8e9f7eee3e38f696e4b4544315" and "998e8f2517bee19b54539e54de0a9b130ee1f272" have entirely different histories.
5183f73006
...
998e8f2517
|
@ -1,10 +0,0 @@
|
||||||
# Campfire v0.3.0
|
|
||||||
- Added notifications view
|
|
||||||
- Many more background tweaks, fixes, and optimisations
|
|
||||||
|
|
||||||
# Campfire v0.2.0
|
|
||||||
- Complete UI overhaul (thanks mae!)
|
|
||||||
- Added light and dark themes
|
|
||||||
- Added ability to like and boost posts
|
|
||||||
- Added ability to view threads in context
|
|
||||||
- Many background tweaks, fixes, and optimisations
|
|
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "campfire-client",
|
"name": "campfire-client",
|
||||||
"version": "0.3.0",
|
"version": "0.2.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "campfire-client",
|
"name": "campfire-client",
|
||||||
"version": "0.3.0",
|
"version": "0.2.0",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@poppanator/sveltekit-svg": "^4.2.1",
|
"@poppanator/sveltekit-svg": "^4.2.1",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "campfire-client",
|
"name": "campfire-client",
|
||||||
"version": "0.3.0",
|
"version": "0.2.0",
|
||||||
"description": "social media for the galaxy-wide-web! 🌌",
|
"description": "social media for the galaxy-wide-web! 🌌",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import { client } from '$lib/client/client.js';
|
import { client } from '../client/client.js';
|
||||||
import { user } from '$lib/stores/user.js';
|
|
||||||
import { capabilities } from '../client/instance.js';
|
import { capabilities } from '../client/instance.js';
|
||||||
import Post from '$lib/post.js';
|
import Post from '../post.js';
|
||||||
import User from '$lib/user/user.js';
|
import User from '../user/user.js';
|
||||||
import Emoji from '$lib/emoji.js';
|
import Emoji from '../emoji.js';
|
||||||
import { get } from 'svelte/store';
|
import { get } from 'svelte/store';
|
||||||
|
|
||||||
export async function createApp(host) {
|
export async function createApp(host) {
|
||||||
|
@ -93,7 +92,7 @@ export async function verifyCredentials() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getNotifications(since_id, limit, types) {
|
export async function getNotifications(since_id, limit, types) {
|
||||||
if (!get(user)) return false;
|
if (!get(client).user) return false;
|
||||||
|
|
||||||
let url = `https://${get(client).instance.host}/api/v1/notifications`;
|
let url = `https://${get(client).instance.host}/api/v1/notifications`;
|
||||||
|
|
||||||
|
@ -113,7 +112,6 @@ export async function getNotifications(since_id, limit, types) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getTimeline(last_post_id) {
|
export async function getTimeline(last_post_id) {
|
||||||
if (!get(user)) return false;
|
|
||||||
let url = `https://${get(client).instance.host}/api/v1/timelines/home`;
|
let url = `https://${get(client).instance.host}/api/v1/timelines/home`;
|
||||||
if (last_post_id) url += "?max_id=" + last_post_id;
|
if (last_post_id) url += "?max_id=" + last_post_id;
|
||||||
const data = await fetch(url, {
|
const data = await fetch(url, {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Instance, server_types } from './instance.js';
|
||||||
import * as api from './api.js';
|
import * as api from './api.js';
|
||||||
import { get, writable } from 'svelte/store';
|
import { get, writable } from 'svelte/store';
|
||||||
import { last_read_notif_id } from '$lib/notifications.js';
|
import { last_read_notif_id } from '$lib/notifications.js';
|
||||||
import { user, logged_in } from '$lib/stores/user.js';
|
import { user } from '$lib/stores/user.js';
|
||||||
|
|
||||||
export const client = writable(false);
|
export const client = writable(false);
|
||||||
|
|
||||||
|
@ -206,7 +206,6 @@ export class Client {
|
||||||
console.warn("Failed to log out correctly; ditching the old tokens anyways.");
|
console.warn("Failed to log out correctly; ditching the old tokens anyways.");
|
||||||
}
|
}
|
||||||
localStorage.removeItem(save_name);
|
localStorage.removeItem(save_name);
|
||||||
logged_in.set(false);
|
|
||||||
client.set(new Client());
|
client.set(new Client());
|
||||||
console.log("Logged out successfully.");
|
console.log("Logged out successfully.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ export async function getNotifications() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notif.status = notif.status ? await api.parsePost(notif.status, 0, false) : null;
|
notif.status = await api.parsePost(notif.status, 0, false);
|
||||||
notifications.update(notifications => [...notifications, notif]);
|
notifications.update(notifications => [...notifications, notif]);
|
||||||
}
|
}
|
||||||
last_read_notif_id.set(data[0].id);
|
last_read_notif_id.set(data[0].id);
|
||||||
|
|
|
@ -1,22 +1,4 @@
|
||||||
import { client } from '$lib/client/client.js';
|
import { writable } from 'svelte/store';
|
||||||
import * as api from '$lib/client/api.js';
|
|
||||||
import { get, writable } from 'svelte/store';
|
|
||||||
|
|
||||||
export let user = writable(0);
|
export let user = writable(0);
|
||||||
export let logged_in = writable(false);
|
export let logged_in = writable(false);
|
||||||
|
|
||||||
export async function getUser() {
|
|
||||||
// already known
|
|
||||||
if (get(user)) return get(user);
|
|
||||||
|
|
||||||
// cannot provide- not logged in
|
|
||||||
if (!get(client).app || !get(client).app.token) return false;
|
|
||||||
|
|
||||||
// logged in- attempt to retrieve using token
|
|
||||||
const data = await api.verifyCredentials();
|
|
||||||
if (!data) return false;
|
|
||||||
|
|
||||||
user.set(await api.parseUser(data));
|
|
||||||
console.log(`Logged in as @${get(user).username}@${get(user).host}`);
|
|
||||||
return get(user);
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
import Button from './Button.svelte';
|
import Button from './Button.svelte';
|
||||||
import Feed from './Feed.svelte';
|
import Feed from './Feed.svelte';
|
||||||
import { client } from '$lib/client/client.js';
|
import { client } from '$lib/client/client.js';
|
||||||
import { user } from '$lib/stores/user.js';
|
|
||||||
import { play_sound } from '$lib/sound.js';
|
import { play_sound } from '$lib/sound.js';
|
||||||
import { getTimeline } from '$lib/timeline.js';
|
import { getTimeline } from '$lib/timeline.js';
|
||||||
import { getNotifications } from '$lib/notifications.js';
|
import { getNotifications } from '$lib/notifications.js';
|
||||||
|
@ -151,11 +150,11 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="account-button">
|
<div id="account-button">
|
||||||
<img src={$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">
|
<div class="account-name" aria-hidden="true">
|
||||||
<a href={$user.url} class="nickname" title={$user.nickname}>{$user.nickname}</a>
|
<a href={$client.user.url} class="nickname" title={$client.user.nickname}>{$client.user.nickname}</a>
|
||||||
<span class="username" title={`@${$user.username}@${$user.host}`}>
|
<span class="username" title={`@${$client.user.username}@${$client.user.host}`}>
|
||||||
{`@${$user.username}@${$user.host}`}
|
{`@${$client.user.username}@${$client.user.host}`}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<a class="notification" href={data.status ? `/post/${data.status.id}` : null} aria-label={aria_label}>
|
<a class="notification" href={`/post/${data.status.id}`} aria-label={aria_label}>
|
||||||
<header aria-hidden>
|
<header aria-hidden>
|
||||||
<span class="notif-icon">
|
<span class="notif-icon">
|
||||||
{#if data.type === "favourite"}
|
{#if data.type === "favourite"}
|
||||||
|
@ -92,7 +92,7 @@
|
||||||
<style>
|
<style>
|
||||||
.notification {
|
.notification {
|
||||||
display: block;
|
display: block;
|
||||||
margin-bottom: 8px;
|
margin: 8px 0;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: var(--bg-800);
|
background: var(--bg-800);
|
||||||
|
|
|
@ -3,25 +3,27 @@
|
||||||
import Navigation from '$lib/ui/Navigation.svelte';
|
import Navigation from '$lib/ui/Navigation.svelte';
|
||||||
import Widgets from '$lib/ui/Widgets.svelte';
|
import Widgets from '$lib/ui/Widgets.svelte';
|
||||||
import { client, Client } from '$lib/client/client.js';
|
import { client, Client } from '$lib/client/client.js';
|
||||||
import { user, getUser } from '$lib/stores/user.js';
|
|
||||||
import { get } from 'svelte/store';
|
import { get } from 'svelte/store';
|
||||||
import { logged_in } from '$lib/stores/user.js';
|
import { logged_in } from '$lib/stores/user.js';
|
||||||
import { unread_notif_count, last_read_notif_id } from '$lib/notifications.js';
|
import { unread_notif_count, last_read_notif_id } from '$lib/notifications.js';
|
||||||
|
|
||||||
let ready = new Promise(resolve => {
|
let ready = new Promise(resolve => {
|
||||||
if (get(client)) {
|
if (get(client)) {
|
||||||
if (get(user)) logged_in.set(true);
|
if (get(client).user) logged_in.set(true);
|
||||||
return resolve();
|
return resolve();
|
||||||
}
|
}
|
||||||
let new_client = new Client();
|
let new_client = new Client();
|
||||||
new_client.load();
|
new_client.load();
|
||||||
client.set(new_client);
|
client.set(new_client);
|
||||||
|
|
||||||
return getUser().then(new_user => {
|
return new_client.getClientUser().then(user => {
|
||||||
if (!new_user) return resolve();
|
if (!user) {
|
||||||
|
client.set(new_client);
|
||||||
logged_in.set(true);
|
return resolve();
|
||||||
user.set(new_user);
|
}
|
||||||
|
if (user) logged_in.set(true);
|
||||||
|
new_client.user = user;
|
||||||
|
window.peekie = new_client;
|
||||||
|
|
||||||
// spin up async task to fetch notifications
|
// spin up async task to fetch notifications
|
||||||
get(client).getNotifications(
|
get(client).getNotifications(
|
||||||
|
@ -31,6 +33,10 @@
|
||||||
unread_notif_count.set(notif_data.length);
|
unread_notif_count.set(notif_data.length);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
client.update(client => {
|
||||||
|
client.user = user;
|
||||||
|
return client;
|
||||||
|
});
|
||||||
return resolve();
|
return resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import { get } from 'svelte/store';
|
import { get } from 'svelte/store';
|
||||||
import { logged_in } from '$lib/stores/user.js';
|
import { client } from '$lib/client/client.js';
|
||||||
import { timeline, getTimeline } from '$lib/timeline.js';
|
import { timeline, getTimeline } from '$lib/timeline.js';
|
||||||
|
|
||||||
import LoginForm from '$lib/ui/LoginForm.svelte';
|
import LoginForm from '$lib/ui/LoginForm.svelte';
|
||||||
|
@ -9,18 +9,16 @@
|
||||||
import User from '$lib/user/user.js';
|
import User from '$lib/user/user.js';
|
||||||
import Button from '$lib/ui/Button.svelte';
|
import Button from '$lib/ui/Button.svelte';
|
||||||
|
|
||||||
logged_in.subscribe(logged_in => {
|
getTimeline();
|
||||||
if (logged_in) getTimeline();
|
|
||||||
});
|
|
||||||
document.addEventListener("scroll", event => {
|
document.addEventListener("scroll", event => {
|
||||||
if (get(logged_in) && get(page).url.pathname !== "/") return;
|
if (get(page).url.pathname !== "/") return;
|
||||||
if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 2048) {
|
if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 2048) {
|
||||||
getTimeline();
|
getTimeline();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $logged_in}
|
{#if $client.user}
|
||||||
<Feed posts={$timeline} />
|
<Feed posts={$timeline} />
|
||||||
{:else}
|
{:else}
|
||||||
<LoginForm />
|
<LoginForm />
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { error } from '@sveltejs/kit';
|
import { error } from '@sveltejs/kit';
|
||||||
import { get } from 'svelte/store';
|
import { get } from 'svelte/store';
|
||||||
import { last_read_notif_id } from '$lib/notifications.js';
|
|
||||||
import { logged_in, user, getUser } from '$lib/stores/user.js';
|
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
|
|
||||||
|
@ -25,18 +23,24 @@
|
||||||
return c;
|
return c;
|
||||||
});
|
});
|
||||||
|
|
||||||
getUser().then(new_user => {
|
get(client).getClientUser().then(user => {
|
||||||
if (!new_user) return;
|
if (user) client.update(client => {
|
||||||
|
client.user = user
|
||||||
logged_in.set(true);
|
return client;
|
||||||
user.set(new_user);
|
});
|
||||||
|
|
||||||
return get(client).getNotifications(
|
return get(client).getNotifications(
|
||||||
get(last_read_notif_id)
|
get(last_read_notification_id)
|
||||||
).then(notif_data => {
|
).then(notif_data => {
|
||||||
|
client.update(client => {
|
||||||
|
// we've just logged in, so assume all past notifications are read.
|
||||||
|
// i *would* just use the mastodon marker API to get the last read
|
||||||
|
// notification, but this does not appear to be widely supported.
|
||||||
if (notif_data.constructor === Array && notif_data.length > 0)
|
if (notif_data.constructor === Array && notif_data.length > 0)
|
||||||
last_read_notif_id.set(notif_data[0].id);
|
last_read_notification_id.set(notif_data[0].id);
|
||||||
get(client).save();
|
client.save();
|
||||||
|
return client;
|
||||||
|
});
|
||||||
goto("/");
|
goto("/");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,16 +1,10 @@
|
||||||
<script>
|
<script>
|
||||||
import { notifications, getNotifications } from '$lib/notifications.js';
|
import { notifications, getNotifications } from '$lib/notifications.js';
|
||||||
import { logged_in } from '$lib/stores/user.js';
|
|
||||||
import { goto } from '$app/navigation';
|
|
||||||
import { get } from 'svelte/store';
|
|
||||||
import Notification from '$lib/ui/Notification.svelte';
|
import Notification from '$lib/ui/Notification.svelte';
|
||||||
|
|
||||||
if (!get(logged_in)) goto("/");
|
|
||||||
|
|
||||||
getNotifications();
|
getNotifications();
|
||||||
/*
|
/*
|
||||||
document.addEventListener("scroll", event => {
|
document.addEventListener("scroll", event => {
|
||||||
if (get(logged_in) && get(page).url.pathname !== "/") return;
|
|
||||||
if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 2048) {
|
if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 2048) {
|
||||||
getNotifications();
|
getNotifications();
|
||||||
}
|
}
|
||||||
|
@ -47,6 +41,10 @@
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.notifications {
|
||||||
|
margin: 16px 0;
|
||||||
|
}
|
||||||
|
|
||||||
.loading {
|
.loading {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 80vh;
|
height: 80vh;
|
||||||
|
|
Loading…
Reference in a new issue