feat: Add MembersList component, configure Electron frontend with Vite, and establish Gitea release workflow.
Some checks failed
Build and Release / build-and-release (push) Failing after 7m35s

This commit is contained in:
Bryan1029384756
2026-02-11 06:42:31 -06:00
parent c472f0ee2d
commit 49bc491e08
6 changed files with 25 additions and 9 deletions

View File

@@ -44,7 +44,8 @@ jobs:
run: | run: |
cd Frontend/Electron cd Frontend/Electron
npm run build npm run build
xvfb-run npx electron-builder --linux --win npx electron-builder --linux
xvfb-run npx electron-builder --win
env: env:
GH_TOKEN: ${{ secrets.CI_TOKEN }} GH_TOKEN: ${{ secrets.CI_TOKEN }}
WINEDEBUG: "-all" WINEDEBUG: "-all"

View File

@@ -2,6 +2,8 @@
"name": "discord", "name": "discord",
"private": true, "private": true,
"version": "1.0.3", "version": "1.0.3",
"description": "A Discord clone built with Convex, React, and Electron",
"author": "Moyettes",
"type": "module", "type": "module",
"main": "main.cjs", "main": "main.cjs",
"homepage": "./", "homepage": "./",

View File

@@ -23,6 +23,7 @@ import EmojiesGreyscale from './emojies_greyscale.png';
import TypingIcon from './typing.svg'; import TypingIcon from './typing.svg';
import DMIcon from './dm.svg'; import DMIcon from './dm.svg';
import SpoilerIcon from './spoiler.svg'; import SpoilerIcon from './spoiler.svg';
import CrownIcon from './crown.svg';
export { export {
AddIcon, AddIcon,
@@ -49,7 +50,8 @@ export {
PinIcon, PinIcon,
TypingIcon, TypingIcon,
DMIcon, DMIcon,
SpoilerIcon SpoilerIcon,
CrownIcon
}; };
export const Icons = { export const Icons = {
@@ -77,5 +79,6 @@ export const Icons = {
Pin: PinIcon, Pin: PinIcon,
Typing: TypingIcon, Typing: TypingIcon,
DM: DMIcon, DM: DMIcon,
Spoiler: SpoilerIcon Spoiler: SpoilerIcon,
Crown: CrownIcon
}; };

View File

@@ -2,6 +2,7 @@ import React from 'react';
import { useQuery } from 'convex/react'; import { useQuery } from 'convex/react';
import { api } from '../../../../convex/_generated/api'; import { api } from '../../../../convex/_generated/api';
import { useOnlineUsers } from '../contexts/PresenceContext'; import { useOnlineUsers } from '../contexts/PresenceContext';
import { CrownIcon } from '../assets/icons';
const USER_COLORS = ['#5865F2', '#EBA7CD', '#57F287', '#FEE75C', '#EB459E', '#ED4245']; const USER_COLORS = ['#5865F2', '#EBA7CD', '#57F287', '#FEE75C', '#EB459E', '#ED4245'];
@@ -13,6 +14,12 @@ function getUserColor(name) {
return USER_COLORS[Math.abs(hash) % USER_COLORS.length]; return USER_COLORS[Math.abs(hash) % USER_COLORS.length];
} }
const ColoredIcon = ({ src, color, size = '24px', style = {} }) => (
<div style={{ width: size, height: size, overflow: 'hidden', display: 'flex', alignItems: 'center', justifyContent: 'center', ...style }}>
<img src={src} alt="" style={color ? { width: size, height: size, transform: 'translateX(-1000px)', filter: `drop-shadow(1000px 0 0 ${color})` } : { width: size, height: size, objectFit: 'contain' }} />
</div>
);
const STATUS_COLORS = { const STATUS_COLORS = {
online: '#3ba55c', online: '#3ba55c',
idle: '#faa61a', idle: '#faa61a',
@@ -38,7 +45,7 @@ const MembersList = ({ channelId, visible, onMemberClick }) => {
const ungrouped = []; const ungrouped = [];
onlineMembers.forEach(member => { onlineMembers.forEach(member => {
const hoistedRole = member.roles.find(r => r.isHoist && r.name !== '@everyone'); const hoistedRole = member.roles.find(r => r.isHoist && r.name !== '@everyone' && r.name !== 'Owner');
if (hoistedRole) { if (hoistedRole) {
const key = `${hoistedRole.position}_${hoistedRole.name}`; const key = `${hoistedRole.position}_${hoistedRole.name}`;
if (!roleGroups[key]) { if (!roleGroups[key]) {
@@ -54,8 +61,9 @@ const MembersList = ({ channelId, visible, onMemberClick }) => {
const sortedGroups = Object.values(roleGroups).sort((a, b) => b.role.position - a.role.position); const sortedGroups = Object.values(roleGroups).sort((a, b) => b.role.position - a.role.position);
const renderMember = (member) => { const renderMember = (member) => {
const topRole = member.roles.length > 0 ? member.roles[0] : null; const displayRole = member.roles.find(r => r.name !== '@everyone' && r.name !== 'Owner') || null;
const nameColor = topRole && topRole.name !== '@everyone' ? topRole.color : '#fff'; const nameColor = displayRole ? displayRole.color : '#fff';
const isOwner = member.roles.some(r => r.name === 'Owner');
const effectiveStatus = resolveStatus(member.status, member.id); const effectiveStatus = resolveStatus(member.status, member.id);
return ( return (
@@ -87,8 +95,9 @@ const MembersList = ({ channelId, visible, onMemberClick }) => {
/> />
</div> </div>
<div className="member-info"> <div className="member-info">
<span className="member-name" style={{ color: nameColor }}> <span className="member-name" style={{ color: nameColor, display: 'flex', alignItems: 'center', gap: '4px' }}>
{member.username} {member.username}
{isOwner && <ColoredIcon src={CrownIcon} color="var(--text-feedback-warning)" size="14px" />}
</span> </span>
{member.customStatus && ( {member.customStatus && (
<div style={{ fontSize: '12px', color: 'var(--text-muted)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}> <div style={{ fontSize: '12px', color: 'var(--text-muted)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>

View File

@@ -11,5 +11,6 @@ export default defineConfig({
}, },
build: { build: {
outDir: 'dist-react', outDir: 'dist-react',
chunkSizeWarningLimit: 1000,
}, },
}) })

View File

@@ -1,4 +1,4 @@
When i scroll up one time with my scroll wheel and move my mouse it scrolls down to the start.
- 955px - 955px
- I want to give users the choice to update the app. Can we make updating work 2 ways. One, optional updates, i want to somehow make some updates marked as optional, where techinically older versions will still work so we dont care if they are on a older version. And some updates non optional, where we will require users to update to the latest version to continue using the app. So for example when they launch the app we will check if their is a update but we dont update the app right away. We will show a download icon like discord in the header, that will be the update.svg icon. Make the icon use this color "hsl(138.353 calc(1*38.117%) 56.275% /1);"