diff --git a/materialious/src/lib/components/settings/ExportImport.svelte b/materialious/src/lib/components/settings/ExportImport.svelte
index d72ef15b..050f4d6a 100644
--- a/materialious/src/lib/components/settings/ExportImport.svelte
+++ b/materialious/src/lib/components/settings/ExportImport.svelte
@@ -6,10 +6,21 @@
import { importSubscriptions } from '$lib/importExport';
import { postSubscribeInvidious } from '$lib/api/invidious/subscribe';
import { getSubscriptionsInvidious } from '$lib/api/invidious/feed';
- import { backendInUseStore, invidiousAuthStore, invidiousInstanceStore } from '$lib/store';
+ import {
+ backendInUseStore,
+ interfaceAdvancedThemingStore,
+ interfaceBorderRadiusStore,
+ invidiousAuthStore,
+ invidiousInstanceStore
+ } from '$lib/store';
import { Clipboard } from '@capacitor/clipboard';
- import { loadSettingsFromFile, settingsToJson } from '$lib/externalSettings';
+ import {
+ bookmarkletSaveToUrl,
+ loadSettingsFromFile,
+ settingsToJson
+ } from '$lib/externalSettings';
import { downloadStringAsFile } from '$lib/misc';
+ import { zNumber, zThemeColors } from '$lib/externalSettings/settings';
async function importInvidiousSubs() {
const importedSubs = await getSubscriptionsInvidious();
@@ -179,3 +190,79 @@
type="file"
/>
+
+
{$_('layout.theme.theme')}
+
+
+
+
+
+
+
+
+
+ {
+ const files = (event.target as HTMLInputElement).files;
+ if (files?.length === 0 || !files) return;
+
+ await loadSettingsFromFile(files[0]);
+ }}
+ accept=".json"
+ type="file"
+ />
+
diff --git a/materialious/src/lib/externalSettings/index.ts b/materialious/src/lib/externalSettings/index.ts
index ebe24c4c..a8a5514b 100644
--- a/materialious/src/lib/externalSettings/index.ts
+++ b/materialious/src/lib/externalSettings/index.ts
@@ -2,7 +2,7 @@ import { page } from '$app/state';
import { get } from 'svelte/store';
import { z } from 'zod';
-import { persistedStores } from './settings';
+import { persistedStores, type PersistedStore } from './settings';
import { isOwnBackend } from '$lib/shared';
import { addOrUpdateKeyValue, getKeyValue } from '$lib/api/backend/keyvalue';
@@ -121,10 +121,10 @@ export function loadSettingsFromEnv() {
}
}
-export function bookmarkletSaveToUrl(): string {
+export function bookmarkletSaveToUrl(stores: PersistedStore[] = persistedStores): string {
const url = new URL(location.origin);
- for (const { name, store, serialize, excludeFromBookmarklet } of persistedStores) {
+ for (const { name, store, serialize, excludeFromBookmarklet } of stores) {
const value = get(store);
const encoded = serialize ? serialize(value) : value?.toString();
@@ -136,10 +136,10 @@ export function bookmarkletSaveToUrl(): string {
return url.toString();
}
-export function settingsToJson(): string {
+export function settingsToJson(stores: PersistedStore[] = persistedStores): string {
const settings: Record = {};
- for (const { name, store, excludeFromBookmarklet } of persistedStores) {
+ for (const { name, store, excludeFromBookmarklet } of stores) {
const value = get(store);
if (!excludeFromBookmarklet) {
settings[name] = value;
diff --git a/materialious/src/lib/externalSettings/settings.ts b/materialious/src/lib/externalSettings/settings.ts
index 8a9f5c59..2305095c 100644
--- a/materialious/src/lib/externalSettings/settings.ts
+++ b/materialious/src/lib/externalSettings/settings.ts
@@ -60,7 +60,7 @@ import {
import { isOwnBackend } from '$lib/shared';
import { SUPPORTED_THEME_KEYS } from '$lib/shared/theme';
-type PersistedStore = {
+export type PersistedStore = {
name: string;
store: Writable;
schema: z.ZodType;
@@ -69,18 +69,18 @@ type PersistedStore = {
excludeFromBackendSync?: boolean; // Won't be sync'd to account cloud
};
-const zBoolean = z.coerce.boolean();
-const zNumber = z.coerce.number();
-const zFloat = z.coerce.number().min(0).max(1);
-const zString = z.string();
-const zArray = z.array(z.string());
-const zChapterMode = z.enum(['automatic', 'manual', 'timeline']);
-const zChapterModeRecord = z.record(z.string(), zChapterMode.optional());
-const zAuth = z.object({
+export const zBoolean = z.coerce.boolean();
+export const zNumber = z.coerce.number();
+export const zFloat = z.coerce.number().min(0).max(1);
+export const zString = z.string();
+export const zArray = z.array(z.string());
+export const zChapterMode = z.enum(['automatic', 'manual', 'timeline']);
+export const zChapterModeRecord = z.record(z.string(), zChapterMode.optional());
+export const zAuth = z.object({
username: z.string(),
token: z.string()
});
-const zThemeColors = z.record(
+export const zThemeColors = z.record(
z.string().refine((val) => SUPPORTED_THEME_KEYS.includes(val), {
message: 'CSS property not allowed'
}),
diff --git a/materialious/src/lib/i18n/locales/en.json b/materialious/src/lib/i18n/locales/en.json
index 45c91124..d307a55b 100644
--- a/materialious/src/lib/i18n/locales/en.json
+++ b/materialious/src/lib/i18n/locales/en.json
@@ -295,7 +295,8 @@
"exportSub": "Export subscriptions",
"exportToClipboard": "Export to clipboard",
"exportToFile": "Export to file",
- "importFromFile": "Import from file"
+ "importFromFile": "Import from file",
+ "exportToShareUrl": "Export to share URL"
},
"deArrow": {
"title": "DeArrow",
diff --git a/materialious/src/lib/importExport.ts b/materialious/src/lib/importExport.ts
index 52957d45..5d4a7593 100644
--- a/materialious/src/lib/importExport.ts
+++ b/materialious/src/lib/importExport.ts
@@ -221,7 +221,7 @@ export async function exportSubscriptionsAsFile(exportType: 'InvidiousJSON' | 'O
if (data) {
downloadStringAsFile(
data,
- `materialious-export-${new Date().toDateString().replaceAll(' ', '')}.${exportType === 'InvidiousJSON' ? 'json' : 'opml'}`
+ `materialious-export.${exportType === 'InvidiousJSON' ? 'json' : 'opml'}`
);
}
}
diff --git a/materialious/src/lib/misc.ts b/materialious/src/lib/misc.ts
index 9988a359..09aefa7f 100644
--- a/materialious/src/lib/misc.ts
+++ b/materialious/src/lib/misc.ts
@@ -125,7 +125,7 @@ export function downloadStringAsFile(content: string, filename: string) {
const a = document.createElement('a');
a.href = url;
- a.download = filename;
+ a.download = `${new Date().toDateString().replaceAll(' ', '')}-${filename}`;
document.body.appendChild(a);
a.click();
diff --git a/materialious/src/routes/+layout.svelte b/materialious/src/routes/+layout.svelte
index 41093b79..24a9e7df 100644
--- a/materialious/src/routes/+layout.svelte
+++ b/materialious/src/routes/+layout.svelte
@@ -133,6 +133,8 @@
// Should always be loaded after env settings
// So user preferences overwrite instance preferences.
bookmarkletLoadFromUrl();
+
+ setThemeColors($interfaceAdvancedThemingStore);
});
let syncToSettingsInitialized = false;