chiark / gitweb /
Landscape mode via url
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 26 Nov 2020 00:10:54 +0000 (00:10 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 26 Nov 2020 00:10:54 +0000 (00:10 +0000)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Cargo.lock.example
Cargo.toml
src/api.rs
src/bin/daemon-otter.rs
src/imports.rs
src/session.rs
templates/loading.tera
templates/script.ts

index c27d1cfacb2800edd10be06804f5b8fdbc7325f3..6b1e531da9cc8f2de0e0a0bc1e12c55c97fd54ec 100644 (file)
@@ -646,6 +646,15 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "heck"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
+dependencies = [
+ "unicode-segmentation",
+]
+
 [[package]]
 name = "hermit-abi"
 version = "0.1.17"
@@ -1152,6 +1161,7 @@ dependencies = [
  "serde_json",
  "serde_with",
  "slotmap",
+ "strum",
  "thiserror",
  "toml 0.5.7",
  "typetag",
@@ -1703,6 +1713,27 @@ version = "0.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
 
+[[package]]
+name = "strum"
+version = "0.20.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7318c509b5ba57f18533982607f24070a55d353e90d4cae30c467cdb2ad5ac5c"
+dependencies = [
+ "strum_macros",
+]
+
+[[package]]
+name = "strum_macros"
+version = "0.20.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149"
+dependencies = [
+ "heck",
+ "proc-macro2 1.0.24",
+ "quote 1.0.7",
+ "syn 1.0.48",
+]
+
 [[package]]
 name = "subtle"
 version = "1.0.0"
@@ -1987,6 +2018,12 @@ dependencies = [
  "tinyvec",
 ]
 
+[[package]]
+name = "unicode-segmentation"
+version = "1.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
+
 [[package]]
 name = "unicode-xid"
 version = "0.1.0"
index cc055521561b920465b878c8c9b8d210b225f626..9b580e5f364923c5da98983f70b00ba1df633dc2 100644 (file)
@@ -58,6 +58,7 @@ serde = { version = "1", features = ["derive","rc"] }
 serde_json = "1"
 serde_with = "1"
 slotmap = { version = "0.4", features = ['serde'] }
+strum = { version = "0.20", features = ['derive'] }
 thiserror = "1"
 toml = "0.5"
 typetag = "0.1.6"
index 77f11b4844b2ea53cfaa6b154c1d3e8c6218fc7c..621a814131d8d97906f76eadd4f3423a9ff906b0 100644 (file)
@@ -6,6 +6,28 @@ use crate::imports::*;
 
 type WRC = WhatResponseToClientOp;
 
+#[derive(Clone,Copy,Debug,Eq,PartialEq,Serialize,Deserialize,EnumString)]
+pub enum PresentationLayout {
+  Portrait,
+  Landscape,
+}
+
+impl<'r> FromParam<'r> for PresentationLayout {
+  type Error = strum::ParseError;
+  fn from_param(param: &'r RawStr) -> Result<Self, Self::Error> {
+    param.as_str().parse()
+  }
+}
+
+impl PresentationLayout {
+  pub fn template(self) -> &'static str {
+    match self {
+      PresentationLayout::Portrait => "session",
+      PresentationLayout::Landscape => "landscape",
+    }
+  }
+}
+
 #[derive(Debug,Serialize,Deserialize)]
 struct ApiPiece<O : ApiPieceOp> {
   ctoken : RawToken,
index a91ba444e75b56a7f04190533a05b736ef934be3..6b12c962ea29a748bed374b36aae66eabd8d1e6d 100644 (file)
@@ -57,13 +57,27 @@ impl<'r> FromParam<'r> for CheckedResourceLeaf {
 
 #[derive(Serialize,Debug)]
 struct LoadingRenderContext<'r> {
-  ptoken : &'r RawTokenVal,
+  ptoken: &'r RawTokenVal,
+  layout: PresentationLayout,
 }
 #[get("/")]
 #[throws(OE)]
-fn loading(ptoken: WholeQueryString) -> Template {
+fn loading_p(ptoken: WholeQueryString) -> Template {
+  loading(PresentationLayout::Portrait, ptoken)?
+}
+#[get("/l")]
+#[throws(OE)]
+fn loading_l(ptoken: WholeQueryString) -> Template {
+  loading(PresentationLayout::Landscape, ptoken)?
+}
+
+#[throws(OE)]
+fn loading(layout: PresentationLayout, ptoken: WholeQueryString) -> Template {
   if let Some(ptoken) = ptoken.0 {
-    let c = LoadingRenderContext { ptoken : RawTokenVal::from_str(ptoken) };
+    let c = LoadingRenderContext {
+      ptoken: RawTokenVal::from_str(ptoken),
+      layout,
+    };
     Template::render("loading",&c)
   } else {
     let c = FrontPageRenderContext { };
@@ -209,7 +223,8 @@ fn main() {
     .attach(Template::fairing())
     .manage(cors_state)
     .mount("/", routes![
-      loading,
+      loading_l,
+      loading_p,
       resource,
       updates,
     ])
index 6d4d575ed2c1a5de9aa6f1cb1ec0d5fca33cf25f..d53231217195c16ef2c8dc931dbd2a7796cc526c 100644 (file)
@@ -32,6 +32,7 @@ pub use std::mem;
 pub use std::os::unix;
 pub use std::time::Instant;
 pub use std::path::PathBuf;
+pub use std::string::ParseError;
 pub use std::os::unix::ffi::OsStrExt;
 pub use std::env;
 pub use std::process::exit;
@@ -111,6 +112,8 @@ pub use either::{Either,Left,Right};
 
 pub use if_chain::if_chain;
 
+pub use strum::EnumString;
+
 pub use crate::global::*;
 pub use crate::gamestate::*;
 pub use crate::pieces::*;
@@ -123,6 +126,7 @@ pub use crate::slotmap_slot_idx::*;
 pub use crate::cmdlistener::*;
 pub use crate::mgmtchannel::*;
 pub use crate::api::{Lens,TransparentLens,ApiPieceOpError};
+pub use crate::api::{PresentationLayout};
 pub use crate::utils::*;
 pub use crate::spec::*;
 pub use crate::debugreader::DebugReader;
index 736f5a797dc79154d6530d7be1fb771b3d40709e..b14e41709b1302e3dc284e107eb9dbc19a6a75b5 100644 (file)
@@ -53,8 +53,9 @@ struct DataLoadPlayer {
 struct SessionForm {
   ptoken : RawToken,
 }
-#[post("/_/session", format="json", data="<form>")]
-fn session(form : Json<SessionForm>) -> Result<Template,OE> {
+#[post("/_/session/<layout>", format="json", data="<form>")]
+fn session(form : Json<SessionForm>, layout: 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;
@@ -187,7 +188,7 @@ fn session(form : Json<SessionForm>) -> Result<Template,OE> {
         &player, client, &c.nick, &c.ctoken,
         iad.gref.lock().ok().as_ref().map(|ig| &**ig));
 
-  Ok(Template::render("session",&c))
+  Ok(Template::render(layout.template(),&c))
 }
 
 pub fn mount(rocket_instance: Rocket) -> Rocket {
index f011ede4c5f9f6be713cf3dca1b38824fff96ea4..ddd1ea0f20f5e602cc86b909860b9c3a8906c93d 100644 (file)
@@ -6,6 +6,7 @@
 <link rel="license" href="/_/libre">
 <script defer>let wasm_input = fetch('/_/wasm.wasm');</script>
 <script src="/_/wasm.js" defer></script>
+<script id="global-info" data-layout="{{ layout }}"></script>
 <script src="/_/script.js" defer></script>
 </head>
 <body id="loading_body">
index 2610224d295a18f06b682611f8cf6dd6601d3fd7..04e96116c93af53064ab248f5a06463e05f8d9e6 100644 (file)
@@ -87,6 +87,7 @@ type PieceErrorHandler = (piece: PieceId, p: PieceInfo, m: PieceOpError)
   => boolean;
 interface DispatchTable<H> { [key: string]: H };
 
+var globalinfo_elem : HTMLElement;
 var general_timeout : number = 10000;
 var messages : DispatchTable<MessageHandler> = Object();
 var pieceops : DispatchTable<PieceHandler> = Object();
@@ -1148,9 +1149,11 @@ var wasm_promise : Promise<any>;;
 
 function doload(){
   console.log('DOLOAD');
+  globalinfo_elem = document.getElementById('global-info')!;
+  let layout = globalinfo_elem!.dataset!.layout!;
   var elem = document.getElementById('loading_token')!;
   var ptoken = elem.dataset.ptoken;
-  xhr_post_then('/_/session'
+  xhr_post_then('/_/session/' + layout
                JSON.stringify({ ptoken : ptoken }),
                loaded);