1//! Conflict pages and page versions as OneNote shows them.
2
3use crate::document::descendants;
4use onestore::{
5 ExGuid,
6 page::{Page, PageObject, PageParagraph, ParagraphContent},
7};
8
9/// OneNote's highlight for conflicting changes on a conflict page, COLORREF.
10pub const CONFLICTING: u32 = 0xd6d6ff;
11
12/// OneNote's highlight for what a page version changed since the version before it, COLORREF.
13pub const CHANGED: u32 = 0xd6ffd6;
14
15/// `page` with its conflict `objects` marked as OneNote shows a conflict page's: a band
16/// across each conflicting paragraph.
17pub fn highlighted(page: Page, objects: &[ExGuid]) -> Page {
18 banded(page, objects, CONFLICTING)
19}
20
21/// `version`, a page version, with the text it changed since `older`, the version before it,
22/// banded as OneNote shows it; all of it without one.
23pub fn changes(version: Page, older: Option<&Page>) -> Page {
24 let texts = |page: &Page| {
25 page.objects
26 .iter()
27 .flat_map(|object| match object {
28 PageObject::Outline(outline) => std::slice::from_ref(outline),
29 PageObject::Title(title) => title.outlines.as_slice(),
30 _ => &[],
31 })
32 .flat_map(|outline| descendants(&outline.paragraphs, None))
33 .filter_map(|(_, _, node)| match &node.content {
34 ParagraphContent::Text(text) => Some((text.id, text.text.text().to_owned())),
35 _ => None,
36 })
37 .collect::<Vec<_>>()
38 };
39 let before = older.map(texts).unwrap_or_default();
40 let changed: Vec<ExGuid> = texts(&version)
41 .into_iter()
42 .filter(|text| !before.contains(text))
43 .map(|(id, _)| id)
44 .collect();
45 banded(version, &changed, CHANGED)
46}
47
48fn banded(mut page: Page, objects: &[ExGuid], color: u32) -> Page {
49 fn mark(paragraphs: &mut [PageParagraph], objects: &[ExGuid], color: u32) {
50 for paragraph in paragraphs {
51 match &mut paragraph.content {
52 ParagraphContent::Table(table) => {
53 for cell in table.rows.iter_mut().flat_map(|row| &mut row.cells) {
54 mark(&mut cell.paragraphs, objects, color);
55 }
56 }
57 ParagraphContent::Text(text)
58 if objects.contains(&paragraph.id) || objects.contains(&text.id) =>
59 {
60 paragraph.format.highlight = Some(color);
61 }
62 _ => {}
63 }
64 }
65 }
66 for object in &mut page.objects {
67 match object {
68 PageObject::Outline(outline) => mark(&mut outline.paragraphs, objects, color),
69 PageObject::Title(title) => {
70 for outline in &mut title.outlines {
71 mark(&mut outline.paragraphs, objects, color);
72 }
73 }
74 _ => {}
75 }
76 }
77 page
78}