feat: Implement core Discord features including members list, direct messages, user presence, authentication, and chat UI.
Some checks failed
Build and Release / build-and-release (push) Has been cancelled

This commit is contained in:
Bryan1029384756
2026-02-11 04:36:40 -06:00
parent a29858fd32
commit cb4361da1a
32 changed files with 2051 additions and 144 deletions

View File

@@ -0,0 +1,47 @@
import React, { createContext, useContext, useMemo } from 'react';
import usePresence from '@convex-dev/presence/react';
import { api } from '../../../../convex/_generated/api';
const PresenceContext = createContext({
onlineUsers: new Set(),
resolveStatus: (storedStatus, userId) => storedStatus || 'offline',
});
export const useOnlineUsers = () => useContext(PresenceContext);
/**
* Status resolution logic:
* - If user is NOT connected (no heartbeat) → "offline"
* - If user IS connected and chose "invisible" → "offline"
* - If user IS connected → show their chosen status (online/idle/dnd)
*/
function resolveStatusFn(onlineUsers, storedStatus, userId) {
if (!onlineUsers.has(userId)) return 'offline';
if (storedStatus === 'invisible') return 'offline';
return storedStatus || 'online';
}
export const PresenceProvider = ({ userId, children }) => {
const presenceState = usePresence(api.presence, 'global', userId);
const onlineUsers = useMemo(() => {
const set = new Set();
if (presenceState) {
for (const p of presenceState) {
if (p.online) set.add(p.userId);
}
}
return set;
}, [presenceState]);
const value = useMemo(() => ({
onlineUsers,
resolveStatus: (storedStatus, uid) => resolveStatusFn(onlineUsers, storedStatus, uid),
}), [onlineUsers]);
return (
<PresenceContext.Provider value={value}>
{children}
</PresenceContext.Provider>
);
};

View File

@@ -23,9 +23,21 @@ export function ThemeProvider({ children }) {
return localStorage.getItem(STORAGE_KEY) || THEMES.DARK;
});
// On mount, check settings.json as fallback when localStorage is empty
useEffect(() => {
if (!localStorage.getItem(STORAGE_KEY) && window.appSettings) {
window.appSettings.get('theme').then((saved) => {
if (saved && Object.values(THEMES).includes(saved)) {
setTheme(saved);
}
});
}
}, []);
useEffect(() => {
document.documentElement.className = theme;
localStorage.setItem(STORAGE_KEY, theme);
window.appSettings?.set('theme', theme);
}, [theme]);
return (