Fix IO groups breaking upon editing (#2766)

* Fix IO groups breaking upon editing

* Emit change signal after group/ungroup
This commit is contained in:
Abdo 2023-10-23 02:43:31 +03:00 committed by GitHub
parent 9740393d72
commit 14940a617b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 35 additions and 14 deletions

View file

@ -59,11 +59,15 @@ message GetImageOcclusionNoteResponse {
string value = 2; string value = 2;
} }
message ImageOcclusion { message ImageOcclusionShape {
string shape = 1; string shape = 1;
repeated ImageOcclusionProperty properties = 2; repeated ImageOcclusionProperty properties = 2;
} }
message ImageOcclusion {
repeated ImageOcclusionShape shapes = 1;
}
message ImageOcclusionNote { message ImageOcclusionNote {
bytes image_data = 1; bytes image_data = 1;
repeated ImageOcclusion occlusions = 2; repeated ImageOcclusion occlusions = 2;

View file

@ -2,10 +2,12 @@
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html // License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
use std::borrow::Cow; use std::borrow::Cow;
use std::collections::HashMap;
use std::collections::HashSet; use std::collections::HashSet;
use std::fmt::Write; use std::fmt::Write;
use anki_proto::image_occlusion::get_image_occlusion_note_response::ImageOcclusion; use anki_proto::image_occlusion::get_image_occlusion_note_response::ImageOcclusion;
use anki_proto::image_occlusion::get_image_occlusion_note_response::ImageOcclusionShape;
use htmlescape::encode_attribute; use htmlescape::encode_attribute;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use nom::branch::alt; use nom::branch::alt;
@ -317,14 +319,20 @@ fn render_image_occlusion(text: &str, question_side: bool, active: bool, ordinal
} }
pub fn parse_image_occlusions(text: &str) -> Vec<ImageOcclusion> { pub fn parse_image_occlusions(text: &str) -> Vec<ImageOcclusion> {
parse_text_with_clozes(text) let mut occlusions: HashMap<u16, Vec<ImageOcclusionShape>> = HashMap::new();
.iter() for node in parse_text_with_clozes(text) {
.filter_map(|node| match node { if let TextOrCloze::Cloze(cloze) = node {
TextOrCloze::Cloze(cloze) if cloze.image_occlusion().is_some() => { if cloze.image_occlusion().is_some() {
parse_image_cloze(cloze.image_occlusion().unwrap()) if let Some(shape) = parse_image_cloze(cloze.image_occlusion().unwrap()) {
occlusions.entry(cloze.ordinal).or_default().push(shape);
} }
_ => None, }
}) }
}
occlusions
.values()
.map(|v| ImageOcclusion { shapes: v.to_vec() })
.collect() .collect()
} }

View file

@ -3,8 +3,8 @@
use std::fmt::Write; use std::fmt::Write;
use anki_proto::image_occlusion::get_image_occlusion_note_response::ImageOcclusion;
use anki_proto::image_occlusion::get_image_occlusion_note_response::ImageOcclusionProperty; use anki_proto::image_occlusion::get_image_occlusion_note_response::ImageOcclusionProperty;
use anki_proto::image_occlusion::get_image_occlusion_note_response::ImageOcclusionShape;
use htmlescape::encode_attribute; use htmlescape::encode_attribute;
use nom::bytes::complete::escaped; use nom::bytes::complete::escaped;
use nom::bytes::complete::is_not; use nom::bytes::complete::is_not;
@ -18,7 +18,7 @@ fn unescape(text: &str) -> String {
text.replace("\\:", ":") text.replace("\\:", ":")
} }
pub fn parse_image_cloze(text: &str) -> Option<ImageOcclusion> { pub fn parse_image_cloze(text: &str) -> Option<ImageOcclusionShape> {
if let Some((shape, _)) = text.split_once(':') { if let Some((shape, _)) = text.split_once(':') {
let mut properties = vec![]; let mut properties = vec![];
let mut remaining = &text[shape.len()..]; let mut remaining = &text[shape.len()..];
@ -36,7 +36,7 @@ pub fn parse_image_cloze(text: &str) -> Option<ImageOcclusion> {
}) })
} }
return Some(ImageOcclusion { return Some(ImageOcclusionShape {
shape: shape.to_string(), shape: shape.to_string(),
properties, properties,
}); });

View file

@ -200,6 +200,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{iconSize} {iconSize}
on:click={() => { on:click={() => {
tool.action(canvas); tool.action(canvas);
emitChangeSignal();
}} }}
> >
{@html tool.icon} {@html tool.icon}

View file

@ -18,9 +18,17 @@ export function extractShapesFromClozedField(
): ShapeOrShapes[] { ): ShapeOrShapes[] {
const output: ShapeOrShapes[] = []; const output: ShapeOrShapes[] = [];
for (const occlusion of occlusions) { for (const occlusion of occlusions) {
if (isValidType(occlusion.shape)) { const group: Shape[] = [];
const props = Object.fromEntries(occlusion.properties.map(prop => [prop.name, prop.value])); for (const shape of occlusion.shapes) {
output.push(buildShape(occlusion.shape, props)); if (isValidType(shape.shape)) {
const props = Object.fromEntries(shape.properties.map(prop => [prop.name, prop.value]));
group.push(buildShape(shape.shape, props));
}
}
if (group.length > 1) {
output.push(group);
} else {
output.push(group[0]);
} }
} }