Skip to content

Add XP, levels and profile cosmetics - #65

Closed
professorDeveloper wants to merge 1 commit into
next/3.3.0from
feat/xp-levels
Closed

professorDeveloper wants to merge 1 commit into
next/3.3.0from
feat/xp-levels

Conversation

@professorDeveloper

Copy link
Copy Markdown
Owner

Adds XP, levels and profile cosmetics. Needs professorDeveloper/sozo-backend#78 for anything to show; without it every decoration stays hidden and the app behaves as before.

What it adds

  • lib/features/progress/:
    • domain/progress.dart: the level curve (level n needs floor(100·n^1.5) XP, the same as the server), LevelProgress for the ring, and lenient parsing of /progress answers and of the level / frame / title / nameColor fields on cards.
    • data/progress_service.dart: the active profile's progress, cached per household profile, and level-up detection against the last level seen. The first level ever seen is a baseline, not a celebration.
    • data/watch_time_uploader.dart: sends WatchStatsStore.byDay to POST /api/progress/watch-time as each day's running total for today and yesterday. It sends every ten minutes while the player ticks and when the app goes to the background (paused or hidden). Offline is handled by comparing against the last total sent, so nothing extra is stored. A random per-install device id lets two devices add up; it is kept out of backups.
    • presentation/pages/progress_page.dart (/progress): level ring, XP to the next level, today's watch XP against the cap, how XP is earned, recent gains, and the locker. Tap an unlocked item to equip it, tap again to take it off. Locked items say which level or badge unlocks them. StreakBadge, which was unused, now sits in the app bar here.
    • presentation/widgets/user_badge_line.dart: FramedAvatar, UserBadgeLine, LevelChip and the Cosmetics id → colour/words table.
    • presentation/dialogs/level_up_dialog.dart, shown by AchievementCelebrationHost after any badge dialog, never over the player.
  • Used in: comment cards (frame, name colour, level chip), SocialAvatar (so every social list gets the frame), SocialUserTile, other users' profile header (with title), activity card actor line, and the own profile header (frame, name colour, level link to /progress).
  • Signing out clears the cached progress and the upload state, and a profile switch flushes pending watch time first.
  • 62 new progress.* keys in all 16 locales, translated.
  • Tests: test/features/progress/progress_test.dart covers the level curve, parsing, level-up detection, upload batching, offline retry and replay safety.

Not done

  • Watch Party member bar: PartyMember carries no level or cosmetics, so decorating it needs a backend watch-party change too. Not a trivial import, and another branch is editing watch party, so it is left out.

Not verified

  • Nothing was run locally (no flutter on this machine by the owner's rule). CI is the only check.
  • No device or emulator run, so the look of frames, the locker and the level-up dialog is unchecked.

A progress page with the level ring, recent XP and a locker for avatar
frames, titles and name colours. Watch time goes to the server every ten
minutes while playing and when the app goes to the background, as each
day's running total so a retry adds nothing. Comment authors, social
cards, activity cards and the profile header show the frame, name colour
and level. A level-up is celebrated by the achievement celebration host.
Nothing shows until the server answers /progress.
@professorDeveloper

Copy link
Copy Markdown
Owner Author

Combined into one PR against release/3.2.1.

@professorDeveloper
professorDeveloper deleted the feat/xp-levels branch November 7, 2026 13:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant