mirror of
https://github.com/imputnet/cobalt.git
synced 2025-07-18 11:18:28 +00:00
Merge branch 'AA/sidebar-actual-light-mode' of https://github.com/alectrocute/cobalt into AA/sidebar-actual-light-mode
This commit is contained in:
commit
de9dc3138d
@ -243,11 +243,13 @@ export default async function(o) {
|
||||
}
|
||||
|
||||
if (basicInfo?.short_description?.startsWith("Provided to YouTube by")) {
|
||||
let descItems = basicInfo.short_description.split("\n\n");
|
||||
fileMetadata.album = descItems[2];
|
||||
fileMetadata.copyright = descItems[3];
|
||||
if (descItems[4].startsWith("Released on:")) {
|
||||
fileMetadata.date = descItems[4].replace("Released on: ", '').trim()
|
||||
let descItems = basicInfo.short_description.split("\n\n", 5);
|
||||
if (descItems.length === 5) {
|
||||
fileMetadata.album = descItems[2];
|
||||
fileMetadata.copyright = descItems[3];
|
||||
if (descItems[4].startsWith("Released on:")) {
|
||||
fileMetadata.date = descItems[4].replace("Released on: ", '').trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,5 +26,6 @@
|
||||
"heading.plausible": "anonymous traffic analytics",
|
||||
"heading.cloudflare": "web privacy & security",
|
||||
"heading.responsibility": "user responsibilities",
|
||||
"heading.abuse": "reporting abuse"
|
||||
"heading.abuse": "reporting abuse",
|
||||
"heading.motivation": "motivation"
|
||||
}
|
||||
|
@ -5,15 +5,27 @@
|
||||
import SectionHeading from "$components/misc/SectionHeading.svelte";
|
||||
</script>
|
||||
|
||||
<section id="saving">
|
||||
<section id="summary">
|
||||
<SectionHeading
|
||||
title={$t("about.heading.summary")}
|
||||
sectionId="saving"
|
||||
sectionId="summary"
|
||||
/>
|
||||
|
||||
cobalt lets you save anything from your favorite websites: video, audio, photos or gifs — cobalt can do it all!
|
||||
cobalt helps you save anything from your favorite websites: video, audio, photos or gifs. just paste the link and you're ready to rock!
|
||||
|
||||
no ads, trackers, or paywalls, no nonsense. just a convenient web app that works everywhere.
|
||||
no ads, trackers, paywalls, or other nonsense. just a convenient web app that works anywhere and whenever you need it.
|
||||
</section>
|
||||
|
||||
<section id="motivation">
|
||||
<SectionHeading
|
||||
title={$t("about.heading.motivation")}
|
||||
sectionId="motivation"
|
||||
/>
|
||||
|
||||
cobalt was created for public benefit, to protect people from ads and malware pushed by alternatives.
|
||||
we believe that the best software is safe, open, and accessible.
|
||||
|
||||
it's possible thanks to our long-standing infrastructure partner, [royalehosting.net]({partners.royalehosting})!
|
||||
</section>
|
||||
|
||||
<section id="privacy">
|
||||
@ -44,9 +56,6 @@ cobalt is extremely efficient and a processing server can run on basically any h
|
||||
|
||||
main processing instances are hosted on several dedicated servers in several countries,
|
||||
to reduce latency and distribute the traffic.
|
||||
|
||||
we constantly improve our infrastructure along with our long-standing partner, [royalehosting.net]({partners.royalehosting})!
|
||||
you're in good hands, and will get what you need within seconds.
|
||||
</section>
|
||||
|
||||
<section id="community">
|
||||
|
@ -6,10 +6,10 @@
|
||||
"body.keep_going": "you can help us stay motivated & keep creating safe alternatives to abusive tools by sharing cobalt with a friend or donating.",
|
||||
|
||||
"card.once": "one-time donation",
|
||||
"card.monthly": "monthly donation",
|
||||
"card.recurring": "recurring donation",
|
||||
"card.custom": "custom amount (from $2)",
|
||||
|
||||
"card.processor": "processed by {{value}}",
|
||||
"card.processor": "via {{value}}",
|
||||
|
||||
"card.option.5": "cup of coffee",
|
||||
"card.option.10": "full size pizza",
|
||||
|
@ -114,7 +114,7 @@
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
padding: 48px;
|
||||
padding: 47px;
|
||||
padding-right: 0;
|
||||
gap: 14px;
|
||||
white-space: pre-wrap;
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
<style>
|
||||
:global(.donate-card) {
|
||||
--donate-card-main-padding: 18px;
|
||||
--donate-card-main-padding: 16px;
|
||||
--donate-card-padding: 12px;
|
||||
|
||||
display: flex;
|
||||
@ -37,7 +37,7 @@
|
||||
text-align: left;
|
||||
border-radius: var(--donate-card-padding);
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
padding: 14px 18px;
|
||||
padding: 12px 16px;
|
||||
color: var(--white);
|
||||
gap: 0;
|
||||
letter-spacing: -0.3px;
|
||||
@ -79,10 +79,4 @@
|
||||
gap: 4px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 760px) {
|
||||
:global(.donate-card) {
|
||||
--donate-card-main-padding: 16px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -1,5 +1,8 @@
|
||||
<script lang="ts">
|
||||
import settings from "$lib/state/settings";
|
||||
|
||||
import { donate } from "$lib/env";
|
||||
import { device } from "$lib/device";
|
||||
import { t } from "$lib/i18n/translations";
|
||||
|
||||
import DonateCardContainer from "$components/donate/DonateCardContainer.svelte";
|
||||
@ -11,7 +14,6 @@
|
||||
import IconPizza from "@tabler/icons-svelte/IconPizza.svelte";
|
||||
import IconToolsKitchen2 from "@tabler/icons-svelte/IconToolsKitchen2.svelte";
|
||||
import IconPaperBag from "@tabler/icons-svelte/IconPaperBag.svelte";
|
||||
import IconArrowRight from "@tabler/icons-svelte/IconArrowRight.svelte";
|
||||
import IconSoup from "@tabler/icons-svelte/IconSoup.svelte";
|
||||
import IconFridge from "@tabler/icons-svelte/IconFridge.svelte";
|
||||
import IconArmchair from "@tabler/icons-svelte/IconArmchair.svelte";
|
||||
@ -20,7 +22,11 @@
|
||||
import IconPhoto from "@tabler/icons-svelte/IconPhoto.svelte";
|
||||
import IconWorldWww from "@tabler/icons-svelte/IconWorldWww.svelte";
|
||||
import IconBath from "@tabler/icons-svelte/IconBath.svelte";
|
||||
import OuterLink from "$components/misc/OuterLink.svelte";
|
||||
|
||||
import IconArrowLeft from "@tabler/icons-svelte/IconArrowLeft.svelte";
|
||||
import IconArrowRight from "@tabler/icons-svelte/IconArrowRight.svelte";
|
||||
|
||||
let donateList: HTMLElement;
|
||||
|
||||
let customInput: HTMLInputElement;
|
||||
let customInputValue: number | null;
|
||||
@ -39,7 +45,7 @@
|
||||
4900: IconApple,
|
||||
7398: IconDeviceLaptop,
|
||||
8629: IconPhoto,
|
||||
9433: IconBath
|
||||
9433: IconBath,
|
||||
};
|
||||
|
||||
type Processor = "stripe" | "liberapay";
|
||||
@ -66,7 +72,30 @@
|
||||
}
|
||||
|
||||
const amount = Math.floor(Number(customInputValue) * 100);
|
||||
return window.open(donationMethods[processor](amount), '_blank');
|
||||
return window.open(donationMethods[processor](amount), "_blank");
|
||||
};
|
||||
|
||||
const scrollBehavior = $settings.appearance.reduceMotion
|
||||
? "instant"
|
||||
: "smooth";
|
||||
|
||||
$: showLeftScroll = false;
|
||||
$: showRightScroll = true;
|
||||
|
||||
const scroll = (direction: "left" | "right") => {
|
||||
const currentPos = donateList.scrollLeft;
|
||||
const newPos = direction === "left" ? currentPos - 150 : currentPos + 150;
|
||||
const maxPos = donateList.scrollWidth - donateList.getBoundingClientRect().width;
|
||||
|
||||
donateList.scroll({
|
||||
left: newPos,
|
||||
behavior: scrollBehavior,
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
showLeftScroll = newPos > 0;
|
||||
showRightScroll = newPos < maxPos && newPos !== maxPos;
|
||||
}, 150)
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -84,12 +113,13 @@
|
||||
<div class="donation-type-text">
|
||||
<div class="donate-card-title">{$t("donate.card.once")}</div>
|
||||
<div class="donate-card-subtitle">
|
||||
{$t("donate.card.processor", { value: 'stripe' })}
|
||||
{$t("donate.card.processor", { value: "stripe" })}
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<button
|
||||
id="donation-type-monthly"
|
||||
id="donation-type-recurring"
|
||||
class="donation-type"
|
||||
on:click={() => (processor = "liberapay")}
|
||||
class:selected={processor === "liberapay"}
|
||||
@ -98,29 +128,72 @@
|
||||
>
|
||||
<div class="donation-type-icon"><IconCalendarRepeat /></div>
|
||||
<div class="donation-type-text">
|
||||
<div class="donate-card-title">{$t("donate.card.monthly")}</div>
|
||||
<div class="donate-card-title">{$t("donate.card.recurring")}</div>
|
||||
<div class="donate-card-subtitle">
|
||||
{$t("donate.card.processor", { value: 'liberapay' })}
|
||||
{$t("donate.card.processor", { value: "liberapay" })}
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
<div id="donation-options">
|
||||
{#each Object.entries(PRESET_DONATION_AMOUNTS) as [ amount, component ]}
|
||||
<DonationOption
|
||||
price={+amount}
|
||||
desc={$t(`donate.card.option.${amount}`)}
|
||||
href={donationMethods[processor](+amount * 100)}
|
||||
>
|
||||
<svelte:component this={component} />
|
||||
</DonationOption>
|
||||
{/each}
|
||||
|
||||
<div
|
||||
id="donation-options-container"
|
||||
aria-hidden="true"
|
||||
class:mask-both={!device.is.mobile && showLeftScroll && showRightScroll}
|
||||
class:mask-left={!device.is.mobile && showLeftScroll && !showRightScroll}
|
||||
class:mask-right={!device.is.mobile && showRightScroll && !showLeftScroll}
|
||||
>
|
||||
{#if !device.is.mobile}
|
||||
<div id="donation-options-scroll">
|
||||
<button
|
||||
class="scroll-button left"
|
||||
class:hidden={!showLeftScroll}
|
||||
on:click={() => {
|
||||
scroll("left");
|
||||
}}
|
||||
>
|
||||
<IconArrowLeft />
|
||||
</button>
|
||||
<button
|
||||
class="scroll-button right"
|
||||
class:hidden={!showRightScroll}
|
||||
on:click={() => {
|
||||
scroll("right");
|
||||
}}
|
||||
>
|
||||
<IconArrowRight />
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<div
|
||||
id="donation-options"
|
||||
bind:this={donateList}
|
||||
on:wheel={() => {
|
||||
const currentPos = donateList.scrollLeft;
|
||||
const maxPos = donateList.scrollWidth - donateList.getBoundingClientRect().width;
|
||||
showLeftScroll = currentPos > 0;
|
||||
showRightScroll = currentPos < maxPos && currentPos !== maxPos;
|
||||
}}
|
||||
>
|
||||
{#each Object.entries(PRESET_DONATION_AMOUNTS) as [amount, component]}
|
||||
<DonationOption
|
||||
price={+amount}
|
||||
desc={$t(`donate.card.option.${amount}`)}
|
||||
href={donationMethods[processor](+amount * 100)}
|
||||
>
|
||||
<svelte:component this={component} />
|
||||
</DonationOption>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="donation-custom">
|
||||
<div id="input-container" class:focused={customFocused}>
|
||||
{#if customInputValue || customInput?.validity.badInput}
|
||||
<span id="input-dollar-sign">$</span>
|
||||
{/if}
|
||||
|
||||
<input
|
||||
id="donation-custom-input"
|
||||
type="number"
|
||||
@ -137,6 +210,7 @@
|
||||
on:keydown={(e) => e.key === "Enter" && sendCustom()}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
id="donation-custom-submit"
|
||||
on:click={sendCustom}
|
||||
@ -146,9 +220,6 @@
|
||||
<IconArrowRight />
|
||||
</button>
|
||||
</div>
|
||||
<div class="donate-card-subtitle processor-mobile">
|
||||
{$t("donate.card.processor", { value: processor })}
|
||||
</div>
|
||||
</DonateCardContainer>
|
||||
|
||||
<style>
|
||||
@ -166,7 +237,7 @@
|
||||
#donation-types {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: var(--donate-card-padding);
|
||||
gap: calc(var(--donate-card-main-padding) / 2);
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
@ -198,9 +269,9 @@
|
||||
mask-image: linear-gradient(
|
||||
90deg,
|
||||
rgba(0, 0, 0, 0) 0%,
|
||||
rgba(0, 0, 0, 1) 4%,
|
||||
rgba(0, 0, 0, 1) 3%,
|
||||
rgba(0, 0, 0, 1) 50%,
|
||||
rgba(0, 0, 0, 1) 96%,
|
||||
rgba(0, 0, 0, 1) 97%,
|
||||
rgba(0, 0, 0, 0) 100%
|
||||
);
|
||||
}
|
||||
@ -283,13 +354,82 @@
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.processor-mobile {
|
||||
display: none;
|
||||
text-align: center;
|
||||
#donation-options-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: calc(var(--donate-card-main-padding) / 2);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#donation-options-scroll {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 3;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.scroll-button {
|
||||
pointer-events: all;
|
||||
color: white;
|
||||
padding: 0 16px;
|
||||
background-color: transparent;
|
||||
height: 100%;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
#donation-options-container:hover #donation-options-scroll {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.scroll-button.hidden {
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
#donation-options-container.mask-both:hover #donation-options {
|
||||
mask-image: linear-gradient(
|
||||
90deg,
|
||||
rgba(0, 0, 0, 0) 0%,
|
||||
rgba(0, 0, 0, 1) 20%,
|
||||
rgba(0, 0, 0, 1) 50%,
|
||||
rgba(0, 0, 0, 1) 80%,
|
||||
rgba(0, 0, 0, 0) 100%
|
||||
);
|
||||
}
|
||||
|
||||
#donation-options-container.mask-left:hover #donation-options {
|
||||
mask-image: linear-gradient(
|
||||
90deg,
|
||||
rgba(0, 0, 0, 0) 0%,
|
||||
rgba(0, 0, 0, 1) 20%,
|
||||
rgba(0, 0, 0, 1) 50%,
|
||||
rgba(0, 0, 0, 1) 97%,
|
||||
rgba(0, 0, 0, 0) 100%
|
||||
);
|
||||
}
|
||||
|
||||
#donation-options-container.mask-right:hover #donation-options {
|
||||
mask-image: linear-gradient(
|
||||
90deg,
|
||||
rgba(0, 0, 0, 0) 0%,
|
||||
rgba(0, 0, 0, 1) 3%,
|
||||
rgba(0, 0, 0, 1) 50%,
|
||||
rgba(0, 0, 0, 1) 80%,
|
||||
rgba(0, 0, 0, 0) 100%
|
||||
);
|
||||
}
|
||||
|
||||
@media screen and (max-width: 550px) {
|
||||
:global(#donation-box) {
|
||||
--donate-card-main-padding: 14px;
|
||||
min-width: unset;
|
||||
}
|
||||
|
||||
@ -305,17 +445,5 @@
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
.donation-type .donate-card-subtitle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.processor-mobile {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
#donation-options > :global(a) {
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
|
@ -111,8 +111,9 @@
|
||||
<style>
|
||||
:global(#share-box) {
|
||||
padding: var(--donate-card-main-padding);
|
||||
min-width: 300px;
|
||||
min-width: 320px;
|
||||
width: fit-content;
|
||||
transition: box-shadow 0.15s;
|
||||
}
|
||||
|
||||
#share-card-header {
|
||||
@ -139,7 +140,6 @@
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 12px;
|
||||
max-height: 140px;
|
||||
}
|
||||
|
||||
#share-qr {
|
||||
@ -152,8 +152,8 @@
|
||||
}
|
||||
|
||||
#share-qr :global(svg) {
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
width: 132px;
|
||||
height: 132px;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 0 0 2px rgba(255, 255, 255, var(--donate-border-opacity));
|
||||
}
|
||||
@ -198,8 +198,7 @@
|
||||
z-index: 1;
|
||||
box-shadow:
|
||||
0 0 0 2px rgba(255, 255, 255, var(--donate-border-opacity)) inset,
|
||||
0 0 10px 2px rgba(0, 0, 0, 0.5);
|
||||
transition: box-shadow 0.15s;
|
||||
0 0 20px 3px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
:global(#share-box.expanded #share-qr svg) {
|
||||
|
@ -162,6 +162,14 @@
|
||||
|
||||
#services-disclaimer {
|
||||
padding: 0;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
.expanded #services-disclaimer {
|
||||
padding: 0;
|
||||
user-select: text;
|
||||
-webkit-user-select: text;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 535px) {
|
||||
|
Loading…
Reference in New Issue
Block a user