| 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 | 1474 | && self.locked.is_none(); |
| 1475 | 1475 | self.toolbar(&theme, !welcome)?; |
| 1476 | 1476 | if welcome { |
| 1477 | self.welcome(&theme); | |
| 1477 | self.welcome(); | |
| 1478 | 1478 | return Ok((section, Id::ROOT, None)); |
| 1479 | 1479 | } |
| 1480 | 1480 | self.ui.open( |
| ... | ... | @@ -1704,7 +1704,7 @@ impl State { |
| 1704 | 1704 | recycle::bar(&mut self.ui); |
| 1705 | 1705 | } |
| 1706 | 1706 | if self.session.is_none() && self.locked.is_some() { |
| 1707 | self.locked_page(&theme); | |
| 1707 | self.locked_page(); | |
| 1708 | 1708 | self.ui.close(); |
| 1709 | 1709 | self.ui.close(); |
| 1710 | 1710 | self.ui.close(); |
| ... | ... | @@ -1717,7 +1717,7 @@ impl State { |
| 1717 | 1717 | return Ok((section, open_tab, None)); |
| 1718 | 1718 | } |
| 1719 | 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 | 1721 | self.ui.close(); |
| 1722 | 1722 | self.ui.close(); |
| 1723 | 1723 | self.ui.close(); |
| ... | ... | @@ -4193,6 +4193,20 @@ impl State { |
| 4193 | 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 | 4210 | /// Paints the interface with the page in its box. |
| 4197 | 4211 | fn paint(&mut self, target: &draw::Target) -> Result<(), Box<dyn Error>> { |
| 4198 | 4212 | let start = Instant::now(); |
crates/snowbound/src/protection.rs+5-2| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | //! dialogs that unlock one and set, change or remove its password, Lock All, and locking a |
| 3 | 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 | 6 | use accesskit::Role; |
| 7 | 7 | use std::{error::Error, sync::Arc, time::Duration}; |
| 8 | 8 | use ui::{Anchor, Axis, Flags, Id, Spec, Ui, children, fill, px}; |
| ... | ... | @@ -155,11 +155,13 @@ impl State { |
| 155 | 155 | } |
| 156 | 156 | |
| 157 | 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 | 159 | let Some(locked) = &self.locked else { |
| 160 | 160 | return; |
| 161 | 161 | }; |
| 162 | 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 | 165 | let ui = &mut self.ui; |
| 164 | 166 | let entered = |
| 165 | 167 | ui::popup::navigation(ui, &[notice()], &[NamedKey::Enter]).contains(&NamedKey::Enter); |
| ... | ... | @@ -229,6 +231,7 @@ impl State { |
| 229 | 231 | ui.close(); |
| 230 | 232 | ui.close(); |
| 231 | 233 | ui.close(); |
| 234 | ui.theme = chrome; | |
| 232 | 235 | if ui.signal(open).clicked || entered { |
| 233 | 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 | 1150 | |
| 1151 | 1151 | /// The window below the title bar on the first run, or once every notebook is closed: |
| 1152 | 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 | 1154 | let id = self.ui.id("welcome"); |
| 1155 | 1155 | #[cfg(target_os = "linux")] |
| 1156 | 1156 | let install = crate::desktop::installable().then_some(( |
| ... | ... | @@ -1163,9 +1163,7 @@ impl crate::State { |
| 1163 | 1163 | let install = None; |
| 1164 | 1164 | let servers = self.servers.clone(); |
| 1165 | 1165 | self.notice( |
| 1166 | theme, | |
| 1167 | 1166 | id, |
| 1168 | theme.base, | |
| 1169 | 1167 | "No notebooks open", |
| 1170 | 1168 | &servers, |
| 1171 | 1169 | [ |
| ... | ... | @@ -1202,7 +1200,7 @@ impl crate::State { |
| 1202 | 1200 | |
| 1203 | 1201 | /// The page's place while notebook `library` has no sections, as OneNote 2010 shows |
| 1204 | 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 | 1204 | let downloading = library.downloading(); |
| 1207 | 1205 | let new = crate::Command::Structure( |
| 1208 | 1206 | library, |
| ... | ... | @@ -1219,27 +1217,27 @@ impl crate::State { |
| 1219 | 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 | 1224 | /// a part, an icon, a label and what it does; then the saved `servers` to reconnect to. |
| 1227 | 1225 | fn notice( |
| 1228 | 1226 | &mut self, |
| 1229 | theme: &Theme, | |
| 1230 | 1227 | id: ui::Id, |
| 1231 | background: [f32; 4], | |
| 1232 | 1228 | title: &str, |
| 1233 | 1229 | servers: &[String], |
| 1234 | 1230 | buttons: Vec<(&str, &'static [&'static str], &str, crate::Command)>, |
| 1235 | 1231 | ) { |
| 1236 | 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 | 1235 | let [left, top, right, bottom] = self.ui.rect(id).unwrap_or_default(); |
| 1238 | 1236 | self.ui.open_as( |
| 1239 | 1237 | id, |
| 1240 | 1238 | Spec { |
| 1241 | 1239 | size: [fill(), fill()], |
| 1242 | fill: Some(background), | |
| 1240 | fill: Some(theme.paper), | |
| 1243 | 1241 | ..Spec::default() |
| 1244 | 1242 | }, |
| 1245 | 1243 | ); |
| ... | ... | @@ -1292,6 +1290,7 @@ impl crate::State { |
| 1292 | 1290 | let saved = crate::server::saved_servers(&mut self.ui, servers); |
| 1293 | 1291 | self.ui.close(); |
| 1294 | 1292 | self.ui.close(); |
| 1293 | self.ui.theme = chrome; | |
| 1295 | 1294 | if let Some(saved) = saved { |
| 1296 | 1295 | self.saved_server(saved); |
| 1297 | 1296 | } |