Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c900fc476f | ||
|
|
d612b40fdb | ||
|
|
faa4c42f20 | ||
|
|
17fa913ba9 |
@@ -62,24 +62,115 @@ jobs:
|
||||
path: ui/build
|
||||
retention-days: 1
|
||||
|
||||
# ── docker: backend ───────────────────────────────────────────────────────────
|
||||
docker-backend:
|
||||
name: Docker / backend
|
||||
# ── ui: source map upload ─────────────────────────────────────────────────────
|
||||
# Commented out — re-enable when GlitchTip source map uploads are needed again.
|
||||
#
|
||||
# upload-sourcemaps:
|
||||
# name: Upload source maps
|
||||
# runs-on: ubuntu-latest
|
||||
# needs: [check-ui]
|
||||
# steps:
|
||||
# - name: Compute release version (strip leading v)
|
||||
# id: ver
|
||||
# run: |
|
||||
# V="${{ gitea.ref_name }}"
|
||||
# echo "version=${V#v}" >> "$GITHUB_OUTPUT"
|
||||
#
|
||||
# - name: Download build artifacts
|
||||
# uses: actions/download-artifact@v3
|
||||
# with:
|
||||
# name: ui-build
|
||||
# path: build
|
||||
#
|
||||
# - name: Install sentry-cli
|
||||
# run: npm install -g @sentry/cli
|
||||
#
|
||||
# - name: Inject debug IDs into build artifacts
|
||||
# run: sentry-cli sourcemaps inject ./build
|
||||
# env:
|
||||
# SENTRY_URL: https://errors.libnovel.cc/
|
||||
# SENTRY_AUTH_TOKEN: ${{ secrets.GLITCHTIP_AUTH_TOKEN }}
|
||||
# SENTRY_ORG: libnovel
|
||||
# SENTRY_PROJECT: ui
|
||||
#
|
||||
# - name: Upload injected build (for docker-ui)
|
||||
# uses: actions/upload-artifact@v3
|
||||
# with:
|
||||
# name: ui-build-injected
|
||||
# path: build
|
||||
# retention-days: 1
|
||||
#
|
||||
# - name: Create GlitchTip release
|
||||
# run: sentry-cli releases new ${{ steps.ver.outputs.version }}
|
||||
# env:
|
||||
# SENTRY_URL: https://errors.libnovel.cc/
|
||||
# SENTRY_AUTH_TOKEN: ${{ secrets.GLITCHTIP_AUTH_TOKEN }}
|
||||
# SENTRY_ORG: libnovel
|
||||
# SENTRY_PROJECT: ui
|
||||
#
|
||||
# - name: Upload source maps to GlitchTip
|
||||
# run: sentry-cli sourcemaps upload ./build --release ${{ steps.ver.outputs.version }}
|
||||
# env:
|
||||
# SENTRY_URL: https://errors.libnovel.cc/
|
||||
# SENTRY_AUTH_TOKEN: ${{ secrets.GLITCHTIP_AUTH_TOKEN }}
|
||||
# SENTRY_ORG: libnovel
|
||||
# SENTRY_PROJECT: ui
|
||||
#
|
||||
# - name: Finalize GlitchTip release
|
||||
# run: sentry-cli releases finalize ${{ steps.ver.outputs.version }}
|
||||
# env:
|
||||
# SENTRY_URL: https://errors.libnovel.cc/
|
||||
# SENTRY_AUTH_TOKEN: ${{ secrets.GLITCHTIP_AUTH_TOKEN }}
|
||||
# SENTRY_ORG: libnovel
|
||||
# SENTRY_PROJECT: ui
|
||||
#
|
||||
# - name: Prune old GlitchTip releases (keep latest 10)
|
||||
# run: |
|
||||
# set -euo pipefail
|
||||
# KEEP=10
|
||||
# OLD=$(curl -sf \
|
||||
# -H "Authorization: Bearer $SENTRY_AUTH_TOKEN" \
|
||||
# "$SENTRY_URL/api/0/organizations/$SENTRY_ORG/releases/?project=$SENTRY_PROJECT&per_page=100" \
|
||||
# | python3 -c "
|
||||
# import sys, json
|
||||
# releases = json.load(sys.stdin)
|
||||
# for r in releases[$KEEP:]:
|
||||
# print(r['version'])
|
||||
# " KEEP=$KEEP)
|
||||
# for ver in $OLD; do
|
||||
# echo "Deleting old release: $ver"
|
||||
# sentry-cli releases delete "$ver" || true
|
||||
# done
|
||||
# env:
|
||||
# SENTRY_URL: https://errors.libnovel.cc
|
||||
# SENTRY_AUTH_TOKEN: ${{ secrets.GLITCHTIP_AUTH_TOKEN }}
|
||||
# SENTRY_ORG: libnovel
|
||||
# SENTRY_PROJECT: ui
|
||||
|
||||
# ── docker: all images in one job (single login) ──────────────────────────────
|
||||
# backend, runner, ui, and caddy are built sequentially in one job so Docker
|
||||
# Hub only needs to be authenticated once. This also eliminates 3 redundant
|
||||
# checkout + setup-buildx + scheduler round-trips compared to separate jobs.
|
||||
docker:
|
||||
name: Docker
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test-backend]
|
||||
needs: [test-backend, check-ui]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
|
||||
# Single login — credential is written to ~/.docker/config.json and
|
||||
# reused by all subsequent build-push-action steps in this job.
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USER }}
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
# ── backend ──────────────────────────────────────────────────────────────
|
||||
- name: Docker meta / backend
|
||||
id: meta-backend
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ secrets.DOCKER_USER }}/libnovel-backend
|
||||
@@ -88,38 +179,23 @@ jobs:
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,value=latest
|
||||
|
||||
- name: Build and push
|
||||
- name: Build and push / backend
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: backend
|
||||
target: backend
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
tags: ${{ steps.meta-backend.outputs.tags }}
|
||||
labels: ${{ steps.meta-backend.outputs.labels }}
|
||||
build-args: |
|
||||
VERSION=${{ steps.meta.outputs.version }}
|
||||
VERSION=${{ steps.meta-backend.outputs.version }}
|
||||
COMMIT=${{ gitea.sha }}
|
||||
cache-from: type=registry,ref=${{ secrets.DOCKER_USER }}/libnovel-backend:latest
|
||||
cache-to: type=inline
|
||||
|
||||
# ── docker: runner ────────────────────────────────────────────────────────────
|
||||
docker-runner:
|
||||
name: Docker / runner
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test-backend]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USER }}
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
# ── runner ───────────────────────────────────────────────────────────────
|
||||
- name: Docker meta / runner
|
||||
id: meta-runner
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ secrets.DOCKER_USER }}/libnovel-runner
|
||||
@@ -128,115 +204,25 @@ jobs:
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,value=latest
|
||||
|
||||
- name: Build and push
|
||||
- name: Build and push / runner
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: backend
|
||||
target: runner
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
tags: ${{ steps.meta-runner.outputs.tags }}
|
||||
labels: ${{ steps.meta-runner.outputs.labels }}
|
||||
build-args: |
|
||||
VERSION=${{ steps.meta.outputs.version }}
|
||||
VERSION=${{ steps.meta-runner.outputs.version }}
|
||||
COMMIT=${{ gitea.sha }}
|
||||
cache-from: type=registry,ref=${{ secrets.DOCKER_USER }}/libnovel-runner:latest
|
||||
cache-to: type=inline
|
||||
|
||||
# ── ui: source map upload ─────────────────────────────────────────────────────
|
||||
upload-sourcemaps:
|
||||
name: Upload source maps
|
||||
runs-on: ubuntu-latest
|
||||
needs: [check-ui]
|
||||
steps:
|
||||
- name: Compute release version (strip leading v)
|
||||
id: ver
|
||||
run: |
|
||||
V="${{ gitea.ref_name }}"
|
||||
echo "version=${V#v}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Download build artifacts
|
||||
# ── ui ───────────────────────────────────────────────────────────────────
|
||||
- name: Download ui build artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: ui-build
|
||||
path: build
|
||||
|
||||
- name: Install sentry-cli
|
||||
run: npm install -g @sentry/cli
|
||||
|
||||
- name: Inject debug IDs into build artifacts
|
||||
run: sentry-cli sourcemaps inject ./build
|
||||
env:
|
||||
SENTRY_URL: https://errors.libnovel.cc/
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.GLITCHTIP_AUTH_TOKEN }}
|
||||
SENTRY_ORG: libnovel
|
||||
SENTRY_PROJECT: ui
|
||||
|
||||
- name: Upload injected build (for docker-ui)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ui-build-injected
|
||||
path: build
|
||||
retention-days: 1
|
||||
|
||||
- name: Create GlitchTip release
|
||||
run: sentry-cli releases new ${{ steps.ver.outputs.version }}
|
||||
env:
|
||||
SENTRY_URL: https://errors.libnovel.cc/
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.GLITCHTIP_AUTH_TOKEN }}
|
||||
SENTRY_ORG: libnovel
|
||||
SENTRY_PROJECT: ui
|
||||
|
||||
- name: Upload source maps to GlitchTip
|
||||
run: sentry-cli sourcemaps upload ./build --release ${{ steps.ver.outputs.version }}
|
||||
env:
|
||||
SENTRY_URL: https://errors.libnovel.cc/
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.GLITCHTIP_AUTH_TOKEN }}
|
||||
SENTRY_ORG: libnovel
|
||||
SENTRY_PROJECT: ui
|
||||
|
||||
- name: Finalize GlitchTip release
|
||||
run: sentry-cli releases finalize ${{ steps.ver.outputs.version }}
|
||||
env:
|
||||
SENTRY_URL: https://errors.libnovel.cc/
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.GLITCHTIP_AUTH_TOKEN }}
|
||||
SENTRY_ORG: libnovel
|
||||
SENTRY_PROJECT: ui
|
||||
|
||||
- name: Prune old GlitchTip releases (keep latest 10)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
KEEP=10
|
||||
OLD=$(curl -sf \
|
||||
-H "Authorization: Bearer $SENTRY_AUTH_TOKEN" \
|
||||
"$SENTRY_URL/api/0/organizations/$SENTRY_ORG/releases/?project=$SENTRY_PROJECT&per_page=100" \
|
||||
| python3 -c "
|
||||
import sys, json
|
||||
releases = json.load(sys.stdin)
|
||||
for r in releases[$KEEP:]:
|
||||
print(r['version'])
|
||||
" KEEP=$KEEP)
|
||||
for ver in $OLD; do
|
||||
echo "Deleting old release: $ver"
|
||||
sentry-cli releases delete "$ver" || true
|
||||
done
|
||||
env:
|
||||
SENTRY_URL: https://errors.libnovel.cc
|
||||
SENTRY_AUTH_TOKEN: ${{ secrets.GLITCHTIP_AUTH_TOKEN }}
|
||||
SENTRY_ORG: libnovel
|
||||
SENTRY_PROJECT: ui
|
||||
|
||||
# ── docker: ui ────────────────────────────────────────────────────────────────
|
||||
docker-ui:
|
||||
name: Docker / ui
|
||||
runs-on: ubuntu-latest
|
||||
needs: [check-ui, upload-sourcemaps]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Download injected build (debug IDs already embedded)
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: ui-build-injected
|
||||
path: ui/build
|
||||
|
||||
- name: Allow build/ into Docker context (override .dockerignore)
|
||||
@@ -244,16 +230,8 @@ jobs:
|
||||
grep -v '^build$' ui/.dockerignore > ui/.dockerignore.tmp
|
||||
mv ui/.dockerignore.tmp ui/.dockerignore
|
||||
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USER }}
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
- name: Docker meta / ui
|
||||
id: meta-ui
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ secrets.DOCKER_USER }}/libnovel-ui
|
||||
@@ -262,38 +240,24 @@ jobs:
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,value=latest
|
||||
|
||||
- name: Build and push
|
||||
- name: Build and push / ui
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: ui
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
tags: ${{ steps.meta-ui.outputs.tags }}
|
||||
labels: ${{ steps.meta-ui.outputs.labels }}
|
||||
build-args: |
|
||||
BUILD_VERSION=${{ steps.meta.outputs.version }}
|
||||
BUILD_VERSION=${{ steps.meta-ui.outputs.version }}
|
||||
BUILD_COMMIT=${{ gitea.sha }}
|
||||
BUILD_TIME=${{ gitea.event.head_commit.timestamp }}
|
||||
PREBUILT=1
|
||||
cache-from: type=registry,ref=${{ secrets.DOCKER_USER }}/libnovel-ui:latest
|
||||
cache-to: type=inline
|
||||
|
||||
# ── docker: caddy ─────────────────────────────────────────────────────────────
|
||||
docker-caddy:
|
||||
name: Docker / caddy
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USER }}
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
# ── caddy ────────────────────────────────────────────────────────────────
|
||||
- name: Docker meta / caddy
|
||||
id: meta-caddy
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ secrets.DOCKER_USER }}/libnovel-caddy
|
||||
@@ -302,13 +266,13 @@ jobs:
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=raw,value=latest
|
||||
|
||||
- name: Build and push
|
||||
- name: Build and push / caddy
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: caddy
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
tags: ${{ steps.meta-caddy.outputs.tags }}
|
||||
labels: ${{ steps.meta-caddy.outputs.labels }}
|
||||
cache-from: type=registry,ref=${{ secrets.DOCKER_USER }}/libnovel-caddy:latest
|
||||
cache-to: type=inline
|
||||
|
||||
@@ -316,7 +280,7 @@ jobs:
|
||||
release:
|
||||
name: Gitea Release
|
||||
runs-on: ubuntu-latest
|
||||
needs: [docker-backend, docker-runner, docker-ui, docker-caddy, upload-sourcemaps]
|
||||
needs: [docker]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
|
||||
@@ -161,6 +161,9 @@
|
||||
"profile_theme_amber": "Amber",
|
||||
"profile_theme_slate": "Slate",
|
||||
"profile_theme_rose": "Rose",
|
||||
"profile_theme_forest": "Forest",
|
||||
"profile_theme_mono": "Mono",
|
||||
"profile_theme_cyber": "Cyberpunk",
|
||||
"profile_theme_light": "Light",
|
||||
"profile_theme_light_slate": "Light Blue",
|
||||
"profile_theme_light_rose": "Light Rose",
|
||||
|
||||
@@ -161,6 +161,9 @@
|
||||
"profile_theme_amber": "Ambre",
|
||||
"profile_theme_slate": "Ardoise",
|
||||
"profile_theme_rose": "Rose",
|
||||
"profile_theme_forest": "Forêt",
|
||||
"profile_theme_mono": "Mono",
|
||||
"profile_theme_cyber": "Cyberpunk",
|
||||
"profile_theme_light": "Light",
|
||||
"profile_theme_light_slate": "Light Blue",
|
||||
"profile_theme_light_rose": "Light Rose",
|
||||
|
||||
@@ -161,6 +161,9 @@
|
||||
"profile_theme_amber": "Amber",
|
||||
"profile_theme_slate": "Abu-abu",
|
||||
"profile_theme_rose": "Mawar",
|
||||
"profile_theme_forest": "Hutan",
|
||||
"profile_theme_mono": "Mono",
|
||||
"profile_theme_cyber": "Cyberpunk",
|
||||
"profile_theme_light": "Light",
|
||||
"profile_theme_light_slate": "Light Blue",
|
||||
"profile_theme_light_rose": "Light Rose",
|
||||
|
||||
@@ -161,6 +161,9 @@
|
||||
"profile_theme_amber": "Âmbar",
|
||||
"profile_theme_slate": "Ardósia",
|
||||
"profile_theme_rose": "Rosa",
|
||||
"profile_theme_forest": "Floresta",
|
||||
"profile_theme_mono": "Mono",
|
||||
"profile_theme_cyber": "Cyberpunk",
|
||||
"profile_theme_light": "Light",
|
||||
"profile_theme_light_slate": "Light Blue",
|
||||
"profile_theme_light_rose": "Light Rose",
|
||||
|
||||
@@ -161,6 +161,9 @@
|
||||
"profile_theme_amber": "Янтарь",
|
||||
"profile_theme_slate": "Сланец",
|
||||
"profile_theme_rose": "Роза",
|
||||
"profile_theme_forest": "Лес",
|
||||
"profile_theme_mono": "Моно",
|
||||
"profile_theme_cyber": "Киберпанк",
|
||||
"profile_theme_light": "Light",
|
||||
"profile_theme_light_slate": "Light Blue",
|
||||
"profile_theme_light_rose": "Light Rose",
|
||||
|
||||
@@ -97,6 +97,48 @@
|
||||
--color-success: #16a34a; /* green-600 */
|
||||
}
|
||||
|
||||
/* ── Forest theme — dark green ────────────────────────────────────────── */
|
||||
[data-theme="forest"] {
|
||||
--color-brand: #4ade80; /* green-400 */
|
||||
--color-brand-dim: #16a34a; /* green-600 */
|
||||
--color-surface: #0a130d; /* custom near-black green */
|
||||
--color-surface-2: #111c14; /* custom dark green */
|
||||
--color-surface-3: #1a2e1e; /* custom mid green */
|
||||
--color-muted: #6b9a77; /* custom muted green */
|
||||
--color-text: #e8f5e9; /* custom light green-tinted white */
|
||||
--color-border: #1e3a24; /* custom green border */
|
||||
--color-danger: #f87171; /* red-400 */
|
||||
--color-success: #4ade80; /* green-400 */
|
||||
}
|
||||
|
||||
/* ── Mono theme — pure dark with white accent ─────────────────────────── */
|
||||
[data-theme="mono"] {
|
||||
--color-brand: #f4f4f5; /* zinc-100 — white accent */
|
||||
--color-brand-dim: #a1a1aa; /* zinc-400 */
|
||||
--color-surface: #09090b; /* zinc-950 */
|
||||
--color-surface-2: #18181b; /* zinc-900 */
|
||||
--color-surface-3: #27272a; /* zinc-800 */
|
||||
--color-muted: #71717a; /* zinc-500 */
|
||||
--color-text: #f4f4f5; /* zinc-100 */
|
||||
--color-border: #27272a; /* zinc-800 */
|
||||
--color-danger: #f87171; /* red-400 */
|
||||
--color-success: #4ade80; /* green-400 */
|
||||
}
|
||||
|
||||
/* ── Cyberpunk theme — dark with neon cyan/magenta accents ────────────── */
|
||||
[data-theme="cyber"] {
|
||||
--color-brand: #22d3ee; /* cyan-400 — neon cyan */
|
||||
--color-brand-dim: #06b6d4; /* cyan-500 */
|
||||
--color-surface: #050712; /* custom near-black blue */
|
||||
--color-surface-2: #0d1117; /* custom dark blue-black */
|
||||
--color-surface-3: #161b27; /* custom dark blue */
|
||||
--color-muted: #6272a4; /* dracula comment blue */
|
||||
--color-text: #e2e8f0; /* slate-200 */
|
||||
--color-border: #1e2d45; /* custom dark border */
|
||||
--color-danger: #ff5555; /* dracula red */
|
||||
--color-success: #50fa7b; /* dracula green */
|
||||
}
|
||||
|
||||
html {
|
||||
background-color: var(--color-surface);
|
||||
color: var(--color-text);
|
||||
|
||||
@@ -150,6 +150,9 @@ export * from './profile_theme_label.js'
|
||||
export * from './profile_theme_amber.js'
|
||||
export * from './profile_theme_slate.js'
|
||||
export * from './profile_theme_rose.js'
|
||||
export * from './profile_theme_forest.js'
|
||||
export * from './profile_theme_mono.js'
|
||||
export * from './profile_theme_cyber.js'
|
||||
export * from './profile_theme_light.js'
|
||||
export * from './profile_theme_light_slate.js'
|
||||
export * from './profile_theme_light_rose.js'
|
||||
|
||||
44
ui/src/lib/paraglide/messages/profile_theme_cyber.js
Normal file
44
ui/src/lib/paraglide/messages/profile_theme_cyber.js
Normal file
@@ -0,0 +1,44 @@
|
||||
/* eslint-disable */
|
||||
import { getLocale, experimentalStaticLocale } from '../runtime.js';
|
||||
|
||||
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
||||
|
||||
/** @typedef {{}} Profile_Theme_CyberInputs */
|
||||
|
||||
const en_profile_theme_cyber = /** @type {(inputs: Profile_Theme_CyberInputs) => LocalizedString} */ () => {
|
||||
return /** @type {LocalizedString} */ (`Cyberpunk`)
|
||||
};
|
||||
|
||||
const ru_profile_theme_cyber = /** @type {(inputs: Profile_Theme_CyberInputs) => LocalizedString} */ () => {
|
||||
return /** @type {LocalizedString} */ (`Киберпанк`)
|
||||
};
|
||||
|
||||
const id_profile_theme_cyber = /** @type {(inputs: Profile_Theme_CyberInputs) => LocalizedString} */ () => {
|
||||
return /** @type {LocalizedString} */ (`Cyberpunk`)
|
||||
};
|
||||
|
||||
const pt_profile_theme_cyber = /** @type {(inputs: Profile_Theme_CyberInputs) => LocalizedString} */ () => {
|
||||
return /** @type {LocalizedString} */ (`Cyberpunk`)
|
||||
};
|
||||
|
||||
const fr_profile_theme_cyber = /** @type {(inputs: Profile_Theme_CyberInputs) => LocalizedString} */ () => {
|
||||
return /** @type {LocalizedString} */ (`Cyberpunk`)
|
||||
};
|
||||
|
||||
/**
|
||||
* | output |
|
||||
* | --- |
|
||||
* | "Cyberpunk" |
|
||||
*
|
||||
* @param {Profile_Theme_CyberInputs} inputs
|
||||
* @param {{ locale?: "en" | "ru" | "id" | "pt" | "fr" }} options
|
||||
* @returns {LocalizedString}
|
||||
*/
|
||||
export const profile_theme_cyber = /** @type {((inputs?: Profile_Theme_CyberInputs, options?: { locale?: "en" | "ru" | "id" | "pt" | "fr" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Profile_Theme_CyberInputs, { locale?: "en" | "ru" | "id" | "pt" | "fr" }, {}>} */ ((inputs = {}, options = {}) => {
|
||||
const locale = experimentalStaticLocale ?? options.locale ?? getLocale()
|
||||
if (locale === "en") return en_profile_theme_cyber(inputs)
|
||||
if (locale === "ru") return ru_profile_theme_cyber(inputs)
|
||||
if (locale === "id") return id_profile_theme_cyber(inputs)
|
||||
if (locale === "pt") return pt_profile_theme_cyber(inputs)
|
||||
return fr_profile_theme_cyber(inputs)
|
||||
});
|
||||
44
ui/src/lib/paraglide/messages/profile_theme_forest.js
Normal file
44
ui/src/lib/paraglide/messages/profile_theme_forest.js
Normal file
@@ -0,0 +1,44 @@
|
||||
/* eslint-disable */
|
||||
import { getLocale, experimentalStaticLocale } from '../runtime.js';
|
||||
|
||||
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
||||
|
||||
/** @typedef {{}} Profile_Theme_ForestInputs */
|
||||
|
||||
const en_profile_theme_forest = /** @type {(inputs: Profile_Theme_ForestInputs) => LocalizedString} */ () => {
|
||||
return /** @type {LocalizedString} */ (`Forest`)
|
||||
};
|
||||
|
||||
const ru_profile_theme_forest = /** @type {(inputs: Profile_Theme_ForestInputs) => LocalizedString} */ () => {
|
||||
return /** @type {LocalizedString} */ (`Лес`)
|
||||
};
|
||||
|
||||
const id_profile_theme_forest = /** @type {(inputs: Profile_Theme_ForestInputs) => LocalizedString} */ () => {
|
||||
return /** @type {LocalizedString} */ (`Hutan`)
|
||||
};
|
||||
|
||||
const pt_profile_theme_forest = /** @type {(inputs: Profile_Theme_ForestInputs) => LocalizedString} */ () => {
|
||||
return /** @type {LocalizedString} */ (`Floresta`)
|
||||
};
|
||||
|
||||
const fr_profile_theme_forest = /** @type {(inputs: Profile_Theme_ForestInputs) => LocalizedString} */ () => {
|
||||
return /** @type {LocalizedString} */ (`Forêt`)
|
||||
};
|
||||
|
||||
/**
|
||||
* | output |
|
||||
* | --- |
|
||||
* | "Forest" |
|
||||
*
|
||||
* @param {Profile_Theme_ForestInputs} inputs
|
||||
* @param {{ locale?: "en" | "ru" | "id" | "pt" | "fr" }} options
|
||||
* @returns {LocalizedString}
|
||||
*/
|
||||
export const profile_theme_forest = /** @type {((inputs?: Profile_Theme_ForestInputs, options?: { locale?: "en" | "ru" | "id" | "pt" | "fr" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Profile_Theme_ForestInputs, { locale?: "en" | "ru" | "id" | "pt" | "fr" }, {}>} */ ((inputs = {}, options = {}) => {
|
||||
const locale = experimentalStaticLocale ?? options.locale ?? getLocale()
|
||||
if (locale === "en") return en_profile_theme_forest(inputs)
|
||||
if (locale === "ru") return ru_profile_theme_forest(inputs)
|
||||
if (locale === "id") return id_profile_theme_forest(inputs)
|
||||
if (locale === "pt") return pt_profile_theme_forest(inputs)
|
||||
return fr_profile_theme_forest(inputs)
|
||||
});
|
||||
44
ui/src/lib/paraglide/messages/profile_theme_mono.js
Normal file
44
ui/src/lib/paraglide/messages/profile_theme_mono.js
Normal file
@@ -0,0 +1,44 @@
|
||||
/* eslint-disable */
|
||||
import { getLocale, experimentalStaticLocale } from '../runtime.js';
|
||||
|
||||
/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */
|
||||
|
||||
/** @typedef {{}} Profile_Theme_MonoInputs */
|
||||
|
||||
const en_profile_theme_mono = /** @type {(inputs: Profile_Theme_MonoInputs) => LocalizedString} */ () => {
|
||||
return /** @type {LocalizedString} */ (`Mono`)
|
||||
};
|
||||
|
||||
const ru_profile_theme_mono = /** @type {(inputs: Profile_Theme_MonoInputs) => LocalizedString} */ () => {
|
||||
return /** @type {LocalizedString} */ (`Моно`)
|
||||
};
|
||||
|
||||
const id_profile_theme_mono = /** @type {(inputs: Profile_Theme_MonoInputs) => LocalizedString} */ () => {
|
||||
return /** @type {LocalizedString} */ (`Mono`)
|
||||
};
|
||||
|
||||
const pt_profile_theme_mono = /** @type {(inputs: Profile_Theme_MonoInputs) => LocalizedString} */ () => {
|
||||
return /** @type {LocalizedString} */ (`Mono`)
|
||||
};
|
||||
|
||||
const fr_profile_theme_mono = /** @type {(inputs: Profile_Theme_MonoInputs) => LocalizedString} */ () => {
|
||||
return /** @type {LocalizedString} */ (`Mono`)
|
||||
};
|
||||
|
||||
/**
|
||||
* | output |
|
||||
* | --- |
|
||||
* | "Mono" |
|
||||
*
|
||||
* @param {Profile_Theme_MonoInputs} inputs
|
||||
* @param {{ locale?: "en" | "ru" | "id" | "pt" | "fr" }} options
|
||||
* @returns {LocalizedString}
|
||||
*/
|
||||
export const profile_theme_mono = /** @type {((inputs?: Profile_Theme_MonoInputs, options?: { locale?: "en" | "ru" | "id" | "pt" | "fr" }) => LocalizedString) & import('../runtime.js').MessageMetadata<Profile_Theme_MonoInputs, { locale?: "en" | "ru" | "id" | "pt" | "fr" }, {}>} */ ((inputs = {}, options = {}) => {
|
||||
const locale = experimentalStaticLocale ?? options.locale ?? getLocale()
|
||||
if (locale === "en") return en_profile_theme_mono(inputs)
|
||||
if (locale === "ru") return ru_profile_theme_mono(inputs)
|
||||
if (locale === "id") return id_profile_theme_mono(inputs)
|
||||
if (locale === "pt") return pt_profile_theme_mono(inputs)
|
||||
return fr_profile_theme_mono(inputs)
|
||||
});
|
||||
@@ -38,6 +38,9 @@
|
||||
{ id: 'amber', color: '#f59e0b' },
|
||||
{ id: 'slate', color: '#818cf8' },
|
||||
{ id: 'rose', color: '#fb7185' },
|
||||
{ id: 'forest', color: '#4ade80' },
|
||||
{ id: 'mono', color: '#f4f4f5' },
|
||||
{ id: 'cyber', color: '#22d3ee' },
|
||||
{ id: 'light', color: '#d97706', light: true },
|
||||
{ id: 'light-slate', color: '#4f46e5', light: true },
|
||||
{ id: 'light-rose', color: '#e11d48', light: true },
|
||||
|
||||
@@ -45,7 +45,7 @@ export const PUT: RequestHandler = async ({ request, locals }) => {
|
||||
}
|
||||
|
||||
// theme is optional — if provided (and non-empty) it must be a known value
|
||||
const validThemes = ['amber', 'slate', 'rose', 'light', 'light-slate', 'light-rose'];
|
||||
const validThemes = ['amber', 'slate', 'rose', 'forest', 'mono', 'cyber', 'light', 'light-slate', 'light-rose'];
|
||||
if (body.theme !== undefined && body.theme !== '' && !validThemes.includes(body.theme)) {
|
||||
error(400, `Invalid theme — must be one of: ${validThemes.join(', ')}`);
|
||||
}
|
||||
|
||||
@@ -458,6 +458,7 @@
|
||||
<button
|
||||
type="button"
|
||||
onclick={() => (showHistory = false)}
|
||||
aria-label="Close history"
|
||||
class="w-8 h-8 flex items-center justify-center rounded-lg text-(--color-muted) hover:text-(--color-text) hover:bg-(--color-surface-3) transition-colors"
|
||||
>
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
|
||||
@@ -145,6 +145,9 @@
|
||||
{ id: 'amber', label: () => m.profile_theme_amber(), swatch: '#f59e0b' },
|
||||
{ id: 'slate', label: () => m.profile_theme_slate(), swatch: '#818cf8' },
|
||||
{ id: 'rose', label: () => m.profile_theme_rose(), swatch: '#fb7185' },
|
||||
{ id: 'forest', label: () => m.profile_theme_forest(), swatch: '#4ade80' },
|
||||
{ id: 'mono', label: () => m.profile_theme_mono(), swatch: '#f4f4f5' },
|
||||
{ id: 'cyber', label: () => m.profile_theme_cyber(), swatch: '#22d3ee' },
|
||||
{ id: 'light', label: () => m.profile_theme_light(), swatch: '#d97706', light: true },
|
||||
{ id: 'light-slate', label: () => m.profile_theme_light_slate(), swatch: '#4f46e5', light: true },
|
||||
{ id: 'light-rose', label: () => m.profile_theme_light_rose(), swatch: '#e11d48', light: true },
|
||||
|
||||
Reference in New Issue
Block a user