mirror of
https://github.com/revanced/revanced-website.git
synced 2025-04-29 22:24:31 +02:00
feat: API outage banner (#254)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de> Co-authored-by: oSumAtrIX <github@osumatrix.me> Co-authored-by: Ushie <ushiekane@gmail.com>
This commit is contained in:
parent
87ce20ff56
commit
adf569c6be
1230
pnpm-lock.yaml
generated
1230
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -34,7 +34,7 @@ body {
|
|||||||
.wrapper {
|
.wrapper {
|
||||||
margin-inline: auto;
|
margin-inline: auto;
|
||||||
width: min(90%, 80rem);
|
width: min(90%, 80rem);
|
||||||
margin-top: 7rem;
|
margin-top: 2.6rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
@ -73,6 +73,9 @@ body {
|
|||||||
--surface-nine: hsl(calc(var(--hue, 206) + 24), 9.5%, 17.5%);
|
--surface-nine: hsl(calc(var(--hue, 206) + 24), 9.5%, 17.5%);
|
||||||
|
|
||||||
--red-one: hsl(333, 84%, 62%);
|
--red-one: hsl(333, 84%, 62%);
|
||||||
|
--red-two: hsl(357, 74%, 60%);
|
||||||
|
|
||||||
|
--yellow-one: hsl(59, 100%, 72%);
|
||||||
|
|
||||||
--bezier-one: cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
--bezier-one: cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
||||||
--drop-shadow-one: 0px 4px 5px 0px rgba(0, 0, 0, 0.14), 0px 1px 10px 0px rgba(0, 0, 0, 0.12),
|
--drop-shadow-one: 0px 4px 5px 0px rgba(0, 0, 0, 0.14), 0px 1px 10px 0px rgba(0, 0, 0, 0.12),
|
||||||
|
@ -74,6 +74,15 @@ async function about(): Promise<AboutData> {
|
|||||||
return { about: json };
|
return { about: json };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function ping(): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
const res = await fetch(`${settings.api_base_url()}/v4/ping`, { method: 'HEAD' });
|
||||||
|
return res.ok;
|
||||||
|
} catch (error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const staleTime = 5 * 60 * 1000;
|
export const staleTime = 5 * 60 * 1000;
|
||||||
export const queries = {
|
export const queries = {
|
||||||
manager: {
|
manager: {
|
||||||
@ -100,5 +109,10 @@ export const queries = {
|
|||||||
queryKey: ['info'],
|
queryKey: ['info'],
|
||||||
queryFn: about,
|
queryFn: about,
|
||||||
staleTime
|
staleTime
|
||||||
|
},
|
||||||
|
ping: {
|
||||||
|
queryKey: ['ping'],
|
||||||
|
queryFn: ping,
|
||||||
|
staleTime
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -4,21 +4,48 @@ import { RV_API_URL } from '$env/static/public';
|
|||||||
export const default_api_url = RV_API_URL;
|
export const default_api_url = RV_API_URL;
|
||||||
|
|
||||||
const URL_KEY = 'revanced_api_url';
|
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));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Get base URL
|
// Get base URL
|
||||||
export function api_base_url(): string {
|
export function api_base_url(): string {
|
||||||
if (browser) {
|
if (browser) {
|
||||||
return localStorage.getItem(URL_KEY) || default_api_url;
|
const apiUrl = localStorage.getItem(URL_KEY) || default_api_url;
|
||||||
|
|
||||||
|
if (!localStorage.getItem(STATUS_KEY)) {
|
||||||
|
set_status_url(apiUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
return apiUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return default_api_url;
|
return default_api_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function status_url(): string | null {
|
||||||
|
if (browser) {
|
||||||
|
return localStorage.getItem(STATUS_KEY) || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// (re)set base URL.
|
// (re)set base URL.
|
||||||
export function set_api_base_url(url?: string) {
|
export function set_api_base_url(url?: string) {
|
||||||
if (!url) {
|
if (!url) {
|
||||||
localStorage.removeItem(URL_KEY);
|
localStorage.removeItem(URL_KEY);
|
||||||
} else {
|
} else {
|
||||||
localStorage.setItem(URL_KEY, url);
|
localStorage.setItem(URL_KEY, url);
|
||||||
|
set_status_url(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,16 +3,20 @@
|
|||||||
import { horizontalSlide } from '$util/horizontalSlide';
|
import { horizontalSlide } from '$util/horizontalSlide';
|
||||||
import { fade } from 'svelte/transition';
|
import { fade } from 'svelte/transition';
|
||||||
import { expoOut } from 'svelte/easing';
|
import { expoOut } from 'svelte/easing';
|
||||||
|
import { createQuery } from '@tanstack/svelte-query';
|
||||||
|
|
||||||
import Navigation from './NavButton.svelte';
|
import Navigation from './NavButton.svelte';
|
||||||
import Modal from '$lib/components/Dialogue.svelte';
|
import Modal from '$lib/components/Dialogue.svelte';
|
||||||
import Button from '$lib/components/Button.svelte';
|
import Button from '$lib/components/Button.svelte';
|
||||||
|
import Banner from '$lib/components/Banner.svelte';
|
||||||
|
import Query from '$lib/components/Query.svelte';
|
||||||
|
|
||||||
import Cog from 'svelte-material-icons/Cog.svelte';
|
import Cog from 'svelte-material-icons/Cog.svelte';
|
||||||
import Replay from 'svelte-material-icons/Replay.svelte';
|
import Replay from 'svelte-material-icons/Replay.svelte';
|
||||||
|
|
||||||
import { api_base_url, set_api_base_url, default_api_url } from '$data/api/settings';
|
import { status_url, api_base_url, set_api_base_url, default_api_url } from '$data/api/settings';
|
||||||
import RouterEvents from '$data/RouterEvents';
|
import RouterEvents from '$data/RouterEvents';
|
||||||
|
import { queries } from '$data/api';
|
||||||
|
|
||||||
import { useQueryClient } from '@tanstack/svelte-query';
|
import { useQueryClient } from '@tanstack/svelte-query';
|
||||||
|
|
||||||
@ -31,6 +35,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
let url = api_base_url();
|
let url = api_base_url();
|
||||||
|
const statusUrl = status_url();
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
set_api_base_url(url);
|
set_api_base_url(url);
|
||||||
@ -44,6 +49,7 @@
|
|||||||
let menuOpen = false;
|
let menuOpen = false;
|
||||||
let modalOpen = false;
|
let modalOpen = false;
|
||||||
let y: number;
|
let y: number;
|
||||||
|
const pingQuery = () => createQuery(['ping'], queries.ping);
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
return RouterEvents.subscribe((event) => {
|
return RouterEvents.subscribe((event) => {
|
||||||
@ -56,53 +62,88 @@
|
|||||||
|
|
||||||
<svelte:window bind:scrollY={y} />
|
<svelte:window bind:scrollY={y} />
|
||||||
|
|
||||||
<nav class:scrolled={y > 10}>
|
<div id="nav-container">
|
||||||
<a class="menu-btn skiptab-btn" href="#skiptab">Skip navigation</a>
|
<Query query={pingQuery()} let:data>
|
||||||
|
{#if !data}
|
||||||
|
<span class="banner">
|
||||||
|
<Banner level="caution" permanent>
|
||||||
|
The API is currently unresponsive and some services may not work correctly. {#if statusUrl}
|
||||||
|
Check the <a href={statusUrl} target="_blank" rel="noopener noreferrer">status page</a> for
|
||||||
|
updates.
|
||||||
|
{/if}
|
||||||
|
</Banner>
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</Query>
|
||||||
|
|
||||||
<button
|
<nav class:scrolled={y > 10}>
|
||||||
class="menu-btn mobile-only"
|
<a class="menu-btn skiptab-btn" href="#skiptab">Skip navigation</a>
|
||||||
on:click={() => (menuOpen = !menuOpen)}
|
|
||||||
class:open={menuOpen}
|
|
||||||
aria-label="Menu"
|
|
||||||
>
|
|
||||||
<span class="menu-btn__burger" />
|
|
||||||
</button>
|
|
||||||
<a href="/" id="logo"><img src="/logo.svg" alt="ReVanced Logo" /></a>
|
|
||||||
|
|
||||||
{#key menuOpen}
|
<button
|
||||||
<div
|
class="menu-btn mobile-only"
|
||||||
class="nav-wrapper"
|
|
||||||
class:desktop-only={!menuOpen}
|
|
||||||
transition:horizontalSlide={{ direction: 'inline', easing: expoOut, duration: 400 }}
|
|
||||||
>
|
|
||||||
<div id="main-navigation">
|
|
||||||
<ul class="nav-buttons">
|
|
||||||
<Navigation href="/" label="Home">Home</Navigation>
|
|
||||||
<Navigation queryKey="manager" href="/download" label="Download">Download</Navigation>
|
|
||||||
<Navigation queryKey="patches" href="/patches" label="Patches">Patches</Navigation>
|
|
||||||
<Navigation queryKey="contributors" href="/contributors" label="Contributors">
|
|
||||||
Contributors
|
|
||||||
</Navigation>
|
|
||||||
<Navigation queryKey={['about', 'team']} href="/donate" label="Donate">Donate</Navigation>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div id="secondary-navigation">
|
|
||||||
<button on:click={() => (modalOpen = !modalOpen)} aria-label="Settings">
|
|
||||||
<Cog size="20px" color="var(--surface-six)" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/key}
|
|
||||||
|
|
||||||
{#if menuOpen}
|
|
||||||
<div
|
|
||||||
class="overlay mobile-only"
|
|
||||||
transition:fade={{ duration: 350 }}
|
|
||||||
on:click={() => (menuOpen = !menuOpen)}
|
on:click={() => (menuOpen = !menuOpen)}
|
||||||
on:keypress={() => (menuOpen = !menuOpen)}
|
class:open={menuOpen}
|
||||||
/>
|
aria-label="Menu"
|
||||||
{/if}
|
>
|
||||||
</nav>
|
<span class="menu-btn__burger" />
|
||||||
|
</button>
|
||||||
|
<a href="/" id="logo"><img src="/logo.svg" alt="ReVanced Logo" /></a>
|
||||||
|
|
||||||
|
{#key menuOpen}
|
||||||
|
<div
|
||||||
|
id="nav-wrapper-container"
|
||||||
|
class:desktop-only={!menuOpen}
|
||||||
|
transition:horizontalSlide={{ direction: 'inline', easing: expoOut, duration: 400 }}
|
||||||
|
>
|
||||||
|
<div id="banner-pad">
|
||||||
|
<Query query={pingQuery()} let:data>
|
||||||
|
{#if !data}
|
||||||
|
<span class="banner">
|
||||||
|
<Banner level="caution" permanent>
|
||||||
|
The API is currently unresponsive and some services may not work correctly. {#if statusUrl}
|
||||||
|
Check the
|
||||||
|
<a href={statusUrl} target="_blank" rel="noopener noreferrer">status page</a> for
|
||||||
|
updates.
|
||||||
|
{/if}
|
||||||
|
</Banner>
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</Query>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="nav-wrapper">
|
||||||
|
<div id="main-navigation">
|
||||||
|
<ul class="nav-buttons">
|
||||||
|
<Navigation href="/" label="Home">Home</Navigation>
|
||||||
|
<Navigation queryKey="manager" href="/download" label="Download">Download</Navigation>
|
||||||
|
<Navigation queryKey="patches" href="/patches" label="Patches">Patches</Navigation>
|
||||||
|
<Navigation queryKey="contributors" href="/contributors" label="Contributors">
|
||||||
|
Contributors
|
||||||
|
</Navigation>
|
||||||
|
<Navigation queryKey={['about', 'team']} href="/donate" label="Donate"
|
||||||
|
>Donate</Navigation
|
||||||
|
>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div id="secondary-navigation">
|
||||||
|
<button on:click={() => (modalOpen = !modalOpen)} aria-label="Settings">
|
||||||
|
<Cog size="20px" color="var(--surface-six)" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/key}
|
||||||
|
|
||||||
|
{#if menuOpen}
|
||||||
|
<div
|
||||||
|
class="overlay mobile-only"
|
||||||
|
transition:fade={{ duration: 350 }}
|
||||||
|
on:click={() => (menuOpen = !menuOpen)}
|
||||||
|
on:keypress={() => (menuOpen = !menuOpen)}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- settings -->
|
<!-- settings -->
|
||||||
<Modal bind:modalOpen>
|
<Modal bind:modalOpen>
|
||||||
@ -126,7 +167,7 @@
|
|||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<style>
|
<style lang="scss">
|
||||||
#logo {
|
#logo {
|
||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
}
|
}
|
||||||
@ -160,15 +201,26 @@
|
|||||||
top: 30px;
|
top: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#nav-container {
|
||||||
|
position: sticky;
|
||||||
|
z-index: 666;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
&:has(.nav-buttons > li:first-child.selected) {
|
||||||
|
margin-bottom: 2.65rem;
|
||||||
|
|
||||||
|
&:has(.banner) {
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nav {
|
nav {
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 2rem;
|
gap: 2rem;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 1rem 2rem;
|
padding: 1rem 2rem;
|
||||||
z-index: 666;
|
|
||||||
height: 70px;
|
height: 70px;
|
||||||
background-color: var(--surface-eight);
|
background-color: var(--surface-eight);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -181,10 +233,6 @@
|
|||||||
gap: 2rem;
|
gap: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
img {
|
||||||
height: 22px;
|
height: 22px;
|
||||||
}
|
}
|
||||||
@ -220,21 +268,45 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#banner-pad {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#nav-wrapper-container {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
@media (max-width: 767px) {
|
@media (max-width: 767px) {
|
||||||
|
#banner-pad {
|
||||||
|
display: block;
|
||||||
|
width: 100vw;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#nav-container:has(.nav-buttons > li:first-child.selected):has(.banner) {
|
||||||
|
margin-bottom: 0rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#nav-wrapper-container {
|
||||||
|
overflow: hidden;
|
||||||
|
position: fixed;
|
||||||
|
width: 20rem;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100%;
|
||||||
|
background-color: var(--surface-eight);
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
.nav-wrapper {
|
.nav-wrapper {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
position: fixed;
|
|
||||||
width: 20rem;
|
width: 20rem;
|
||||||
top: 0px;
|
|
||||||
border-radius: 0px 24px 24px 0px;
|
border-radius: 0px 24px 24px 0px;
|
||||||
left: 0px;
|
|
||||||
background-color: var(--surface-eight);
|
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
padding-top: 6rem;
|
padding-top: 6rem;
|
||||||
z-index: 100;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.desktop-only {
|
.desktop-only {
|
||||||
|
160
src/lib/components/Banner.svelte
Normal file
160
src/lib/components/Banner.svelte
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import Info from 'svelte-material-icons/InformationOutline.svelte';
|
||||||
|
import Warning from 'svelte-material-icons/AlertOutline.svelte';
|
||||||
|
import Caution from 'svelte-material-icons/AlertCircleOutline.svelte';
|
||||||
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
import Button from './Button.svelte';
|
||||||
|
|
||||||
|
export let level: 'info' | 'warning' | 'caution' = 'info';
|
||||||
|
export let permanent: boolean = false;
|
||||||
|
|
||||||
|
const icons = { info: Info, warning: Warning, caution: Caution };
|
||||||
|
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
let closed: boolean = false;
|
||||||
|
|
||||||
|
const dismissBanner = () => {
|
||||||
|
closed = true;
|
||||||
|
dispatch('dismissed');
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="banner-container" class:closed class:permanent>
|
||||||
|
<div class="banner {level}">
|
||||||
|
<div class="banner-text">
|
||||||
|
<svelte:component this={icons[level]} size={permanent ? 22.4 : 32} />
|
||||||
|
<span><slot /></span>
|
||||||
|
</div>
|
||||||
|
{#if !permanent}
|
||||||
|
<Button type="text" icon="close" on:click={dismissBanner}>Dismiss</Button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.banner-container,
|
||||||
|
.banner-container *,
|
||||||
|
.banner-container :global(*) {
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-text :global(a) {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-text :global(a:hover) {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-container:not(.permanent) {
|
||||||
|
animation: dropDown var(--bezier-one) 0.7s forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-container.closed {
|
||||||
|
animation: swipeUp var(--bezier-one) 1.5s forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-container.permanent {
|
||||||
|
font-size: 0.87rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner {
|
||||||
|
margin: 0;
|
||||||
|
padding: 1.5rem 1.7rem;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 1.3rem;
|
||||||
|
margin: 0.7rem 1rem;
|
||||||
|
border-radius: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-container.permanent > .banner {
|
||||||
|
padding: 0.5rem 0.7rem;
|
||||||
|
margin: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-text {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex: 1;
|
||||||
|
gap: 0.55rem;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.info {
|
||||||
|
background-color: var(--surface-four);
|
||||||
|
color: var(--text-one);
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.warning {
|
||||||
|
background-color: var(--yellow-one);
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.warning > :global(button) {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.warning > :global(button img) {
|
||||||
|
filter: grayscale(1) brightness(0); /* Make the icon black */
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.caution {
|
||||||
|
background-color: var(--red-two);
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.caution > :global(button) {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner.caution > :global(button img) {
|
||||||
|
filter: grayscale(1) brightness(0); /* Make the icon white */
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner > :global(button):hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 767px) {
|
||||||
|
.banner {
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 1.1rem 1.3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner > :global(button) {
|
||||||
|
align-self: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes dropDown {
|
||||||
|
0% {
|
||||||
|
top: -100%;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes swipeUp {
|
||||||
|
0% {
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
top: -100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -110,6 +110,7 @@
|
|||||||
|
|
||||||
<QueryClientProvider client={queryClient}>
|
<QueryClientProvider client={queryClient}>
|
||||||
<NavHost />
|
<NavHost />
|
||||||
|
|
||||||
<Dialogue bind:modalOpen={showConsentModal} notDismissible>
|
<Dialogue bind:modalOpen={showConsentModal} notDismissible>
|
||||||
<svelte:fragment slot="title">It's your choice</svelte:fragment>
|
<svelte:fragment slot="title">It's your choice</svelte:fragment>
|
||||||
<svelte:fragment slot="description">
|
<svelte:fragment slot="description">
|
||||||
|
@ -168,7 +168,6 @@
|
|||||||
.wrap {
|
.wrap {
|
||||||
margin-inline: auto;
|
margin-inline: auto;
|
||||||
width: min(87%, 100rem);
|
width: min(87%, 100rem);
|
||||||
margin-top: 7rem;
|
|
||||||
}
|
}
|
||||||
.wrappezoid {
|
.wrappezoid {
|
||||||
height: calc(100vh - 225px);
|
height: calc(100vh - 225px);
|
||||||
|
@ -211,7 +211,6 @@
|
|||||||
main {
|
main {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
margin-top: 7rem;
|
|
||||||
|
|
||||||
// support revanced and heart thingy
|
// support revanced and heart thingy
|
||||||
section {
|
section {
|
||||||
|
@ -207,7 +207,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.search {
|
.search {
|
||||||
padding-top: 5rem;
|
padding-top: 0.6rem;
|
||||||
padding-bottom: 1.25rem;
|
padding-bottom: 1.25rem;
|
||||||
background-color: var(--surface-eight);
|
background-color: var(--surface-eight);
|
||||||
}
|
}
|
||||||
@ -258,10 +258,6 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search {
|
|
||||||
padding-top: 4.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.patches-container {
|
.patches-container {
|
||||||
margin-top: 1rem;
|
margin-top: 1rem;
|
||||||
margin-bottom: 1.5rem;
|
margin-bottom: 1.5rem;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user