max / goingson
| 1 | //! The app's own furniture: where you can go, and what stays on screen. |
| 2 | //! |
| 3 | //! <!-- wiki: quasi-overview --> |
| 4 | //! |
| 5 | //! [`Chrome`] is where it goes: a nav is places rather than content, and a |
| 6 | //! panel says what it is for. |
| 7 | //! |
| 8 | //! # The places |
| 9 | //! |
| 10 | //! Eleven views over three tabs, and which view a tab opens. A nav offering a |
| 11 | //! different set would be a second answer to what the app contains. |
| 12 | //! |
| 13 | //! Three views are not places, and each for a different reason: |
| 14 | //! |
| 15 | //! - `project-dashboard`, `task-overview` and `contact-dashboard` are details |
| 16 | //! reached from a row, not tabs. Which tab stays lit while one is open is |
| 17 | //! [`Screen::at_place`](quasi_router::Screen::at_place). |
| 18 | //! - `task-graph` is bespoke. A place pointing at a route that does not exist |
| 19 | //! would be a `NotFound` the first time it was pressed rather than a gap |
| 20 | //! anybody could see, so it is left out and said so here. |
| 21 | //! - The board is a mode of the Tasks place, so [`super::board`] marks Tasks |
| 22 | //! while it is showing. |
| 23 | //! |
| 24 | //! # Settings is a place, drawn wherever the renderer draws places |
| 25 | //! |
| 26 | //! Where it sits is a stylesheet's opinion about a place, not a different kind |
| 27 | //! of thing, so a webview is free to push it right. Describing it as anything |
| 28 | //! else would be this module answering the placement question the vocabulary |
| 29 | //! declines. |
| 30 | //! |
| 31 | //! # What the chrome does not carry |
| 32 | //! |
| 33 | //! - **A sync indicator.** A [`Role::Status`] panel is its shape, and there is |
| 34 | //! nothing describable to put in one while every sync command awaits a |
| 35 | //! network client and a route handler is synchronous. A `Status` panel |
| 36 | //! drawing an empty box would be worse than none. |
| 37 | //! - **The `?` shortcut overlay.** [`Chrome::bind`] is the member for it and |
| 38 | //! this app binds nothing, because there is no described help screen to bind |
| 39 | //! to and an overlay needs a container quasi-webview emits only alongside a |
| 40 | //! binding. Binding a key to a route that does not exist to get the container |
| 41 | //! is a trick, not a fix. |
| 42 | //! |
| 43 | //! # One chrome, assembled here |
| 44 | //! |
| 45 | //! [`super::protocol`] takes [`chrome`], because more than one module |
| 46 | //! contributes to it and somewhere has to put them together. The timer band is |
| 47 | //! [`super::time_tracking`]'s to describe; this only asks for it. |
| 48 | |
| 49 | use ; |
| 50 | |
| 51 | |
| 52 | |
| 53 | |
| 54 | /// The key a screen names to say it is the task list. |
| 55 | /// |
| 56 | /// The keys are spelled as consts because two places name each one: the [`Place`] |
| 57 | /// in the nav, and the screen that says it is there. A typo in either is a tab |
| 58 | /// that never lights, which is the quietest possible failure, so neither end |
| 59 | /// spells it as a literal. |
| 60 | pub const TASKS: &str = "tasks"; |
| 61 | /// The projects screen, and the project dashboard behind it. |
| 62 | pub const PROJECTS: &str = "projects"; |
| 63 | /// The problems queue. |
| 64 | pub const PROBLEMS: &str = "problems"; |
| 65 | /// The day plan. |
| 66 | pub const DAY: &str = "day-plan"; |
| 67 | /// The weekly review. |
| 68 | pub const WEEK: &str = "weekly-review"; |
| 69 | /// The monthly review. |
| 70 | pub const MONTH: &str = "monthly-review"; |
| 71 | /// The Timer screen. |
| 72 | pub const TIMER: &str = "timer"; |
| 73 | /// The calendar. |
| 74 | pub const EVENTS: &str = "events"; |
| 75 | /// Mail, and the Out box and compose screens reached from it. |
| 76 | pub const EMAILS: &str = "emails"; |
| 77 | /// The Out box. |
| 78 | pub const OUTBOX: &str = "outbox"; |
| 79 | /// Contacts, and the contact dashboard behind it. |
| 80 | pub const CONTACTS: &str = "contacts"; |
| 81 | /// Search, across all five kinds the index holds. |
| 82 | pub const SEARCH: &str = "search"; |
| 83 | /// Settings, and Import & Export, which its sidebar navigates to. |
| 84 | pub const SETTINGS: &str = "settings"; |
| 85 | |
| 86 | /// The places the app has, in the order the header offers them. |
| 87 | /// |
| 88 | /// A group's own action is the view its tab opens, which is `TAB_DEFAULTS` in |
| 89 | /// `navigation.js`. A group with nowhere to go would be a tab that does |
| 90 | /// nothing, and pressing Work in the shipped app opens Tasks. |
| 91 | |
| 92 | |
| 93 | new.within |
| 94 | new, |
| 95 | new, |
| 96 | new, |
| 97 | ], |
| 98 | new.within |
| 99 | new, |
| 100 | new, |
| 101 | new, |
| 102 | new, |
| 103 | new, |
| 104 | ], |
| 105 | new.within |
| 106 | new, |
| 107 | // Eudora put Out beside In, and this app's outbox is a real place |
| 108 | // rather than a state a message is in: goingson `a3c76a24`. |
| 109 | new, |
| 110 | new, |
| 111 | ], |
| 112 | // Search reaches every kind, so it belongs to no group and is a place |
| 113 | // of its own. It is a nav entry rather than a binding because the app |
| 114 | // binds no keys and cannot until quasicoherent `858be2a6` gives the |
| 115 | // overlay a container -- and because a nav entry is the one entry point |
| 116 | // that serves pointer, touch and keyboard alike, which is what goingson |
| 117 | // `6b3aa22b` was actually complaining about. |
| 118 | new, |
| 119 | // No sub-places, so it draws as a place of its own. The shipped header |
| 120 | // puts it on the right; where it lands here is the stylesheet's. |
| 121 | new, |
| 122 | ] |
| 123 | |
| 124 | |
| 125 | /// Everything the app keeps offered, whatever screen is showing. |
| 126 | /// |
| 127 | /// Each contributor takes the chrome and gives it back, which is the chain |
| 128 | /// [`super::router`] already is. The band is described by the module that owns |
| 129 | /// it, so there is one answer to what it says. |
| 130 | |
| 131 | |
| 132 | let offered = nav.into_iter.fold; |
| 133 | chrome |
| 134 | |
| 135 |