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

This commit is contained in:
2026-06-05 17:13:03 +02:00
parent 8ecfc9a1fe
commit ee293d7daf
301 changed files with 8247 additions and 2218 deletions

View File

@@ -9,7 +9,7 @@
(click)="navigateToServer()"
type="button"
class="flex items-center gap-1.5 rounded-md bg-secondary px-2 py-1 text-foreground transition-colors hover:bg-secondary/80"
title="Back to {{ voiceSession()?.serverName }}"
[title]="backToServerTitle()"
>
<ng-icon
name="lucideArrowLeft"
@@ -31,7 +31,9 @@
<!-- Voice status indicator -->
<div class="flex items-center gap-1 px-1">
<span class="w-1.5 h-1.5 rounded-full bg-green-500 animate-pulse"></span>
<span class="text-xs text-muted-foreground max-w-20 truncate">{{ voiceSession()?.roomName || 'Voice' }}</span>
<span class="text-xs text-muted-foreground max-w-20 truncate">{{
voiceSession()?.roomName || ('voice.floating.voiceFallback' | translate)
}}</span>
</div>
<!-- Divider -->
@@ -43,7 +45,7 @@
(click)="toggleMute()"
type="button"
[class]="getCompactButtonClass(isMuted())"
title="Toggle Mute"
[title]="'voice.floating.toggleMute' | translate"
>
<ng-icon
[name]="isMuted() ? 'lucideMicOff' : 'lucideMic'"
@@ -55,7 +57,7 @@
(click)="toggleDeafen()"
type="button"
[class]="getCompactButtonClass(isDeafened())"
title="Toggle Deafen"
[title]="'voice.floating.toggleDeafen' | translate"
>
<ng-icon
name="lucideHeadphones"
@@ -68,7 +70,7 @@
(click)="toggleScreenShare()"
type="button"
[class]="getCompactScreenShareClass()"
title="Toggle Screen Share"
[title]="'voice.floating.toggleScreenShare' | translate"
>
<ng-icon
[name]="isScreenSharing() ? 'lucideMonitorOff' : 'lucideMonitor'"
@@ -86,7 +88,7 @@
(click)="disconnect()"
type="button"
class="inline-flex h-7 w-7 items-center justify-center rounded-md border border-destructive/20 bg-destructive/10 text-destructive transition-colors hover:bg-destructive/15"
title="Disconnect"
[title]="'voice.floating.disconnect' | translate"
>
<ng-icon
name="lucidePhoneOff"

View File

@@ -29,6 +29,7 @@ import { UsersActions } from '../../../../store/users/users.actions';
import { selectCurrentUser } from '../../../../store/users/users.selectors';
import { DebugConsoleComponent, ScreenShareQualityDialogComponent } from '../../../../shared';
import { ThemeNodeDirective } from '../../../../domains/theme';
import { APP_TRANSLATE_IMPORTS, AppI18nService } from '../../../../core/i18n';
@Component({
selector: 'app-floating-voice-controls',
@@ -38,7 +39,8 @@ import { ThemeNodeDirective } from '../../../../domains/theme';
NgIcon,
DebugConsoleComponent,
ScreenShareQualityDialogComponent,
ThemeNodeDirective
ThemeNodeDirective,
...APP_TRANSLATE_IMPORTS
],
viewProviders: [
provideIcons({
@@ -65,6 +67,7 @@ export class FloatingVoiceControlsComponent implements OnInit {
private readonly voiceSessionService = inject(VoiceSessionFacade);
private readonly voicePlayback = inject(VoicePlaybackService);
private readonly store = inject(Store);
private readonly appI18n = inject(AppI18nService);
currentUser = this.store.selectSignal(selectCurrentUser);
@@ -98,6 +101,12 @@ export class FloatingVoiceControlsComponent implements OnInit {
}
}
backToServerTitle(): string {
return this.appI18n.instant('voice.floating.backToServer', {
server: this.voiceSession()?.serverName ?? ''
});
}
/** Navigate back to the voice-connected server. */
navigateToServer(): void {
this.voiceSessionService.navigateToVoiceServer();

View File

@@ -6,13 +6,13 @@
@if (showConnectionError()) {
<div class="mb-3 flex items-center gap-2 rounded-md border border-destructive/30 bg-destructive/10 p-2">
<span class="w-2 h-2 rounded-full bg-destructive animate-pulse"></span>
<span class="text-xs text-destructive">{{ connectionErrorMessage() || 'Connection error' }}</span>
<span class="text-xs text-destructive">{{ connectionErrorMessage() }}</span>
<button
type="button"
(click)="retryConnection()"
class="ml-auto text-xs text-destructive hover:underline"
>
Retry
{{ 'voice.controls.retry' | translate }}
</button>
</div>
}
@@ -36,14 +36,14 @@
/>
<div class="flex-1 min-w-0">
<p class="font-medium text-sm text-foreground truncate text-left">
{{ currentUser()?.displayName || 'Unknown' }}
{{ currentUser()?.displayName || ('common.unknown' | translate) }}
</p>
@if (showConnectionError() || isConnected()) {
<p class="text-xs text-muted-foreground text-left">
@if (showConnectionError()) {
<span class="text-destructive">Connection Error</span>
<span class="text-destructive">{{ 'voice.controls.connectionErrorStatus' | translate }}</span>
} @else if (isConnected()) {
<span class="text-green-500">Connected</span>
<span class="text-green-500">{{ 'voice.controls.connected' | translate }}</span>
}
</p>
}

View File

@@ -40,6 +40,7 @@ import {
UserAvatarComponent,
ProfileCardService
} from '../../../../shared';
import { APP_TRANSLATE_IMPORTS, AppI18nService } from '../../../../core/i18n';
interface AudioDevice {
deviceId: string;
@@ -55,7 +56,8 @@ interface AudioDevice {
DebugConsoleComponent,
ScreenShareQualityDialogComponent,
UserAvatarComponent,
ThemeNodeDirective
ThemeNodeDirective,
...APP_TRANSLATE_IMPORTS
],
viewProviders: [
provideIcons({
@@ -83,13 +85,22 @@ export class VoiceControlsComponent implements OnInit, OnDestroy {
private readonly hostEl = inject(ElementRef);
private readonly profileCard = inject(ProfileCardService);
private readonly mobileMedia = inject(MobileMediaService);
private readonly appI18n = inject(AppI18nService);
currentUser = this.store.selectSignal(selectCurrentUser);
currentRoom = this.store.selectSignal(selectCurrentRoom);
isConnected = computed(() => this.webrtcService.isVoiceConnected());
showConnectionError = computed(() => this.webrtcService.shouldShowConnectionError());
connectionErrorMessage = computed(() => this.webrtcService.connectionErrorMessage());
connectionErrorMessage = computed(() => {
const message = this.webrtcService.connectionErrorMessage();
if (!message) {
return this.appI18n.instant('voice.controls.connectionError');
}
return this.appI18n.instant(message);
});
isMuted = signal(false);
isDeafened = signal(false);
isCameraEnabled = computed(() => this.webrtcService.isCameraEnabled());
@@ -242,7 +253,7 @@ export class VoiceControlsComponent implements OnInit, OnDestroy {
this.webrtcService.clearConnectionError();
this.saveSettings();
} catch (error) {
const message = error instanceof Error ? error.message : 'Failed to connect voice session.';
const message = error instanceof Error ? error.message : 'voice.controls.failedConnect';
this.webrtcService.reportConnectionError(message);
}