Migrate rest of modules to pinia, remove vuex, replace lodash with lodash-es #3571

Merged
hj merged 41 commits from vuex-removal into develop 2026-09-03 22:00:40 +00:00
Member
No description provided.
hj added 24 commits 2026-09-02 19:30:22 +00:00
fix
Some checks failed
ci/woodpecker/pr/test-e2e Pipeline is pending
ci/woodpecker/pr/test Pipeline is pending
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/changelog Pipeline failed
ci/woodpecker/pr/lint Pipeline was canceled
71a9851881
changelog i guess
All checks were successful
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/changelog Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/test-e2e Pipeline was successful
88271d3bbc
leftover
All checks were successful
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/changelog Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/test-e2e Pipeline was successful
2731ea81cb
Author
Member

/oc review

/oc review
opencode-fix-bot left a comment

opencode-agent:job=80:generation=1

Automated review of d603aac32731ea81 (27 commits, 58 files, +890/−1183), done for /oc review.

Verdict

A thorough, near-complete vuex → pinia migration: no vuex / $store / window.vuex / vuex mapGetters / commit / dispatch references remain anywhere in src/ or test/, the removed modules/{api,drafts,index}.js have no dangling importers, and the unit suite passes at the same level as develop (418 passed / 1 failed / 2 skipped — the one failure and the two MSW-dependent spec files fail identically at base; verified by running the suite at both commits). But there are a few small, real regressions I'd want fixed before merge.

Should fix (likely regressions)

  1. src/stores/users.js:709 — typo error.tatusCode (was error.statusCode), so a 401 login failure reports the generic "An error occurred…" instead of "Wrong username or password". Not caught by tests: the bad-credentials spec uses 403.
  2. src/components/emoji_input/suggestor.js:18const usersCurry = data.store && suggestUsers(data.store) still gates on data.store, but this PR removed store: this.$store from both callers (post_status_form.js / user_card.js emojiUserSuggestor). Net effect: @-mention user suggestions are dead in the composer and user-card fields. suggestUsers() is arg-less and pinia-based, so the gate can simply be dropped.
  3. src/components/side_drawer/side_drawer.js:113mapState(useDraftsStore, ['draftCount']), but the pinia getter is draftsCount (src/stores/drafts.js:50). The drafts badge in the side drawer is always undefined/hidden. Renamed correctly everywhere else — this one spot was missed.
  4. src/stores/drafts.js:61 (loadDrafts)new Map(Object.entries(currentData)) throws when the pleroma-fe-drafts key is absent (localforage resolves null; Object.entries(null) → TypeError). The old vuex module guarded with || {}; the new saveDraftToStorage/deleteDraftFromStorage helpers kept ?? {}, but loadDrafts didn't. loginUser calls it un-awaited, so most users get an unhandled rejection and no drafts on every login.
  5. Shout init race — the instance_capabilities.js hook that called initializeSocket when shoutAvailable arrived from nodeinfo was removed; loginUser now checks shoutAvailable itself (users.js:667), but checkOAuthToken and getNodeInfo run concurrently in after_store.js's Promise.all. If login resolves before nodeinfo, the shout socket is never initialized for the session.
  6. src/stores/shout.js:13,17token is declared in both state and getters; pinia warns "A getter cannot have the same name as another state property" and the getter shadows the always-dead token: null state (verified against pinia 3). Drop the state field.

Notes / nits

  • lodash-es: the title says "replace lodash with lodash-es", but nothing imports lodash-es (0 occurrences in src/ and test/); 66 app files still import … from 'lodash' (CJS), lodash was dropped from dependencies, and lodash-es sits unused in devDependencies. The build only keeps working because hoisted transitive lodash@^4.17.21 remains in yarn.lock — an undeclared direct dependency. Removing babel-plugin-lodash also means full-CJS lodash gets bundled. Either migrate the imports to lodash-es or keep lodash as an explicit dependency.
  • src/stores/drafts.js:70abandonAllDrafts(store) has a stray vuex-era store arg, and it double-deletes: each abandonDraft already removes the draft from storage, then the bulk deleteDraftFromStorage(ids) runs again.
  • src/stores/follow_requests.js — throws bare strings in startFetching/stopFetching; stopFetching uses a comma-operator one-liner; the store ↔ stores/fetchers/follow_requests.js import cycle only works because usage is deferred to call time.
  • follow_request_card.js doDeny now marks the notification seen, while notification.js doDeny still dismisses it — inconsistent UX for the same action.
  • The new stores (drafts, followRequests, profileConfig) and the new loginUser/logout branches (profileConfig onLogin/onLogout, shout gating, locked-user follow-request fetching) have no direct test coverage; the post_status_form draft specs themselves were ported faithfully.
  • Test-only: the "failed logout" spec doesn't stub useFollowRequestsStore().startFetching(), so a real fetcher starts a 10 s polling loop during tests (was a no-op fallback at base).

What looks good

  • The vuex removal itself is complete and clean; after_store.js threading updated, mock_store.js removed with no leftover test scaffolding.
  • piniaPersistPlugin keeps the vuex-lz localStorage fallback so existing users' persisted state migrates per-store — nice touch.
  • Navigation badge refactor (badges maps) is consistent: all four badgeGetter keys (drafts, followRequests, unreadChats, unreadAnnouncements) resolve, and the unreadAnnouncementsCount rename matches the store everywhere.
  • updateNotificationSettings now sends block_from_strangers / hide_notification_contents as snake_cased query params (via paramsString) instead of a PUT payload, consistent with the settings-map keys.


Generated by opencode-fix-bot for /oc review on PR #3571 (base develop@d603aac31b787c250bc5359a08303fbd9fa4f7a8, head vuex-removal@2731ea81cbfd5f2c2872e7c3d32892089ac48cc0). Marker: opencode-agent:job=80:generation=1

opencode-agent:job=80:generation=1 **Automated review of `d603aac3` → `2731ea81`** (27 commits, 58 files, +890/−1183), done for `/oc review`. ## Verdict A thorough, near-complete vuex → pinia migration: no `vuex` / `$store` / `window.vuex` / vuex `mapGetters` / `commit` / `dispatch` references remain anywhere in `src/` or `test/`, the removed `modules/{api,drafts,index}.js` have no dangling importers, and the unit suite passes at the same level as `develop` (418 passed / 1 failed / 2 skipped — the one failure and the two MSW-dependent spec files fail identically at base; verified by running the suite at both commits). But there are a few small, real regressions I'd want fixed before merge. ## Should fix (likely regressions) 1. **`src/stores/users.js:709`** — typo `error.tatusCode` (was `error.statusCode`), so a 401 login failure reports the generic "An error occurred…" instead of "Wrong username or password". Not caught by tests: the bad-credentials spec uses 403. 2. **`src/components/emoji_input/suggestor.js:18`** — `const usersCurry = data.store && suggestUsers(data.store)` still gates on `data.store`, but this PR removed `store: this.$store` from both callers (`post_status_form.js` / `user_card.js` `emojiUserSuggestor`). Net effect: `@`-mention user suggestions are dead in the composer and user-card fields. `suggestUsers()` is arg-less and pinia-based, so the gate can simply be dropped. 3. **`src/components/side_drawer/side_drawer.js:113`** — `mapState(useDraftsStore, ['draftCount'])`, but the pinia getter is `draftsCount` (`src/stores/drafts.js:50`). The drafts badge in the side drawer is always `undefined`/hidden. Renamed correctly everywhere else — this one spot was missed. 4. **`src/stores/drafts.js:61` (`loadDrafts`)** — `new Map(Object.entries(currentData))` throws when the `pleroma-fe-drafts` key is absent (localforage resolves `null`; `Object.entries(null)` → TypeError). The old vuex module guarded with `|| {}`; the new `saveDraftToStorage`/`deleteDraftFromStorage` helpers kept `?? {}`, but `loadDrafts` didn't. `loginUser` calls it un-awaited, so most users get an unhandled rejection and no drafts on every login. 5. **Shout init race** — the `instance_capabilities.js` hook that called `initializeSocket` when `shoutAvailable` arrived from nodeinfo was removed; `loginUser` now checks `shoutAvailable` itself (`users.js:667`), but `checkOAuthToken` and `getNodeInfo` run concurrently in `after_store.js`'s `Promise.all`. If login resolves before nodeinfo, the shout socket is never initialized for the session. 6. **`src/stores/shout.js:13,17`** — `token` is declared in both `state` and `getters`; pinia warns *"A getter cannot have the same name as another state property"* and the getter shadows the always-dead `token: null` state (verified against pinia 3). Drop the state field. ## Notes / nits - **lodash-es**: the title says "replace lodash with lodash-es", but nothing imports `lodash-es` (0 occurrences in `src/` and `test/`); 66 app files still `import … from 'lodash'` (CJS), `lodash` was dropped from dependencies, and `lodash-es` sits unused in devDependencies. The build only keeps working because hoisted transitive `lodash@^4.17.21` remains in yarn.lock — an undeclared direct dependency. Removing `babel-plugin-lodash` also means full-CJS lodash gets bundled. Either migrate the imports to `lodash-es` or keep `lodash` as an explicit dependency. - `src/stores/drafts.js:70` — `abandonAllDrafts(store)` has a stray vuex-era `store` arg, and it double-deletes: each `abandonDraft` already removes the draft from storage, then the bulk `deleteDraftFromStorage(ids)` runs again. - `src/stores/follow_requests.js` — throws bare strings in `startFetching`/`stopFetching`; `stopFetching` uses a comma-operator one-liner; the store ↔ `stores/fetchers/follow_requests.js` import cycle only works because usage is deferred to call time. - `follow_request_card.js` `doDeny` now marks the notification seen, while `notification.js` `doDeny` still dismisses it — inconsistent UX for the same action. - The new stores (`drafts`, `followRequests`, `profileConfig`) and the new `loginUser`/`logout` branches (profileConfig `onLogin`/`onLogout`, shout gating, locked-user follow-request fetching) have no direct test coverage; the post_status_form draft specs themselves were ported faithfully. - Test-only: the "failed logout" spec doesn't stub `useFollowRequestsStore().startFetching()`, so a real fetcher starts a 10 s polling loop during tests (was a no-op fallback at base). ## What looks good - The vuex removal itself is complete and clean; `after_store.js` threading updated, `mock_store.js` removed with no leftover test scaffolding. - `piniaPersistPlugin` keeps the `vuex-lz` localStorage fallback so existing users' persisted state migrates per-store — nice touch. - Navigation badge refactor (`badges` maps) is consistent: all four `badgeGetter` keys (`drafts`, `followRequests`, `unreadChats`, `unreadAnnouncements`) resolve, and the `unreadAnnouncementsCount` rename matches the store everywhere. - `updateNotificationSettings` now sends `block_from_strangers` / `hide_notification_contents` as snake_cased query params (via `paramsString`) instead of a PUT payload, consistent with the settings-map keys. — Generated by `opencode-fix-bot` for `/oc review` on PR #3571 (base `develop`@`d603aac31b787c250bc5359a08303fbd9fa4f7a8`, head `vuex-removal`@`2731ea81cbfd5f2c2872e7c3d32892089ac48cc0`). Marker: `opencode-agent:job=80:generation=1`
hj added 2 commits 2026-09-03 10:42:30 +00:00
more lodash-es
Some checks failed
ci/woodpecker/pr/changelog Pipeline is pending
ci/woodpecker/pr/lint Pipeline is pending
ci/woodpecker/pr/test-e2e Pipeline is pending
ci/woodpecker/pr/test Pipeline is pending
ci/woodpecker/pr/build Pipeline was canceled
1f20bd2f60
drive-by
All checks were successful
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/changelog Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/test-e2e Pipeline was successful
47741a52e5
hj added 4 commits 2026-09-03 18:23:55 +00:00
drive-by: promiseInterval fetches on creation
Some checks failed
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/changelog Pipeline was successful
ci/woodpecker/pr/lint Pipeline failed
ci/woodpecker/pr/test Pipeline failed
ci/woodpecker/pr/test-e2e unknown status
e682a372d8
hj added 2 commits 2026-09-03 18:33:13 +00:00
fix test?
Some checks failed
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/changelog Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/test Pipeline failed
ci/woodpecker/pr/test-e2e unknown status
67bb642ffa
fix tests again
All checks were successful
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/changelog Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/test-e2e Pipeline was successful
6e04b28b71
Author
Member

/oc review

/oc review
opencode-fix-bot left a comment

opencode-agent:job=81:generation=1

Re-review of d603aac36e04b28b (37 commits, 127 files, +1929/−1633 vs develop; 10 new commits since the previous bot review of 2731ea81), done for /oc review.

Previously flagged issues — all resolved

  1. src/stores/users.js:709error.tatusCode typo fixed (now error.statusCode at :705/:709), so 401 logins again report "Wrong username or password".
  2. src/components/emoji_input/suggestor.js:18 — dead data.store && gate dropped; suggestUsers() is arg-less and pinia-based, so @-mention suggestions work again in the composer and user-card fields.
  3. src/components/side_drawer/side_drawer.js:113 — now maps draftsCount, matching the pinia getter; the drafts badge is no longer undefined.
  4. src/stores/drafts.jsloadDrafts (and both storage helpers) guard reads with ?? {} (:22, :28, :56), so no more Object.entries(null) TypeError on first login; abandonAllDrafts lost the stray vuex-era arg and the double-delete.
  5. Shout init race — closed: instanceCapabilities.set() now calls initializeSocket() when shoutAvailable arrives after login (src/stores/instance_capabilities.js:46-49), and initializeSocket no longer throws on double-init (src/stores/shout.js).
  6. src/stores/shout.js — the token state/getter collision is gone (getter only).
  7. lodash-es — the title's promise is now real: zero from 'lodash' imports remain in src//test/ (69 files import lodash-es), and lodash-es@4.17.21 moved from devDependencies into dependencies, so it's no longer an undeclared hoisted transitive.

Verification

  • Full unit suite run locally at 6e04b28b (headless chromium): 471 passed / 0 failed / 2 skipped across all 37 spec files — up from 418/1/2 at the previously reviewed head. The only failure at the old head is gone, and 53 new tests cover the drafts and follow-requests stores (drafts.spec.js, follow_requests.spec.js, extended users.spec.js with the follow-requests fetcher stubbed).
  • No vuex / $store / vuex mapGetters / commit / dispatch remnants in app code; the remaining vuex references are the intentional vuex-lz localStorage migration fallbacks.
  • The "promiseInterval fetches on creation" drive-by is correct: it removes the redundant explicit fetchAndUpdate() from the follow-requests/notifications fetchers, which previously double-fired on startup (explicit call + first loop iteration of promiseInterval).
  • Follow-request approve/deny consolidation into the store (follow_requests.js + new global follow_request_confirm mounted in App.vue) also fixes the old bare-string throws, the comma-operator stopFetching, and makes the API call awaited before the request entry is removed — nice cleanup of two near-duplicated component implementations.

Minor notes (non-blocking)

  1. Failed-logout restart asymmetrylogout() stops the follow-requests fetcher only if (this.currentUser.locked) (src/stores/users.js:730-731), but the failure path restarts it unconditionally (users.js:791). For a non-locked user whose logout fails, startFetching() throws Fetcher already exists! inside the catch handler → an unhandled rejection (the earlier fetcher restarts in that block still run, so state stays consistent, but it's noisy). Guarding the restart the same way the stop is guarded (capturing locked before teardown) would fix it.
  2. Confirm-dialog error UXdoApprove/doDeny hide the modal and clear tempId before awaiting the API call, and rejections aren't caught, so on API failure the dialog is already gone with no feedback. Old component code had the same flaw (no regression), but it's now trivially fixable in one place.
  3. Deny semantics change in notifications — denying from a notification used to dismiss the notification (dismissNotificationLocal); the unified store now always marks the follow-request notification seen instead. Consistency is welcome, but the notification now lingers (seen, not dismissed) — flagging in case that UX shift is unintentional.
  4. New store↔store import cycle follow_requests → notifications → users → follow_requests — works only because usage is deferred to call time (same pattern as elsewhere in this migration), worth keeping an eye on.

Verdict

All blocking regressions from the previous review are fixed and test coverage is meaningfully better. Remaining items are minor; nothing blocks merge from my side.


Generated by opencode-fix-bot for /oc review on PR #3571 (base develop@d603aac31b787c250bc5359a08303fbd9fa4f7a8, head vuex-removal@6e04b28b719f95b53b526f568d69335ee577627e). Marker: opencode-agent:job=81:generation=1

opencode-agent:job=81:generation=1 **Re-review of `d603aac3` → `6e04b28b`** (37 commits, 127 files, +1929/−1633 vs `develop`; 10 new commits since the previous bot review of `2731ea81`), done for `/oc review`. ## Previously flagged issues — all resolved 1. **`src/stores/users.js:709`** — `error.tatusCode` typo fixed (now `error.statusCode` at :705/:709), so 401 logins again report "Wrong username or password". 2. **`src/components/emoji_input/suggestor.js:18`** — dead `data.store &&` gate dropped; `suggestUsers()` is arg-less and pinia-based, so `@`-mention suggestions work again in the composer and user-card fields. 3. **`src/components/side_drawer/side_drawer.js:113`** — now maps `draftsCount`, matching the pinia getter; the drafts badge is no longer `undefined`. 4. **`src/stores/drafts.js`** — `loadDrafts` (and both storage helpers) guard reads with `?? {}` (:22, :28, :56), so no more `Object.entries(null)` TypeError on first login; `abandonAllDrafts` lost the stray vuex-era arg and the double-delete. 5. **Shout init race** — closed: `instanceCapabilities.set()` now calls `initializeSocket()` when `shoutAvailable` arrives after login (`src/stores/instance_capabilities.js:46-49`), and `initializeSocket` no longer throws on double-init (`src/stores/shout.js`). 6. **`src/stores/shout.js`** — the `token` state/getter collision is gone (getter only). 7. **lodash-es** — the title's promise is now real: zero `from 'lodash'` imports remain in `src/`/`test/` (69 files import `lodash-es`), and `lodash-es@4.17.21` moved from devDependencies into `dependencies`, so it's no longer an undeclared hoisted transitive. ## Verification - Full unit suite run locally at `6e04b28b` (headless chromium): **471 passed / 0 failed / 2 skipped across all 37 spec files** — up from 418/1/2 at the previously reviewed head. The only failure at the old head is gone, and 53 new tests cover the drafts and follow-requests stores (`drafts.spec.js`, `follow_requests.spec.js`, extended `users.spec.js` with the follow-requests fetcher stubbed). - No `vuex` / `$store` / vuex `mapGetters` / `commit` / `dispatch` remnants in app code; the remaining `vuex` references are the intentional `vuex-lz` localStorage migration fallbacks. - The "promiseInterval fetches on creation" drive-by is correct: it removes the redundant explicit `fetchAndUpdate()` from the follow-requests/notifications fetchers, which previously double-fired on startup (explicit call + first loop iteration of `promiseInterval`). - Follow-request approve/deny consolidation into the store (`follow_requests.js` + new global `follow_request_confirm` mounted in `App.vue`) also fixes the old bare-string throws, the comma-operator `stopFetching`, and makes the API call awaited before the request entry is removed — nice cleanup of two near-duplicated component implementations. ## Minor notes (non-blocking) 1. **Failed-logout restart asymmetry** — `logout()` stops the follow-requests fetcher only `if (this.currentUser.locked)` (`src/stores/users.js:730-731`), but the failure path restarts it unconditionally (`users.js:791`). For a non-locked user whose logout fails, `startFetching()` throws `Fetcher already exists!` inside the catch handler → an unhandled rejection (the earlier fetcher restarts in that block still run, so state stays consistent, but it's noisy). Guarding the restart the same way the stop is guarded (capturing `locked` before teardown) would fix it. 2. **Confirm-dialog error UX** — `doApprove`/`doDeny` hide the modal and clear `tempId` before awaiting the API call, and rejections aren't caught, so on API failure the dialog is already gone with no feedback. Old component code had the same flaw (no regression), but it's now trivially fixable in one place. 3. **Deny semantics change in notifications** — denying from a *notification* used to dismiss the notification (`dismissNotificationLocal`); the unified store now always marks the follow-request notification seen instead. Consistency is welcome, but the notification now lingers (seen, not dismissed) — flagging in case that UX shift is unintentional. 4. New store↔store import cycle `follow_requests → notifications → users → follow_requests` — works only because usage is deferred to call time (same pattern as elsewhere in this migration), worth keeping an eye on. ## Verdict All blocking regressions from the previous review are fixed and test coverage is meaningfully better. Remaining items are minor; nothing blocks merge from my side. — Generated by `opencode-fix-bot` for `/oc review` on PR #3571 (base `develop`@`d603aac31b787c250bc5359a08303fbd9fa4f7a8`, head `vuex-removal`@`6e04b28b719f95b53b526f568d69335ee577627e`). Marker: `opencode-agent:job=81:generation=1`
add check
Some checks failed
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/changelog Pipeline was successful
ci/woodpecker/pr/lint Pipeline failed
ci/woodpecker/pr/test Pipeline failed
ci/woodpecker/pr/test-e2e unknown status
da53e35817
handle errors
Some checks failed
ci/woodpecker/pr/test-e2e Pipeline is pending
ci/woodpecker/pr/test Pipeline is pending
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/changelog Pipeline was successful
ci/woodpecker/pr/lint Pipeline was canceled
4b04488ce0
lint+fix
Some checks failed
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/changelog Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/test-e2e Pipeline failed
ded8ae863d
oops
All checks were successful
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/changelog Pipeline was successful
ci/woodpecker/pr/lint Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful
ci/woodpecker/pr/test-e2e Pipeline was successful
eaa75f55e6
hj merged commit 7bc4fd7be7 into develop 2026-09-03 22:00:40 +00:00
hj deleted branch vuex-removal 2026-09-03 22:00:40 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
pleroma/pleroma-fe!3571
No description provided.