web: updated api endpoint & params, default instance override

- dialogs can be undismissable now (impossible to click away by pressing the bg behind it)
- added security warning about api override
- moved default api url to env
- added new processing settings page
This commit is contained in:
wukko 2024-08-04 00:43:24 +06:00
parent 168c1bdbbb
commit aba444ec8b
No known key found for this signature in database
GPG key ID: 3E30B3F26C7B4AA2
14 changed files with 134 additions and 23 deletions

View file

@ -8,6 +8,7 @@
"button.share": "share", "button.share": "share",
"button.copy": "copy", "button.copy": "copy",
"button.import": "import", "button.import": "import",
"button.continue": "continue",
"reset.title": "reset all settings?", "reset.title": "reset all settings?",
"reset.body": "are you sure you want to reset all settings? this action is immediate and irreversible.", "reset.body": "are you sure you want to reset all settings? this action is immediate and irreversible.",
@ -22,5 +23,8 @@
"safety.title": "important safety notice", "safety.title": "important safety notice",
"import.body": "importing unknown or corrupted files may unexpectedly alter or break cobalt functionality. only import files that you've personally exported and haven't modified. if you were asked to import this file by someone - don't do it.\n\nwe are not responsible for any harm caused by importing unknown setting files." "import.body": "importing unknown or corrupted files may unexpectedly alter or break cobalt functionality. only import files that you've personally exported and haven't modified. if you were asked to import this file by someone - don't do it.\n\nwe are not responsible for any harm caused by importing unknown setting files.",
"api.override.title": "processing instance override",
"api.override.body": "{{ value }} is now the processing instance. if you don't trust it, press \"cancel\" and it'll be ignored.\n\nyou can change your choice later in processing settings."
} }

View file

@ -6,6 +6,7 @@
"page.download": "downloading", "page.download": "downloading",
"page.advanced": "advanced", "page.advanced": "advanced",
"page.debug": "debug information", "page.debug": "debug information",
"page.processing": "processing",
"section.general": "general", "section.general": "general",
"section.save": "save", "section.save": "save",
@ -103,5 +104,9 @@
"advanced.data": "settings data", "advanced.data": "settings data",
"advanced.reset": "reset all settings", "advanced.reset": "reset all settings",
"advanced.import": "import", "advanced.import": "import",
"advanced.export": "export" "advanced.export": "export",
"processing.override": "default instance override",
"processing.override.title": "use instance-provided processing server",
"processing.override.description": "cobalt will use the processing server from DEFAULT_API when this is enabled."
} }

View file

@ -5,6 +5,7 @@
import DialogBackdropClose from "$components/dialog/DialogBackdropClose.svelte"; import DialogBackdropClose from "$components/dialog/DialogBackdropClose.svelte";
export let id: string; export let id: string;
export let dismissable = true;
let dialogParent: HTMLDialogElement; let dialogParent: HTMLDialogElement;
@ -32,5 +33,5 @@
<dialog id="dialog-{id}" bind:this={dialogParent} class:closing class:open> <dialog id="dialog-{id}" bind:this={dialogParent} class:closing class:open>
<slot></slot> <slot></slot>
<DialogBackdropClose closeFunc={close} /> <DialogBackdropClose closeFunc={dismissable ? close : () => {}} />
</dialog> </dialog>

View file

@ -16,6 +16,7 @@
export let id: string; export let id: string;
export let items: Optional<DialogPickerItem[]> = undefined; export let items: Optional<DialogPickerItem[]> = undefined;
export let buttons: Optional<DialogButton[]> = undefined; export let buttons: Optional<DialogButton[]> = undefined;
export let dismissable = true;
let dialogDescription = "dialog.picker.description."; let dialogDescription = "dialog.picker.description.";
@ -30,7 +31,7 @@
let close: () => void; let close: () => void;
</script> </script>
<DialogContainer {id} bind:close> <DialogContainer {id} {dismissable} bind:close>
<div <div
class="dialog-body picker-dialog" class="dialog-body picker-dialog"
class:three-columns={items && items.length <= 3} class:three-columns={items && items.length <= 3}

View file

@ -19,6 +19,7 @@
export let id: string; export let id: string;
export let url: string; export let url: string;
export let bodyText: string = ""; export let bodyText: string = "";
export let dismissable = true;
let close: () => void; let close: () => void;
@ -31,7 +32,7 @@
} }
</script> </script>
<DialogContainer {id} bind:close> <DialogContainer {id} {dismissable} bind:close>
<div class="dialog-body popup-body"> <div class="dialog-body popup-body">
<div class="meowbalt-container"> <div class="meowbalt-container">
<Meowbalt emotion="question" /> <Meowbalt emotion="question" />

View file

@ -17,11 +17,12 @@
export let bodyText = ""; export let bodyText = "";
export let bodySubText = ""; export let bodySubText = "";
export let buttons: Optional<DialogButton[]> = undefined; export let buttons: Optional<DialogButton[]> = undefined;
export let dismissable = true;
let close: () => void; let close: () => void;
</script> </script>
<DialogContainer {id} bind:close> <DialogContainer {id} {dismissable} bind:close>
<div class="dialog-body small-dialog" class:meowbalt-visible={meowbalt}> <div class="dialog-body small-dialog" class:meowbalt-visible={meowbalt}>
{#if meowbalt} {#if meowbalt}
<div class="meowbalt-container"> <div class="meowbalt-container">

View file

@ -1,33 +1,94 @@
import { get } from "svelte/store"; import { get } from "svelte/store";
import settings from "$lib/state/settings";
import env, { apiURL } from "$lib/env";
import { t } from "$lib/i18n/translations";
import settings, { updateSetting } from "$lib/state/settings";
import { createDialog } from "$lib/dialogs";
import type { CobaltAPIResponse } from "$lib/types/api"; import type { CobaltAPIResponse } from "$lib/types/api";
import type { Optional } from "$lib/types/generic"; import type { Optional } from "$lib/types/generic";
const apiURL = "https://api.cobalt.tools";
const request = async (url: string) => { const request = async (url: string) => {
const saveSettings = get(settings).save; const saveSettings = get(settings).save;
const request = { const request = {
url, url,
isAudioOnly: saveSettings.downloadMode === "audio", downloadMode: saveSettings.downloadMode,
isAudioMuted: saveSettings.downloadMode === "mute",
aFormat: saveSettings.audioFormat,
isTTFullAudio: saveSettings.tiktokFullAudio,
dubLang: saveSettings.youtubeDubBrowserLang,
vCodec: saveSettings.youtubeVideoCodec, audioFormat: saveSettings.audioFormat,
vQuality: saveSettings.videoQuality, tiktokFullAudio: saveSettings.tiktokFullAudio,
youtubeDubBrowserLang: saveSettings.youtubeDubBrowserLang,
filenamePattern: saveSettings.filenameStyle, youtubeVideoCodec: saveSettings.youtubeVideoCodec,
videoQuality: saveSettings.videoQuality,
filenameStyle: saveSettings.filenameStyle,
disableMetadata: saveSettings.disableMetadata, disableMetadata: saveSettings.disableMetadata,
twitterGif: saveSettings.twitterGif, twitterGif: saveSettings.twitterGif,
tiktokH265: saveSettings.tiktokH265, tiktokH265: saveSettings.tiktokH265,
} }
const response: Optional<CobaltAPIResponse> = await fetch(`${apiURL}/api/json`, { if (env.DEFAULT_API && !get(settings).processing.seenOverrideWarning) {
let _actions: {
resolve: () => void;
reject: () => void;
};
const promise = new Promise<void>(
(resolve, reject) => (_actions = { resolve, reject })
).catch(() => {
return {}
});
createDialog({
id: "security-api-override",
type: "small",
icon: "warn-red",
title: get(t)("dialog.api.override.title"),
bodyText: get(t)("dialog.api.override.body", { value: env.DEFAULT_API }),
dismissable: false,
buttons: [
{
text: get(t)("dialog.button.cancel"),
main: false,
action: () => {
_actions.reject();
updateSetting({
processing: {
seenOverrideWarning: true,
},
})
},
},
{
text: get(t)("dialog.button.continue"),
color: "red",
main: true,
timeout: 5000,
action: () => {
_actions.resolve();
updateSetting({
processing: {
allowDefaultOverride: true,
seenOverrideWarning: true,
},
})
},
},
],
})
await promise;
}
let api = apiURL;
if (env.DEFAULT_API && get(settings).processing.allowDefaultOverride) {
api = env.DEFAULT_API;
}
const response: Optional<CobaltAPIResponse> = await fetch(api, {
method: "POST", method: "POST",
redirect: "manual", redirect: "manual",
body: JSON.stringify(request), body: JSON.stringify(request),

View file

@ -9,7 +9,7 @@ import { createDialog } from "$lib/dialogs";
import type { DialogInfo } from "$lib/types/dialog"; import type { DialogInfo } from "$lib/types/dialog";
export const openSavingDialog = (url: string, body: string | void) => { export const openSavingDialog = (url: string, body: string | void) => {
let dialogData: DialogInfo = { const dialogData: DialogInfo = {
type: "saving", type: "saving",
id: "saving", id: "saving",
url url

View file

@ -4,6 +4,7 @@ const variables = {
HOST: env.PUBLIC_HOST, HOST: env.PUBLIC_HOST,
PLAUSIBLE_HOST: env.PUBLIC_PLAUSIBLE_HOST, PLAUSIBLE_HOST: env.PUBLIC_PLAUSIBLE_HOST,
PLAUSIBLE_ENABLED: env.PUBLIC_HOST && env.PUBLIC_PLAUSIBLE_HOST, PLAUSIBLE_ENABLED: env.PUBLIC_HOST && env.PUBLIC_PLAUSIBLE_HOST,
DEFAULT_API: env.PUBLIC_DEFAULT_API,
} }
const donate = { const donate = {
@ -20,5 +21,7 @@ const donate = {
} }
}; };
export { donate }; const apiURL = "https://api.cobalt.tools";
export { donate, apiURL };
export default variables; export default variables;

View file

@ -28,7 +28,11 @@ const defaultSettings: CobaltSettings = {
youtubeDubBrowserLang: false, youtubeDubBrowserLang: false,
}, },
privacy: { privacy: {
disableAnalytics: false disableAnalytics: false,
},
processing: {
allowDefaultOverride: false,
seenOverrideWarning: false,
} }
} }

View file

@ -18,6 +18,7 @@ export type DialogPickerItem = {
type Dialog = { type Dialog = {
id: string, id: string,
dismissable?: boolean,
}; };
type SmallDialog = Dialog & { type SmallDialog = Dialog & {

View file

@ -22,9 +22,14 @@ type CobaltSettingsAdvanced = {
}; };
type CobaltSettingsPrivacy = { type CobaltSettingsPrivacy = {
disableAnalytics: boolean disableAnalytics: boolean,
}; };
type CobaltSettingsProcessing = {
allowDefaultOverride: boolean,
seenOverrideWarning: boolean,
}
type CobaltSettingsSave = { type CobaltSettingsSave = {
audioFormat: typeof audioFormatOptions[number], audioFormat: typeof audioFormatOptions[number],
disableMetadata: boolean, disableMetadata: boolean,
@ -44,7 +49,8 @@ export type CurrentCobaltSettings = {
advanced: CobaltSettingsAdvanced, advanced: CobaltSettingsAdvanced,
appearance: CobaltSettingsAppearance, appearance: CobaltSettingsAppearance,
save: CobaltSettingsSave, save: CobaltSettingsSave,
privacy: CobaltSettingsPrivacy privacy: CobaltSettingsPrivacy,
processing: CobaltSettingsProcessing,
}; };
export type CobaltSettings = CurrentCobaltSettings; export type CobaltSettings = CurrentCobaltSettings;

View file

@ -17,6 +17,7 @@
import IconSettingsBolt from "@tabler/icons-svelte/IconSettingsBolt.svelte"; import IconSettingsBolt from "@tabler/icons-svelte/IconSettingsBolt.svelte";
import IconBug from "@tabler/icons-svelte/IconBug.svelte"; import IconBug from "@tabler/icons-svelte/IconBug.svelte";
import IconLock from "@tabler/icons-svelte/IconLock.svelte"; import IconLock from "@tabler/icons-svelte/IconLock.svelte";
import IconCloudNetwork from "@tabler/icons-svelte/IconCloudNetwork.svelte";
import IconArrowLeft from "@tabler/icons-svelte/IconArrowLeft.svelte"; import IconArrowLeft from "@tabler/icons-svelte/IconArrowLeft.svelte";
@ -129,6 +130,13 @@
</SettingsNavSection> </SettingsNavSection>
<SettingsNavSection> <SettingsNavSection>
<SettingsNavTab
tabName="processing"
tabLink="processing"
iconColor="gray"
>
<IconCloudNetwork />
</SettingsNavTab>
<SettingsNavTab <SettingsNavTab
tabName="advanced" tabName="advanced"
tabLink="advanced" tabLink="advanced"

View file

@ -0,0 +1,15 @@
<script lang="ts">
import { t } from "$lib/i18n/translations";
import SettingsCategory from "$components/settings/SettingsCategory.svelte";
import SettingsToggle from "$components/buttons/SettingsToggle.svelte";
</script>
<SettingsCategory sectionId="override" title={$t("settings.processing.override")}>
<SettingsToggle
settingContext="processing"
settingId="allowDefaultOverride"
title={$t("settings.processing.override.title")}
description={$t("settings.processing.override.description")}
/>
</SettingsCategory>