diff --git a/src/data/api/cache.ts b/src/data/api/cache.ts deleted file mode 100644 index edc61fa..0000000 --- a/src/data/api/cache.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { browser } from "$app/environment"; - -import { dev_log } from "$lib/utils"; - -const CACHE_KEY_PREFIX = "revanced_api_cache_l1"; -const L1_CACHE_VALIDITY = 5 * 60 * 1000; // 5 minutes - -function l1_key_name(endpoint: string) { - return `${CACHE_KEY_PREFIX}:${endpoint}`; -} - -// Get item from the cache -export function get(endpoint: string) { - if (!browser) { - return null; - } - - const key_name = l1_key_name(endpoint); - const ls_data: { valid_until: number; data: any } | null = JSON.parse(localStorage.getItem(key_name)); - - if (ls_data === null || ls_data.valid_until <= Date.now()) { - dev_log("Cache", `missed "${endpoint}"`); - localStorage.removeItem(key_name); - return null; - } - - - dev_log("Cache", `hit "${endpoint}"`); - return ls_data.data; -} - -// Update the cache -export function update(endpoint: string, data: any) { - if (!browser) { - return; - } - - localStorage.setItem(l1_key_name(endpoint), JSON.stringify({ - data, - valid_until: Date.now() + L1_CACHE_VALIDITY - })); -} - -// Clear the cache -export function clear() { - for (const key of Object.keys(localStorage)) { - if (key.startsWith(CACHE_KEY_PREFIX)) { - localStorage.removeItem(key); - } - } -} diff --git a/src/data/api/index.ts b/src/data/api/index.ts deleted file mode 100644 index c265bba..0000000 --- a/src/data/api/index.ts +++ /dev/null @@ -1,161 +0,0 @@ -import type { Readable, Subscriber, Unsubscriber, Writable } from "svelte/store"; -import { writable } from "svelte/store"; -import { error } from "@sveltejs/kit"; - -import { prerendering, browser, dev } from "$app/environment"; - -import * as settings from "./settings"; -import * as cache from "./cache"; - -export class API implements Readable { - private store: Writable; - // True if we have or are about to request data from the API. - has_requested: boolean; - - // `transform` will transform the data received from the API. - constructor(public readonly endpoint: string, private readonly default_value: T, private readonly transform: ((v: any) => T) = (v) => v as T) { - // Initialize with cached data if possible. - const cached_data = cache.get(this.endpoint); - this.has_requested = cached_data !== null; - - this.store = writable(cached_data || this.default_value); - } - - private url() { - return `${settings.api_base_url()}/${this.endpoint}`; - } - - // Please don't call this directly - private async _update(fetch_fn: typeof fetch) { - // Try to get data from the cache. - let data = cache.get(this.endpoint); - - if (data === null) { - // Fetch and transform data - const response = await fetch_fn(this.url()); - data = this.transform(await response.json()); - - // Update the cache. - cache.update(this.endpoint, data); - } - - this.store.set(data); - } - - // Retrieve data and update. - private update(fetch_fn = fetch) { - // Make sure we set this immediately outside of the async function to avoid JS event loop weirdness. - this.has_requested = true; - return this._update(fetch_fn); - } - - // Start retrieving data if needed. - retrieve_if_needed() { - if (!this.has_requested) { - return this.update(); - } - return Promise.resolve() - } - - // Implements the load function found in `+page/layout.ts` files. - page_load_impl() { - return async ({ fetch }) => { - if (prerendering) { - return {}; - } - - // Might be better to actually return some data from the load function and use that on the client. - if (!(dev || browser || prerendering)) { - throw new Error("The API client is not optimized for production server-side rendering. Please change that :)"); - } - - try { - await this.update(fetch); - return {}; - } catch(e) { - console.error(e); - throw error(504, "API Request Error"); - } - }; - } - - // Implement Svelte store. - subscribe(run: Subscriber, invalidate?: any): Unsubscriber { - // Make sure we have up-to-date data from the API. - if (browser) { - this.retrieve_if_needed(); - } - - return this.store.subscribe(run, invalidate); - } -} - -// API Endpoints -import type { Patch, Repository, Tool } from '../types'; -import { dev_log } from "$lib/utils"; - -export type ReposData = Repository[]; -export type PatchesData = { patches: Patch[]; packages: string[] }; -export type ToolsData = { [repo: string]: Tool }; - -export const repositories = new API("contributors", [], json => json.repositories); - -// It needs to look this way to not break everything. -const tools_placeholder: ToolsData = { - "revanced/revanced-manager": { - version: "v0.0.0", - timestamp: "", - repository: "", - assets: [{ - url: "", - name: "", - content_type: "", - size: null, - }] - } -} - -export const tools = new API("tools", tools_placeholder, json => { - // The API returns data in a weird shape. Make it easier to work with. - let map: Map = new Map(); - for (const tool of json["tools"]) { - const repo: string = tool.repository; - - if (!map.has(repo)) { - map.set(repo, { - version: tool.version, - repository: repo, - // Just use the timestamp of the first one we find. - timestamp: tool.timestamp, - assets: [] - }); - } - - let value = map.get(repo); - value.assets.push({ - name: tool.name, - size: tool.size, - url: tool.browser_download_url, - content_type: tool.content_type - }); - - map.set(repo, value); - } - - return Object.fromEntries(map); -}); - -export const patches = new API("patches", { patches: [], packages: [] }, patches => { - let packages: string[] = []; - - // gets packages - for (let i = 0; i < patches.length; i++) { - patches[i].compatiblePackages.forEach((pkg: Patch) => { - let index = packages.findIndex((x) => x == pkg.name); - if (index === -1) { - packages.push(pkg.name); - } - }); - } - return { patches, packages }; -}); diff --git a/src/data/api/settings.ts b/src/data/api/settings.ts deleted file mode 100644 index 6760c20..0000000 --- a/src/data/api/settings.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { browser } from "$app/environment"; - -const URL_KEY = "revanced_api_url"; - -// Get base URL -export function api_base_url(): string { - const default_base_url = "https://releases.revanced.app"; - if (browser) { - return localStorage.getItem(URL_KEY) || default_base_url; - } - - return default_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); - } -} diff --git a/src/lib/components/atoms/LogoOption.svelte b/src/lib/components/atoms/LogoOption.svelte index a9de0f9..3006387 100644 --- a/src/lib/components/atoms/LogoOption.svelte +++ b/src/lib/components/atoms/LogoOption.svelte @@ -17,55 +17,54 @@ selected = selected; } console.log(selected); - localStorage.setItem("selected", JSON.stringify(selected)); + localStorage.setItem('selected', JSON.stringify(selected)); }; -
+ + +
{filename} - +

{name}

{filename}
- +
diff --git a/src/routes/polling/+page.svelte b/src/routes/polling/+page.svelte deleted file mode 100644 index 40f2d56..0000000 --- a/src/routes/polling/+page.svelte +++ /dev/null @@ -1,239 +0,0 @@ - - - - ReVanced · Logo Poll - - - - -
-
-
-

ReVanced

-

{currentPage >= logoPages ? 'Review selected logos' : 'Select logos'}

-

- {selected.length}/{logos.length} selected · Page {Number(currentPage) + 1}/{logoPages + 1} -

- -
- -
- {#each logos.slice(min, max) as { id, gdrive_direct_url, name, filename }} - {#key currentPage} - - - - {/key} - {/each} - - {#if currentPage >= logoPages} - {#each logos as { id, gdrive_direct_url, name, filename }} - {#if selected.includes(id)} - - - - {/if} - {/each} - {/if} -
- - {#if currentPage >= logoPages && !selected.length} -
-
No logos have been selected.
-
- {/if} -
-
- - -
-
- - diff --git a/src/routes/polling/+page.ts b/src/routes/polling/+page.ts deleted file mode 100644 index 7f9ba3a..0000000 --- a/src/routes/polling/+page.ts +++ /dev/null @@ -1,5 +0,0 @@ -import type { PageLoad } from './$types'; - -import { repositories } from '../../data/api'; - -export const load: PageLoad = repositories.page_load_impl();