fix: blank page on channel click + logout issue

This commit is contained in:
2026-06-29 14:16:32 -04:00
parent a7da8104d7
commit 175ec90705
4 changed files with 37 additions and 28 deletions
+1 -6
View File
@@ -10,11 +10,6 @@ import (
// Shared by password login, registration, and WebAuthn login. // Shared by password login, registration, and WebAuthn login.
func SetSessionCookie(w http.ResponseWriter, cookieName, token string, duration time.Duration) { func SetSessionCookie(w http.ResponseWriter, cookieName, token string, duration time.Duration) {
secure := os.Getenv("COOKIE_SECURE") == "true" secure := os.Getenv("COOKIE_SECURE") == "true"
sameSite := http.SameSiteLaxMode
if secure {
sameSite = http.SameSiteStrictMode
}
http.SetCookie(w, &http.Cookie{ http.SetCookie(w, &http.Cookie{
Name: cookieName, Name: cookieName,
@@ -22,7 +17,7 @@ func SetSessionCookie(w http.ResponseWriter, cookieName, token string, duration
Path: "/", Path: "/",
HttpOnly: true, HttpOnly: true,
Secure: secure, Secure: secure,
SameSite: sameSite, SameSite: http.SameSiteDefaultMode,
MaxAge: int(duration.Seconds()), MaxAge: int(duration.Seconds()),
}) })
} }
+2 -2
View File
@@ -82,10 +82,10 @@ export function ChatArea() {
{messages.map((message) => ( {messages.map((message) => (
<div key={message.id} className="break-words"> <div key={message.id} className="break-words">
<span className="text-gb-fg-f"> <span className="text-gb-fg-f">
[{formatTime(message.createdAt)}] [{formatTime(message.created_at)}]
</span>{" "} </span>{" "}
<span className="text-gb-aqua"> <span className="text-gb-aqua">
&lt;{message.author.username}&gt; &lt;{message.author_username}&gt;
</span>{" "} </span>{" "}
<span className="text-gb-fg">{message.content}</span> <span className="text-gb-fg">{message.content}</span>
</div> </div>
+30 -16
View File
@@ -1,14 +1,15 @@
import { create } from 'zustand'; import { create } from "zustand";
import { api } from '../lib/api.ts'; import { api } from "../lib/api.ts";
import type { User } from './auth.ts';
export interface Message { export interface Message {
id: string; id: string;
channelId: string; channel_id: string;
author: User; author_id: string;
author_username: string;
author_display_name: string | null;
content: string; content: string;
createdAt: string; created_at: string;
updatedAt?: string; edited_at: string | null;
} }
interface MessageState { interface MessageState {
@@ -30,22 +31,33 @@ export const useMessageStore = create<MessageState>((set) => ({
fetchMessages: async (channelId, before) => { fetchMessages: async (channelId, before) => {
set({ isLoading: true, error: null }); set({ isLoading: true, error: null });
try { try {
const params = before ? `?before=${encodeURIComponent(before)}` : ''; const params = before ? `?before=${encodeURIComponent(before)}` : "";
const messages = await api.get<Message[]>(`/channels/${channelId}/messages${params}`); const messages = await api.get<Message[]>(
`/channels/${channelId}/messages${params}`,
);
set((state) => ({ set((state) => ({
messagesByChannel: { ...state.messagesByChannel, [channelId]: messages }, messagesByChannel: {
...state.messagesByChannel,
[channelId]: Array.isArray(messages) ? messages : [],
},
isLoading: false, isLoading: false,
})); }));
} catch (error) { } catch (error) {
set({ set({
isLoading: false, isLoading: false,
error: error instanceof Error ? error.message : 'Failed to fetch messages', error:
error instanceof Error
? error.message
: "Failed to fetch messages",
}); });
} }
}, },
sendMessage: async (channelId, content) => { sendMessage: async (channelId, content) => {
const message = await api.post<Message>(`/channels/${channelId}/messages`, { content }); const message = await api.post<Message>(
`/channels/${channelId}/messages`,
{ content },
);
set((state) => { set((state) => {
const list = state.messagesByChannel[channelId] || []; const list = state.messagesByChannel[channelId] || [];
return { return {
@@ -60,25 +72,27 @@ export const useMessageStore = create<MessageState>((set) => ({
addMessage: (message) => addMessage: (message) =>
set((state) => { set((state) => {
const list = state.messagesByChannel[message.channelId] || []; const list = state.messagesByChannel[message.channel_id] || [];
if (list.some((m) => m.id === message.id)) { if (list.some((m) => m.id === message.id)) {
return state; return state;
} }
return { return {
messagesByChannel: { messagesByChannel: {
...state.messagesByChannel, ...state.messagesByChannel,
[message.channelId]: [...list, message], [message.channel_id]: [...list, message],
}, },
}; };
}), }),
updateMessage: (message) => updateMessage: (message) =>
set((state) => { set((state) => {
const list = state.messagesByChannel[message.channelId] || []; const list = state.messagesByChannel[message.channel_id] || [];
return { return {
messagesByChannel: { messagesByChannel: {
...state.messagesByChannel, ...state.messagesByChannel,
[message.channelId]: list.map((m) => (m.id === message.id ? message : m)), [message.channel_id]: list.map((m) =>
m.id === message.id ? message : m,
),
}, },
}; };
}), }),
+4 -4
View File
@@ -50,14 +50,14 @@ function extractServer(payload: UnknownPayload): Server | null {
} }
function extractIds(payload: UnknownPayload): { channelId: string; messageId: string } | null { function extractIds(payload: UnknownPayload): { channelId: string; messageId: string } | null {
if (typeof payload.channelId !== 'string' || typeof payload.messageId !== 'string') { if (typeof payload.channel_id !== 'string' || typeof payload.message_id !== 'string') {
return null; return null;
} }
return { channelId: payload.channelId, messageId: payload.messageId }; return { channelId: payload.channel_id, messageId: payload.message_id };
} }
function extractChannelId(payload: UnknownPayload): string | null { function extractChannelId(payload: UnknownPayload): string | null {
return typeof payload.channelId === 'string' ? payload.channelId : null; return typeof payload.channel_id === 'string' ? payload.channel_id : null;
} }
export const useWebSocketStore = create<WebSocketState>((set, get) => ({ export const useWebSocketStore = create<WebSocketState>((set, get) => ({
@@ -142,7 +142,7 @@ export const useWebSocketStore = create<WebSocketState>((set, get) => ({
} }
case 'message_deleted': { case 'message_deleted': {
const ids = extractIds(data.payload); const ids = extractIds(data.payload);
if (ids) removeMessage(ids.channelId, ids.messageId); if (ids) removeMessage(ids.channel_id, ids.message_id);
break; break;
} }
case 'channel_created': { case 'channel_created': {