Compare commits
No commits in common. "7ed8ebf6e5c1eec9af19f31304fb65ba57f93335" and "0dd903a4ebdc3bfabbbf76393546a0a6136f36af" have entirely different histories.
7ed8ebf6e5
...
0dd903a4eb
12 changed files with 56 additions and 315 deletions
|
@ -1,3 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 32 32">
|
|
||||||
<path d="M20.763 7.627a2 2 0 1 1 2.908 2.746l-5.236 5.545 5.547 5.236.141.149a2 2 0 0 1-2.887 2.76l-5.546-5.237-5.236 5.547a2 2 0 1 1-2.908-2.746l5.236-5.546-5.546-5.235-.142-.149a2 2 0 0 1 2.731-2.893l.157.133 5.545 5.236 5.236-5.546Z"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 329 B |
|
@ -1,3 +0,0 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 32 32">
|
|
||||||
<path d="M24.546 8.627a2 2 0 0 1 2.908 2.746l-.03.032-.03.032-.03.032-.03.032-.06.064-.06.063-.12.126c-.036.04-.02.023-.058.062l-.03.032-.059.062-.029.03-.059.063-.058.062-.03.03-.028.032-.116.122-.028.03-.03.032c-.097.103.04-.044-.057.06l-.453.48-.223.236-.11.117-.11.116-.856.907-.052.055-.053.056-.31.328-.051.055-.026.027-.026.027c-.114.122.064-.067-.05.054l-.026.027-.025.027-.051.055-.026.026-.025.027-.102.108-.05.052-.026.028-.024.026-.1.107-.051.052-.15.159-.024.026-.026.026-.049.053-.1.105-.023.026-.025.026-.025.027-.025.025-.097.104-.099.104-.024.026-.025.026-.146.155-.048.052-.049.05-.097.103-.049.052-.047.05-.097.103-.096.102c-.09.095.042-.045-.049.05l-.023.026-.024.025-.192.203-.023.026-.024.024-.024.026-.024.025-.38.403-.095.1-.095.1c-.04.043-.006.008-.047.05l-.023.026-.025.025-.093.1-.19.2-.023.025-.024.025-.046.05-.19.2-.047.05-.047.05-.19.2-.023.025-.023.025c-.084.089.036-.038-.048.05l-.047.05-.048.05a59.55 59.55 0 0 1-.094.1c-.104.11.057-.059-.047.051l-.048.05-.047.05-.023.025-.025.025c-.058.062.011-.01-.047.051-.042.046-.005.005-.048.05l-.094.1-.025.026-.023.025-.048.051-.048.05-.335.355-1.572 1.666-.102.107-.025.027-.025.027-.026.027-.025.026-.102.109-.026.027-.05.055-.027.026-.051.055-.026.027-.026.027-.103.11c-.033.035-.02.02-.052.056l-.053.054-.025.028-.053.055-.026.029-.105.11c-.052.056 0 .002-.053.056l-.026.029-.026.027-.027.028-.027.029-.053.056-.106.113c-.066.07.012-.014-.054.056l-.026.029-.028.028-.107.114c-.076.08-.032.035-.108.116l-.11.115-.11.116-.027.03-.083.087-.222.236-.226.238-.113.12-.03.031-.084.091-.03.03-.028.03-.03.03-.027.032-.06.06c-.123.132.067-.069-.057.062l-.029.031-.03.03-.028.032-.058.062-.03.03-.029.032-.03.031-.059.063-.06.062c-.09.097-.026.03-.117.126l-.24.255a2.002 2.002 0 0 1-2.91 0l-5.782-6.125-.133-.156a2 2 0 0 1 3.041-2.59l4.328 4.584.164-.173c.057-.06 0 .002.056-.058l.055-.06.054-.057.029-.029.027-.03.108-.114.028-.029.027-.03.027-.027.027-.03.054-.056.027-.029.027-.029.027-.028.027-.029.053-.056.027-.029.026-.028.054-.057.053-.055c.095-.1-.042.044.053-.057l.21-.223.21-.22.103-.11.05-.055.027-.027.05-.054.027-.028.051-.054.103-.108.203-.216.2-.212.1-.106.026-.026.024-.027.026-.026.024-.027.025-.026.05-.053.025-.026.098-.105.05-.052.049-.052.099-.104.39-.414c.107-.113-.01.012.097-.102.098-.103-.05.052.048-.052l.049-.05.095-.103.097-.102.048-.05.023-.026.025-.025.191-.203.024-.026.024-.024.023-.026.025-.025.38-.403.094-.1.095-.1.047-.05.024-.026.024-.025.047-.05.048-.05.188-.2.023-.025.025-.025.047-.05.047-.05.047-.05.094-.1.048-.05.047-.05.188-.2.025-.025.023-.025.047-.05.048-.05.047-.05.095-.1c.067-.072-.02.02.046-.051.05-.052 0 .002.048-.05l.048-.05.024-.025.023-.025c.054-.058.04-.044.095-.101l.096-.1.023-.026.024-.025.047-.051.025-.025.023-.025.096-.101.023-.026.025-.025.191-.203 1.572-1.666.026-.027.025-.026.152-.161.103-.109.05-.054.027-.028.026-.026.206-.22.052-.055.052-.054.052-.056.264-.278.212-.226.053-.056.054-.057.055-.058.053-.056.109-.115.109-.116.055-.058.027-.029.027-.029.11-.117.223-.236.454-.48c.046-.05.01-.011.057-.06l.058-.062.115-.122.03-.031.029-.03.087-.094.03-.03.117-.126.06-.062.029-.031.03-.033.06-.062.06-.064.03-.032.029-.031.06-.064.06-.064Z"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 3.2 KiB |
|
@ -23,7 +23,6 @@
|
||||||
"navigation": {
|
"navigation": {
|
||||||
"timeline": "Timeline",
|
"timeline": "Timeline",
|
||||||
"notifications": "Notifications",
|
"notifications": "Notifications",
|
||||||
"follow_requests": "Follow requests",
|
|
||||||
"explore": "Explore",
|
"explore": "Explore",
|
||||||
"lists": "Lists",
|
"lists": "Lists",
|
||||||
|
|
||||||
|
@ -38,10 +37,6 @@
|
||||||
"back": "Back"
|
"back": "Back"
|
||||||
},
|
},
|
||||||
|
|
||||||
"follow_requests": {
|
|
||||||
"none": "no follow requests to action right now!"
|
|
||||||
},
|
|
||||||
|
|
||||||
"timeline": {
|
"timeline": {
|
||||||
"home": "Home",
|
"home": "Home",
|
||||||
"local": "Local",
|
"local": "Local",
|
||||||
|
|
|
@ -176,66 +176,6 @@ export async function getNotifications(host, token, min_id, max_id, limit, types
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* GET /api/v1/follow_requests
|
|
||||||
* @param {string} host - The domain of the target server.
|
|
||||||
* @param {string} token - The application token.
|
|
||||||
* @param {string} min_id - If provided, only shows follow requests since this ID.
|
|
||||||
* @param {string} max_id - If provided, only shows follow requests before this ID.
|
|
||||||
* @param {string} limit - The maximum number of follow requests to retrieve (default 40, max 80).
|
|
||||||
*/
|
|
||||||
export async function getFollowRequests(host, token, since_id, max_id, limit) {
|
|
||||||
let url = `https://${host}/api/v1/follow_requests`;
|
|
||||||
|
|
||||||
let params = new URLSearchParams();
|
|
||||||
if (since_id) params.append("since_id", since_id);
|
|
||||||
if (max_id) params.append("max_id", max_id);
|
|
||||||
if (limit) params.append("limit", limit);
|
|
||||||
const params_string = params.toString();
|
|
||||||
if (params_string) url += '?' + params_string;
|
|
||||||
|
|
||||||
const data = await fetch(url, {
|
|
||||||
method: 'GET',
|
|
||||||
headers: { "Authorization": "Bearer " + token }
|
|
||||||
}).then(res => res.json());
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* POST /api/v1/follow_requests/:account_id/authorize
|
|
||||||
* @param {string} host - The domain of the target server.
|
|
||||||
* @param {string} token - The application token.
|
|
||||||
* @param {string} account_id - The account ID of the follow request to accept
|
|
||||||
*/
|
|
||||||
export async function acceptFollowRequest(host, token, account_id) {
|
|
||||||
let url = `https://${host}/api/v1/follow_requests/${account_id}/authorize`;
|
|
||||||
|
|
||||||
const data = await fetch(url, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { "Authorization": "Bearer " + token }
|
|
||||||
}).then(res => res.json());
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* POST /api/v1/follow_requests/:account_id/reject
|
|
||||||
* @param {string} host - The domain of the target server.
|
|
||||||
* @param {string} token - The application token.
|
|
||||||
* @param {string} account_id - The account ID of the follow request to reject
|
|
||||||
*/
|
|
||||||
export async function rejectFollowRequest(host, token, account_id) {
|
|
||||||
let url = `https://${host}/api/v1/follow_requests/${account_id}/reject`;
|
|
||||||
|
|
||||||
const data = await fetch(url, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { "Authorization": "Bearer " + token }
|
|
||||||
}).then(res => res.json());
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /api/v1/timelines/{timeline}
|
* GET /api/v1/timelines/{timeline}
|
||||||
* @param {string} host - The domain of the target server.
|
* @param {string} host - The domain of the target server.
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
import { server } from './client/server.js';
|
|
||||||
import { writable } from "svelte/store";
|
|
||||||
import * as api from "./api.js";
|
|
||||||
import { app } from './client/app.js';
|
|
||||||
import { get } from 'svelte/store';
|
|
||||||
import { parseAccount } from './account.js';
|
|
||||||
|
|
||||||
// Cache for all requests
|
|
||||||
export let followRequests = writable();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets all follow requests
|
|
||||||
* @param {boolean} force
|
|
||||||
*/
|
|
||||||
export async function fetchFollowRequests(force) {
|
|
||||||
// if already cached, return for now
|
|
||||||
if(!get(followRequests) && !force) return;
|
|
||||||
|
|
||||||
let newReqs = await api.getFollowRequests(
|
|
||||||
get(server).host,
|
|
||||||
get(app).token
|
|
||||||
);
|
|
||||||
|
|
||||||
// parse accounts
|
|
||||||
newReqs = newReqs.map((r) => parseAccount(r));
|
|
||||||
|
|
||||||
followRequests.set(newReqs);
|
|
||||||
}
|
|
|
@ -154,7 +154,8 @@
|
||||||
a.disabled,
|
a.disabled,
|
||||||
button.disabled {
|
button.disabled {
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
opacity: .35;
|
opacity: .5;
|
||||||
|
background: transparent;
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,8 @@
|
||||||
import { playSound } from '$lib/sound.js';
|
import { playSound } from '$lib/sound.js';
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import { createEventDispatcher, onMount } from 'svelte';
|
import { createEventDispatcher } from 'svelte';
|
||||||
import { unread_notif_count } from '$lib/notifications.js';
|
import { unread_notif_count } from '$lib/notifications.js';
|
||||||
import { fetchFollowRequests, followRequests } from '$lib/followRequests.js'
|
|
||||||
import Lang from '$lib/lang';
|
import Lang from '$lib/lang';
|
||||||
|
|
||||||
import Logo from '$lib/../img/campfire-logo.svg';
|
import Logo from '$lib/../img/campfire-logo.svg';
|
||||||
|
@ -25,7 +24,6 @@
|
||||||
import InfoIcon from '../../img/icons/info.svg';
|
import InfoIcon from '../../img/icons/info.svg';
|
||||||
import SettingsIcon from '../../img/icons/settings.svg';
|
import SettingsIcon from '../../img/icons/settings.svg';
|
||||||
import LogoutIcon from '../../img/icons/logout.svg';
|
import LogoutIcon from '../../img/icons/logout.svg';
|
||||||
import FollowersIcon from '../../img/icons/followers.svg';
|
|
||||||
|
|
||||||
const VERSION = APP_VERSION;
|
const VERSION = APP_VERSION;
|
||||||
const lang = Lang('en_GB');
|
const lang = Lang('en_GB');
|
||||||
|
@ -42,7 +40,7 @@
|
||||||
goto(`/${$server.host}/${$account.username}`);
|
goto(`/${$server.host}/${$account.username}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function logOut() {
|
async function log_out() {
|
||||||
if (!confirm("This will log you out. Are you sure?")) return;
|
if (!confirm("This will log you out. Are you sure?")) return;
|
||||||
|
|
||||||
const res = await api.revokeToken(
|
const res = await api.revokeToken(
|
||||||
|
@ -61,10 +59,6 @@
|
||||||
|
|
||||||
goto("/");
|
goto("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(async () => {
|
|
||||||
await fetchFollowRequests(true)
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id="navigation">
|
<div id="navigation">
|
||||||
|
@ -97,19 +91,6 @@
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</Button>
|
</Button>
|
||||||
{#if $followRequests.length > 0}
|
|
||||||
<Button label="Follow requests"
|
|
||||||
href="/follow-requests"}
|
|
||||||
active={$page.url.pathname === "/follow-requests"}>
|
|
||||||
<svelte:fragment slot="icon">
|
|
||||||
<FollowersIcon/>
|
|
||||||
</svelte:fragment>
|
|
||||||
{lang.string('navigation.follow_requests')}
|
|
||||||
<span class="notification-count">
|
|
||||||
{$followRequests.length}
|
|
||||||
</span>
|
|
||||||
</Button>
|
|
||||||
{/if}
|
|
||||||
<Button label="Explore" disabled>
|
<Button label="Explore" disabled>
|
||||||
<svelte:fragment slot="icon">
|
<svelte:fragment slot="icon">
|
||||||
<ExploreIcon height="auto"/>
|
<ExploreIcon height="auto"/>
|
||||||
|
@ -161,7 +142,7 @@
|
||||||
<SettingsIcon/>
|
<SettingsIcon/>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</Button>
|
</Button>
|
||||||
<Button centered label="{lang.string('navigation.log_out')}" on:click={() => logOut()}>
|
<Button centered label="{lang.string('navigation.log_out')}" on:click={() => log_out()}>
|
||||||
<svelte:fragment slot="icon">
|
<svelte:fragment slot="icon">
|
||||||
<LogoutIcon/>
|
<LogoutIcon/>
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
|
|
@ -144,22 +144,19 @@
|
||||||
<style>
|
<style>
|
||||||
.notification {
|
.notification {
|
||||||
display: block;
|
display: block;
|
||||||
border-top: 1px solid color-mix(in srgb, transparent, var(--text) 25%);
|
border-top: 1px solid color-mix(in srgb, transparent, var(--text) 50%);
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
text-decoration: inherit;
|
text-decoration: inherit;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
transition: background-color .1s;
|
transition: background-color .1s;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
background-color: var(--bg-900);
|
|
||||||
}
|
}
|
||||||
.notification:first-of-type {
|
.notification:first-of-type {
|
||||||
border-top: none;
|
border-top: none;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.notification:hover {
|
.notification:hover {
|
||||||
background-color: color-mix(in srgb, var(--bg-800), transparent 35%);
|
background-color: color-mix(in srgb, var(--bg-800), transparent 50%);
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
<script>
|
|
||||||
export let title;
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<header>
|
|
||||||
<h1>{title}</h1>
|
|
||||||
<div class="header-items">
|
|
||||||
<slot/>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
header {
|
|
||||||
width: 100%;
|
|
||||||
height: 64px;
|
|
||||||
margin: 16px 0;
|
|
||||||
padding: 0 8px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
user-select: none;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
header h1 {
|
|
||||||
font-size: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
header .header-items {
|
|
||||||
margin-left: auto;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -7,7 +7,6 @@
|
||||||
import LoginForm from '$lib/ui/LoginForm.svelte';
|
import LoginForm from '$lib/ui/LoginForm.svelte';
|
||||||
import Button from '$lib/ui/Button.svelte';
|
import Button from '$lib/ui/Button.svelte';
|
||||||
import Post from '$lib/ui/post/Post.svelte';
|
import Post from '$lib/ui/post/Post.svelte';
|
||||||
import PageHeader from '../lib/ui/core/PageHeader.svelte';
|
|
||||||
|
|
||||||
const lang = Lang('en_GB');
|
const lang = Lang('en_GB');
|
||||||
|
|
||||||
|
@ -24,11 +23,14 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if $account}
|
{#if $account}
|
||||||
<PageHeader title={lang.string('timeline.home')}>
|
<header>
|
||||||
<Button centered active>{lang.string('timeline.home')}</Button>
|
<h1>{lang.string('timeline.home')}</h1>
|
||||||
<Button centered disabled>{lang.string('timeline.local')}</Button>
|
<nav>
|
||||||
<Button centered disabled>{lang.string('timeline.federated')}</Button>
|
<Button centered active>{lang.string('timeline.home')}</Button>
|
||||||
</PageHeader>
|
<Button centered disabled>{lang.string('timeline.local')}</Button>
|
||||||
|
<Button centered disabled>{lang.string('timeline.federated')}</Button>
|
||||||
|
</nav>
|
||||||
|
</header>
|
||||||
|
|
||||||
<div id="feed" role="feed">
|
<div id="feed" role="feed">
|
||||||
{#if $timeline.length <= 0}
|
{#if $timeline.length <= 0}
|
||||||
|
@ -45,6 +47,30 @@
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
header {
|
||||||
|
width: 100%;
|
||||||
|
height: 64px;
|
||||||
|
margin: 16px 0;
|
||||||
|
padding: 0 8px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
user-select: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
header h1 {
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav {
|
||||||
|
margin-left: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
#feed {
|
#feed {
|
||||||
margin-bottom: 20vh;
|
margin-bottom: 20vh;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,144 +0,0 @@
|
||||||
<script>
|
|
||||||
import { followRequests } from '$lib/followRequests.js';
|
|
||||||
import PageHeader from '../../lib/ui/core/PageHeader.svelte';
|
|
||||||
import Lang from '$lib/lang';
|
|
||||||
import {server} from '$lib/client/server';
|
|
||||||
import {app} from '$lib/client/app';
|
|
||||||
import Button from '../../lib/ui/Button.svelte';
|
|
||||||
import * as api from '$lib/api'
|
|
||||||
|
|
||||||
import TickIcon from '../../img/icons/tick.svg'
|
|
||||||
import CrossIcon from '../../img/icons/cross.svg'
|
|
||||||
import { get } from 'svelte/store';
|
|
||||||
|
|
||||||
const lang = Lang('en_GB');
|
|
||||||
|
|
||||||
async function actionRequest(account_id, approved) {
|
|
||||||
// remove item from array first - this updates the ui and
|
|
||||||
// makes the interaction more seamless
|
|
||||||
$followRequests.splice(
|
|
||||||
$followRequests.indexOf(
|
|
||||||
$followRequests.find(r => r.id)
|
|
||||||
),
|
|
||||||
1
|
|
||||||
);
|
|
||||||
|
|
||||||
// hack: force the state to update now that we just spliced the array
|
|
||||||
$followRequests = $followRequests
|
|
||||||
|
|
||||||
if(approved) {
|
|
||||||
await api.acceptFollowRequest(
|
|
||||||
get(server).host,
|
|
||||||
get(app).token,
|
|
||||||
account_id
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
await api.rejectFollowRequest(
|
|
||||||
get(server).host,
|
|
||||||
get(app).token,
|
|
||||||
account_id
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// aliases
|
|
||||||
const acceptRequest = (id) => actionRequest(id, true);
|
|
||||||
const denyRequest = (id) => actionRequest(id, false);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<PageHeader title={lang.string('navigation.follow_requests')}/>
|
|
||||||
|
|
||||||
{#if $followRequests.length < 1}
|
|
||||||
<p class="request-zero">{lang.string('follow_requests.none')}</p>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#each $followRequests as req}
|
|
||||||
<div class="request">
|
|
||||||
<a href="/{$server.host}/@{req.fqn}" class="request-avatar-container" on:mouseup|stopPropagation>
|
|
||||||
<img src={req.avatar_url} alt="" width="48" height="48" class="post-avatar" loading="lazy" decoding="async">
|
|
||||||
</a>
|
|
||||||
<div class="info">
|
|
||||||
<div class="request-user-info">
|
|
||||||
<a href="/{$server.host}/@{req.fqn}" class="name">{@html req.rich_name}</a>
|
|
||||||
<span class="username">{req.mention}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="request-options">
|
|
||||||
<Button filled title="Yes" on:click={() => acceptRequest(req.id)}>
|
|
||||||
<TickIcon width="24px"/>
|
|
||||||
</Button>
|
|
||||||
<Button title="No" on:click={() => denyRequest(req.id)}>
|
|
||||||
<CrossIcon width="24px"/>
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.request {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
|
|
||||||
background: var(--bg-900);
|
|
||||||
padding: .5rem;
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.request a,
|
|
||||||
.request a:visited {
|
|
||||||
color: inherit;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
.request a:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
.request-avatar-container {
|
|
||||||
margin-right: 12px;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.post-avatar {
|
|
||||||
border-radius: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.info {
|
|
||||||
display: flex;
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
.request-user-info {
|
|
||||||
margin-top: -2px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.request-user-info a {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.request-user-info .username {
|
|
||||||
opacity: .8;
|
|
||||||
font-size: .9em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.request-options {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.request-options :global(button) {
|
|
||||||
width: fit-content;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.request-zero {
|
|
||||||
opacity: 0.8;
|
|
||||||
font-size: 0.95rem;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -4,7 +4,6 @@
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { page } from '$app/stores';
|
import { page } from '$app/stores';
|
||||||
import Notification from '$lib/ui/Notification.svelte';
|
import Notification from '$lib/ui/Notification.svelte';
|
||||||
import PageHeader from '../../lib/ui/core/PageHeader.svelte';
|
|
||||||
import Lang from '$lib/lang';
|
import Lang from '$lib/lang';
|
||||||
|
|
||||||
const lang = Lang('en_GB');
|
const lang = Lang('en_GB');
|
||||||
|
@ -34,7 +33,9 @@
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<PageHeader title={lang.string('navigation.notifications')}/>
|
<header>
|
||||||
|
<h1>{lang.string('navigation.notifications')}</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
<div class="notifications">
|
<div class="notifications">
|
||||||
{#if $notifications.length === 0}
|
{#if $notifications.length === 0}
|
||||||
|
@ -49,6 +50,20 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
header {
|
||||||
|
width: 100%;
|
||||||
|
height: 64px;
|
||||||
|
margin: 16px 0 8px 0;
|
||||||
|
padding: 0 8px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
.loading {
|
.loading {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 80vh;
|
height: 80vh;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue