Mostro mascot in every tab header, with mood artwork from the sticker set
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 35/100
Research direction
Start with .specify/DESIGN_SYSTEM.md and the handoff note for handoff 11, since the issue requires a design decision before code. Then read home_screen.dart, lib/shared/widgets/tab_app_bar.dart, and lib/shared/mascot/mostro_mood.dart, along with their unit tests. Done means the phased shared header and mood artwork/events follow the stated freshness, priority, accessibility, and reduced-motion rules, with the design guidance updated and tests passing.
Written by the indexing model from the issue text.
Description
Problem
The three bottom-bar tabs are siblings, but their app bars disagree in the centre:
- Book (
home_screen.dart,_HeaderMascot) shows the Mostro mascot. It is interactive: a tap bounces it, 7 taps make it dizzy, it shuffles while the book is slow and celebrates a completed trade. - Trades and Chat (
TabAppBar,lib/shared/widgets/tab_app_bar.dart) show the wordMostroin text (handoff 11: "the centre only says which app this is").
Switching tabs is the most frequent gesture in the app, and the bar's centre jumps from a picture to a word every time. The word carries no information: the user knows which app they are in. And the mascot already watches the trade stream to celebrate a completed trade, but it is missing from Trades, where that celebration belongs.
Book Trades (today) Chat (today)
☰ [mascot] 🔔 ☰ Mostro 🔔 ☰ Mostro 🔔
Book Trades (proposed) Chat (proposed)
☰ [mascot] 🔔 ☰ [mascot] 🔔 ☰ [mascot] 🔔
Proposal
Part 1: one header for every tab
- Move
_HeaderMascotout ofhome_screen.dartintolib/shared/mascot/. It is the mascot plus its moods (patience timer, trade-update listener). TabAppBarshows it in place of the text. The book's header andTabAppBarare already near copies (same insets, 48 dp targets, aStackof centre +Row), so the book can useTabAppBartoo, which leaves one widget for all three tabs (DS-CMP-12).- The mascot keeps its accessible name (
Mostro), so a screen reader reads the same thing as today. - The book's "impatient" mood depends on
orderBookProvider. On the other tabs it either stays neutral or uses the same signal; to decide in the PR. - Design decision first: this changes handoff 11. Update
.specify/DESIGN_SYSTEM.md(or the handoff note it cites) in the same PR, before the code.
Part 2: moods with their own artwork (sticker set)
Today a mood only changes how the single artwork moves (lib/shared/mascot/mostro_mood.dart: "Everything else about the mascot is the same artwork"). There is now a set of 24 Mostro stickers (512 px PNG with alpha, plus 100 px Telegram emoji versions):
bored celebrate check confused cool cry dispute escrow facepalm fire gm hodl laugh lightning love money p2p rocket scared surprised thanks thinking thumbsup waving
The proposal is to let a mood carry its own artwork, keeping its motion. At header size (26 dp), the stickers with props or colour (celebrate, dispute, escrow, lightning, love, check, cry) still read clearly. The subtle ones (thinking, bored, scared) read less clearly, but well enough. They carry their own dark outline, so they work on both themes.
Existing moods → artwork
| Mood | Trigger (today) | Sticker |
|---|---|---|
celebrating |
a TradeUpdate to success / settledByAdmin / completedByAdmin |
celebrate |
asleep |
empty book (OrderListEmpty) |
bored (it has the Zs) |
impatient |
book still loading after 6 s | thinking |
dizzy |
7 taps within the streak window | confused |
happy |
a tap | waving |
New trade moods come from TradeUpdate, i.e. from daemon messages:
| Mood | Trigger | Sticker |
|---|---|---|
| escrow locked | status → active (the seller's hold invoice is paid) |
escrow |
| fiat sent | status → fiatSent |
money |
| dispute | status → dispute |
dispute |
| canceled | canceled, cooperativelyCanceled, canceledByAdmin, expired |
cry |
| offline | ConnectionState.offline |
scared (ambient, until back online) |
| order published | create_order confirmed by the daemon |
rocket |
| rating sent | 5 stars → love; any other score → thanks |
love / thanks |
| daemon refused an action | a CantDo |
facepalm |
Easter eggs. These follow the pure rules in mostro_mood.dart, like the seasons:
| Egg | Rule | Sticker |
|---|---|---|
| gm | first launch of the session between 05:00 and 11:00 local | gm |
| genesis day (3 Jan) | replaces today's 📰 badge | hodl |
| unassigned | cool, fire, laugh, lightning, surprised, thumbsup, check, p2p |
ideas welcome |
Rules any mood must follow
- Only fresh events. A history replay after a restore re-emits old transitions (#474). A mood reacts only when
TradeUpdate.occurredAtis recent (within a few seconds), or a restore makes Mostro celebrate, cry and argue all at once. Note that today's_onTradeUpdateignoresoccurredAt, so a replayedsuccessprobably makes it celebrate already. Fix that in Part 2. - Never from the book. The Kind 38383
stag is not a trade's status (#203). Every trade mood comes fromTradeUpdate. - Decoration, never the only signal. A trade's state stays on its card and in its notices. The mascot only echoes it, and its semantics label does not change with the mood.
- Reactions play once and go back to neutral. Ambient moods (asleep, impatient, offline) loop. If two moods apply at once, one has priority: offline > dispute > the others > ambient > neutral. Put this in
mostro_mood.dart, with unit tests, likemoodForTaps. - Reduce motion (DS-MOT-3). Swapping the artwork is static, so it stays when motion is off. Only the movement is gated.
- Assets. Ship only the stickers that are used, trimmed, as about 256 px webp: about 13 KB each, about 312 KB for all 24. No new Rust, no persisted state. The moods are transient and need no identity reset.
Phasing
- Part 1: shared header, mascot in all tabs, design guide updated.
- Artwork for the existing moods, plus the
occurredAtfreshness guard. - New trade moods (escrow, fiat sent, dispute, canceled, offline, published, rating, CantDo).
- Easter eggs (gm, genesis day, the unassigned stickers).
Out of scope
- Sending the stickers in peer chat. That is a separate idea, and it touches the chat envelope.
- Changing the drawer header or the About screen artwork.
- Dominant language
- Dart
- Stars
- 11
- Forks
- 9
- Avg merge
- 20h 36m
- Merged PRs (30d)
- 236
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from MostroP2P/app
-
area: ui feature priority: medium
Difficulty 1/5 Under an hour Newbie friendliness 90/100
Maintainers usually reply within 1 day
-
area: rust-core bug priority: low
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 85/100
Maintainers usually reply within 1 day
-
area: ui
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
jhomlala/betterplayer#1609 ·
Maintainers usually reply within 1 day
-
[FR] 缓存键放置在外面Openenhancement
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
bggRGjQaUbCoE/PiliPlus#3310 ·
Maintainers usually reply within 1 day
-
package:code_builder type-bug
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
Maintainers usually reply within 1 day
-
type:feature
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 1 day
-
[material_ui] CalendarDatePicker day numbers are cut off with large text scale on narrow screensOpen
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day