Skip to content
Merged
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
2 changes: 2 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
RV_API_URL=https://api.revanced.app
RV_STATUS_URL=https://status.revanced.app
RV_EMAIL=contact@revanced.app
RV_GOOGLE_TAG_MANAGER_ID=
RV_DMCA_GUID=
2 changes: 2 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ jobs:
RV_API_URL: ${{ vars.RV_API_URL }}
RV_GOOGLE_TAG_MANAGER_ID: ${{ vars.RV_GOOGLE_TAG_MANAGER_ID }}
RV_DMCA_GUID: ${{ vars.RV_DMCA_GUID }}
RV_STATUS_URL: ${{ vars.RV_STATUS_URL }}
RV_EMAIL: ${{ vars.RV_EMAIL }}
run: npm run build

- name: Deploy
Expand Down
2 changes: 1 addition & 1 deletion src/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@
</head>

<body>
%sveltekit.body%
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>
2 changes: 1 addition & 1 deletion src/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ p {
line-height: 1.75rem;
}

@media screen and (max-width: 767px) {
@media (max-width: 768px) {
h1 {
font-size: 2.6rem;
line-height: 3.75rem;
Expand Down
51 changes: 32 additions & 19 deletions src/data/api/settings.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
import { browser } from '$app/environment';
import { RV_API_URL } from '$env/static/public';
import { RV_API_URL, RV_EMAIL, RV_STATUS_URL } from '$env/static/public';

export const default_api_url = RV_API_URL;
export const default_status_url = RV_STATUS_URL;
export const default_email = RV_EMAIL;

const URL_KEY = 'revanced_api_url';
const STATUS_KEY = 'revanced_status_url';

function set_status_url(apiUrl: string) {
fetch(`${apiUrl}/v4/about`)
.then((response) => (response.ok ? response.json() : null))
.then((data) => {
if (data?.status) {
localStorage.setItem(STATUS_KEY, data.status);
console.log('Status is now:', localStorage.getItem(STATUS_KEY));
}
});
}
const EMAIL_KEY = 'revanced_email';

export const API_VERSION = 'v4';

Expand All @@ -24,22 +16,28 @@ export function api_base_url(): string {
if (browser) {
const apiUrl = localStorage.getItem(URL_KEY) || default_api_url;

if (!localStorage.getItem(STATUS_KEY)) {
set_status_url(apiUrl);
}
set_about_info(apiUrl);

return apiUrl;
}

return default_api_url;
}

export function status_url(): string | null {
export function status_url(): string {
if (browser) {
return localStorage.getItem(STATUS_KEY) || default_status_url;
}

return default_status_url;
}

export function email(): string {
if (browser) {
return localStorage.getItem(STATUS_KEY) || null;
return localStorage.getItem(EMAIL_KEY) || default_email;
}

return null;
return default_email;
}

// (re)set base URL.
Expand All @@ -48,6 +46,21 @@ export function set_api_base_url(url?: string) {
localStorage.removeItem(URL_KEY);
} else {
localStorage.setItem(URL_KEY, url);
set_status_url(url);
set_about_info(url);
}
}

function set_about_info(apiUrl: string) {
if (!localStorage.getItem(STATUS_KEY) || !localStorage.getItem(EMAIL_KEY)) {
fetch(`${apiUrl}/v4/about`)
.then((response) => (response.ok ? response.json() : null))
.then((data) => {
if (data?.status) {
localStorage.setItem(STATUS_KEY, data.status);
localStorage.setItem(EMAIL_KEY, data.contact.email);
console.log('Status is now:', localStorage.getItem(STATUS_KEY));
console.log('Email is now:', localStorage.getItem(EMAIL_KEY));
}
});
}
}
61 changes: 61 additions & 0 deletions src/layout/Banners/AnnouncementBanner.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<script lang="ts">
import { read_announcements } from '$lib/stores';
import Banner from '$layout/Banners/Banner.svelte';
import { goto } from '$app/navigation';
import { createQuery } from '@tanstack/svelte-query';
import { queries } from '$data/api';
import moment from 'moment';

const query = createQuery(queries.announcements());

$: latestUnreadAnnouncement = (() => {
const announcements = $query.data?.announcements ?? [];

const nonArchived = announcements.filter(
(a) => !a.archived_at || moment(a.archived_at).isAfter(moment())
);

const announcement = nonArchived[0];

return announcement && !$read_announcements.has(announcement.id) ? announcement : undefined;
})();

function setAsRead() {
if (!latestUnreadAnnouncement) return;

read_announcements.update((set) => {
const updated = new Set(set);
updated.add(latestUnreadAnnouncement.id);
return updated;
});
}

function handleClick() {
if (!latestUnreadAnnouncement) return;

goto(`/announcements/${latestUnreadAnnouncement.id}`);
setAsRead();
}

function handleClose() {
if (!latestUnreadAnnouncement) return;

setAsRead();
}

function getBannerLevel(level: number | undefined): 'info' | 'caution' {
if (!level || level == 0) return 'info';
return 'caution';
}
</script>

{#if latestUnreadAnnouncement}
<Banner
title={'We have an announcement'}
description={`You can read more about "${latestUnreadAnnouncement.title}" in our latest post.`}
level={getBannerLevel(latestUnreadAnnouncement.level)}
buttonText="Read more"
buttonOnClick={handleClick}
onDismiss={handleClose}
/>
{/if}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { createEventDispatcher } from 'svelte';
import Close from 'svelte-material-icons/Close.svelte';
import ArrowRight from 'svelte-material-icons/ArrowRight.svelte';
import Button from './Button.svelte';
import Button from '$lib/components/Button.svelte';

export let title: string;
export let description: string | undefined = undefined;
Expand Down Expand Up @@ -83,7 +83,7 @@
color: #601410;
}

@media (max-width: 767px) {
@media (max-width: 768px) {
flex-direction: column;
padding: 1.1rem 1.3rem;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script lang="ts">
import { goto } from '$app/navigation';
import Banner from '$lib/components/Banner.svelte';
import { email } from '$data/api/settings';
import Banner from '$layout/Banners/Banner.svelte';

export let statusUrl: string | null = null;

Expand All @@ -9,7 +10,7 @@

<Banner
title="API service is currently down"
description="We're actively investigating and will update you shortly. We appreciate your patience."
description="Some features of the site might be impacted. If this issue persists, reach out to mailto:{email()}"
buttonText={statusUrl ? 'View status' : undefined}
buttonOnClick={statusUrl ? handleClick : undefined}
level="caution"
Expand Down
55 changes: 55 additions & 0 deletions src/layout/Dialogs/ConsentDialog.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<script lang="ts">
import Button from '$lib/components/Button.svelte';
import Dialog from '$layout/Dialogs/Dialog.svelte';
import { onMount } from 'svelte';
import { allowAnalytics } from '$lib/stores';
import { RV_GOOGLE_TAG_MANAGER_ID } from '$env/static/public';

let showConsentDialog = false;

function enableAnalytics() {
//@ts-ignore
window.dataLayer = window.dataLayer || [];
function gtag(...args: any[]) {
//@ts-ignore
window.dataLayer.push(args);
}
gtag('js', new Date());

const script = document.createElement('script');
script.src = `https://www.googletagmanager.com/gtm.js?id=${RV_GOOGLE_TAG_MANAGER_ID}`;
document.head.append(script);
}

function handleConsent(allowed: boolean) {
localStorage.setItem('analytics', allowed.toString());
allowAnalytics.set(allowed);
showConsentDialog = false;

if (allowed) enableAnalytics();
}

onMount(() => {
const savedConsent = localStorage.getItem('analytics');

if (savedConsent !== null) {
const allowed = savedConsent === 'true';
allowAnalytics.set(allowed);
if (allowed) enableAnalytics();
} else {
showConsentDialog = true;
}
});
</script>

<Dialog bind:dialogOpen={showConsentDialog} notDismissible>
<svelte:fragment slot="title">It's your choice</svelte:fragment>
<svelte:fragment slot="description">
We use analytics to improve your experience on this site. By clicking "Allow", you allow us to
collect anonymous data about your visit.
</svelte:fragment>
<svelte:fragment slot="buttons">
<Button type="text" on:click={() => handleConsent(false)}>Deny</Button>
<Button type="filled" on:click={() => handleConsent(true)}>Allow</Button>
</svelte:fragment>
</Dialog>
Loading