feat: Rename to Toju and add translation
Some checks failed
Deploy Web Apps / deploy (push) Successful in 5m52s
Build Android APK / build-android-apk (push) Failing after 23m15s
Queue Release Build / prepare (push) Successful in 1m42s
Queue Release Build / build-linux (push) Failing after 9m33s
Queue Release Build / build-windows (push) Successful in 26m5s
Queue Release Build / finalize (push) Has been skipped
Some checks failed
Deploy Web Apps / deploy (push) Successful in 5m52s
Build Android APK / build-android-apk (push) Failing after 23m15s
Queue Release Build / prepare (push) Successful in 1m42s
Queue Release Build / build-linux (push) Failing after 9m33s
Queue Release Build / build-windows (push) Successful in 26m5s
Queue Release Build / finalize (push) Has been skipped
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
[class.border-destructive/40]="isServerMarkedBanned(server)"
|
||||
[class.bg-destructive/5]="isServerMarkedBanned(server)"
|
||||
[class.hover:border-destructive/60]="isServerMarkedBanned(server)"
|
||||
[title]="isJoinedServer(server) ? 'Double-click to open ' + server.name : 'Double-click to join ' + server.name"
|
||||
[title]="serverCardTitle(server)"
|
||||
(dblclick)="openServerCard(server)"
|
||||
>
|
||||
<div class="flex min-w-0 items-start gap-3">
|
||||
@@ -43,7 +43,7 @@
|
||||
name="lucideLock"
|
||||
class="h-3 w-3"
|
||||
/>
|
||||
Banned
|
||||
{{ 'servers.browser.card.banned' | translate }}
|
||||
</span>
|
||||
} @else if (server.isPrivate) {
|
||||
<span class="inline-flex items-center gap-1 rounded-full bg-secondary px-2 py-0.5 text-[11px] font-medium text-muted-foreground">
|
||||
@@ -51,7 +51,7 @@
|
||||
name="lucideLock"
|
||||
class="h-3 w-3"
|
||||
/>
|
||||
Private
|
||||
{{ 'servers.browser.card.private' | translate }}
|
||||
</span>
|
||||
} @else if (server.hasPassword) {
|
||||
<span class="inline-flex items-center gap-1 rounded-full bg-secondary px-2 py-0.5 text-[11px] font-medium text-muted-foreground">
|
||||
@@ -59,7 +59,7 @@
|
||||
name="lucideLock"
|
||||
class="h-3 w-3"
|
||||
/>
|
||||
Password
|
||||
{{ 'servers.browser.card.password' | translate }}
|
||||
</span>
|
||||
} @else {
|
||||
<ng-icon
|
||||
@@ -84,8 +84,8 @@
|
||||
@if (server.topic) {
|
||||
<span class="truncate">{{ server.topic }}</span>
|
||||
}
|
||||
<span class="truncate">Owner: {{ getServerOwnerLabel(server) }}</span>
|
||||
<span class="truncate">{{ server.sourceName || server.hostName || 'Unknown' }}</span>
|
||||
<span class="truncate">{{ ownerLabel(server) }}</span>
|
||||
<span class="truncate">{{ server.sourceName || server.hostName || ('common.labels.unknown' | translate) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -94,11 +94,11 @@
|
||||
<div
|
||||
class="flex items-center overflow-hidden rounded-md border border-emerald-500/30 bg-emerald-500/10 text-xs font-semibold text-emerald-500"
|
||||
>
|
||||
<span class="px-2.5 py-1.5">Joined</span>
|
||||
<span class="px-2.5 py-1.5">{{ 'servers.browser.card.joined' | translate }}</span>
|
||||
<button
|
||||
type="button"
|
||||
class="grid h-8 w-8 place-items-center border-l border-emerald-500/20 transition-colors hover:bg-emerald-500/15"
|
||||
[attr.aria-label]="'Server actions for ' + server.name"
|
||||
[attr.aria-label]="serverActionsLabel(server)"
|
||||
(click)="toggleJoinedServerMenu($event, server)"
|
||||
>
|
||||
<ng-icon
|
||||
@@ -115,7 +115,7 @@
|
||||
class="w-full px-3 py-2 text-left text-xs font-medium text-destructive transition-colors hover:bg-destructive/10"
|
||||
(click)="openLeaveDialog($event, server)"
|
||||
>
|
||||
Leave
|
||||
{{ 'servers.browser.card.leave' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
@@ -123,11 +123,11 @@
|
||||
<button
|
||||
type="button"
|
||||
class="rounded-md bg-primary px-2.5 py-1.5 text-xs font-semibold text-primary-foreground transition-colors hover:bg-primary/90"
|
||||
[attr.aria-label]="'Join ' + server.name"
|
||||
[attr.aria-label]="joinServerLabel(server)"
|
||||
(click)="joinServer(server)"
|
||||
>
|
||||
<span class="sr-only">{{ server.name }}</span>
|
||||
Join
|
||||
{{ 'servers.browser.card.join' | translate }}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
@@ -144,9 +144,9 @@
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
aria-label="Search servers"
|
||||
[attr.aria-label]="'servers.browser.search.ariaLabel' | translate"
|
||||
class="h-10 w-full rounded-lg border border-border bg-secondary py-2 pl-10 pr-3 text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary"
|
||||
[placeholder]="searchPlaceholder"
|
||||
[placeholder]="resolvedSearchPlaceholder"
|
||||
[(ngModel)]="searchQuery"
|
||||
(ngModelChange)="onSearchChange($event)"
|
||||
/>
|
||||
@@ -154,7 +154,7 @@
|
||||
|
||||
@if (showMyServers && savedRooms().length > 0) {
|
||||
<div class="mt-2 flex items-center gap-2 overflow-x-auto pb-1">
|
||||
<span class="shrink-0 text-xs font-medium text-muted-foreground">My Servers</span>
|
||||
<span class="shrink-0 text-xs font-medium text-muted-foreground">{{ 'servers.browser.search.myServers' | translate }}</span>
|
||||
@for (room of savedRooms(); track room.id) {
|
||||
<button
|
||||
type="button"
|
||||
@@ -172,8 +172,8 @@
|
||||
@if (isSearchMode) {
|
||||
<div class="sticky top-0 z-10 flex items-center justify-between border-b border-border bg-background/95 px-3 py-2 backdrop-blur">
|
||||
<div>
|
||||
<h3 class="text-sm font-semibold text-foreground">Search results</h3>
|
||||
<p class="text-xs text-muted-foreground">{{ searchResults().length }} found</p>
|
||||
<h3 class="text-sm font-semibold text-foreground">{{ 'servers.browser.search.resultsTitle' | translate }}</h3>
|
||||
<p class="text-xs text-muted-foreground">{{ 'servers.browser.search.resultsCount' | translate: { count: searchResults().length } }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -187,7 +187,7 @@
|
||||
name="lucideSearch"
|
||||
class="mb-3 h-10 w-10 opacity-50"
|
||||
/>
|
||||
<p class="text-sm font-medium">No servers found</p>
|
||||
<p class="text-sm font-medium">{{ 'servers.browser.search.noResults' | translate }}</p>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="space-y-2 p-3">
|
||||
@@ -202,8 +202,8 @@
|
||||
name="lucideSearch"
|
||||
class="mb-4 h-12 w-12 opacity-40"
|
||||
/>
|
||||
<p class="text-base font-semibold text-foreground">{{ emptyStateTitle }}</p>
|
||||
<p class="mt-1 max-w-sm text-sm">{{ emptyStateMessage }}</p>
|
||||
<p class="text-base font-semibold text-foreground">{{ resolvedEmptyStateTitle }}</p>
|
||||
<p class="mt-1 max-w-sm text-sm">{{ resolvedEmptyStateMessage }}</p>
|
||||
</div>
|
||||
} @else {
|
||||
<div class="space-y-6 p-3">
|
||||
@@ -244,42 +244,42 @@
|
||||
|
||||
@if (showBannedDialog()) {
|
||||
<app-confirm-dialog
|
||||
title="Banned"
|
||||
confirmLabel="OK"
|
||||
cancelLabel="Close"
|
||||
[title]="'servers.browser.bannedDialog.title' | translate"
|
||||
[confirmLabel]="'common.actions.ok' | translate"
|
||||
[cancelLabel]="'common.actions.close' | translate"
|
||||
variant="danger"
|
||||
[widthClass]="'w-96 max-w-[90vw]'"
|
||||
(confirmed)="closeBannedDialog()"
|
||||
(cancelled)="closeBannedDialog()"
|
||||
>
|
||||
<p>You are banned from {{ bannedServerName() || 'this server' }}.</p>
|
||||
<p>{{ bannedDialogMessage() }}</p>
|
||||
</app-confirm-dialog>
|
||||
}
|
||||
|
||||
@if (showPasswordDialog() && passwordPromptServer()) {
|
||||
<app-confirm-dialog
|
||||
title="Password required"
|
||||
confirmLabel="Join server"
|
||||
cancelLabel="Cancel"
|
||||
[title]="'servers.browser.passwordDialog.title' | translate"
|
||||
[confirmLabel]="'servers.browser.passwordDialog.confirm' | translate"
|
||||
[cancelLabel]="'common.actions.cancel' | translate"
|
||||
[widthClass]="'w-[420px] max-w-[92vw]'"
|
||||
(confirmed)="confirmPasswordJoin()"
|
||||
(cancelled)="closePasswordDialog()"
|
||||
>
|
||||
<div class="space-y-3">
|
||||
<p>Enter the password to join {{ passwordPromptServer()!.name }}.</p>
|
||||
<p>{{ passwordDialogMessage(passwordPromptServer()!) }}</p>
|
||||
|
||||
<div>
|
||||
<label
|
||||
for="join-server-password"
|
||||
class="mb-1 block text-xs font-medium uppercase tracking-wide text-muted-foreground"
|
||||
>
|
||||
Server password
|
||||
{{ 'servers.browser.passwordDialog.label' | translate }}
|
||||
</label>
|
||||
<input
|
||||
id="join-server-password"
|
||||
type="password"
|
||||
[(ngModel)]="joinPassword"
|
||||
placeholder="Enter password"
|
||||
[placeholder]="'servers.browser.passwordDialog.placeholder' | translate"
|
||||
class="w-full rounded-lg border border-border bg-secondary px-3 py-2 text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-primary"
|
||||
/>
|
||||
</div>
|
||||
@@ -303,19 +303,19 @@
|
||||
aria-labelledby="join-plugin-consent-title"
|
||||
>
|
||||
<header class="border-b border-border p-4">
|
||||
<p class="text-sm text-muted-foreground">Plugin downloads</p>
|
||||
<p class="text-sm text-muted-foreground">{{ 'servers.plugins.eyebrow' | translate }}</p>
|
||||
<h2
|
||||
id="join-plugin-consent-title"
|
||||
class="mt-1 text-lg font-semibold"
|
||||
>
|
||||
{{ dialog.server.name }} uses plugins
|
||||
{{ pluginUsesPluginsLabel(dialog.server.name) }}
|
||||
</h2>
|
||||
</header>
|
||||
|
||||
<div class="grid min-h-0 gap-4 overflow-auto p-4">
|
||||
@if (dialog.required.length > 0) {
|
||||
<section class="grid gap-2">
|
||||
<h3 class="text-sm font-semibold">Required before joining</h3>
|
||||
<h3 class="text-sm font-semibold">{{ 'servers.plugins.requiredTitle' | translate }}</h3>
|
||||
@for (requirement of dialog.required; track requirement.pluginId) {
|
||||
<div class="grid gap-3 rounded-lg border border-border bg-background/50 px-3 py-2">
|
||||
<div class="flex items-start justify-between gap-3">
|
||||
@@ -325,12 +325,14 @@
|
||||
<p class="mt-1 text-xs text-muted-foreground">{{ requirement.reason }}</p>
|
||||
}
|
||||
</div>
|
||||
<span class="shrink-0 rounded-full bg-primary/10 px-2 py-0.5 text-xs font-semibold text-primary">Required</span>
|
||||
<span class="shrink-0 rounded-full bg-primary/10 px-2 py-0.5 text-xs font-semibold text-primary">{{
|
||||
'servers.plugins.requiredBadge' | translate
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
@if (requirement.manifest?.capabilities; as capabilities) {
|
||||
<details class="rounded-md border border-border bg-secondary/40 px-2 py-1.5 text-xs text-muted-foreground">
|
||||
<summary class="cursor-pointer font-semibold text-foreground">Capabilities</summary>
|
||||
<summary class="cursor-pointer font-semibold text-foreground">{{ 'servers.plugins.capabilities' | translate }}</summary>
|
||||
<div class="mt-2 flex flex-wrap gap-1.5">
|
||||
@for (capability of capabilities; track capability) {
|
||||
<span class="rounded-full bg-background px-2 py-0.5 font-mono text-[11px] text-muted-foreground">{{ capability }}</span>
|
||||
@@ -350,7 +352,7 @@
|
||||
name="lucideExternalLink"
|
||||
class="h-3.5 w-3.5"
|
||||
/>
|
||||
Source
|
||||
{{ 'servers.plugins.source' | translate }}
|
||||
</button>
|
||||
}
|
||||
|
||||
@@ -365,7 +367,7 @@
|
||||
name="lucideFileText"
|
||||
class="h-3.5 w-3.5"
|
||||
/>
|
||||
{{ pluginConsentReadmeLoadingId() === requirement.pluginId ? 'Loading' : 'Readme' }}
|
||||
{{ pluginReadmeButtonLabel(requirement.pluginId) }}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
@@ -376,7 +378,7 @@
|
||||
|
||||
@if (dialog.optional.length > 0) {
|
||||
<section class="grid gap-2">
|
||||
<h3 class="text-sm font-semibold">Optional plugins</h3>
|
||||
<h3 class="text-sm font-semibold">{{ 'servers.plugins.optionalTitle' | translate }}</h3>
|
||||
@for (requirement of dialog.optional; track requirement.pluginId) {
|
||||
<div class="grid gap-3 rounded-lg border border-border bg-background/50 px-3 py-2">
|
||||
<label class="flex items-start gap-3">
|
||||
@@ -397,7 +399,7 @@
|
||||
|
||||
@if (requirement.manifest?.capabilities; as capabilities) {
|
||||
<details class="rounded-md border border-border bg-secondary/40 px-2 py-1.5 text-xs text-muted-foreground">
|
||||
<summary class="cursor-pointer font-semibold text-foreground">Capabilities</summary>
|
||||
<summary class="cursor-pointer font-semibold text-foreground">{{ 'servers.plugins.capabilities' | translate }}</summary>
|
||||
<div class="mt-2 flex flex-wrap gap-1.5">
|
||||
@for (capability of capabilities; track capability) {
|
||||
<span class="rounded-full bg-background px-2 py-0.5 font-mono text-[11px] text-muted-foreground">{{ capability }}</span>
|
||||
@@ -417,7 +419,7 @@
|
||||
name="lucideExternalLink"
|
||||
class="h-3.5 w-3.5"
|
||||
/>
|
||||
Source
|
||||
{{ 'servers.plugins.source' | translate }}
|
||||
</button>
|
||||
}
|
||||
|
||||
@@ -432,7 +434,7 @@
|
||||
name="lucideFileText"
|
||||
class="h-3.5 w-3.5"
|
||||
/>
|
||||
{{ pluginConsentReadmeLoadingId() === requirement.pluginId ? 'Loading' : 'Readme' }}
|
||||
{{ pluginReadmeButtonLabel(requirement.pluginId) }}
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
@@ -457,7 +459,7 @@
|
||||
[disabled]="pluginConsentBusy()"
|
||||
class="inline-flex min-h-8 items-center justify-center rounded-lg border border-border bg-card px-3 py-1.5 text-sm font-semibold transition-colors hover:bg-secondary disabled:cursor-not-allowed disabled:opacity-55"
|
||||
>
|
||||
Cancel join
|
||||
{{ 'servers.plugins.cancelJoin' | translate }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
@@ -465,7 +467,7 @@
|
||||
[disabled]="pluginConsentBusy()"
|
||||
class="inline-flex min-h-8 items-center justify-center rounded-lg border border-primary bg-primary px-3 py-1.5 text-sm font-semibold text-primary-foreground transition-colors hover:bg-primary/90 disabled:cursor-not-allowed disabled:opacity-55"
|
||||
>
|
||||
{{ pluginConsentBusy() ? 'Downloading' : dialog.required.length > 0 ? 'Accept and join' : 'Join' }}
|
||||
{{ pluginConsentConfirmLabel(dialog.required.length) }}
|
||||
</button>
|
||||
</footer>
|
||||
</section>
|
||||
@@ -473,7 +475,7 @@
|
||||
@if (pluginConsentReadme(); as readme) {
|
||||
<app-modal-backdrop
|
||||
[zIndex]="52"
|
||||
ariaLabel="Close readme"
|
||||
[ariaLabel]="'servers.plugins.closeReadme' | translate"
|
||||
(dismissed)="closePluginConsentReadme()"
|
||||
/>
|
||||
<section
|
||||
@@ -484,7 +486,7 @@
|
||||
>
|
||||
<header class="flex items-start justify-between gap-3 border-b border-border p-4">
|
||||
<div class="min-w-0">
|
||||
<p class="text-sm text-muted-foreground">Plugin readme</p>
|
||||
<p class="text-sm text-muted-foreground">{{ 'servers.plugins.readmeEyebrow' | translate }}</p>
|
||||
<h2
|
||||
id="join-plugin-readme-title"
|
||||
class="mt-1 truncate text-lg font-semibold"
|
||||
@@ -496,7 +498,7 @@
|
||||
type="button"
|
||||
(click)="closePluginConsentReadme()"
|
||||
class="grid h-8 w-8 shrink-0 place-items-center rounded-lg border border-border text-muted-foreground transition-colors hover:bg-secondary hover:text-foreground"
|
||||
title="Close readme"
|
||||
[title]="'common.actions.close' | translate"
|
||||
>
|
||||
X
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user