small fixes

This commit is contained in:
2026-04-17 03:36:39 -04:00
parent 7b4260bc90
commit fbdc19e8ab
8 changed files with 89 additions and 41 deletions
+21 -3
View File
@@ -90,14 +90,25 @@ pub fn init(ctx: &ReducerContext) {
pub fn on_connect(ctx: &ReducerContext) { pub fn on_connect(ctx: &ReducerContext) {
log::info!("on_connect START: identity={}", ctx.sender().to_hex()); log::info!("on_connect START: identity={}", ctx.sender().to_hex());
// We'll keep this extremely minimal to ensure connection stability // Extract potential name from OIDC if available
let mut initial_name = None;
if let Some(jwt) = ctx.sender_auth().jwt() {
let sub = jwt.subject();
// Use first 8 chars of sub if it's a long string/UUID
initial_name = Some(if sub.len() > 12 { sub[..8].to_string() } else { sub.to_string() });
}
if let Some(mut user) = ctx.db.user().identity().find(ctx.sender()) { if let Some(mut user) = ctx.db.user().identity().find(ctx.sender()) {
user.online = true; user.online = true;
// Update name from OIDC if current user has no name
if user.name.is_none() && initial_name.is_some() {
user.name = initial_name;
}
ctx.db.user().identity().update(user); ctx.db.user().identity().update(user);
} else { } else {
ctx.db.user().insert(User { ctx.db.user().insert(User {
identity: ctx.sender(), identity: ctx.sender(),
name: None, name: initial_name,
online: true, online: true,
issuer: None, issuer: None,
subject: None, subject: None,
@@ -160,9 +171,16 @@ pub fn update_auth_info(ctx: &ReducerContext) {
log::info!("update_auth_info: identity={}", ctx.sender().to_hex()); log::info!("update_auth_info: identity={}", ctx.sender().to_hex());
if let Some(mut user) = ctx.db.user().identity().find(ctx.sender()) { if let Some(mut user) = ctx.db.user().identity().find(ctx.sender()) {
if let Some(jwt) = ctx.sender_auth().jwt() { if let Some(jwt) = ctx.sender_auth().jwt() {
let sub = jwt.subject();
user.issuer = Some(jwt.issuer().to_string()); user.issuer = Some(jwt.issuer().to_string());
user.subject = Some(jwt.subject().to_string()); user.subject = Some(sub.to_string());
user.anonymous = false; user.anonymous = false;
// Also update name if they don't have a custom one yet
if user.name.is_none() {
user.name = Some(if sub.len() > 12 { sub[..8].to_string() } else { sub.to_string() });
}
ctx.db.user().identity().update(user); ctx.db.user().identity().update(user);
sync_server_member_info(&ctx.db, ctx.sender()); sync_server_member_info(&ctx.db, ctx.sender());
log::info!("update_auth_info: updated user with OIDC info"); log::info!("update_auth_info: updated user with OIDC info");
+18 -18
View File
@@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import { createSpacetimeDBProvider } from "spacetimedb/svelte"; import { createSpacetimeDBProvider } from "spacetimedb/svelte";
import type { ConnectionBuilder } from "spacetimedb"; import type { ConnectionBuilder } from "spacetimedb";
import { untrack } from "svelte";
import { getStdbHost, getStdbDbName, handleConnect } from "./config"; import { getStdbHost, getStdbDbName, handleConnect } from "./config";
let { builder, children, onCancel }: { builder: ConnectionBuilder<any>, children: any, onCancel?: () => void } = $props(); let { builder, children, onCancel }: { builder: ConnectionBuilder<any>, children: any, onCancel?: () => void } = $props();
@@ -8,28 +9,27 @@
// Initialize the provider // Initialize the provider
const db = createSpacetimeDBProvider(builder); const db = createSpacetimeDBProvider(builder);
// Fallback: Also register direct listener on the connection if possible // Handshake latch to prevent infinite reactive loops
$effect(() => { let hasSyncedForThisConnection = $state(false);
if ($db.connection) {
$db.connection.onConnect((conn: any, identity: any, token: string) => {
console.log("InnerProvider: connection.onConnect triggered, syncing state...");
handleConnect(conn, identity, token);
});
}
});
// Watch for successful connection and persist state // Watch for successful connection and persist state
$effect(() => { $effect(() => {
console.log("InnerProvider State:", { // Only trigger when the underlying connection actually changes
isActive: $db.isActive, const conn = $db.connection;
hasIdentity: !!$db.identity, const isActive = $db.isActive;
hasToken: !!$db.token, const identity = $db.identity;
hasConn: !!$db.connection
});
if ($db.isActive && $db.identity && $db.connection) { if (isActive && identity && conn) {
console.log("InnerProvider: Connection valid, syncing state..."); untrack(() => {
handleConnect($db.connection, $db.identity, $db.token || ""); if (!hasSyncedForThisConnection) {
console.log("InnerProvider: Initial handshake established, syncing state...");
handleConnect(conn, identity, $db.token || "");
hasSyncedForThisConnection = true;
}
});
} else if (!isActive) {
// Reset latch if connection drops
hasSyncedForThisConnection = false;
} }
}); });
+10 -3
View File
@@ -11,12 +11,19 @@
}>(); }>();
let builder = $state<ConnectionBuilder<any> | null>(null); let builder = $state<ConnectionBuilder<any> | null>(null);
let lastUsedToken = $state<string | undefined>(undefined);
$effect(() => { $effect(() => {
if (!auth.isLoading) { if (!auth.isLoading) {
console.log("InnerSpacetimeProvider: Initializing connection..."); const currentToken = auth.user?.id_token;
connectionState.status = "connecting";
builder = connectionBuilder(auth.user?.id_token); // Only re-initialize if the token actually changed
if (currentToken !== lastUsedToken || !builder) {
console.log("InnerSpacetimeProvider: Initializing connection...");
connectionState.status = "connecting";
builder = connectionBuilder(currentToken);
lastUsedToken = currentToken;
}
} }
}); });
</script> </script>
+17 -9
View File
@@ -53,13 +53,13 @@
} }
}); });
// Split combined connection if it changes // Split combined connection if it changes (Only when on login screen)
$effect(() => { $effect(() => {
if (combinedConnection.includes(":")) { if (!userWantsToConnect && combinedConnection.includes(":")) {
const lastColon = combinedConnection.lastIndexOf(":"); const lastColon = combinedConnection.lastIndexOf(":");
const host = combinedConnection.substring(0, lastColon); const host = combinedConnection.substring(0, lastColon);
const db = combinedConnection.substring(lastColon + 1); const db = combinedConnection.substring(lastColon + 1);
if (host && db) { if (host && db && (host !== stdbHost || db !== stdbDbName)) {
untrack(() => { untrack(() => {
stdbHost = host; stdbHost = host;
stdbDbName = db; stdbDbName = db;
@@ -71,23 +71,31 @@
// Update combined connection if individual fields change (e.g. on mount) // Update combined connection if individual fields change (e.g. on mount)
$effect(() => { $effect(() => {
const hostPart = stdbHost.replace(/^(https?|wss?):\/\//, ""); const hostPart = stdbHost.replace(/^(https?|wss?):\/\//, "");
combinedConnection = `${hostPart}:${stdbDbName}`; const expected = `${hostPart}:${stdbDbName}`;
if (combinedConnection !== expected) {
combinedConnection = expected;
}
}); });
let hasStoredToken = $state(false); let hasStoredToken = $state(false);
$effect(() => { $effect(() => {
// Check for token on mount and when connection params change // Check for token when connection params change
const _ = combinedConnection; if (stdbHost && stdbDbName) {
hasStoredToken = !!TokenStore.get(stdbHost, stdbDbName); hasStoredToken = !!TokenStore.get(stdbHost, stdbDbName);
}
}); });
$effect(() => { $effect(() => {
if (stdbHost) localStorage.setItem(HOST_KEY, stdbHost); if (stdbHost && localStorage.getItem(HOST_KEY) !== stdbHost) {
localStorage.setItem(HOST_KEY, stdbHost);
}
}); });
$effect(() => { $effect(() => {
if (stdbDbName) localStorage.setItem(DB_NAME_KEY, stdbDbName); if (stdbDbName && localStorage.getItem(DB_NAME_KEY) !== stdbDbName) {
localStorage.setItem(DB_NAME_KEY, stdbDbName);
}
}); });
const isBypassEnabled = const isBypassEnabled =
+5 -1
View File
@@ -301,7 +301,11 @@
{/if} {/if}
{#if chat.userContextMenu} {#if chat.userContextMenu}
<UserContextMenu {...chat.userContextMenu} onClose={() => (chat.userContextMenu = null)} /> <UserContextMenu
{...chat.userContextMenu}
onClose={() => (chat.userContextMenu = null)}
onAction={closeSidebars}
/>
{/if} {/if}
{#if chat.confirmModal} {#if chat.confirmModal}
+8 -3
View File
@@ -5,11 +5,12 @@
import type * as Types from "../../module_bindings/types"; import type * as Types from "../../module_bindings/types";
import { portal } from "../../portal"; import { portal } from "../../portal";
let { x, y, user, onClose }: { let { x, y, user, onClose, onAction }: {
x: number, x: number,
y: number, y: number,
user: Types.User, user: Types.User,
onClose: () => void onClose: () => void,
onAction?: () => void
} = $props(); } = $props();
const chat = getContext<ChatService>("chat"); const chat = getContext<ChatService>("chat");
@@ -108,6 +109,7 @@
{#if !isMe} {#if !isMe}
<button class="menu-item" onclick={() => { <button class="menu-item" onclick={() => {
chat.handleOpenDirectMessage(user.identity); chat.handleOpenDirectMessage(user.identity);
onAction?.();
onClose(); onClose();
}}> }}>
<span>Message</span> <span>Message</span>
@@ -116,7 +118,10 @@
{/if} {/if}
{#if !isMe} {#if !isMe}
<button class="menu-item" onclick={mentionUser}> <button class="menu-item" onclick={() => {
mentionUser();
onAction?.();
}}>
<span>Mention</span> <span>Mention</span>
<i class="fas fa-at"></i> <i class="fas fa-at"></i>
</button> </button>
@@ -115,10 +115,13 @@
} }
.channel-item-hash { .channel-item-hash {
font-size: 1.2rem; font-size: 1rem;
color: var(--text-muted); color: var(--text-muted);
margin-right: 4px; margin-right: 4px;
width: 20px; width: 20px;
text-align: center; display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
} }
</style> </style>
@@ -296,11 +296,14 @@
} }
.channel-item-hash { .channel-item-hash {
font-size: 1.2rem; font-size: 1rem;
color: var(--text-muted); color: var(--text-muted);
margin-right: 4px; margin-right: 4px;
width: 20px; width: 20px;
text-align: center; display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
} }
/* Voice Member List Styles */ /* Voice Member List Styles */