Merge branch 'main' into main

This commit is contained in:
Aphex 2024-10-20 14:56:05 +02:00 committed by GitHub
commit 162b3cebe9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 411 additions and 129 deletions

View File

@ -127,7 +127,7 @@ export default async function({ host, patternMatch, params }) {
case "tiktok":
r = await tiktok({
postId: patternMatch.postId,
id: patternMatch.id,
shortLink: patternMatch.shortLink,
fullAudio: params.tiktokFullAudio,
isAudioOnly,
h265: params.tiktokH265,

View File

@ -111,10 +111,10 @@ export const services = {
tiktok: {
patterns: [
":user/video/:postId",
":id",
"t/:id",
":shortLink",
"t/:shortLink",
":user/photo/:postId",
"v/:id.html"
"v/:postId.html"
],
subdomains: ["vt", "vm", "m"],
},

View File

@ -39,7 +39,7 @@ export const testers = {
pattern.id?.length === 6,
"tiktok": pattern =>
pattern.postId?.length <= 21 || pattern.id?.length <= 13,
pattern.postId?.length <= 21 || pattern.shortLink?.length <= 13,
"tumblr": pattern =>
pattern.id?.length < 21

View File

@ -12,7 +12,7 @@ export default async function(obj) {
let postId = obj.postId;
if (!postId) {
let html = await fetch(`${shortDomain}${obj.id}`, {
let html = await fetch(`${shortDomain}${obj.shortLink}`, {
redirect: "manual",
headers: {
"user-agent": genericUserAgent.split(' Chrome/1')[0]
@ -24,7 +24,7 @@ export default async function(obj) {
if (html.startsWith('<a href="https://')) {
const extractedURL = html.split('<a href="')[1].split('?')[0];
const { patternMatch } = extract(extractedURL);
postId = patternMatch.postId
postId = patternMatch.postId;
}
}
if (!postId) return { error: "fetch.short_link" };

View File

@ -208,7 +208,7 @@ export default async function({ id, index, toGif, dispatcher, alwaysProxy }) {
let url = bestQuality(content.video_info.variants);
const shouldRenderGif = content.type === "animated_gif" && toGif;
const videoFilename = `twitter_${id}_${i + 1}.mp4`;
const videoFilename = `twitter_${id}_${i + 1}.${shouldRenderGif ? "gif" : "mp4"}`;
let type = "video";
if (shouldRenderGif) type = "gif";

View File

@ -99,7 +99,9 @@ const formatKeys = (keyData) => {
if (data.ips) {
formatted[key].ips = data.ips.map(addr => {
if (ip.isValid(addr)) {
return [ ip.parse(addr), 32 ];
const parsed = ip.parse(addr);
const range = parsed.kind() === 'ipv6' ? 128 : 32;
return [ parsed, range ];
}
return ip.parseCIDR(addr);

View File

@ -3,7 +3,42 @@ this document provides info about methods and acceptable variables for all cobal
> if you are looking for the documentation for the old (7.x) api, you can find
> it [here](https://github.com/imputnet/cobalt/blob/7/docs/api.md)
<!-- TODO: authorization -->
## authentication
an api instance may be configured to require you to authenticate yourself.
if this is the case, you will typically receive an [error response](#error-response)
with a **`api.auth.<method>.missing`** code, which tells you that a particular method
of authentication is required.
authentication is done by passing the `Authorization` header, containing
the authentication scheme and the token:
```
Authorization: <scheme> <token>
```
currently, cobalt supports two ways of authentication. an instance can
choose to configure both, or neither:
- [`Api-Key`](#api-key-authentication)
- [`Bearer`](#bearer-authentication)
### api-key authentication
the api key authentication is the most straightforward. the instance owner
will assign you an api key which you can then use to authenticate like so:
```
Authorization: Api-Key aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
```
if you are an instance owner and wish to configure api key authentication,
see the [instance](run-an-instance.md#api-key-file-format) documentation!
### bearer authentication
the cobalt server may be configured to issue JWT bearers, which are short-lived
tokens intended for use by regular users (e.g. after passing a challenge).
currently, cobalt can issue tokens for successfully solved [turnstile](run-an-instance.md#list-of-all-environment-variables)
challenge, if the instance has turnstile configured. the resulting token is passed like so:
```
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```
## POST: `/`
cobalt's main processing endpoint.
@ -108,3 +143,18 @@ response body type: `application/json`
| `commit` | `string` | commit hash |
| `branch` | `string` | git branch |
| `remote` | `string` | git remote |
## POST: `/session`
used for generating JWT tokens, if enabled. currently, cobalt only supports
generating tokens when a [turnstile](run-an-instance.md#list-of-all-environment-variables) challenge solution
is submitted by the client.
the turnstile challenge response is submitted via the `cf-turnstile-response` header.
### response body
| key | type | description |
|:----------------|:-----------|:-------------------------------------------------------|
| `token` | `string` | a `Bearer` token used for later request authentication |
| `exp` | `number` | number in seconds indicating the token lifetime |
on failure, an [error response](#error-response) is returned.

View File

@ -10,5 +10,8 @@
],
"twitter": [
"auth_token=<replace_this>; ct0=<replace_this>"
],
"youtube_oauth": [
"<output from running `pnpm run token:youtube` in `api` folder goes here>"
]
}

View File

@ -72,11 +72,17 @@ sudo service nscd start
| `RATELIMIT_MAX` | `20` | `30` | max requests per time window. requests above this amount will be blocked for the rate limit window duration. |
| `DURATION_LIMIT` | `10800` | `18000` | max allowed video duration in **seconds**. |
| `TUNNEL_LIFESPAN` | `90` | `120` | the duration for which tunnel info is stored in ram, **in seconds**. |
| `TURNSTILE_SITEKEY` | | `1x00000000000000000000BB` | [cloudflare turnstile](https://www.cloudflare.com/products/turnstile/) sitekey used by browser clients to request a challenge.\*\* |
| `TURNSTILE_SECRET` | | `1x0000000000000000000000000000000AA` | [cloudflare turnstile](https://www.cloudflare.com/products/turnstile/) secret used by cobalt to verify the client successfully solved the challenge.\*\* |
| `JWT_SECRET` | | | the secret used for issuing JWT tokens for request authentication. to choose a value, generate a random, secure, long string (ideally >=16 characters).\*\* |
| `JWT_EXPIRY` | `120` | `240` | the duration of how long a cobalt-issued JWT token will remain valid, in seconds. |
| `API_KEY_URL` | | `file://keys.json` | the location of the api key database. for loading API keys, cobalt supports HTTP(S) urls, or local files by specifying a local path using the `file://` protocol. see the "api key file format" below for more details. |
| `API_AUTH_REQUIRED` | | `1` | when set to `1`, the user always needs to be authenticated in some way before they can access the API (either via an api key or via turnstile, if enabled). |
\* the higher the nice value, the lower the priority. [read more here](https://en.wikipedia.org/wiki/Nice_(Unix)).
\*\* in order to enable turnstile bot protection, all three **`TURNSTILE_SITEKEY`, `TURNSTILE_SECRET` and `JWT_SECRET`** need to be set.
#### FREEBIND_CIDR
setting a `FREEBIND_CIDR` allows cobalt to pick a random IP for every download and use it for all
requests it makes for that particular download. to use freebind in cobalt, you need to follow its [setup instructions](https://github.com/imputnet/freebind.js?tab=readme-ov-file#setup) first. if you configure this option while running cobalt

View File

@ -8,12 +8,6 @@
"page.terms": "terms and ethics",
"page.credits": "thanks & licenses",
"community.discord": "community discord server",
"community.twitter": "news account on twitter",
"community.github": "github repo",
"community.email": "support email",
"community.telegram": "news channel on telegram",
"heading.general": "general terms",
"heading.licenses": "licenses",
"heading.summary": "best way to save what you love",
@ -27,5 +21,14 @@
"heading.responsibility": "user responsibilities",
"heading.abuse": "reporting abuse",
"heading.motivation": "motivation",
"heading.testers": "beta testers"
"heading.testers": "beta testers",
"support.github": "check out cobalt's source code, contribute changes, or report issues",
"support.discord": "chat with the community and developers about cobalt or ask for help",
"support.twitter": "follow cobalt's updates and development on your twitter timeline",
"support.telegram": "stay up to date with latest cobalt updates via a telegram channel",
"support.description.issue": "if you want to report a bug or some other recurring issue, please do it on github.",
"support.description.help": "use discord for any other questions. describe the issue properly in #cobalt-support or else no one will be able help you.",
"support.description.best-effort": "all support is best effort and not guaranteed, a reply might take some time."
}

View File

@ -6,6 +6,17 @@
import BetaTesters from "$components/misc/BetaTesters.svelte";
</script>
<section id="imput">
<SectionHeading
title="imput"
sectionId="imput"
/>
cobalt is made with love and care by the [imput](https://imput.net/) research and development team.
you can support us on the [donate page](/donate)!
</section>
<section id="testers">
<SectionHeading
title={$t("about.heading.testers")}

View File

@ -1,6 +1,6 @@
{
"reset.title": "reset all settings?",
"reset.body": "are you sure you want to reset all settings? this action is immediate and irreversible.",
"reset.title": "reset all data?",
"reset.body": "are you sure you want to reset all data? this action is immediate and irreversible.",
"picker.title": "select what to save",
"picker.description.desktop": "click an item to save it. images can also be saved via the right click menu.",

View File

@ -106,7 +106,7 @@
"advanced.debug.title": "enable debug features",
"advanced.debug.description": "gives you access to a page with various info that can be useful for debugging.",
"advanced.data": "settings data",
"advanced.data": "data management",
"processing.override": "default instance override",
"processing.override.title": "use the instance-provided processing server",

View File

@ -0,0 +1,116 @@
<script lang="ts">
import { t } from "$lib/i18n/translations";
import { openURL } from "$lib/download";
import IconExternalLink from "@tabler/icons-svelte/IconExternalLink.svelte";
import IconBrandGithub from "@tabler/icons-svelte/IconBrandGithub.svelte";
import IconBrandTwitter from "@tabler/icons-svelte/IconBrandTwitter.svelte";
import IconBrandDiscord from "@tabler/icons-svelte/IconBrandDiscord.svelte";
import IconBrandTelegram from "@tabler/icons-svelte/IconBrandTelegram.svelte";
const platformIcons = {
github: {
icon: IconBrandGithub,
color: "#8842cd",
},
discord: {
icon: IconBrandDiscord,
color: "#5865f2",
},
twitter: {
icon: IconBrandTwitter,
color: "#1da1f2",
},
telegram: {
icon: IconBrandTelegram,
color: "#1c9efb",
},
};
export let platform: keyof typeof platformIcons;
export let externalLink: string;
</script>
<button
class="support-card"
role="link"
on:click={() => {
openURL(externalLink);
}}
>
<div class="support-card-header">
<div
class="icon-holder support-icon-{platform}"
style="
background-color: {platformIcons[platform].color};
box-shadow: 0 0 90px 10px {platformIcons[platform].color};
"
>
<svelte:component this={platformIcons[platform].icon} />
</div>
<div class="support-card-title">
{platform}
<IconExternalLink />
</div>
</div>
<div class="subtext support-card-description">
{$t(`about.support.${platform}`)}
</div>
</button>
<style>
.support-card {
padding: var(--padding);
gap: 4px;
height: fit-content;
text-align: left;
flex-direction: column;
align-items: flex-start;
justify-content: flex-start;
overflow: hidden;
}
.support-card-header {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 8px;
}
.icon-holder {
display: flex;
align-items: center;
justify-content: center;
background-color: var(--gray);
padding: 4px;
border-radius: 5px;
}
.icon-holder :global(svg) {
width: 20px;
height: 20px;
stroke-width: 1.5px;
stroke: var(--white);
}
.support-card-title {
display: flex;
flex-direction: row;
align-items: center;
gap: 6px;
}
.support-card-title :global(svg) {
stroke: var(--secondary);
opacity: 0.5;
width: 14px;
height: 14px;
}
.support-card-description {
padding: 0;
}
</style>

View File

@ -47,6 +47,7 @@
background: var(--button);
box-shadow: var(--button-box-shadow);
padding: var(--switcher-padding);
gap: calc(var(--switcher-padding) - 1.5px);
}
.switcher :global(.button.active) {

View File

@ -23,7 +23,16 @@
onDestroy(() => clearInterval(interval));
}
</script>
{#if button.link}
<a
class="button elevated link-button"
class:color={button.color}
class:active={button.main}
href={button.link}
>
{button.text}
</a>
{:else}
<button
class="button elevated popup-button {button.color}"
class:color={button.color}
@ -36,8 +45,14 @@
>
{button.text}{seconds ? ` (${seconds})` : ""}
</button>
{/if}
<style>
.link-button {
text-decoration: none;
font-weight: 500;
width: 100%;
}
.popup-button {
width: 100%;
height: 40px;

View File

@ -4,6 +4,7 @@
import SmallDialog from "$components/dialog/SmallDialog.svelte";
import PickerDialog from "$components/dialog/PickerDialog.svelte";
import SavingDialog from "$components/dialog/SavingDialog.svelte";
import NoScriptDialog from "$components/dialog/NoScriptDialog.svelte";
$: backdropVisible = $dialogs.length > 0;
</script>
@ -13,6 +14,7 @@
more info here: https://github.com/microsoft/TypeScript/issues/46680
-->
<div id="dialog-holder">
<NoScriptDialog />
{#each $dialogs as dialog}
{#if dialog.type === "small"}
<SmallDialog {...dialog} />
@ -71,7 +73,7 @@
pointer-events: none;
}
#dialog-backdrop {
#dialog-backdrop, :global(#nojs-dialog-backdrop) {
position: absolute;
height: 100%;
width: 100%;

View File

@ -0,0 +1,39 @@
<script lang="ts">
import SmallDialog from "$components/dialog/SmallDialog.svelte";
</script>
<noscript style="display: contents">
<div id="nojs-ack">
<SmallDialog
id="nojs-dialog"
meowbalt="error"
bodyText={
"cobalt uses javascript for api requests and ui interactions, but it's not available in your browser. "
+ "you can still navigate around cobalt, but most functionality won't work."
}
buttons={[
{
text: "got it",
main: true,
action: () => {},
link: "#nojs-ack"
},
]}
/>
<div id="nojs-dialog-backdrop"></div>
</div>
</noscript>
<style>
:global(#nojs-ack) {
display: contents;
}
:global(#nojs-ack:target) {
display: none;
}
#nojs-dialog-backdrop {
opacity: 1;
}
</style>

View File

@ -1,11 +1,11 @@
<svg width="24" height="24" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M25.5 2H6.5C5.67157 2 5 2.67157 5 3.5V27.5C5 28.3284 5.67157 29 6.5 29H16.4244C16.795 29 17.1524 28.8628 17.4278 28.6149L26.5034 20.4469C26.8195 20.1624 27 19.7572 27 19.332V3.5C27 2.67157 26.3284 2 25.5 2Z" fill="#E19747"/>
<rect x="7" y="4" width="18" height="23" rx="1" fill="#F3EEF8"/>
<path d="M18 3C18 1.89543 17.1046 1 16 1C14.8954 1 14 1.89543 14 3H13C11.8954 3 11 3.89543 11 5V6.5C11 6.77614 11.2239 7 11.5 7H20.5C20.7761 7 21 6.77614 21 6.5V5C21 3.89543 20.1046 3 19 3H18ZM17 3C17 3.55228 16.5523 4 16 4C15.4477 4 15 3.55228 15 3C15 2.44772 15.4477 2 16 2C16.5523 2 17 2.44772 17 3Z" fill="#9B9B9B"/>
<path d="M25.5 2H6.5C5.67157 2 5 2.67157 5 3.5V27.5C5 28.3284 5.67157 29 6.5 29H16.4244C16.795 29 17.1524 28.8628 17.4278 28.6149L26.5034 20.4469C26.8195 20.1624 27 19.7572 27 19.332V3.5C27 2.67157 26.3284 2 25.5 2Z" fill="#DA882F"/>
<rect x="7" y="4" width="18" height="23" rx="1" fill="#F5F5F5"/>
<path d="M18 3C18 1.89543 17.1046 1 16 1C14.8954 1 14 1.89543 14 3H13C11.8954 3 11 3.89543 11 5V6.5C11 6.77614 11.2239 7 11.5 7H20.5C20.7761 7 21 6.77614 21 6.5V5C21 3.89543 20.1046 3 19 3H18ZM17 3C17 3.55228 16.5523 4 16 4C15.4477 4 15 3.55228 15 3C15 2.44772 15.4477 2 16 2C16.5523 2 17 2.44772 17 3Z" fill="#8F8F8F"/>
<path d="M28 11C28.5523 11 29 11.4477 29 12V26L28.5 26.5L24 31H14C13.4477 31 13 30.5523 13 30V12C13 11.4477 13.4477 11 14 11H28Z" fill="#D9D9D9"/>
<path d="M29 26H24.846C24.3788 26 24 26.3788 24 26.846V31C24.0914 30.9584 24.1755 30.9005 24.2478 30.8282L28.8282 26.2478C28.9005 26.1755 28.9584 26.0914 29 26Z" fill="#B9B9B9"/>
<path d="M15 15.5C15 15.2239 15.1919 15 15.4286 15H26.5714C26.8081 15 27 15.2239 27 15.5C27 15.7761 26.8081 16 26.5714 16H15.4286C15.1919 16 15 15.7761 15 15.5Z" fill="#9B9B9B"/>
<path d="M15 18.5C15 18.2239 15.1919 18 15.4286 18H26.5714C26.8081 18 27 18.2239 27 18.5C27 18.7761 26.8081 19 26.5714 19H15.4286C15.1919 19 15 18.7761 15 18.5Z" fill="#9B9B9B"/>
<path d="M15.4286 21C15.1919 21 15 21.2239 15 21.5C15 21.7761 15.1919 22 15.4286 22H26.5714C26.8081 22 27 21.7761 27 21.5C27 21.2239 26.8081 21 26.5714 21H15.4286Z" fill="#9B9B9B"/>
<path d="M15 24.5C15 24.2239 15.199 24 15.4444 24H22.5556C22.801 24 23 24.2239 23 24.5C23 24.7761 22.801 25 22.5556 25H15.4444C15.199 25 15 24.7761 15 24.5Z" fill="#9B9B9B"/>
<path d="M29 26H24.846C24.3788 26 24 26.3788 24 26.846V31C24.0914 30.9584 24.1755 30.9005 24.2478 30.8282L28.8282 26.2478C28.9005 26.1755 28.9584 26.0914 29 26Z" fill="#BDBDBD"/>
<path d="M15 15.5C15 15.2239 15.1919 15 15.4286 15H26.5714C26.8081 15 27 15.2239 27 15.5C27 15.7761 26.8081 16 26.5714 16H15.4286C15.1919 16 15 15.7761 15 15.5Z" fill="#8F8F8F"/>
<path d="M15 18.5C15 18.2239 15.1919 18 15.4286 18H26.5714C26.8081 18 27 18.2239 27 18.5C27 18.7761 26.8081 19 26.5714 19H15.4286C15.1919 19 15 18.7761 15 18.5Z" fill="#8F8F8F"/>
<path d="M15.4286 21C15.1919 21 15 21.2239 15 21.5C15 21.7761 15.1919 22 15.4286 22H26.5714C26.8081 22 27 21.7761 27 21.5C27 21.2239 26.8081 21 26.5714 21H15.4286Z" fill="#8F8F8F"/>
<path d="M15 24.5C15 24.2239 15.199 24 15.4444 24H22.5556C22.801 24 23 24.2239 23 24.5C23 24.7761 22.801 25 22.5556 25H15.4444C15.199 25 15 24.7761 15 24.5Z" fill="#8F8F8F"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,5 +1,5 @@
<svg width="24" height="24" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14.3599 3.00421L8.21995 3.80421C7.89995 3.84421 7.65995 4.12421 7.65995 4.44421V12.0642C7.08995 11.8642 6.45995 11.7842 5.79995 11.8542C3.74995 12.0742 2.12995 13.7742 1.99995 15.8342C1.83995 18.3242 3.80995 20.3842 6.26995 20.3842C8.62995 20.3842 10.5499 18.4742 10.5499 16.1042C10.5499 16.0142 10.5499 15.9242 10.5399 15.8342V8.00421C10.5399 7.72421 10.7499 7.48421 11.0299 7.44421L14.4899 6.99421C14.7499 6.96421 14.9499 6.73421 14.9499 6.46421V3.53421C14.9599 3.21421 14.6799 2.96421 14.3599 3.00421Z" fill="#6B438B"/>
<path d="M29.4 5.37423L23.26 6.17423C22.94 6.21423 22.7 6.48423 22.7 6.80423V16.8142C22.13 16.6142 21.5 16.5342 20.84 16.6042C18.79 16.8242 17.17 18.5242 17.04 20.5842C16.88 23.0742 18.85 25.1342 21.31 25.1342C23.67 25.1342 25.59 23.2242 25.59 20.8542C25.59 20.7642 25.59 20.6742 25.58 20.5842V10.3742C25.58 10.0942 25.79 9.85423 26.07 9.81423L29.53 9.36423C29.8 9.32423 30 9.10424 30 8.83424V5.89423C30 5.57423 29.72 5.33423 29.4 5.37423Z" fill="#6B438B"/>
<path d="M13.09 10.6543L19.23 9.85429C19.55 9.80429 19.83 10.0543 19.83 10.3743V13.3043C19.83 13.5743 19.63 13.8043 19.37 13.8343L15.91 14.2843C15.63 14.3243 15.42 14.5643 15.42 14.8443V25.0643C15.43 25.1543 15.43 25.2443 15.43 25.3343C15.43 27.7043 13.51 29.6143 11.15 29.6143C8.68995 29.6143 6.71995 27.5543 6.87995 25.0643C6.99995 23.0043 8.61995 21.3143 10.67 21.0943C11.33 21.0243 11.96 21.1043 12.53 21.3043V11.2943C12.53 10.9643 12.77 10.6943 13.09 10.6543Z" fill="#6B438B"/>
<path d="M14.3599 3.00421L8.21995 3.80421C7.89995 3.84421 7.65995 4.12421 7.65995 4.44421V12.0642C7.08995 11.8642 6.45995 11.7842 5.79995 11.8542C3.74995 12.0742 2.12995 13.7742 1.99995 15.8342C1.83995 18.3242 3.80995 20.3842 6.26995 20.3842C8.62995 20.3842 10.5499 18.4742 10.5499 16.1042C10.5499 16.0142 10.5499 15.9242 10.5399 15.8342V8.00421C10.5399 7.72421 10.7499 7.48421 11.0299 7.44421L14.4899 6.99421C14.7499 6.96421 14.9499 6.73421 14.9499 6.46421V3.53421C14.9599 3.21421 14.6799 2.96421 14.3599 3.00421Z" fill="#7941A5"/>
<path d="M29.4 5.37423L23.26 6.17423C22.94 6.21423 22.7 6.48423 22.7 6.80423V16.8142C22.13 16.6142 21.5 16.5342 20.84 16.6042C18.79 16.8242 17.17 18.5242 17.04 20.5842C16.88 23.0742 18.85 25.1342 21.31 25.1342C23.67 25.1342 25.59 23.2242 25.59 20.8542C25.59 20.7642 25.59 20.6742 25.58 20.5842V10.3742C25.58 10.0942 25.79 9.85423 26.07 9.81423L29.53 9.36423C29.8 9.32423 30 9.10424 30 8.83424V5.89423C30 5.57423 29.72 5.33423 29.4 5.37423Z" fill="#7941A5"/>
<path d="M13.09 10.6543L19.23 9.85429C19.55 9.80429 19.83 10.0543 19.83 10.3743V13.3043C19.83 13.5743 19.63 13.8043 19.37 13.8343L15.91 14.2843C15.63 14.3243 15.42 14.5643 15.42 14.8443V25.0643C15.43 25.1543 15.43 25.2443 15.43 25.3343C15.43 27.7043 13.51 29.6143 11.15 29.6143C8.68995 29.6143 6.71995 27.5543 6.87995 25.0643C6.99995 23.0043 8.61995 21.3143 10.67 21.0943C11.33 21.0243 11.96 21.1043 12.53 21.3043V11.2943C12.53 10.9643 12.77 10.6943 13.09 10.6543Z" fill="#7941A5"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -1,5 +1,5 @@
<svg width="24" height="24" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M7.80282 23H12.0122L13.0122 16L12.0122 9H7.80282C6.80707 9 6 9.84705 6 10.8921V21.1079C6 22.153 6.80707 23 7.80282 23ZM26 16.0232C26 17.7104 24.6322 19.0781 22.945 19.0781C21.2579 19.0781 19.8901 17.7104 19.8901 16.0232C19.8901 14.336 21.2579 12.9683 22.945 12.9683C24.6322 12.9683 26 14.336 26 16.0232Z" fill="#9B9B9B"/>
<path d="M20.6106 26.8309L11.9976 23.0011L11.9976 9.01942L20.0474 5.23153C21.1704 4.70349 23.0356 5.2552 23.0356 6.49651V25.3045C23.0356 26.5512 21.7343 27.3705 20.6106 26.8309Z" fill="#D3D3D3"/>
<path d="M7.80282 23H12.0122L13.0122 16L12.0122 9H7.80282C6.80707 9 6 9.84705 6 10.8921V21.1079C6 22.153 6.80707 23 7.80282 23ZM26 16.0232C26 17.7104 24.6322 19.0781 22.945 19.0781C21.2579 19.0781 19.8901 17.7104 19.8901 16.0232C19.8901 14.336 21.2579 12.9683 22.945 12.9683C24.6322 12.9683 26 14.336 26 16.0232Z" fill="#8C8C8C"/>
<path d="M20.6106 26.8309L11.9976 23.0011L11.9976 9.01942L20.0474 5.23153C21.1704 4.70349 23.0356 5.2552 23.0356 6.49651V25.3045C23.0356 26.5512 21.7343 27.3705 20.6106 26.8309Z" fill="#C8C8C8"/>
<path d="M24.9692 26.6519L5.1497 6.83167C4.68545 6.36742 4.68545 5.61418 5.1497 5.14994C5.61394 4.6857 6.36718 4.6857 6.83142 5.14994L26.6509 24.9694C27.1151 25.4337 27.1151 26.1869 26.6509 26.6511C26.1866 27.1161 25.4342 27.1161 24.9692 26.6519Z" fill="#F8312F"/>
</svg>

Before

Width:  |  Height:  |  Size: 907 B

After

Width:  |  Height:  |  Size: 907 B

View File

@ -1,5 +1,5 @@
<svg width="24" height="24" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.5194 7.0517C10.2265 6.93064 9.99626 6.69861 9.88117 6.41614L8.929 4.25725C8.75112 3.91425 8.23842 3.91425 8.071 4.25725L7.11883 6.41614C6.99327 6.69861 6.76308 6.92055 6.48057 7.0517L5.26682 7.57629C4.91106 7.74779 4.91106 8.24212 5.26682 8.41362L6.48057 8.93821C6.77354 9.05927 7.00374 9.2913 7.11883 9.57377L8.071 11.7427C8.24888 12.0858 8.76158 12.0858 8.929 11.7427L9.88117 9.57377C10.0067 9.2913 10.2369 9.06936 10.5194 8.93821L11.7332 8.41362C12.0889 8.24212 12.0889 7.74779 11.7332 7.57629L10.5194 7.0517Z" fill="#FFB02E"/>
<path d="M25.5744 13.5546C24.7045 13.1673 24.0166 12.4539 23.6525 11.5775L20.7897 4.81023C20.2637 3.72992 18.7363 3.72992 18.2103 4.81023L15.3475 11.5775C14.9733 12.4539 14.2854 13.1673 13.4256 13.5546L9.80419 15.1955C8.73194 15.7254 8.73194 17.2746 9.80419 17.8045L13.4256 19.4454C14.2955 19.8327 14.9834 20.5461 15.3475 21.4225L18.2103 28.1898C18.7363 29.2701 20.2637 29.2701 20.7897 28.1898L23.6525 21.4225C24.0267 20.5461 24.7146 19.8327 25.5744 19.4454L29.1958 17.8045C30.2681 17.2746 30.2681 15.7254 29.1958 15.1955L25.5744 13.5546Z" fill="#FFB02E"/>
<path d="M8.2811 20.3304C8.44173 20.7222 8.73465 21.0258 9.10315 21.2021L10.6528 21.927C11.1157 22.1621 11.1157 22.8379 10.6528 23.073L9.10315 23.7979C8.73465 23.9742 8.44173 24.2876 8.2811 24.6696L7.05276 27.6474C6.82598 28.1175 6.17402 28.1175 5.94724 27.6474L4.7189 24.6696C4.55827 24.2778 4.26535 23.9742 3.89685 23.7979L2.34724 23.073C1.88425 22.8379 1.88425 22.1621 2.34724 21.927L3.89685 21.2021C4.26535 21.0258 4.55827 20.7124 4.7189 20.3304L5.94724 17.3526C6.17402 16.8825 6.82598 16.8825 7.05276 17.3526L8.2811 20.3304Z" fill="#FFB02E"/>
<path d="M10.5194 7.0517C10.2265 6.93064 9.99626 6.69861 9.88117 6.41614L8.929 4.25725C8.75112 3.91425 8.23842 3.91425 8.071 4.25725L7.11883 6.41614C6.99327 6.69861 6.76308 6.92055 6.48057 7.0517L5.26682 7.57629C4.91106 7.74779 4.91106 8.24212 5.26682 8.41362L6.48057 8.93821C6.77354 9.05927 7.00374 9.2913 7.11883 9.57377L8.071 11.7427C8.24888 12.0858 8.76158 12.0858 8.929 11.7427L9.88117 9.57377C10.0067 9.2913 10.2369 9.06936 10.5194 8.93821L11.7332 8.41362C12.0889 8.24212 12.0889 7.74779 11.7332 7.57629L10.5194 7.0517Z" fill="#FFA514"/>
<path d="M25.5744 13.5546C24.7045 13.1673 24.0166 12.4539 23.6525 11.5775L20.7897 4.81023C20.2637 3.72992 18.7363 3.72992 18.2103 4.81023L15.3475 11.5775C14.9733 12.4539 14.2854 13.1673 13.4256 13.5546L9.80419 15.1955C8.73194 15.7254 8.73194 17.2746 9.80419 17.8045L13.4256 19.4454C14.2955 19.8327 14.9834 20.5461 15.3475 21.4225L18.2103 28.1898C18.7363 29.2701 20.2637 29.2701 20.7897 28.1898L23.6525 21.4225C24.0267 20.5461 24.7146 19.8327 25.5744 19.4454L29.1958 17.8045C30.2681 17.2746 30.2681 15.7254 29.1958 15.1955L25.5744 13.5546Z" fill="#FFA514"/>
<path d="M8.2811 20.3304C8.44173 20.7222 8.73465 21.0258 9.10315 21.2021L10.6528 21.927C11.1157 22.1621 11.1157 22.8379 10.6528 23.073L9.10315 23.7979C8.73465 23.9742 8.44173 24.2876 8.2811 24.6696L7.05276 27.6474C6.82598 28.1175 6.17402 28.1175 5.94724 27.6474L4.7189 24.6696C4.55827 24.2778 4.26535 23.9742 3.89685 23.7979L2.34724 23.073C1.88425 22.8379 1.88425 22.1621 2.34724 21.927L3.89685 21.2021C4.26535 21.0258 4.55827 20.7124 4.7189 20.3304L5.94724 17.3526C6.17402 16.8825 6.82598 16.8825 7.05276 17.3526L8.2811 20.3304Z" fill="#FFA514"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -8,6 +8,9 @@
export let title: string;
export let sectionId: string;
export let beta = false;
export let copyData = "";
const sectionURL = `${$page.url.origin}${$page.url.pathname}#${sectionId}`;
let copied = false;
@ -19,19 +22,27 @@
</script>
<div class="heading-container">
<h3 class="content-title">{title}</h3>
<h3 class="content-title">
{title}
</h3>
{#if beta}
<div class="beta-label">{$t("general.beta")}</div>
<div class="beta-label">
{$t("general.beta")}
</div>
{/if}
<button
class="link-copy"
aria-label={copied ? $t("button.copied") : $t("button.copy.section")}
aria-label={copied
? $t("button.copied")
: $t(`button.copy${copyData ? "" : ".section"}`)}
on:click={() => {
copied = true;
copyURL(`${$page.url.origin}${$page.url.pathname}#${sectionId}`);
copyURL(copyData || sectionURL);
}}
>
<CopyIcon check={copied} />
<CopyIcon check={copied} regularIcon={!!copyData} />
</button>
</div>

View File

@ -225,7 +225,7 @@
flex-direction: column;
max-width: 640px;
width: 100%;
gap: 10px;
gap: 8px;
}
#input-container {

View File

@ -98,7 +98,7 @@ export const customInstanceWarning = async () => {
text: get(t)("button.continue"),
color: "red",
main: true,
timeout: 15000,
timeout: 5000,
action: () => {
_actions.resolve();
updateSetting({

View File

@ -6,7 +6,8 @@ export type DialogButton = {
color?: "red",
main: boolean,
timeout?: number, // milliseconds
action: () => unknown | Promise<unknown>
action: () => unknown | Promise<unknown>,
link?: string
}
export type SmallDialogIcons = "warn-red";

View File

@ -4,61 +4,76 @@
import { contacts } from "$lib/env";
import { t } from "$lib/i18n/translations";
import DonateAltItem from "$components/donate/DonateAltItem.svelte";
import AboutSupport from "$components/about/AboutSupport.svelte";
let buttonContainerWidth: number;
</script>
<!--
this page is not final and is more of a quick mockup. this is why donate alt item is used for links.
-->
<div id="community-body">
{#if $locale !== "ru"}
<DonateAltItem
type="open"
name={$t("about.community.discord")}
address={contacts.discord}
/>
<div id="support-page">
<div
id="support-buttons"
bind:offsetWidth={buttonContainerWidth}
<DonateAltItem
type="open"
name={$t("about.community.twitter")}
address={contacts.twitter}
title="@justusecobalt"
/>
{/if}
<DonateAltItem
type="open"
name={$t("about.community.github")}
address={contacts.github}
/>
<DonateAltItem
type="open"
name={$t("about.community.email")}
address="mailto:{contacts.email}"
title="{contacts.email}"
class:two={$locale === "ru"}
class:one={buttonContainerWidth < 500}
>
<AboutSupport
platform="github"
externalLink={contacts.github}
/>
{#if $locale === "ru"}
<DonateAltItem
type="open"
name={$t("about.community.telegram")}
address={contacts.telegram_ru}
title="@justusecobalt_ru"
<AboutSupport
platform="telegram"
externalLink={contacts.telegram_ru}
/>
{:else}
<AboutSupport
platform="discord"
externalLink={contacts.discord}
/>
<AboutSupport
platform="twitter"
externalLink={contacts.twitter}
/>
{/if}
</div>
<div class="subtext support-note">
{$t("about.support.description.issue")}
{#if $locale !== "ru"}
{$t("about.support.description.help")}
{/if}
{$t("about.support.description.best-effort")}
</div>
</div>
<style>
#community-body {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
#support-page {
display: flex;
flex-direction: column;
gap: 18px;
}
@media screen and (max-width: 1030px) {
#community-body {
#support-buttons {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
overflow-x: scroll;
gap: var(--padding);
}
#support-buttons.two {
grid-template-columns: 1fr 1fr;
}
#support-buttons.one {
grid-template-columns: 1fr;
}
.support-note {
text-align: left;
padding: 0;
}
</style>

View File

@ -1,12 +1,20 @@
<script lang="ts">
import { onMount } from "svelte";
import { goto } from "$app/navigation";
import { version } from "$lib/version";
import { device, app } from "$lib/device";
import { defaultNavPage } from "$lib/subnav";
import settings, { storedSettings } from "$lib/state/settings";
import SectionHeading from "$components/misc/SectionHeading.svelte";
$: sections = [
{ title: "device", data: device },
{ title: "app", data: app },
{ title: "settings", data: $storedSettings },
{ title: "version", data: $version },
];
onMount(() => {
if (!$settings.advanced.debug) {
goto(defaultNavPage("settings"), { replaceState: true });
@ -15,38 +23,37 @@
</script>
{#if $settings.advanced.debug}
<div id="advanced-page">
<h3>device:</h3>
<div class="message-container subtext">
{JSON.stringify(device, null, 2)}
<div id="debug-page">
{#each sections as { title, data }, i}
<div class="debug-section">
<SectionHeading
sectionId={title}
{title}
copyData={JSON.stringify(data)}
/>
<div class="json-block subtext">
{JSON.stringify(data, null, 2)}
</div>
<h3>app:</h3>
<div class="message-container subtext">
{JSON.stringify(app, null, 2)}
</div>
<h3>settings:</h3>
<div class="message-container subtext">
{JSON.stringify($storedSettings, null, 2)}
</div>
<h3>version:</h3>
<div class="message-container subtext">
{JSON.stringify($version, null, 2)}
</div>
{/each}
</div>
{/if}
<style>
#advanced-page {
#debug-page {
display: flex;
flex-direction: column;
padding: var(--padding);
padding: calc(var(--subnav-padding) / 2);
gap: var(--padding);
}
.message-container {
.debug-section {
display: flex;
flex-direction: column;
gap: var(--padding);
}
.json-block {
display: flex;
flex-direction: column;
line-break: anywhere;