Resolve clippy warnings
Some checks failed
Monorepo build / build-flake (push) Has been cancelled

Of which there are an incredible number...
This commit was merged in pull request #394.
This commit is contained in:
2026-02-12 09:09:18 -05:00
committed by savanni
parent 755b13b44d
commit d656cc968f
34 changed files with 192 additions and 308 deletions

View File

@@ -411,7 +411,7 @@ impl App {
request.credential,
)? {
Ok(user) => user,
Err(err) => return Ok(Err(err.into())),
Err(err) => return Ok(Err(err)),
};
match db.new_session(&user.id) {

View File

@@ -63,7 +63,7 @@ pub struct SetTabletopImageRequest {
macro_rules! identifier {
($name:ident) => {
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize)]
pub struct $name(String);
impl $name {
@@ -103,11 +103,13 @@ macro_rules! identifier {
}
identifier!(AuthenticationId);
identifier!(CardId);
identifier!(CharacterId);
identifier!(GameId);
identifier!(InvitationId);
identifier!(SceneId);
identifier!(SessionId);
identifier!(UserId);
identifier!(GameId);
identifier!(SceneId);
identifier!(InvitationId);
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct Invitation {
@@ -151,33 +153,6 @@ pub enum AuthResponse {
PasswordReset((SessionId, UserOverview)),
}
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct CharacterId(String);
impl CharacterId {
pub fn as_str(&self) -> &str {
&self.0
}
}
impl Default for CharacterId {
fn default() -> Self {
Self(format!("{}", Uuid::new_v4().hyphenated()))
}
}
impl From<&str> for CharacterId {
fn from(s: &str) -> Self {
Self(s.to_owned())
}
}
impl From<String> for CharacterId {
fn from(s: String) -> Self {
Self(s)
}
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
pub struct Charsheet {
pub id: CharacterId,
@@ -187,33 +162,6 @@ pub struct Charsheet {
pub data: Vec<u8>,
}
#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
pub struct CardId(String);
impl CardId {
pub fn as_str(&self) -> &str {
&self.0
}
}
impl Default for CardId {
fn default() -> Self {
Self(format!("{}", Uuid::new_v4().hyphenated()))
}
}
impl From<&str> for CardId {
fn from(s: &str) -> Self {
Self(s.to_owned())
}
}
impl From<String> for CardId {
fn from(s: String) -> Self {
Self(s)
}
}
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
pub enum Location {
#[default]

View File

@@ -146,7 +146,7 @@ impl Connection {
}
pub async fn config() -> Result<PwaConfig, ClientError> {
let response = Request::get(&format!("/api/config"))
let response = Request::get("/api/config")
.header("Content-Type", "application/json")
.send()
.await
@@ -159,7 +159,7 @@ impl Connection {
username: String,
password: String,
) -> Result<(Connection, UserOverview), ClientError> {
let request = Request::post(&format!("/api/auth"))
let request = Request::post("/api/auth")
.header("Content-Type", "application/json")
.body(
serde_wasm_bindgen::to_value(
@@ -189,7 +189,7 @@ impl Connection {
display_name: String,
password: String,
) -> Result<(), ClientError> {
let request = Request::post(&format!("/api/users"))
let request = Request::post("/api/users")
.header("Content-Type", "application/json")
.body(
serde_wasm_bindgen::to_value(
@@ -218,7 +218,7 @@ impl Connection {
user_name: String,
display_name: String,
) -> Result<StartRegisterPasskeyResponse, ClientError> {
let request = Request::post(&format!("/api/passkey-register/start"))
let request = Request::post("/api/passkey-register/start")
.header("Content-Type", "application/json")
.body(
serde_wasm_bindgen::to_value(
@@ -245,7 +245,7 @@ impl Connection {
user_id: UserId,
credential: RegisterPublicKeyCredential,
) -> Result<(), ClientError> {
let request = Request::post(&format!("/api/passkey-register/finish"))
let request = Request::post("/api/passkey-register/finish")
.header("Content-Type", "application/json")
.body(
serde_wasm_bindgen::to_value(
@@ -268,7 +268,7 @@ impl Connection {
}
pub async fn start_auth_with_passkey() -> Result<StartPasskeyAuthResponse, ClientError> {
let request = Request::post(&format!("/api/passkey-auth/start"))
let request = Request::post("/api/passkey-auth/start")
.header("Content-Type", "application/json");
handle_response(
@@ -284,7 +284,7 @@ impl Connection {
auth_id: AuthenticationId,
credential: PublicKeyCredential,
) -> Result<(Connection, UserOverview), ClientError> {
let request = Request::post(&format!("/api/passkey-auth/finish"))
let request = Request::post("/api/passkey-auth/finish")
.header("Content-Type", "application/json")
.body(
serde_wasm_bindgen::to_value(
@@ -337,7 +337,7 @@ impl Client for Connection {
}
async fn list_invitations(&self) -> Result<Vec<Invitation>, ClientError> {
let response: Response = Request::get(&format!("/api/invitations"))
let response: Response = Request::get("/api/invitations")
.header("Content-Type", "application/json")
.header(
"Authorization",
@@ -351,7 +351,7 @@ impl Client for Connection {
}
async fn create_invitation(&self, display_name: String) -> Result<Invitation, ClientError> {
let request = Request::put(&format!("/api/invitations"))
let request = Request::put("/api/invitations")
.header("Content-Type", "application/json")
.header(
"Authorization",
@@ -374,7 +374,7 @@ impl Client for Connection {
}
async fn get_self(&self) -> Result<UserOverview, ClientError> {
let response: Response = Request::get(&format!("/api/self"))
let response: Response = Request::get("/api/self")
.header("Content-Type", "application/json")
.header(
"Authorization",
@@ -388,7 +388,7 @@ impl Client for Connection {
}
async fn list_users(&self) -> Result<Vec<UserOverview>, ClientError> {
let response: Response = Request::get(&format!("/api/users"))
let response: Response = Request::get("/api/users")
.header("Content-Type", "application/json")
.header(
"Authorization",
@@ -570,7 +570,7 @@ impl Client for Connection {
if let Some(user_id) = filter.user_id {
query_params.append("user_id", user_id.as_str());
}
let query_str = format!("/api/characters?{}", query_params.to_string());
let query_str = format!("/api/characters?{}", query_params);
let response: Response = Request::get(&query_str)
.header("Content-Type", "application/json")
@@ -585,7 +585,7 @@ impl Client for Connection {
let sheets: Vec<Charsheet> = handle_response(response).await?;
Ok(sheets
.into_iter()
.flat_map(|sheet| Character::try_from(sheet))
.flat_map(Character::try_from)
.collect())
}

View File

@@ -67,7 +67,7 @@ pub fn CardElement(
let editing: UseStateHandle<bool> = use_state(|| *new_card);
use_effect_with(
(new_card.clone(), card.clone()),
(*new_card, card.clone()),
clone!((editing), move |(new_card, _)| {
editing.set(*new_card);
|| ()
@@ -197,17 +197,14 @@ fn EditingCard(
(on_save, on_cancel, title_ref, content_ref, new_card, card),
move |_| {
let mut card = card.clone();
match (
if let (Some(title), Some(content)) = (
title_ref.cast::<HtmlInputElement>(),
content_ref.cast::<HtmlInputElement>(),
) {
(Some(title), Some(content)) => {
card.title = Some(title.value());
card.content = content.value();
on_save.emit((new_card, card));
on_cancel.emit(());
}
_ => {}
card.title = Some(title.value());
card.content = content.value();
on_save.emit((new_card, card));
on_cancel.emit(());
}
}
));

View File

@@ -66,8 +66,6 @@ fn CharacterRow(
width: 10%;
);
let system_sheet = Character::try_from(sheet.clone()).unwrap();
let on_edit = use_callback((sheet.clone(), on_edit.clone()), |_, (sheet, on_edit)| {
on_edit.emit(sheet.id())
});
@@ -84,7 +82,7 @@ fn CharacterRow(
html! {
<Row class={classes!(style.clone())}>
{system_sheet.character_list_row()}
{sheet.character_list_row()}
<div class={edit_button_size.clone()}>
{edit_button}
</div>

View File

@@ -1,7 +1,7 @@
use yew::prelude::*;
pub trait DropMenuOption: PartialEq {
fn as_html(self: &Self, selected: bool) -> Html;
fn as_html(&self, selected: bool) -> Html;
}
#[derive(Properties, PartialEq)]

View File

@@ -1,13 +1,12 @@
use stylist::css;
use visions_types::{CharacterId, GameOverview, UserId, UserOverview};
use visions_types::{CharacterId, GameOverview, UserOverview};
use yew::prelude::*;
use crate::{
clone,
components::*,
design,
systems::{Character, SystemName, UnsupportedGameType, SYSTEMS},
types::GameEditTab,
systems::{Character, SystemName, SYSTEMS},
};
#[derive(Properties, PartialEq)]
@@ -61,6 +60,7 @@ pub fn NewGame(
}
}
/*
#[derive(Properties, PartialEq)]
pub struct EditGameProps_ {
tab: GameEditTab,
@@ -173,8 +173,7 @@ pub fn EditGame(
serde_json::from_str(&overview.system).map_err(|_| UnsupportedGameType);
let (players, unattached_users): (Vec<UserOverview>, Vec<UserOverview>) = users
.iter()
.map(|user| user.clone())
.iter().cloned()
.partition(|user| overview.players.contains(&user.id) || user.id == overview.gm);
let (gms, players): (Vec<UserOverview>, Vec<UserOverview>) =
@@ -259,6 +258,7 @@ pub fn AddRow(AddProps { user, on_add }: &AddProps) -> Html {
</Row>
}
}
*/
#[derive(Properties, PartialEq)]
pub struct ViewGameDetailsProps {
@@ -356,8 +356,6 @@ fn CharacterRow(
width: 10%;
);
let system_sheet = Character::try_from(sheet.clone()).unwrap();
let on_edit = use_callback((sheet.clone(), on_edit.clone()), |_, (sheet, on_edit)| {
on_edit.emit(sheet.id())
});
@@ -374,7 +372,7 @@ fn CharacterRow(
html! {
<Row class={classes!(design::border_invisible(), row_coloration.clone())}>
{system_sheet.character_list_row()}
{sheet.character_list_row()}
<div class={edit_button_size.clone()}>
{edit_button}
</div>

View File

@@ -2,7 +2,7 @@ use serde::Serialize;
use wasm_bindgen::JsValue;
use yew::prelude::*;
use crate::{clone, components::*};
use crate::components::*;
#[derive(Clone, PartialEq, Serialize)]
pub enum Role {
@@ -40,6 +40,7 @@ impl From<Role> for JsValue {
}
}
/*
#[derive(Properties, PartialEq)]
pub struct EditUserProps {
pub username: Option<String>,
@@ -69,7 +70,7 @@ pub fn EditUser(
move || email
});
let admin_field = use_state({
let admin = admin.clone();
let admin = *admin;
move || admin
});
@@ -86,10 +87,7 @@ pub fn EditUser(
let on_save_ = Callback::from(clone!(
(on_save, username_field, email_field, admin_field),
move |_| match ((*username_field).clone(), (*email_field).clone()) {
(Some(unf), Some(ef)) => on_save.emit((unf, ef, *admin_field, Role::Gm)),
_ => (),
}
move |_| if let (Some(unf), Some(ef)) = ((*username_field).clone(), (*email_field).clone()) { on_save.emit((unf, ef, *admin_field, Role::Gm)) }
));
html! {
@@ -108,3 +106,4 @@ pub fn EditUser(
</div>
}
}
*/

View File

@@ -53,10 +53,10 @@ pub fn CollapsableSidebar(
let child_container_style = css!(
overflow-y: auto;
);
let is_visible = use_state(|| visible.clone());
let is_visible = use_state(|| *visible);
let on_toggle_sidebar = use_callback(is_visible.clone(), |_, is_visible| {
let visible = (**is_visible).clone();
let visible = **is_visible ;
is_visible.set(!visible);
});

View File

@@ -142,7 +142,7 @@ pub fn DiscreteMeter(
<MeterStep
value={i}
state={state}
variant={variant.clone()} />
variant={*variant} />
}
})
.collect::<Html>()
@@ -236,7 +236,7 @@ fn MeterStep(
);
let on_mouse_enter = use_callback(
(value.clone(), on_hover.clone()),
(*value, on_hover.clone()),
|_: MouseEvent, (value, on_hover)| {
if let Some(ref on_hover) = on_hover {
on_hover.emit(*value);
@@ -265,12 +265,12 @@ fn MeterStep(
MeterVariant::Dots => dot_style,
};
let element = match state {
match state {
MeterStepState::Filled => bar_element(classes!(element_style, bar_step_filled)),
MeterStepState::Unfilled => bar_element(classes!(element_style)),
MeterStepState::Unavailable => bar_element(classes!(element_style, bar_step_unavailable)),
MeterStepState::Hover => bar_element(classes!(element_style, bar_step_hover)),
};
element
}
}

View File

@@ -67,10 +67,10 @@ impl GuageState {
}
fn show_operations(&self) -> bool {
match self.mode {
GuageMode::OperationsVisible | GuageMode::StartEditing(_) => true,
_ => false,
}
matches!(
self.mode,
GuageMode::OperationsVisible | GuageMode::StartEditing(_)
)
}
}
@@ -101,8 +101,8 @@ impl Reducible for GuageState {
},
GuageAction::ActivateEditing(opcode) => {
let text = match opcode {
OpCode::Add => format!("+ 1"),
OpCode::Subtract => format!("- 1"),
OpCode::Add => "+ 1".to_string(),
OpCode::Subtract => "- 1".to_string(),
OpCode::Set => format!("= {}", self.current),
};
Self {
@@ -218,9 +218,8 @@ pub fn Guage(
};
let on_focus = Callback::from(clone!(state, move |_| {
match state.mode {
GuageMode::Idle => state.dispatch(GuageAction::ShowOperations),
_ => {}
if let GuageMode::Idle = state.mode {
state.dispatch(GuageAction::ShowOperations)
}
}));

View File

@@ -45,7 +45,7 @@ pub fn ModalElement(
if *open {
let _ = modal.show_modal();
} else {
let _ = modal.close();
modal.close();
}
});

View File

@@ -58,7 +58,7 @@ pub fn SelectionButton<T: ListItem + Clone + 'static>(
let last_idx = options.len();
let buttons: Vec<Html> = options
.into_iter()
.iter()
.enumerate()
.map(|(idx, option)| {
let style = if idx == 0 {

View File

@@ -80,9 +80,9 @@ fn ListItemComponent<T: ListItem + Clone + 'static>(
}: &ListItemProps<T>,
) -> Html {
let classes = if *enabled {
format!("list-selector__item_enabled")
"list-selector__item_enabled".to_string()
} else {
format!("list-selector__item")
"list-selector__item".to_string()
};
let on_click: Callback<MouseEvent> =
Callback::from(clone!((on_select, item), move |_| on_select

View File

@@ -22,7 +22,6 @@ mod edit_game;
pub use edit_game::*;
mod edit_user;
pub use edit_user::*;
mod foundation;
pub use foundation::*;

View File

@@ -40,8 +40,7 @@ pub fn PlayerList(
);
let (players, unattached_users): (Vec<UserOverview>, Vec<UserOverview>) = users
.iter()
.map(|user| user.clone())
.iter().cloned()
.partition(|user| players.contains(&user.id));
html! {

View File

@@ -52,11 +52,8 @@ pub fn TabView(
let on_select = Callback::from(clone!(
(pages, current_page_id),
move |page_name: String| {
match pages.iter().find(|page| page.id() == page_name) {
Some(page) => {
current_page_id.set(page.id().to_string());
}
None => {}
if let Some(page) = pages.iter().find(|page| page.id() == page_name) {
current_page_id.set(page.id().to_string());
}
}
));

View File

@@ -1,4 +1,3 @@
use stylist::css;
use visions_types::Card;
use yew::prelude::*;

View File

@@ -1,6 +1,7 @@
use stylist::css;
use yew::prelude::*;
#[allow(unused)]
#[derive(PartialEq, Properties)]
pub struct TooltipProps {
#[prop_or_default]
@@ -11,6 +12,7 @@ pub struct TooltipProps {
pub children: Html,
}
#[allow(unused)]
#[function_component]
pub fn Tooltip(
TooltipProps {

View File

@@ -56,7 +56,7 @@ pub fn WebsocketProvider<C: Client + Clone + 'static>(
(client.clone(), game_id.clone(), on_message.clone()),
clone!(socket_state, move |(client, game_id, on_message)| {
let ws_client = client.connect_to_game(
&game_id,
game_id,
on_message.clone(),
Box::new(clone!(socket_state, move |_evt| {
log!("on close");

View File

@@ -131,7 +131,7 @@ pub fn border_default(hoverable: bool) -> Classes {
let hover_style = if hoverable {
css!(
:hover {
box-shadow: ${*&hover_shadow};
box-shadow: ${hover_shadow};
}
)
} else {

View File

@@ -61,13 +61,11 @@ impl AppState {
&self.base_url
}
/*
pub fn authenticated(&self) -> bool {
if let ConnectionState::Authenticated { .. } = self.connection {
true
} else {
false
}
matches!(self.connection, ConnectionState::Authenticated { .. })
}
*/
pub fn client(&self) -> Option<&Connection> {
if let ConnectionState::Authenticated { ref client, .. } = self.connection {
@@ -174,15 +172,14 @@ pub fn StateProvider(StateProviderProps { base_url, children }: &StateProviderPr
}
async fn hydrate_client(app_state: UseReducerHandle<AppState>) {
match web_sys::window() {
Some(window) => match window.session_storage() {
if let Some(window) = web_sys::window() {
match window.session_storage() {
Ok(Some(storage)) => hydrate_client_(&window, &storage, &app_state).await,
_ => {
// Need to convert this into an error that can then be displayed
error!("no session ID detected");
}
},
None => (),
}
}
}
@@ -195,7 +192,7 @@ async fn hydrate_client_(
let session_id: SessionId = session_id.into();
let client = Connection::new(session_id.clone());
match client.get_self().await {
Ok(user) => set_session(&app_state, client, user),
Ok(user) => set_session(app_state, client, user),
Err(ClientError::Unauthorized) => {
clear_session(app_state);
window

View File

@@ -29,12 +29,14 @@ pub struct Candela {
scars: Vec<String>,
}
/*
#[derive(Clone, PartialEq, Eq, Deserialize, Debug, Default)]
struct ActionGroup {
max_drives: u8,
drives: u8,
resistances: u8,
}
*/
#[derive(Clone, PartialEq, Eq, Deserialize, Serialize, Debug, Default)]
struct Action {
@@ -157,14 +159,13 @@ pub fn ActionGroupHeader(
sheet_editing,
}: &ActionGroupHeaderProperties,
) -> Html {
let on_update: Callback<u8> =
use_callback((state.clone(), name.clone()), |value, (state, name)| {
state.dispatch(SheetAction::UpdateDrive(name.clone(), value))
});
let on_update: Callback<u8> = use_callback((state.clone(), *name), |value, (state, name)| {
state.dispatch(SheetAction::UpdateDrive(*name, value))
});
let on_change_max: Callback<u8> =
use_callback((state.clone(), name.clone()), |value, (state, name)| {
state.dispatch(SheetAction::UpdateDriveMax(name.clone(), value))
use_callback((state.clone(), *name), |value, (state, name)| {
state.dispatch(SheetAction::UpdateDriveMax(*name, value))
});
html! {
@@ -207,14 +208,12 @@ pub fn ActionElement(
let gilded_symbol = if *gilded { "" } else { "" };
let editable = on_update.is_some();
let on_update: Callback<u8> = use_callback(
(name.clone(), on_update.clone()),
|value, (name, on_update)| {
let on_update: Callback<u8> =
use_callback((*name, on_update.clone()), |value, (name, on_update)| {
if let Some(on_update) = on_update {
on_update.emit((name.clone(), value));
on_update.emit((*name, value));
}
},
);
});
html! {
<div class={styles}>

View File

@@ -69,7 +69,7 @@ impl From<&SystemName> for JsValue {
impl From<SystemName> for JsValue {
fn from(r: SystemName) -> JsValue {
r.into()
JsValue::from(&r)
}
}
@@ -192,9 +192,10 @@ impl Character {
}
}
impl PartialOrd for Character {
/*
* impl PartialOrd for Character {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.name().cmp(&other.name()))
Some(self.name().cmp(other.name()))
}
}
@@ -203,6 +204,7 @@ impl Ord for Character {
self.name().cmp(other.name())
}
}
*/
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
pub enum CharacterDetails {
@@ -242,19 +244,19 @@ impl TryFrom<Charsheet> for Character {
}
}
impl Into<Charsheet> for Character {
fn into(self) -> Charsheet {
let system = match self.details {
impl From<Character> for Charsheet {
fn from(val: Character) -> Self {
let system = match val.details {
CharacterDetails::Candela(_) => SystemName::Candela,
CharacterDetails::Cypher(_) => SystemName::Cypher,
};
let data = serde_json::to_vec(&self.details).unwrap();
let data = serde_json::to_vec(&val.details).unwrap();
Charsheet {
id: self.id,
game_id: self.game_id,
user_id: self.user_id,
id: val.id,
game_id: val.game_id,
user_id: val.user_id,
system: serde_json::to_string(&system).unwrap(),
data,
}

View File

@@ -21,7 +21,7 @@ pub fn navigate_to(path: &str) {
Some(window) => {
window
.location()
.set_pathname(&path)
.set_pathname(path)
.expect("path navigation to succeed");
}
None => {

View File

@@ -1,6 +1,5 @@
use std::rc::Rc;
use gloo_console::log;
use jiff::Timestamp;
use stylist::css;
use visions_types::*;
@@ -16,6 +15,7 @@ use crate::{
};
#[derive(Clone, PartialEq)]
#[derive(Default)]
struct ViewState {
users: Vec<UserOverview>,
invitations: Vec<Invitation>,
@@ -23,16 +23,6 @@ struct ViewState {
invitation_modal_is_open: bool,
}
impl Default for ViewState {
fn default() -> Self {
Self {
users: vec![],
invitations: vec![],
error: None,
invitation_modal_is_open: false,
}
}
}
enum ViewStateAction {
SetUsers(Vec<UserOverview>),
@@ -54,7 +44,7 @@ impl Reducible for ViewState {
..(*self).clone()
},
ViewStateAction::SetInvitations(invitations) => Self {
invitations: invitations,
invitations,
error: None,
..(*self).clone()
},
@@ -90,7 +80,7 @@ impl Reducible for ViewState {
#[function_component]
pub fn Admin() -> Html {
let app_state = use_context::<UseReducerHandle<AppState>>().expect("app state not found");
let view_state: UseReducerHandle<ViewState> = use_reducer(|| ViewState::default());
let view_state: UseReducerHandle<ViewState> = use_reducer(ViewState::default);
let client = app_state.client();
@@ -148,7 +138,7 @@ struct UserListProps {
#[function_component]
fn UserList(UserListProps { users }: &UserListProps) -> Html {
let _user_list: UseStateHandle<Vec<UserOverview>> = use_state(|| vec![]);
let _user_list: UseStateHandle<Vec<UserOverview>> = use_state(std::vec::Vec::new);
html! {
<div>
@@ -179,8 +169,7 @@ pub fn InvitationList(
) -> Html {
let invitations: Vec<Html> = invitations
.iter()
.enumerate()
.map(|(idx, invitation)| {
.map(|invitation| {
html! {
<InvitationRow
invitation={invitation.clone()}

View File

@@ -43,31 +43,25 @@ fn populate_data<C: Client + Clone + 'static>(
id: CharacterId,
) {
wasm_bindgen_futures::spawn_local(async move {
match client {
Some(client) => match client.character(&id).await {
Ok(Ok(character)) => character_state.set(Some(character)),
Ok(Err(err)) => {
error!(format!("{:?}", err));
todo!()
}
Err(_) => todo!(),
},
None => {}
}
if let Some(client) = client { match client.character(&id).await {
Ok(Ok(character)) => character_state.set(Some(character)),
Ok(Err(err)) => {
error!(format!("{:?}", err));
todo!()
}
Err(_) => todo!(),
} }
})
}
fn save_character<C: Client + Clone + 'static>(client: Option<C>, character: Character) {
wasm_bindgen_futures::spawn_local(async move {
match client {
Some(client) => match client.update_character(character).await {
Ok(_) => {}
Err(err) => {
error!(format!("{:?}", err));
todo!();
}
},
None => {}
};
if let Some(client) = client { match client.update_character(character).await {
Ok(_) => {}
Err(err) => {
error!(format!("{:?}", err));
todo!();
}
} };
});
}

View File

@@ -4,7 +4,7 @@ use visions_types::*;
use yew::prelude::*;
use yew_router::prelude::*;
use crate::{clone, components::*, design, types::GameEditTab};
use crate::{clone, components::*, design};
#[derive(Properties, PartialEq)]
pub struct DesignProps {}
@@ -20,9 +20,8 @@ pub enum Page {
#[at("/design/card")]
Card,
#[at("/design/edit-game")]
EditGame,
// #[at("/design/edit-game")]
// EditGame,
#[at("/design/fields-labels")]
FieldsLabels,
@@ -54,7 +53,7 @@ impl ListItem for Page {
Page::Buttons => "buttons",
Page::Card => "card",
Page::Default => "",
Page::EditGame => "edit-game",
// Page::EditGame => "edit-game",
Page::FieldsLabels => "fields-labels",
Page::GameManagement => "game-management",
Page::Modal => "modal",
@@ -82,72 +81,61 @@ impl ListItem for Page {
match self {
Page::Buttons => {
html! { <div onclick={Callback::from({
let on_navigate = on_navigate.clone();
move |_| on_navigate(Page::Buttons)
})}>{"Buttons"}</div> }
}
Page::Card => {
html! { <div onclick={Callback::from({
let on_navigate = on_navigate.clone();
move |_| on_navigate(Page::Card)
})}>{"Card"}</div> }
}
Page::Default => {
html! { <div onclick={Callback::from({
let on_navigate = on_navigate.clone();
move |_| on_navigate(Page::Default)
})}>{"Default"}</div> }
}
Page::EditGame => {
html! { <div onclick={Callback::from({
let on_navigate = on_navigate.clone();
move |_| on_navigate(Page::EditGame)
})}>{"Edit Game"}</div> }
}
// Page::EditGame => {
// html! { <div onclick={Callback::from({
// move |_| on_navigate(Page::EditGame)
// })}>{"Edit Game"}</div> }
// }
Page::FieldsLabels => {
html! { <div onclick={Callback::from({
let on_navigate = on_navigate.clone();
move |_| on_navigate(Page::FieldsLabels)
})}>{"Fields and Labels"}</div> }
}
Page::GameManagement => {
html! { <div onclick={Callback::from({
let on_navigate = on_navigate.clone();
move |_| on_navigate(Page::GameManagement)
})}>{"Game Management"}</div> }
}
Page::Modal => {
html! { <div onclick={Callback::from({
let on_navigate = on_navigate.clone();
move |_| on_navigate(Page::Modal)
})}>{"Modal Dialogs"}</div> }
}
Page::Panel => {
html! { <div onclick={Callback::from({
let on_navigate = on_navigate.clone();
move |_| on_navigate(Page::Panel)
})}>{"Panel"}</div> }
}
Page::SemanticTokens => {
html! { <div onclick={Callback::from(
clone!(on_navigate, move |_| on_navigate(Page::SemanticTokens))
move |_| on_navigate(Page::SemanticTokens)
)}>{"Semantic Tokens"}</div> }
}
Page::Swatches => {
html! { <div onclick={Callback::from({
let on_navigate = on_navigate.clone();
move |_| on_navigate(Page::Swatches)
})}>{"Swatches"}</div> }
}
Page::Tabs => {
html! { <div onclick={Callback::from({
let on_navigate = on_navigate.clone();
move |_| on_navigate(Page::Tabs)
})}>{"Tabs"}</div> }
}
Page::UserManagement => {
html! { <div onclick={Callback::from({
let on_navigate = on_navigate.clone();
move |_| on_navigate(Page::UserManagement)
})}>{"User Management"}</div> }
}
@@ -231,7 +219,7 @@ fn switch(route: Page) -> Html {
Page::Buttons => html! { <ButtonsPage /> },
Page::Card => html! { <CardsPage /> },
Page::Default => html! { <SwatchPage /> },
Page::EditGame => html! { <EditGamePage /> },
// Page::EditGame => html! { <EditGamePage /> },
Page::FieldsLabels => html! { <FieldsLabelsPage /> },
Page::Modal => html! { <ModalPage /> },
Page::Panel => html! { <PanelPage /> },
@@ -265,7 +253,7 @@ fn switch(route: Page) -> Html {
Page::Modal,
Page::UserManagement,
Page::GameManagement,
Page::EditGame
// Page::EditGame
]} />
<div class="design__main">
{page}
@@ -287,6 +275,7 @@ pub fn Design(DesignProps {}: &DesignProps) -> Html {
enum SelectionOptions {
Passkey,
Password,
#[allow(clippy::upper_case_acronyms)]
SSO,
}
@@ -599,6 +588,7 @@ pub fn TabsPage() -> Html {
html! { <TabView pages={vec![page1, page2]}/> }
}
/*
#[function_component]
pub fn EditGamePage() -> Html {
let savanni = UserOverview {
@@ -659,3 +649,4 @@ pub fn EditGamePage() -> Html {
</>
}
}
*/

View File

@@ -1,5 +1,4 @@
use gloo_console::log;
use stylist::css;
use visions_types::*;
use yew::prelude::*;
@@ -7,7 +6,6 @@ use crate::{
client::{CharacterFilter, Client},
clone,
components::*,
design,
state::AppState,
systems::Character,
types::{GameEditTab, GAME_EDIT_TABS},
@@ -23,6 +21,7 @@ struct ViewState {
characters: Vec<Character>,
}
#[allow(clippy::enum_variant_names)]
enum ViewStateAction {
SetPage(GameEditTab),
SetGame(GameOverview),
@@ -114,7 +113,7 @@ pub struct GameDetailsViewProps {
#[function_component]
pub fn GameDetailsView(GameDetailsViewProps { id }: &GameDetailsViewProps) -> Html {
let app_state = use_context::<UseReducerHandle<AppState>>().expect("app state not found");
let state = use_reducer(|| ViewState::default());
let state = use_reducer(ViewState::default);
let actions: GameEditActions = game_details_actions(&app_state, &state);
@@ -127,19 +126,19 @@ pub fn GameDetailsView(GameDetailsViewProps { id }: &GameDetailsViewProps) -> Ht
match app_state.user() {
Some(user) => {
let overview = (*state).overview.as_ref();
let users: &Vec<UserOverview> = (*state).users.as_ref();
let characters: &Vec<Character> = (*state).characters.as_ref();
let overview = state.overview.as_ref();
let users: &Vec<UserOverview> = state.users.as_ref();
let characters: &Vec<Character> = state.characters.as_ref();
let editable = match overview {
Some(overview) => user.admin || overview.gm == user.id,
_ => false,
};
let gm: Option<UserOverview> = (*state)
let gm: Option<UserOverview> = state
.overview
.as_ref()
.map(|game| game.gm.clone())
.and_then(|gm_id| (*state).users.iter().find(|user| user.id == gm_id))
.and_then(|gm_id| state.users.iter().find(|user| user.id == gm_id))
.cloned();
let current_view = match (state.game_edit_tab.clone(), gm.clone()) {
@@ -150,9 +149,9 @@ pub fn GameDetailsView(GameDetailsViewProps { id }: &GameDetailsViewProps) -> Ht
/>
},
(GameEditTab::Players, Some(gm)) => html! {
(GameEditTab::Players, Some(_gm)) => html! {
<PlayerList
users={(*state).users.clone()}
users={state.users.clone()}
players={state.overview.clone().map(|overview| overview.players.iter().cloned().collect()).unwrap_or(vec![])}
on_add_player={actions.on_add_player}
on_remove_player={actions.on_remove_player} />
@@ -171,7 +170,7 @@ pub fn GameDetailsView(GameDetailsViewProps { id }: &GameDetailsViewProps) -> Ht
html! {
<div>
<Row>
<TextEntry placeholder="game name" value={(*overview).name.clone()} />
<TextEntry placeholder="game name" value={overview.name.clone()} />
<div>{format!("{}", overview.system.to_string())}</div>
</Row>
@@ -181,7 +180,7 @@ pub fn GameDetailsView(GameDetailsViewProps { id }: &GameDetailsViewProps) -> Ht
</Row>
<SelectionButton<GameEditTab>
selected={(*state).game_edit_tab.clone()}
selected={state.game_edit_tab.clone()}
options={Vec::from(GAME_EDIT_TABS.clone())}
on_change={change_page}
/>
@@ -220,24 +219,21 @@ fn populate_data<C: Client + Clone + 'static>(
game_id: GameId,
) {
wasm_bindgen_futures::spawn_local(async move {
match client {
Some(client) => {
let overview = client.game_overview(&game_id).await.unwrap();
state.dispatch(ViewStateAction::SetGame(overview));
if let Some(client) = client {
let overview = client.game_overview(&game_id).await.unwrap();
state.dispatch(ViewStateAction::SetGame(overview));
let users = client.list_users().await.unwrap();
state.dispatch(ViewStateAction::SetUsers(users));
let users = client.list_users().await.unwrap();
state.dispatch(ViewStateAction::SetUsers(users));
let characters = client
.characters(CharacterFilter {
game_id: Some(game_id),
user_id: None,
})
.await
.unwrap();
state.dispatch(ViewStateAction::SetCharacters(characters));
}
None => {}
let characters = client
.characters(CharacterFilter {
game_id: Some(game_id),
user_id: None,
})
.await
.unwrap();
state.dispatch(ViewStateAction::SetCharacters(characters));
}
})
}
@@ -248,17 +244,14 @@ fn add_player<C: Client + Clone + 'static>(
player_id: UserId,
) {
wasm_bindgen_futures::spawn_local(async move {
match (client, (*state).overview.clone()) {
(Some(client), Some(mut overview)) => {
match client.link_player_to_game(&overview.id, &player_id).await {
Ok(_) => {
overview.players.insert(player_id);
state.dispatch(ViewStateAction::SetGame(overview));
}
Err(err) => log!(format!("on_save failed: {:?}", err)),
if let (Some(client), Some(mut overview)) = (client, state.overview.clone()) {
match client.link_player_to_game(&overview.id, &player_id).await {
Ok(_) => {
overview.players.insert(player_id);
state.dispatch(ViewStateAction::SetGame(overview));
}
Err(err) => log!(format!("on_save failed: {:?}", err)),
}
_ => {}
}
})
}
@@ -269,20 +262,17 @@ fn remove_player<C: Client + Clone + 'static>(
player_id: UserId,
) {
wasm_bindgen_futures::spawn_local(async move {
match (client, (*state).overview.clone()) {
(Some(client), Some(mut overview)) => {
match client
.unlink_player_from_game(&overview.id, &player_id)
.await
{
Ok(_) => {
let _ = overview.players.remove(&player_id);
state.dispatch(ViewStateAction::SetGame(overview));
}
Err(err) => log!(format!("on_save failed: {:?}", err)),
if let (Some(client), Some(mut overview)) = (client, state.overview.clone()) {
match client
.unlink_player_from_game(&overview.id, &player_id)
.await
{
Ok(_) => {
let _ = overview.players.remove(&player_id);
state.dispatch(ViewStateAction::SetGame(overview));
}
Err(err) => log!(format!("on_save failed: {:?}", err)),
}
_ => {}
}
})
}
@@ -292,14 +282,13 @@ fn create_character<C: Client + Clone + 'static>(
state: UseReducerHandle<ViewState>,
) {
wasm_bindgen_futures::spawn_local(async move {
match (client, (*state).overview.clone()) {
(Some(client), Some(overview)) => match client.create_character(&overview.id).await {
if let (Some(client), Some(overview)) = (client, state.overview.clone()) {
match client.create_character(&overview.id).await {
Ok(id) => {
navigate_to(&format!("/characters/{}", id.as_str()));
}
Err(err) => log!(format!("create character failed: {:?}", err)),
},
_ => {}
}
}
})
}

View File

@@ -18,7 +18,7 @@ pub struct GameViewProps {
pub fn GameView(GameViewProps { game_id }: &GameViewProps) -> Html {
let app_state: UseReducerHandle<AppState> = use_context().expect("app state not found");
let game_state: UseStateHandle<Option<GameOverview>> = use_state(|| None);
let _user_list: UseStateHandle<Vec<UserOverview>> = use_state(|| vec![]);
let _user_list: UseStateHandle<Vec<UserOverview>> = use_state(std::vec::Vec::new);
let client = app_state.client().cloned();
use_effect_with(
@@ -84,12 +84,9 @@ fn request_game_overview(
game_state: UseStateHandle<Option<GameOverview>>,
) {
wasm_bindgen_futures::spawn_local(async move {
match client {
Some(client) => match client.game_overview(&game_id).await {
Ok(game) => game_state.set(Some(game)),
Err(_) => todo!(),
},
None => {}
}
if let Some(client) = client { match client.game_overview(&game_id).await {
Ok(game) => game_state.set(Some(game)),
Err(_) => todo!(),
} }
})
}

View File

@@ -1,4 +1,4 @@
use gloo_console::{error, log};
use gloo_console::error;
use stylist::css;
use visions_types::{
Card, CardId, GameId, GameMessage, GameOverview, GameRequest, Location, SceneId,
@@ -185,7 +185,7 @@ impl Reducible for ViewState {
ViewStateAction::CardNew => Self {
sidebar_card: Some(Card {
id: CardId::default(),
game_id: (*self).game_id.clone(),
game_id: self.game_id.clone(),
location: Location::GM,
title: Some("untitled".to_owned()),
content: "".to_owned(),
@@ -283,9 +283,8 @@ fn View(
let on_select_card = Callback::from(clone!(state, move |card_id| {
let card_id = CardId::from(card_id);
match state.cards.iter().find(|card| card.id == card_id) {
Some(card) => state.dispatch(ViewStateAction::OpenCard(card.clone())),
None => {}
if let Some(card) = state.cards.iter().find(|card| card.id == card_id) {
state.dispatch(ViewStateAction::OpenCard(card.clone()))
}
}));
@@ -325,7 +324,7 @@ fn View(
};
let mut characters = state.characters.clone();
characters.sort_by(|a, b| a.cmp(b));
characters.sort_by(|l, r| l.name().cmp(r.name()));
let pc_elements = characters
.iter()
@@ -597,6 +596,6 @@ fn move_card_to(
let card = view_state.cards.iter().find(|c| c.id == card_id).cloned();
if let Some(mut card) = card {
card.location = dest;
let _ = socket.send(GameRequest::CardUpdate(card));
socket.send(GameRequest::CardUpdate(card));
}
}

View File

@@ -4,7 +4,7 @@ use visions_types::*;
use yew::prelude::*;
use crate::{
client::{Client, ClientError, Connection},
client::{Client, Connection},
clone,
components::*,
systems::SystemName,
@@ -13,12 +13,6 @@ use crate::{
AppState,
};
#[derive(Properties, PartialEq)]
pub struct LandingProps {
#[prop_or(Callback::from(|_| {}))]
pub on_add_user: Callback<()>,
}
#[function_component]
pub fn Landing() -> Html {
let app_state = use_context::<UseReducerHandle<AppState>>().expect("app state not found");
@@ -47,9 +41,9 @@ struct GameListProps<C: Client + Clone> {
#[function_component]
fn GameList<C: Client + Clone + 'static>(GameListProps { client }: &GameListProps<C>) -> Html {
let game_list: UseStateHandle<Vec<GameOverview>> = use_state(|| vec![]);
let game_list: UseStateHandle<Vec<GameOverview>> = use_state(std::vec::Vec::new);
let user_ref: UseStateHandle<Option<UserOverview>> = use_state(|| None);
let users_ref: UseStateHandle<Vec<UserOverview>> = use_state(|| vec![]);
let users_ref: UseStateHandle<Vec<UserOverview>> = use_state(std::vec::Vec::new);
let modal_title: UseStateHandle<String> = use_state(|| "".to_owned());
let modal_content: UseStateHandle<Option<Html>> = use_state(|| None);

View File

@@ -223,7 +223,7 @@ async fn login_with_passkey() -> Result<(Connection, UserOverview), ClientError>
.unwrap();
let credential: web_sys::PublicKeyCredential =
web_sys::PublicKeyCredential::from(js_val).into();
web_sys::PublicKeyCredential::from(js_val);
let credential = webauthn_rs_proto::PublicKeyCredential::from(credential);
Connection::finish_auth_with_passkey(auth_response.auth_id, credential).await

View File

@@ -1,20 +1,18 @@
use gloo_console::log;
use stylist::css;
use visions_types::{
InvitationId, StartPasskeyAuthResponse, StartRegisterPasskeyRequest,
InvitationId,
StartRegisterPasskeyResponse,
};
use webauthn_rs_proto::RegisterPublicKeyCredential;
use yew::prelude::*;
use crate::{
client::{Client, ClientError, Connection},
client::{ClientError, Connection},
clone,
components::*,
design,
state::AppState,
utils::navigate_to,
views::Login,
};
#[derive(PartialEq, Properties)]
@@ -58,7 +56,7 @@ pub fn NewUser(NewUserProps { id }: &NewUserProps) -> Html {
log!(format!("NewUser: {:?} {:?}", is_valid, error));
let form = match ((*is_valid).clone(), (*error).clone()) {
let form = match ((*is_valid), (*error).clone()) {
(None, None) => html! { <div>{"Validating invitation"}</div> },
(Some(true), None) => html! {
<PanelElement title="Welcome to Visions VTT">