|
3 | 3 | import { horizontalSlide } from '$util/horizontalSlide';
|
4 | 4 | import { fade } from 'svelte/transition';
|
5 | 5 | import { expoOut } from 'svelte/easing';
|
| 6 | + import { createQuery } from '@tanstack/svelte-query'; |
6 | 7 |
|
7 | 8 | import Navigation from './NavButton.svelte';
|
8 | 9 | import Modal from '$lib/components/Dialogue.svelte';
|
9 | 10 | import Button from '$lib/components/Button.svelte';
|
| 11 | + import Banner from '$lib/components/Banner.svelte'; |
| 12 | + import Query from '$lib/components/Query.svelte'; |
10 | 13 |
|
11 | 14 | import Cog from 'svelte-material-icons/Cog.svelte';
|
12 | 15 | import Replay from 'svelte-material-icons/Replay.svelte';
|
13 | 16 |
|
14 |
| - import { api_base_url, set_api_base_url, default_api_url } from '$data/api/settings'; |
| 17 | + import { status_url, api_base_url, set_api_base_url, default_api_url } from '$data/api/settings'; |
15 | 18 | import RouterEvents from '$data/RouterEvents';
|
| 19 | + import { queries } from '$data/api'; |
16 | 20 |
|
17 | 21 | import { useQueryClient } from '@tanstack/svelte-query';
|
18 | 22 |
|
|
31 | 35 | }
|
32 | 36 |
|
33 | 37 | let url = api_base_url();
|
| 38 | + const statusUrl = status_url(); |
34 | 39 |
|
35 | 40 | function save() {
|
36 | 41 | set_api_base_url(url);
|
|
44 | 49 | let menuOpen = false;
|
45 | 50 | let modalOpen = false;
|
46 | 51 | let y: number;
|
| 52 | + const pingQuery = () => createQuery(['ping'], queries.ping); |
47 | 53 |
|
48 | 54 | onMount(() => {
|
49 | 55 | return RouterEvents.subscribe((event) => {
|
|
56 | 62 |
|
57 | 63 | <svelte:window bind:scrollY={y} />
|
58 | 64 |
|
59 |
| -<nav class:scrolled={y > 10}> |
60 |
| - <a class="menu-btn skiptab-btn" href="#skiptab">Skip navigation</a> |
61 |
| - |
62 |
| - <button |
63 |
| - class="menu-btn mobile-only" |
64 |
| - on:click={() => (menuOpen = !menuOpen)} |
65 |
| - class:open={menuOpen} |
66 |
| - aria-label="Menu" |
67 |
| - > |
68 |
| - <span class="menu-btn__burger" /> |
69 |
| - </button> |
70 |
| - <a href="/" id="logo"><img src="/logo.svg" alt="ReVanced Logo" /></a> |
71 |
| - |
72 |
| - {#key menuOpen} |
73 |
| - <div |
74 |
| - class="nav-wrapper" |
75 |
| - class:desktop-only={!menuOpen} |
76 |
| - transition:horizontalSlide={{ direction: 'inline', easing: expoOut, duration: 400 }} |
| 65 | +<div id="nav-container"> |
| 66 | + <Query query={pingQuery()} let:data> |
| 67 | + {#if !data} |
| 68 | + <span class="banner"> |
| 69 | + <Banner level="caution" permanent> |
| 70 | + The API is currently unresponsive and some services may not work correctly. {#if statusUrl} |
| 71 | + Check the <a href={statusUrl} target="_blank" rel="noopener noreferrer">status page</a> for |
| 72 | + updates. |
| 73 | + {/if} |
| 74 | + </Banner> |
| 75 | + </span> |
| 76 | + {/if} |
| 77 | + </Query> |
| 78 | + |
| 79 | + <nav class:scrolled={y > 10}> |
| 80 | + <a class="menu-btn skiptab-btn" href="#skiptab">Skip navigation</a> |
| 81 | + |
| 82 | + <button |
| 83 | + class="menu-btn mobile-only" |
| 84 | + on:click={() => (menuOpen = !menuOpen)} |
| 85 | + class:open={menuOpen} |
| 86 | + aria-label="Menu" |
77 | 87 | >
|
78 |
| - <div id="main-navigation"> |
79 |
| - <ul class="nav-buttons"> |
80 |
| - <Navigation href="/" label="Home">Home</Navigation> |
81 |
| - <Navigation queryKey="manager" href="/download" label="Download">Download</Navigation> |
82 |
| - <Navigation queryKey="patches" href="/patches" label="Patches">Patches</Navigation> |
83 |
| - <Navigation queryKey="contributors" href="/contributors" label="Contributors"> |
84 |
| - Contributors |
85 |
| - </Navigation> |
86 |
| - <Navigation queryKey={['about', 'team']} href="/donate" label="Donate">Donate</Navigation> |
87 |
| - </ul> |
88 |
| - </div> |
89 |
| - <div id="secondary-navigation"> |
90 |
| - <button on:click={() => (modalOpen = !modalOpen)} aria-label="Settings"> |
91 |
| - <Cog size="20px" color="var(--surface-six)" /> |
92 |
| - </button> |
| 88 | + <span class="menu-btn__burger" /> |
| 89 | + </button> |
| 90 | + <a href="/" id="logo"><img src="/logo.svg" alt="ReVanced Logo" /></a> |
| 91 | + |
| 92 | + {#key menuOpen} |
| 93 | + <div |
| 94 | + id="nav-wrapper-container" |
| 95 | + class:desktop-only={!menuOpen} |
| 96 | + transition:horizontalSlide={{ direction: 'inline', easing: expoOut, duration: 400 }} |
| 97 | + > |
| 98 | + <div id="banner-pad"> |
| 99 | + <Query query={pingQuery()} let:data> |
| 100 | + {#if !data} |
| 101 | + <span class="banner"> |
| 102 | + <Banner level="caution" permanent> |
| 103 | + The API is currently unresponsive and some services may not work correctly. {#if statusUrl} |
| 104 | + Check the |
| 105 | + <a href={statusUrl} target="_blank" rel="noopener noreferrer">status page</a> for |
| 106 | + updates. |
| 107 | + {/if} |
| 108 | + </Banner> |
| 109 | + </span> |
| 110 | + {/if} |
| 111 | + </Query> |
| 112 | + </div> |
| 113 | + |
| 114 | + <div class="nav-wrapper"> |
| 115 | + <div id="main-navigation"> |
| 116 | + <ul class="nav-buttons"> |
| 117 | + <Navigation href="/" label="Home">Home</Navigation> |
| 118 | + <Navigation queryKey="manager" href="/download" label="Download">Download</Navigation> |
| 119 | + <Navigation queryKey="patches" href="/patches" label="Patches">Patches</Navigation> |
| 120 | + <Navigation queryKey="contributors" href="/contributors" label="Contributors"> |
| 121 | + Contributors |
| 122 | + </Navigation> |
| 123 | + <Navigation queryKey={['about', 'team']} href="/donate" label="Donate" |
| 124 | + >Donate</Navigation |
| 125 | + > |
| 126 | + </ul> |
| 127 | + </div> |
| 128 | + <div id="secondary-navigation"> |
| 129 | + <button on:click={() => (modalOpen = !modalOpen)} aria-label="Settings"> |
| 130 | + <Cog size="20px" color="var(--surface-six)" /> |
| 131 | + </button> |
| 132 | + </div> |
| 133 | + </div> |
93 | 134 | </div>
|
94 |
| - </div> |
95 |
| - {/key} |
96 |
| - |
97 |
| - {#if menuOpen} |
98 |
| - <div |
99 |
| - class="overlay mobile-only" |
100 |
| - transition:fade={{ duration: 350 }} |
101 |
| - on:click={() => (menuOpen = !menuOpen)} |
102 |
| - on:keypress={() => (menuOpen = !menuOpen)} |
103 |
| - /> |
104 |
| - {/if} |
105 |
| -</nav> |
| 135 | + {/key} |
| 136 | + |
| 137 | + {#if menuOpen} |
| 138 | + <div |
| 139 | + class="overlay mobile-only" |
| 140 | + transition:fade={{ duration: 350 }} |
| 141 | + on:click={() => (menuOpen = !menuOpen)} |
| 142 | + on:keypress={() => (menuOpen = !menuOpen)} |
| 143 | + /> |
| 144 | + {/if} |
| 145 | + </nav> |
| 146 | +</div> |
106 | 147 |
|
107 | 148 | <!-- settings -->
|
108 | 149 | <Modal bind:modalOpen>
|
|
126 | 167 | </svelte:fragment>
|
127 | 168 | </Modal>
|
128 | 169 |
|
129 |
| -<style> |
| 170 | +<style lang="scss"> |
130 | 171 | #logo {
|
131 | 172 | padding: 0.5rem;
|
132 | 173 | }
|
|
160 | 201 | top: 30px;
|
161 | 202 | }
|
162 | 203 |
|
| 204 | + #nav-container { |
| 205 | + position: sticky; |
| 206 | + z-index: 666; |
| 207 | + width: 100%; |
| 208 | +
|
| 209 | + &:has(.nav-buttons > li:first-child.selected) { |
| 210 | + margin-bottom: 2.65rem; |
| 211 | +
|
| 212 | + &:has(.banner) { |
| 213 | + margin-bottom: 1.5rem; |
| 214 | + } |
| 215 | + } |
| 216 | + } |
| 217 | +
|
163 | 218 | nav {
|
164 |
| - position: fixed; |
165 |
| - top: 0; |
166 | 219 | display: flex;
|
167 | 220 | gap: 2rem;
|
168 | 221 | justify-content: space-between;
|
169 | 222 | align-items: center;
|
170 | 223 | padding: 1rem 2rem;
|
171 |
| - z-index: 666; |
172 | 224 | height: 70px;
|
173 | 225 | background-color: var(--surface-eight);
|
174 | 226 | width: 100%;
|
|
181 | 233 | gap: 2rem;
|
182 | 234 | }
|
183 | 235 |
|
184 |
| - a { |
185 |
| - display: flex; |
186 |
| - } |
187 |
| -
|
188 | 236 | img {
|
189 | 237 | height: 22px;
|
190 | 238 | }
|
|
220 | 268 | }
|
221 | 269 | }
|
222 | 270 |
|
| 271 | + #banner-pad { |
| 272 | + display: none; |
| 273 | + } |
| 274 | +
|
| 275 | + #nav-wrapper-container { |
| 276 | + width: 100%; |
| 277 | + } |
| 278 | +
|
223 | 279 | @media (max-width: 767px) {
|
| 280 | + #banner-pad { |
| 281 | + display: block; |
| 282 | + width: 100vw; |
| 283 | + visibility: hidden; |
| 284 | + } |
| 285 | +
|
| 286 | + #nav-container:has(.nav-buttons > li:first-child.selected):has(.banner) { |
| 287 | + margin-bottom: 0rem; |
| 288 | + } |
| 289 | +
|
| 290 | + #nav-wrapper-container { |
| 291 | + overflow: hidden; |
| 292 | + position: fixed; |
| 293 | + width: 20rem; |
| 294 | + top: 0; |
| 295 | + left: 0; |
| 296 | + height: 100%; |
| 297 | + background-color: var(--surface-eight); |
| 298 | + z-index: 100; |
| 299 | + } |
| 300 | +
|
224 | 301 | .nav-wrapper {
|
225 | 302 | flex-direction: column;
|
226 | 303 | gap: 0.5rem;
|
227 | 304 | height: 100%;
|
228 | 305 | margin: 0 auto;
|
229 |
| - position: fixed; |
230 | 306 | width: 20rem;
|
231 |
| - top: 0px; |
232 | 307 | border-radius: 0px 24px 24px 0px;
|
233 |
| - left: 0px; |
234 |
| - background-color: var(--surface-eight); |
235 | 308 | padding: 1rem;
|
236 | 309 | padding-top: 6rem;
|
237 |
| - z-index: 100; |
238 | 310 | }
|
239 | 311 |
|
240 | 312 | .desktop-only {
|
|
0 commit comments