chiark / gitweb /
layout wip and also a todo
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Fri, 27 Nov 2020 01:28:22 +0000 (01:28 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Fri, 27 Nov 2020 01:28:22 +0000 (01:28 +0000)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/accounts.rs
src/api.rs
src/bin/daemon-otter.rs
src/bin/otter.rs
src/cmdlistener.rs
src/commands.rs
src/gamestate.rs
src/session.rs

index 4c4743d5591f68058f428e97e8288707c9714544..789d019b623c8b988e11b4d2be255c4def73c8a0 100644 (file)
@@ -55,6 +55,7 @@ pub struct AccountRecord {
   pub nick: String,
   pub timezone: String,
   pub access: AccessRecord,
+  pub layout: PresentationLayout,
 }
 
 #[derive(Clone,Debug,Hash,Ord,PartialOrd,Eq,PartialEq)]
index 64632f31b93058e772b6604cba068b2ae7e99a79..44dddf9d9b0f7820bde670f47cee169bcab913cd 100644 (file)
@@ -36,6 +36,10 @@ impl PresentationLayout {
   }
 }
 
+impl Default for PresentationLayout {
+  fn default() -> Self { PL::Portrait }
+}
+
 pub struct AbbrevPresentationLayout(pub PresentationLayout);
 
 impl<'r> FromParam<'r> for AbbrevPresentationLayout {
index ab337ef4a5f7ee40cc3f7b807fbdfadd1519e656..78da71be729cf41e64de06c2248d4fe143cbed95 100644 (file)
@@ -63,19 +63,22 @@ struct LoadingRenderContext<'r> {
 #[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,
index c6967712b75343352036b7fa95891e85726ac620..bebb70a9868bc45c73d8455265943ecb9ba7d031 100644 (file)
@@ -21,6 +21,7 @@ type MR = MgmtResponse;
 type MGI = MgmtGameInstruction;
 type MGR = MgmtGameResponse;
 type TP = TablePermission;
+type PL = PresentationLayout;
 
 use argparse::action::ParseResult::Parsed;
 
@@ -65,6 +66,7 @@ struct MainOpts {
   account: AccountName,
   nick: Option<String>,
   timezone: Option<String>,
+  layout: Option<PresentationLayout>,
   access: Option<AccessOpt>,
   socket_path: String,
   verbose: i32,
@@ -255,6 +257,7 @@ fn main() {
     socket_path: Option<String>,
     nick: Option<String>,
     timezone: Option<String>,
+    layout: Option<PresentationLayout>,
     access: Option<AccessOpt>,
     verbose: i32,
     config_filename: Option<String>,
@@ -290,6 +293,20 @@ fn main() {
       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"],
@@ -330,7 +347,7 @@ fn main() {
   }, &|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 ||{
@@ -381,6 +398,7 @@ fn main() {
       access,
       nick,
       timezone,
+      layout,
       socket_path,
       verbose,
       superuser,
@@ -456,6 +474,7 @@ impl Conn {
       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),
     };
 
index 20acfe2f4ff876a19c579619162fad3b3e3cb8e2..691e238fad755900d81df397a039841c9ea961f5 100644 (file)
@@ -82,22 +82,28 @@ fn execute(cs: &mut CommandStream, cmd: MgmtCommand) -> MgmtResponse {
       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)?;
@@ -108,6 +114,7 @@ fn execute(cs: &mut CommandStream, cmd: MgmtCommand) -> MgmtResponse {
         }
         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)?;
@@ -321,6 +328,7 @@ fn execute_game_insn<'cs, 'igr, 'ig : 'igr>(
       let tz = tz_from_str(&timezone);
       let gpl = GPlayerState {
         nick: nick.to_string(),
+        layout: arecord.layout,
       };
       let ipl = IPlayerState {
         acctid,
index 047780242fc2415d86db7294da976ae455bf869f..1e08f92201a29b2ec37236ab0a7207ec39ff49b7 100644 (file)
@@ -44,6 +44,7 @@ pub struct AccountDetails {
   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
index b9395a4b00200ff749dd228b68dd7f75d0df257e..b4edba3ae20451718636d80b8e3c936b773fb056 100644 (file)
@@ -52,6 +52,7 @@ pub struct GameState {
 #[derive(Debug,Serialize,Deserialize,Clone)]
 pub struct GPlayerState {
   pub nick: String,
+  pub layout: PresentationLayout,
 }
 
 #[derive(Debug,Serialize,Deserialize)]
index f42babbbccc3d4fc428277748f5862a8188172ba..73e6dbecc8e67c7cc20fc1cb33007db55901614e 100644 (file)
@@ -56,12 +56,12 @@ struct SessionForm {
   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);
@@ -72,6 +72,7 @@ fn session(form : Json<SessionForm>, layout: PresentationLayout)
       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![];
@@ -101,6 +102,10 @@ fn session(form : Json<SessionForm>, layout: PresentationLayout)
     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);
@@ -196,7 +201,7 @@ fn session(form : Json<SessionForm>, layout: PresentationLayout)
       }).map_err(|e| InternalError::JSONEncode(e))?,
     };
     trace!("SessionRenderContext {:?}", &src);
-    (src, client)
+    (src, client, layout)
   };
   info!("rendering /_/session for {:?} {:?} {:?} {:?} {:?}",
         &player, client, &c.nick, &c.ctoken,