Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 4 additions & 18 deletions frontend/src/routes/admin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -179,10 +179,6 @@ function QRPanel({
}
>
<div className="flex flex-col gap-4">
<Alert size="sm" color="secondary">
Waiting for {result.voterName} to scan the QR code…
</Alert>

{/* QR code — white background ensures readability regardless of theme */}
<div className="flex justify-center">
<div
Expand Down Expand Up @@ -945,14 +941,8 @@ function Admin() {
const [tallyDownloadError, setTallyDownloadError] = useState<string | null>(
null,
);
// Ref so the SSE closure always reads the current qrInfo without re-subscribing.
const qrInfoRef = useRef(qrInfo);
const [loadError, setLoadError] = useState<string | null>(null);

useEffect(() => {
qrInfoRef.current = qrInfo;
}, [qrInfo]);

const reloadVoters = useCallback(async () => {
try {
const list = await fetchVoterList();
Expand Down Expand Up @@ -1050,13 +1040,9 @@ function Admin() {
withCredentials: true,
});
es.onmessage = (e) => {
const raw = (e.data as string).replace(/^"|"$/g, "");
if (raw === "Ready") {
const name = qrInfoRef.current?.voterName ?? null;
setQrInfo(null);
setJoinedVoterName(name);
reloadVoters();
}
const name = e.data as string;
setJoinedVoterName(name);
reloadVoters();
};
es.onerror = () => console.warn("invite-watch SSE disconnected");
return () => es.close();
Expand Down Expand Up @@ -1283,7 +1269,7 @@ function Admin() {
<div className="flex flex-col gap-6">
<AddVoterPanel onAdded={handleVoterAdded} voteState={voteState} />

{joinedVoterName && !qrInfo && (
{joinedVoterName && (
<Alert
size="m"
color="primary"
Expand Down
10 changes: 3 additions & 7 deletions rustsystem-server/src/api/host/invite_watch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,16 @@ impl APIHandler for InviteWatch {
const PATH: &'static str = "/invite-watch";
const SUCCESS_CODE: StatusCode = StatusCode::OK;
type SuccessResponse =
Sse<FilterMap<WatchStream<bool>, fn(bool) -> Option<Result<Event, APIError>>>>;
Sse<FilterMap<WatchStream<Option<String>>, fn(Option<String>) -> Option<Result<Event, APIError>>>>;

async fn route(request: Self::Request) -> Result<Self::SuccessResponse, APIError> {
let InviteWatchRequest {
auth,
state: State(state),
} = request;

let upon_event = |new_state| {
if new_state {
Some(Ok::<Event, APIError>(Event::default().data("Ready")))
} else {
Some(Ok::<Event, APIError>(Event::default().data("Wait")))
}
let upon_event = |new_state: Option<String>| {
new_state.map(|name| Ok::<Event, APIError>(Event::default().data(name)))
};

let meeting = state.get_meeting(auth.muuid).await?;
Expand Down
3 changes: 1 addition & 2 deletions rustsystem-server/src/api/host/start_invite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ impl APIHandler for StartInvite {
state: State(state),
} = request;

let meeting = state.get_meeting(auth.muuid).await?;
meeting.invite_auth.write().await.set_state(true);
state.get_meeting(auth.muuid).await?;

info!(muuid = %auth.muuid, "Invite watch opened");

Expand Down
4 changes: 2 additions & 2 deletions rustsystem-server/src/api/login.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ impl APIHandler for Login {
voter.name.clone()
}; // voters write guard released

// Signal the invite watcher.
meeting.invite_auth.write().await.set_state(true);
// Signal the invite watcher with the voter's name.
meeting.invite_auth.write().await.notify_login(voter_name.clone());

// Validate optional admin credentials.
let is_host = if let Some(admin_cred) = body.admin_cred {
Expand Down
10 changes: 5 additions & 5 deletions rustsystem-server/src/invite_auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,22 @@ use tokio::sync::watch::{Receiver, Sender};
use tracing::error;

pub struct InviteAuthority {
state_tx: Sender<bool>,
state_tx: Sender<Option<String>>,
}
impl InviteAuthority {
pub fn new() -> Self {
Self {
state_tx: Sender::new(false),
state_tx: Sender::new(None),
}
}

pub fn set_state(&mut self, new_state: bool) {
if let Err(e) = self.state_tx.send(new_state) {
pub fn notify_login(&mut self, voter_name: String) {
if let Err(e) = self.state_tx.send(Some(voter_name)) {
error!("{e}");
}
}

pub fn new_watcher(&self) -> Receiver<bool> {
pub fn new_watcher(&self) -> Receiver<Option<String>> {
self.state_tx.subscribe()
}
}
Loading