feat: polls with live voting via WebSocket
- /poll command opens creation modal (2-10 options) - PollDisplay with vote bars, percentages, live WS updates - Backend: polls/poll_options/poll_votes tables, Create/Get/Vote endpoints - attachPolls enriches message list responses - POLL_UPDATE broadcast on vote for real-time sync
This commit is contained in:
@@ -10,6 +10,7 @@ import { useThreadStore } from "../stores/thread.ts";
|
||||
import { GiphyPicker, type Gif } from "./GiphyPicker";
|
||||
import { CommandDropdown } from "./CommandDropdown";
|
||||
import { findCommand } from "../lib/slashCommands";
|
||||
import { PollDisplay, CreatePollModal } from "./Poll.tsx";
|
||||
import { MentionDropdown } from "./MentionDropdown";
|
||||
import { useReadStatesStore } from "../stores/readStates.ts";
|
||||
import { MessageSearch } from "./MessageSearch";
|
||||
@@ -217,6 +218,7 @@ const MessageItem = memo(({
|
||||
</span>{" "}
|
||||
<span className="text-gb-fg">{renderContent(message.content, memberUsernames)}</span>
|
||||
{renderEmbeds(message.embeds)}
|
||||
{message.poll && <PollDisplay poll={message.poll} channelId={message.channel_id} />}
|
||||
|
||||
{/* Message reactions */}
|
||||
<ReactionBar
|
||||
@@ -272,6 +274,7 @@ export function ChatArea() {
|
||||
const [showSearch, setShowSearch] = useState(false);
|
||||
const [mentionQuery, setMentionQuery] = useState<string | null>(null);
|
||||
const [commandQuery, setCommandQuery] = useState<string | null>(null);
|
||||
const [showPollModal, setShowPollModal] = useState(false);
|
||||
const [slowmodeRemaining, setSlowmodeRemaining] = useState(0);
|
||||
const [selectMode, setSelectMode] = useState(false);
|
||||
const [showThreads, setShowThreads] = useState(false);
|
||||
@@ -494,6 +497,13 @@ export function ChatArea() {
|
||||
const spaceIdx = messageText.indexOf(' ');
|
||||
const cmdName = spaceIdx === -1 ? messageText.slice(1) : messageText.slice(1, spaceIdx);
|
||||
const args = spaceIdx === -1 ? '' : messageText.slice(spaceIdx + 1).trim();
|
||||
// /poll opens the poll creation modal
|
||||
if (cmdName === 'poll') {
|
||||
setShowPollModal(true);
|
||||
setInput('');
|
||||
setCommandQuery(null);
|
||||
return;
|
||||
}
|
||||
const cmd = findCommand(cmdName);
|
||||
if (cmd) {
|
||||
messageText = cmd.transform(args, currentUser?.username || 'user');
|
||||
@@ -782,6 +792,12 @@ export function ChatArea() {
|
||||
<UserProfileModal userId={profileUserId} onClose={() => setProfileUserId(null)} />
|
||||
)}
|
||||
{MenuPortal}
|
||||
{showPollModal && activeChannelId && (
|
||||
<CreatePollModal
|
||||
channelId={activeChannelId}
|
||||
onClose={() => setShowPollModal(false)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user