fix: blank page on channel click + logout issue
This commit is contained in:
@@ -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()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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">
|
||||||
<{message.author.username}>
|
<{message.author_username}>
|
||||||
</span>{" "}
|
</span>{" "}
|
||||||
<span className="text-gb-fg">{message.content}</span>
|
<span className="text-gb-fg">{message.content}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+30
-16
@@ -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,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -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': {
|
||||||
|
|||||||
Reference in New Issue
Block a user