diff --git a/frontend/apps/crates/components/src/qr_dialog/state.rs b/frontend/apps/crates/components/src/qr_dialog/state.rs index 09fcc2343..9f807890a 100644 --- a/frontend/apps/crates/components/src/qr_dialog/state.rs +++ b/frontend/apps/crates/components/src/qr_dialog/state.rs @@ -1,7 +1,11 @@ use std::rc::Rc; use qrcode_generator::QrCodeEcc; -use utils::{routes::Route, unwrap::UnwrapJiExt}; +use shared::domain::jig::codes::JigCode; +use utils::{ + routes::{KidsRoute, Route}, + unwrap::UnwrapJiExt, +}; use wasm_bindgen::JsValue; use super::QrDialogCallbacks; @@ -21,6 +25,25 @@ impl QrDialog { callbacks, }) } + + pub fn new_jig_code( + code: JigCode, + jig_name: String, + code_name: Option, + callbacks: QrDialogCallbacks, + ) -> Rc { + let jig_name = jig_name.replace(" ", "-"); + let code_name = code_name.map(|n| n.replace(" ", "-")); + let mut file_label = format!("{}_{}", code.to_string(), jig_name); + if let Some(code_name) = code_name { + file_label = format!("{}_{}", code_name, file_label); + } + QrDialog::new( + Route::Kids(KidsRoute::StudentCode(Some(code.to_string()))), + file_label, + callbacks, + ) + } } fn file_to_object_url(filetype: &str, data: &str) -> String { diff --git a/frontend/apps/crates/components/src/share_asset/actions.rs b/frontend/apps/crates/components/src/share_asset/actions.rs index 7715e5269..c78ede43d 100644 --- a/frontend/apps/crates/components/src/share_asset/actions.rs +++ b/frontend/apps/crates/components/src/share_asset/actions.rs @@ -31,7 +31,7 @@ impl ShareAsset { let res = jig::codes::Create::api_with_auth(JigPlayerSessionCreatePath(), Some(req)).await.toast_on_err(); let res = bail_on_err!(res); - state.student_code.set(Some(res.index.to_string())); + state.student_code.set(Some(res.index)); })); } @@ -48,14 +48,10 @@ impl ShareAsset { pub fn show_qr_code(self: &Rc) { let state = self; - let code = self - .student_code - .get_cloned() - .unwrap_or_default() - .to_string(); - let qr_dialog = QrDialog::new( - Route::Kids(KidsRoute::StudentCode(Some(code.clone()))), - code, + let qr_dialog = QrDialog::new_jig_code( + state.student_code.get().unwrap_ji(), + state.asset.unwrap_jig().jig_data.display_name.clone(), + state.code_name.get_cloned(), QrDialogCallbacks::new(clone!(state => move || { state.qr_dialog.set(None); })), diff --git a/frontend/apps/crates/components/src/share_asset/dom.rs b/frontend/apps/crates/components/src/share_asset/dom.rs index 4554e38d1..9f3e20e81 100644 --- a/frontend/apps/crates/components/src/share_asset/dom.rs +++ b/frontend/apps/crates/components/src/share_asset/dom.rs @@ -276,14 +276,14 @@ impl ShareAsset { None => None, Some(student_code) => { let url = SETTINGS.get().unwrap_ji().remote_target.pages_url(); - Some(url + &Route::Kids(KidsRoute::StudentCode(Some(student_code))).to_string()) + Some(url + &Route::Kids(KidsRoute::StudentCode(Some(student_code.to_string()))).to_string()) }, } })) .prop_signal("code", state.student_code.signal_cloned().map(|student_code| { match student_code { None => String::new(), - Some(student_code) => student_code, + Some(student_code) => student_code.to_string(), } })) .prop_signal("secondsToExpire", state.student_code.signal_cloned().map(|student_code| { @@ -335,7 +335,7 @@ impl ShareAsset { .event(clone!(state => move |_: events::Click| { if let Some(student_code) = &*state.student_code.lock_ref() { let url = SETTINGS.get().unwrap_ji().remote_target.pages_url_iframe(); - let url = url + &Route::Kids(KidsRoute::StudentCode(Some(student_code.clone()))).to_string(); + let url = url + &Route::Kids(KidsRoute::StudentCode(Some(student_code.to_string()))).to_string(); clipboard::write_text(&url); ShareAsset::set_copied_mutable(state.copied_student_url.clone()); }; @@ -351,7 +351,7 @@ impl ShareAsset { })) .event(clone!(state => move|_: events::Click| { let student_code = state.student_code.get_cloned().unwrap_ji(); - clipboard::write_text(&student_code); + clipboard::write_text(&student_code.to_string()); ShareAsset::set_copied_mutable(state.copied_student_code.clone()); })) }), diff --git a/frontend/apps/crates/components/src/share_asset/state.rs b/frontend/apps/crates/components/src/share_asset/state.rs index ff932808d..4788b97a4 100644 --- a/frontend/apps/crates/components/src/share_asset/state.rs +++ b/frontend/apps/crates/components/src/share_asset/state.rs @@ -3,6 +3,7 @@ use std::rc::Rc; use awsm_web::loaders::helpers::AsyncLoader; use futures_signals::signal::Mutable; use shared::domain::asset::Asset; +use shared::domain::jig::codes::JigCode; use shared::domain::jig::TextDirection; use utils::asset::{ CoursePlayerOptions, JigPlayerOptions, PlaylistPlayerOptions, ResourceContentExt, @@ -15,7 +16,7 @@ use crate::qr_dialog::QrDialog; pub struct ShareAsset { pub active_popup: Mutable>, - pub student_code: Mutable>, + pub student_code: Mutable>, pub loader: AsyncLoader, pub asset: Asset, pub copied_embed: Mutable, diff --git a/frontend/apps/crates/entry/classroom/src/codes/jig_code_sessions/actions.rs b/frontend/apps/crates/entry/classroom/src/codes/jig_code_sessions/actions.rs index c68d36aea..f2a9266fd 100644 --- a/frontend/apps/crates/entry/classroom/src/codes/jig_code_sessions/actions.rs +++ b/frontend/apps/crates/entry/classroom/src/codes/jig_code_sessions/actions.rs @@ -18,12 +18,8 @@ use shared::{ }, }; use utils::{ - bail_on_err, date_formatters, - error_ext::ErrorExt, - js_wrappers::download_url, - prelude::ApiEndpointExt, - routes::{KidsRoute, Route}, - unwrap::UnwrapJiExt, + bail_on_err, date_formatters, error_ext::ErrorExt, js_wrappers::download_url, + prelude::ApiEndpointExt, unwrap::UnwrapJiExt, }; use wasm_bindgen::JsValue; use wasm_bindgen_futures::spawn_local; @@ -86,14 +82,25 @@ impl CodeSessions { pub fn show_qr_code(self: &Rc) { let state = self; - let qr_dialog = QrDialog::new( - Route::Kids(KidsRoute::StudentCode(Some(self.code.to_string()))), - self.code.to_string(), - QrDialogCallbacks::new(clone!(state => move || { - state.qr_dialog.set(None); - })), - ); - self.qr_dialog.set(Some(qr_dialog)); + if let Some(code_response) = state.code_response.lock_ref().as_ref() { + let qr_dialog = QrDialog::new_jig_code( + code_response.index, + state + .jig + .lock_ref() + .as_ref() + .unwrap() + .jig + .jig_data + .display_name + .clone(), + code_response.name.clone(), + QrDialogCallbacks::new(clone!(state => move || { + state.qr_dialog.set(None); + })), + ); + self.qr_dialog.set(Some(qr_dialog)); + } } fn generate_csv_string(&self) -> String { diff --git a/shared/rust/src/domain/jig/codes.rs b/shared/rust/src/domain/jig/codes.rs index b90307f55..72b11df0c 100644 --- a/shared/rust/src/domain/jig/codes.rs +++ b/shared/rust/src/domain/jig/codes.rs @@ -11,7 +11,7 @@ use crate::{api::endpoints::PathPart, domain::module::StableModuleId}; use super::{JigId, JigPlayerSettings}; /// Four-digit code identifying a Jig player session -#[derive(Serialize, Deserialize, Debug, Copy, Clone, PathPart)] +#[derive(Serialize, Deserialize, Debug, Copy, Clone, PathPart, PartialEq, Eq)] #[cfg_attr(feature = "backend", derive(sqlx::Type))] #[cfg_attr(feature = "backend", sqlx(transparent))] pub struct JigCode(pub i32);