Compare commits

...

236 commits

Author SHA1 Message Date
Henry Jameson
7ac4729dec lint 2026-02-13 09:13:38 +02:00
Henry Jameson
0a7a2f0da4 Merge branch 'setttingssync' into shigusegubu-themes3 2026-02-13 09:09:02 +02:00
Henry Jameson
e9993e8d5a config.mergedConfig -> syncConfig.mergedConfig 2026-02-13 09:07:03 +02:00
Henry Jameson
0a00ce025a lint 2026-02-13 08:37:07 +02:00
Henry Jameson
5aec0faa2c modify logic behind push notification subscriptions 2026-02-12 22:24:33 +02:00
Henry Jameson
a91821933f rewrote push notifications plugin 2026-02-12 22:14:52 +02:00
Henry Jameson
90ac30249b post-merge headache 2026-02-12 22:14:44 +02:00
Henry Jameson
3530830b07 Merge branch 'develop' into setttingssync 2026-02-12 17:16:18 +02:00
Henry Jameson
b0dc2dd74a test 2026-02-11 21:26:39 +02:00
Henry Jameson
cafe49de11 Merge branch 'instance-migration' into shigusegubu-themes3 2026-02-11 00:39:50 +02:00
Henry Jameson
d0202e9ca9 Merge branch 'instance-migration' into shigusegubu-themes3 2026-02-05 01:40:10 +02:00
Henry Jameson
7c6ce89b6e Merge branch 'instance-migration' into shigusegubu-themes3 2026-02-05 01:21:06 +02:00
Henry Jameson
b419408643 Merge branch 'instance-migration' into shigusegubu-themes3 2026-01-29 21:42:10 +02:00
Henry Jameson
04f9547c13 fix bookmarks 2026-01-29 21:41:34 +02:00
Henry Jameson
0fec78ec81 Merge branch 'instance-migration' into shigusegubu-themes3 2026-01-29 21:33:04 +02:00
Henry Jameson
6eb94da3e8 make sw shut up 2026-01-29 21:24:21 +02:00
Henry Jameson
775a469507 fix background 2026-01-29 21:24:18 +02:00
Henry Jameson
4ea48dafb9 Merge branch 'instance-migration' into shigusegubu-themes3 2026-01-29 21:15:30 +02:00
Henry Jameson
7d5c2e32cc Merge branch 'instance-migration' into shigusegubu-themes3 2026-01-29 20:50:13 +02:00
Henry Jameson
a96e3b4b5d Merge branch 'instance-migration' into shigusegubu-themes3 2026-01-29 20:47:31 +02:00
Henry Jameson
f1a96ec639 undo sw changes 2026-01-28 23:22:12 +02:00
Henry Jameson
384531c108 lint 2026-01-28 21:32:14 +02:00
Henry Jameson
6877008017 fixed objectCollection not leaving a journal entry on removal 2026-01-28 21:31:41 +02:00
Henry Jameson
e0d9a71322 cleanup & debug 2026-01-27 23:13:23 +02:00
Henry Jameson
ed9e9a3877 minor fixes & refactoring 2026-01-27 22:58:20 +02:00
Henry Jameson
83a419caf7 login works again 2026-01-27 21:55:36 +02:00
Henry Jameson
ebe487c5d8 it boots again 2026-01-26 23:24:48 +02:00
Henry Jameson
3cdcb87831 fix tests 2026-01-23 17:24:02 +02:00
Henry Jameson
6aadf5f1c6 cleaned and fixed errors detected by biome 2026-01-23 15:07:31 +02:00
Henry Jameson
ae17911560 proper temporary setting + fix appearance stuff using stale data 2026-01-23 14:53:22 +02:00
Henry Jameson
1f57fab6ae theme/style/palette seem to be working 2026-01-23 14:11:48 +02:00
Henry Jameson
a5b3840d06 fixed up language 2026-01-23 13:15:34 +02:00
Henry Jameson
9822ebc3bf language + biome 2026-01-23 12:40:45 +02:00
Henry Jameson
1b310d7174 fixed up temporary changes 2026-01-23 00:46:44 +02:00
Henry Jameson
80e09efd71 most stuff seem to work without errors 2026-01-23 00:17:27 +02:00
Henry Jameson
35a3d59235 WIP 2026-01-22 20:52:47 +02:00
Henry Jameson
5bdf341560 MASSIVE refactor, replacing instance module with store, separating emoji stuff into its own store, making sure everything refers to new stores (WIP) 2026-01-22 17:16:51 +02:00
Henry Jameson
dc7308766c fix some navigation issues 2026-01-22 00:55:55 +02:00
Henry Jameson
9452b3084a some initial work on moving instance settings to pinia 2026-01-22 00:22:18 +02:00
Henry Jameson
20071d5a11 clutter page unsync -> sync 2026-01-21 16:51:08 +02:00
Henry Jameson
1942d43eb3 fix the lint-fix command for eslint 2026-01-21 16:03:33 +02:00
Henry Jameson
8bbc17f982 fix sss not saving cache locally 2026-01-21 15:59:13 +02:00
Henry Jameson
db73f1a3dc Merge branch '2-10-1-fixes' into shigusegubu-themes3 2026-01-08 22:10:42 +02:00
Henry Jameson
c32dda4849 Merge branch 'biome' into shigusegubu-themes3 2026-01-06 18:27:01 +02:00
Henry Jameson
4502a6cc25 Merge branch 'admin-tabs-2' into shigusegubu-themes3 2025-12-15 22:56:19 +02:00
Henry Jameson
37b9dc77f3 Merge branch 'admin-tabs-2' into shigusegubu-themes3 2025-12-11 21:58:41 +02:00
Henry Jameson
30966210f4 Merge branch 'admin-tabs-2' into shigusegubu-themes3 2025-12-11 18:31:26 +02:00
Henry Jameson
39856570a8 Merge branch 'admin-tabs-2' into shigusegubu-themes3 2025-12-11 15:45:37 +02:00
Henry Jameson
c12a7fcf7b Merge branch 'admin-tabs-2' into shigusegubu-themes3 2025-12-10 20:37:38 +02:00
Henry Jameson
03e9e5082f Merge branch 'admin-tabs-2' into shigusegubu-themes3 2025-12-09 13:24:57 +02:00
Henry Jameson
b07560ca6b Merge branch 'admin-tabs-2' into shigusegubu-themes3 2025-12-08 22:44:37 +02:00
Henry Jameson
12b98a48b2 Merge branch 'admin-tabs-2' into shigusegubu-themes3 2025-12-08 22:31:37 +02:00
Henry Jameson
4704f57cbf Merge branch 'settings-shuffle' into shigusegubu-themes3 2025-11-27 19:34:23 +02:00
Henry Jameson
ea8218d855 i18n 2025-11-27 12:26:44 +02:00
Henry Jameson
ba8be56bc4 fix fun content not hiding properly 2025-11-27 12:03:15 +02:00
Henry Jameson
b1c338a976 fix tab cutoff 2025-11-27 12:03:07 +02:00
Henry Jameson
7aeeb25f00 Merge branch 'settings-shuffle' into shigusegubu-themes3 2025-11-26 18:44:09 +02:00
Henry Jameson
f77c2bef5f Merge branch 'settings-shuffle' into shigusegubu-themes3 2025-11-26 00:25:41 +02:00
Henry Jameson
f2db381817 Merge branch 'settings-shuffle' into shigusegubu-themes3 2025-11-25 20:30:02 +02:00
Henry Jameson
1abbba698d Merge branch 'settings-shuffle' into shigusegubu-themes3 2025-11-24 20:54:21 +02:00
Henry Jameson
15d0aa466b Merge remote-tracking branch 'origin/develop' into shigusegubu-themes3 2025-10-02 11:39:29 +03:00
Henry Jameson
a0a27410ea debug2 2025-09-18 18:19:50 +03:00
Henry Jameson
454a225a75 debug 2025-09-18 18:16:50 +03:00
Henry Jameson
d242f45ffb Merge remote-tracking branch 'origin/develop' into shigusegubu-themes3 2025-09-15 19:38:25 +03:00
Henry Jameson
19e6390ccb Merge branch 'final-fixes' into shigusegubu-themes3 2025-08-28 00:06:54 +03:00
Henry Jameson
8c7da4c621 Merge remote-tracking branch 'origin/develop' into shigusegubu-themes3 2025-08-26 21:24:21 +03:00
Henry Jameson
d7ab91e167 Merge branch 'copy-emoji-one' into shigusegubu-themes3 2025-08-20 07:14:19 +03:00
Henry Jameson
09ca89871a Merge branch 'misc-style-fixes-or-changes' into shigusegubu-themes3 2025-08-19 17:30:25 +03:00
Henry Jameson
6ff87af516 Merge branch 'misc-style-fixes-or-changes' into shigusegubu-themes3 2025-08-15 10:06:31 +03:00
Henry Jameson
30a668de7a Merge branch 'misc-style-fixes-or-changes' into shigusegubu-themes3 2025-08-15 09:34:09 +03:00
Henry Jameson
31efcccbf6 Merge branch 'copy-emoji-one' into shigusegubu-themes3 2025-08-15 00:02:34 +03:00
Henry Jameson
6b71793b3b Merge branch 'misc-style-fixes-or-changes' into shigusegubu-themes3 2025-08-14 23:16:01 +03:00
Henry Jameson
4da91e0076 Merge branch 'misc-style-fixes-or-changes' into shigusegubu-themes3 2025-08-14 18:15:16 +03:00
Henry Jameson
52e4cfc573 Merge branch 'misc-style-fixes-or-changes' into shigusegubu-themes3 2025-08-14 18:06:29 +03:00
Henry Jameson
242de86c35 Merge branch 'misc-style-fixes-or-changes' into shigusegubu-themes3 2025-08-14 17:58:17 +03:00
Henry Jameson
7ee584c65d Merge branch 'misc-style-fixes-or-changes' into shigusegubu-themes3 2025-08-14 17:50:15 +03:00
Henry Jameson
d34e57bc0b Merge branch 'misc-style-fixes-or-changes' into shigusegubu-themes3 2025-08-14 17:27:41 +03:00
Henry Jameson
41add4fc6a Merge branch 'themes-3-1' into shigusegubu-themes3 2025-08-10 23:39:49 +03:00
Henry Jameson
eef6f6d0e2 Merge remote-tracking branch 'origin/develop' into shigusegubu-themes3 2025-08-10 23:39:43 +03:00
Henry Jameson
651ce2080e Merge branch 'profile-edit' into shigusegubu-themes3 2025-08-08 10:18:02 +03:00
Henry Jameson
aa8d09d5a4 Merge branch 'profile-edit' into shigusegubu-themes3 2025-08-05 18:46:00 +03:00
Henry Jameson
2029852784 Merge branch 'profile-edit' into shigusegubu-themes3 2025-08-05 18:38:13 +03:00
Henry Jameson
3efe6d1243 Merge branch 'profile-edit' into shigusegubu-themes3 2025-08-05 15:24:48 +03:00
Henry Jameson
23d53e9fd0 Merge branch 'profile-edit' into shigusegubu-themes3 2025-08-05 00:27:58 +03:00
Henry Jameson
5c86951798 Merge branch 'profile-overhaul' into shigusegubu-themes3 2025-08-01 02:20:01 +03:00
Henry Jameson
5b030bc863 Merge branch 'profile-overhaul' into shigusegubu-themes3 2025-08-01 02:13:56 +03:00
Henry Jameson
a06d8a3186 Merge branch 'profile-overhaul' into shigusegubu-themes3 2025-08-01 00:59:11 +03:00
Henry Jameson
0eac23daba Merge branch 'profile-overhaul' into shigusegubu-themes3 2025-07-31 22:46:44 +03:00
Henry Jameson
63e6527d2d Merge branch 'profile-overhaul' into shigusegubu-themes3 2025-07-31 22:35:16 +03:00
Henry Jameson
741523e51a Merge branch 'profile-overhaul' into shigusegubu-themes3 2025-07-31 22:02:10 +03:00
Henry Jameson
22dc4ff983 Merge branch 'profile-overhaul' into shigusegubu-themes3 2025-07-31 21:44:22 +03:00
Henry Jameson
59266b30ed Merge branch 'profile-overhaul' into shigusegubu-themes3 2025-07-31 21:36:08 +03:00
Henry Jameson
a616b20c7c Merge branch 'profile-overhaul' into shigusegubu-themes3 2025-07-30 23:20:45 +03:00
Henry Jameson
57059b3297 Merge branch 'profile-overhaul' into shigusegubu-themes3 2025-07-30 10:29:39 +03:00
Henry Jameson
8a1dbcdcff Merge branch 'profile-overhaul' into shigusegubu-themes3 2025-07-30 10:22:50 +03:00
Henry Jameson
e3e0d1f3f4 Merge branch 'profile-overhaul' into shigusegubu-themes3 2025-07-30 10:05:03 +03:00
Henry Jameson
2c68d1512d Merge branch 'profile-overhaul' into shigusegubu-themes3 2025-07-30 01:20:40 +03:00
Henry Jameson
be56291869 Merge branch 'profile-overhaul' into shigusegubu-themes3 2025-07-30 01:13:34 +03:00
Henry Jameson
82db998c19 Merge branch 'profile-overhaul' into shigusegubu-themes3 2025-07-30 00:40:39 +03:00
Henry Jameson
a1d3d04087 Merge branch 'profile-overhaul' into shigusegubu-themes3 2025-07-29 19:03:39 +03:00
Henry Jameson
33a0e4b2b9 Merge branch 'firefix' into shigusegubu-themes3 2025-07-17 17:57:38 +03:00
Henry Jameson
081a77ee0c Merge branch 'timed-user-mutes' into shigusegubu-themes3 2025-07-09 19:05:47 +03:00
Henry Jameson
637bbf5803 Merge branch 'fix-style-editors' into shigusegubu-themes3 2025-07-03 11:21:04 +03:00
Henry Jameson
b6ed146b5a Merge branch 'fix-style-editors' into shigusegubu-themes3 2025-07-03 10:43:21 +03:00
Henry Jameson
17348b9823 Merge branch 'fix-style-editors' into shigusegubu-themes3 2025-07-02 23:26:59 +03:00
Henry Jameson
a55d571a44 Merge branch 'fix-style-editors' into shigusegubu-themes3 2025-07-02 22:55:29 +03:00
Henry Jameson
8cfae10f37 update component preview on render 2025-07-02 18:15:12 +03:00
Henry Jameson
5a65e1d895 small fix 2025-07-02 18:14:56 +03:00
Henry Jameson
1e26b9188c undo link->style 2025-07-02 10:42:44 +03:00
Henry Jameson
567bccb9fa i spent too much time on this 2025-07-02 02:26:17 +03:00
Henry Jameson
1cb4740fc9 fix component preview styles 2025-07-02 00:36:37 +03:00
Henry Jameson
980917a16f Merge remote-tracking branch 'origin/develop' into shigusegubu-themes3 2025-06-29 16:40:54 +03:00
Henry Jameson
9cac70d8e6 Merge branch 'akkoma-support-part-2' into shigusegubu-themes3 2025-06-28 22:48:12 +03:00
Henry Jameson
2f70309970 Merge branch 'akkoma-support-part-2' into shigusegubu-themes3 2025-06-28 22:31:30 +03:00
Henry Jameson
a72dc45f46 Merge branch 'csp-akkoma' into shigusegubu-themes3 2025-06-28 16:05:44 +03:00
Henry Jameson
dcdb5a8ab5 Merge branch 'csp-akkoma' into shigusegubu-themes3 2025-06-28 15:57:47 +03:00
Henry Jameson
a3d857f0f9 Merge remote-tracking branch 'origin/develop' into shigusegubu-themes3 2025-06-26 00:09:42 +03:00
Henry Jameson
3a59fddb4a Merge branch 'smallfixes' into shigusegubu-themes3 2025-06-26 00:09:29 +03:00
Henry Jameson
182c707436 Merge branch 'from/develop/tusooa/sw-cache-assets' into shigusegubu-themes3 2025-06-25 15:54:40 +03:00
Henry Jameson
109882a68e Merge branch 'akkoma' into shigusegubu-themes3 2025-06-24 17:05:57 +03:00
Henry Jameson
a2391a11cf Merge branch 'akkoma' into shigusegubu-themes3 2025-06-18 19:58:45 +03:00
Henry Jameson
9b555a790d Merge branch 'akkoma' into shigusegubu-themes3 2025-06-18 19:55:51 +03:00
Henry Jameson
3695774f8e clarity 2025-06-18 19:55:43 +03:00
Henry Jameson
25620f1cea Merge branch 'akkoma' into shigusegubu-themes3 2025-06-18 19:54:14 +03:00
Henry Jameson
53213e40de Merge branch 'akkoma' into shigusegubu-themes3 2025-06-18 19:48:07 +03:00
Henry Jameson
4a1914d71c Merge remote-tracking branch 'origin/develop' into shigusegubu-themes3 2025-05-21 20:47:48 +03:00
Henry Jameson
afbf63412d Merge branch 'sss-objects' into shigusegubu-themes3 2025-04-11 11:52:01 +03:00
Henry Jameson
aff02e393d Merge branch 'sss-objects' into shigusegubu-themes3 2025-04-09 00:36:18 +03:00
Henry Jameson
e6fc460b02 Merge remote-tracking branch 'origin/develop' into shigusegubu-themes3 2025-04-08 15:07:19 +03:00
Henry Jameson
89d45a86e5 Merge branch 'fix-word-break' into shigusegubu-themes3 2025-04-03 19:04:56 +03:00
Henry Jameson
2fcbebc995 Merge branch 'fix-word-break' into shigusegubu-themes3 2025-04-03 12:45:33 +03:00
Henry Jameson
f068549adb Merge branch 'fix-word-break' into shigusegubu-themes3 2025-04-03 11:30:56 +03:00
Henry Jameson
b43c556a84 Merge branch 'fix-word-break' into shigusegubu-themes3 2025-04-03 10:56:32 +03:00
Henry Jameson
aeef5c77de Merge branch 'sss-objects' into shigusegubu-themes3 2025-04-03 01:44:12 +03:00
Henry Jameson
efe8dbf921 Merge branch 'fix-bookrmarkdropdown' into shigusegubu-themes3 2025-03-27 16:21:45 +02:00
Henry Jameson
10329e9f45 Merge branch 'fix-breezy' into shigusegubu-themes3 2025-03-26 22:17:23 +02:00
Henry Jameson
c968347c0a undo config.json change because there's no proper way to set those in either UI 2025-03-26 16:08:47 +02:00
Henry Jameson
425d0662a1 remove sgsgb-related stuff 2025-03-26 16:01:58 +02:00
Henry Jameson
55d29065f0 Merge branch 'sss-objects' into shigusegubu-themes3 2025-03-26 15:58:15 +02:00
Henry Jameson
515d5451fa make a separate file to store all information about fields and their migrations 2025-03-26 15:57:48 +02:00
Henry Jameson
47a6777284 Merge branch 'sss-objects' into shigusegubu-themes3 2025-03-25 21:26:30 +02:00
Henry Jameson
42f51ff315 Merge branch 'develop' into shigusegubu-themes3 2025-03-25 20:09:01 +02:00
Henry Jameson
add0e5f934 Merge branch 'sss-objects' into shigusegubu-themes3 2025-03-25 19:58:31 +02:00
Henry Jameson
350dd2fcf8 Merge branch 'fixes-roundup5' into shigusegubu-themes3 2025-03-13 15:24:57 +02:00
Henry Jameson
155d9b0999 Merge remote-tracking branch 'origin/develop' into shigusegubu-themes3 2025-03-13 13:00:21 +02:00
Henry Jameson
f051de13e7 Merge branch 'fixes-roundup5' into shigusegubu-themes3 2025-03-13 13:00:12 +02:00
Henry Jameson
b058bab73a Merge remote-tracking branch 'origin/develop' into shigusegubu-themes3 2025-03-13 02:14:34 +02:00
Henry Jameson
06e42053b2 Merge branch 'fixes-roundup5' into shigusegubu-themes3 2025-03-13 02:14:12 +02:00
Henry Jameson
8ad1c4a3ff Merge branch 'fixes-roundup5' into shigusegubu-themes3 2025-03-05 02:51:15 +02:00
Henry Jameson
af432072ca Merge branch 'tusooa/vite' into shigusegubu-themes3 2025-03-04 19:04:15 +02:00
Henry Jameson
52b1c3d21a Merge remote-tracking branch 'origin/develop' into shigusegubu-themes3 2025-02-20 15:15:59 +02:00
Henry Jameson
d95eb5be85 Merge branch 'fixes-roundup4' into shigusegubu-themes3 2025-02-20 15:15:47 +02:00
Henry Jameson
9d92fb45a2 Merge branch 'fixes-roundup4' into shigusegubu-themes3 2025-02-19 16:22:46 +02:00
Henry Jameson
83e3a6c628 Merge branch 'fixes-roundup4' into shigusegubu-themes3 2025-02-18 22:40:41 +02:00
Henry Jameson
4dbb275c48 Merge branch 'fixes-roundup4' into shigusegubu-themes3 2025-02-12 22:06:31 +02:00
Henry Jameson
01bf0e8261 Merge branch 'fixes-roundup4' into shigusegubu-themes3 2025-02-12 15:54:59 +02:00
Henry Jameson
fe5edb7db9 Merge branch 'fixes-roundup4' into shigusegubu-themes3 2025-02-12 15:46:16 +02:00
Henry Jameson
33a239b89b Merge remote-tracking branch 'origin/develop' into shigusegubu-themes3 2025-02-10 23:22:19 +02:00
Henry Jameson
5a918d94df Merge branch 'fixes-roundup4' into shigusegubu-themes3 2025-02-10 23:21:25 +02:00
Henry Jameson
fb609674ad huh? 2025-02-05 08:47:10 +02:00
Henry Jameson
0ed64938b3 Merge branch 'fixes-roundup4' into shigusegubu-themes3 2025-02-05 08:43:38 +02:00
Henry Jameson
c11ebb1e7f Merge remote-tracking branch 'origin/develop' into shigusegubu-themes3 2025-02-03 21:45:58 +02:00
Henry Jameson
2d26737bab Merge branch 'migrate/vuex-to-pinia' into shigusegubu-themes3 2025-02-03 00:15:01 +02:00
Henry Jameson
f4934ec723 Merge remote-tracking branch 'origin/develop' into shigusegubu-themes3 2025-01-28 17:30:36 +02:00
Henry Jameson
c1ac4674af Merge branch 'fixes-roundup3' into shigusegubu-themes3 2025-01-27 17:56:23 +02:00
Henry Jameson
3711dfa913 Merge branch 'fixes-roundup3' into shigusegubu-themes3 2025-01-27 13:30:35 +02:00
Henry Jameson
26abe6b403 Merge branch 'fixes-roundup3' into shigusegubu-themes3 2025-01-26 22:51:49 +02:00
Henry Jameson
90bc03d394 Merge branch 'customizable-post-actions' into shigusegubu-themes3 2025-01-21 10:53:19 +02:00
Henry Jameson
6baf0ec339 Merge branch 'customizable-post-actions' into shigusegubu-themes3 2025-01-20 01:58:29 +02:00
Henry Jameson
f246611aa2 Merge remote-tracking branch 'origin/develop' into shigusegubu-themes3 2025-01-19 18:27:09 +02:00
Henry Jameson
19277f6cd5 Merge remote-tracking branch 'origin/develop' into shigusegubu-themes3 2025-01-19 18:26:50 +02:00
Henry Jameson
2b4052a2c8 Merge branch 'customizable-post-actions' into shigusegubu-themes3 2025-01-19 18:26:46 +02:00
Henry Jameson
04c5699c5a Merge branch 'customizable-post-actions' into shigusegubu-themes3 2025-01-19 17:23:55 +02:00
Henry Jameson
e92ecc612f Merge branch 'customizable-post-actions' into shigusegubu-themes3 2025-01-18 21:45:25 +02:00
Henry Jameson
478779121d Merge branch 'customizable-post-actions' into shigusegubu-themes3 2025-01-16 20:14:51 +02:00
Henry Jameson
f6841decce Merge branch 'fixes-batch2' into shigusegubu-themes3 2025-01-08 22:09:31 +02:00
Henry Jameson
1f37c53ab3 Merge branch 'consistent-mutes' into shigusegubu-themes3 2025-01-04 02:04:30 +02:00
Henry Jameson
3ffe042b25 Merge branch 'consistent-mutes' into shigusegubu-themes3 2025-01-02 23:03:37 +02:00
Henry Jameson
e498c51006 Merge remote-tracking branch 'origin/develop' into shigusegubu-themes3 2024-12-31 13:26:31 +02:00
Henry Jameson
72c980dbc3 Merge branch 'drafts-improvements' into shigusegubu-themes3 2024-12-31 12:12:17 +02:00
Henry Jameson
a59c9557a8 Merge branch 'drafts-improvements' into shigusegubu-themes3 2024-12-31 01:07:54 +02:00
Henry Jameson
9c952173f4 Merge branch 'themes-updates' into shigusegubu-themes3 2024-12-30 21:03:55 +02:00
Henry Jameson
cd9ed41d2d Merge branch 'themes-updates' into shigusegubu-themes3 2024-12-30 16:40:42 +02:00
Henry Jameson
b7c3cc30de Merge branch 'themes-updates' into shigusegubu-themes3 2024-12-30 16:32:56 +02:00
Henry Jameson
d679642a19 Merge branch 'drafts-improvements' into shigusegubu-themes3 2024-12-30 03:10:42 +02:00
Henry Jameson
1348bbb4d2 Merge branch 'mobile-modals' into shigusegubu-themes3 2024-12-29 22:30:04 +02:00
Henry Jameson
e8338a2f65 Merge branch 'mobile-modals' into shigusegubu-themes3 2024-12-29 18:56:14 +02:00
Henry Jameson
5e65c2efb7 Merge branch 'themes-updates' into shigusegubu-themes3 2024-12-29 18:16:54 +02:00
Henry Jameson
d1db92c896 Merge branch 'drafts-improvements' into shigusegubu-themes3 2024-12-27 17:10:34 +02:00
Henry Jameson
727253aba3 Merge remote-tracking branch 'origin/develop' into shigusegubu-themes3 2024-12-27 02:11:21 +02:00
Henry Jameson
38ea52d38b Merge remote-tracking branch 'origin/develop' into shigusegubu-themes3 2024-12-27 02:11:03 +02:00
Henry Jameson
8809424d75 Merge branch 'emoji-fixes' into shigusegubu-themes3 2024-12-27 00:29:29 +02:00
Henry Jameson
4b89c96799 Merge branch 'themes-updates' into shigusegubu-themes3 2024-12-27 00:29:21 +02:00
Henry Jameson
1a306c2723 Merge branch 'themes-updates' into shigusegubu-themes3 2024-12-24 16:24:51 +02:00
Henry Jameson
2d459df039 Merge branch 'emoji-fixes' into shigusegubu-themes3 2024-12-24 11:57:01 +02:00
Henry Jameson
c2e750daf7 Merge branch 'emoji-fixes' into shigusegubu-themes3 2024-12-24 11:12:00 +02:00
Henry Jameson
5dac99d828 Merge branch 'emoji-fixes' into shigusegubu-themes3 2024-12-23 23:16:05 +02:00
Henry Jameson
49dba9cfab Merge branch 'fixes-batch' into shigusegubu-themes3 2024-12-23 14:16:02 +02:00
Henry Jameson
48ffb39bf8 Merge branch 'fixes-batch' into shigusegubu-themes3 2024-12-23 04:45:48 +02:00
Henry Jameson
53ed51f9e5 Merge branch 'fixes-batch' into shigusegubu-themes3 2024-12-23 04:42:32 +02:00
Henry Jameson
3cb0dec5e1 Merge branch 'fixes-batch' into shigusegubu-themes3 2024-12-19 15:33:22 +02:00
Henry Jameson
5f3fcad181 Merge branch 'fixes-batch' into shigusegubu-themes3 2024-12-19 14:56:00 +02:00
Henry Jameson
66febc0756 Merge branch 'loader-fixes' into shigusegubu-themes3 2024-12-12 19:03:24 +02:00
Henry Jameson
108b8fe3f8 Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-12-10 15:56:05 +02:00
Henry Jameson
11072e5fc8 Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-12-04 15:55:09 +02:00
Henry Jameson
4503bd77d7 Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-12-04 14:04:04 +02:00
Henry Jameson
3af29e78b9 when switching to new style, use "native" palette, also show it in appearance tab 2024-12-04 14:03:27 +02:00
Henry Jameson
a0e12cabc6 Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-12-01 22:26:52 +02:00
Henry Jameson
749d08054c use breezy theme by default 2024-11-28 18:17:33 +02:00
Henry Jameson
2f10b94af8 Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-11-28 18:10:16 +02:00
Henry Jameson
eb5f47ebf9 Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-11-26 02:02:02 +02:00
Henry Jameson
31527054c2 Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-11-19 03:20:04 +02:00
Henry Jameson
42087a564f bundling theme now works and so are bundled style's palettes 2024-11-19 03:18:52 +02:00
Henry Jameson
89b0ed83f2 Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-11-15 00:40:24 +02:00
Henry Jameson
ca84e08247 Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-11-12 23:24:54 +02:00
Henry Jameson
1b644370b1 Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-10-30 22:52:14 +02:00
Henry Jameson
ba0855ad64 Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-10-29 23:55:57 +02:00
Henry Jameson
ca57af0a43 Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-10-29 21:17:48 +02:00
Henry Jameson
a023c44bee Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-10-28 21:23:14 +02:00
Henry Jameson
0562fe1c44 Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-10-25 16:58:48 +03:00
Henry Jameson
461eb8752d Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-10-22 10:08:40 +03:00
Henry Jameson
f03df3c993 Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-10-13 17:13:26 +03:00
Henry Jameson
eac63e0c57 Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-10-13 17:09:57 +03:00
Henry Jameson
0da9ba1b7a Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-10-07 12:30:07 +03:00
Henry Jameson
f8b39faae7 Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-10-07 12:25:29 +03:00
Henry Jameson
104bc8c86e oops 2024-10-06 01:57:39 +03:00
Henry Jameson
d647cd82d1 Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-10-06 01:49:46 +03:00
Henry Jameson
e2705f57b1 Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-10-05 23:15:15 +03:00
Henry Jameson
761cc52be7 palette and style for v3 2024-10-05 19:31:57 +03:00
Henry Jameson
f161cc4113 restore sgsgb palettes 2024-10-05 19:31:04 +03:00
Henry Jameson
6946626217 fix? 2024-10-05 19:24:32 +03:00
Henry Jameson
b0b6380ea4 Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-10-05 19:07:09 +03:00
Henry Jameson
d818b47938 Merge branch 'themes3-grand-finale-maybe' into shigusegubu-themes3 2024-10-05 18:54:18 +03:00
Henry Jameson
16610c8a12 Merge remote-tracking branch 'origin/develop' into shigusegubu-themes3 2024-10-05 18:53:54 +03:00
Henry Jameson
8163366402 Merge remote-tracking branch 'origin/develop' into shigusegubu-clean 2024-10-03 02:19:07 +03:00
Henry Jameson
2884d6e9ba Merge branch 'admin-dashboard-fixes' into shigusegubu-clean 2023-11-22 21:58:32 +02:00
76 changed files with 910 additions and 473 deletions

View file

@ -17,7 +17,7 @@
"ci-eslint": "yarn exec eslint",
"ci-stylelint": "yarn exec stylelint '**/*.scss' '**/*.vue'",
"lint": "yarn ci-biome; yarn ci-eslint; yarn ci-stylelint",
"lint-fix": "yarn exec eslint --fix; yarn exec stylelint '**/*.scss' '**/*.vue' --fix; biome check --write"
"lint-fix": "yarn exec eslint -- --fix; yarn exec stylelint '**/*.scss' '**/*.vue' --fix; biome check --write"
},
"dependencies": {
"@babel/runtime": "7.28.4",

View file

@ -25,7 +25,7 @@
"sidebarRight": false,
"subjectLineBehavior": "email",
"theme": null,
"style": null,
"palette": null,
"style": "BreezyDX",
"palette": "sigsegv2",
"webPushNotifications": false
}

View file

@ -26,6 +26,7 @@ import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useShoutStore } from 'src/stores/shout.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
export default {
name: 'app',
@ -72,7 +73,7 @@ export default {
},
created() {
// Load the locale from the storage
const val = this.$store.getters.mergedConfig.interfaceLanguage
const val = useSyncConfigStore().mergedConfig.interfaceLanguage
this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val })
document.getElementById('modal').classList = ['-' + this.layoutType]
@ -122,7 +123,7 @@ export default {
]
},
navClasses() {
const { navbarColumnStretch } = this.$store.getters.mergedConfig
const { navbarColumnStretch } = useSyncConfigStore().mergedConfig
return [
'-' + this.layoutType,
...(navbarColumnStretch ? ['-column-stretch'] : []),
@ -134,11 +135,13 @@ export default {
userBackground() {
return this.currentUser.background_image
},
instanceBackground() {
return this.mergedConfig.hideInstanceWallpaper ? null : this.background
},
background() {
return this.userBackground || this.instanceBackground
return (
this.userBackground ||
(this.mergedConfig.hideInstanceWallpaper
? null
: this.instanceBackground)
)
},
bgStyle() {
if (this.background) {
@ -160,19 +163,19 @@ export default {
if (this.isChats) return false
if (this.isListEdit) return false
return (
this.$store.getters.mergedConfig.alwaysShowNewPostButton ||
useSyncConfigStore().mergedConfig.alwaysShowNewPostButton ||
this.layoutType === 'mobile'
)
},
shoutboxPosition() {
return this.$store.getters.mergedConfig.alwaysShowNewPostButton || false
return useSyncConfigStore().mergedConfig.alwaysShowNewPostButton || false
},
hideShoutbox() {
return this.$store.getters.mergedConfig.hideShoutbox
return useSyncConfigStore().mergedConfig.hideShoutbox
},
reverseLayout() {
const { thirdColumnMode, sidebarRight: reverseSetting } =
this.$store.getters.mergedConfig
useSyncConfigStore().mergedConfig
if (this.layoutType !== 'wide') {
return reverseSetting
} else {
@ -182,10 +185,10 @@ export default {
}
},
noSticky() {
return this.$store.getters.mergedConfig.disableStickyHeaders
return useSyncConfigStore().mergedConfig.disableStickyHeaders
},
showScrollbars() {
return this.$store.getters.mergedConfig.showScrollbars
return useSyncConfigStore().mergedConfig.showScrollbars
},
scrollParent() {
return window /* this.$refs.appContentRef */
@ -193,7 +196,7 @@ export default {
showInstanceSpecificPanel() {
return (
this.instanceSpecificPanelPresent &&
!this.$store.getters.mergedConfig.hideISP
!useSyncConfigStore().mergedConfig.hideISP
)
},
...mapGetters(['mergedConfig']),
@ -208,7 +211,7 @@ export default {
'editingAvailable',
]),
...mapState(useInstanceStore, {
background: (store) => store.instanceIdentity.background,
instanceBackground: (store) => store.instanceIdentity.background,
showFeaturesPanel: (store) => store.instanceIdentity.showFeaturesPanel,
instanceSpecificPanelPresent: (store) =>
store.instanceIdentity.showInstanceSpecificPanel &&

View file

@ -17,7 +17,7 @@ config.autoAddCss = false
import App from '../App.vue'
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
import FaviconService from '../services/favicon_service/favicon_service.js'
import { applyConfig } from '../services/style_setter/style_setter.js'
import { applyStyleConfig } from '../services/style_setter/style_setter.js'
import { initServiceWorker, updateFocus } from '../services/sw/sw.js'
import {
windowHeight,
@ -88,25 +88,25 @@ const getInstanceConfig = async ({ store }) => {
data.pleroma,
)
useInstanceStore().set({
name: 'textlimit',
path: 'textlimit',
value: textlimit,
})
useInstanceStore().set({
name: 'accountApprovalRequired',
path: 'accountApprovalRequired',
value: data.approval_required,
})
useInstanceStore().set({
name: 'birthdayRequired',
path: 'birthdayRequired',
value: !!data.pleroma?.metadata.birthday_required,
})
useInstanceStore().set({
name: 'birthdayMinAge',
path: 'birthdayMinAge',
value: data.pleroma?.metadata.birthday_min_age || 0,
})
if (vapidPublicKey) {
useInstanceStore().set({
name: 'vapidPublicKey',
path: 'vapidPublicKey',
value: vapidPublicKey,
})
}
@ -258,7 +258,7 @@ const getAppSecret = async ({ store }) => {
const resolveStaffAccounts = ({ store, accounts }) => {
const nicknames = accounts.map((uri) => uri.split('/').pop())
useInstanceStore().set({
name: 'staffAccounts',
path: 'staffAccounts',
value: nicknames,
})
}
@ -384,20 +384,20 @@ const getNodeInfo = async ({ store }) => {
const software = data.software
useInstanceStore().set({
name: 'backendVersion',
path: 'backendVersion',
value: software.version,
})
useInstanceStore().set({
name: 'backendRepository',
path: 'backendRepository',
value: software.repository,
})
const priv = metadata.private
useInstanceStore().set({ name: 'privateMode', value: priv })
useInstanceStore().set({ path: 'privateMode', value: priv })
const frontendVersion = window.___pleromafe_commit_hash
useInstanceStore().set({
name: 'frontendVersion',
path: 'frontendVersion',
value: frontendVersion,
})
@ -547,7 +547,7 @@ const afterStoreSetup = async ({ pinia, store, storageError, i18n }) => {
return Promise.reject(e)
}
applyConfig(store.state.config, i18n.global)
applyStyleConfig(store.state.config, i18n.global)
// Now we can try getting the server settings and logging in
// Most of these are preloaded into the index.html so blocking is minimized

View file

@ -5,6 +5,7 @@ import StaffPanel from '../staff_panel/staff_panel.vue'
import TermsOfServicePanel from '../terms_of_service_panel/terms_of_service_panel.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
const About = {
components: {
@ -21,7 +22,7 @@ const About = {
showInstanceSpecificPanel() {
return (
useInstanceStore().instanceIdentity.showInstanceSpecificPanel &&
!this.$store.getters.mergedConfig.hideISP &&
!useSyncConfigStore().mergedConfig.hideISP &&
useInstanceStore().instanceIdentity.instanceSpecificPanelContent
)
},

View file

@ -8,6 +8,7 @@ import ProgressButton from '../progress_button/progress_button.vue'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useReportsStore } from 'src/stores/reports'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faEllipsisV } from '@fortawesome/free-solid-svg-icons'
@ -89,10 +90,10 @@ const AccountActions = {
},
computed: {
shouldConfirmBlock() {
return this.$store.getters.mergedConfig.modalOnBlock
return useSyncConfigStore().mergedConfig.modalOnBlock
},
shouldConfirmRemoveUserFromFollowers() {
return this.$store.getters.mergedConfig.modalOnRemoveUserFromFollowers
return useSyncConfigStore().mergedConfig.modalOnRemoveUserFromFollowers
},
...mapState(useInstanceCapabilitiesStore, [
'blockExpiration',

View file

@ -9,6 +9,7 @@ import VideoAttachment from '../video_attachment/video_attachment.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useMediaViewerStore } from 'src/stores/media_viewer'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
@ -58,8 +59,8 @@ const Attachment = {
localDescription: this.description || this.attachment.description,
nsfwImage:
useInstanceStore().instanceIdentity.nsfwCensorImage || nsfwImage,
hideNsfwLocal: this.$store.getters.mergedConfig.hideNsfw,
preloadImage: this.$store.getters.mergedConfig.preloadImage,
hideNsfwLocal: useSyncConfigStore().mergedConfig.hideNsfw,
preloadImage: useSyncConfigStore().mergedConfig.preloadImage,
loading: false,
img:
fileTypeService.fileType(this.attachment.mimetype) === 'image' &&
@ -93,7 +94,7 @@ const Attachment = {
return this.size === 'hide'
},
useContainFit() {
return this.$store.getters.mergedConfig.useContainFit
return useSyncConfigStore().mergedConfig.useContainFit
},
placeholderName() {
if (this.attachment.description === '' || !this.attachment.description) {

View file

@ -1,8 +1,10 @@
import { mapGetters } from 'vuex'
import { mapState } from 'pinia'
import Select from 'src/components/select/select.vue'
import ConfirmModal from './confirm_modal.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
export default {
props: ['type', 'user', 'status'],
emits: ['hide', 'show', 'muted'],
@ -43,7 +45,7 @@ export default {
}
}
},
...mapGetters(['mergedConfig']),
...mapState(useSyncConfigStore, ['mergedConfig']),
},
methods: {
optionallyPrompt() {

View file

@ -9,6 +9,7 @@ import Status from '../status/status.vue'
import ThreadTree from '../thread_tree/thread_tree.vue'
import { useInterfaceStore } from 'src/stores/interface'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
@ -81,7 +82,7 @@ const conversation = {
// maxDepthInThread = max number of depths that is *visible*
// since our depth starts with 0 and "showing" means "showing children"
// there is a -2 here
const maxDepth = this.$store.getters.mergedConfig.maxDepthInThread - 2
const maxDepth = useSyncConfigStore().mergedConfig.maxDepthInThread - 2
return maxDepth >= 1 ? maxDepth : 1
},
streamingEnabled() {
@ -91,22 +92,22 @@ const conversation = {
)
},
displayStyle() {
return this.$store.getters.mergedConfig.conversationDisplay
return useSyncConfigStore().mergedConfig.conversationDisplay
},
isTreeView() {
return !this.isLinearView
},
treeViewIsSimple() {
return !this.$store.getters.mergedConfig.conversationTreeAdvanced
return !useSyncConfigStore().mergedConfig.conversationTreeAdvanced
},
isLinearView() {
return this.displayStyle === 'linear'
},
shouldFadeAncestors() {
return this.$store.getters.mergedConfig.conversationTreeFadeAncestors
return useSyncConfigStore().mergedConfig.conversationTreeFadeAncestors
},
otherRepliesButtonPosition() {
return this.$store.getters.mergedConfig.conversationOtherRepliesButton
return useSyncConfigStore().mergedConfig.conversationOtherRepliesButton
},
showOtherRepliesButtonBelowStatus() {
return this.otherRepliesButtonPosition === 'below'

View file

@ -5,6 +5,7 @@ import ConfirmModal from '../confirm_modal/confirm_modal.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
@ -96,7 +97,7 @@ export default {
return this.$store.state.users.currentUser
},
shouldConfirmLogout() {
return this.$store.getters.mergedConfig.modalOnLogout
return useSyncConfigStore().mergedConfig.modalOnLogout
},
},
methods: {

View file

@ -1,3 +1,5 @@
import { useSyncConfigStore } from 'src/stores/sync_config.js'
const DialogModal = {
props: {
darkOverlay: {
@ -13,7 +15,7 @@ const DialogModal = {
},
computed: {
mobileCenter() {
return this.$store.getters.mergedConfig.modalMobileCenter
return useSyncConfigStore().mergedConfig.modalMobileCenter
},
},
}

View file

@ -6,6 +6,8 @@ import Gallery from 'src/components/gallery/gallery.vue'
import PostStatusForm from 'src/components/post_status_form/post_status_form.vue'
import StatusContent from 'src/components/status_content/status_content.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faPollH } from '@fortawesome/free-solid-svg-icons'
@ -57,7 +59,7 @@ const Draft = {
: undefined
},
localCollapseSubjectDefault() {
return this.$store.getters.mergedConfig.collapseMessageWithSubject
return useSyncConfigStore().mergedConfig.collapseMessageWithSubject
},
nsfwClickthrough() {
if (!this.draft.nsfw) {

View file

@ -1,5 +1,7 @@
import DialogModal from 'src/components/dialog_modal/dialog_modal.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
const DraftCloser = {
data() {
return {
@ -12,10 +14,10 @@ const DraftCloser = {
emits: ['save', 'discard'],
computed: {
action() {
if (this.$store.getters.mergedConfig.autoSaveDraft) {
if (useSyncConfigStore().mergedConfig.autoSaveDraft) {
return 'save'
} else {
return this.$store.getters.mergedConfig.unsavedPostAction
return useSyncConfigStore().mergedConfig.unsavedPostAction
}
},
shouldConfirm() {

View file

@ -2,13 +2,16 @@ import { take } from 'lodash'
import Popover from 'src/components/popover/popover.vue'
import ScreenReaderNotice from 'src/components/screen_reader_notice/screen_reader_notice.vue'
import { ensureFinalFallback } from '../../i18n/languages.js'
import Completion from '../../services/completion/completion.js'
import { findOffset } from '../../services/offset_finder/offset_finder.service.js'
import genRandomSeed from '../../services/random_seed/random_seed.service.js'
import EmojiPicker from '../emoji_picker/emoji_picker.vue'
import UnicodeDomainIndicator from '../unicode_domain_indicator/unicode_domain_indicator.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { ensureFinalFallback } from 'src/i18n/languages.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faSmileBeam } from '@fortawesome/free-regular-svg-icons'
@ -131,10 +134,10 @@ const EmojiInput = {
},
computed: {
padEmoji() {
return this.$store.getters.mergedConfig.padEmoji
return useSyncConfigStore().mergedConfig.padEmoji
},
defaultCandidateIndex() {
return this.$store.getters.mergedConfig.autocompleteSelect ? 0 : -1
return useSyncConfigStore().mergedConfig.autocompleteSelect ? 0 : -1
},
preText() {
return this.modelValue.slice(0, this.caret)
@ -163,7 +166,7 @@ const EmojiInput = {
},
languages() {
return ensureFinalFallback(
this.$store.getters.mergedConfig.interfaceLanguage,
useSyncConfigStore().mergedConfig.interfaceLanguage,
)
},
maybeLocalizedEmojiNamesAndKeywords() {
@ -331,7 +334,6 @@ const EmojiInput = {
if (!this.pickerShown) {
this.scrollIntoView()
this.$refs.picker.showPicker()
this.$refs.picker.startEmojiLoad()
} else {
this.$refs.picker.hidePicker()
}

View file

@ -1,3 +1,5 @@
import { useEmojiStore } from 'src/stores/emoji.js'
/**
* suggest - generates a suggestor function to be used by emoji-input
* data: object providing source information for specific types of suggestions:

View file

@ -8,6 +8,7 @@ import StillImage from '../still-image/still-image.vue'
import { useEmojiStore } from 'src/stores/emoji.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
@ -340,7 +341,7 @@ const EmojiPicker = {
this.$nextTick(() => {
this.updateEmojiSize()
})
return this.$store.getters.mergedConfig.fontSize
return useSyncConfigStore().mergedConfig.fontSize
},
emojiHeight() {
return this.emojiSize
@ -405,7 +406,7 @@ const EmojiPicker = {
},
languages() {
return ensureFinalFallback(
this.$store.getters.mergedConfig.interfaceLanguage,
useSyncConfigStore().mergedConfig.interfaceLanguage,
)
},
maybeLocalizedEmojiName() {

View file

@ -3,6 +3,8 @@ import {
requestUnfollow,
} from '../../services/follow_manipulate/follow_manipulate'
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
export default {
props: ['relationship', 'user', 'labelFollowing', 'buttonClass'],
components: {
@ -16,7 +18,7 @@ export default {
},
computed: {
shouldConfirmUnfollow() {
return this.$store.getters.mergedConfig.modalOnUnfollow
return useSyncConfigStore().mergedConfig.modalOnUnfollow
},
isPressed() {
return this.inProgress || this.relationship.following

View file

@ -2,6 +2,8 @@ import { notificationsFromStore } from '../../services/notification_utils/notifi
import BasicUserCard from '../basic_user_card/basic_user_card.vue'
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
const FollowRequestCard = {
props: ['user'],
components: {
@ -76,7 +78,7 @@ const FollowRequestCard = {
},
computed: {
mergedConfig() {
return this.$store.getters.mergedConfig
return useSyncConfigStore().mergedConfig
},
shouldConfirmApprove() {
return this.mergedConfig.modalOnApproveFollow

View file

@ -1,4 +1,6 @@
import { mapGetters } from 'vuex'
import { mapState } from 'pinia'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
const LinkPreview = {
name: 'LinkPreview',
@ -24,7 +26,7 @@ const LinkPreview = {
hideNsfwConfig() {
return this.mergedConfig.hideNsfw
},
...mapGetters(['mergedConfig']),
...mapState(useSyncConfigStore, ['mergedConfig']),
},
created() {
if (this.useImage) {

View file

@ -2,6 +2,7 @@ import fileSizeFormatService from '../../services/file_size_format/file_size_for
import statusPosterService from '../../services/status_poster/status_poster.service.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faCircleNotch, faUpload } from '@fortawesome/free-solid-svg-icons'
@ -33,7 +34,7 @@ const mediaUpload = {
}
// Skip if image compression is disabled
if (!this.$store.getters.mergedConfig.imageCompression) {
if (!useSyncConfigStore().mergedConfig.imageCompression) {
return file
}
@ -78,7 +79,7 @@ const mediaUpload = {
// Convert to WebP if supported and alwaysUseJpeg is false, otherwise JPEG
const type =
!this.$store.getters.mergedConfig.alwaysUseJpeg && supportsWebP
!useSyncConfigStore().mergedConfig.alwaysUseJpeg && supportsWebP
? 'image/webp'
: 'image/jpeg'
const extension = type === 'image/webp' ? '.webp' : '.jpg'

View file

@ -1,7 +1,9 @@
import { mapGetters } from 'vuex'
import { mapState } from 'pinia'
import MentionLink from 'src/components/mention_link/mention_link.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
export const MENTIONS_LIMIT = 5
const MentionsLine = {
@ -26,7 +28,7 @@ const MentionsLine = {
manyMentions() {
return this.extraMentions.length > 0
},
...mapGetters(['mergedConfig']),
...mapState(useSyncConfigStore, ['mergedConfig']),
},
methods: {
toggleShowMore() {

View file

@ -13,7 +13,7 @@ import SideDrawer from '../side_drawer/side_drawer.vue'
import { useAnnouncementsStore } from 'src/stores/announcements.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
@ -75,15 +75,15 @@ const MobileNav = {
return this.$route.name === 'chat'
},
...mapState(useAnnouncementsStore, ['unreadAnnouncementCount']),
...mapState(useServerSideStorageStore, {
...mapState(useSyncConfigStore, {
pinnedItems: (store) =>
new Set(store.prefsStorage.collections.pinnedNavItems).has('chats'),
}),
shouldConfirmLogout() {
return this.$store.getters.mergedConfig.modalOnLogout
return useSyncConfigStore().mergedConfig.modalOnLogout
},
closingDrawerMarksAsSeen() {
return this.$store.getters.mergedConfig.closingDrawerMarksAsSeen
return useSyncConfigStore().mergedConfig.closingDrawerMarksAsSeen
},
...mapGetters(['unreadChatCount']),
},

View file

@ -1,6 +1,7 @@
import { debounce } from 'lodash'
import { usePostStatusStore } from 'src/stores/post_status.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faPen } from '@fortawesome/free-solid-svg-icons'
@ -45,10 +46,10 @@ const MobilePostStatusButton = {
)
},
isPersistent() {
return !!this.$store.getters.mergedConfig.alwaysShowNewPostButton
return !!useSyncConfigStore().mergedConfig.alwaysShowNewPostButton
},
autohideFloatingPostButton() {
return !!this.$store.getters.mergedConfig.autohideFloatingPostButton
return !!useSyncConfigStore().mergedConfig.autohideFloatingPostButton
},
},
watch: {

View file

@ -12,7 +12,7 @@ import NavigationPins from 'src/components/navigation/navigation_pins.vue'
import { useAnnouncementsStore } from 'src/stores/announcements'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
@ -84,28 +84,28 @@ const NavPanel = {
this.editMode = !this.editMode
},
toggleCollapse() {
useServerSideStorageStore().setPreference({
useSyncConfigStore().setPreference({
path: 'simple.collapseNav',
value: !this.collapsed,
})
useServerSideStorageStore().pushServerSideStorage()
useSyncConfigStore().pushSyncConfig()
},
isPinned(item) {
return this.pinnedItems.has(item)
},
togglePin(item) {
if (this.isPinned(item)) {
useServerSideStorageStore().removeCollectionPreference({
useSyncConfigStore().removeCollectionPreference({
path: 'collections.pinnedNavItems',
value: item,
})
} else {
useServerSideStorageStore().addCollectionPreference({
useSyncConfigStore().addCollectionPreference({
path: 'collections.pinnedNavItems',
value: item,
})
}
useServerSideStorageStore().pushServerSideStorage()
useSyncConfigStore().pushSyncConfig()
},
},
computed: {
@ -122,7 +122,7 @@ const NavPanel = {
...mapPiniaState(useInstanceStore, {
privateMode: (store) => store.private,
}),
...mapPiniaState(useServerSideStorageStore, {
...mapPiniaState(useSyncConfigStore, {
collapsed: (store) => store.prefsStorage.simple.collapseNav,
pinnedItems: (store) =>
new Set(store.prefsStorage.collections.pinnedNavItems),

View file

@ -5,7 +5,7 @@ import { routeTo } from 'src/components/navigation/navigation.js'
import OptionalRouterLink from 'src/components/optional_router_link/optional_router_link.vue'
import { useAnnouncementsStore } from 'src/stores/announcements.js'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faThumbtack } from '@fortawesome/free-solid-svg-icons'
@ -23,17 +23,17 @@ const NavigationEntry = {
},
togglePin(value) {
if (this.isPinned(value)) {
useServerSideStorageStore().removeCollectionPreference({
useSyncConfigStore().removeCollectionPreference({
path: 'collections.pinnedNavItems',
value,
})
} else {
useServerSideStorageStore().addCollectionPreference({
useSyncConfigStore().addCollectionPreference({
path: 'collections.pinnedNavItems',
value,
})
}
useServerSideStorageStore().pushServerSideStorage()
useSyncConfigStore().pushSyncConfig()
},
},
computed: {
@ -47,7 +47,7 @@ const NavigationEntry = {
...mapState({
currentUser: (state) => state.users.currentUser,
}),
...mapPiniaState(useServerSideStorageStore, {
...mapPiniaState(useSyncConfigStore, {
pinnedItems: (store) =>
new Set(store.prefsStorage.collections.pinnedNavItems),
}),

View file

@ -18,7 +18,7 @@ import { useBookmarkFoldersStore } from 'src/stores/bookmark_folders'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useListsStore } from 'src/stores/lists'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
@ -70,7 +70,7 @@ const NavPanel = {
...mapPiniaState(useBookmarkFoldersStore, {
bookmarks: getBookmarkFolderEntries,
}),
...mapPiniaState(useServerSideStorageStore, {
...mapPiniaState(useSyncConfigStore, {
pinnedItems: (store) =>
new Set(store.prefsStorage.collections.pinnedNavItems),
}),

View file

@ -17,6 +17,7 @@ import UserLink from '../user_link/user_link.vue'
import UserPopover from '../user_popover/user_popover.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
@ -181,7 +182,7 @@ const Notification = {
return highlightClass(this.notification.from_profile)
},
userStyle() {
const highlight = this.$store.getters.mergedConfig.highlight
const highlight = useSyncConfigStore().mergedConfig.highlight
const user = this.notification.from_profile
return highlightStyle(highlight[user.screen_name])
},
@ -209,7 +210,7 @@ const Notification = {
return isStatusNotification(this.notification.type)
},
mergedConfig() {
return this.$store.getters.mergedConfig
return useSyncConfigStore().mergedConfig
},
shouldConfirmApprove() {
return this.mergedConfig.modalOnApproveFollow

View file

@ -108,6 +108,8 @@
<script>
import Popover from '../popover/popover.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import { faFilter } from '@fortawesome/free-solid-svg-icons'
@ -117,7 +119,7 @@ export default {
components: { Popover },
computed: {
filters() {
return this.$store.getters.mergedConfig.notificationVisibility
return useSyncConfigStore().mergedConfig.notificationVisibility
},
},
methods: {

View file

@ -17,6 +17,7 @@ import NotificationFilters from './notification_filters.vue'
import { useAnnouncementsStore } from 'src/stores/announcements.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
@ -98,7 +99,7 @@ const Notifications = {
return this.unseenNotifications.length
},
ignoreInactionableSeen() {
return this.$store.getters.mergedConfig.ignoreInactionableSeen
return useSyncConfigStore().mergedConfig.ignoreInactionableSeen
},
extraNotificationsCount() {
return countExtraNotifications(this.$store)
@ -136,10 +137,10 @@ const Notifications = {
)
},
noSticky() {
return this.$store.getters.mergedConfig.disableStickyHeaders
return useSyncConfigStore().mergedConfig.disableStickyHeaders
},
unseenAtTop() {
return this.$store.getters.mergedConfig.unseenAtTop
return useSyncConfigStore().mergedConfig.unseenAtTop
},
showExtraNotifications() {
return !this.noExtra

View file

@ -5,6 +5,7 @@ import Timeago from 'components/timeago/timeago.vue'
import genRandomSeed from '../../services/random_seed/random_seed.service.js'
import { usePollsStore } from 'src/stores/polls.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
export default {
name: 'Poll',
@ -48,7 +49,7 @@ export default {
return (this.poll && this.poll.expired) || false
},
expirationLabel() {
if (this.$store.getters.mergedConfig.useAbsoluteTimeFormat) {
if (useSyncConfigStore().mergedConfig.useAbsoluteTimeFormat) {
return this.expired ? 'polls.expired_at' : 'polls.expires_at'
} else {
return this.expired ? 'polls.expired' : 'polls.expires_in'

View file

@ -25,6 +25,7 @@ import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useMediaViewerStore } from 'src/stores/media_viewer.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { pollFormToMasto } from 'src/services/poll/poll.service.js'
@ -163,7 +164,7 @@ const PostStatusForm = {
const preset = this.$route.query.message
let statusText = preset || ''
const { scopeCopy } = this.$store.getters.mergedConfig
const { scopeCopy } = useSyncConfigStore().mergedConfig
const [statusType, refId] = typeAndRefId({
replyTo: this.replyTo,
@ -193,7 +194,7 @@ const PostStatusForm = {
: this.$store.state.users.currentUser.default_scope
const { postContentType: contentType, sensitiveByDefault } =
this.$store.getters.mergedConfig
useSyncConfigStore().mergedConfig
statusParams = {
type: statusType,
@ -324,7 +325,7 @@ const PostStatusForm = {
},
hideScopeNotice() {
return (
this.disableNotice || this.$store.getters.mergedConfig.hideScopeNotice
this.disableNotice || useSyncConfigStore().mergedConfig.hideScopeNotice
)
},
pollContentError() {
@ -380,7 +381,7 @@ const PostStatusForm = {
return this.newStatus.hasPoll
},
shouldAutoSaveDraft() {
return this.$store.getters.mergedConfig.autoSaveDraft
return useSyncConfigStore().mergedConfig.autoSaveDraft
},
autoSaveState() {
if (this.saveable) {

View file

@ -1,5 +1,7 @@
import ConfirmModal from '../confirm_modal/confirm_modal.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
export default {
props: ['user', 'relationship'],
data() {
@ -20,7 +22,7 @@ export default {
}
},
shouldConfirmRemoveUserFromFollowers() {
return this.$store.getters.mergedConfig.modalOnRemoveUserFromFollowers
return useSyncConfigStore().mergedConfig.modalOnRemoveUserFromFollowers
},
},
methods: {

View file

@ -4,6 +4,10 @@ import DraftButtons from './draft_buttons.vue'
import ModifiedIndicator from './modified_indicator.vue'
import ProfileSettingIndicator from './profile_setting_indicator.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
export default {
components: {
ModifiedIndicator,
@ -235,13 +239,14 @@ export default {
case 'admin':
return this.$store.state.adminSettings.config
default:
return this.$store.getters.mergedConfig
return useSyncConfigStore().mergedConfig
}
},
configSink() {
if (this.path == null) {
return (k, v) => this.$emit('update:modelValue', v)
}
switch (this.realSource) {
case 'profile':
return (k, v) =>
@ -250,15 +255,37 @@ export default {
return (k, v) =>
this.$store.dispatch('pushAdminSetting', { path: k, value: v })
default:
if (this.timedApplyMode) {
return (k, v) =>
this.$store.dispatch('setOptionTemporarily', {
name: k,
value: v,
})
} else {
return (k, v) =>
this.$store.dispatch('setOption', { name: k, value: v })
return (readPath, value) => {
const writePath = `simple.${readPath}`
if (!this.timedApplyMode) {
useSyncConfigStore().setPreference({ path: writePath, value })
useSyncConfigStore().pushSyncConfig()
} else {
if (useInterfaceStore().temporaryChangesTimeoutId !== null) {
console.error("Can't track more than one temporary change")
return
}
const oldValue = get(this.configSource, readPath)
useSyncConfigStore().setPreference({ path: writePath, value })
const confirm = () => {
useSyncConfigStore().pushSyncConfig()
useInterfaceStore().clearTemporaryChanges()
}
const revert = () => {
useSyncConfigStore().setPreference({
path: writePath,
value: oldValue,
})
useInterfaceStore().clearTemporaryChanges()
}
useInterfaceStore().setTemporaryChanges({ confirm, revert })
}
}
}
},
@ -267,7 +294,7 @@ export default {
case 'profile':
return {}
default:
return get(this.$store.getters.defaultConfig, this.path)
return get(useInstanceStore().prefsStorage, this.path)
}
},
isProfileSetting() {
@ -318,7 +345,8 @@ export default {
},
matchesExpertLevel() {
const settingExpertLevel = this.expert || 0
const userToggleExpert = this.$store.state.config.expertLevel || 0
const userToggleExpert =
useSyncConfigStore().mergedConfig.expertLevel || 0
return settingExpertLevel <= userToggleExpert
},
@ -344,7 +372,7 @@ export default {
this.draft = cloneDeep(this.state)
} else {
set(
this.$store.getters.mergedConfig,
useSyncConfigStore().mergedConfig,
this.path,
cloneDeep(this.defaultState),
)

View file

@ -1,19 +1,18 @@
import { mapState as mapPiniaState } from 'pinia'
import { mapState } from 'vuex'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
const SharedComputedObject = () => ({
user() {
return this.$store.state.users.currentUser
},
expertLevel() {
return this.$store.getters.mergedConfig.expertLevel > 0
},
mergedConfig() {
return this.$store.getters.mergedConfig
},
adminConfig() {
return this.$store.state.adminSettings.config
},
adminDraft() {
return this.$store.state.adminSettings.draft
},
...mapPiniaState(useSyncConfigStore, ['mergedConfig']),
...mapPiniaState(useSyncConfigStore, {
expertLevel: (store) => store.mergedConfig.expertLevel,
}),
...mapState({
adminConfig: (state) => state.adminSettings.config,
adminDraft: (state) => state.adminSettings.draft,
user: (state) => state.users.currentUser,
}),
})
export default SharedComputedObject

View file

@ -9,6 +9,7 @@ import PanelLoading from 'src/components/panel_loading/panel_loading.vue'
import Popover from '../popover/popover.vue'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import {
newExporter,
@ -191,11 +192,11 @@ const SettingsModal = {
}),
expertLevel: {
get() {
return this.$store.state.config.expertLevel > 0
return useSyncConfigStore().mergedConfig.expertLevel > 0
},
set(value) {
this.$store.dispatch('setOption', {
name: 'expertLevel',
useSyncConfigStore().setPreference({
path: 'simple.expertLevel',
value: value ? 1 : 0,
})
},

View file

@ -54,7 +54,7 @@
:key="style.key"
:data-theme-key="style.key"
class="button-default theme-preview"
:class="{ toggled: isThemeActive(style.key), disabled: switchInProgress }"
:class="{ toggled: isStyleActive(style.key), disabled: switchInProgress }"
:disabled="switchInProgress"
@click="style.version === 'v2' ? setTheme(style.key) : setStyle(style.key)"
>
@ -90,7 +90,7 @@
class="btn button-default palette-entry"
:class="{ toggled: isPaletteActive(p.key), disabled: switchInProgress }"
:disabled="switchInProgress"
@click="() => setPalette(p.key, p)"
@click="() => setLocalPalette(p.key, p)"
>
<div class="palette-label">
<label>
@ -113,7 +113,7 @@
class="btn button-default palette-entry"
:class="{ toggled: isPaletteActive(p.key), disabled: switchInProgress }"
:disabled="switchInProgress"
@click="() => setPalette(p.key, p)"
@click="() => setLocalPalette(p.key, p)"
>
<div class="palette-label">
<label>
@ -143,7 +143,7 @@
:compact="true"
:apply="true"
:disabled="switchInProgress"
@apply-palette="data => setPaletteCustom(data)"
@apply-palette="data => setLocalPaletteCustom(data)"
/>
</template>
<template v-else-if="customThemeVersion === 'v2'">

View file

@ -12,7 +12,7 @@ import UnitSetting from '../helpers/unit_setting.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
const ClutterTab = {
components: {
@ -33,7 +33,7 @@ const ClutterTab = {
store.instanceIdentity.showInstanceSpecificPanel &&
store.instanceIdentity.instanceSpecificPanelContent,
}),
...mapState(useServerSideStorageStore, {
...mapState(useSyncConfigStore, {
muteFilters: (store) =>
Object.entries(store.prefsStorage.simple.muteFilters),
muteFiltersObject: (store) => store.prefsStorage.simple.muteFilters,
@ -89,10 +89,10 @@ const ClutterTab = {
},
},
methods: {
...mapActions(useServerSideStorageStore, [
...mapActions(useSyncConfigStore, [
'setPreference',
'unsetPreference',
'pushServerSideStorage',
'pushSyncConfig',
]),
getDatetimeLocal(timestamp) {
const date = new Date(timestamp)
@ -139,7 +139,7 @@ const ClutterTab = {
filter.order = this.muteFilters.length + 2
this.muteFiltersDraftObject[newId] = filter
this.setPreference({ path: 'simple.muteFilters.' + newId, value: filter })
this.pushServerSideStorage()
this.pushSyncConfig()
},
exportFilter(id) {
this.exportedFilter = { ...this.muteFiltersDraftObject[id] }
@ -155,19 +155,19 @@ const ClutterTab = {
this.muteFiltersDraftObject[newId] = filter
this.setPreference({ path: 'simple.muteFilters.' + newId, value: filter })
this.pushServerSideStorage()
this.pushSyncConfig()
},
deleteFilter(id) {
delete this.muteFiltersDraftObject[id]
this.unsetPreference({ path: 'simple.muteFilters.' + id, value: null })
this.pushServerSideStorage()
this.pushSyncConfig()
},
purgeExpiredFilters() {
this.muteFiltersExpired.forEach(([id]) => {
delete this.muteFiltersDraftObject[id]
this.unsetPreference({ path: 'simple.muteFilters.' + id, value: null })
})
this.pushServerSideStorage()
this.pushSyncConfig()
},
updateFilter(id, field, value) {
const filter = { ...this.muteFiltersDraftObject[id] }
@ -193,7 +193,7 @@ const ClutterTab = {
path: 'simple.muteFilters.' + id,
value: this.muteFiltersDraftObject[id],
})
this.pushServerSideStorage()
this.pushSyncConfig()
this.muteFiltersDraftDirty[id] = false
},
},

View file

@ -19,9 +19,7 @@
</BooleanSetting>
</li>
<li>
<BooleanSetting
path="hideUserStats"
>
<BooleanSetting path="hideUserStats">
{{ $t('settings.hide_user_stats') }}
</BooleanSetting>
</li>

View file

@ -13,6 +13,7 @@ import SharedComputedObject from '../helpers/shared_computed_object.js'
import UnitSetting from '../helpers/unit_setting.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import localeService from 'src/services/locale/locale.service.js'
import { cacheKey, clearCache, emojiCacheKey } from 'src/services/sw/sw.js'
@ -116,7 +117,7 @@ const ComposingTab = {
},
language: {
get: function () {
return this.$store.getters.mergedConfig.interfaceLanguage
return useSyncConfigStore().mergedConfig.interfaceLanguage
},
set: function (val) {
this.$store.dispatch('setOption', {

View file

@ -13,7 +13,7 @@ import UnitSetting from '../helpers/unit_setting.vue'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import {
newExporter,
@ -36,11 +36,11 @@ const FilteringTab = {
label: this.$t(`user_card.mute_block_${mode}`),
})),
muteFiltersDraftObject: cloneDeep(
useServerSideStorageStore().prefsStorage.simple.muteFilters,
useSyncConfigStore().prefsStorage.simple.muteFilters,
),
muteFiltersDraftDirty: Object.fromEntries(
Object.entries(
useServerSideStorageStore().prefsStorage.simple.muteFilters,
useSyncConfigStore().prefsStorage.simple.muteFilters,
).map(([k]) => [k, false]),
),
exportedFilter: null,
@ -92,7 +92,7 @@ const FilteringTab = {
},
computed: {
...SharedComputedObject(),
...mapState(useServerSideStorageStore, {
...mapState(useSyncConfigStore, {
muteFilters: (store) =>
Object.entries(store.prefsStorage.simple.muteFilters),
muteFiltersObject: (store) => store.prefsStorage.simple.muteFilters,
@ -149,10 +149,10 @@ const FilteringTab = {
},
},
methods: {
...mapActions(useServerSideStorageStore, [
...mapActions(useSyncConfigStore, [
'setPreference',
'unsetPreference',
'pushServerSideStorage',
'pushSyncConfig',
]),
getDatetimeLocal(timestamp) {
const date = new Date(timestamp)
@ -199,7 +199,7 @@ const FilteringTab = {
filter.order = this.muteFilters.length + 2
this.muteFiltersDraftObject[newId] = filter
this.setPreference({ path: 'simple.muteFilters.' + newId, value: filter })
this.pushServerSideStorage()
this.pushSyncConfig()
},
exportFilter(id) {
this.exportedFilter = { ...this.muteFiltersDraftObject[id] }
@ -215,19 +215,19 @@ const FilteringTab = {
this.muteFiltersDraftObject[newId] = filter
this.setPreference({ path: 'simple.muteFilters.' + newId, value: filter })
this.pushServerSideStorage()
this.pushSyncConfig()
},
deleteFilter(id) {
delete this.muteFiltersDraftObject[id]
this.unsetPreference({ path: 'simple.muteFilters.' + id, value: null })
this.pushServerSideStorage()
this.pushSyncConfig()
},
purgeExpiredFilters() {
this.muteFiltersExpired.forEach(([id]) => {
delete this.muteFiltersDraftObject[id]
this.unsetPreference({ path: 'simple.muteFilters.' + id, value: null })
})
this.pushServerSideStorage()
this.pushSyncConfig()
},
updateFilter(id, field, value) {
const filter = { ...this.muteFiltersDraftObject[id] }
@ -253,7 +253,7 @@ const FilteringTab = {
path: 'simple.muteFilters.' + id,
value: this.muteFiltersDraftObject[id],
})
this.pushServerSideStorage()
this.pushSyncConfig()
this.muteFiltersDraftDirty[id] = false
},
},

View file

@ -11,6 +11,7 @@ import UnitSetting from '../helpers/unit_setting.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import localeService from 'src/services/locale/locale.service.js'
@ -37,7 +38,7 @@ const GeneralTab = {
computed: {
language: {
get: function () {
return this.$store.getters.mergedConfig.interfaceLanguage
return useSyncConfigStore().mergedConfig.interfaceLanguage
},
set: function (val) {
this.$store.dispatch('setOption', {
@ -48,6 +49,9 @@ const GeneralTab = {
},
...SharedComputedObject(),
...mapState(useInstanceCapabilitiesStore, ['blockExpiration']),
...mapState(useSyncConfigStore, {
theme3hacks: (store) => store.mergedConfig.theme3hacks,
}),
},
methods: {
updateProfile() {

View file

@ -68,7 +68,7 @@
</li>
<li>
<FontControl
:model-value="mergedConfig.theme3hacks.fonts.interface"
:model-value="theme3hacks.fonts.interface"
name="ui"
:label="$t('settings.style.fonts.components_inline.interface')"
:fallback="{ family: 'sans-serif' }"
@ -78,7 +78,7 @@
</li>
<li>
<FontControl
:model-value="mergedConfig.theme3hacks.fonts.input"
:model-value="theme3hacks.fonts.input"
name="input"
:fallback="{ family: 'inherit' }"
:label="$t('settings.style.fonts.components_inline.input')"

View file

@ -7,6 +7,7 @@ import SharedComputedObject from '../helpers/shared_computed_object.js'
import UnitSetting from '../helpers/unit_setting.vue'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
const GeneralTab = {
data() {
@ -32,12 +33,12 @@ const GeneralTab = {
'suggestionsEnabled',
]),
columns() {
const mode = this.$store.getters.mergedConfig.thirdColumnMode
const mode = useSyncConfigStore().mergedConfig.thirdColumnMode
const notif = mode === 'none' ? [] : ['notifs']
if (
this.$store.getters.mergedConfig.sidebarRight ||
useSyncConfigStore().mergedConfig.sidebarRight ||
mode === 'postform'
) {
return [...notif, 'content', 'sidebar']

View file

@ -11,6 +11,7 @@ import Preview from './theme_preview.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import {
getContrastRatioLayers,
@ -81,7 +82,7 @@ export default {
}),
availableStyles: [],
selected: '',
selectedTheme: this.$store.getters.mergedConfig.theme,
selectedTheme: useSyncConfigStore().mergedConfig.theme,
themeWarning: undefined,
tempImportFile: undefined,
engineVersion: 0,

View file

@ -22,7 +22,7 @@ import UserPopover from '../user_popover/user_popover.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator'
@ -259,9 +259,7 @@ const Status = {
},
muteFilterHits() {
return muteFilterHits(
Object.values(
useServerSideStorageStore().prefsStorage.simple.muteFilters,
),
Object.values(useSyncConfigStore().prefsStorage.simple.muteFilters),
this.status,
)
},
@ -480,7 +478,7 @@ const Status = {
return this.$store.state.users.currentUser
},
mergedConfig() {
return this.$store.getters.mergedConfig
return useSyncConfigStore().mergedConfig
},
isSuspendable() {
return !this.replying && this.mediaPlaying.length === 0

View file

@ -5,7 +5,7 @@ import Popover from 'src/components/popover/popover.vue'
import ActionButtonContainer from './action_button_container.vue'
import { BUTTONS } from './buttons_definitions.js'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import genRandomSeed from 'src/services/random_seed/random_seed.service.js'
@ -36,7 +36,7 @@ const StatusActionButtons = {
ActionButtonContainer,
},
computed: {
...mapState(useServerSideStorageStore, {
...mapState(useSyncConfigStore, {
pinnedItems: (store) =>
new Set(store.prefsStorage.collections.pinnedStatusActions),
}),
@ -111,18 +111,18 @@ const StatusActionButtons = {
return this.pinnedItems.has(button.name)
},
unpin(button) {
useServerSideStorageStore().removeCollectionPreference({
useSyncConfigStore().removeCollectionPreference({
path: 'collections.pinnedStatusActions',
value: button.name,
})
useServerSideStorageStore().pushServerSideStorage()
useSyncConfigStore().pushSyncConfig()
},
pin(button) {
useServerSideStorageStore().addCollectionPreference({
useSyncConfigStore().addCollectionPreference({
path: 'collections.pinnedStatusActions',
value: button.name,
})
useServerSideStorageStore().pushServerSideStorage()
useSyncConfigStore().pushSyncConfig()
},
getComponent(button) {
if (!this.$store.state.users.currentUser && button.anonLink) {

View file

@ -7,6 +7,7 @@ import LinkPreview from '../link-preview/link-preview.vue'
import Poll from '../poll/poll.vue'
import { useMediaViewerStore } from 'src/stores/media_viewer.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
@ -74,7 +75,7 @@ const StatusContent = {
uncontrolledShowingLongSubject: false,
// not as computed because it sets the initial state which will be changed later
uncontrolledExpandingSubject:
!this.$store.getters.mergedConfig.collapseMessageWithSubject,
!useSyncConfigStore().mergedConfig.collapseMessageWithSubject,
}
},
computed: {

View file

@ -0,0 +1,127 @@
import Popover from 'components/popover/popover.vue'
import SelectComponent from 'components/select/select.vue'
import { assign } from 'lodash'
import StillImage from './still-image.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface'
export default {
components: { StillImage, Popover, SelectComponent },
props: {
shortcode: {
type: String,
required: true,
},
isLocal: {
type: Boolean,
required: true,
},
},
data() {
return {
knownLocalPacks: {},
packName: '',
}
},
computed: {
isUserAdmin() {
return this.$store.state.users.currentUser.rights.admin
},
},
methods: {
displayError(msg) {
useInterfaceStore().pushGlobalNotice({
messageKey: 'admin_dash.emoji.error',
messageArgs: [msg],
level: 'error',
})
},
copyToLocalPack() {
this.$store.state.api.backendInteractor
.addNewEmojiFile({
packName: this.packName,
file: this.$attrs.src,
shortcode: this.shortcode,
filename: '',
})
.then((resp) => resp.json())
.then((resp) => {
if (resp.error !== undefined) {
this.displayError(resp.error)
return
}
useInterfaceStore().pushGlobalNotice({
messageKey: 'admin_dash.emoji.copied_successfully',
messageArgs: [this.shortcode, this.packName],
level: 'success',
})
this.$refs.emojiPopover.hidePopover()
this.packName = ''
})
},
// Copied from emoji_tab.js
loadPacksPaginated(listFunction) {
const pageSize = 25
const allPacks = {}
return listFunction({
instance: useInstanceStore().server,
page: 1,
pageSize: 0,
})
.then((data) => data.json())
.then((data) => {
if (data.error !== undefined) {
return Promise.reject(data.error)
}
let resultingPromise = Promise.resolve({})
for (let i = 0; i < Math.ceil(data.count / pageSize); i++) {
resultingPromise = resultingPromise
.then(() =>
listFunction({
instance: useInstanceStore().server,
page: i,
pageSize,
}),
)
.then((data) => data.json())
.then((pageData) => {
if (pageData.error !== undefined) {
return Promise.reject(pageData.error)
}
assign(allPacks, pageData.packs)
})
}
return resultingPromise
})
.then(() => allPacks)
.catch((data) => {
this.displayError(data)
})
},
fetchEmojiPacksIfAdmin() {
if (!this.isUserAdmin) return
this.loadPacksPaginated(
this.$store.state.api.backendInteractor.listEmojiPacks,
).then((allPacks) => {
// Sort by key
const sorted = Object.keys(allPacks)
.sort()
.reduce((acc, key) => {
if (key.length === 0) return acc
acc[key] = allPacks[key]
return acc
}, {})
this.knownLocalPacks = sorted
})
},
},
}

View file

@ -1,3 +1,5 @@
import { useSyncConfigStore } from 'src/stores/sync_config.js'
const StillImage = {
props: [
'src',
@ -15,7 +17,7 @@ const StillImage = {
return {
// for lazy loading, see loadLazy()
realSrc: this.src,
stopGifs: this.$store.getters.mergedConfig.stopGifs,
stopGifs: useSyncConfigStore().mergedConfig.stopGifs,
}
},
computed: {

View file

@ -0,0 +1,129 @@
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import * as DateUtils from 'src/services/date_utils/date_utils.js'
import localeService from 'src/services/locale/locale.service.js'
export default {
name: 'Timeago',
props: ['time', 'autoUpdate', 'longFormat', 'nowThreshold', 'templateKey'],
data() {
return {
relativeTimeMs: 0,
relativeTime: { key: 'time.now', num: 0 },
interval: null,
}
},
computed: {
shouldUseAbsoluteTimeFormat() {
if (!useSyncConfigStore().mergedConfig.useAbsoluteTimeFormat) {
return false
}
return (
DateUtils.durationStrToMs(
useSyncConfigStore().mergedConfig.absoluteTimeFormatMinAge,
) <= this.relativeTimeMs
)
},
time12hFormat() {
return useSyncConfigStore().mergedConfig.absoluteTimeFormat12h === '12h'
},
browserLocale() {
return localeService.internalToBrowserLocale(this.$i18n.locale)
},
timeAsDate() {
return typeof this.time === 'string'
? new Date(Date.parse(this.time))
: this.time
},
localeDateString() {
return this.timeAsDate.toLocaleString(this.browserLocale)
},
relativeTimeString() {
const timeString = this.$i18n.t(
this.relativeTime.key,
[this.relativeTime.num],
this.relativeTime.num,
)
if (
typeof this.templateKey === 'string' &&
this.relativeTime.key !== 'time.now'
) {
return this.$i18n.t(this.templateKey, [timeString])
}
return timeString
},
absoluteTimeString() {
if (this.longFormat) {
return this.localeDateString
}
const now = new Date()
const formatter = (() => {
if (DateUtils.isSameDay(this.timeAsDate, now)) {
return new Intl.DateTimeFormat(this.browserLocale, {
minute: 'numeric',
hour: 'numeric',
hour12: this.time12hFormat,
})
} else if (DateUtils.isSameMonth(this.timeAsDate, now)) {
return new Intl.DateTimeFormat(this.browserLocale, {
month: 'short',
day: 'numeric',
hour12: this.time12hFormat,
})
} else if (DateUtils.isSameYear(this.timeAsDate, now)) {
return new Intl.DateTimeFormat(this.browserLocale, {
month: 'short',
day: 'numeric',
hour12: this.time12hFormat,
})
} else {
return new Intl.DateTimeFormat(this.browserLocale, {
year: 'numeric',
month: 'short',
hour12: this.time12hFormat,
})
}
})()
return formatter.format(this.timeAsDate)
},
relativeOrAbsoluteTimeString() {
return this.shouldUseAbsoluteTimeFormat
? this.absoluteTimeString
: this.relativeTimeString
},
},
watch: {
time(newVal, oldVal) {
if (oldVal !== newVal) {
clearTimeout(this.interval)
this.refreshRelativeTimeObject()
}
},
},
created() {
this.refreshRelativeTimeObject()
},
unmounted() {
clearTimeout(this.interval)
},
methods: {
refreshRelativeTimeObject() {
const nowThreshold =
typeof this.nowThreshold === 'number' ? this.nowThreshold : 1
this.relativeTimeMs = DateUtils.relativeTimeMs(this.time)
this.relativeTime = this.longFormat
? DateUtils.relativeTime(this.time, nowThreshold)
: DateUtils.relativeTimeShort(this.time, nowThreshold)
if (this.autoUpdate) {
this.interval = setTimeout(
this.refreshRelativeTimeObject,
1000 * this.autoUpdate,
)
}
},
},
}

View file

@ -7,132 +7,4 @@
</time>
</template>
<script>
import * as DateUtils from 'src/services/date_utils/date_utils.js'
import localeService from 'src/services/locale/locale.service.js'
export default {
name: 'Timeago',
props: ['time', 'autoUpdate', 'longFormat', 'nowThreshold', 'templateKey'],
data() {
return {
relativeTimeMs: 0,
relativeTime: { key: 'time.now', num: 0 },
interval: null,
}
},
computed: {
shouldUseAbsoluteTimeFormat() {
if (!this.$store.getters.mergedConfig.useAbsoluteTimeFormat) {
return false
}
return (
DateUtils.durationStrToMs(
this.$store.getters.mergedConfig.absoluteTimeFormatMinAge,
) <= this.relativeTimeMs
)
},
time12hFormat() {
return this.$store.getters.mergedConfig.absoluteTimeFormat12h === '12h'
},
browserLocale() {
return localeService.internalToBrowserLocale(this.$i18n.locale)
},
timeAsDate() {
return typeof this.time === 'string'
? new Date(Date.parse(this.time))
: this.time
},
localeDateString() {
return this.timeAsDate.toLocaleString(this.browserLocale)
},
relativeTimeString() {
const timeString = this.$i18n.t(
this.relativeTime.key,
[this.relativeTime.num],
this.relativeTime.num,
)
if (
typeof this.templateKey === 'string' &&
this.relativeTime.key !== 'time.now'
) {
return this.$i18n.t(this.templateKey, [timeString])
}
return timeString
},
absoluteTimeString() {
if (this.longFormat) {
return this.localeDateString
}
const now = new Date()
const formatter = (() => {
if (DateUtils.isSameDay(this.timeAsDate, now)) {
return new Intl.DateTimeFormat(this.browserLocale, {
minute: 'numeric',
hour: 'numeric',
hour12: this.time12hFormat,
})
} else if (DateUtils.isSameMonth(this.timeAsDate, now)) {
return new Intl.DateTimeFormat(this.browserLocale, {
month: 'short',
day: 'numeric',
hour12: this.time12hFormat,
})
} else if (DateUtils.isSameYear(this.timeAsDate, now)) {
return new Intl.DateTimeFormat(this.browserLocale, {
month: 'short',
day: 'numeric',
hour12: this.time12hFormat,
})
} else {
return new Intl.DateTimeFormat(this.browserLocale, {
year: 'numeric',
month: 'short',
hour12: this.time12hFormat,
})
}
})()
return formatter.format(this.timeAsDate)
},
relativeOrAbsoluteTimeString() {
return this.shouldUseAbsoluteTimeFormat
? this.absoluteTimeString
: this.relativeTimeString
},
},
watch: {
time(newVal, oldVal) {
if (oldVal !== newVal) {
clearTimeout(this.interval)
this.refreshRelativeTimeObject()
}
},
},
created() {
this.refreshRelativeTimeObject()
},
unmounted() {
clearTimeout(this.interval)
},
methods: {
refreshRelativeTimeObject() {
const nowThreshold =
typeof this.nowThreshold === 'number' ? this.nowThreshold : 1
this.relativeTimeMs = DateUtils.relativeTimeMs(this.time)
this.relativeTime = this.longFormat
? DateUtils.relativeTime(this.time, nowThreshold)
: DateUtils.relativeTimeShort(this.time, nowThreshold)
if (this.autoUpdate) {
this.interval = setTimeout(
this.refreshRelativeTimeObject,
1000 * this.autoUpdate,
)
}
},
},
}
</script>
<script src="./timeago.js" />

View file

@ -9,6 +9,7 @@ import Status from '../status/status.vue'
import TimelineMenu from '../timeline_menu/timeline_menu.vue'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import timelineFetcher from 'src/services/timeline_fetcher/timeline_fetcher.service.js'
@ -125,7 +126,7 @@ const Timeline = {
return this.timeline.visibleStatuses.slice(min, max).map((_) => _.id)
},
virtualScrollingEnabled() {
return this.$store.getters.mergedConfig.virtualScrolling
return useSyncConfigStore().mergedConfig.virtualScrolling
},
...mapState(useInterfaceStore, {
mobileLayout: (store) => store.layoutType === 'mobile',
@ -313,7 +314,7 @@ const Timeline = {
},
watch: {
newStatusCount(count) {
if (!this.$store.getters.mergedConfig.streaming) {
if (!useSyncConfigStore().mergedConfig.streaming) {
return
}
if (count > 0) {
@ -323,7 +324,9 @@ const Timeline = {
if (
top < 15 &&
!this.paused &&
!(this.unfocused && this.$store.getters.mergedConfig.pauseOnUnfocused)
!(
this.unfocused && useSyncConfigStore().mergedConfig.pauseOnUnfocused
)
) {
this.showNewStatuses()
} else {

View file

@ -1,7 +1,7 @@
import Modal from 'src/components/modal/modal.vue'
import { useInstanceStore } from 'src/stores/instance.js'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import pleromaTanFoxMask from 'src/assets/pleromatan_apology_fox_mask.png'
import pleromaTanMask from 'src/assets/pleromatan_apology_mask.png'
@ -41,9 +41,9 @@ const UpdateNotification = {
return (
!useInstanceStore().disableUpdateNotification &&
this.$store.state.users.currentUser &&
useServerSideStorageStore().flagStorage.updateCounter <
useSyncConfigStore().flagStorage.updateCounter <
CURRENT_UPDATE_COUNTER &&
!useServerSideStorageStore().prefsStorage.simple.dontShowUpdateNotifs
!useSyncConfigStore().prefsStorage.simple.dontShowUpdateNotifs
)
},
},
@ -53,22 +53,22 @@ const UpdateNotification = {
},
neverShowAgain() {
this.toggleShow()
useServerSideStorageStore().setFlag({
useSyncConfigStore().setFlag({
flag: 'updateCounter',
value: CURRENT_UPDATE_COUNTER,
})
useServerSideStorageStore().setPreference({
useSyncConfigStore().setPreference({
path: 'simple.dontShowUpdateNotifs',
value: true,
})
useServerSideStorageStore().pushServerSideStorage()
useSyncConfigStore().pushSyncConfig()
},
dismiss() {
useServerSideStorageStore().setFlag({
useSyncConfigStore().setFlag({
flag: 'updateCounter',
value: CURRENT_UPDATE_COUNTER,
})
useServerSideStorageStore().pushServerSideStorage()
useSyncConfigStore().pushSyncConfig()
},
},
mounted() {

View file

@ -27,6 +27,7 @@ import { useEmojiStore } from 'src/stores/emoji.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { usePostStatusStore } from 'src/stores/post_status'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { propsToNative } from 'src/services/attributes_helper/attributes_helper.service.js'
import localeService from 'src/services/locale/locale.service.js'
@ -223,12 +224,12 @@ export default {
userHighlightType: {
get() {
const data =
this.$store.getters.mergedConfig.highlight[this.user.screen_name]
useSyncConfigStore().mergedConfig.highlight[this.user.screen_name]
return (data && data.type) || 'disabled'
},
set(type) {
const data =
this.$store.getters.mergedConfig.highlight[this.user.screen_name]
useSyncConfigStore().mergedConfig.highlight[this.user.screen_name]
if (type !== 'disabled') {
this.$store.dispatch('setHighlight', {
user: this.user.screen_name,
@ -247,7 +248,7 @@ export default {
userHighlightColor: {
get() {
const data =
this.$store.getters.mergedConfig.highlight[this.user.screen_name]
useSyncConfigStore().mergedConfig.highlight[this.user.screen_name]
return data && data.color
},
set(color) {

View file

@ -293,7 +293,7 @@
</div>
</div>
<div
v-if="!editable && loggedIn && isOtherUser && (hasNote || !hideBio) && !mergedConfig.userCardHidePersonalMarks"
v-if="!editable && loggedIn && isOtherUser && (hasNote || !hideBio) && !userCardHidePersonalMarks"
class="personal-marks"
>
<UserNote
@ -357,7 +357,7 @@
<RichContent
v-if="!hideBio"
class="user-card-bio"
:class="{ '-justify-left': mergedConfig.userCardLeftJustify }"
:class="{ '-justify-left': userCardLeftJustify }"
:html="editable ? newBio.replace(/\n/g, '<br>') : user.description_html"
:emoji="editable ? emoji : user.emoji"
:handle-links="true"
@ -368,7 +368,7 @@
v-model="newBio"
enable-emoji-picker
class="user-card-bio"
:class="{ '-justify-left': mergedConfig.userCardLeftJustify }"
:class="{ '-justify-left': userCardLeftJustify }"
:suggest="emojiUserSuggestor"
>
<template #default="inputProps">
@ -505,11 +505,11 @@
class="user-extras"
>
<span
v-if="!editable && !mergedConfig.hideUserStats"
v-if="!editable && !hideUserStats"
class="user-stats"
>
<dl
v-if="!mergedConfig.hideUserStats && !hideBio"
v-if="!hideUserStats && !hideBio"
class="user-count"
>
<dd>{{ user.statuses_count }}</dd>

View file

@ -1,7 +1,10 @@
import { mapState } from 'pinia'
import { defineAsyncComponent } from 'vue'
import UserCard from '../user_card/user_card.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
const UserPopover = {
name: 'UserPopover',
props: ['userId', 'overlayCenters', 'disabled', 'overlayCentersSelector'],
@ -9,14 +12,11 @@ const UserPopover = {
UserCard,
Popover: defineAsyncComponent(() => import('../popover/popover.vue')),
},
computed: {
userPopoverAvatarAction() {
return this.$store.getters.mergedConfig.userPopoverAvatarAction
},
userPopoverOverlay() {
return this.$store.getters.mergedConfig.userPopoverOverlay
},
},
computed: mapState(useSyncConfigStore, {
userPopoverAvatarAction: (state) =>
state.mergedConfig.userPopoverAvatarAction,
userPopoverOverlay: (state) => state.mergedConfig.userPopoverOverlay,
}),
}
export default UserPopover

View file

@ -2,13 +2,15 @@ import Checkbox from 'src/components/checkbox/checkbox.vue'
import ConfirmModal from 'src/components/confirm_modal/confirm_modal.vue'
import Select from 'src/components/select/select.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { durationStrToMs } from 'src/services/date_utils/date_utils.js'
const UserTimedFilterModal = {
data() {
const action = this.isMute
? this.$store.getters.mergedConfig.onMuteDefaultAction
: this.$store.getters.mergedConfig.onBlockDefaultAction
? useSyncConfigStore().mergedConfig.onMuteDefaultAction
: useSyncConfigStore().mergedConfig.onBlockDefaultAction
const doAsk = action === 'ask'
const defaultValues = {}
@ -44,9 +46,9 @@ const UserTimedFilterModal = {
computed: {
shouldConfirm() {
if (this.isMute) {
return this.$store.getters.mergedConfig.onMuteDefaultAction === 'ask'
return useSyncConfigStore().mergedConfig.onMuteDefaultAction === 'ask'
} else {
return this.$store.getters.mergedConfig.onBlockDefaultAction === 'ask'
return useSyncConfigStore().mergedConfig.onBlockDefaultAction === 'ask'
}
},
expiryString() {

View file

@ -1,3 +1,5 @@
import { useSyncConfigStore } from 'src/stores/sync_config.js'
const VideoAttachment = {
props: ['attachment', 'controls'],
data() {
@ -9,10 +11,10 @@ const VideoAttachment = {
},
computed: {
loopVideo() {
if (this.$store.getters.mergedConfig.loopVideoSilentOnly) {
if (useSyncConfigStore().mergedConfig.loopVideoSilentOnly) {
return !this.hasAudio
}
return this.$store.getters.mergedConfig.loopVideo
return useSyncConfigStore().mergedConfig.loopVideo
},
},
methods: {

View file

@ -1,6 +1,8 @@
import apiService from '../../services/api/api.service.js'
import FollowCard from '../follow_card/follow_card.vue'
import { useInstanceStore } from 'src/stores/instance.js'
const WhoToFollow = {
components: {
FollowCard,

14
src/lib/language.js Normal file
View file

@ -0,0 +1,14 @@
import { useI18nStore } from 'src/stores/i18n.js'
export const piniaLanguagePlugin = ({ store, options }) => {
if (store.$id === 'sync_config') {
store.$onAction(({ name, args }) => {
if (name === 'setPreference') {
const { path, value } = args[0]
if (path === 'simple.interfaceLanguage') {
useI18nStore().setLanguage(value)
}
}
})
}
}

View file

@ -1,37 +1,96 @@
import { useInstanceStore } from 'src/stores/instance.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
export default (store) => {
export const piniaPushNotificationsPlugin = ({ store }) => {
if (
store.$id !== 'sync_config' &&
store.$id !== 'instance' &&
store.$id !== 'interface'
)
return
store.$onAction(({ name: actionName, args }) => {
if (
store.$id === 'interface' &&
actionName !== 'setNotificationPermission' &&
actionName !== 'setLoginStatus'
)
return
// Initial state
let vapidPublicKey = useInstanceStore().vapidPublicKey
let enabled = useSyncConfigStore().mergedConfig.webPushNotifications
let permissionGranted =
useInterfaceStore().notificationPermission === 'granted'
let permissionPresent =
useInterfaceStore().notificationPermission !== undefined
let user = !!window.vuex.state.users.currentUser
if (store.$id === 'instance') {
if (actionName === 'set' && args[0].path === 'vapidPublicKey') {
const { value } = args[0]
vapidPublicKey = value
}
}
if (!vapidPublicKey || !permissionPresent) {
return
}
if (store.$id === 'interface') {
if (actionName === 'setNotificationPermission') {
permissionGranted = args[0] === 'granted'
} else if (actionName === 'setLoginStatus') {
user = args[0]
} else {
return
}
} else if (store.$id === 'sync_config') {
if (
actionName === 'setPreference' &&
args[0].path === 'simple.webPushNotifications'
) {
const { value } = args[0]
enabled = value
} else {
return
}
}
if (permissionGranted && enabled && user) {
console.log('piniaReg')
return window.vuex.dispatch('registerPushNotifications')
} else {
console.log('piniaUnreg')
return window.vuex.dispatch('unregisterPushNotifications')
}
})
}
export const vuexPushNotificationsPlugin = (store) => {
store.subscribe((mutation, state) => {
// Initial state
const vapidPublicKey = useInstanceStore().vapidPublicKey
const webPushNotification = state.config.webPushNotifications
const permission = useInterfaceStore().notificationPermission === 'granted'
const enabled = useSyncConfigStore().mergedConfig.webPushNotifications
const permissionGranted =
useInterfaceStore().notificationPermission === 'granted'
const permissionPresent =
useInterfaceStore().notificationPermission !== undefined
const user = state.users.currentUser
const isUserMutation = mutation.type === 'setCurrentUser'
const isVapidMutation =
mutation.type === 'setInstanceOption' &&
mutation.payload.name === 'vapidPublicKey'
const isPermMutation =
mutation.type === 'setNotificationPermission' &&
mutation.payload === 'granted'
const isUserConfigMutation =
mutation.type === 'setOption' &&
mutation.payload.name === 'webPushNotifications'
const isVisibilityMutation =
mutation.type === 'setOption' &&
mutation.payload.name === 'notificationVisibility'
if (!permissionPresent || !vapidPublicKey) return
if (
isUserMutation ||
isVapidMutation ||
isPermMutation ||
isUserConfigMutation ||
isVisibilityMutation
mutation.type === 'setCurrentUser' ||
mutation.type === 'clearCurrentUser'
) {
if (user && vapidPublicKey && permission && webPushNotification) {
console.log(!!user, permissionGranted, enabled)
if (user && permissionGranted && enabled) {
console.log('vuexReg')
return store.dispatch('registerPushNotifications')
} else if (isUserConfigMutation && !webPushNotification) {
} else {
console.log('vuexUnreg')
return store.dispatch('unregisterPushNotifications')
}
}

29
src/lib/style.js Normal file
View file

@ -0,0 +1,29 @@
import { applyStyleConfig } from 'src/services/style_setter/style_setter.js'
const APPEARANCE_SETTINGS_KEYS = new Set(
[
'sidebarColumnWidth',
'contentColumnWidth',
'notifsColumnWidth',
'themeEditorMinWidth',
'textSize',
'navbarSize',
'panelHeaderSize',
'forcedRoundness',
'emojiSize',
'emojiReactionsScale',
].map((x) => 'simple.' + x),
)
export const piniaStylePlugin = ({ store, options }) => {
if (store.$id === 'sync_config') {
store.$onAction(({ name, args, after }) => {
if (name === 'setPreference') {
const { path } = args[0]
if (APPEARANCE_SETTINGS_KEYS.has(path)) {
after(() => applyStyleConfig(store.mergedConfig))
}
}
})
}
}

View file

@ -20,9 +20,15 @@ import messages from './i18n/messages.js'
import createPersistedState, {
piniaPersistPlugin,
} from './lib/persisted_state.js'
import pushNotifications from './lib/push_notifications_plugin.js'
import {
piniaPushNotificationsPlugin,
vuexPushNotificationsPlugin,
} from './lib/push_notifications_plugin.js'
import vuexModules from './modules/index.js'
import { piniaLanguagePlugin } from 'src/lib/language.js'
import { piniaStylePlugin } from 'src/lib/style.js'
const currentLocale = (window.navigator.language || 'en').split('-')[0]
const i18n = createI18n({
@ -35,7 +41,7 @@ const i18n = createI18n({
messages.setLanguage(i18n.global, currentLocale)
const persistedStateOptions = {
paths: ['serverSideStorage.cache', 'config', 'users.lastLoginName', 'oauth'],
paths: ['syncConfig.cache', 'config', 'users.lastLoginName', 'oauth'],
}
;(async () => {
@ -66,9 +72,12 @@ const persistedStateOptions = {
try {
let storageError
const plugins = [pushNotifications]
const plugins = [vuexPushNotificationsPlugin]
const pinia = createPinia()
pinia.use(piniaPersistPlugin())
pinia.use(piniaLanguagePlugin)
pinia.use(piniaStylePlugin)
pinia.use(piniaPushNotificationsPlugin)
try {
const persistedState = await createPersistedState(persistedStateOptions)

View file

@ -3,7 +3,7 @@ import { set } from 'lodash'
import messages from '../i18n/messages'
import localeService from '../services/locale/locale.service.js'
import { applyConfig } from '../services/style_setter/style_setter.js'
import { applyStyleConfig } from '../services/style_setter/style_setter.js'
import { defaultState, instanceDefaultConfig } from './default_config_state.js'
import { useEmojiStore } from 'src/stores/emoji.js'
@ -71,7 +71,7 @@ const config = {
mutations: {
setOptionTemporarily(state, { name, value }) {
set(state, name, value)
applyConfig(state)
applyStyleConfig(state)
},
setOption(state, { name, value }) {
set(state, name, value)
@ -162,7 +162,7 @@ const config = {
} else {
commit('setOption', { name, value })
if (APPEARANCE_SETTINGS_KEYS.has(name)) {
applyConfig(state)
applyStyleConfig(state)
}
if (name.startsWith('theme3hacks')) {
dispatch('applyTheme', { recompile: true })

View file

@ -1,9 +1,10 @@
const browserLocale = (window.navigator.language || 'en').split('-')[0]
const browserLocale = (navigator.language || 'en').split('-')[0]
/// Instance config entries provided by static config or pleroma api
/// Put settings here only if it does not make sense for a normal user
/// to override it.
export const staticOrApiConfigDefault = {
name: 'PleromaFE',
theme: 'pleroma-dark',
palette: null,
style: null,

View file

@ -10,7 +10,7 @@ import {
} from '../services/notification_utils/notification_utils.js'
import { useReportsStore } from 'src/stores/reports.js'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
const emptyNotifications = () => ({
desktopNotificationSilence: true,
@ -119,9 +119,7 @@ export const notifications = {
maybeShowNotification(
store,
Object.values(
useServerSideStorageStore().prefsStorage.simple.muteFilters,
),
Object.values(useSyncConfigStore().prefsStorage.simple.muteFilters),
notification,
)
} else if (notification.seen) {

View file

@ -26,7 +26,7 @@ import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface.js'
import { useOAuthStore } from 'src/stores/oauth.js'
import { useServerSideStorageStore } from 'src/stores/serverSideStorage'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import { declarations } from 'src/modules/config_declaration'
@ -682,7 +682,7 @@ const users = {
useInterfaceStore().setLastTimeline('public-timeline')
useInterfaceStore().setLayoutWidth(windowWidth())
useInterfaceStore().setLayoutHeight(windowHeight())
store.commit('clearServerSideStorage')
//useSyncConfigStore().clearSyncConfig()
})
},
loginUser(store, accessToken) {
@ -702,7 +702,7 @@ const users = {
user.domainMutes = []
commit('setCurrentUser', user)
useServerSideStorageStore().setServerSideStorage(user)
useSyncConfigStore().setSyncConfig(user)
commit('addNewUsers', [user])
useEmojiStore().fetchEmoji()
@ -723,17 +723,16 @@ const users = {
/*
// Reset wordfilter
Object.keys(
useServerSideStorageStore().prefsStorage.simple.muteFilters
useSyncConfigStore().prefsStorage.simple.muteFilters
).forEach(key => {
useServerSideStorageStore().unsetPreference({ path: 'simple.muteFilters.' + key, value: null })
useSyncConfigStore().unsetPreference({ path: 'simple.muteFilters.' + key, value: null })
})
// Reset flag to 0 to re-run migrations
useServerSideStorageStore().setFlag({ flag: 'configMigration', value: 0 })
useSyncConfigStore().setFlag({ flag: 'configMigration', value: 0 })
/**/
const { configMigration } =
useServerSideStorageStore().flagStorage
const { configMigration } = useSyncConfigStore().flagStorage
declarations
.filter((x) => {
return (
@ -744,12 +743,12 @@ const users = {
})
.toSorted((a, b) => a.configMigration - b.configMigration)
.forEach((value) => {
value.migration(useServerSideStorageStore(), store.rootState)
useServerSideStorageStore().setFlag({
value.migration(useSyncConfigStore(), store.rootState)
useSyncConfigStore().setFlag({
flag: 'configMigration',
value: value.migrationNum,
})
useServerSideStorageStore().pushServerSideStorage()
useSyncConfigStore().pushSyncConfig()
})
if (user.token) {

View file

@ -318,9 +318,7 @@ const updateProfileJSON = ({ credentials, params }) => {
credentials,
payload: params,
method: 'PATCH',
})
.then((data) => data.json())
.then((data) => parseUser(data))
}).then((data) => parseUser(data))
}
// Params needed:

View file

@ -255,7 +255,7 @@ const extractStyleConfig = ({
const defaultStyleConfig = extractStyleConfig(defaultState)
export const applyConfig = (input) => {
export const applyStyleConfig = (input) => {
const config = extractStyleConfig(input)
if (config === defaultStyleConfig) {

View file

@ -41,7 +41,7 @@ function subscribePush(registration, isEnabled, vapidPublicKey) {
function unsubscribePush(registration) {
return registration.pushManager.getSubscription().then((subscription) => {
if (subscription === null) {
return
return Promise.resolve('No subscription')
}
return subscription.unsubscribe()
})
@ -158,23 +158,23 @@ export function registerPushNotifications(
export function unregisterPushNotifications(token) {
if (isPushSupported()) {
Promise.all([
deleteSubscriptionFromBackEnd(token),
getOrCreateServiceWorker()
.then((registration) => {
return unsubscribePush(registration).then((result) => [
registration,
result,
])
})
.then(([, unsubResult]) => {
if (!unsubResult) {
console.warn("Push subscription cancellation wasn't successful")
}
}),
]).catch((e) =>
console.warn(`Failed to disable Web Push Notifications: ${e.message}`),
)
getOrCreateServiceWorker()
.then((registration) => {
return unsubscribePush(registration).then((result) => [
registration,
result,
])
})
.then(([, unsubResult]) => {
if (unsubResult === 'No subscription') return
if (!unsubResult) {
console.warn("Push subscription cancellation wasn't successful")
}
return deleteSubscriptionFromBackEnd(token)
})
.catch((e) => {
console.warn(`Failed to disable Web Push Notifications: ${e.message}`)
})
}
}

View file

@ -1,5 +1,14 @@
import Cookies from 'js-cookie'
import { defineStore } from 'pinia'
import { useEmojiStore } from 'src/stores/emoji.js'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import messages from 'src/i18n/messages'
import localeService from 'src/services/locale/locale.service.js'
const BACKEND_LANGUAGE_COOKIE_NAME = 'userLanguage'
export const useI18nStore = defineStore('i18n', {
state: () => ({
i18n: null,
@ -10,5 +19,16 @@ export const useI18nStore = defineStore('i18n', {
i18n: newI18n.global,
})
},
setLanguage(originalValue) {
const value =
originalValue || useSyncConfigStore().mergedConfig.interfaceLanguage
messages.setLanguage(this.i18n, value)
useEmojiStore().loadUnicodeEmojiData(value)
Cookies.set(
BACKEND_LANGUAGE_COOKIE_NAME,
localeService.internalToBackendLocaleMulti(value),
)
},
},
})

View file

@ -17,7 +17,11 @@ import { toRaw } from 'vue'
import { CURRENT_UPDATE_COUNTER } from 'src/components/update_notification/update_notification.js'
export const VERSION = 1
import { useInstanceStore } from 'src/stores/instance'
import { defaultState as configDefaultState } from 'src/modules/default_config_state'
export const VERSION = 2
export const NEW_USER_DATE = new Date('2022-08-04') // date of writing this, basically
export const COMMAND_TRIM_FLAGS = 1000
@ -41,6 +45,7 @@ export const defaultState = {
dontShowUpdateNotifs: false,
collapseNav: false,
muteFilters: {},
...configDefaultState,
},
collections: {
pinnedStatusActions: ['reply', 'retweet', 'favorite', 'emoji'],
@ -128,13 +133,13 @@ export const _getRecentData = (cache, live, isTest) => {
live._version === cache._version
) {
console.debug(
'Same version/timestamp on both source, source of truth irrelevant',
'Same version/timestamp on both sources, source of truth irrelevant',
)
result.recent = cache
result.stale = live
} else {
console.debug(
'Different timestamp, figuring out which one is more recent',
'Different timestamp or version, figuring out which one is more recent',
)
if (live._timestamp < cache._timestamp) {
result.recent = cache
@ -208,7 +213,7 @@ const _mergeJournal = (...journals) => {
// side effect
journal.sort((a, b) => (a.timestamp > b.timestamp ? 1 : -1))
if (path.startsWith('collections')) {
if (path.startsWith('collections') || path.startsWith('objectCollection')) {
const lastRemoveIndex = findLastIndex(
journal,
({ operation }) => operation === 'removeFromCollection',
@ -229,6 +234,7 @@ const _mergeJournal = (...journals) => {
return false
}
if (a.operation === 'addToCollection') {
// TODO check how objectCollections behaves here
return a.args[0] === b.args[0]
}
return false
@ -368,21 +374,21 @@ export const _resetFlags = (
return result
}
export const _doMigrations = (cache) => {
if (!cache) return cache
export const _doMigrations = (cache, live) => {
const data = cache ?? live
if (cache._version < VERSION) {
if (data._version < VERSION) {
console.debug(
'Local cached data has older version, seeing if there any migrations that can be applied',
'Data has older version, seeing if there any migrations that can be applied',
)
// no migrations right now since we only have one version
console.debug('No migrations found')
}
if (cache._version > VERSION) {
if (data._version > VERSION) {
console.debug(
'Local cached data has newer version, seeing if there any reverse migrations that can be applied',
'Data has newer version, seeing if there any reverse migrations that can be applied',
)
// no reverse migrations right now but we leave a possibility of loading a hotpatch if need be
@ -391,9 +397,9 @@ export const _doMigrations = (cache) => {
console.debug('Found hotpatch migration, applying')
return window._PLEROMA_HOTPATCH.reverseMigrations.call(
{},
'serverSideStorage',
{ from: cache._version, to: VERSION },
cache,
'syncConfigStore',
{ from: data._version, to: VERSION },
data,
)
}
}
@ -402,7 +408,7 @@ export const _doMigrations = (cache) => {
return cache
}
export const useServerSideStorageStore = defineStore('serverSideStorage', {
export const useSyncConfigStore = defineStore('sync_config', {
state() {
return cloneDeep(defaultState)
},
@ -510,19 +516,40 @@ export const useServerSideStorageStore = defineStore('serverSideStorage', {
`tried to edit internal (starts with _) field '${path}', ignoring.`,
)
}
const collection = new Set(get(this.prefsStorage, path))
collection.delete(value)
set(this.prefsStorage, path, [...collection])
this.prefsStorage._journal = [
...this.prefsStorage._journal,
{
operation: 'removeFromCollection',
path,
args: [value],
timestamp: Date.now(),
},
]
this.dirty = true
const { _key } = value
if (path.startsWith('collection')) {
const collection = new Set(get(this.prefsStorage, path))
collection.delete(value)
set(this.prefsStorage, path, [...collection])
this.prefsStorage._journal = [
...this.prefsStorage._journal,
{
operation: 'removeFromCollection',
path,
args: [value],
timestamp: Date.now(),
},
]
this.dirty = true
} else if (path.startsWith('objectCollection')) {
const collection = new Set(get(this.prefsStorage, path + '.index'))
collection.delete(_key)
set(this.prefsStorage, path + '.index', [...collection])
const data = get(this.prefsStorage, path + '.data')
delete data[_key]
this.prefsStorage._journal = [
...this.prefsStorage._journal,
{
operation: 'removeFromCollection',
path,
args: [{ _key }],
timestamp: Date.now(),
},
]
}
},
reorderCollectionPreference({ path, value, movement }) {
if (path.startsWith('_')) {
@ -554,24 +581,23 @@ export const useServerSideStorageStore = defineStore('serverSideStorage', {
username,
)
},
clearServerSideStorage() {
clearSyncConfig() {
const blankState = { ...cloneDeep(defaultState) }
Object.keys(this).forEach((k) => {
this[k] = blankState[k]
})
},
setServerSideStorage(userData) {
setSyncConfig(userData) {
const live = userData.storage
this.raw = live
let cache = this.cache
if (cache && cache._user !== userData.fqn) {
if (cache?._user !== userData.fqn) {
console.warn(
'Cache belongs to another user! reinitializing local cache!',
)
cache = null
}
cache = _doMigrations(cache)
console.log(cache, live)
let { recent, stale, needUpload } = _getRecentData(cache, live)
@ -589,6 +615,9 @@ export const useServerSideStorageStore = defineStore('serverSideStorage', {
})
}
recent = recent && _doMigrations(recent)
stale = stale && _doMigrations(stale)
if (!needUpload && recent && stale) {
console.debug('Checking if data needs merging...')
// discarding timestamps and versions
@ -627,7 +656,7 @@ export const useServerSideStorageStore = defineStore('serverSideStorage', {
this.flagStorage = this.cache.flagStorage
this.prefsStorage = this.cache.prefsStorage
},
pushServerSideStorage({ force = false } = {}) {
pushSyncConfig({ force = false } = {}) {
const needPush = this.dirty || force
if (!needPush) return
this.updateCache({ username: window.vuex.state.users.currentUser.fqn })
@ -635,9 +664,26 @@ export const useServerSideStorageStore = defineStore('serverSideStorage', {
window.vuex.state.api.backendInteractor
.updateProfileJSON({ params })
.then((user) => {
this.setServerSideStorage(user)
this.setSyncConfig(user)
this.dirty = false
})
},
},
getters: {
mergedConfig: (state) => {
const instancePrefs = useInstanceStore().prefsStorage
const result = Object.fromEntries(
Object.entries(state.prefsStorage.simple).map(([k, v]) => [
k,
v ?? instancePrefs[k],
]),
)
return result
},
},
persist: {
afterLoad(state) {
return state
},
},
})

View file

@ -39,7 +39,7 @@ const setSettings = async () => {
const locale = vuexState.config.interfaceLanguage || 'en'
i18n.locale = locale
const notificationsNativeArray = Object.entries(
vuexState.config.notificationNative,
vuexState.config.notificationNative || {},
)
state.webPushAlwaysShowNotifications =
vuexState.config.webPushAlwaysShowNotifications

View file

@ -7,18 +7,13 @@ createTestingPinia()
import EmojiInput from 'src/components/emoji_input/emoji_input.vue'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
const generateInput = (value, padEmoji = true) => {
const wrapper = shallowMount(EmojiInput, {
global: {
renderStubDefaultSlot: true,
mocks: {
$store: {
getters: {
mergedConfig: {
padEmoji,
},
},
},
$t: (msg) => msg,
},
stubs: {
@ -49,6 +44,12 @@ const generateInput = (value, padEmoji = true) => {
}
describe('EmojiInput', () => {
beforeEach(() => {
const store = useSyncConfigStore(createTestingPinia())
store.mergedConfig = {
padEmoji: true,
}
})
describe('insertion mechanism', () => {
it('inserts string at the end with trailing space', () => {
const initialString = 'Testing'
@ -112,6 +113,10 @@ describe('EmojiInput', () => {
it('inserts string without any padding if padEmoji setting is set to false', () => {
const initialString = 'Eat some spam!'
const wrapper = generateInput(initialString, false)
const store = useSyncConfigStore(createTestingPinia())
store.mergedConfig = {
padEmoji: false,
}
const input = wrapper.find('input')
input.setValue(initialString)
wrapper.setData({ caret: initialString.length, keepOpen: false })
@ -147,6 +152,10 @@ describe('EmojiInput', () => {
it('correctly sets caret after insertion if padEmoji setting is set to false', async () => {
const initialString = '1234'
const wrapper = generateInput(initialString, false)
const store = useSyncConfigStore(createTestingPinia())
store.mergedConfig = {
padEmoji: false,
}
const input = wrapper.find('input')
input.setValue(initialString)
wrapper.setData({ caret: initialString.length })

View file

@ -1,6 +1,21 @@
import { createTestingPinia } from '@pinia/testing'
import { useSyncConfigStore } from 'src/stores/sync_config.js'
import * as NotificationUtils from 'src/services/notification_utils/notification_utils.js'
describe('NotificationUtils', () => {
beforeEach(() => {
const store = useSyncConfigStore(createTestingPinia())
store.mergedConfig = {
notificationVisibility: {
likes: true,
repeats: true,
mentions: false,
},
}
})
describe('filteredNotificationsFromStore', () => {
it('should return sorted notifications with configured types', () => {
const store = {
@ -26,13 +41,7 @@ describe('NotificationUtils', () => {
},
},
getters: {
mergedConfig: {
notificationVisibility: {
likes: true,
repeats: true,
mentions: false,
},
},
mergedConfig: {},
},
}
const expected = [

View file

@ -12,25 +12,25 @@ import {
COMMAND_TRIM_FLAGS_AND_RESET,
defaultState,
newUserFlags,
useServerSideStorageStore,
useSyncConfigStore,
VERSION,
} from 'src/stores/serverSideStorage.js'
} from 'src/stores/sync_config.js'
describe('The serverSideStorage module', () => {
describe('The SyncConfig module', () => {
beforeEach(() => {
setActivePinia(createPinia())
})
describe('mutations', () => {
describe('setServerSideStorage', () => {
describe('setSyncConfig', () => {
const user = {
created_at: new Date('1999-02-09'),
storage: {},
}
it('should initialize storage if none present', () => {
const store = useServerSideStorageStore()
store.setServerSideStorage(store, user)
const store = useSyncConfigStore()
store.setSyncConfig({ ...user })
expect(store.cache._version).to.eql(VERSION)
expect(store.cache._timestamp).to.be.a('number')
expect(store.cache.flagStorage).to.eql(defaultState.flagStorage)
@ -38,8 +38,8 @@ describe('The serverSideStorage module', () => {
})
it('should initialize storage with proper flags for new users if none present', () => {
const store = useServerSideStorageStore()
store.setServerSideStorage({ ...user, created_at: new Date() })
const store = useSyncConfigStore()
store.setSyncConfig({ ...user, created_at: new Date() })
expect(store.cache._version).to.eql(VERSION)
expect(store.cache._timestamp).to.be.a('number')
expect(store.cache.flagStorage).to.eql(newUserFlags)
@ -47,14 +47,14 @@ describe('The serverSideStorage module', () => {
})
it('should merge flags even if remote timestamp is older', () => {
const store = useServerSideStorageStore()
const store = useSyncConfigStore()
store.cache = {
_timestamp: Date.now(),
_version: VERSION,
...cloneDeep(defaultState),
}
store.setServerSideStorage({
store.setSyncConfig({
...user,
storage: {
_timestamp: 123,
@ -76,10 +76,10 @@ describe('The serverSideStorage module', () => {
})
it('should reset local timestamp to remote if contents are the same', () => {
const store = useServerSideStorageStore()
const store = useSyncConfigStore()
store.cache = null
store.setServerSideStorage({
store.setSyncConfig({
...user,
storage: {
_timestamp: 123,
@ -95,9 +95,9 @@ describe('The serverSideStorage module', () => {
expect(store.cache.flagStorage.updateCounter).to.eql(999)
})
it('should remote version if local missing', () => {
const store = useServerSideStorageStore()
store.setServerSideStorage(store, user)
it('should use remote version if local missing', () => {
const store = useSyncConfigStore()
store.setSyncConfig(store, user)
expect(store.cache._version).to.eql(VERSION)
expect(store.cache._timestamp).to.be.a('number')
expect(store.cache.flagStorage).to.eql(defaultState.flagStorage)
@ -105,7 +105,7 @@ describe('The serverSideStorage module', () => {
})
describe('setPreference', () => {
it('should set preference and update journal log accordingly', () => {
const store = useServerSideStorageStore()
const store = useSyncConfigStore()
store.setPreference({ path: 'simple.testing', value: 1 })
expect(store.prefsStorage.simple.testing).to.eql(1)
expect(store.prefsStorage._journal.length).to.eql(1)
@ -119,18 +119,34 @@ describe('The serverSideStorage module', () => {
})
it('should keep journal to a minimum', () => {
const store = useServerSideStorageStore()
const store = useSyncConfigStore()
store.setPreference({ path: 'simple.testing', value: 1 })
store.setPreference({ path: 'simple.testing', value: 2 })
store.addCollectionPreference({ path: 'collections.testing', value: 2 })
store.addCollectionPreference({
path: 'objectCollections.testing',
value: { _key: 'a', foo: 1 },
})
expect(store.prefsStorage.objectCollections.testing).to.eql({
data: { a: { _key: 'a', foo: 1 } },
index: ['a'],
})
store.removeCollectionPreference({
path: 'collections.testing',
value: 2,
})
store.removeCollectionPreference({
path: 'objectCollections.testing',
value: { _key: 'a' },
})
store.updateCache({ username: 'test' })
expect(store.prefsStorage.simple.testing).to.eql(2)
expect(store.prefsStorage.collections.testing).to.eql([])
expect(store.prefsStorage._journal.length).to.eql(2)
expect(store.prefsStorage.objectCollections.testing).to.eql({
data: {},
index: [],
})
expect(store.prefsStorage._journal.length).to.eql(3)
expect(store.prefsStorage._journal[0]).to.eql({
path: 'simple.testing',
operation: 'set',
@ -145,22 +161,41 @@ describe('The serverSideStorage module', () => {
// should have A timestamp, we don't really care what it is
timestamp: store.prefsStorage._journal[1].timestamp,
})
expect(store.prefsStorage._journal[2]).to.eql({
path: 'objectCollections.testing',
operation: 'removeFromCollection',
args: [{ _key: 'a' }],
// should have A timestamp, we don't really care what it is
timestamp: store.prefsStorage._journal[2].timestamp,
})
})
it('should remove duplicate entries from journal', () => {
const store = useServerSideStorageStore()
const store = useSyncConfigStore()
store.setPreference({ path: 'simple.testing', value: 1 })
store.setPreference({ path: 'simple.testing', value: 1 })
store.addCollectionPreference({ path: 'collections.testing', value: 2 })
store.addCollectionPreference({ path: 'collections.testing', value: 2 })
store.addCollectionPreference({
path: 'objectCollections.testing',
value: { _key: 'a', foo: 1 },
})
store.addCollectionPreference({
path: 'objectCollections.testing',
value: { _key: 'a', foo: 1 },
})
store.updateCache({ username: 'test' })
expect(store.prefsStorage.simple.testing).to.eql(1)
expect(store.prefsStorage.collections.testing).to.eql([2])
expect(store.prefsStorage._journal.length).to.eql(2)
expect(store.prefsStorage.objectCollections.testing).to.eql({
data: { a: { _key: 'a', foo: 1 } },
index: ['a'],
})
expect(store.prefsStorage._journal.length).to.eql(4)
})
it('should remove depth = 3 set/unset entries from journal', () => {
const store = useServerSideStorageStore()
const store = useSyncConfigStore()
store.setPreference({ path: 'simple.object.foo', value: 1 })
store.unsetPreference({ path: 'simple.object.foo' })
store.updateCache(store, { username: 'test' })
@ -169,7 +204,7 @@ describe('The serverSideStorage module', () => {
})
it('should not allow unsetting depth <= 2', () => {
const store = useServerSideStorageStore()
const store = useSyncConfigStore()
store.setPreference({ path: 'simple.object.foo', value: 1 })
expect(() => store.unsetPreference({ path: 'simple' })).to.throw()
expect(() =>
@ -178,7 +213,7 @@ describe('The serverSideStorage module', () => {
})
it('should not allow (un)setting depth > 3', () => {
const store = useServerSideStorageStore()
const store = useSyncConfigStore()
store.setPreference({ path: 'simple.object', value: {} })
expect(() =>
store.setPreference({ path: 'simple.object.lv3', value: 1 }),