Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add announcements #195

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -150,14 +150,16 @@ hr {
border-top: 1px solid var(--grey-three);
}

input {
input,
textarea {
padding: 1rem;
border-radius: 12px;
border: 1px solid var(--grey-three);
background-color: transparent;
color: var(--accent-color-two);
}

input:focus {
input:focus,
textarea:focus {
outline: 1px solid var(--accent-color);
}
99 changes: 83 additions & 16 deletions src/data/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ import type {
CryptoWallet,
Social,
Info,
CompatiblePackage
CompatiblePackage,
Announcement,
NoAnnouncements,
PostAnnouncement,
Login as LoginRequest,
Login,
LoginResponse
} from '$lib/types';

export type ReposData = { repositories: Repository[] };
Expand All @@ -21,12 +27,40 @@ export type TeamData = { members: TeamMember[] };
export type InfoData = { info: Info };
export type DonationData = { wallets: CryptoWallet[]; platforms: DonationPlatform[] };
export type SocialsData = { socials: Social[] };
export type AnnouncementsData = { announcements: Announcement[] | NoAnnouncements };

function build_url(endpoint: string) {
return `${settings.api_base_url()}/${endpoint}`;
}

async function get_json(endpoint: string) {
const url = `${settings.api_base_url()}/${endpoint}`;
const url = build_url(endpoint);
return await fetch(url).then((r) => r.json());
}

async function post_json(endpoint: string, body: any) {
const url = build_url(endpoint);
const token = settings.get_access_token();
return await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: token ? `Bearer ${token}` : ''
},
body: JSON.stringify(body)
}).then((r) => r.json());
}

async function delete_json(endpoint: string) {
const url = build_url(endpoint);
return await fetch(url, {
method: 'DELETE',
headers: {
Authorization: `Bearer ${settings.get_access_token()}`
}
}).then((r) => r.json());
}

async function repositories(): Promise<ReposData> {
const json = await get_json('contributors');
return { repositories: json.repositories };
Expand Down Expand Up @@ -77,41 +111,74 @@ async function socials(): Promise<SocialsData> {
return { socials: json.socials };
}

async function announcements(channel?: string): Promise<AnnouncementsData> {
const json = await get_json(channel ? `v2/announcements/${channel}` : 'v2/announcements');
return { announcements: json.reverse() };
}

async function postAnnouncement(channel: string, announcement: PostAnnouncement) {
await post_json(`v2/announcements/${channel}`, announcement);
}

async function deleteAnnouncement(announcementId: number) {
await delete_json(`v2/announcements/${announcementId}`);
}

async function login(login: Login): Promise<LoginResponse> {
return await post_json('v2/login', login);
}

export const staleTime = 5 * 60 * 1000;
export const queries = {
manager: {
manager: () => ({
queryKey: ['manager'],
queryFn: manager,
staleTime
},
patches: {
}),
patches: () => ({
queryKey: ['patches'],
queryFn: patches,
staleTime
},
repositories: {
}),
repositories: () => ({
queryKey: ['repositories'],
queryFn: repositories,
staleTime
},
team: {
}),
team: () => ({
queryKey: ['team'],
queryFn: team,
staleTime
},
info: {
}),
info: () => ({
queryKey: ['info'],
queryFn: info,
staleTime
},
donate: {
}),
donate: () => ({
queryKey: ['donate'],
queryFn: donate,
staleTime
},
socials: {
}),
socials: () => ({
queryKey: ['socials'],
queryFn: socials,
staleTime
}
}),
announcements: (channel?: string) => ({
queryKey: ['announcements'],
queryFn: () => announcements(channel)
}),
postAnnouncement: (channel: string, announcement: PostAnnouncement) => ({
mutationKey: ['postAnnouncement'],
mutationFn: () => postAnnouncement(channel, announcement)
}),
deleteAnnouncement: (announcementId: number) => ({
mutationKey: ['deleteAnnouncement'],
mutationFn: () => deleteAnnouncement(announcementId)
}),
login: (loginRequest: LoginRequest) => ({
mutationKey: ['login'],
mutationFn: () => login(loginRequest)
})
};
20 changes: 19 additions & 1 deletion src/data/api/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,29 @@ export function api_base_url(): string {
return default_base_url;
}

// (re)set base URL.
// (Re)set base URL.
export function set_api_base_url(url?: string) {
if (!url) {
localStorage.removeItem(URL_KEY);
} else {
localStorage.setItem(URL_KEY, url);
}
}

// Get access token.
export function get_access_token(): string | null {
if (browser) {
return localStorage.getItem('revanced_api_access_token');
}

return null;
}

// Set access token.
export function set_access_token(token?: string) {
if (!token) {
localStorage.removeItem('revanced_api_access_token');
} else {
localStorage.setItem('revanced_api_access_token', token);
}
}
11 changes: 2 additions & 9 deletions src/layout/Footer/FooterHost.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
import Query from '$lib/components/Query.svelte';
import FooterSection from './FooterSection.svelte';

const infoQuery = createQuery(['info'], queries.info);
const socialsQuery = createQuery(['socials'], queries.socials);
const infoQuery = createQuery(['info'], queries.info());
const socialsQuery = createQuery(['socials'], queries.socials());
</script>

<!-- squiggly divider line -->
Expand Down Expand Up @@ -163,13 +163,6 @@
margin-top: 1rem;
}

ul {
display: flex;
gap: 1rem;
flex-direction: column;
width: max-content;
}

@media screen and (max-width: 1050px) {
.footer-top {
flex-direction: column;
Expand Down
2 changes: 1 addition & 1 deletion src/layout/Hero/SocialHost.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import { createQuery } from '@tanstack/svelte-query';
import Query from '$lib/components/Query.svelte';

const query = createQuery(['socials'], queries.socials);
const query = createQuery(['socials'], queries.socials());
</script>

<div class="social-host">
Expand Down
2 changes: 1 addition & 1 deletion src/layout/Navbar/NavButton.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
if (queryKey !== null) {
if (Array.isArray(queryKey)) {
queryKey.forEach((key) => {
const query = queries[key];
const query = (queries[key] as Function)();
dev_log('Prefetching', query);
client.prefetchQuery(query as any);
});
Expand Down
73 changes: 68 additions & 5 deletions src/layout/Navbar/NavHost.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<script lang="ts">
import { onMount } from 'svelte';
import { horizontalSlide } from '$util/horizontalSlide';
import { fade } from 'svelte/transition';
import { expoOut } from 'svelte/easing';
Expand All @@ -12,7 +11,11 @@
import * as settings from '$data/api/settings';
import RouterEvents from '$data/RouterEvents';

import { useQueryClient } from '@tanstack/svelte-query';
import { createMutation, useQueryClient } from '@tanstack/svelte-query';
import { queries } from '$data/api';
import { onMount, subscribe } from 'svelte/internal';
import { set_access_token } from '$data/api/settings';
import type { Login } from '$lib/types';

const client = useQueryClient();

Expand All @@ -39,6 +42,18 @@
let modalOpen = false;
let y: number;

let login: Login = {
username: '',
password: ''
};

let loginMutation = createMutation(queries.login(login));
loginMutation.subscribe((result) => {
login.username = '';
login.password = '';
if (result.data) set_access_token(result.data.access_token);
});

onMount(() => {
return RouterEvents.subscribe((event) => {
if (event.navigating) {
Expand Down Expand Up @@ -83,6 +98,15 @@
</ul>
</div>
<div id="secondary-navigation">
<a href="/announcements">
<Svg viewBoxHeight={24} svgHeight={20}>
<path
class:selected={'/announcements' ===
'/' + $RouterEvents.target_url.pathname.split('/')[1]}
d="M18 11v2h4v-2h-4zm-2 6.61c.96.71 2.21 1.65 3.2 2.39.4-.53.8-1.07 1.2-1.6-.99-.74-2.24-1.68-3.2-2.4-.4.54-.8 1.08-1.2 1.61zM20.4 5.6c-.4-.53-.8-1.07-1.2-1.6-.99.74-2.24 1.68-3.2 2.4.4.53.8 1.07 1.2 1.6.96-.72 2.21-1.65 3.2-2.4zM4 9c-1.1 0-2 .9-2 2v2c0 1.1.9 2 2 2h1v4h2v-4h1l5 3V6L8 9H4zm11.5 3c0-1.33-.58-2.53-1.5-3.35v6.69c.92-.81 1.5-2.01 1.5-3.34z"
/>
</Svg>
</a>
<button on:click={() => (modalOpen = !modalOpen)} aria-label="Settings">
<Svg viewBoxHeight={24} svgHeight={20}>
<path
Expand Down Expand Up @@ -127,22 +151,61 @@
</Svg>
</button>
</div>

<div class="api-url-buttons">
<Button type="text" on:click={clear_and_reload} label="Clear Cache Button">Clear cache</Button>
<Button type="text" on:click={save} label="Save Button">Save</Button>
</div>
<br />
<div class="login">
<input placeholder="Username" type="text" bind:value={login.username} />
<input placeholder="Password" type="password" bind:value={login.password} />
</div>
</div>

<svelte:fragment slot="buttons">
<Button type="text" on:click={clear_and_reload} label="Clear Cache Button">Clear cache</Button>
<Button type="text" on:click={save} label="Save Button">Save</Button>
<Button
type="text"
on:click={() => {
$loginMutation.mutate();
}}
>
Login
</Button>
</svelte:fragment>
</Modal>

<style>
<style lang="scss">
.api-url-buttons {
display: flex;
gap: 2rem;
justify-content: flex-end;
width: 100%;
}

.login {
display: flex;
flex-direction: column;
width: 100%;
color: var(--grey-five);
gap: 1rem;
align-items: center;

input {
margin-top: 0;
}
}

#logo {
padding: 0.5rem;
}

path {
fill: var(--grey-five);
}
path.selected {
fill: var(--accent-color);
}

button:hover path {
fill: var(--accent-color-two);
Expand Down
5 changes: 2 additions & 3 deletions src/lib/components/Dialogue.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<script lang="ts">
import { fade } from 'svelte/transition';
import { quadInOut } from 'svelte/easing';
import { disableScrollHandling } from '$app/navigation';
export let modalOpen = false;
export let fullscreen = false;
export let notDismissible = false;
Expand Down Expand Up @@ -113,8 +112,8 @@

.modal {
position: fixed;
width: min(85%, 425px);
max-height: 75%;
width: min(90%, 425px);
max-height: 95%;
overflow-y: scroll;
top: 50%;
left: 50%;
Expand Down
Loading
Loading