address warnings

This commit is contained in:
2026-04-21 11:15:45 -04:00
parent b413b8bd0d
commit bbe27fc6d0
20 changed files with 66 additions and 211 deletions
+3 -2
View File
@@ -16,7 +16,8 @@
} = $props();
// 1. Initialize the provider instance for this specific builder
const db = createSpacetimeDBProvider(builder);
// We untrack the builder here because SpacetimeProvider handles remounting on builder changes.
const db = createSpacetimeDBProvider(untrack(() => builder));
// 1.1 Connection Timeout
// If we stay in "connecting" state for too long without an identity or error,
@@ -49,7 +50,7 @@
// 2. Handshake Synchronization
// Ensures session persistence happens when a valid identity and token are available
let lastPersistedToken = $state<string | undefined>(undefined);
let lastUsedOidcTokenForUpgrade = $state<string | undefined>(oidcToken);
let lastUsedOidcTokenForUpgrade = $state<string | undefined>(untrack(() => oidcToken));
$effect(() => {
const conn = $db.connection;
-97
View File
@@ -341,103 +341,6 @@
opacity: 1;
}
.ios-switch {
position: relative;
display: inline-block;
width: 34px;
height: 20px;
}
.ios-switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: var(--background-accent);
transition: .4s;
border-radius: 20px;
}
.slider:before {
position: absolute;
content: "";
height: 16px;
width: 16px;
left: 2px;
bottom: 2px;
background-color: var(--header-primary);
transition: .4s;
border-radius: 50%;
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}
input:checked + .slider {
background-color: var(--status-positive);
}
input:checked + .slider:before {
transform: translateX(14px);
}
.hero-header {
margin-bottom: 32px;
display: flex;
flex-direction: column;
align-items: center;
}
.logo-container {
width: 100px;
height: 100px;
margin-bottom: 16px;
filter: drop-shadow(0 0 10px var(--brand));
}
.logo-svg {
width: 100%;
height: 100%;
color: var(--brand);
}
.zep-blimp {
animation: float 4s infinite ease-in-out;
transform-origin: center;
}
.blimp-top, .blimp-bottom {
fill: none;
stroke: currentColor;
stroke-width: 6;
stroke-linecap: round;
opacity: 0.8;
}
.blimp-filling {
fill: none;
stroke: url(#logoGrad);
stroke-width: 8;
stroke-linecap: round;
filter: drop-shadow(0 0 8px var(--brand));
animation: energy-pulse 2s infinite ease-in-out;
}
.tagline {
font-size: 0.9rem;
color: var(--text-muted);
margin-top: 4px;
letter-spacing: 1px;
text-transform: uppercase;
font-weight: 700;
}
@keyframes float {
0%, 100% { transform: translateY(0) rotate(-2deg); }
50% { transform: translateY(-10px) rotate(2deg); }
+4
View File
@@ -201,6 +201,8 @@
<button
class="icon-btn notification-toggle {chat.isChannelNotificationsEnabled(chat.activeChannelId) ? 'subscribed' : ''}"
onclick={() => chat.toggleChannelNotifications(chat.activeChannelId!)}
title={chat.isChannelNotificationsEnabled(chat.activeChannelId) ? "Mute Channel" : "Unmute Channel"}
aria-label="Toggle notifications"
>
<i class="fas {chat.isChannelNotificationsEnabled(chat.activeChannelId) ? 'fa-bell' : 'fa-bell-slash'}"></i>
</button>
@@ -217,6 +219,8 @@
<button
class="icon-btn notification-toggle {chat.isChannelNotificationsEnabled(chat.activeChannelId!) ? 'subscribed' : ''}"
onclick={() => chat.toggleChannelNotifications(chat.activeChannelId!)}
title={chat.isChannelNotificationsEnabled(chat.activeChannelId!) ? "Mute DM" : "Unmute DM"}
aria-label="Toggle notifications"
>
<i class="fas {chat.isChannelNotificationsEnabled(chat.activeChannelId!) ? 'fa-bell' : 'fa-bell-slash'}"></i>
</button>
+17 -3
View File
@@ -83,7 +83,9 @@
style="color: {disabled ? 'var(--text-muted)' : 'var(--text-normal)'}; cursor: {disabled ? 'not-allowed' : 'text'};"
/>
{#if options.length > 0}
<i class="fas fa-chevron-down chevron"
<button
type="button"
class="chevron-btn"
style="opacity: {disabled ? 0.3 : 1}; cursor: {disabled ? 'not-allowed' : 'pointer'};"
onclick={(e) => {
if (disabled) return;
@@ -96,7 +98,10 @@
handleFocus();
}
}}
></i>
aria-label="Toggle dropdown"
>
<i class="fas fa-chevron-down chevron"></i>
</button>
{/if}
{#if isOpen && filteredOptions.length > 0}
@@ -146,9 +151,18 @@
box-shadow: 0 0 0 2px var(--brand);
}
.chevron {
.chevron-btn {
position: absolute;
right: 12px;
background: none;
border: none;
padding: 0;
display: flex;
align-items: center;
justify-content: center;
}
.chevron {
font-size: 0.8rem;
color: var(--interactive-normal);
cursor: pointer;
+2 -2
View File
@@ -85,14 +85,14 @@
}
</script>
<div class="emoji-picker" onclick={(e) => e.stopPropagation()}>
<div class="emoji-picker" onclick={(e) => e.stopPropagation()} role="dialog" aria-label="Emoji Picker" tabindex="-1">
<div class="picker-header">
<input
type="text"
placeholder="Search emojis..."
bind:value={searchTerm}
class="search-input"
autofocus
aria-label="Search emojis"
/>
</div>
<div class="picker-content">
+8 -3
View File
@@ -12,11 +12,17 @@
const bannerUrl = $derived(user.bannerId ? chat.getBannerUrl(user) : null);
const isMe = $derived(chat.identity?.isEqual(user.identity));
let isEditingStatus = $state(false);
let statusText = $state(user.status || "");
let _localStatus = $state<string | null>(null);
let statusText = $derived.by({
get: () => _localStatus ?? user.status ?? "",
set: (v: string) => { _localStatus = v; }
});
async function handleStatusSubmit(e: Event) {
e.preventDefault();
await chat.handleSetStatus(statusText.trim() || undefined);
_localStatus = null; // Reset to sync with backend next time
isEditingStatus = false;
}
</script>
@@ -52,10 +58,9 @@
bind:value={statusText}
placeholder="Set a status..."
maxlength="128"
autofocus
onblur={() => { if (!statusText) isEditingStatus = false; }}
/>
<button type="submit" style="display: none;"></button>
<button type="submit" style="display: none;" aria-label="Save status"></button>
</form>
{:else}
<!-- svelte-ignore a11y_click_events_have_key_events -->
+10
View File
@@ -24,6 +24,8 @@
<button
class="server-icon {chat.activeServerId === null ? 'active' : ''}"
onclick={() => (chat.activeServerId = null)}
aria-label="Direct Messages"
title="Direct Messages"
>
<i class="fas fa-comment-dots"></i>
</button>
@@ -45,6 +47,8 @@
class="server-icon {chat.activeServerId === server.id ? 'active' : ''}"
onclick={() => (chat.activeServerId = server.id)}
style={avatarUrl ? `background-image: url(${avatarUrl}); background-size: cover; background-position: center; border: none;` : ""}
aria-label={server.name}
title={server.name}
>
{#if !avatarUrl}
{server.name.substring(0, 2).toUpperCase()}
@@ -59,6 +63,8 @@
class="server-icon"
onclick={() => (chat.showCreateServerModal = true)}
style="cursor: {chat.isFullyAuthenticated ? 'pointer' : 'not-allowed'};"
aria-label="Create Server"
title="Create Server"
>
<i class="fas fa-plus"></i>
</button>
@@ -69,6 +75,8 @@
class="server-icon"
onclick={() => (chat.showDiscoveryModal = true)}
style="color: var(--status-positive);"
aria-label="Discover Servers"
title="Discover Servers"
>
<i class="fas fa-search"></i>
</button>
@@ -86,6 +94,8 @@
class="server-icon"
onclick={onShowServerSettings}
style="color: var(--brand); margin-bottom: 12px;"
aria-label="Connection Settings"
title="Connection Settings"
>
<i class="fas fa-network-wired"></i>
</button>
@@ -543,30 +543,6 @@
z-index: 6000; /* Above settings */
}
.danger-modal {
background-color: var(--background-primary);
max-width: 440px;
width: 90%;
padding: 24px;
border-radius: 8px;
box-shadow: var(--elevation-high);
border: 1px solid var(--background-modifier-accent);
animation: modal-pop 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.danger-modal h2 {
color: var(--status-danger);
margin: 0 0 16px 0;
font-size: 1.2rem;
}
.danger-modal p {
color: var(--text-normal);
line-height: 1.5;
margin-bottom: 24px;
font-size: 0.95rem;
}
.modal-actions {
display: flex;
justify-content: flex-end;
+2 -2
View File
@@ -13,9 +13,9 @@
className?: string;
}>();
const style = circle
const style = $derived(circle
? `width: ${width}; height: ${width}; border-radius: 50%;`
: `width: ${width}; height: ${height}; border-radius: ${borderRadius};`;
: `width: ${width}; height: ${height}; border-radius: ${borderRadius};`);
</script>
<div
+9 -4
View File
@@ -1,5 +1,5 @@
<script lang="ts">
import { getContext, onMount } from "svelte";
import { getContext, onMount, untrack } from "svelte";
import type { ChatService } from "../services/chat.svelte";
import type { WebRTCService } from "../services/webrtc/webrtc.svelte";
import type * as Types from "../../module_bindings/types";
@@ -17,11 +17,16 @@
const webrtc = getContext<WebRTCService>("webrtc");
let menuRef = $state<HTMLDivElement | null>(null);
let adjustedX = $state(x);
let adjustedY = $state(y);
let adjustedX = $state(untrack(() => x));
let adjustedY = $state(untrack(() => y));
$effect(() => {
adjustedX = x;
adjustedY = y;
});
// Voice specific states
const peerIdHex = user.identity.toHexString();
const peerIdHex = $derived(user.identity.toHexString());
const voiceState = $derived(chat.userStates.find(s => s.identity.isEqual(user.identity)));
const isMe = $derived(chat.identity?.isEqual(user.identity));
const isLocalUserInVoice = $derived(!!chat.connectedVoiceChannel);
-4
View File
@@ -252,10 +252,6 @@
white-space: nowrap;
}
.watch-btn.active {
background-color: #f23f43;
}
.fullscreen-btn {
background-color: rgba(0, 0, 0, 0.6);
color: white;
@@ -14,6 +14,8 @@
chat.isVoiceChannel = false;
chat.showCreateChannelModal = true;
}}
title="Create Text Channel"
aria-label="Create Text Channel"
>
<i class="fas fa-plus"></i>
</button>
@@ -64,6 +64,8 @@
chat.isVoiceChannel = true;
chat.showCreateChannelModal = true;
}}
title="Create Voice Channel"
aria-label="Create Voice Channel"
>
<i class="fas fa-plus"></i>
</button>
@@ -301,19 +301,4 @@
display: flex;
gap: 8px;
}
.btn-clear {
background: none;
border: none;
color: var(--text-muted);
cursor: pointer;
font-size: 1.1rem;
opacity: 0.6;
transition: opacity 0.1s;
}
.btn-clear:hover {
opacity: 1;
color: var(--text-normal);
}
</style>
@@ -89,21 +89,6 @@
text-transform: uppercase;
}
.form-group select {
padding: 10px;
background-color: var(--background-tertiary);
color: var(--text-normal);
border: 1px solid var(--background-modifier-accent);
border-radius: 4px;
font-size: 1rem;
outline: none;
cursor: pointer;
}
.form-group select:hover {
background-color: var(--background-modifier-hover);
}
.voice-sensitivity-box {
background-color: var(--background-secondary);
padding: 16px;
@@ -156,7 +156,7 @@
</Input>
</div>
<div class="form-group">
<label>Emoji Image</label>
<div class="label-heading">Emoji Image</div>
<label class="custom-file-upload">
<i class="fas fa-image"></i>
<span class="file-name-text">{newEmojiFile ? newEmojiFile.name : "Select Image"}</span>
@@ -364,7 +364,7 @@
gap: 8px;
}
.form-group label {
.form-group label, .label-heading {
font-size: 0.75rem;
font-weight: 700;
color: var(--text-muted);
@@ -464,26 +464,4 @@
width: 100%;
text-align: center;
}
.btn-success {
background-color: var(--status-positive);
color: white;
border: none;
padding: 8px 20px;
border-radius: 4px;
font-weight: 600;
cursor: pointer;
transition: opacity 0.1s;
}
.btn-success:hover {
opacity: 0.9;
}
.btn-success:disabled {
background-color: var(--background-modifier-accent);
color: var(--text-muted);
cursor: not-allowed;
opacity: 0.5;
}
</style>
@@ -86,17 +86,6 @@
color: var(--text-muted);
text-transform: uppercase;
}
.form-group select {
padding: 10px;
background-color: var(--background-tertiary);
color: var(--text-normal);
border: none;
border-radius: 4px;
font-size: 1rem;
outline: none;
cursor: pointer;
}
.help-text {
font-size: 0.75rem;
@@ -50,7 +50,7 @@
</div>
<div class="form-group">
<label>Your Public Key</label>
<div class="label-heading">Your Public Key</div>
<div class="key-display">
<pre>{chat.myPublicKey}</pre>
<Button variant="secondary" size="small" class="copy-btn" onclick={copyPublicKey}>
@@ -179,7 +179,7 @@
margin-bottom: 20px;
}
.form-group label {
.form-group label, .label-heading {
display: block;
margin-bottom: 8px;
color: var(--header-secondary);
@@ -276,7 +276,7 @@ export class ChannelAudioWebRTCService {
// Map local track to the transceiver created by the offer
const transceivers = pc.getTransceivers();
const audioTrack = this.localStream?.getAudioTracks()[0];
const audioTransceiver = transceivers.find(t => t.receiver.track.kind === 'audio');
const audioTransceiver = transceivers.find((t: RTCRtpTransceiver) => t.receiver.track.kind === 'audio');
if (audioTransceiver && audioTrack) {
await audioTransceiver.sender.replaceTrack(audioTrack);
@@ -288,8 +288,8 @@ export class ScreenSharingWebRTCService {
const videoTrack = this.localScreenStream?.getVideoTracks()[0];
const audioTrack = this.localScreenStream?.getAudioTracks()[0];
const videoTransceiver = transceivers.find(t => t.receiver.track.kind === 'video');
const audioTransceiver = transceivers.find(t => t.receiver.track.kind === 'audio');
const videoTransceiver = transceivers.find((t: RTCRtpTransceiver) => t.receiver.track.kind === 'video');
const audioTransceiver = transceivers.find((t: RTCRtpTransceiver) => t.receiver.track.kind === 'audio');
if (videoTransceiver && videoTrack) {
await videoTransceiver.sender.replaceTrack(videoTrack);