mirror of
https://github.com/imputnet/cobalt.git
synced 2025-01-16 03:45:14 +00:00
web: added saving method preference, made downloading resilient
This commit is contained in:
parent
87adffaf02
commit
5c780a2d2e
|
@ -72,9 +72,12 @@
|
||||||
"metadata.disable.title": "disable file metadata",
|
"metadata.disable.title": "disable file metadata",
|
||||||
"metadata.disable.description": "title, artist, and other info will not be added to the file.",
|
"metadata.disable.description": "title, artist, and other info will not be added to the file.",
|
||||||
|
|
||||||
"saving.method": "saving method",
|
"saving.title": "saving method",
|
||||||
"saving.ask.title": "ask how to save",
|
"saving.ask": "ask",
|
||||||
"saving.ask.description": "offer several ways to save the file instead of opening it in a new tab.",
|
"saving.download": "download",
|
||||||
|
"saving.share": "share",
|
||||||
|
"saving.copy": "copy",
|
||||||
|
"saving.description": "preferred way of saving the file or link from cobalt. if preferred method is unavailable or something goes wrong, cobalt will ask you what to do next.",
|
||||||
|
|
||||||
"accessibility": "accessibility",
|
"accessibility": "accessibility",
|
||||||
"accessibility.transparency.title": "reduce visual transparency",
|
"accessibility.transparency.title": "reduce visual transparency",
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="action-buttons">
|
<div class="action-buttons">
|
||||||
{#if !(app.is.installed && device.is.iOS)}
|
{#if device.supports.directDownload}
|
||||||
<VerticalActionButton
|
<VerticalActionButton
|
||||||
id="save-download"
|
id="save-download"
|
||||||
fill
|
fill
|
||||||
|
@ -46,7 +46,7 @@
|
||||||
</VerticalActionButton>
|
</VerticalActionButton>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if navigator.share !== undefined}
|
{#if device.supports.share}
|
||||||
<VerticalActionButton
|
<VerticalActionButton
|
||||||
id="save-share"
|
id="save-share"
|
||||||
fill
|
fill
|
||||||
|
|
|
@ -15,6 +15,12 @@ const installed = window.matchMedia('(display-mode: standalone)').matches;
|
||||||
const reducedMotion = window.matchMedia(`(prefers-reduced-motion: reduce)`).matches;
|
const reducedMotion = window.matchMedia(`(prefers-reduced-motion: reduce)`).matches;
|
||||||
const reducedTransparency = window.matchMedia(`(prefers-reduced-transparency: reduce)`).matches;
|
const reducedTransparency = window.matchMedia(`(prefers-reduced-transparency: reduce)`).matches;
|
||||||
|
|
||||||
|
const app = {
|
||||||
|
is: {
|
||||||
|
installed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const device = {
|
const device = {
|
||||||
is: {
|
is: {
|
||||||
iPhone,
|
iPhone,
|
||||||
|
@ -28,13 +34,12 @@ const device = {
|
||||||
reducedMotion,
|
reducedMotion,
|
||||||
reducedTransparency,
|
reducedTransparency,
|
||||||
},
|
},
|
||||||
|
supports: {
|
||||||
|
share: navigator.share !== undefined,
|
||||||
|
directDownload: !(installed && iOS),
|
||||||
|
},
|
||||||
userAgent: navigator.userAgent,
|
userAgent: navigator.userAgent,
|
||||||
}
|
}
|
||||||
|
|
||||||
const app = {
|
|
||||||
is: {
|
|
||||||
installed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export { device, app };
|
export { device, app };
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { get } from "svelte/store";
|
import { get } from "svelte/store";
|
||||||
|
|
||||||
import { app, device } from "$lib/device";
|
import { device } from "$lib/device";
|
||||||
import settings from "$lib/state/settings";
|
import settings from "$lib/state/settings";
|
||||||
|
|
||||||
import { createDialog } from "$lib/dialogs";
|
import { createDialog } from "$lib/dialogs";
|
||||||
|
@ -17,28 +17,20 @@ export const openURL = (url: string) => {
|
||||||
|
|
||||||
/* if new tab got blocked by user agent, show a saving dialog */
|
/* if new tab got blocked by user agent, show a saving dialog */
|
||||||
if (!open) {
|
if (!open) {
|
||||||
openSavingDialog(url);
|
return openSavingDialog(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const shareURL = async (url: string) => {
|
export const shareURL = async (url: string) => {
|
||||||
try {
|
|
||||||
return await navigator?.share({ url });
|
return await navigator?.share({ url });
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const copyURL = async (url: string) => {
|
export const copyURL = async (url: string) => {
|
||||||
try {
|
return await navigator?.clipboard?.writeText(url);
|
||||||
return await navigator?.clipboard.writeText(url);
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const downloadFile = (url: string) => {
|
export const downloadFile = (url: string) => {
|
||||||
const savingPreference = get(settings).save.downloadPopup;
|
const pref = get(settings).save.savingMethod;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
user actions (such as invoke share, open new tab) have expiration.
|
user actions (such as invoke share, open new tab) have expiration.
|
||||||
|
@ -49,11 +41,20 @@ export const downloadFile = (url: string) => {
|
||||||
invoke an action without the user agent interrupting it.
|
invoke an action without the user agent interrupting it.
|
||||||
if not, we show a saving dialog for user to re-invoke that action.
|
if not, we show a saving dialog for user to re-invoke that action.
|
||||||
*/
|
*/
|
||||||
if (savingPreference || !navigator.userActivation.isActive) {
|
|
||||||
openSavingDialog(url);
|
if (pref === "ask" || !navigator.userActivation.isActive) {
|
||||||
} else if (device.is.iOS && app.is.installed) {
|
return openSavingDialog(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (pref === "share" && device.supports.share) {
|
||||||
return shareURL(url);
|
return shareURL(url);
|
||||||
} else {
|
} else if (pref === "download" && device.supports.directDownload) {
|
||||||
return openURL(url);
|
return openURL(url);
|
||||||
|
} else if (pref === "copy") {
|
||||||
|
return copyURL(url);
|
||||||
}
|
}
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
return openSavingDialog(url);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,8 @@ const defaultSettings: CobaltSettings = {
|
||||||
audioFormat: "mp3",
|
audioFormat: "mp3",
|
||||||
disableMetadata: false,
|
disableMetadata: false,
|
||||||
downloadMode: "auto",
|
downloadMode: "auto",
|
||||||
downloadPopup: false,
|
|
||||||
filenameStyle: "classic",
|
filenameStyle: "classic",
|
||||||
|
savingMethod: "download",
|
||||||
tiktokH265: false,
|
tiktokH265: false,
|
||||||
tiktokFullAudio: false,
|
tiktokFullAudio: false,
|
||||||
twitterGif: false,
|
twitterGif: false,
|
||||||
|
|
|
@ -10,7 +10,6 @@ const oldSwitcherValues = {
|
||||||
|
|
||||||
const oldCheckboxes = [
|
const oldCheckboxes = [
|
||||||
'audioMode',
|
'audioMode',
|
||||||
'downloadPopup',
|
|
||||||
'fullTikTokAudio',
|
'fullTikTokAudio',
|
||||||
'muteAudio',
|
'muteAudio',
|
||||||
'reduceTransparency',
|
'reduceTransparency',
|
||||||
|
@ -101,7 +100,6 @@ export const migrateOldSettings = () => {
|
||||||
filenameStyle: getLiteral('filenamePattern'),
|
filenameStyle: getLiteral('filenamePattern'),
|
||||||
tiktokFullAudio: getBool('fullTikTokAudio'),
|
tiktokFullAudio: getBool('fullTikTokAudio'),
|
||||||
tiktokH265: getBool('tiktokH265'),
|
tiktokH265: getBool('tiktokH265'),
|
||||||
downloadPopup: getBool('downloadPopup'),
|
|
||||||
disableMetadata: getBool('disableMetadata'),
|
disableMetadata: getBool('disableMetadata'),
|
||||||
twitterGif: getBool('twitterGif'),
|
twitterGif: getBool('twitterGif'),
|
||||||
youtubeDubBrowserLang: getBool('ytDub'),
|
youtubeDubBrowserLang: getBool('ytDub'),
|
||||||
|
|
|
@ -7,6 +7,7 @@ export const downloadModeOptions = ["auto", "audio", "mute"] as const;
|
||||||
export const filenameStyleOptions = ["classic", "basic", "pretty", "nerdy"] as const;
|
export const filenameStyleOptions = ["classic", "basic", "pretty", "nerdy"] as const;
|
||||||
export const videoQualityOptions = ["max", "2160", "1440", "1080", "720", "480", "360", "240", "144"] as const;
|
export const videoQualityOptions = ["max", "2160", "1440", "1080", "720", "480", "360", "240", "144"] as const;
|
||||||
export const youtubeVideoCodecOptions = ["h264", "av1", "vp9"] as const;
|
export const youtubeVideoCodecOptions = ["h264", "av1", "vp9"] as const;
|
||||||
|
export const savingMethodOptions = ["ask", "download", "share", "copy"] as const;
|
||||||
|
|
||||||
type CobaltSettingsAppearance = {
|
type CobaltSettingsAppearance = {
|
||||||
theme: typeof themeOptions[number],
|
theme: typeof themeOptions[number],
|
||||||
|
@ -28,8 +29,8 @@ type CobaltSettingsSave = {
|
||||||
audioFormat: typeof audioFormatOptions[number],
|
audioFormat: typeof audioFormatOptions[number],
|
||||||
disableMetadata: boolean,
|
disableMetadata: boolean,
|
||||||
downloadMode: typeof downloadModeOptions[number],
|
downloadMode: typeof downloadModeOptions[number],
|
||||||
downloadPopup: boolean,
|
|
||||||
filenameStyle: typeof filenameStyleOptions[number],
|
filenameStyle: typeof filenameStyleOptions[number],
|
||||||
|
savingMethod: typeof savingMethodOptions[number],
|
||||||
tiktokH265: boolean,
|
tiktokH265: boolean,
|
||||||
tiktokFullAudio: boolean,
|
tiktokFullAudio: boolean,
|
||||||
twitterGif: boolean,
|
twitterGif: boolean,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { t } from "$lib/i18n/translations";
|
import { t } from "$lib/i18n/translations";
|
||||||
|
|
||||||
import { filenameStyleOptions } from "$lib/types/settings";
|
import { filenameStyleOptions, savingMethodOptions } from "$lib/types/settings";
|
||||||
|
|
||||||
import SettingsCategory from "$components/settings/SettingsCategory.svelte";
|
import SettingsCategory from "$components/settings/SettingsCategory.svelte";
|
||||||
import Switcher from "$components/buttons/Switcher.svelte";
|
import Switcher from "$components/buttons/Switcher.svelte";
|
||||||
|
@ -30,6 +30,20 @@
|
||||||
</div>
|
</div>
|
||||||
</SettingsCategory>
|
</SettingsCategory>
|
||||||
|
|
||||||
|
<SettingsCategory sectionId="saving" title={$t("settings.saving.title")}>
|
||||||
|
<Switcher big={true} description={$t("settings.saving.description")}>
|
||||||
|
{#each savingMethodOptions as value}
|
||||||
|
<SettingsButton
|
||||||
|
settingContext="save"
|
||||||
|
settingId="savingMethod"
|
||||||
|
settingValue={value}
|
||||||
|
>
|
||||||
|
{$t(`settings.saving.${value}`)}
|
||||||
|
</SettingsButton>
|
||||||
|
{/each}
|
||||||
|
</Switcher>
|
||||||
|
</SettingsCategory>
|
||||||
|
|
||||||
<SettingsCategory
|
<SettingsCategory
|
||||||
sectionId="disable-metadata"
|
sectionId="disable-metadata"
|
||||||
title={$t("settings.metadata.file")}
|
title={$t("settings.metadata.file")}
|
||||||
|
@ -41,12 +55,3 @@
|
||||||
description={$t("settings.metadata.disable.description")}
|
description={$t("settings.metadata.disable.description")}
|
||||||
/>
|
/>
|
||||||
</SettingsCategory>
|
</SettingsCategory>
|
||||||
|
|
||||||
<SettingsCategory sectionId="saving" title={$t("settings.saving.method")}>
|
|
||||||
<SettingsToggle
|
|
||||||
settingContext="save"
|
|
||||||
settingId="downloadPopup"
|
|
||||||
title={$t("settings.saving.ask.title")}
|
|
||||||
description={$t("settings.saving.ask.description")}
|
|
||||||
/>
|
|
||||||
</SettingsCategory>
|
|
||||||
|
|
Loading…
Reference in a new issue