Merge branch 'main' into feat/privacy-updates

This commit is contained in:
Maya 2025-10-20 06:00:54 +03:00 committed by GitHub
commit 9ccf5440c2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 501 additions and 161 deletions

View File

@ -2,6 +2,7 @@ PUB_HOSTNAME=localhost:5173 # only gets used for plausible (for now)
PUB_PLAUSIBLE_URL=https://plausible.example.com # can be empty
PUB_ENV=development # "production", "development", or "nightly"
PUB_VERTD_URL=https://vertd.vert.sh # default vertd instance
PUB_DISABLE_ALL_EXTERNAL_REQUESTS=false # disables vertd, stripe, plausible, etc. use if your boss complains about privacy
# please do not change these. donations help a lot
PUB_DONATION_URL=https://donations.vert.sh

View File

@ -1,67 +1,68 @@
name: Docker Image CI
on:
push:
branches: [ "main" ]
tags: [ 'v*' ]
paths:
- 'src/**'
- 'static/**'
pull_request:
branches: [ "main" ]
paths:
- 'src/**'
- 'static/**'
workflow_dispatch:
push:
branches: ["main"]
tags: ["v*"]
paths:
- "src/**"
- "static/**"
pull_request:
branches: ["main"]
paths:
- "src/**"
- "static/**"
workflow_dispatch:
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,format=short
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
PUB_ENV=production
PUB_HOSTNAME=${{ vars.PUB_HOSTNAME || '' }}
PUB_PLAUSIBLE_URL=${{ vars.PUB_PLAUSIBLE_URL || '' }}
PUB_VERTD_URL=https://vertd.vert.sh
PUB_DONATION_URL=https://donations.vert.sh
PUB_STRIPE_KEY=pk_live_51RDVmAGSxPVad6bQwzVNnbc28nlmzA30krLWk1fefCMpUPiSRPkavMMbGqa8A3lUaOCMlsUEVy2CWDYg0ip3aPpL00ZJlsMkf2
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GitHub Container Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ghcr.io/${{ github.repository }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,format=short
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
PUB_ENV=production
PUB_HOSTNAME=${{ vars.PUB_HOSTNAME || '' }}
PUB_PLAUSIBLE_URL=${{ vars.PUB_PLAUSIBLE_URL || '' }}
PUB_VERTD_URL=https://vertd.vert.sh
PUB_DISABLE_ALL_EXTERNAL_REQUESTS=false
PUB_DONATION_URL=https://donations.vert.sh
PUB_STRIPE_KEY=pk_live_51RDVmAGSxPVad6bQwzVNnbc28nlmzA30krLWk1fefCMpUPiSRPkavMMbGqa8A3lUaOCMlsUEVy2CWDYg0ip3aPpL00ZJlsMkf2

View File

@ -6,6 +6,7 @@ ARG PUB_ENV
ARG PUB_HOSTNAME
ARG PUB_PLAUSIBLE_URL
ARG PUB_VERTD_URL
ARG PUB_DISABLE_ALL_EXTERNAL_REQUESTS
ARG PUB_DONATION_URL
ARG PUB_STRIPE_KEY
@ -13,6 +14,7 @@ ENV PUB_ENV=${PUB_ENV}
ENV PUB_HOSTNAME=${PUB_HOSTNAME}
ENV PUB_PLAUSIBLE_URL=${PUB_PLAUSIBLE_URL}
ENV PUB_VERTD_URL=${PUB_VERTD_URL}
ENV PUB_DISABLE_ALL_EXTERNAL_REQUESTS=${PUB_DISABLE_ALL_EXTERNAL_REQUESTS}
ENV PUB_DONATION_URL=${PUB_DONATION_URL}
ENV PUB_STRIPE_KEY=${PUB_STRIPE_KEY}
@ -33,4 +35,4 @@ COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/build /usr/share/nginx/html
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl --fail --silent --output /dev/null http://localhost || exit 1
CMD curl --fail --silent --output /dev/null http://localhost || exit 1

View File

@ -8,6 +8,7 @@ services:
PUB_HOSTNAME: ${PUB_HOSTNAME:-localhost:5173}
PUB_PLAUSIBLE_URL: ${PUB_PLAUSIBLE_URL:-}
PUB_ENV: ${PUB_ENV:-production}
PUB_DISABLE_ALL_EXTERNAL_REQUESTS: ${DISABLE_ALL_EXTERNAL_REQUESTS:-false}
PUB_VERTD_URL: ${PUB_VERTD_URL:-}
PUB_DONATION_URL: ${PUB_DONATION_URL:-https://donations.vert.sh}
PUB_STRIPE_KEY: ${PUB_STRIPE_KEY:-pk_live_51RDVmAGSxPVad6bQwzVNnbc28nlmzA30krLWk1fefCMpUPiSRPkavMMbGqa8A3lUaOCMlsUEVy2CWDYg0ip3aPpL00ZJlsMkf2}

View File

@ -6,13 +6,16 @@ This file covers how to run VERT under a Docker container.
- [Using an image from the GitHub Container Registry](#using-an-image-from-the-github-container-registry)
### Manually building the image
First, clone the repository:
```shell
$ git clone https://github.com/VERT-sh/VERT
$ cd VERT/
```
Then build a Docker image with:
```shell
$ docker build -t vert-sh/vert \
--build-arg PUB_ENV=production \
@ -20,10 +23,12 @@ $ docker build -t vert-sh/vert \
--build-arg PUB_PLAUSIBLE_URL=https://plausible.example.com \
--build-arg PUB_VERTD_URL=https://vertd.vert.sh \
--build-arg PUB_DONATION_URL=https://donations.vert.sh \
--build-arg PUB_DISABLE_ALL_EXTERNAL_REQUESTS=false
--build-arg PUB_STRIPE_KEY="" .
```
You can then run it by using:
```shell
$ docker run -d \
--restart unless-stopped \
@ -33,6 +38,7 @@ $ docker run -d \
```
This will do the following:
- Use the previously built image as the container `vert`, in detached mode
- Continuously restart the container until manually stopped
- Map `3000/tcp` (host) to `80/tcp` (container)
@ -40,7 +46,9 @@ This will do the following:
We also have a [`docker-compose.yml`](/docker-compose.yml) file available. Use `docker compose up` if you want to start the stack, or `docker compose down` to bring it down. You can pass `--build` to `docker compose up` to rebuild the Docker image (useful if you've changed any of the environment variables) as well as `-d` to start it in detached mode. You can read more about Docker Compose in general [here](https://docs.docker.com/compose/intro/compose-application-model/).
### Using an image from the GitHub Container Registry
While there's an image you can pull instead of cloning the repo and building the image yourself, you will not be able to update any of the environment variables (e.g. `PUB_PLAUSIBLE_URL`) as they're baked directly into the image and not obtained during runtime. If you're okay with this, you can simply run this command instead:
```shell
$ docker run -d \
--restart unless-stopped \

252
messages/id.json Normal file
View File

@ -0,0 +1,252 @@
{
"$schema": "https://inlang.com/schema/inlang-message-format",
"navbar": {
"upload": "Unggah",
"convert": "Konversi",
"settings": "Pengaturan",
"about": "Tentang",
"toggle_theme": "Ganti Tema"
},
"footer": {
"copyright": "© {year} VERT.",
"source_code": "Kode sumber",
"discord_server": "Peladen Discord"
},
"upload": {
"title": "Konverter berkas andalanmu.",
"subtitle": "Semua gambar, audio, dan pemrosesan dokumen dilakukan pada perangkatmu. Video dikonversi pada peladen kilat kami. Tidak ada batas ukuran berkas, tidak ada iklan, dan benar-benar sumber terbuka.",
"uploader": {
"text": "Jatuhkan dan klik untuk {action}",
"convert": "Konversi",
"jpegify": "jpegify"
},
"cards": {
"title": "Dapat Ditangani VERT ...",
"images": "Gambar",
"audio": "Audio",
"documents": "Dokumen",
"video": "Video",
"video_server_processing": "Proses di Server",
"local_supported": "Proses di Lokal",
"status": {
"text": "<b>Status:</b> {status}",
"ready": "siap",
"not_ready": "belum siap",
"not_initialized": "tidak terinisialisasi",
"downloading": "mengunduh...",
"initializing": "menginisialisasi...",
"unknown": "status tidak diketahui"
},
"supported_formats": "Format yang didukung:"
},
"tooltip": {
"partial_support": "Format ini hanya dapat dikonversi ke {direction}.",
"direction_input": "sumber asal (dari)",
"direction_output": "target (ke)",
"video_server_processing": "Video upload ke server untuk diproses secara baku, belajar bagaimana mengaturnya di sini."
}
},
"convert": {
"external_warning": {
"title": "Peringatan server eksternal",
"text": "Jika kamu memilih untuk mengonversi ke format video, berkas tersebut akan diunggah ke server eksternal untuk dikonversi. Apakah kamu ingin melanjutkan?",
"yes": "Ya",
"no": "Tidak"
},
"panel": {
"convert_all": "Konversi semua",
"download_all": "Unduh semua sebagai .zip",
"remove_all": "Hapus semua berkas",
"set_all_to": "Atur semua ke",
"na": "N/A"
},
"dropdown": {
"audio": "Audio",
"video": "Video",
"doc": "Dokumen",
"image": "Gambar",
"placeholder": "Cari format"
},
"tooltips": {
"unknown_file": "Jenis berkas tidak diketahui",
"audio_file": "Berkas audio",
"video_file": "Berkas video",
"document_file": "Berkas dokumen",
"image_file": "Berkas gambar",
"convert_file": "Konversi berkas ini",
"download_file": "Unduh berkas ini"
},
"errors": {
"cant_convert": "Kami tidak dapat mengonversi berkas ini.",
"vertd_server": "apa yang kamu lakukan..? kamu seharusnya menjalankan peladen vertd!",
"vertd_generic_body": "Terjadi galat saat mencoba mengonversi video kamu. Apakah kamu ingin mengirimkan video ini ke pengembang untuk membantu memperbaiki kutu ini? Hanya berkas video kamu yang akan dikirim. Tidak ada data identifikasi yang diunggah.",
"vertd_generic_title": "Konversi video galat",
"vertd_generic_yes": "Kirim video",
"vertd_generic_no": "Jangan kirim",
"vertd_failed_to_keep": "Gagal menyimpan video di peladen: {error}",
"unsupported_format": "Hanya berkas gambar, video, audio, dan dokumen yang didukung",
"vertd_not_found": "Tidak dapat menemukan layanan vertd untuk memulai konversi video. Apakah URL layanan sudah diatur dengan benar?",
"worker_downloading": "Konverter {type} sedang diinisialisasi, harap tunggu beberapa saat.",
"worker_error": "Konverter {type} mengalami kesalahan saat inisialisasi, coba lagi nanti.",
"worker_timeout": "Konverter {type} memerlukan waktu lebih lama dari perkiraan untuk inisialisasi, harap tunggu beberapa saat lagi atau segarkan halaman.",
"audio": "audio",
"doc": "dokumen",
"image": "gambar"
}
},
"settings": {
"title": "Pengaturan",
"errors": {
"save_failed": "Gagal menyimpan pengaturan!"
},
"appearance": {
"title": "Tampilan",
"brightness_theme": "Tema kecerahan",
"brightness_description": "Ingin suasana terang benderang, atau malam yang sunyi?",
"light": "Terang",
"dark": "Gelap",
"effect_settings": "Pengaturan efek",
"effect_description": "Ingin efek keren, atau tampilan yang lebih sederhana?",
"enable": "Aktifkan",
"disable": "Nonaktifkan"
},
"conversion": {
"title": "Konversi",
"advanced_settings": "Pengaturan lanjutan",
"filename_format": "Format nama berkas",
"filename_description": "Ini akan menentukan nama berkas saat diunduh, <b>tidak termasuk ekstensi berkas.</b> Kamu dapat menggunakan template berikut dalam format, yang akan diganti dengan informasi terkait: <b>%name%</b> untuk nama berkas asli, <b>%extension%</b> untuk ekstensi berkas asli, dan <b>%date%</b> untuk tanggal saat berkas dikonversi.",
"placeholder": "VERT_%name%",
"default_format": "Format konversi baku",
"default_format_description": "Ini akan mengubah format baku yang dipilih saat kamu mengunggah berkas dengan tipe tersebut.",
"default_format_image": "Gambar",
"default_format_video": "Video",
"default_format_audio": "Audio",
"default_format_document": "Dokumen",
"metadata": "Metadata berkas",
"metadata_description": "Menentukan apakah metadata (EXIF, info lagu, dll.) dari berkas asli akan dipertahankan di berkas hasil konversi.",
"keep": "Pertahankan",
"remove": "Hapus",
"quality": "Kualitas konversi",
"quality_description": "Mengubah kualitas keluaran baku berkas hasil konversi. Nilai yang lebih tinggi dapat menghasilkan waktu konversi dan ukuran berkas yang lebih besar.",
"quality_video": "Mengubah kualitas keluaran baku berkas video hasil konversi. Nilai yang lebih tinggi dapat memperpanjang waktu dan ukuran berkas.",
"quality_audio": "Audio (kbps)",
"quality_images": "Gambar (%)",
"rate": "Laju sampel (Hz)"
},
"vertd": {
"title": "Konversi video",
"status": "status:",
"loading": "memuat...",
"available": "tersedia, commit id {commitId}",
"unavailable": "tidak tersedia (apakah URL sudah benar?)",
"description": "Proyek <code>vertd</code> adalah server wrapper untuk FFmpeg. Ini memungkinkan kamu mengonversi video melalui antarmuka web VERT, sambil memanfaatkan kekuatan GPU untuk mempercepat proses.",
"hosting_info": "Kami menyediakan instance publik untuk kemudahanmu, tetapi kamu juga bisa dengan mudah meng-host sendiri di PC atau server jika tahu caranya. Kamu dapat mengunduh binary server [vertd_link]di sini[/vertd_link] - proses penyiapan akan semakin mudah di masa depan, jadi tetap pantau!",
"instance": "Instance",
"url_placeholder": "Contoh: http://localhost:24153",
"conversion_speed": "Kecepatan konversi",
"speed_description": "Menjelaskan kompromi antara kecepatan dan kualitas. Kecepatan lebih tinggi menghasilkan kualitas lebih rendah, tetapi proses lebih cepat.",
"speeds": {
"very_slow": "Sangat Lambat",
"slower": "Agak Lambat",
"slow": "Lambat",
"medium": "Sedang",
"fast": "Cepat",
"ultra_fast": "Sangat Cepat"
},
"auto_instance": "Otomatis (disarankan)",
"eu_instance": "Falkenstein, Jerman",
"us_instance": "Washington, AS",
"custom_instance": "Kustom"
},
"privacy": {
"title": "Privasi & data",
"plausible_title": "Analitik Plausible",
"plausible_description": "Kami menggunakan [plausible_link]Plausible[/plausible_link], alat analitik yang berfokus pada privasi, untuk mengumpulkan statistik anonim sepenuhnya. Semua data dianonimkan dan diagregasi, tanpa informasi yang dapat diidentifikasi. Kamu dapat melihat analitiknya [analytics_link]di sini[/analytics_link] dan memilih untuk keluar di bawah.",
"opt_in": "Ikut serta",
"opt_out": "Tidak ikut",
"cache_title": "Manajemen cache",
"cache_description": "Kami menyimpan berkas konverter di browser agar kamu tidak perlu mengunduh ulang setiap kali, meningkatkan performa dan menghemat data.",
"refresh_cache": "Segarkan cache",
"clear_cache": "Hapus cache",
"files_cached": "{size} ({count} berkas)",
"loading_cache": "Memuat...",
"total_size": "Total Ukuran",
"files_cached_label": "File Tersimpan",
"cache_cleared": "Cache berhasil dihapus!",
"cache_clear_error": "Gagal menghapus cache."
},
"language": {
"title": "Bahasa",
"description": "Pilih bahasa pilihanmu untuk antarmuka VERT."
}
},
"about": {
"title": "Tentang",
"why": {
"title": "Mengapa VERT?",
"description": "<b>Konverter berkas selalu mengecewakan kami.</b> Mereka jelek, penuh iklan, dan yang paling penting; lambat. Kami memutuskan untuk menyelesaikan masalah ini sekali untuk selamanya dengan membuat alternatif yang memperbaiki semua masalah itu, dan lebih banyak lagi.<br/><br/>Semua berkas non-video dikonversi sepenuhnya di perangkat; artinya tidak ada jeda antara pengiriman dan penerimaan berkas, dan kami tidak pernah melihat berkas yang kamu konversi.<br/><br/>File video diunggah ke server RTX 4000 Ada super cepat kami. Videomu akan tetap di sana selama satu jam jika tidak dikonversi. Jika dikonversi, video akan bertahan satu jam atau hingga diunduh. Setelah itu, berkas akan dihapus dari server kami."
},
"sponsors": {
"title": "Sponsor",
"description": "Ingin mendukung kami? Hubungi pengembang di server [discord_link]Discord[/discord_link], atau kirim email ke",
"email_copied": "Email disalin ke clipboard!"
},
"resources": {
"title": "Sumber daya",
"discord": "Discord",
"source": "Sumber",
"email": "Email"
},
"donate": {
"title": "Donasi untuk VERT",
"description": "Dengan dukunganmu, kami dapat terus memelihara dan meningkatkan VERT.",
"one_time": "Sekali",
"monthly": "Bulanan",
"custom": "Kustom",
"pay_now": "Bayar sekarang",
"donate_amount": "Donasi ${amount} USD",
"thank_you": "Terima kasih atas donasimu!",
"payment_failed": "Pembayaran gagal: {message}{period} Kamu tidak dikenai biaya.",
"donation_error": "Terjadi kesalahan saat memproses donasi. Coba lagi nanti.",
"payment_error": "Kesalahan mengambil detail pembayaran. Coba lagi nanti."
},
"credits": {
"title": "Kredit",
"contact_team": "Jika kamu ingin menghubungi tim pengembang, gunakan email yang ada di kartu \"Sumber Daya\".",
"notable_contributors": "Kontributor penting",
"notable_description": "Kami ingin berterima kasih kepada orang-orang ini atas kontribusi besar mereka untuk VERT.",
"github_contributors": "Kontributor GitHub",
"github_description": "[jpegify_link]Terima kasih[/jpegify_link] banyak kepada semua orang yang telah membantu! [github_link]Ingin membantu juga?[/github_link]",
"no_contributors": "Sepertinya belum ada yang berkontribusi... [contribute_link]jadilah yang pertama berkontribusi![/contribute_link]",
"libraries": "Pustaka",
"libraries_description": "Terima kasih besar kepada FFmpeg (audio, video), ImageMagick (gambar), dan Pandoc (dokumen) atas pemeliharaannya selama bertahun-tahun. VERT bergantung pada mereka untuk menyediakan konversi berkas.",
"roles": {
"lead_developer": "Pengembang utama; backend konversi, implementasi UI",
"developer": "Pengembang; implementasi UI",
"designer": "Desainer; UX, branding, pemasaran",
"docker_ci": "Pemeliharaan Docker & CI",
"former_cofounder": "Mantan co-founder & desainer"
}
},
"errors": {
"github_contributors": "Kesalahan mengambil kontributor GitHub"
}
},
"workers": {
"errors": {
"general": "Kesalahan mengonversi {file}: {message}",
"cancel": "Kesalahan membatalkan konversi untuk {file}: {message}",
"magick": "Kesalahan di worker Magick, konversi gambar mungkin tidak berfungsi dengan benar.",
"ffmpeg": "Kesalahan memuat ffmpeg, beberapa fitur mungkin tidak berfungsi.",
"no_audio": "Tidak ditemukan aliran audio.",
"invalid_rate": "Laju sampel tidak valid: {rate}Hz"
}
},
"jpegify": {
"title": "JPEGIFY RAHASIA!!!",
"subtitle": "(psst... jangan beri tahu siapa pun!)",
"button": "JPEGIFY {compression}%!!!",
"download": "Unduh",
"delete": "Hapus"
}
}

View File

@ -1,7 +1,7 @@
{
"$schema": "https://inlang.com/schema/project-settings",
"baseLocale": "en",
"locales": ["en", "es", "fr", "de", "it", "hr", "tr", "ja", "el"],
"locales": ["en", "es", "fr", "de", "it", "hr", "tr", "ja", "el", "id"],
"modules": [
"https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@4/dist/index.js",
"https://cdn.jsdelivr.net/npm/@inlang/plugin-m-function-matcher@2/dist/index.js"

View File

@ -1,4 +1,4 @@
import { PUB_ENV } from "$env/static/public";
import { PUB_DISABLE_ALL_EXTERNAL_REQUESTS, PUB_ENV } from "$env/static/public";
export const GITHUB_URL_VERT = "https://github.com/VERT-sh/VERT";
export const GITHUB_URL_VERTD = "https://github.com/VERT-sh/vertd";
@ -11,3 +11,7 @@ export const VERT_NAME =
? "VERT Nightly"
: "VERT.sh";
export const CONTACT_EMAIL = "hello@vert.sh";
// i'm not entirely sure this should be in consts.ts, but it is technically a constant as .env is static for VERT
export const DISABLE_ALL_EXTERNAL_REQUESTS =
PUB_DISABLE_ALL_EXTERNAL_REQUESTS === "true";

View File

@ -4,13 +4,23 @@ import { FFmpegConverter } from "./ffmpeg.svelte";
import { PandocConverter } from "./pandoc.svelte";
import { VertdConverter } from "./vertd.svelte";
import { MagickConverter } from "./magick.svelte";
import { DISABLE_ALL_EXTERNAL_REQUESTS } from "$lib/consts";
export const converters = [
new MagickConverter(),
new FFmpegConverter(),
new VertdConverter(),
new PandocConverter(),
];
const getConverters = (): Converter[] => {
const converters: Converter[] = [
new MagickConverter(),
new FFmpegConverter(),
];
if (!DISABLE_ALL_EXTERNAL_REQUESTS) {
converters.push(new VertdConverter());
}
converters.push(new PandocConverter());
return converters;
};
export const converters = getConverters();
export function getConverterByFormat(format: string) {
for (const converter of converters) {

View File

@ -1,7 +1,10 @@
<script lang="ts">
import Panel from "$lib/components/visual/Panel.svelte";
import { HeartHandshakeIcon } from "lucide-svelte";
import { GITHUB_URL_VERT } from "$lib/consts";
import {
DISABLE_ALL_EXTERNAL_REQUESTS,
GITHUB_URL_VERT,
} from "$lib/consts";
import { m } from "$lib/paraglide/messages";
import { link, sanitize } from "$lib/store/index.svelte";
@ -90,11 +93,32 @@
</div>
<!-- GitHub contributors -->
<div class="flex flex-col gap-4">
<div class="flex flex-col gap-1">
<h2 class="text-base font-bold">
{m["about.credits.github_contributors"]()}
</h2>
{#if !DISABLE_ALL_EXTERNAL_REQUESTS}
<div class="flex flex-col gap-4">
<div class="flex flex-col gap-1">
<h2 class="text-base font-bold">
{m["about.credits.github_contributors"]()}
</h2>
{#if ghContribs && ghContribs.length > 0}
<p class="text-base text-muted font-normal">
{@html link(
"github_link",
m["about.credits.github_description"](),
GITHUB_URL_VERT,
true
)}
</p>
{:else}
<p class="text-base text-muted font-normal italic">
{@html link(
"contribute_link",
m["about.credits.no_contributors"](),
GITHUB_URL_VERT,
)}
</p>
{/if}
</div>
{#if ghContribs && ghContribs.length > 0}
<p class="text-base text-muted font-normal">
{@html sanitize(

View File

@ -15,6 +15,7 @@
import { onMount } from "svelte";
import { error } from "$lib/logger";
import { ToastManager } from "$lib/toast/index.svelte";
import { DISABLE_ALL_EXTERNAL_REQUESTS } from "$lib/consts";
const { settings = $bindable() }: { settings: ISettings } = $props();
@ -81,50 +82,55 @@
{m["settings.privacy.title"]()}
</h2>
<div class="flex flex-col gap-8">
<div class="flex flex-col gap-4">
<div class="flex flex-col gap-2">
<p class="text-base font-bold">
{m["settings.privacy.plausible_title"]()}
</p>
<p class="text-sm text-muted font-normal">
{@html sanitize(link(
["plausible_link", "analytics_link"],
m["settings.privacy.plausible_description"](),
[
"https://plausible.io/privacy-focused-web-analytics",
"https://ats.vert.sh/vert.sh",
],
))}
</p>
</div>
<div class="flex flex-col gap-3 w-full">
<div class="flex gap-3 w-full">
<button
onclick={() => (settings.plausible = true)}
class="btn {$effects
? ''
: '!scale-100'} {settings.plausible
? 'selected'
: ''} flex-1 p-4 rounded-lg text-black dynadark:text-white flex items-center justify-center"
>
<PlayIcon size="24" class="inline-block mr-2" />
{m["settings.privacy.opt_in"]()}
</button>
{#if !DISABLE_ALL_EXTERNAL_REQUESTS}
<div class="flex flex-col gap-4">
<div class="flex flex-col gap-2">
<p class="text-base font-bold">
{m["settings.privacy.plausible_title"]()}
</p>
<p class="text-sm text-muted font-normal">
{@html link(
["plausible_link", "analytics_link"],
m["settings.privacy.plausible_description"](),
[
"https://plausible.io/privacy-focused-web-analytics",
"https://ats.vert.sh/vert.sh",
],
)}
</p>
</div>
<div class="flex flex-col gap-3 w-full">
<div class="flex gap-3 w-full">
<button
onclick={() => (settings.plausible = true)}
class="btn {$effects
? ''
: '!scale-100'} {settings.plausible
? 'selected'
: ''} flex-1 p-4 rounded-lg text-black dynadark:text-white flex items-center justify-center"
>
<PlayIcon size="24" class="inline-block mr-2" />
{m["settings.privacy.opt_in"]()}
</button>
<button
onclick={() => (settings.plausible = false)}
class="btn {$effects
? ''
: '!scale-100'} {settings.plausible
? ''
: 'selected'} flex-1 p-4 rounded-lg text-black dynadark:text-white flex items-center justify-center"
>
<PauseIcon size="24" class="inline-block mr-2" />
{m["settings.privacy.opt_out"]()}
</button>
<button
onclick={() => (settings.plausible = false)}
class="btn {$effects
? ''
: '!scale-100'} {settings.plausible
? ''
: 'selected'} flex-1 p-4 rounded-lg text-black dynadark:text-white flex items-center justify-center"
>
<PauseIcon
size="24"
class="inline-block mr-2"
/>
{m["settings.privacy.opt_out"]()}
</button>
</div>
</div>
</div>
</div>
{/if}
<div class="flex flex-col gap-4">
<div class="flex flex-col gap-2">
<p class="text-base font-bold">

View File

@ -325,6 +325,7 @@ export const availableLocales = {
de: "Deutsch",
it: "Italiano",
hr: "Hrvatski",
id: "Bahasa Indonesia",
tr: "Türkçe",
ja: "日本語",
el: "Ελληνικά",

View File

@ -3,7 +3,7 @@
import { goto, beforeNavigate, afterNavigate } from "$app/navigation";
import { PUB_PLAUSIBLE_URL, PUB_HOSTNAME } from "$env/static/public";
import { VERT_NAME } from "$lib/consts";
import { DISABLE_ALL_EXTERNAL_REQUESTS, VERT_NAME } from "$lib/consts";
import * as Layout from "$lib/components/layout";
import * as Navbar from "$lib/components/layout/Navbar";
import featuredImage from "$lib/assets/VERT_Feature.webp";
@ -85,12 +85,14 @@
Settings.instance.load();
VertdInstance.instance
.url()
.then((u) => fetch(`${u}/api/version`))
.then((res) => {
if (res.ok) $vertdLoaded = true;
});
if (!DISABLE_ALL_EXTERNAL_REQUESTS) {
VertdInstance.instance
.url()
.then((u) => fetch(`${u}/api/version`))
.then((res) => {
if (res.ok) $vertdLoaded = true;
});
}
return () => {
window.removeEventListener("paste", handlePaste);
@ -100,7 +102,9 @@
$effect(() => {
enablePlausible =
!!PUB_PLAUSIBLE_URL && Settings.instance.settings.plausible;
!!PUB_PLAUSIBLE_URL &&
Settings.instance.settings.plausible &&
!DISABLE_ALL_EXTERNAL_REQUESTS;
if (!enablePlausible && browser) {
// reset pushState on opt-out so that plausible stops firing events on page navigation
history.pushState = History.prototype.pushState;

View File

@ -12,6 +12,7 @@
import { onMount } from "svelte";
import type { WorkerStatus } from "$lib/converters/converter.svelte";
import { sanitize } from "$lib/store/index.svelte";
import { DISABLE_ALL_EXTERNAL_REQUESTS } from "$lib/consts";
const getSupportedFormats = (name: string) =>
converters
@ -29,37 +30,51 @@
title: string;
status: WorkerStatus;
};
} = $derived({
Images: {
formats: getSupportedFormats("imagemagick"),
icon: Image,
title: m["upload.cards.images"](),
status:
converters.find((c) => c.name === "imagemagick")?.status ||
"not-ready",
},
Audio: {
formats: getSupportedFormats("ffmpeg"),
icon: AudioLines,
title: m["upload.cards.audio"](),
status:
converters.find((c) => c.name === "ffmpeg")?.status ||
"not-ready",
},
Documents: {
formats: getSupportedFormats("pandoc"),
icon: BookText,
title: m["upload.cards.documents"](),
status:
converters.find((c) => c.name === "pandoc")?.status ||
"not-ready",
},
Video: {
formats: getSupportedFormats("vertd"),
icon: Film,
title: m["upload.cards.video"](),
status: $vertdLoaded === true ? "ready" : "not-ready", // not using converter.status for this
},
} = $derived.by(() => {
const output: {
[key: string]: {
formats: string;
icon: typeof Image;
title: string;
status: WorkerStatus;
};
} = {
Images: {
formats: getSupportedFormats("imagemagick"),
icon: Image,
title: m["upload.cards.images"](),
status:
converters.find((c) => c.name === "imagemagick")?.status ||
"not-ready",
},
Audio: {
formats: getSupportedFormats("ffmpeg"),
icon: AudioLines,
title: m["upload.cards.audio"](),
status:
converters.find((c) => c.name === "ffmpeg")?.status ||
"not-ready",
},
Documents: {
formats: getSupportedFormats("pandoc"),
icon: BookText,
title: m["upload.cards.documents"](),
status:
converters.find((c) => c.name === "pandoc")?.status ||
"not-ready",
},
};
if (!DISABLE_ALL_EXTERNAL_REQUESTS) {
output.Video = {
formats: getSupportedFormats("vertd"),
icon: Film,
title: m["upload.cards.video"](),
status: $vertdLoaded === true ? "ready" : "not-ready", // not using converter.status for this
};
}
return output;
});
const getTooltip = (format: string) => {

View File

@ -8,7 +8,7 @@
import avatarJovannMC from "$lib/assets/avatars/jovannmc.jpg";
import avatarRealmy from "$lib/assets/avatars/realmy.jpg";
import avatarAzurejelly from "$lib/assets/avatars/azurejelly.jpg";
import { GITHUB_API_URL } from "$lib/consts";
import { DISABLE_ALL_EXTERNAL_REQUESTS, GITHUB_API_URL } from "$lib/consts";
import { dev } from "$app/environment";
import { page } from "$app/state";
import { m } from "$lib/paraglide/messages";
@ -70,6 +70,10 @@
let ghContribs: Contributor[] = [];
onMount(async () => {
if (DISABLE_ALL_EXTERNAL_REQUESTS) {
return;
}
// Check if the data is already in sessionStorage
const cachedContribs = sessionStorage.getItem("ghContribs");
if (cachedContribs) {
@ -134,7 +138,9 @@
}
});
const donationsEnabled = dev || page.url.origin.endsWith("//vert.sh");
const donationsEnabled =
(dev || page.url.origin.endsWith("//vert.sh")) &&
!DISABLE_ALL_EXTERNAL_REQUESTS;
</script>
<div class="flex flex-col h-full items-center">

View File

@ -7,6 +7,7 @@
import { onMount } from "svelte";
import { m } from "$lib/paraglide/messages";
import { ToastManager } from "$lib/toast/index.svelte";
import { DISABLE_ALL_EXTERNAL_REQUESTS } from "$lib/consts";
let settings = $state(Settings.Settings.instance.settings);
@ -63,12 +64,16 @@
>
<div class="flex flex-col gap-4 flex-1">
<Settings.Conversion bind:settings />
<Settings.Vertd bind:settings />
{#if !DISABLE_ALL_EXTERNAL_REQUESTS}
<Settings.Vertd bind:settings />
{:else if PUB_PLAUSIBLE_URL}
<Settings.Privacy bind:settings />
{/if}
</div>
<div class="flex flex-col gap-4 flex-1">
<Settings.Appearance />
{#if PUB_PLAUSIBLE_URL}
{#if PUB_PLAUSIBLE_URL && !DISABLE_ALL_EXTERNAL_REQUESTS}
<Settings.Privacy bind:settings />
{/if}
</div>