pub nick: String,
pub timezone: String,
pub access: AccessRecord,
+ pub layout: PresentationLayout,
}
#[derive(Clone,Debug,Hash,Ord,PartialOrd,Eq,PartialEq)]
}
}
+impl Default for PresentationLayout {
+ fn default() -> Self { PL::Portrait }
+}
+
pub struct AbbrevPresentationLayout(pub PresentationLayout);
impl<'r> FromParam<'r> for AbbrevPresentationLayout {
#[get("/")]
#[throws(OE)]
fn loading_p(ptoken: WholeQueryString) -> Template {
- loading(PresentationLayout::Portrait, ptoken)?
+ loading(None, ptoken)?
}
// xxx also do p, make it an account/player property
#[get("/<layout>")]
#[throws(OE)]
fn loading_l(layout: AbbrevPresentationLayout, ptoken: WholeQueryString)
-> Template {
- loading(layout.0, ptoken)?
+ loading(Some(layout.0), ptoken)?
}
#[throws(OE)]
-fn loading(layout: PresentationLayout, ptoken: WholeQueryString) -> Template {
+fn loading(layout: Option<PresentationLayout>, ptoken: WholeQueryString)
+ -> Template
+{
if let Some(ptoken) = ptoken.0 {
+ // xxx do something sensible if token mangled
let c = LoadingRenderContext {
ptoken: RawTokenVal::from_str(ptoken),
layout,
type MGI = MgmtGameInstruction;
type MGR = MgmtGameResponse;
type TP = TablePermission;
+type PL = PresentationLayout;
use argparse::action::ParseResult::Parsed;
account: AccountName,
nick: Option<String>,
timezone: Option<String>,
+ layout: Option<PresentationLayout>,
access: Option<AccessOpt>,
socket_path: String,
verbose: i32,
socket_path: Option<String>,
nick: Option<String>,
timezone: Option<String>,
+ layout: Option<PresentationLayout>,
access: Option<AccessOpt>,
verbose: i32,
config_filename: Option<String>,
StoreOption,
"display times in timezone TZ (Olson timezone name) \
(default is to use server's default timezone)");
+ let mut layout = ap.refer(&mut rma.layout);
+ layout.add_option(
+ &["--layout-portrait"],
+ StoreConst(Some(PL::Portrait)),
+ "set account to display in portrait (by default)");
+ layout.add_option(
+ &["--layout-landscape"],
+ StoreConst(Some(PL::Landscape)),
+ "set account to display in landscape (by default)");
+ layout.add_option(
+ &["--layout-default"],
+ StoreConst(None),
+ "do not modify default layout");
+
let mut access = ap.refer(&mut rma.access);
access.add_option(&["--url-on-stdout"],
}, &|RawMainArgs {
account, nick, timezone,
access, socket_path, verbose, config_filename, superuser,
- subcommand, subargs, spec_dir,
+ subcommand, subargs, spec_dir, layout,
}|{
let config = Thunk::<Result<(Arc<ServerConfig>,String),APE>,_>::new(
move ||{
access,
nick,
timezone,
+ layout,
socket_path,
verbose,
superuser,
account: ma.account.clone(),
nick: wantup.u(&ma.nick),
timezone: wantup.u(&ma.timezone),
+ layout: wantup.u(&ma.layout),
access: wantup.u(&ma.access).map(Into::into),
};
Fine
},
- CreateAccount(AccountDetails { account, nick, timezone, access }) => {
+ CreateAccount(AccountDetails {
+ account, nick, timezone, access, layout
+ }) => {
let mut ag = AccountsGuard::lock();
let auth = authorise_for_account(cs, &ag, &account)?;
let access = cs.accountrecord_from_spec(access)?
.unwrap_or_else(|| AccessRecord::new_unset());
let nick = nick.unwrap_or_else(|| account.to_string());
let account = account.to_owned().into();
+ let layout = layout.unwrap_or_default();
let record = AccountRecord {
account, nick, access,
timezone: timezone.unwrap_or_default(),
+ layout,
};
ag.insert_entry(record, auth)?;
Fine
}
- UpdateAccount(AccountDetails { account, nick, timezone, access }) => {
+ UpdateAccount(AccountDetails {
+ account, nick, timezone, access, layout
+ }) => {
let mut ag = AccountsGuard::lock();
let mut games = games_lock();
let auth = authorise_for_account(cs, &ag, &account)?;
}
update_from(nick, &mut record.nick );
update_from(timezone, &mut record.timezone);
+ update_from(layout, &mut record.layout );
/*
if let Some(new_timezone) = timezone {
let ipr = ig.iplayers.byid_mut(player)?;
let tz = tz_from_str(&timezone);
let gpl = GPlayerState {
nick: nick.to_string(),
+ layout: arecord.layout,
};
let ipl = IPlayerState {
acctid,
pub account: AccountName,
pub nick: Option<String>,
pub timezone: Option<String>,
+ pub layout: Option<PresentationLayout>,
#[serde(flatten)]
pub access: Option<Box<dyn PlayerAccessSpec>>,
// pub invite: Acl<AccountPerm>, todo
#[derive(Debug,Serialize,Deserialize,Clone)]
pub struct GPlayerState {
pub nick: String,
+ pub layout: PresentationLayout,
}
#[derive(Debug,Serialize,Deserialize)]
ptoken : RawToken,
}
#[post("/_/session/<layout>", format="json", data="<form>")]
-fn session(form : Json<SessionForm>, layout: PresentationLayout)
+fn session(form : Json<SessionForm>, layout: Option<PresentationLayout>)
-> Result<Template,OE> {
// make session in this game, log a message to other players
let iad = lookup_token(form.ptoken.borrow())?;
let player = iad.ident;
- let (c, client) = {
+ let (c, client, layout) = {
let mut ig = iad.gref.lock()?;
let cl = Client { player, lastseen: Instant::now() };
let client = ig.clients.insert(cl);
acctid: iad.acctid,
};
let ctoken = record_token(&mut ig, ciad)?;
+ ig.save_game_later(); // in case we changed anything eg gpl.layout
let ig = &mut *ig;
let mut uses = vec![];
let gpl = ig.gs.players.byid_mut(player)?;
let pr = ig.iplayers.byid(player)?;
let tz = &pr.ipl.tz;
+ if let Some(layout) = layout {
+ gpl.layout = layout;
+ }
+ let layout = gpl.layout;
let mut pieces : Vec<_> = ig.gs.pieces.iter().collect();
pieces.sort_by_key(|(_,pr)| &pr.zlevel);
}).map_err(|e| InternalError::JSONEncode(e))?,
};
trace!("SessionRenderContext {:?}", &src);
- (src, client)
+ (src, client, layout)
};
info!("rendering /_/session for {:?} {:?} {:?} {:?} {:?}",
&player, client, &c.nick, &c.ctoken,