Skip to content

feat: share saves & states with other users#3569

Merged
zurdi15 merged 5 commits into
masterfrom
feat/share-savestates
Jun 21, 2026
Merged

feat: share saves & states with other users#3569
zurdi15 merged 5 commits into
masterfrom
feat/share-savestates

Conversation

@zurdi15

@zurdi15 zurdi15 commented Jun 21, 2026

Copy link
Copy Markdown
Member

Description
Explain the changes or enhancements you are proposing with this pull request.

Brings the share-with-other-users behavior that v2 notes and screenshots already have to saves and states — owners flip a per-item public/private toggle and everyone else sees the public items in a read-only Community section alongside their own Mine section. Saves/states are RomAssets like screenshots, so the implementation reuses the exact same end-to-end pattern instead of inventing anything new.

The Save data subtab is also unified with the Play view by extracting AssetList (saves) and AssetStrip (states) into components/shared/ and generalising them so both contexts render the same visuals — saves as an info-dense list, states as 16:9 cards. A small Play-view nit was bundled in: the Saves/States slider tab count is now a pill instead of a · N text concatenation.

Backend (sharing)

  • Save.is_public / State.is_public columns + migration 0087_save_state_visibility.
  • UserSaveSchema / UserStateSchema enriched with username / user_avatar_path / user_updated_at (mirrors UserScreenshotSchema).
  • get_rom_shared_{saves,states}(rom_id, user_id, public_only=False) → own (public + private) ∪ others' public, mirroring get_rom_gallery_screenshots.
  • PUT /saves/{id}/visibility and PUT /states/{id}/visibility (owner-only). Save download relaxed to allow public items from other users; device-sync side effects stay gated to the owner.
  • DetailedRomSchema gains all_user_saves / all_user_states, populated alongside all_user_screenshots.

Frontend (v2)

  • Regenerated OpenAPI types; saveApi.setSaveVisibility / stateApi.setStateVisibility.
  • SaveDataTab restructured into Mine / Community sections per subtab: own items show toggle (mdi-lock / mdi-lock-open-variant) + download + delete; community items show author chip + download.
  • AssetList and AssetStrip moved to components/shared/ and generalised with selectable / selectedId / showOwner / scrollable (list) / wrap (strip) + #actions slot. EmulatorJS still uses them in select mode; SaveDataTab uses them in manage mode.
  • SliderBtnGroupItem.badge field; RSliderBtnGroup renders it as an inline count pill, replacing the previous ${label} · ${count} string.
  • i18n keys (saves-section-mine / saves-section-community / states-section-mine / states-section-community / cant-toggle-visibility) added to every locale dir; en_US source of truth + Spanish translated, rest copy English as placeholder per CLAUDE.md §VII.12.

Checklist
Please check all that apply.

  • I've tested the changes locally
  • I've updated relevant comments
  • I've assigned reviewers for this PR
  • I've added unit tests that cover the changes

Per the v2 constitution (§VII.16-17, §VIII.10) Vitest covers pure logic and Storybook play() covers components. The full suite (npm run test → 12 files, 415 tests) plus npm run typecheck, ESLint, and python3 frontend/src/locales/check_i18n_locales.py all pass; the shared AssetList / AssetStrip stories continue to render and exercise their interactions through composeStories.

Screenshots (if applicable)

image image

zurdi15 and others added 3 commits June 21, 2026 14:00
…ections

- Introduced new API endpoints for updating visibility of saves and states.
- Added `is_public` property to `SaveSchema` and `StateSchema`.
- Created new models for user saves and states with visibility attributes.
- Updated the `SaveDataTab` component to differentiate between "Mine" and "Community" sections.
- Implemented visibility toggle functionality for user saves and states.
- Enhanced localization files to include new strings for visibility actions.
…states

- Introduced AssetList.vue for displaying a vertical list of saves with detailed information.
- Added AssetStrip.vue for a horizontal strip of state tiles, supporting selection and management modes.
- Created stories for AssetStrip to demonstrate various states and scenarios.
- Enhanced RSliderBtnGroup to include a badge for displaying counts next to labels.
- Updated EmulatorJS.vue to utilize the new AssetList and AssetStrip components, including badge counts for saves and states.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 21, 2026 15:25
@zurdi15 zurdi15 linked an issue Jun 21, 2026 that may be closed by this pull request
@zurdi15 zurdi15 changed the title feat: share saves & states with other users (v2) feat: share saves & states with other users Jun 21, 2026
@zurdi15 zurdi15 self-assigned this Jun 21, 2026
@github-actions

github-actions Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Test Results (mariadb)

    1 files      1 suites   2m 26s ⏱️
1 718 tests 1 718 ✅ 0 💤 0 ❌
1 720 runs  1 720 ✅ 0 💤 0 ❌

Results for commit 91640c3.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

☂️ Python Coverage

current status: ✅

Overall Coverage

Lines Covered Coverage Threshold Status
18188 13218 73% 0% 🟢

New Files

No new covered files...

Modified Files

File Coverage Status
backend/endpoints/responses/assets.py 93% 🟢
backend/endpoints/responses/rom.py 94% 🟢
backend/endpoints/saves.py 71% 🟢
backend/endpoints/states.py 36% 🟢
backend/handler/database/saves_handler.py 93% 🟢
backend/handler/database/states_handler.py 88% 🟢
backend/models/assets.py 96% 🟢
TOTAL 82% 🟢

updated for commit: 91640c3 by action🐍

@github-actions

github-actions Bot commented Jun 21, 2026

Copy link
Copy Markdown
Contributor

Test Results (postgresql)

    1 files      1 suites   2m 28s ⏱️
1 718 tests 1 718 ✅ 0 💤 0 ❌
1 720 runs  1 720 ✅ 0 💤 0 ❌

Results for commit 91640c3.

♻️ This comment has been updated with latest results.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds per-save/per-state public sharing (mirroring v2 screenshots/notes) and refactors the v2 UI so saves/states can be managed in “Mine” vs “Community” sections using shared list/strip components.

Changes:

  • Backend: introduce is_public for saves/states, add visibility toggle endpoints, and expose combined all_user_saves/all_user_states on DetailedRomSchema.
  • Frontend: update Save Data tab into Mine/Community, add visibility toggle actions, and regenerate OpenAPI types.
  • UI primitives: add badge support to RSliderBtnGroup and migrate AssetList/AssetStrip into components/shared/.

Reviewed changes

Copilot reviewed 36 out of 45 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
frontend/src/v2/views/Player/EmulatorJS.vue Switches to shared AssetList/AssetStrip and uses new badge field for tab counts.
frontend/src/v2/lib/primitives/RSliderBtnGroup/types.ts Adds badge field to slider button items.
frontend/src/v2/lib/primitives/RSliderBtnGroup/RSliderBtnGroup.vue Renders the new badge pill and adds styling.
frontend/src/v2/components/shared/AssetStrip.vue Generalizes state/save strip into shared selectable/manage modes with owner chip + actions slot.
frontend/src/v2/components/shared/AssetStrip.stories.ts Moves Storybook namespace from Player to Shared.
frontend/src/v2/components/shared/AssetList.vue Generalizes save list into shared selectable/manage modes with owner chip + actions slot.
frontend/src/v2/components/shared/AssetList.stories.ts Moves Storybook namespace from Player to Shared.
frontend/src/v2/components/Player/ResumePanel.stories.ts Updates story imports to use shared AssetList/AssetStrip.
frontend/src/v2/components/GameDetails/SaveDataTab.vue Splits saves/states into Mine vs Community, adds visibility toggles, and uses shared components.
frontend/src/services/api/state.ts Adds setStateVisibility API call.
frontend/src/services/api/save.ts Adds setSaveVisibility API call.
frontend/src/locales/zh_TW/rom.json Adds new Mine/Community section labels + toggle-visibility error key.
frontend/src/locales/zh_CN/rom.json Adds new Mine/Community section labels + toggle-visibility error key.
frontend/src/locales/ru_RU/rom.json Adds new Mine/Community section labels + toggle-visibility error key.
frontend/src/locales/ro_RO/rom.json Adds new Mine/Community section labels + toggle-visibility error key.
frontend/src/locales/pt_BR/rom.json Adds new Mine/Community section labels + toggle-visibility error key.
frontend/src/locales/pl_PL/rom.json Adds new Mine/Community section labels + toggle-visibility error key.
frontend/src/locales/ko_KR/rom.json Adds new Mine/Community section labels + toggle-visibility error key.
frontend/src/locales/ja_JP/rom.json Adds new Mine/Community section labels + toggle-visibility error key.
frontend/src/locales/it_IT/rom.json Adds new Mine/Community section labels + toggle-visibility error key.
frontend/src/locales/hu_HU/rom.json Adds new Mine/Community section labels + toggle-visibility error key.
frontend/src/locales/fr_FR/rom.json Adds new Mine/Community section labels + toggle-visibility error key.
frontend/src/locales/es_ES/rom.json Adds new Mine/Community section labels + toggle-visibility error key (Spanish translated).
frontend/src/locales/en_US/rom.json Adds new Mine/Community section labels + toggle-visibility error key (source locale).
frontend/src/locales/en_GB/rom.json Adds new Mine/Community section labels + toggle-visibility error key.
frontend/src/locales/de_DE/rom.json Adds new Mine/Community section labels + toggle-visibility error key.
frontend/src/locales/cs_CZ/rom.json Adds new Mine/Community section labels + toggle-visibility error key.
frontend/src/locales/bg_BG/rom.json Adds new Mine/Community section labels + toggle-visibility error key.
frontend/src/generated/models/UserStateSchema.ts Adds generated “community” state schema enriched with owner info.
frontend/src/generated/models/UserSaveSchema.ts Adds generated “community” save schema enriched with owner info.
frontend/src/generated/models/StateSchema.ts Adds is_public field to generated state schema.
frontend/src/generated/models/SaveSchema.ts Adds is_public field to generated save schema.
frontend/src/generated/models/LogEntrySchema.ts Adds generated log entry schema (from OpenAPI regen).
frontend/src/generated/models/DetailedRomSchema.ts Adds all_user_saves/all_user_states fields to generated detailed ROM schema.
frontend/src/generated/models/Body_update_state_visibility_api_states__id__visibility_put.ts Adds generated request body type for state visibility endpoint.
frontend/src/generated/models/Body_update_save_visibility_api_saves__id__visibility_put.ts Adds generated request body type for save visibility endpoint.
frontend/src/generated/index.ts Exports newly generated models/types.
backend/models/assets.py Adds is_public columns to Save and State models.
backend/handler/database/states_handler.py Adds get_state_by_id and get_rom_shared_states queries.
backend/handler/database/saves_handler.py Adds get_save_by_id and get_rom_shared_saves queries.
backend/endpoints/states.py Adds owner-only PUT /states/{id}/visibility.
backend/endpoints/saves.py Allows public download for non-owners and adds PUT /saves/{id}/visibility.
backend/endpoints/responses/rom.py Populates all_user_saves/all_user_states on detailed ROM responses.
backend/endpoints/responses/assets.py Adds is_public to Save/State schemas and introduces UserSaveSchema/UserStateSchema.
backend/alembic/versions/0087_save_state_visibility.py Migration to add is_public + indexes on saves/states tables.
Files not reviewed (9)
  • frontend/src/generated/index.ts: Generated file
  • frontend/src/generated/models/Body_update_save_visibility_api_saves__id__visibility_put.ts: Generated file
  • frontend/src/generated/models/Body_update_state_visibility_api_states__id__visibility_put.ts: Generated file
  • frontend/src/generated/models/DetailedRomSchema.ts: Generated file
  • frontend/src/generated/models/LogEntrySchema.ts: Generated file
  • frontend/src/generated/models/SaveSchema.ts: Generated file
  • frontend/src/generated/models/StateSchema.ts: Generated file
  • frontend/src/generated/models/UserSaveSchema.ts: Generated file
  • frontend/src/generated/models/UserStateSchema.ts: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread frontend/src/locales/en_US/rom.json Outdated
Comment thread frontend/src/locales/en_GB/rom.json Outdated
Comment thread frontend/src/v2/lib/primitives/RSliderBtnGroup/RSliderBtnGroup.vue Outdated
Comment thread frontend/src/v2/lib/primitives/RSliderBtnGroup/RSliderBtnGroup.vue Outdated
zurdi15 and others added 2 commits June 21, 2026 15:45
Notes already paints the lock button primary when private and muted when
public; bring screenshots and the new saves/states toggles to the same
binding so the three visibility surfaces read consistently.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* i18n `rom.cant-toggle-visibility` is interpolated with `{error}` in
  SaveDataTab but the strings dropped the placeholder, hiding the
  backend error detail from the snackbar. Add `{error}` to every locale
  (en_US source + es_ES translated, others English placeholder).
* `RSliderBtnGroup` badge visibility check did not handle the string
  `"0"` / `""` cases allowed by the `string | number | null` type.
  Extract a `showBadge` helper and use it in both the router-link and
  RBtn branches.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@zurdi15
zurdi15 requested a review from gantoine June 21, 2026 15:58
@zurdi15
zurdi15 merged commit ee33bf1 into master Jun 21, 2026
18 checks passed
@zurdi15
zurdi15 deleted the feat/share-savestates branch June 21, 2026 19:18
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.

[Feature] Share Save States/Save Files with other users

2 participants