mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-09-14 15:16:40 +00:00
feat(ui): make favourites mean one thing across every list
Three names had grown around one idea. "Favourite" was a filter in Settings, an invisible app-only flag on a contact, a device-settable bit on a channel, and — on the Nodes screen — a menu row that actually pinned to the Favourites dial. Nothing marked a favourite on screen, and the dial only took chat contacts. A favourite is now the starred flag (ContactInfo::flags bit 0 for contacts and rooms, ch_fav_bitmask for channels), settable on the device everywhere via a Fav: ON/OFF row, marked with a star on its row, and sorted to the top of the list — in Messages, Tools > Nodes and the Locator target picker. Settings > Contacts > "Favs top" turns the sorting off; it defaults on, and is stored inverted so an upgraded prefs file reads back as on rather than off. MyMesh::setContactFavourite() writes the same bit the app sets and bumps lastmod, so the two stay in sync. The DMs/Rooms = Fav list filters no longer depend on having starred someone in the app first. Pinning is now separate and explicit, and the dial takes contacts, room servers and channels. Slots carry a kind (NodePrefs::favourite_kinds, schema 0xC0DE0029) — a channel slot holds an index, so emptiness is decided by the kind first, since channel 0's payload is all zeroes. Choosing what to pin reuses the Messages screen's own Direct/Channels/Rooms browse instead of a second picker built on the dial, which drops that picker, its key/label tables and the now-unused getRecentDMContacts(). A filled tile gained Unpin/Replace under Hold Enter. Fixes a room server being pinnable and then unremovable: the picker's recent-conversations tier didn't filter by contact type and room posts share the DM history, opening one from the dial skipped the login handshake, and Unpin only existed in the chat contact list that rooms never appear in. Also: PopupMenu::_visible was written and never read (render recomputes the cap from display height), which is why menus with more items than the "visible" argument always worked; Settings' all/fav values and the dm_show_all comment said things that were not true. Built for Heltec V3, Wio Tracker L1, Wio Tracker L1 e-ink and T-Echo Card. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
| :------------------------: | :------------------------: |
|
||||
|  |  |
|
||||
|
||||
A dedicated home page showing a grid of up to 6 pinned contacts for quick access. The layout adapts to the display orientation:
|
||||
A dedicated home page showing a grid of up to 6 pinned conversations — chat contacts, room servers or channels — for quick access. The layout adapts to the display orientation:
|
||||
|
||||
- **Portrait** (OLED, e-ink portrait) — 2 columns × 3 rows
|
||||
- **Landscape** (e-ink landscape) — 3 columns × 2 rows
|
||||
@@ -19,45 +19,53 @@ A dedicated home page showing a grid of up to 6 pinned contacts for quick access
|
||||
|
||||
Navigate tiles with **UP / DOWN / LEFT / RIGHT**. Pressing a directional key at the edge of the grid switches to the adjacent home page instead of wrapping.
|
||||
|
||||
**Enter on a filled tile** — opens that contact's DM directly.
|
||||
**Enter on a filled tile** — opens that conversation directly: a contact's DM, a channel's history, or a room server (running the room's login handshake first if it isn't logged in yet).
|
||||
|
||||
**Enter on an empty tile (`+`)** — opens a contact picker to fill the slot.
|
||||
**Enter on an empty tile (`+`)** — starts the picker to fill the slot.
|
||||
|
||||
**Hold Enter on a filled tile** — opens **Unpin** / **Replace** for that slot.
|
||||
|
||||
Channel tiles show their name with a leading `#`, so they read apart from contacts and rooms sharing the same grid.
|
||||
|
||||
---
|
||||
|
||||
### Unread badge
|
||||
|
||||
Filled tiles show an unread message count in the top-right corner when there are unread DMs from that contact. The contact name is ellipsized to make room for the badge.
|
||||
Filled tiles show an unread message count in the top-right corner — unread DMs for a contact or room, unread posts for a channel. The name is ellipsized to make room for the badge.
|
||||
|
||||
If a pinned contact is removed from the contacts list — explicitly, or auto-evicted to make room when the table is full — its slot is freed automatically and goes back to an empty `+` tile.
|
||||
If a pinned target disappears — a contact removed explicitly or auto-evicted to make room when the table is full, or a deleted channel — its slot is freed automatically and goes back to an empty `+` tile.
|
||||
|
||||
---
|
||||
|
||||
### Pinning a contact
|
||||
### Pinning
|
||||
|
||||
**From the Favourites Dial** — press **Enter** on an empty tile (`+`). A picker opens showing:
|
||||
|
||||
1. Contacts marked as favourites in the upstream app (starred contacts) — listed first
|
||||
2. Recent DM contacts — listed after
|
||||
3. All remaining chat contacts — fallback when the first two tiers are empty (e.g. fresh install before any DMs)
|
||||
**From the Favourites Dial** — press **Enter** on an empty tile (`+`), or **Hold Enter** on a filled one and choose **Replace**. This opens the **Messages** screen in its normal Direct / Channels / Rooms browse; pick an entry and you land back on the dial with that slot filled. It's the same list you already use to open a conversation, rather than a second browser of its own.
|
||||
|
||||
| OLED | E-Ink |
|
||||
| :------------------------: | :------------------------: |
|
||||
|  |  |
|
||||
|
||||
<!-- screenshot pending: Pin-to-dial contact picker (favourites first, then recent DMs, then all contacts) -->
|
||||
<!-- screenshot pending: Messages browse entered from an empty dial tile -->
|
||||
|
||||
Select a contact to pin it to that slot.
|
||||
**From the Messages lists** — **Hold Enter** on a contact, room or channel entry › **Pin to dial**, then choose a slot from the slot picker (Slot 1–6, showing the current occupant or "empty").
|
||||
|
||||
**From a DM conversation** — **Hold Enter** › context menu › **Pin to dial**, then choose a slot from the slot picker (Slot 1–6, showing the current occupant name or "empty").
|
||||
**From Tools › Nodes** — **Hold Enter** on a node › **Pin to dial**. This one doesn't ask which slot; it takes the first free one (and says which), since that menu is already long.
|
||||
|
||||
If the selected contact is already pinned in another slot, it is moved to the new slot automatically.
|
||||
If the target is already pinned in another slot, it is moved to the new slot automatically.
|
||||
|
||||
---
|
||||
|
||||
### Unpinning a contact
|
||||
### Unpinning
|
||||
|
||||
Open the contact's DM, **Hold Enter** › context menu › **Unpin (slot N)**.
|
||||
**From the Favourites Dial** — **Hold Enter** on the tile › **Unpin**.
|
||||
|
||||
**From the Messages lists or Tools › Nodes** — **Hold Enter** › context menu › **Unpin (slot N)**.
|
||||
|
||||
---
|
||||
|
||||
### Pinning is not the same as favouriting
|
||||
|
||||
A pinned tile and a **Fav: ON** entry are two independent things. Pinning puts something on this page. Favouriting marks it with a ★ and sorts it to the top of every list it appears in, and is what the **Settings › Contacts** list filters read. Either can be used without the other.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -109,18 +109,23 @@ Selecting the row opens a read-only list of the resolved hops — each shown as
|
||||
| Item | Action |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------ |
|
||||
| Mark as read | Clears unread counter for this contact |
|
||||
| Notif: default / OFF / ON | Per-contact notification override — **LEFT/RIGHT** to cycle |
|
||||
| Melody: global / M1 / M2 | Per-contact melody override — **LEFT/RIGHT** to cycle |
|
||||
| Notif: Default / OFF / ON | Per-contact notification override — **LEFT/RIGHT** to cycle |
|
||||
| Melody: Global / M1 / M2 | Per-contact melody override — **LEFT/RIGHT** to cycle |
|
||||
| Fav: ON / OFF | Mark this contact as a favourite — **LEFT/RIGHT** to toggle |
|
||||
| Pin to dial / Unpin (slot N) | Pin this contact to a Favourites Dial slot; if already pinned shows which slot |
|
||||
|
||||
**Fav** and **Pin to dial** are separate. **Fav** is the starred flag shared with the companion app: it marks the row with a ★, sorts it above the rest of the list (unless **Settings › Contacts › Favs top** is off), and drives the `DMs = Fav` list filter. **Pin to dial** puts the contact on the [Favourites Dial](../favourites_dial/favourites_dial.md) page and changes nothing about the list.
|
||||
|
||||
When **Pin to dial** is selected, a slot picker opens (Slot 1–6 showing current occupant name or "empty"). Choosing a slot that already holds another contact moves the new contact there.
|
||||
|
||||
In the **Rooms** list the context menu instead offers:
|
||||
|
||||
| Item | Action |
|
||||
| ------- | ---------------------------------------------------------------------------- |
|
||||
| Login… | Opens the password prompt to (re-)log in to this room (see Rooms — logging in) |
|
||||
| Logout | Only shown once logged in. Forgets the saved password so the next open prompts for one again |
|
||||
| Item | Action |
|
||||
| ------------- | ---------------------------------------------------------------------------- |
|
||||
| Login… | Opens the password prompt to (re-)log in to this room (see Rooms — logging in) |
|
||||
| Logout | Only shown once logged in. Forgets the saved password so the next open prompts for one again |
|
||||
| Fav: ON / OFF | Mark this room as a favourite — **LEFT/RIGHT** to toggle; drives the **Rooms = Fav** list filter |
|
||||
| Pin to dial / Unpin (slot N) | Pin this room to a [Favourites Dial](../favourites_dial/favourites_dial.md) slot |
|
||||
|
||||
---
|
||||
|
||||
@@ -135,9 +140,10 @@ In the **Rooms** list the context menu instead offers:
|
||||
| Item | Action |
|
||||
| ------------------------- | --------------------------------------------------------------------- |
|
||||
| Mark all read | Clears all unread for this channel |
|
||||
| Notif: default / OFF / ON | Per-channel notification override — **LEFT/RIGHT** to cycle |
|
||||
| Melody: global / M1 / M2 | Per-channel melody override — **LEFT/RIGHT** to cycle |
|
||||
| Notif: Default / OFF / ON | Per-channel notification override — **LEFT/RIGHT** to cycle |
|
||||
| Melody: Global / M1 / M2 | Per-channel melody override — **LEFT/RIGHT** to cycle |
|
||||
| Fav: ON / OFF | Add or remove this channel from favourites — **LEFT/RIGHT** to toggle |
|
||||
| Pin to dial / Unpin (slot N) | Pin this channel to a [Favourites Dial](../favourites_dial/favourites_dial.md) slot |
|
||||
| Edit | Opens the Add/Edit form below, pre-filled with the channel's name |
|
||||
| Delete | Removes the channel immediately (no confirm prompt) |
|
||||
|
||||
|
||||
@@ -114,11 +114,16 @@ European Latin-diacritic letters (Polish, Czech, Slovak, German, French, Spanish
|
||||
|
||||
### Contacts
|
||||
|
||||
| Setting | Options | Notes |
|
||||
| -------- | ---------------- | ---------------------------------------------------- |
|
||||
| DMs | all / favourites | Show all chat contacts or only upstream-starred ones |
|
||||
| Channels | all / favourites | Show all channels or only favourited ones |
|
||||
| Rooms | all / favourites | Show all room servers or only favourited ones |
|
||||
| Setting | Options | Notes |
|
||||
| -------- | --------- | ------------------------------------------- |
|
||||
| DMs | All / Fav | Show all chat contacts or only favourited ones |
|
||||
| Channels | All / Fav | Show all channels or only favourited ones |
|
||||
| Rooms | All / Fav | Show all room servers or only favourited ones |
|
||||
| Favs top | ON / OFF | Sort favourites to the top of every list (default ON) |
|
||||
|
||||
Favourites are set per item in its context menu (**Hold Enter** › **Fav: ON / OFF**) — see [Message Screen](../message_screen/message_screen.md), and the same row exists in Tools › Nodes. A contact's or room's favourite flag is the same one the companion app shows as a starred contact, so it syncs both ways; a channel's is device-only.
|
||||
|
||||
A favourite is marked with a ★ on its row wherever it is listed, and — unless **Favs top** is off — sorted above everything else. The three filters above are independent of that: they control what's *listed at all*, the sort only controls the order.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -25,13 +25,13 @@ Filter by category with **LEFT/RIGHT** (one coherent axis — type only):
|
||||
| Filter | Shows |
|
||||
| ------ | ------------------------------ |
|
||||
| All | All known nodes |
|
||||
| Fav | Upstream-starred contacts only |
|
||||
| Fav | Favourites only (★) |
|
||||
| Comp | Companion (chat) nodes |
|
||||
| Rpt | Repeaters |
|
||||
| Room | Room servers |
|
||||
| Snsr | Sensors |
|
||||
|
||||
Select a node to see its coordinates, distance, bearing with cardinal direction, type, and last-heard time. A node that is **broadcasting its position** via Live Share is marked with a **♦ diamond** beside its name in the list (the same marker the map uses), and its detail shows `Sharing pos:` with the share age and whether it's DM-verified or channel-only.
|
||||
Select a node to see its coordinates, distance, bearing with cardinal direction, type, and last-heard time. A node that is **broadcasting its position** via Live Share is marked with a **♦ diamond** beside its name in the list (the same marker the map uses), and its detail shows `Sharing pos:` with the share age and whether it's DM-verified or channel-only. A **★ star** marks a favourite, which is also sorted to the top of the list unless **Settings › Contacts › Favs top** is off.
|
||||
|
||||
**Hold Enter** opens the same **Options** menu everywhere (list and detail), in a fixed order — only the actions that apply appear:
|
||||
|
||||
@@ -41,6 +41,8 @@ Select a node to see its coordinates, distance, bearing with cardinal direction,
|
||||
| Ping | a public key is known for the node |
|
||||
| Save waypoint | selected node has GPS |
|
||||
| Set as target | selected node has GPS **and** a public key — pins it as the active **Locator/Nav target** right away (see **Locator**) |
|
||||
| Fav: ON / OFF | selected node is a saved contact — the same starred flag the Messages lists use, shared with the companion app |
|
||||
| Pin to dial / Unpin (slot N) | selected node is a saved contact — puts it on the [Favourites Dial](../favourites_dial/favourites_dial.md), taking the first free slot |
|
||||
| Admin | selected node is a saved **repeater or room server** contact — opens **Tools › Admin** for it directly (see **Admin**) |
|
||||
| Sort: Dist/Recent | browsing stored nodes — **LEFT/RIGHT** on the row flips distance ↔ last-heard in place |
|
||||
| Discover scan / Rescan | always (live `NODE_DISCOVER_REQ` scan) |
|
||||
@@ -272,7 +274,7 @@ Navigate with **UP/DOWN**, change a value with **LEFT/RIGHT** (or **Enter**); **
|
||||
| Setting | Options | Notes |
|
||||
| ------- | -------------------------------- | -------------------------------------------------------------------------------------- |
|
||||
| Alert | ON / OFF | Master switch. Enabling without a target prompts you to pick one. |
|
||||
| Target | none / person / waypoint | **Enter** opens a picker — **None** first (clears the target), then **favourites** (offered even with no known position yet, so you can arm ahead of time), then any other contact with a currently-resolvable position (live-sharing *or* just last-advertised, e.g. a repeater), then waypoints; **UP/DOWN** + **Enter** to choose. **LEFT/RIGHT** quick-cycles the same set in place, including back to **None**. A person is shown with an `@` prefix, plus a compact **age tag** (e.g. `@Bob (5m)`) when the position is last-advertised rather than a live share. Shows `none` until set. |
|
||||
| Target | none / person / waypoint | **Enter** opens a picker — **None** first (clears the target), then **dial-pinned people** (offered even with no known position yet, so you can arm ahead of time), then any other contact with a currently-resolvable position (live-sharing *or* just last-advertised, e.g. a repeater), then waypoints; **UP/DOWN** + **Enter** to choose. **LEFT/RIGHT** quick-cycles the same set in place, including back to **None**. A person is shown with an `@` prefix, a ★ if they're a favourite, plus a compact **age tag** (e.g. `@Bob (5m)`) when the position is last-advertised rather than a live share. Shows `none` until set. |
|
||||
| Radius | 50 / 100 / 250 / 500 m / 1 km | Geofence size. |
|
||||
| Mode | Arrive / Leave / Both | Which crossing fires the alert — entering the radius, leaving it, or both. |
|
||||
| Beeper | ON / OFF | Optional homing tone — shown only in **Arrive** / **Both** modes (see below). |
|
||||
|
||||
Reference in New Issue
Block a user