From: Ian Jackson Date: Sat, 20 Mar 2021 14:03:19 +0000 (+0000) Subject: updates: New "PreparedUpdateEntry_Image" X-Git-Tag: otter-0.5.0~672 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=2c5e680f4c87f930150209a7111f7e30ad704eb4;p=otter.git updates: New "PreparedUpdateEntry_Image" This allows server code to just update the SVG without causing cseq updates, conflicts, etc. Signed-off-by: Ian Jackson --- diff --git a/src/updates.rs b/src/updates.rs index 25be6382..265ae6a5 100644 --- a/src/updates.rs +++ b/src/updates.rs @@ -8,6 +8,8 @@ use crate::prelude::*; #[allow(non_camel_case_types)] type PUE_P = PreparedUpdateEntry_Piece; #[allow(non_camel_case_types)] type TUE_P<'u> = TransmitUpdateEntry_Piece<'u>; +#[allow(non_camel_case_types)] type PUE_I = PreparedUpdateEntry_Image; +#[allow(non_camel_case_types)] type TUE_I<'u> = TransmitUpdateEntry_Image<'u>; // ---------- newtypes, type aliases, basic definitions ---------- @@ -52,6 +54,7 @@ pub struct PreparedUpdate { #[derive(Debug)] pub enum PreparedUpdateEntry { Piece(PreparedUpdateEntry_Piece), + Image(PreparedUpdateEntry_Image), SetTableSize(Pos), SetTableColour(Colour), SetLinks(Arc), @@ -75,10 +78,22 @@ pub struct PreparedUpdateEntry_Piece { ops: SecondarySlotMap, } +pub type PreparedPieceUpdate = PreparedPieceUpdateGeneral< + PieceUpdateOp + >; + +#[allow(non_camel_case_types)] #[derive(Debug,Clone)] -pub struct PreparedPieceUpdate { +pub struct PreparedUpdateEntry_Image { + ims: SecondarySlotMap>, +} + +#[derive(Debug,Clone)] +pub struct PreparedPieceUpdateGeneral { piece: VisiblePieceId, - op: PieceUpdateOp, + op: U, } #[derive(Debug,Clone,Serialize)] @@ -93,11 +108,36 @@ pub struct PreparedPieceState { pub uos: Vec, } +#[derive(Debug,Clone,Serialize)] +pub struct PreparedPieceImage { + pub svg: Html, + pub uos: Vec, +} + #[derive(Serialize,Debug)] pub struct DataLoadPlayer { dasharray: Html, } +pub trait JsonLen { + fn json_len(&self) -> usize; +} + +#[ext] +impl SecondarySlotMap { + fn json_len(&self, player: PlayerId) -> usize { + if let Some(t) = self.get(player) { + 50 + t.json_len() + } else { + 50 + } + } +} + +impl JsonLen for Html { + fn json_len(&self) -> usize { self.0.as_bytes().len() } +} + // ---------- piece updates ---------- #[derive(Debug,Clone,Copy,Serialize)] @@ -163,6 +203,7 @@ enum TransmitUpdateEntry<'u> { svg: Option<&'u Html>, // IsResponseToClientOp::UpdateSvg }, Piece(TransmitUpdateEntry_Piece<'u>), + Image(TransmitUpdateEntry_Image<'u>), RecordedUnpredictable { piece: VisiblePieceId, cseq: ClientSequence, @@ -194,6 +235,13 @@ struct TransmitUpdateEntry_Piece<'u> { op: PieceUpdateOp<&'u PreparedPieceState, &'u ZLevel>, } +#[allow(non_camel_case_types)] +#[derive(Debug,Serialize)] +struct TransmitUpdateEntry_Image<'u> { + piece: VisiblePieceId, + im: &'u PreparedPieceImage, +} + #[derive(Debug,Serialize)] struct FormattedLogEntry<'u> { when: String, @@ -295,16 +343,40 @@ impl PreparedUpdate { impl PreparedUpdateEntry_Piece { pub fn json_len(&self, player: PlayerId) -> usize { - let PUE_P { ref ops, .. } = self; - if let Some(op) = ops.get(player) { - 50 + - op.op.new_state().map(|x| x.svg.0.as_bytes().len()).unwrap_or(0) - } else { - 50 - } + 50 + self.ops.json_len(player) + } +} + +impl JsonLen for PreparedPieceUpdateGeneral { + fn json_len(&self) -> usize { self.op.json_len() } +} + +impl JsonLen for PieceUpdateOp { + fn json_len(&self) -> usize { + self.new_state().map(|x| x.json_len()).unwrap_or(0) + } +} + +impl PreparedUpdateEntry_Image { + fn json_len(&self, player: PlayerId) -> usize { + self.ims.json_len(player) } } +impl JsonLen for PreparedPieceState { + fn json_len(&self) -> usize { self.svg.json_len() + self.uos.json_len() } +} + +impl JsonLen for PreparedPieceImage { + fn json_len(&self) -> usize { self.svg.json_len() + self.uos.json_len() } +} +impl JsonLen for Vec { + fn json_len(&self) -> usize { self.iter().map(|x| x.json_len() + 10).sum() } +} +impl JsonLen for UoDescription { + fn json_len(&self) -> usize { self.desc.json_len() + 50 } +} + impl PreparedUpdateEntry { pub fn json_len(&self, player: PlayerId) -> usize { use PreparedUpdateEntry::*; @@ -312,6 +384,9 @@ impl PreparedUpdateEntry { Piece(op) => { op.json_len(player) } + Image(ims) => { + ims.json_len(player) + } Log(logent) => { logent.logent.html.0.as_bytes().len() * 28 } @@ -679,6 +754,12 @@ impl PreparedUpdate { Some(TUE_P { piece, op: op.map_ref() }) } + fn pue_image_to_tue_i(pue_i: &PUE_I, player: PlayerId) -> Option { + let im = pue_i.ims.get(player)?; + let PreparedPieceUpdateGeneral { piece, ref op } = *im; + Some(TUE_I { piece, im: op }) + } + fn pue_piece_to_tue(pue_p: &PUE_P, player: PlayerId, dest: ClientId) -> Option { let PUE_P { by_client, ref ops } = *pue_p; @@ -723,6 +804,12 @@ impl PreparedUpdate { _ => continue, } } + &PUE::Image(ref pue_i) => { + match pue_image_to_tue_i(pue_i, player) { + Some(tue) => TUE::Image(tue), + _ => continue, + } + } PUE::Log(logent) => { TUE::Log((&tz, &logent)) } diff --git a/templates/script.ts b/templates/script.ts index f167d67e..f971fe63 100644 --- a/templates/script.ts +++ b/templates/script.ts @@ -1055,16 +1055,21 @@ piece_error_handlers.PosOffTable = function() piece_error_handlers.Conflict = function() { return true ; } -function piece_modify(piece: PieceId, p: PieceInfo, info: PreparedPieceState, - conflict_expected: boolean) { +function piece_modify_image(piece: PieceId, p: PieceInfo, + info: PreparedPieceImage) { p.delem.innerHTML = info.svg; p.pelem= piece_element('piece',piece)!; + p.uos = info.uos; +} + +function piece_modify(piece: PieceId, p: PieceInfo, info: PreparedPieceState, + conflict_expected: boolean) { + piece_modify_image(piece, p, info); p.uelem.setAttributeNS(null, "x", info.pos[0]+""); p.uelem.setAttributeNS(null, "y", info.pos[1]+""); p.held = info.held; p.pinned = info.pinned; p.angle = info.angle; - p.uos = info.uos; piece_set_zlevel(piece,p, (oldtop_piece)=>{ p.z = info.z; p.zg = info.zg; @@ -1075,6 +1080,26 @@ function piece_modify(piece: PieceId, p: PieceInfo, info: PreparedPieceState, console.log('MODIFY DONE'); } +type PreparedPieceImage = { + svg: string, + uos: UoDescription[], +} + +type TransmitUpdateEntry_Image = { + piece: PieceId, + im: PreparedPieceImage, +}; + +messages.Image = function(j: TransmitUpdateEntry_Image) { + console.log('IMAGE UPDATE ',j) + var piece = j.piece; + let p = pieces[piece]!; + piece_modify_image(piece, p, j.im); + redisplay_ancillaries(piece,p); + recompute_keybindings(); + console.log('IMAGE DONE'); +} + /* pieceops.Insert = function (piece: PieceId, p: null,