Commit graph

211 commits

Author SHA1 Message Date
d27dc1c553 chore(release): v0.1.1 (+3) — GMS-free build
Some checks failed
ci / test-commons-core (push) Successful in 43s
ci / analyze (push) Successful in 1m23s
site / deploy (push) Successful in 25s
ci / test-app-seeds (push) Has been cancelled
release / android (push) Failing after 10m57s
Bumps to 0.1.1+3 (versionCode 3). Adds CHANGELOG [0.1.1], fastlane
changelogs (en-US, es-ES) for versionCode 3, and a 0.1.1 build entry in
the F-Droid recipe (commit v0.1.1, CurrentVersion/Code 3).
2026-07-17 09:19:16 +02:00
d0fabb80a9 fix(android): drop geolocator for a native LocationManager channel
Removes the geolocator dependency, which transitively embedded
com.google.android.gms.* (play-services-location) — proprietary classes
that F-Droid's scanner rejects. The optional coarse-location button now
talks to Android's own LocationManager over a small platform channel
(org.comunes.tane/coarse_location): permission prompt, single coarse fix
with a 12s timeout, last-known fallback, null on any failure. Behavior
is unchanged and the CoarseLocationProvider interface is preserved, so
the UI, i18n and widget tests need no changes.

Also sets dependenciesInfo.includeInApk/Bundle = false so the AGP
dependency-metadata block (also flagged by F-Droid) is not embedded.
Neither change affects the Google Play build.
2026-07-17 09:19:05 +02:00
5bf06aa258 release: bump to 0.1.0+2 and add promote_production fastlane lane
All checks were successful
ci / analyze (push) Successful in 1m9s
ci / test-commons-core (push) Successful in 38s
ci / test-app-seeds (push) Successful in 5m48s
2026-07-16 15:40:26 +02:00
61f54cc0db ci(forgejo): turn off format gate, fix locale-fragile settings test
All checks were successful
ci / analyze (push) Successful in 1m9s
ci / test-commons-core (push) Successful in 41s
ci / test-app-seeds (push) Successful in 5m52s
Format: repo predates Dart 3.11's tall formatter (~128 files would need a
dedicated reformat commit); disable --set-exit-if-changed for now, keep
flutter analyze as the real gate.

Test: 'drawer Settings opens the settings screen' asserted find.text('Español'),
which only holds when the resolved locale is Spanish. Under AppLocale.en (as
set in the test) the tile reads 'English', so it failed under CI's non-Spanish
host locale. Assert by the language selector's Key + icon instead (locale-robust).
2026-07-16 12:21:27 +02:00
eef99975bf feat(store): branded feature graphic (1024x500) + 512 store icon
Noto Sans wordmark on brand green (#2F7D34), white sprout, and the official
value tagline ('keep and share traditional seeds' / 'guarda y comparte...').
Generated by tool/gen_feature_graphic.py for en-US and es-ES.
2026-07-16 02:49:06 +02:00
fd6b9d5f0d feat(release): automate store publishing (fastlane supply + GitLab CI) and F-Droid recipe
- fastlane: Appfile/Fastfile/Gemfile with deploy_play lane (AAB -> Play internal track)
- CI: tag-gated build:android (signed AAB/APK from CI secrets) + deploy:play jobs
- F-Droid: fdroiddata build recipe at docs/fdroid/org.comunes.tane.yml
- Play compliance: Data Safety / content-rating answer sheet (docs/legal/internal)
- docs/release.md: automated tag-triggered flow, dedicated tane-upload keystore
- pubspec: description now mentions the market, not just the inventory
2026-07-16 02:42:47 +02:00
dc0d18562f fix(quick-add): wrap sheet action row to prevent overflow on small screens
The Cancel / Save-and-add-another / Save actions were a fixed Row that
could not shrink, so on narrow phones and long locales (es/pt/de/fr) the
buttons overflowed the right edge (the clipped 'Guardar'). Replace it with
an OverflowBar that wraps onto stacked, end-aligned lines when they don't
fit; move the added-count onto its own line above.

Guard it in small_screen_overflow_test.dart across the long locales.
2026-07-16 00:34:42 +02:00
7d5f26ff4a feat(links): surface source repo + Weblate links on site and in app
- site: set sourceURL (git.comunes.org/comunes/tane) and weblateURL
  (translate.comunes.org/projects/tane) — activates footer + collaborate links
- app About screen: add 'Source code' and 'Help translate' link tiles
- i18n: add about.sourceCode / about.translate / about.translateSubtitle
  (en base + es/pt/fr/de/ast; ja falls back to base), regenerate slang
- docs: add TRANSLATIONS.md runbook for the Weblate app component + git
  token + slang-regeneration workflow
2026-07-15 19:12:16 +02:00
991785821f feat(screenshots): localize sample variety & market names per shot language 2026-07-15 17:48:44 +02:00
1ce32c2b5c feat: cover seedlings (plantón) in copy + legal, backup cadence, server picker
Beta-tester feedback triage. The data model already had LotType.seedling as
first class; the gaps were copy and UX.

- Seedlings/plantones: broaden landing hero (EN/ES), in-app legal notice, and
  all legal texts (site + docs masters) from seeds-only to "seeds and
  seedlings", with a live-plant phytosanitary/transport caveat. Seeds stay the
  hero — targeted, not a blanket rename.
- Backups: settings line now states the 7-day cadence explicitly; cadence lives
  in AutoBackupService.backupInterval as the single source for text and schedule.
- Community servers: replace the manual wss:// text box with a checklist of the
  known servers (defaults visible/toggleable) plus an "add server" affordance
  with basic validation. No jargon in the UI.

i18n across en/es/pt/fr/de/ast (ja falls back). Tests updated + a new
server-picker widget test.
2026-07-15 15:57:23 +02:00
7891a973f4 feat(screenshots): CC0/PD example photos for all visible varieties (+CREDITS) 2026-07-15 13:19:24 +02:00
eed96b2a75 feat(screenshots): real maize photo as hero variety, surfaced at top of inventory 2026-07-15 13:07:46 +02:00
a7ec13f2f1 fix(web): center unread badge on the menu icon, not the tap target 2026-07-15 12:47:27 +02:00
7f6c88039c fix(web): use red (error color) for unread badge instead of green 2026-07-15 12:45:39 +02:00
bb5d09bc6a fix(screenshots): precache asset images so the home logo renders; explain the Plantare name 2026-07-15 12:26:18 +02:00
8dce6f7027 feat(web): tane.comunes.org landing + localized app screenshots
- Hugo site (site/): EN/ES intro + legal (generated from docs/legal), an
  ES/EN About page from docs/{que-es-tane,what-is-tane}.md, seed-green theme,
  responsive header, store-badge placeholders, multi-stage Hugo->nginx image.
- Golden screenshot harness (test/screenshots/): en,es,fr,de,pt,ja + RTL demo,
  real fonts via DejaVu Sans + FontManifest; skip-by-default tag so CI stays
  green. collect_screenshots.sh feeds site/ and fastlane phoneScreenshots.
- Drop editorial notes from the public explainer.
2026-07-15 02:21:42 +02:00
7a82505a4e feat(plantare): tie the propose form to a real seed
The propose sheet used a free-text seed name, unlinked from the
inventory. Now the seed is picked from your catalogued varieties so the
Plantaré is always tied to a real Variety (tap-through to its detail, and
it shows in that seed's commitments):

- Seed field is an Autocomplete over the inventory; on send the typed name
  resolves to the matching Variety, or creates a quick one if it's new —
  so varietyId is never null. Sheet takes the VarietyRepository; chat
  passes it.
- New repo one-shot `varietyLabels()` (id + label, no joins) feeds the
  picker. Deliberately a Future, not `watchInventory()` — a transient
  sheet must not hold a live Drift subscription (that hung the widget test
  ~36 min). Tests use it too and now run in ~2s with bounded pumps + a
  tall surface, no pumpAndSettle.

Tests: a new name creates & links a Variety; a matching name links the
existing one without duplicating. ui/services/data plantare suites green.
2026-07-15 01:24:50 +02:00
e78656bc07 feat(plantare): UI — propose from chat, review & sign on the ledger
The viral loop, made usable end-to-end:

- Propose sheet (plantare_propose_sheet.dart): from a chat with a peer
  (their key already in hand), pick your side, name the seed, choose what
  comes back (similar · non-GMO organic / work hours / other) and an
  optional return-by, then sign and send. Reached from the chat overflow
  menu; confirms "waiting for them to sign".
- Plantares screen: incoming proposals show Accept & sign / Decline right
  on the tile; every bilateral row wears a handshake badge — awaiting
  signature, signed by both, or declined. Accept falls back to a gentle
  "offline" nudge if the proposal isn't in hand yet.
- i18n: full en + es for the bilateral flow; other locales fall back to
  base per slang config.

Wire-up only touches human copy (no jargon) and stays behind the
optional PlantareService, so inventory-only builds are unaffected.

Tests: propose sheet drives a real sign+send; the ledger renders the
signed/awaiting badges. Fake SocialSession in your_people test gains the
new transport getter. Widget tests targeted + timed. All green.
2026-07-14 11:23:09 +02:00
b607ddde41 feat(plantare): PlantareService — orchestrate the signed handshake
The app-layer driver that turns local intent into a signed proposal,
counter-signs or declines incoming ones, and reconciles every move into
the local ledger. Cryptography and wire format stay in commons_core;
this owns persistence and orchestration.

- propose(): builds + self-signs a PlantarePledge, records the local row
  (remoteState=proposed, my stub) and sends it. Direction maps to
  debtor/creditor: iReturn = I received and owe, owedToMe = I gave.
- accept(): counter-signs the exact in-hand proposal (verified) and sends
  the doubly-signed copy back, closing the row.
- decline(): notifies the proposer and marks the row declined.
- ingest(): verifies stubs before storing — a bad-signature proposal or a
  half-signed "accept" is dropped; proposals not addressed to me are
  ignored. Pending proposals held in memory keyed by pledge id (relay
  redelivers on reconnect), so accept signs the verified payload.

Wired into DI + Bootstrap alongside the inbox/sync listeners and torn
down/rebuilt on identity switch. SocialSession now exposes the transport.

Tests: full propose→accept close, decline, and the three drop paths with
a records-only transport + real repos. services/data green.
2026-07-14 11:21:46 +02:00
01fba40ec2 feat(plantare): schema v12 — bilateral signed columns + repo
Adds the deferred bilateral columns to Plantares (plantare-bilateral.md
§"Schema delta"), all nullable/defaulted so v1 local rows coexist
untouched:

- pledgeId (the shared id both parties key their row by), debtorKey /
  creditorKey, debtorSignature / creditorSignature, movementId (the
  shared hand-over Movement for the provenance DAG), remoteState
  (proposed/accepted/declined — the handshake, distinct from status),
  returnKind (similar/workHours/other, default similar) + workHours.

Repo: createPlantare grows optional bilateral params; plantareByPledgeId
looks a row up by the shared id; applyPlantareSignatures counter-stamps
an incoming accept; setPlantareRemoteState records a decline. The
JSON codec carries every new field so they ride backups.

Versioned migration is guarded/idempotent like the others; schema v12
dumped, test helper regenerated, migration test covers v1..v11 → v12.
db + data + services 295/295 green.
2026-07-14 11:21:46 +02:00
7ae6becd8f feat(i18n): full RTL/CJK support — fonts, Japanese locale, directional fixes
Bundle Noto Sans Arabic + Noto Sans JP (SIL OFL 1.1) as per-glyph fallbacks
for both the UI text theme and every generated PDF, so RTL (Arabic) and CJK
render on all platforms — including desktop, where the system font may lack
them — instead of tofu. A shared pdf_fonts.dart centralizes the PDF theme and
the three label/catalog/recovery services reuse it.

Add Japanese (ja) as the CJK reference locale — fittingly, the app's own name
is Japanese (種, tane, 'seed'). Core strings translated; the rest fall back to
English via slang. Wired into supportedLocales (automatic) and the settings
picker.

Fix three physical Alignment.centerLeft -> AlignmentDirectional.centerStart in
variety_detail_screen, and make month-abbreviation and avatar-initial
truncation grapheme-safe (.characters) so CJK text is never cut mid-character.

Tests: CJK/Arabic PDF glyph render, ja locale resolution + English fallback.
The chat-bubble mirroring flagged by the audit was verified correct (already
respects Directionality) and left unchanged.
2026-07-14 11:11:19 +02:00
fe4591d747 feat(settings): collapse language list into a picker
The flat list of 6 languages plus 'system' dominated Settings. Replace it
with a single tile showing the current language, opening a bottom-sheet
picker (all languages + 'System language'). Resolve LocaleStore defensively
so the screen renders in DI-less widget tests.
2026-07-13 18:11:42 +02:00
b04d45c4b8 feat(i18n): add French and German translations
Full fr/de translations of the app (625 keys each), wired into the
Settings language picker and the small-screen overflow test. Material
ships fr/de localizations, so chrome resolves natively.
2026-07-13 18:11:42 +02:00
adf396d49d feat(plantare): surface product link + dates; spec the bilateral record
The Plantaré screen stored madeOn/dueBy/varietyId but showed none of them,
so it felt half-built. Surface what's already there (no schema change):

- watchPlantareViews() joins each commitment with its variety label
- tile shows the made-on date, a "Return by {date}" line (amber + "overdue"
  when an open promise is past due, via new seedWarning colour), the variety
  name, and taps through to /variety/:id
- add sheet gains an optional return-by date picker (createPlantare already
  took dueBy)
- variety detail shows a read-only commitments section (hidden when empty,
  no add button — honours the single hand-over door)
- i18n en/es/pt/ast; tests for the join, dueBy round-trip, tile, and section

Also specs the deferred two-sided record in docs/design/plantare-bilateral.md
(Nostr pubkey counterparty, PlantareTransport propose->accept->counter-sign,
deferred key/signature/movement columns, provenance DAG, reputation anchor),
with a faithful transcription of the paper Plantaré v0.4 (BAH-Semillero 2009,
CC-BY-SA). Cross-linked from data-model §2.7 and sharing-model §6.
2026-07-13 18:06:33 +02:00
e57763d0a2 fix(chat): collapse trust/rating strips while the keyboard is open
On short screens (e.g. landscape) the fixed-height trust and rating
strips plus the composer overflowed the body once the keyboard shrank
it. Wrap the two secondary strips in HideWhenKeyboardOpen so they yield
their vertical space while typing and reappear when the keyboard closes.
2026-07-13 17:19:47 +02:00
7d2d466fee fix(market): red favorite heart so it pops on the green theme 2026-07-13 17:11:31 +02:00
0e7faaeb90 feat(social): standard NIP-56 reporting — ReportTransport in commons_core, report sheet on offers and chats, local hide + optional block 2026-07-13 08:26:38 +02:00
11b242edbf feat(social): local blocklist — hide blocked authors' offers, chats and incoming messages, with unblock management 2026-07-13 08:25:49 +02:00
5d25f65f76 feat(market): one-time community-rules gate before joining the market, publishing or messaging 2026-07-13 08:24:59 +02:00
a7e10eba7a feat(legal): in-app Privacy & rules screen with plain-words summaries and links to the full documents 2026-07-13 08:24:59 +02:00
9668e0e70b feat(i18n): legal, market-gate, report and block strings (en/es/ast/pt) 2026-07-13 08:24:59 +02:00
d6225eed38 feat(market): save others' offers as favorites (Wallapop-style)
Adds a Favorites feature: a heart on the offer detail saves another
person's listing to an encrypted, per-identity SavedOffersStore
(keystore JSON snapshot, no plaintext at rest). A new /favorites screen
(wired from the drawer) lists saved offers offline-first and, when a
relay is reachable, flags ones that are gone as "no longer available".
i18n en/es/pt/ast; store + screen + detail-heart tests.
2026-07-13 08:21:43 +02:00
f6967e8cbb feat(profile): Material default avatar + square photo crop
Drop the DiceBear generated avatar (and dicebear_core/dicebear_styles/
flutter_svg): the default is again a Material coloured-initial disc from
the pubkey. Picking a photo now goes through a square crop step
(crop_your_image — pure Flutter, all platforms incl. desktop, Apache-2.0,
only pulls the image package we already had) before the 24 KB thumbnail.
2026-07-12 23:39:56 +02:00
17612b8147 feat(profile): drop seed-glyph illustrations from the avatar picker
The picker now offers only a photo; with none, the generated DiceBear
avatar is used. Removes the seedks-ttf illustration row (and the now-dead
avatarGlyphNames/avatarGlyphToken). tane:seed:<glyph> values set before
this still render (avatarGlyphChar kept) for backward compatibility.
2026-07-12 23:22:20 +02:00
109c85298c feat(profile): default avatars via DiceBear "thumbs" (CC0), drop boring_avatars
Replace the flutter_boring_avatars fallback with a friendly DiceBear
"thumbs" face, generated offline (dicebear_core) and deterministically
from the pubkey, rendered as SVG (flutter_svg). The thumbs style is
CC0 1.0 (public domain) — no attribution, AGPL-clean — unlike Multiavatar
whose custom licence restricts use. Style parsed once and per-pubkey SVG
memoized; the CC0 <metadata> block is stripped to keep flutter_svg quiet.
2026-07-12 21:59:10 +02:00
1c2b3d5e8d feat(profile): generated default avatars (boring-avatars beam) from pubkey
People without a photo or seed illustration now get a deterministic
pattern avatar drawn from their pubkey (flutter_boring_avatars, MIT),
in an earthy seed-tone palette, replacing the coloured-initial disc.
Same pubkey renders the same picture on every device with nothing shared.
2026-07-12 21:59:10 +02:00
e65d82017a Merge Tanemaki → Tane rename into main 2026-07-12 13:37:25 +02:00
879eb5b58a remove unused import 2026-07-12 13:35:24 +02:00
af62ca3c03 Merge main (handover test-fix d51d3d7) into Tane rename 2026-07-12 13:28:58 +02:00
51e6bf019d docs(store): rename Tanemaki → Tane in Play Store metadata and mockups
Fastlane title.txt + full_description.txt (en-US, es-ES) now lead with
Tane and keep tanemaki (種まき) as etymology; CI comment and the Material
mockups updated too.
2026-07-12 13:16:53 +02:00
9648c710a7 fix(branding): rename remaining Tanemaki → Tane in platform metadata
Web PWA manifest name, index.html <title> and apple-mobile-web-app-title,
and the Windows executable ProductName / FileDescription.
2026-07-12 13:15:33 +02:00
a534c14983 refactor(branding): rename app Tanemaki → Tane
Public name is now Tane (種, "seed"); Tanemaki (種まき, "to scatter seeds")
is kept only as etymology in the About screen and onboarding.

App not yet distributed, so format tokens rename cleanly with no migration:
backup extension .tanemaki→.tane, QR scheme tanemaki://→tane://, file
prefixes tane-*. Website link and species-catalog User-Agent →
tane.comunes.org. Android label capitalised to "Tane".

Identity/crypto constants already use org.comunes.tane (derivation, HKDF
backup, sync namespace, TANE1 recovery tag) — left untouched, so keys,
backups and sync are unaffected. Tests updated; analyze + full suite green.
2026-07-12 13:04:16 +02:00
d51d3d7057 test(fix): stop handover widget test hanging on awaited stream .first
The 'giving all with payment and promise' widget test awaited
repo.watchSales().first / watchPlantares().first in its body. A Drift
stream's .first never completes under the widget-test fake-async clock
(pumpAndSettle has already returned, so dart_test.yaml's per-test timeout
can't bound it), so the test hung to the framework's 10-min hard cap.

- Read the recorded sale/plantare with one-shot db.select(...).get()
  queries instead (same filter, resolves fine under fake-async) — the
  suite now passes in ~1s.
- Add a pure-Dart guard test that scans test/ui/ and fails loudly if any
  awaited watchX().first reappears, so this stops being recurrent.
2026-07-12 08:17:12 +02:00
2c113cc17d fix(inventory): move 'clear filters' to its own line below the chips
Pinning it beside the horizontal scroll squeezed the chips into a narrow
strip and clipped them under the edge fade (e.g. 'Comparto' cut off by
the scroll arrow). Now the chips get the full width and 'clear filters'
sits on its own line below, shown only when a filter is active.
2026-07-12 07:35:20 +02:00
6eafdfdfbb fix(ux): filter clear pinned, no-match text, instant avatar save, market avatar, favourites, WoT drawer
Six reported UX issues:
- Inventory 'clear filters' is now pinned outside the horizontal scroll,
  always visible — you no longer have to scroll past every chip to find it.
- Empty result now reads 'No seeds match your filters' (not 'no seeds
  yet') when a SEARCH or the 'this month' filter hid everything — the
  'filtered' flag was missing query + sowThisMonthOnly. Guarded by a test.
- Profile avatar saves + publishes the instant you pick it, so it no
  longer looks saved when it wasn't (the Save button sits below the fold).
- Market offer detail shows the author's real avatar (photo/illustration)
  instead of a generic person icon — resolves + caches their kind:0 picture.
- 'Wishlist' renamed to Favourites/Favoritos (en/es/pt/ast).
- The drawer 'following' item now opens the web-of-trust 'your people'
  screen when the social layer is on (was a dead item).

analyze clean; inventory/market/home + overflow suites green.
2026-07-12 02:56:08 +02:00
51d6924464 feat(profile): show other people's avatars in chat, chat list, your people
Follow-up to the avatar feature: peers' published photos/illustrations
now actually render where people appear.

- CachedAvatar: a PeerAvatar that resolves the person's picture from the
  ProfileCache (FutureBuilder), falling back to the coloured-initial disc.
  For list/row sites — one avatar each.
- Chat bubbles: the peer's and my own avatar are resolved once into state
  (_peerPicture/_selfPicture — from the cache / ProfileStore, freshened
  from the peer's published profile) and threaded to each bubble, so many
  bubbles of two people don't each hit the cache.
- Chat list + your-people rows: swapped the static person-icon disc for
  CachedAvatar, so photos/illustrations show there too.
- Tests: CachedAvatar render modes (cached illustration / initial / no
  cache). analyze clean; chat + your-people suites green.

Market offers show no author avatar today (would be a new element, not a
swap) — left out of scope.
2026-07-11 22:50:10 +02:00
ec56819fbf feat(profile): profile photo or seed-illustration avatar
Profiles had only a coloured-initial disc. Now each person can set an
avatar — a real photo OR one of our own seed illustrations (so
pseudonymity stays the default; no photo required).

- ui/avatar.dart: the one-string value scheme carried in the kind:0
  'picture' — a 'data:' photo thumbnail, a 'tane:seed:<glyph>' token, or
  empty. The Nostr ProfileTransport already published 'picture'.
- Photos ride inline as a tiny thumbnail (reuses offerThumbnailDataUri,
  24 KB cap) — no media server, like offer photos.
- avatar_edit.dart: pick/take a photo, choose a seed illustration, or
  remove; ProfileStore stores it; ProfileScreen shows a big editable
  avatar and publishes it.
- PeerAvatar renders photo / illustration / initial fallback.
- ProfileCache gains picture/setPicture; the inbox caches peers' avatars
  alongside their names.
- i18n avatar block (en/es/pt/ast). Tests: value scheme + PeerAvatar
  render modes, store + cache round-trips.

Follow-up: render peers' avatars in chat/market/your-people (thread the
cached picture into PeerAvatar at each call site).
2026-07-11 22:21:52 +02:00
6898e385e8 polish(detail): TODO review — calendar intro, drop abundance, collapse seed-saving
From the owner's TODO.org review of the shipped features:
- Crop calendar now says the months are YOUR notes: a hint line in the
  editor (cropCalendar.editorHint) and a caption under the 'this month'
  screen (calendar.selfNote) — it read as if the app knew when to sow.
- Dropped the 'how much I have' (abundance) input + display: it competed
  with the lot quantity as a second 'how much'. Removed from the lot sheet
  and the lot summary; the DB column + backup/CSV/catalog plumbing stay
  dormant (no destructive migration). offer_status carries 'do I share'.
- Seed-saving guidance moved into a collapsed expander (detail.seedSaving)
  — reference facts about the species shouldn't sit open among the
  grower's own records; opt-in depth, per progressive disclosure.
- Condition checks already live behind the collapsed 'advanced' expander
  (seed lots only) — left as the discreet power-user surface.

Tests: dropped the obsolete abundance→share nudge test; the seed-saving
section test now expands before asserting. analyze clean; suites green.
2026-07-11 14:08:10 +02:00
00db9d4b6a Merge remote-tracking branch 'origin/main'
# Conflicts:
#	apps/app_seeds/lib/i18n/strings.g.dart
#	apps/app_seeds/lib/state/inventory_cubit.dart
2026-07-11 13:31:04 +02:00
15511ee761 Merge branch 'claude/festive-einstein-384c45'
Ego-centric trust replaces the global Duniter WoT, plus Wallapop-style
ratings v1 (kind 30778). Conflicts resolved: pubspec assets (kept
seed_saving, dropped trust referents), chat_screen (avatars/no-links
from main + rating strip and simplified TrustCubit from the branch),
strings.g.dart regenerated from merged sources.
2026-07-11 13:25:51 +02:00