| author | |
| committer | |
| log | 678a46da0816b22d6b37cd361abf395870595796 |
| tree | 103a141a38b8f394a055b5e20f7009207597b104 |
| parent | f4abeb10328178d4685cc9788c296516e6b186a6 |
| signature | Signed by SSH key SHA256:52mNGHRsVFBDED9IAX5pe+LRWUefqTbxEReunq21QvU |
In a dark appearance with Pages Match UI Theme off, the locked section's notice
drew the dark theme's light text on the light page, and the welcome and empty
notebook notices sat on the chrome's surfaces, which a translucent backdrop
lets the desktop show through. They now fill with the page's colour and build
their text and buttons in the theme matching it: the light theme's on white
pages.
Fixes #67.
Assisted-by: claude-opus-5.53 files changed, 30 insertions(+), 14 deletions(-)
crates/snowbound/src/main.rs+17-3| ... | @@ -1474,7 +1474,7 @@ impl State { | ... | @@ -1474,7 +1474,7 @@ impl State { |
| 1474 | && self.locked.is_none(); | 1474 | && self.locked.is_none(); |
| 1475 | self.toolbar(&theme, !welcome)?; | 1475 | self.toolbar(&theme, !welcome)?; |
| 1476 | if welcome { | 1476 | if welcome { |
| 1477 | self.welcome(&theme); | 1477 | self.welcome(); |
| 1478 | return Ok((section, Id::ROOT, None)); | 1478 | return Ok((section, Id::ROOT, None)); |
| 1479 | } | 1479 | } |
| 1480 | self.ui.open( | 1480 | self.ui.open( |
| ... | @@ -1704,7 +1704,7 @@ impl State { | ... | @@ -1704,7 +1704,7 @@ impl State { |
| 1704 | recycle::bar(&mut self.ui); | 1704 | recycle::bar(&mut self.ui); |
| 1705 | } | 1705 | } |
| 1706 | if self.session.is_none() && self.locked.is_some() { | 1706 | if self.session.is_none() && self.locked.is_some() { |
| 1707 | self.locked_page(&theme); | 1707 | self.locked_page(); |
| 1708 | self.ui.close(); | 1708 | self.ui.close(); |
| 1709 | self.ui.close(); | 1709 | self.ui.close(); |
| 1710 | self.ui.close(); | 1710 | self.ui.close(); |
| ... | @@ -1717,7 +1717,7 @@ impl State { | ... | @@ -1717,7 +1717,7 @@ impl State { |
| 1717 | return Ok((section, open_tab, None)); | 1717 | return Ok((section, open_tab, None)); |
| 1718 | } | 1718 | } |
| 1719 | if let Some(library) = self.sectionless.clone().filter(|_| self.session.is_none()) { | 1719 | if let Some(library) = self.sectionless.clone().filter(|_| self.session.is_none()) { |
| 1720 | self.no_sections(&theme, library); | 1720 | self.no_sections(library); |
| 1721 | self.ui.close(); | 1721 | self.ui.close(); |
| 1722 | self.ui.close(); | 1722 | self.ui.close(); |
| 1723 | self.ui.close(); | 1723 | self.ui.close(); |
| ... | @@ -4193,6 +4193,20 @@ impl State { | ... | @@ -4193,6 +4193,20 @@ impl State { |
| 4193 | .colored(self.view.editor.page_color()) | 4193 | .colored(self.view.editor.page_color()) |
| 4194 | } | 4194 | } |
| 4195 | 4195 | ||
| 4196 | /// The colours of what the page area shows in place of a page, which follow the page's: | ||
| 4197 | /// the light theme's on white pages, as Pages Match UI Theme off keeps them in a dark | ||
| 4198 | /// appearance. | ||
| 4199 | pub(crate) fn page_area_theme(&self) -> Theme { | ||
| 4200 | if self.light_pages { | ||
| 4201 | Theme { | ||
| 4202 | accent: self.ui.theme.accent, | ||
| 4203 | ..Theme::light() | ||
| 4204 | } | ||
| 4205 | } else { | ||
| 4206 | self.ui.theme.clone() | ||
| 4207 | } | ||
| 4208 | } | ||
| 4209 | |||
| 4196 | /// Paints the interface with the page in its box. | 4210 | /// Paints the interface with the page in its box. |
| 4197 | fn paint(&mut self, target: &draw::Target) -> Result<(), Box<dyn Error>> { | 4211 | fn paint(&mut self, target: &draw::Target) -> Result<(), Box<dyn Error>> { |
| 4198 | let start = Instant::now(); | 4212 | let start = Instant::now(); |
crates/snowbound/src/protection.rs+5-2| ... | @@ -2,7 +2,7 @@ | ... | @@ -2,7 +2,7 @@ |
| 2 | //! dialogs that unlock one and set, change or remove its password, Lock All, and locking a | 2 | //! dialogs that unlock one and set, change or remove its password, Lock All, and locking a |
| 3 | //! section after a while unused or as it is left. Keys live in memory only (`Library`). | 3 | //! section after a while unused or as it is left. Keys live in memory only (`Library`). |
| 4 | 4 | ||
| 5 | use crate::{Command, Library, State, Theme, art, manage::Structure}; | 5 | use crate::{Command, Library, State, art, manage::Structure}; |
| 6 | use accesskit::Role; | 6 | use accesskit::Role; |
| 7 | use std::{error::Error, sync::Arc, time::Duration}; | 7 | use std::{error::Error, sync::Arc, time::Duration}; |
| 8 | use ui::{Anchor, Axis, Flags, Id, Spec, Ui, children, fill, px}; | 8 | use ui::{Anchor, Axis, Flags, Id, Spec, Ui, children, fill, px}; |
| ... | @@ -155,11 +155,13 @@ impl State { | ... | @@ -155,11 +155,13 @@ impl State { |
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | /// The locked section's page, as OneNote 2010 draws it: a click or Enter unlocks. | 157 | /// The locked section's page, as OneNote 2010 draws it: a click or Enter unlocks. |
| 158 | pub(crate) fn locked_page(&mut self, theme: &Theme) { | 158 | pub(crate) fn locked_page(&mut self) { |
| 159 | let Some(locked) = &self.locked else { | 159 | let Some(locked) = &self.locked else { |
| 160 | return; | 160 | return; |
| 161 | }; | 161 | }; |
| 162 | let (library, path) = (Arc::clone(&locked.library), locked.path.clone()); | 162 | let (library, path) = (Arc::clone(&locked.library), locked.path.clone()); |
| 163 | let theme = &self.page_area_theme(); | ||
| 164 | let chrome = std::mem::replace(&mut self.ui.theme, theme.clone()); | ||
| 163 | let ui = &mut self.ui; | 165 | let ui = &mut self.ui; |
| 164 | let entered = | 166 | let entered = |
| 165 | ui::popup::navigation(ui, &[notice()], &[NamedKey::Enter]).contains(&NamedKey::Enter); | 167 | ui::popup::navigation(ui, &[notice()], &[NamedKey::Enter]).contains(&NamedKey::Enter); |
| ... | @@ -229,6 +231,7 @@ impl State { | ... | @@ -229,6 +231,7 @@ impl State { |
| 229 | ui.close(); | 231 | ui.close(); |
| 230 | ui.close(); | 232 | ui.close(); |
| 231 | ui.close(); | 233 | ui.close(); |
| 234 | ui.theme = chrome; | ||
| 232 | if ui.signal(open).clicked || entered { | 235 | if ui.signal(open).clicked || entered { |
| 233 | self.ask_password(library, path, Dialog::Unlock(Zeroizing::default(), false)); | 236 | self.ask_password(library, path, Dialog::Unlock(Zeroizing::default(), false)); |
| 234 | } | 237 | } |
crates/snowbound/src/sidebar.rs+8-9| ... | @@ -1150,7 +1150,7 @@ impl crate::State { | ... | @@ -1150,7 +1150,7 @@ impl crate::State { |
| 1150 | 1150 | ||
| 1151 | /// The window below the title bar on the first run, or once every notebook is closed: | 1151 | /// The window below the title bar on the first run, or once every notebook is closed: |
| 1152 | /// what is missing, and the ways to start. | 1152 | /// what is missing, and the ways to start. |
| 1153 | pub(crate) fn welcome(&mut self, theme: &Theme) { | 1153 | pub(crate) fn welcome(&mut self) { |
| 1154 | let id = self.ui.id("welcome"); | 1154 | let id = self.ui.id("welcome"); |
| 1155 | #[cfg(target_os = "linux")] | 1155 | #[cfg(target_os = "linux")] |
| 1156 | let install = crate::desktop::installable().then_some(( | 1156 | let install = crate::desktop::installable().then_some(( |
| ... | @@ -1163,9 +1163,7 @@ impl crate::State { | ... | @@ -1163,9 +1163,7 @@ impl crate::State { |
| 1163 | let install = None; | 1163 | let install = None; |
| 1164 | let servers = self.servers.clone(); | 1164 | let servers = self.servers.clone(); |
| 1165 | self.notice( | 1165 | self.notice( |
| 1166 | theme, | ||
| 1167 | id, | 1166 | id, |
| 1168 | theme.base, | ||
| 1169 | "No notebooks open", | 1167 | "No notebooks open", |
| 1170 | &servers, | 1168 | &servers, |
| 1171 | [ | 1169 | [ |
| ... | @@ -1202,7 +1200,7 @@ impl crate::State { | ... | @@ -1202,7 +1200,7 @@ impl crate::State { |
| 1202 | 1200 | ||
| 1203 | /// The page's place while notebook `library` has no sections, as OneNote 2010 shows | 1201 | /// The page's place while notebook `library` has no sections, as OneNote 2010 shows |
| 1204 | /// it, with a button to add one; or while none is on this computer yet. | 1202 | /// it, with a button to add one; or while none is on this computer yet. |
| 1205 | pub(crate) fn no_sections(&mut self, theme: &Theme, library: Arc<Library>) { | 1203 | pub(crate) fn no_sections(&mut self, library: Arc<Library>) { |
| 1206 | let downloading = library.downloading(); | 1204 | let downloading = library.downloading(); |
| 1207 | let new = crate::Command::Structure( | 1205 | let new = crate::Command::Structure( |
| 1208 | library, | 1206 | library, |
| ... | @@ -1219,27 +1217,27 @@ impl crate::State { | ... | @@ -1219,27 +1217,27 @@ impl crate::State { |
| 1219 | vec![("new", art::PLUS, "New Section", new)], | 1217 | vec![("new", art::PLUS, "New Section", new)], |
| 1220 | ) | 1218 | ) |
| 1221 | }; | 1219 | }; |
| 1222 | self.notice(theme, id, theme.strip, title, &[], buttons); | 1220 | self.notice(id, title, &[], buttons); |
| 1223 | } | 1221 | } |
| 1224 | 1222 | ||
| 1225 | /// A box `id` filled with `background`, showing `title` above `buttons` in its middle: each | 1223 | /// A box `id` in the page's colours, showing `title` above `buttons` in its middle: each |
| 1226 | /// a part, an icon, a label and what it does; then the saved `servers` to reconnect to. | 1224 | /// a part, an icon, a label and what it does; then the saved `servers` to reconnect to. |
| 1227 | fn notice( | 1225 | fn notice( |
| 1228 | &mut self, | 1226 | &mut self, |
| 1229 | theme: &Theme, | ||
| 1230 | id: ui::Id, | 1227 | id: ui::Id, |
| 1231 | background: [f32; 4], | ||
| 1232 | title: &str, | 1228 | title: &str, |
| 1233 | servers: &[String], | 1229 | servers: &[String], |
| 1234 | buttons: Vec<(&str, &'static [&'static str], &str, crate::Command)>, | 1230 | buttons: Vec<(&str, &'static [&'static str], &str, crate::Command)>, |
| 1235 | ) { | 1231 | ) { |
| 1236 | const BUTTON: [f32; 2] = [240.0, 32.0]; | 1232 | const BUTTON: [f32; 2] = [240.0, 32.0]; |
| 1233 | let theme = self.page_area_theme(); | ||
| 1234 | let chrome = std::mem::replace(&mut self.ui.theme, theme.clone()); | ||
| 1237 | let [left, top, right, bottom] = self.ui.rect(id).unwrap_or_default(); | 1235 | let [left, top, right, bottom] = self.ui.rect(id).unwrap_or_default(); |
| 1238 | self.ui.open_as( | 1236 | self.ui.open_as( |
| 1239 | id, | 1237 | id, |
| 1240 | Spec { | 1238 | Spec { |
| 1241 | size: [fill(), fill()], | 1239 | size: [fill(), fill()], |
| 1242 | fill: Some(background), | 1240 | fill: Some(theme.paper), |
| 1243 | ..Spec::default() | 1241 | ..Spec::default() |
| 1244 | }, | 1242 | }, |
| 1245 | ); | 1243 | ); |
| ... | @@ -1292,6 +1290,7 @@ impl crate::State { | ... | @@ -1292,6 +1290,7 @@ impl crate::State { |
| 1292 | let saved = crate::server::saved_servers(&mut self.ui, servers); | 1290 | let saved = crate::server::saved_servers(&mut self.ui, servers); |
| 1293 | self.ui.close(); | 1291 | self.ui.close(); |
| 1294 | self.ui.close(); | 1292 | self.ui.close(); |
| 1293 | self.ui.theme = chrome; | ||
| 1295 | if let Some(saved) = saved { | 1294 | if let Some(saved) = saved { |
| 1296 | self.saved_server(saved); | 1295 | self.saved_server(saved); |
| 1297 | } | 1296 | } |