Compare commits

...
Sign in to create a new pull request.

360 commits

Author SHA1 Message Date
KMY
91e252259d Fix lint 2025-06-12 10:37:20 +09:00
KMY
f3c3ea42c2 Merge remote-tracking branch 'parent/main' into kbtopic-remove-quote 2025-06-12 10:17:21 +09:00
Echo
3aed93711c
Make React Spring respect animation preferences (#35018) 2025-06-11 16:51:55 +00:00
Eugen Rochko
f53bb4cd7d
Add "More" to the sidebar menu with links to mutes, blocks, and so on (#34987) 2025-06-11 16:12:04 +00:00
diondiondion
9896bed85f
fix: Fix direction of media gallery arrows (#35014) 2025-06-11 15:17:14 +00:00
diondiondion
2c828748a3
fix: Fix cramped layout of follower recommendations on small viewports (#34967) 2025-06-11 15:15:12 +00:00
David Roetzel
1623d54ec0
Start local prometheus_exporter server only in puma/sidekiq startup (#35005) 2025-06-11 13:37:59 +00:00
Claire
722fb1ff55
Fix quoted posts appearing between text and media (#35011) 2025-06-11 13:17:42 +00:00
Claire
933ee420c3
Remove some unused CSS classes (#35012) 2025-06-11 13:17:07 +00:00
renovate[bot]
0cdf11d6ad
fix(deps): update dependency postcss-preset-env to v10.2.3 (#35009)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-11 12:12:53 +00:00
Eugen Rochko
a13b33d851
Change navigation layout on small screens in web UI (#34910) 2025-06-11 11:55:43 +00:00
Echo
8cf246e4d3
Prevent two composers from being shown (#35006) 2025-06-11 11:12:39 +00:00
Matt Jankowski
629bb74451
Replace selenium-webdriver with playwright (#34867) 2025-06-10 16:33:46 +00:00
renovate[bot]
b8cc9b3290
fix(deps): update dependency postcss-preset-env to v10.2.2 (#34998)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-10 14:12:56 +00:00
renovate[bot]
2c085ea044
fix(deps): update dependency core-js to v3.43.0 (#34999)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-10 14:12:53 +00:00
renovate[bot]
bb89a64af0
chore(deps): update dependency http to '~> 5.3.0' (#34994)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-10 14:12:44 +00:00
Echo
c543e823ab
Ensure featured carousel respects tags (#34995) 2025-06-10 13:28:41 +00:00
Claire
7a7e0ba4cd
Add basic support for remote attachments with multiple media types (#34996) 2025-06-10 13:26:29 +00:00
Claire
c727701839
Fix crash in /about when server returns cached rules without translations attribute (#34997) 2025-06-10 13:25:24 +00:00
Eugen Rochko
1824b1fd29
Fix broken colors in some themed SVGs in web UI (#34988) 2025-06-10 08:36:42 +00:00
renovate[bot]
1bf8a642f0
fix(deps): update dependency sass to v1.89.2 (#34993)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-10 08:36:27 +00:00
Matt Jankowski
dc2cfd50a0
Fix Style/OptionalBooleanParameter cop (#34968) 2025-06-10 08:17:35 +00:00
Eugen Rochko
a2a6117143
Fix wrong dimensions on blurhash previews of news articles in web UI (#34990) 2025-06-10 08:11:46 +00:00
renovate[bot]
24803db2bc
fix(deps): update dependency @vitejs/plugin-react to v4.5.2 (#34992)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-10 08:11:21 +00:00
renovate[bot]
90183b6c27
chore(deps): update dependency rubocop to v1.76.1 (#34991)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-10 07:55:27 +00:00
github-actions[bot]
c3022fe10f
New Crowdin Translations (automated) (#34973)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-06-10 07:52:52 +00:00
Eugen Rochko
f3d60a4a6f
Fix wrong styles on action bar in media modal in web UI (#34989) 2025-06-10 07:42:29 +00:00
renovate[bot]
1dd8a99d9f
fix(deps): update dependency use-debounce to v10.0.5 (#34982)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-10 07:38:19 +00:00
renovate[bot]
66a42c11ba
fix(deps): update dependency rollup-plugin-visualizer to v6.0.3 (#34974)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-10 07:38:00 +00:00
renovate[bot]
132f32dd70
chore(deps): update dependency libvips to v8.17.0 (#34956)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-10 07:37:16 +00:00
Claire
e557769a3c
Remove broken link to /start/share in welcome e-mail (#34962) 2025-06-08 13:58:53 +00:00
Matt Jankowski
d887790e86
Update SafeReblogInsert concern to match Rails 8 method (#34966) 2025-06-06 15:25:09 +00:00
Claire
d0c6f30378
Add fasp queue to sidekiq queue system check (#34965) 2025-06-06 15:23:16 +00:00
Claire
ba75ba3adc
Change github workflow for chromatic to only run on official Mastodon repository (#34963) 2025-06-06 12:57:41 +00:00
diondiondion
c92e21813e
fix: Fix indentation of quote posts in threads (#34961) 2025-06-06 12:37:56 +00:00
PGray
076005eae2
fix: update search column input on param change (#34951) 2025-06-06 12:25:38 +00:00
Renaud Chaput
b10fde673d
Update rack to 3.1.16 (#34959) 2025-06-06 10:15:55 +00:00
Claire
68810643d8
Rewrite AccountNote as Typescript functional component (#34925)
Co-authored-by: diondiondion <mail@diondiondion.com>
2025-06-06 09:59:26 +00:00
diondiondion
f2cfa4f482
feat: Add Storybook for component documentation, testing, and development (#34907)
Co-authored-by: Echo <ChaosExAnima@users.noreply.github.com>
Co-authored-by: Renaud Chaput <renchap@gmail.com>
2025-06-06 09:27:29 +00:00
Claire
989ca63b59
Remove inbound_quotes feature flag (#34958) 2025-06-06 08:25:59 +00:00
Matt Jankowski
f2cdbefa3c
Align versions in templates to current/plausible values (#34952) 2025-06-06 07:42:57 +00:00
Claire
86627624f1
Fix quote post streaming edge cases (#34957) 2025-06-06 07:32:24 +00:00
github-actions[bot]
c09f9a93f1
New Crowdin Translations (automated) (#34953)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-06-06 07:15:31 +00:00
renovate[bot]
963f4977d6
fix(deps): update dependency postcss-preset-env to v10.2.1 (#34947)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-06 06:29:40 +00:00
renovate[bot]
5fde019e39
chore(deps): update dependency ruby-vips to v2.2.4 (#34949)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-06 06:29:19 +00:00
Claire
520974e052
Add ability to filter quote posts in home timeline (#34946) 2025-06-05 15:36:51 +00:00
Claire
3d474807bf
Change “legacy” non-fast-tracked quote posts to not be displayed as such (#34945) 2025-06-05 13:53:57 +00:00
renovate[bot]
09208eafa4
chore(deps): update yarn to v4.9.2 (#34916)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-05 13:37:43 +00:00
renovate[bot]
25c4574480
chore(deps): update dependency opentelemetry-instrumentation-faraday to '~> 0.27.0' (#34917)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-05 13:37:37 +00:00
Matt Jankowski
e2c5a2abaa
Fix Style/FetchEnvVar cop in repo.rake (#34903)
Co-authored-by: Claire <claire.github-309c@sitedethib.com>
2025-06-05 13:37:33 +00:00
renovate[bot]
a80f77a996
fix(deps): update dependency pino-http to v10.5.0 (#34920)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-05 13:36:22 +00:00
Matt Jankowski
1297ad759e
Update rubocop to version 1.76.0 (#34926) 2025-06-05 12:09:05 +00:00
Echo
1fdcaaebbb
Add a way to easily unpin profiles from the featured account area (#34931) 2025-06-05 10:23:01 +00:00
Claire
375add0c83
Fix account note textarea being interactable before the relationship gets fetched (#34932) 2025-06-05 08:49:26 +00:00
renovate[bot]
a4bc438010
chore(deps): update dependency annotaterb to v4.15.0 (#34870)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-05 07:47:34 +00:00
Matt Jankowski
1d152d2181
Replace local vars with let in JS-enabled system specs (#34905) 2025-06-05 07:08:52 +00:00
github-actions[bot]
250c3b0c1f
New Crowdin Translations (automated) (#34939)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-06-05 07:05:25 +00:00
diondiondion
1dafd8c9dd
fix: Fix broken audio player layout in Safari, #34930 (#34933) 2025-06-04 15:34:13 +00:00
diondiondion
6637ecb460
fix: Fix Safari volume bug, #34797 (#34929) 2025-06-04 14:35:29 +00:00
Echo
e9f197740d
Ensure carousel slides don't overflow (#34927) 2025-06-04 14:29:34 +00:00
Claire
12c0e58d9a
Fix mastodon-streaming container image builds on 4.4 (#34921) 2025-06-04 09:36:15 +00:00
Claire
f7c19226cf
Bump version to v4.4.0-beta.1 (#34912) 2025-06-04 08:47:18 +00:00
diondiondion
b64ad77e21
fix: Fix unauthenticated familiar followers request, #34911 (#34914) 2025-06-04 08:25:10 +00:00
renovate[bot]
37bf59f76a
fix(deps): update dependency @vitejs/plugin-react to v4.5.1 (#34898)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-04 07:41:52 +00:00
Claire
129e72b914
Revert "Add telemetry for status / bio formatting (#32677)" (#34906) 2025-06-03 15:06:32 +00:00
Matt Jankowski
6d12831686
Fix Rails/OutputSafety cop from rubocop todo via inline disable (#34893) 2025-06-03 08:00:50 +00:00
github-actions[bot]
efe8def0c6
New Crowdin Translations (automated) (#34897)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-06-03 07:57:07 +00:00
Claire
8224178e8c
Revert "Remove cookie rotator (#32289)" (#34892) 2025-06-02 13:51:27 +00:00
Claire
d4bbe8b719
Fix blocked accounts not being automatically removed from trending statuses (#34891) 2025-06-02 13:38:47 +00:00
Eugen Rochko
c77158c8b7
Fix nested buttons in search popout in web UI (#34871) 2025-06-02 12:21:31 +00:00
David Roetzel
9c80b16401
Accept HTTP Message Signatures (RFC9421) (#34814) 2025-06-02 09:27:08 +00:00
github-actions[bot]
eb42425427
New Crowdin Translations (automated) (#34874)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-06-02 08:24:52 +00:00
Claire
00b56932de
Fix handling of featured tag removal (#34887) 2025-06-02 08:09:30 +00:00
Eugen Rochko
d47199dd4b
Fix not being able to scroll dropdown on touch devices in web UI (#34873) 2025-06-02 08:07:42 +00:00
renovate[bot]
0182fc389e
fix(deps): update dependency sass to v1.89.1 (#34875)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-02 07:49:37 +00:00
renovate[bot]
7036d5ad25
chore(deps): update dependency csv to v3.3.5 (#34881)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-02 07:49:11 +00:00
Lukas Martini
11481df4dc
Fix sidekiq health check in docker-compose for sidekiq 7 (#34879) 2025-06-02 07:48:37 +00:00
Matt Jankowski
0d5123199f
Fix Style/FormatStringToken cop (#34861) 2025-06-02 07:37:33 +00:00
renovate[bot]
1b11bb23d7
chore(deps): update definitelytyped types (non-major) (#34884)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-02 07:37:15 +00:00
renovate[bot]
d051366308
chore(deps): update dependency linzer to v0.7.3 (#34885)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-02 07:09:25 +00:00
Matt Jankowski
7f4ec7d9cf
Include matrix values in upload artifact names (#34876) 2025-05-31 15:52:28 +00:00
Claire
32b521b7f4
Fix multiple issues in quoted posts hydration (#34864) 2025-05-31 15:20:31 +00:00
Eugen Rochko
44d71d59ef
Add icon to header of pinned posts carousel in web UI (#34869) 2025-05-30 22:24:34 +00:00
diondiondion
1cc853059f
refactor(Pinned posts carousel): Don't animate initial resize (#34868) 2025-05-30 18:06:41 +00:00
Matt Jankowski
7efe20337c
Fix Style/FetchEnvVar cop in omniauth config (#34862) 2025-05-30 15:32:47 +00:00
diondiondion
54ad57ea95
fix: Fix autoplay not working properly in AudioModal, #34841 (#34865) 2025-05-30 15:26:08 +00:00
Claire
064d333620
Fix inconsistent filtering of silenced accounts for other silenced accounts (#34863) 2025-05-30 13:20:51 +00:00
Claire
4b39bced3e
Increase capybara default timeout to reduce test flakiness (#34859) 2025-05-30 13:13:24 +00:00
Nicholas La Roux
0789ec93f8
Make account header profile pic exactly 2x post profile pic (#34807) 2025-05-30 12:33:30 +00:00
diondiondion
975db93e3f
feat: Add relationship info to hover card (#34792) 2025-05-30 12:32:19 +00:00
Matt Jankowski
c025824f98
Use config_for for cache buster values (#34851) 2025-05-30 11:54:25 +00:00
Echo
9860046b04
Fix pinned carousel scroll on mobile (#34858) 2025-05-30 09:08:09 +00:00
Claire
71a4a92dda
Fix featured posts and familiar followers showing up on hidden accounts (#34855) 2025-05-30 08:33:52 +00:00
Matt Jankowski
426ee069b5
Update fabrication to version 3.0.0 (#34850) 2025-05-30 08:30:42 +00:00
Matt Jankowski
7fc10bc7b0
Update rack-cors to version 3.0.0 (#34849) 2025-05-30 08:29:25 +00:00
github-actions[bot]
4130d9659c
New Crowdin Translations (automated) (#34847)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-05-30 07:34:17 +00:00
renovate[bot]
208dbb8821
chore(deps): update dependency oj to v3.16.11 (#34853)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-30 07:34:04 +00:00
Matt Jankowski
3c09fd3f89
Fix Style/FetchEnvVar cop in devise config (#34846) 2025-05-30 07:00:37 +00:00
Matt Jankowski
f7a3dd0e38
Use config_for for VAPID key storage (#34845) 2025-05-30 07:00:33 +00:00
Matt Jankowski
a1c260696f
Fix Style/FetchEnvVar cop in production env config (#34844) 2025-05-30 07:00:30 +00:00
KMY
ebdb80168e Fix lint 2025-05-29 13:02:56 +09:00
KMY
c538c23ef7 Merge remote-tracking branch 'parent/main' into kbtopic-remove-quote 2025-05-29 12:52:49 +09:00
KMY
b8239dc9b1 Fix lint and setup script 2025-05-29 10:40:42 +09:00
KMY
96bc94160d Add: 引用リンク挿入メニュー 2025-05-29 10:25:15 +09:00
KMY
7ee568f2c4 Fix lint 2025-05-29 08:52:15 +09:00
KMY
b6c12c6d1f Fix: ドラッグに関する問題 2025-05-29 08:41:11 +09:00
renovate[bot]
ca41a95872
chore(deps): update dependency rubocop to v1.75.8 (#34843)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-28 15:46:21 +00:00
renovate[bot]
6e16cac09f
chore(deps): update dependency ox to v2.14.23 (#34835)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-28 14:53:42 +00:00
Matt Jankowski
38e0a360ca
Add coverage for "default" stylesheet theme helper path (#34732) 2025-05-28 13:33:07 +00:00
David Roetzel
b195956ecb
Encapsulate redis key usage (#34840) 2025-05-28 12:34:37 +00:00
Emelia Smith
a73ade526a
Assert usage of client credentials for account registration (#34828) 2025-05-28 12:09:32 +00:00
Echo
6ffa262546
Update ESLint to not try to resolve virtual modules (#34837) 2025-05-28 10:04:52 +00:00
Darius Kazemi
991796172a
Fix NoMethodError in edge case of emoji cache handling (#34749)
Co-authored-by: Claire <claire.github-309c@sitedethib.com>
2025-05-28 09:39:55 +00:00
Matt Jankowski
71d46e26b2
Update rack to version 3 (#34816) 2025-05-28 08:39:17 +00:00
Matt Jankowski
887533392f
Regenerate rubocop todo with 1.75.7 (#34825) 2025-05-28 08:38:57 +00:00
github-actions[bot]
43ccb04548
New Crowdin Translations (automated) (#34834)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-05-28 08:38:51 +00:00
renovate[bot]
75ae084976
fix(deps): update dependency rollup-plugin-visualizer to v6.0.1 (#34836)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-28 08:20:55 +00:00
renovate[bot]
474013b48c
fix(deps): update dependency postcss-preset-env to v10.2.0 (#34821)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-28 08:01:02 +00:00
renovate[bot]
9d7ecf92fe
chore(deps): update dependency omniauth-saml to v2.2.4 (#34831)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-28 07:45:16 +00:00
Echo
d78535eab9
Add language picker to server rules section (#34820) 2025-05-27 13:57:34 +00:00
renovate[bot]
7ede5460d8
chore(deps): update dependency pghero to v3.7.0 (#34819)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-27 12:14:38 +00:00
github-actions[bot]
32b5da558e
New Crowdin Translations (automated) (#34817)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-05-27 09:28:32 +00:00
renovate[bot]
7132e660a6
chore(deps): update dependency sidekiq-unique-jobs to v8.0.11 (#34815)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-27 08:56:08 +00:00
Claire
0372344d33
Move Mastodon theme handling to custom vite plugin (#34808)
Co-authored-by: Echo <ChaosExAnima@users.noreply.github.com>
2025-05-27 08:50:48 +00:00
KMY
2fddfbf0c2 Test: 新規投稿時のみ引用設定 2025-05-27 17:38:45 +09:00
KMY
c60b6aa65d Fix lint 2025-05-27 13:01:53 +09:00
KMY
0c27b62a25 Change: リアクションデッキのTS化 (WIP) 2025-05-27 12:11:17 +09:00
KMY
7c65b6f9df Merge remote-tracking branch 'parent/main' into kbtopic-remove-quote 2025-05-27 10:51:58 +09:00
Matt Jankowski
37c82a3003
Update sidekiq to version 7 (#34745) 2025-05-26 15:32:41 +00:00
Echo
ba5320671c
Move pinned posts to a carousel (#34754)
Co-authored-by: diondiondion <mail@diondiondion.com>
2025-05-26 13:35:28 +00:00
renovate[bot]
47512fe518
fix(deps): update dependency rollup-plugin-visualizer to v6 (#34805)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-26 13:26:09 +00:00
Claire
955e75e820
Fix premailer strategy when using CDN_HOST (#34813) 2025-05-26 13:19:19 +00:00
Claire
b7e967817b
Fix unnecessary requirement for deprecated OTP_SECRET environment variable (#34810) 2025-05-26 11:59:54 +00:00
Claire
198b59ca3e
Fix NoMethodError in ActivityPub::FetchFeaturedCollectionService (#34811) 2025-05-26 08:24:46 +00:00
Claire
b3615a803e
Remove unnecessary direct dependency to glob (#34809) 2025-05-26 07:42:24 +00:00
renovate[bot]
170668ed69
chore(deps): update dependency selenium-webdriver to v4.33.0 (#34796)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-26 07:41:59 +00:00
github-actions[bot]
d1d3ff087a
New Crowdin Translations (automated) (#34795)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-05-26 07:41:52 +00:00
Claire
558c73a21e
Use @/ absolute paths instead of relative paths in CSS (#34806) 2025-05-26 07:27:44 +00:00
Claire
e0f15a6875
Add cross-account quote to sample data (#34791) 2025-05-24 12:16:28 +00:00
diondiondion
a13756148d
fix: Show hint for quotes hidden by filter (#34790) 2025-05-23 15:26:06 +00:00
Claire
304c0417ed
Fix handling of inlined featured collections in ActivityPub actor objects (#34789) 2025-05-23 15:01:07 +00:00
diondiondion
3bf128e62a
Add dev sample data for post with quote + media (#34787) 2025-05-23 12:52:14 +00:00
Echo
84d03e4e16
Revert React Spring to 9.7.5 and updates Renovate (#34788) 2025-05-23 12:34:41 +00:00
diondiondion
68a5724b3e
fix: Allow quotes to be filtered (#34786) 2025-05-23 11:42:55 +00:00
renovate[bot]
229e100dc0
fix(deps): update dependency @vitejs/plugin-react to v4.5.0 (#34784)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-23 07:30:04 +00:00
github-actions[bot]
11c8177498
New Crowdin Translations (automated) (#34781)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-05-23 07:24:21 +00:00
Matt Jankowski
bd2988bdf4
Fix Style/PreferredHashMethods cop (#34775) 2025-05-23 07:11:59 +00:00
nicole mikołajczyk
6b066eac2c
Fix “Open original page” and “Add or Remove from lists” being included in account dropdown even when irrelevant (#34767)
Signed-off-by: Nicole Mikołajczyk <git@mkljczk.pl>
2025-05-23 07:11:32 +00:00
diondiondion
5dda094daa
fix: Fix various UI text wrapping and overflow issues (#34774) 2025-05-23 07:07:05 +00:00
Claire
02ac18da51
Change display of quote posts to strip fallback link and preview cards (#34772) 2025-05-23 06:53:04 +00:00
David Roetzel
3acd87419c
Update to linzer 0.7 (#34765) 2025-05-23 06:43:02 +00:00
Claire
e0ce4b9b6b
Fix quotes not being displayed in reblogs (#34773) 2025-05-22 15:23:45 +00:00
Renaud Chaput
ef1bf8e9f2
Fix polyfills naming and tag missing a source (#34768) 2025-05-22 12:54:47 +00:00
diondiondion
12c8a6498c
Add "Followers you know" to hovercard (#34769) 2025-05-22 12:46:14 +00:00
Claire
da60acced5
Add boost of remote quote post with fallback link to sample dev data (#34771) 2025-05-22 12:45:24 +00:00
Claire
80849fbfba
Fix preview card being fetched even when a status has a quote or media attachment (#34770) 2025-05-22 12:42:16 +00:00
diondiondion
79ccba1758
Add visual indicator & link to nested quote posts (#34766) 2025-05-22 10:39:45 +00:00
renovate[bot]
72356bd5ec
chore(deps): update dependency ruby-prof to v1.7.2 (#34764)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-22 10:35:49 +00:00
renovate[bot]
6664f16b14
chore(deps): update dependency rack to v2.2.16 (#34763)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-22 10:35:41 +00:00
github-actions[bot]
cddb69ed52
New Crowdin Translations (automated) (#34762)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-05-22 10:11:03 +00:00
Andy Piper
68f951b945
Add security policy in CONTRIBUTING, update year refs. (#34761)
Signed-off-by: Andy Piper <andypiper@users.noreply.github.com>
2025-05-22 10:03:26 +00:00
renovate[bot]
f1172ca8fe
chore(deps): update dependency rubocop to v1.75.7 (#34759)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-22 09:59:43 +00:00
renovate[bot]
e9d62b284a
chore(deps): update node.js to 22.16 (#34760)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-22 09:53:20 +00:00
Matt Jankowski
8d4ae81ab4
Remove OTP_SECRET env configuration (#34748) 2025-05-22 09:33:21 +00:00
Renaud Chaput
83dd09d4dc
Fix JS polyfills missing after the Vite switch (#34758) 2025-05-21 20:11:01 +00:00
Claire
6ab96ba647
Use more generic locale as fallback for rules (#34756) 2025-05-21 16:22:54 +00:00
diondiondion
97b9e8849d
Add rendering of quote posts in web UI (#34738) 2025-05-21 15:50:45 +00:00
Matt Jankowski
f1a6f4333a
Remove redis-namespace gem (#34742) 2025-05-21 15:20:17 +00:00
Matt Jankowski
3a5e310a6d
Remove OTP_SECRET env configuration from setup (#34757) 2025-05-21 15:08:46 +00:00
Claire
8c51a8ba94
Add ability to translate server rules (#34494) 2025-05-21 11:54:12 +00:00
diondiondion
977164decc
docs: Update DEVELOPMENT.md to include vips project dependency (#34753) 2025-05-21 09:17:17 +00:00
Matt Jankowski
67f5122ba6
Use ActiveSupport::TaggedLogging.logger shorthand to set logger in production env (#34746) 2025-05-21 08:50:36 +00:00
renovate[bot]
30ee67e2c6
fix(deps): update dependency @react-spring/web to v10.0.1 (#34752)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-21 08:39:04 +00:00
github-actions[bot]
07741f307e
New Crowdin Translations (automated) (#34750)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-05-21 08:28:04 +00:00
Nick Schonning
d8ea8bc3bb
Enable Stylelint color-hex-length (#34310) 2025-05-21 08:05:45 +00:00
Claire
f7182ddc8b
Change libvips to be enabled by default (#34741) 2025-05-20 17:14:17 +00:00
Matt Jankowski
4709121f72
Remove Legacy OTP Secret code (#34743) 2025-05-20 14:51:19 +00:00
Claire
dab31f7a88
Drop support for PostgreSQL 12 (#34744) 2025-05-20 14:48:29 +00:00
Matt Jankowski
855022f4d9
Use ActiveSupport::TaggedLogging.logger shorthand to set logger (#34734) 2025-05-20 14:31:49 +00:00
Renaud Chaput
a8f12a6fd8
Change Node.js minimum version to Node 20 (#34390) 2025-05-20 14:25:51 +00:00
Claire
ef87cd6910
Fix incorrect progress value being passed to react-spring in video player (#34740) 2025-05-20 13:12:08 +00:00
renovate[bot]
042a9c42be
fix(deps): update dependency @reduxjs/toolkit to v2.8.2 (#34477)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-20 13:11:13 +00:00
Claire
6d6263ce07
Drop redis namespace code (except for Rails cache) (#34665) 2025-05-20 13:02:09 +00:00
Claire
f94b1fce41
Drop compatibility with Redis < 6.2 (#30413) 2025-05-20 12:55:42 +00:00
Claire
d7cb6068b1
Add ability to reorder server rules from admin interface (#34737) 2025-05-20 12:49:11 +00:00
github-actions[bot]
8ed0408adb
New Crowdin Translations (automated) (#34736)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-05-20 08:13:20 +00:00
Claire
0ada6e4168
Bypass date of birth check in dev:populate_sample_data task (#34733) 2025-05-19 20:20:37 +00:00
renovate[bot]
0d809652d9
chore(deps): update dependency lint-staged to v16 (#34657)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 16:10:41 +00:00
Echo
dbf14784bf
Add setting to control the referrer origin (#34731) 2025-05-19 13:13:22 +00:00
renovate[bot]
8ab2c4a9fc
chore(deps): update dependency stylelint-config-standard-scss to v15 (#34658)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: ChaosExAnima <ChaosExAnima@users.noreply.github.com>
2025-05-19 12:46:11 +00:00
diondiondion
4372d17114
fix: Prevent long link names in admin sidebar from being truncated (#34727) 2025-05-19 12:36:46 +00:00
renovate[bot]
65f338c812
fix(deps): update dependency pino to v9.7.0 (#34728)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 12:35:46 +00:00
renovate[bot]
39eff1c3ca
fix(deps): update dependency sass to v1.89.0 (#34729)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 12:35:25 +00:00
renovate[bot]
feb4e0a007
fix(deps): update dependency @react-spring/web to v10 (#34693)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: ChaosExAnima <ChaosExAnima@users.noreply.github.com>
2025-05-19 12:35:10 +00:00
diondiondion
24551375cf
fix: Show Follow account modal before allowing adding to list, #34468 (#34709)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Matt Jankowski <matt@jankowski.online>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: GitHub Actions <noreply@github.com>
2025-05-19 09:54:45 +00:00
Claire
90f7b90223
Change passthrough video processing to emit moov atom at start of video (#34726) 2025-05-19 08:29:31 +00:00
github-actions[bot]
e291f95a04
New Crowdin Translations (automated) (#34713)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-05-19 07:35:35 +00:00
renovate[bot]
b981175f08
chore(deps): update dependency rubocop-rails to v2.32.0 (#34724)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 07:25:28 +00:00
renovate[bot]
695f0c5eaa
fix(deps): update dependency @vitejs/plugin-react to v4.4.1 (#34725)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 07:25:04 +00:00
renovate[bot]
2e4ba88ceb
chore(deps): update dependency rack to v2.2.15 (#34719)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 07:03:16 +00:00
renovate[bot]
3d2bc0c513
fix(deps): update dependency postcss-preset-env to v10.1.6 (#34720)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 07:03:02 +00:00
renovate[bot]
9d4ec09e7a
fix(deps): update dependency ws to v8.18.2 (#34721)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 07:02:38 +00:00
Matt Jankowski
2d13a41462
Use bundler version 2.6.9 (#34708) 2025-05-16 16:02:29 +00:00
renovate[bot]
b4bbea51c4
fix(deps): update dependency babel-plugin-formatjs to v10.5.38 (#34707)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-16 15:26:34 +00:00
renovate[bot]
9e2c0c4cef
chore(deps): update dependency bootsnap to v1.18.6 (#34703)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-16 15:16:02 +00:00
renovate[bot]
48922c6aff
chore(deps): update docker.io/ruby docker tag to v3.4.4 (#34706)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-16 14:57:55 +00:00
renovate[bot]
6d6e1ed958
chore(deps): update dependency ruby to v3.4.4 (#34692)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-16 14:57:51 +00:00
renovate[bot]
6452796879
chore(deps): update dependency rubocop to v1.75.6 (#34704)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-16 14:14:43 +00:00
Claire
8cc5084ca1
Add interstitial for Terms of Service updates (#34527) 2025-05-16 14:03:05 +00:00
Echo
c4f47adb49
Convert from Webpack to Vite (#34450)
Co-authored-by: Renaud Chaput <renchap@gmail.com>
2025-05-16 13:26:12 +00:00
David Roetzel
a5a2c6dc7e
Add support for FASP data sharing (#34415) 2025-05-16 12:24:02 +00:00
Claire
3ea1f074ab
Fix sidekiq JSON serialization warning in ActivityPub::FetchAllRepliesWorker (#34702) 2025-05-16 09:07:33 +00:00
github-actions[bot]
c058c45a8e
New Crowdin Translations (automated) (#34701)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-05-16 08:07:14 +00:00
Claire
24d3599690
Fix middle button mouse up on status header always opening status in a new tab (#34700) 2025-05-15 18:29:43 +00:00
diondiondion
6c743831aa
fix: Hide "Followers you know" widget from your own profile, #34698 (#34699) 2025-05-15 14:40:01 +00:00
diondiondion
3f965d83b0
fix: More "Followers you know" polish & bug fixes (#34697) 2025-05-15 11:33:16 +00:00
Claire
ae281f31db
Add dev:populate_sample_data rake task to populate test data (#34676) 2025-05-15 08:51:07 +00:00
github-actions[bot]
e17c78b679
New Crowdin Translations (automated) (#34695)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-05-15 08:50:48 +00:00
diondiondion
ccffa11f2b
refactor: Remove duplicated AvatarGroup CSS and familiar followers cleanup (#34681) 2025-05-15 08:07:38 +00:00
renovate[bot]
d475bcce65
chore(deps): update dependency bootsnap to v1.18.5 (#34684)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-15 08:00:55 +00:00
Claire
1b68020331
Fix admin dashboard crash on specific Elasticsearch connection errors (#34683) 2025-05-14 14:50:32 +00:00
Claire
e8e93b82f1
Fix NoMethodError in ActivityPub::FetchAllRepliesWorker (#34682) 2025-05-14 13:43:34 +00:00
Claire
aa04efb92a
Move server rule creation form to its own page (#34637) 2025-05-14 09:43:07 +00:00
diondiondion
c45ce549af
refactor: Prevent leading slashes in API urls (#34680) 2025-05-14 08:59:08 +00:00
github-actions[bot]
8d5b73d70d
New Crowdin Translations (automated) (#34679)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-05-14 07:00:32 +00:00
renovate[bot]
16e36d8477
chore(deps): update dependency database_cleaner-active_record to v2.2.1 (#34674)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-14 06:57:27 +00:00
Echo
545e8fbd0c
Fix emoji bundle size (#34677) 2025-05-14 06:39:05 +00:00
diondiondion
865a30ab0d
fix: Hide FamiliarFollowers widget when logged out (#34678) 2025-05-13 17:55:16 +00:00
diondiondion
cc57fa4a41
docs: Improve local development readme (#34675) 2025-05-13 12:22:51 +00:00
Claire
5305e939c4
Add (currently unused) setting for default quote policy (#34623) 2025-05-13 11:47:38 +00:00
Claire
f993d7578b
Use plural forms for date_of_birth prompt (#34636) 2025-05-13 11:29:22 +00:00
github-actions[bot]
65baf9b04a
New Crowdin Translations (automated) (#34672)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-05-13 07:47:56 +00:00
renovate[bot]
050d76c010
fix(deps): update dependency pg to v8.16.0 (#34670)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-13 07:38:15 +00:00
diondiondion
b135a831ea
feat: Add "Followers you know" widget to user profiles (#34652) 2025-05-13 06:38:18 +00:00
KMY
04070aa608 Merge remote-tracking branch 'parent/main' into kbtopic-remove-quote 2025-05-13 07:37:34 +09:00
KMY
1e8420464c StatusReferencesServiceを引用に関与しない新仕様に対応 2025-05-13 07:28:37 +09:00
Marcel Hellkamp
c9a554bdca
fix: OIDC account creation fails for long display names (#34639) 2025-05-12 15:51:53 +00:00
Claire
5ec840a32f
Change REDIS_NAMESPACE deprecation warning to an error (#34664) 2025-05-12 15:14:15 +00:00
Jonny Saunders
b709ef8ac3
Add: Update root status when fetching replies (#34615) 2025-05-12 14:54:58 +00:00
Claire
4e2aa78a56
Fix tootctl accounts create failing because of date-of-birth check (#34663) 2025-05-12 09:28:12 +00:00
github-actions[bot]
3357ae9889
New Crowdin Translations (automated) (#34655)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-05-12 07:40:14 +00:00
renovate[bot]
6fa48fabb2
fix(deps): update dependency sass to v1.88.0 (#34659)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-12 07:20:48 +00:00
Renaud Chaput
9244ffc425
Fix eslint import plugin resolution in vscode (#34651) 2025-05-12 07:12:56 +00:00
renovate[bot]
82688387a8
chore(deps): update dependency mime-types to '~> 3.7.0' (#34634)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-09 14:58:18 +00:00
renovate[bot]
23238ddd95
fix(deps): update dependency vite to v6.2.7 [security] (#34640)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Renaud Chaput <renchap@gmail.com>
2025-05-09 08:05:58 +00:00
Claire
912268295c
Change /api/v2/instance to be enabled without authentication when limited federation mode is enabled (#34576) 2025-05-09 07:46:57 +00:00
renovate[bot]
face71b7b2
fix(deps): update dependency @babel/core to v7.27.1 (#34643)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-09 07:14:25 +00:00
github-actions[bot]
7cd7445abe
New Crowdin Translations (automated) (#34649)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-05-09 07:07:17 +00:00
renovate[bot]
1131f2c439
fix(deps): update dependency ws to v8.17.1 [security] (#34641)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-09 06:48:30 +00:00
Echo
8c579c5b34
Migrate from Jest to Vitest (#34454) 2025-05-07 18:29:02 +00:00
github-actions[bot]
741f166407
New Crowdin Translations (automated) (#34633)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-05-07 08:45:03 +00:00
renovate[bot]
0c738ea0ca
chore(deps): update dependency rack to v2.2.14 (#34629)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-07 08:41:15 +00:00
renovate[bot]
6ac29ab1ac
fix(deps): update dependency @babel/preset-env to v7.27.2 (#34628)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-07 08:13:16 +00:00
renovate[bot]
b99abe44b0
fix(deps): update dependency cssnano to v7.0.7 (#34627)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-07 08:13:12 +00:00
KMY
acc662e490 Add: kmyblueから本家の引用への変換コード 2025-05-07 13:04:24 +09:00
KMY
35386bd054 Fix test 2025-05-07 12:27:49 +09:00
KMY
0557257647 Fix test 2025-05-07 11:45:18 +09:00
KMY
9de0de7d65 Merge remote-tracking branch 'parent/main' into kbtopic-remove-quote 2025-05-07 09:39:51 +09:00
KMY
7d80e90976 Add kmyblue original comments 2025-05-07 09:22:27 +09:00
KMY
721f6f9c97 Fix test 2025-05-07 09:15:44 +09:00
KMY
29b904483e Merge commit 'e3f0b955b8' into kbtopic-remove-quoteMerge 2025-05-07 08:46:25 +09:00
KMY
9d64a77bcf Fix test 2025-05-07 07:46:56 +09:00
Claire
fbe9728f36
Bump version to v4.3.8 (#34626) 2025-05-06 14:17:07 +00:00
Claire
3bbf3e9709
Fix code style issue (#34624) 2025-05-06 13:35:54 +00:00
Claire
79931bf3ae
Merge commit from fork
* Check scheme in account and post links

* Harden media attachments

* Client-side mitigation

* Client-side mitigation for media attachments
2025-05-06 15:02:13 +02:00
Claire
22e2e7f02b
Fix crash when likes or shares collections are not inlined, for real (#34619) 2025-05-06 09:51:42 +00:00
Claire
41d00bc28b
Fix libvips being unconditionally required by tasks (#34620) 2025-05-06 09:45:32 +00:00
Claire
3e5d78cc5b
Fix crash when likes or shares collections are not inlined (#34618) 2025-05-06 07:39:26 +00:00
Renaud Chaput
df6b808750
fix: do not use the deprecated /api/v1/instance end point (#34613) 2025-05-06 06:08:44 +00:00
Claire
aedc5f6921
Add warning for REDIS_NAMESPACE deprecation at startup (#34581) 2025-05-05 13:01:16 +00:00
Claire
89cafb01b4
Remove double-query for signed query strings (#34610) 2025-05-05 12:33:31 +00:00
renovate[bot]
2133f2b47e
fix(deps): update dependency babel-plugin-formatjs to v10.5.38 (#34609)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-05 08:26:12 +00:00
renovate[bot]
833ea0725d
chore(deps): update dependency rubocop to v1.75.5 (#34608)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-05 08:26:07 +00:00
github-actions[bot]
eacf6f2342
New Crowdin Translations (automated) (#34596)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-05-05 08:23:27 +00:00
renovate[bot]
84bca6fd54
chore(deps): update dependency public_suffix to v6.0.2 (#34590)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-05 08:23:21 +00:00
Claire
cbaba54e9d
Add support for importing embedded self-quotes (#34584) 2025-05-05 08:01:16 +00:00
renovate[bot]
d41a741e00
fix(deps): update dependency ws to v8.18.2 (#34603)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-05 07:55:52 +00:00
renovate[bot]
03a0f7caf9
chore(deps): update dependency selenium-webdriver to v4.32.0 (#34604)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-05 07:55:34 +00:00
Jonny Saunders
8b34daf254
Fix: Use strings not symbols to access totalItems in interaction collections (#34594) 2025-05-03 10:37:06 +00:00
Eugen Rochko
b4394ec129
Change design of audio player in web UI (#34520) 2025-05-02 16:15:00 +00:00
renovate[bot]
24c25ec4f5
fix(deps): update babel monorepo to v7.27.1 (#34592)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-02 14:45:49 +00:00
github-actions[bot]
94fa5b7168
New Crowdin Translations (automated) (#34587)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-05-02 06:59:30 +00:00
Matt Jankowski
4354f84c5c
Update rspec-rails to version 8.0.0 (#34588) 2025-05-02 06:33:20 +00:00
Patryk Rzucidło
e3f0b955b8
Fix directory scroll position reset (#34560) 2025-04-30 12:27:37 +00:00
renovate[bot]
05f6f7d28a
fix(deps): update dependency core-js to v3.42.0 (#34577)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-30 07:50:13 +00:00
github-actions[bot]
64ab9be93f
New Crowdin Translations (automated) (#34580)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-04-30 07:31:08 +00:00
renovate[bot]
a2310a06fa
fix(deps): update dependency axios to v1.9.0 (#34547)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-29 14:40:02 +00:00
Eugen Rochko
79013c730d
Add endorsed accounts to profiles in web UI (#34568) 2025-04-29 12:14:22 +00:00
Claire
b81c28e7dc
Fix edit dropdown crashing the web interface on mobile (#34564) 2025-04-29 09:48:54 +00:00
Claire
ce13fca0c5
Add built-in context for interaction policies (#34574) 2025-04-29 08:51:03 +00:00
Claire
98e6dfcbcf
Fix context selector trying to mutate immutable state (#34573) 2025-04-29 08:12:05 +00:00
renovate[bot]
7cb93ef5a1
chore(deps): update dependency connection_pool to v2.5.3 (#34569)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-29 07:23:53 +00:00
github-actions[bot]
66d9e47178
New Crowdin Translations (automated) (#34572)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-04-29 07:05:02 +00:00
renovate[bot]
e7dd0b37c7
chore(deps): update dependency rubocop to v1.75.4 (#34570)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-29 06:47:42 +00:00
renovate[bot]
b0e63fbe1c
chore(deps): update dependency rqrcode to v3.1.0 (#34565)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-29 06:19:10 +00:00
Essem
e96044f389
Update to Twemoji 15.1.0 (#34321) 2025-04-28 14:22:14 +00:00
Eugen Rochko
715cbee93d
Fix dashboard warning about Elasticsearch index mismatch not showing up (#34567)
Co-authored-by: Claire <claire.github-309c@sitedethib.com>
2025-04-28 13:59:49 +00:00
Eugen Rochko
17d8e2b6e3
Refactor context reducer to TypeScript (#34506) 2025-04-28 13:38:40 +00:00
Eugen Rochko
bd9223f0b9
Fix tootctl search deploy --only-mapping not updating index settings (#34566) 2025-04-28 13:02:41 +00:00
Eugen Rochko
40157e063d
Add ability to feature and unfeature hashtags from web UI (#34490) 2025-04-28 11:44:01 +00:00
Eugen Rochko
926c67c648
Refactor <ActionsModal> to TypeScript (#34559) 2025-04-28 11:43:42 +00:00
Claire
17e4345eb2
Add quoted_status attribute to PostStatusService for local testing (#34553) 2025-04-28 10:07:22 +00:00
Claire
9ed6a14d45
Add support for ingesting quote policies (#34479) 2025-04-28 08:48:27 +00:00
renovate[bot]
1a1f3f037d
fix(deps): update dependency pg to v8.15.6 (#34555)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 07:34:18 +00:00
renovate[bot]
3032d9d0dd
chore(deps): update dependency shoulda-matchers to v6.5.0 (#34556)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 07:33:51 +00:00
github-actions[bot]
a20686f593
New Crowdin Translations (automated) (#34558)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-04-28 07:33:20 +00:00
KMY(雪あすか)
7696122cfc
Update status.rb 2025-04-26 13:56:59 +09:00
KMY(雪あすか)
ffb4ca4231
Update registrations_controller_spec.rb 2025-04-26 13:37:28 +09:00
KMY(雪あすか)
c6b740ace2
Update chewy_config.rb 2025-04-26 08:49:32 +09:00
KMY
3233caba60 Merge remote-tracking branch 'parent/main' into kbtopic-remove-quote 2025-04-26 08:37:43 +09:00
KMY
80542ea172 Merge remote-tracking branch 'parent/main' into kbtopic-remove-quote 2025-04-26 08:30:17 +09:00
Claire
ae3b7dd28d
Reject incoming QuoteRequest activities (#34480) 2025-04-25 23:28:09 +00:00
Claire
8f59b63176
Change quote IDs to use snowflake IDs (#34551) 2025-04-25 23:24:26 +00:00
KMY
82b6413f61 Merge remote-tracking branch 'parent/main' into kbtopic-remove-quote 2025-04-26 08:18:16 +09:00
KMY
a88d202c6b Merge commit 'dee744c793' into kbtopic-remove-quote 2025-04-26 08:17:07 +09:00
KMY
e4c72836a3 Merge commit 'df2611a10f' into kbtopic-remove-quote 2025-04-26 07:48:46 +09:00
KMY
89358f1750 Fix test: remove quote from ProcessReferencesService 2025-04-26 07:20:23 +09:00
KMY
2c268e47e7 Fix test 2025-04-26 07:09:30 +09:00
Eugen Rochko
a97647158c
Add REST API for featuring and unfeaturing a hashtag (#34489)
Co-authored-by: Matt Jankowski <matt@jankowski.online>
Co-authored-by: Claire <claire.github-309c@sitedethib.com>
2025-04-25 15:12:05 +00:00
Eugen Rochko
49b6a49c76
Change "Pin on profile" to "Feature on profile" for posts in web UI (#34492) 2025-04-25 15:11:59 +00:00
Claire
d4944a2467
Fix incorrect redirect in response to unauthenticated API requests in limited federation mode (#34549) 2025-04-25 11:24:57 +00:00
Eugen Rochko
91db45b197
Change account search to be more forgiving of spaces (#34455) 2025-04-25 10:35:21 +00:00
Claire
7a70d95435
Add warning for Elasticsearch index analyzers mismatch (#34515) 2025-04-25 10:35:11 +00:00
renovate[bot]
1326c8cb1d
chore(deps): update dependency rqrcode to v3 (#34541)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-25 09:54:56 +00:00
Claire
199acce481
Fix sign-up e-mail confirmation page reloading on error or redirect (#34548) 2025-04-25 09:00:54 +00:00
github-actions[bot]
b1b949f16c
New Crowdin Translations (automated) (#34546)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-04-25 06:44:41 +00:00
Matt Jankowski
6463415e06
Update rubocop-rspec to version 3.6.0 (#34497) 2025-04-24 14:56:13 +00:00
Claire
22ec828951
Change DEFAULT_LOCALE to not override unauthenticated users' browser language (#34535) 2025-04-24 11:38:27 +00:00
Terence Eden
13b13c8726
Reduce path size for oEmbed and logo (#34538)
Co-authored-by: Terence Eden <git@shkspr.mobi>
2025-04-24 11:38:02 +00:00
renovate[bot]
5679bb5394
fix(deps): update dependency pg to v8.15.5 (#34531)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-24 08:24:16 +00:00
github-actions[bot]
1fc66c1970
New Crowdin Translations (automated) (#34534)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-04-24 08:06:10 +00:00
renovate[bot]
57a6c5f4e9
chore(deps): update dependency connection_pool to v2.5.2 (#34530)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-24 07:43:39 +00:00
renovate[bot]
65c67fb827
fix(deps): update dependency pg-connection-string to v2.8.5 (#34532)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-24 07:42:59 +00:00
KMY
d845d1e9fb Remove: kmyblue独自機能の引用 2025-04-24 08:48:28 +09:00
renovate[bot]
ca4139be07
chore(deps): update node.js to 22.15 (#34523)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-23 09:50:42 +00:00
renovate[bot]
ffc853c086
fix(deps): update dependency pg to v8.15.1 (#34516)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-23 08:53:29 +00:00
github-actions[bot]
577e407ffc
New Crowdin Translations (automated) (#34522)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-04-23 08:47:20 +00:00
renovate[bot]
b68c622a07
fix(deps): update dependency pg-connection-string to v2.8.1 (#34517)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-23 08:25:46 +00:00
Claire
7bc301e184
Make Web::PushSubscription#user and Web::PushSubscription#access_token relationships non-optional (#34498)
Co-authored-by: Emelia Smith <ThisIsMissEm@users.noreply.github.com>
2025-04-23 08:12:31 +00:00
Claire
dee744c793
Fix quote serializer (#34510) 2025-04-23 07:29:13 +00:00
renovate[bot]
e097f0e9eb
fix(deps): update dependency sass to v1.87.0 (#34511)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-22 14:55:17 +00:00
Gomasy
6027764c31
Fix icon crushed when account name was too long (#34514) 2025-04-22 12:39:35 +00:00
Emelia Smith
b754e28190
Change devise to not use HTTP Basic Authentication (#34501) 2025-04-22 12:11:21 +00:00
renovate[bot]
cba4682ced
fix(deps): update dependency react-intl to v7.1.11 (#34503)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-22 08:34:08 +00:00
github-actions[bot]
b92f42a6bd
New Crowdin Translations (automated) (#34502)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-04-22 08:33:42 +00:00
Matt Jankowski
8dea1c422a
Combine examples to reduce factories in BulkImportWorker spec (#34499) 2025-04-22 08:23:41 +00:00
renovate[bot]
bc32ff9b57
fix(deps): update dependency postcss-preset-env to v10.1.6 (#34505)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-22 08:22:25 +00:00
renovate[bot]
20162a821c
chore(deps): update dependency nokogiri to v1.18.8 (#34508)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-22 08:22:05 +00:00
Eugen Rochko
3159f3b2f6
Fix featured hashtags not showing year for date in web UI (#34491) 2025-04-18 13:54:13 +00:00
github-actions[bot]
361f528c89
New Crowdin Translations (automated) (#34487)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-04-18 08:51:50 +00:00
Eugen Rochko
bed614d44e
Add option to remove account from followers in web UI (#34488) 2025-04-18 07:23:34 +00:00
Echo
64d94f9e57
Update copy for empty featured tabs (#34483) 2025-04-17 10:27:44 +00:00
Claire
8489f6c8fc
Fix namespace of QuoteAuthorization type in specs (#34481) 2025-04-17 09:19:23 +00:00
Eugen Rochko
c01d219c12
Add --only-mapping option to tootctl search deploy (#34466) 2025-04-17 09:09:03 +00:00
Eugen Rochko
ee62ac53e1
Add "Mutual" relationship tag to profiles in web UI (#34467) 2025-04-17 08:10:11 +00:00
github-actions[bot]
b33f9ea603
New Crowdin Translations (automated) (#34464)
Co-authored-by: GitHub Actions <noreply@github.com>
2025-04-17 08:10:03 +00:00
renovate[bot]
b64a5a7d84
chore(deps): update dependency connection_pool to v2.5.1 (#34475)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-17 08:07:19 +00:00
renovate[bot]
3dc95902d7
chore(deps): update dependency opentelemetry-instrumentation-pg to v0.30.1 (#34472)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-17 08:07:02 +00:00
renovate[bot]
5810bd3310
chore(deps): update docker.io/ruby docker tag to v3.4.3 (#34460)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-17 07:56:10 +00:00
Claire
df2611a10f
Add initial support for ingesting and verifying remote quote posts (#34370) 2025-04-17 07:45:23 +00:00
1074 changed files with 25526 additions and 18419 deletions

View file

@ -9,6 +9,7 @@ services:
environment:
RAILS_ENV: development
NODE_ENV: development
VITE_RUBY_HOST: 0.0.0.0
BIND: 0.0.0.0
BOOTSNAP_CACHE_DIR: /tmp
REDIS_HOST: redis
@ -22,11 +23,12 @@ services:
ES_PORT: '9200'
LIBRE_TRANSLATE_ENDPOINT: http://libretranslate:5000
LOCAL_DOMAIN: ${LOCAL_DOMAIN:-localhost:3000}
VITE_DEV_SERVER_PUBLIC: ${VITE_DEV_SERVER_PUBLIC:-localhost:3036}
# Overrides default command so things don't shut down after the process ends.
command: sleep infinity
ports:
- '3000:3000'
- '3035:3035'
- '3036:3036'
- '4000:4000'
networks:
- external_network

View file

@ -2,3 +2,5 @@
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY=fkSxKD2bF396kdQbrP1EJ7WbU7ZgNokR
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT=r0hvVmzBVsjxC7AMlwhOzmtc36ZCOS1E
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY=PhdFyyfy5xJ7WVd2lWBpcPScRQHzRTNr
MASTODON_USE_LIBVIPS=false

View file

@ -43,7 +43,6 @@ ES_PASS=password
# Make sure to use `bundle exec rails secret` to generate secrets
# -------
SECRET_KEY_BASE=
OTP_SECRET=
# Encryption secrets
# ------------------

View file

@ -50,7 +50,7 @@ body:
label: Mastodon version
description: |
This is displayed at the bottom of the About page, eg. `v4.4.0-alpha.1`
placeholder: v4.3.0
placeholder: v4.4.0-beta.1
validations:
required: false
- type: textarea
@ -60,9 +60,9 @@ body:
Details about your environment, like how Mastodon is deployed, if containers are used, version numbers, etc.
value: |
Please at least include those informations:
- Operating system: (eg. Ubuntu 22.04)
- Ruby version: (from `ruby --version`, eg. v3.4.1)
- Node.js version: (from `node --version`, eg. v20.18.0)
- Operating system: (eg. Ubuntu 24.04.2)
- Ruby version: (from `ruby --version`, eg. v3.4.4)
- Node.js version: (from `node --version`, eg. v22.16.0)
validations:
required: false
- type: textarea

View file

@ -25,26 +25,12 @@
'tesseract.js', // Requires code changes
'react-hotkeys', // Requires code changes
// Requires Webpacker upgrade or replacement
'@svgr/webpack',
'@types/webpack',
'babel-loader',
'compression-webpack-plugin',
'css-loader',
'imports-loader',
'mini-css-extract-plugin',
'postcss-loader',
'sass-loader',
'terser-webpack-plugin',
'webpack',
'webpack-assets-manifest',
'webpack-bundle-analyzer',
'webpack-dev-server',
'webpack-cli',
// react-router: Requires manual upgrade
'history',
'react-router-dom',
// react-spring: Requires manual upgrade when upgrading react
'@react-spring/web',
],
matchUpdateTypes: ['major'],
dependencyDashboardApproval: true,
@ -53,7 +39,6 @@
// Require Dependency Dashboard Approval for major version bumps of these Ruby packages
matchManagers: ['bundler'],
matchPackageNames: [
'rack', // Needs to be synced with Rails version
'strong_migrations', // Requires manual upgrade
'sidekiq', // Requires manual upgrade
'sidekiq-unique-jobs', // Requires manual upgrades and sync with Sidekiq version

41
.github/workflows/chromatic.yml vendored Normal file
View file

@ -0,0 +1,41 @@
name: 'Chromatic'
on:
push:
branches-ignore:
- renovate/*
- stable-*
paths:
- 'package.json'
- 'yarn.lock'
- '**/*.js'
- '**/*.jsx'
- '**/*.ts'
- '**/*.tsx'
- '**/*.css'
- '**/*.scss'
- '.github/workflows/chromatic.yml'
jobs:
chromatic:
name: Run Chromatic
runs-on: ubuntu-latest
if: github.repository == 'mastodon/mastodon'
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Javascript environment
uses: ./.github/actions/setup-javascript
- name: Build Storybook
run: yarn build-storybook
- name: Run Chromatic
uses: chromaui/action@v12
with:
# ⚠️ Make sure to configure a `CHROMATIC_PROJECT_TOKEN` repository secret
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
zip: true
storybookBuildDir: 'storybook-static'

View file

@ -43,4 +43,4 @@ jobs:
uses: ./.github/actions/setup-javascript
- name: JavaScript testing
run: yarn jest --reporters github-actions summary
run: yarn test:js

View file

@ -52,7 +52,7 @@ jobs:
public/assets
public/packs
public/packs-test
tmp/cache/webpacker
tmp/cache/vite
key: ${{ matrix.mode }}-assets-${{ github.head_ref || github.ref_name }}-${{ github.sha }}
restore-keys: |
${{ matrix.mode }}-assets-${{ github.head_ref || github.ref_name }}-${{ github.sha }}
@ -66,7 +66,7 @@ jobs:
- name: Archive asset artifacts
run: |
tar --exclude={"*.br","*.gz"} -zcf artifacts.tar.gz public/assets public/packs*
tar --exclude={"*.br","*.gz"} -zcf artifacts.tar.gz public/assets public/packs* tmp/cache/vite/last-build*.json
- uses: actions/upload-artifact@v4
if: matrix.mode == 'test'
@ -147,7 +147,7 @@ jobs:
uses: ./.github/actions/setup-ruby
with:
ruby-version: ${{ matrix.ruby-version}}
additional-system-dependencies: ffmpeg imagemagick libpam-dev
additional-system-dependencies: ffmpeg libpam-dev
- name: Load database schema
run: |
@ -177,8 +177,8 @@ jobs:
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
test-libvips:
name: Libvips tests
test-imagemagick:
name: ImageMagick tests
runs-on: ubuntu-latest
needs:
@ -224,7 +224,7 @@ jobs:
CAS_ENABLED: true
BUNDLE_WITH: 'pam_authentication test'
GITHUB_RSPEC: ${{ matrix.ruby-version == '.ruby-version' && github.event.pull_request && 'true' }}
MASTODON_USE_LIBVIPS: true
MASTODON_USE_LIBVIPS: false
strategy:
fail-fast: false
@ -249,7 +249,7 @@ jobs:
uses: ./.github/actions/setup-ruby
with:
ruby-version: ${{ matrix.ruby-version}}
additional-system-dependencies: ffmpeg libpam-dev
additional-system-dependencies: ffmpeg imagemagick libpam-dev
- name: Load database schema
run: './bin/rails db:create db:schema:load db:seed'
@ -329,7 +329,7 @@ jobs:
uses: ./.github/actions/setup-ruby
with:
ruby-version: ${{ matrix.ruby-version}}
additional-system-dependencies: ffmpeg imagemagick
additional-system-dependencies: ffmpeg
- name: Set up Javascript environment
uses: ./.github/actions/setup-javascript
@ -337,6 +337,21 @@ jobs:
- name: Load database schema
run: './bin/rails db:create db:schema:load db:seed'
- name: Cache Playwright Chromium browser
id: playwright-cache
uses: actions/cache@v4
with:
path: ~/.cache/ms-playwright
key: playwright-browsers-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- name: Install Playwright Chromium browser (with deps)
if: steps.playwright-cache.outputs.cache-hit != 'true'
run: yarn run playwright install --with-deps chromium
- name: Install Playwright Chromium browser deps
if: steps.playwright-cache.outputs.cache-hit == 'true'
run: yarn run playwright install-deps chromium
- run: bin/rspec spec/system --tag streaming --tag js
- name: Archive logs
@ -350,7 +365,7 @@ jobs:
uses: actions/upload-artifact@v4
if: failure()
with:
name: e2e-screenshots
name: e2e-screenshots-${{ matrix.ruby-version }}
path: tmp/capybara/
test-search:
@ -448,7 +463,7 @@ jobs:
uses: ./.github/actions/setup-ruby
with:
ruby-version: ${{ matrix.ruby-version}}
additional-system-dependencies: ffmpeg imagemagick
additional-system-dependencies: ffmpeg
- name: Set up Javascript environment
uses: ./.github/actions/setup-javascript

6
.gitignore vendored
View file

@ -21,10 +21,11 @@
/public/system
/public/assets
/public/packs
/public/packs-dev
/public/packs-test
.env
.env.production
/node_modules/
node_modules/
/build/
# Ignore elasticsearch config
@ -77,3 +78,6 @@ docker-compose.override.yml
# Ignore local-only rspec configuration
.rspec-local
*storybook.log
storybook-static

2
.nvmrc
View file

@ -1 +1 @@
22.14
22.16

View file

@ -18,10 +18,6 @@
!/log/.keep
/tmp
/coverage
/public/system
/public/assets
/public/packs
/public/packs-test
.env
.env.production
.env.development
@ -60,10 +56,11 @@ docker-compose.override.yml
/public/packs
/public/packs-test
/public/system
/public/vite*
# Ignore emoji map file
/app/javascript/mastodon/features/emoji/emoji_map.json
/app/javascript/mastodon/features/emoji/emoji_sheet.json
/app/javascript/mastodon/features/emoji/emoji_data.json
# Ignore locale files
/app/javascript/mastodon/locales/*.json

View file

@ -1,3 +1,6 @@
---
Naming/BlockForwarding:
EnforcedStyle: explicit
Naming/PredicateMethod:
Enabled: false

View file

@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config --auto-gen-only-exclude --no-offense-counts --no-auto-gen-timestamp`
# using RuboCop version 1.75.2.
# using RuboCop version 1.76.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
@ -31,58 +31,14 @@ Metrics/PerceivedComplexity:
- 'app/services/delivery_antenna_service.rb'
- 'app/services/post_status_service.rb'
Rails/OutputSafety:
Exclude:
- 'config/initializers/simple_form.rb'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowedVars.
Style/FetchEnvVar:
Exclude:
- 'config/environments/production.rb'
- 'config/initializers/2_limited_federation_mode.rb'
- 'config/initializers/3_omniauth.rb'
- 'config/initializers/cache_buster.rb'
- 'config/initializers/devise.rb'
- 'config/initializers/paperclip.rb'
- 'config/initializers/vapid.rb'
- 'lib/tasks/repo.rake'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, MaxUnannotatedPlaceholdersAllowed, Mode, AllowedMethods, AllowedPatterns.
# SupportedStyles: annotated, template, unannotated
# AllowedMethods: redirect
Style/FormatStringToken:
Exclude:
- 'config/initializers/devise.rb'
- 'lib/paperclip/color_extractor.rb'
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: MinBodyLength, AllowConsecutiveConditionals.
Style/GuardClause:
Enabled: false
# Configuration parameters: AllowedMethods.
# AllowedMethods: respond_to_missing?
Style/OptionalBooleanParameter:
Exclude:
- 'app/lib/admin/system_check/message.rb'
- 'app/lib/request.rb'
- 'app/lib/webfinger.rb'
- 'app/services/block_domain_service.rb'
- 'app/services/fetch_resource_service.rb'
- 'app/workers/domain_block_worker.rb'
- 'app/workers/unfollow_follow_worker.rb'
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: short, verbose
Style/PreferredHashMethods:
Exclude:
- 'config/initializers/paperclip.rb'
# This cop supports safe autocorrection (--autocorrect).
Style/RedundantConstantBase:
Exclude:
- 'config/environments/production.rb'
- 'config/initializers/sidekiq.rb'

View file

@ -1 +1 @@
3.4.3
3.4.4

16
.storybook/main.ts Normal file
View file

@ -0,0 +1,16 @@
import type { StorybookConfig } from '@storybook/react-vite';
const config: StorybookConfig = {
stories: ['../app/javascript/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
addons: [
'@storybook/addon-docs',
'@storybook/addon-a11y',
'@storybook/addon-vitest',
],
framework: {
name: '@storybook/react-vite',
options: {},
},
};
export default config;

7
.storybook/manager.ts Normal file
View file

@ -0,0 +1,7 @@
import { addons } from 'storybook/manager-api';
import theme from './storybook-theme';
addons.setConfig({
theme,
});

View file

@ -0,0 +1,18 @@
<style>
/* Increase docs font size */
.sbdocs.sbdocs-content :where(p:not(.sb-anchor, .sb-unstyled, .sb-unstyled p)),
.sbdocs.sbdocs-content :where(li:not(.sb-anchor, .sb-unstyled, .sb-unstyled li)) {
font-size: 1.0666rem; /* 17px */
line-height: 1.585; /* 27px */
}
.sbdocs.sbdocs-content :where(p:not(.sb-anchor, .sb-unstyled, .sb-unstyled p)) code,
.sbdocs.sbdocs-content :where(li:not(.sb-anchor, .sb-unstyled, .sb-unstyled li)) code {
font-size: 0.875rem; /* ~15px */
}
/* Bring numbers back for ordered lists */
ol {
list-style: revert !important;
}
</style>

29
.storybook/preview.ts Normal file
View file

@ -0,0 +1,29 @@
import type { Preview } from '@storybook/react-vite';
// If you want to run the dark theme during development,
// you can change the below to `/application.scss`
import '../app/javascript/styles/mastodon-light.scss';
const preview: Preview = {
// Auto-generate docs: https://storybook.js.org/docs/writing-docs/autodocs
tags: ['autodocs'],
parameters: {
layout: 'centered',
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
a11y: {
// 'todo' - show a11y violations in the test UI only
// 'error' - fail CI on a11y violations
// 'off' - skip a11y checks entirely
test: 'todo',
},
},
};
export default preview;

View file

@ -0,0 +1,7 @@
// The addon package.json incorrectly exports types, so we need to override them here.
// See: https://github.com/storybookjs/storybook/blob/v9.0.4/code/addons/vitest/package.json#L70-L76
declare module '@storybook/addon-vitest/vitest-plugin' {
export * from '@storybook/addon-vitest/dist/vitest-plugin/index';
}
export {};

View file

@ -0,0 +1,7 @@
import { create } from 'storybook/theming';
export default create({
base: 'light',
brandTitle: 'Mastodon Storybook',
brandImage: 'https://joinmastodon.org/logos/wordmark-black-text.svg',
});

View file

@ -0,0 +1,8 @@
import * as a11yAddonAnnotations from '@storybook/addon-a11y/preview';
import { setProjectAnnotations } from '@storybook/react-vite';
import * as projectAnnotations from './preview';
// This is an important step to apply the right configuration when testing your stories.
// More info at: https://storybook.js.org/docs/api/portable-stories/portable-stories-vitest#setprojectannotations
setProjectAnnotations([a11yAddonAnnotations, projectAnnotations]);

View file

@ -2,9 +2,290 @@
All notable changes to this project will be documented in this file.
## [4.4.0] - UNRELEASED
### Added
- **Add “Followers you know” widget to user profiles and hover cards** (#34652, #34678, #34681, #34697, #34699, #34769, #34774 and #34914 by @diondiondion)
- **Add featured tab to profiles on web UI and rework pinned posts** (#34405, #34483, #34491, #34754, #34855, #34858, #34868, and #34869 by @ChaosExAnima, @ClearlyClaire, @Gargron, and @diondiondion)
- Add endorsed accounts to featured tab in web UI (#34421 and #34568 by @Gargron)\
This also includes the following new REST API endpoints:
- `GET /api/v1/accounts/:id/endorsements`: https://docs.joinmastodon.org/methods/accounts/#endorsements
- `POST /api/v1/accounts/:id/endorse`: https://docs.joinmastodon.org/methods/accounts/#endorse
- `POST /api/v1/accounts/:id/unendorse`: https://docs.joinmastodon.org/methods/accounts/#unendorse
- Add ability to add and remove hashtags from featured tags in web UI (#34489, #34887, and #34490 by @ClearlyClaire and @Gargron)\
This is achieved through the new REST API endpoints:
- `POST /api/v1/tags/:id/feature`: https://docs.joinmastodon.org/methods/tags/#feature
- `POST /api/v1/tags/:id/unfeature`: https://docs.joinmastodon.org/methods/tags/#unfeature
- Add reminder when about to post without alt text in web UI (#33760 and #33784 by @Gargron)
- Add a warning in Web UI when composing a post when the selected and detected language are different (#33042, #33683, #33700, #33724, #33770, and #34193 by @ClearlyClaire and @Gargron)
- Add ability to reorder and translate server rules (#34637, #34737, #34494, #34756, and #34820 by @ChaosExAnima and @ClearlyClaire)\
Rules are now shown in the users language, if a translation has been set.\
In the REST API, `Rule` entities now have a new `translations` attribute: https://docs.joinmastodon.org/entities/Rule/#translations
- Add emoji from Twemoji 15.1.0, including in the emoji picker/completion (#33395, #34321, #34620, and #34677 by @ChaosExAnima, @ClearlyClaire, @TheEssem, and @eramdam)
- Add experimental support for verifying and displaying remote quote posts (#34370, #34481, #34510, #34551, #34480, #34479, #34553, #34584, #34623, #34738, #34766, #34770, #34772, #34773, #34786, #34790, and #34864 by @ClearlyClaire and @diondiondion)\
Support for verifying remote quotes according to [FEP-044f](https://codeberg.org/fediverse/fep/src/branch/main/fep/044f/fep-044f.md) and displaying them in the Web UI has been implemented. Such quotes are currently only processed if the `inbound_quotes` experimental feature is enabled (`EXPERIMENTAL_FEATURES=inbound_quotes`).\
Quoting other people is not implemented yet, and it is currently not possible to mark your own posts as allowing quotes. However, a new “Who can quote” setting has been added to the “Posting defaults” section of the user settings. This setting allows you to set a default that will be used for new posts made on Mastodon 4.5 and newer, when quote posts will be fully implemented.\
In the REST API, quote posts are represented by a new `quote` attribute on `Status` and `StatusEdit` entities: https://docs.joinmastodon.org/entities/StatusEdit/#quote https://docs.joinmastodon.org/entities/Status/#quote
- Add option to remove account from followers in web UI (#34488 by @Gargron)
- Add relationship tags to profiles and hover cards in web UI (#34467 and #34792 by @Gargron and @diondiondion)
- Add ability to open posts in a new tab by middle-clicking in web UI (#32988, #33106, #33419, and #34700 by @ClearlyClaire, @Gargron, and @tribela)
- Add new filter action to blur media (#34256 by @ClearlyClaire)\
In the REST API, this adds a new possible value of `blur` to the `filter_action` attribute: https://docs.joinmastodon.org/entities/Filter/#filter_action
- Add dropdown menu to hashtag links in web UI (#34393 by @Gargron)
- **Add server setting to allow referrer** (#33214, #33239, #33903, and #34731 by @ChaosExAnima, @ClearlyClaire, @Gargron, and @renchap)\
In order to protect the privacy of users of small or thematic servers, Mastodon previously avoided transmitting referrer information when clicking outside links, which unfortunately made Mastodon completely invisible to other websites, even though the privacy implications on large generic servers are very limited.\
Server administrators can now chose to opt in to transmit referrer information when following an external link. Only the domain name is transmitted, not the referrer path.
- Add double tap to zoom and swipe to dismiss to media modal in web UI (#34210 by @Gargron)
- Add link from Web UI for Hashtags to the Moderation UI (#31448 by @ThisIsMissEm)
- **Add terms of service** (#33055, #33233, #33230, #33703, #33699, #33994, #33993, #34105, #34122, #34200, and #34527 by @ClearlyClaire, @Gargron, @mjankowski, and @oneiros)\
Server administrators can now fill in Terms of Service, optionally using a provided template.
- **Add age verification on sign-up** (#34150, #34663, and #34636 by @ClearlyClaire and @Gargron)\
Server administrators now have a setting to set a minimum age requirement for creating a new server, asking users for their date of birth. The date of birth is checked against the minimum age requirement server-side but not stored.\
The following REST API changes have been made to accommodate this:
- `registrations.min_age` has been added to the `Instance` entity: https://docs.joinmastodon.org/entities/Instance/#registrations-min_age
- the `date_of_birth` parameter has been added to the account creation API: https://docs.joinmastodon.org/methods/accounts/#create
- Add ability to dismiss alt text badge by tapping it in web UI (#33737 by @Gargron)
- Add loading indicator to timeline gap indicators in web UI (#33762 by @Gargron)
- Add interaction modal when trying to interact with a poll while logged out (#32609 by @ThisIsMissEm)
- **Add experimental FASP support** (#34031, #34415, and #34765 by @oneiros)\
This is a first step towards supporting “Fediverse Auxiliary Service Providers” (https://github.com/mastodon/fediverse_auxiliary_service_provider_specifications). This is mostly interesting to developers who would like to implement their own FASP, but also includes the capability to share data with a discovery provider (see https://www.fediscovery.org).
- Add ability for admins to send announcements to all users via email (#33928 and #34411 by @ClearlyClaire)\
This is meant for critical announcements only, as this will potentially send a lot of emails and cannot be opted out of by users.
- Add option to use system scrollbar styling (#32117 by @vmstan)
- Add hover cards to follow suggestions (#33749 by @ClearlyClaire)
- Add `t` hotkey for post translations (#33441 by @ClearlyClaire)
- Add timestamp to all announcements in Web UI (#18329 by @ClearlyClaire)
- Add dropdown menu with quick actions to lists of accounts in web UI (#34391, #34709, and #34767 by @Gargron, @diondiondion, and @mkljczk)
- Add support for displaying “year in review” notification in web UI (#32710, #32765, #32709, #32807, #32914, #33148, and #33882 by @Gargron and @mjankowski)\
Note that the notification is currently not generated automatically, and at the moment requires a manual undocumented administrator action.
- Add experimental support for receiving HTTP Message Signatures (RFC9421) (#34814 by @oneiros)\
For now, this needs to be explicitly enabled through the `http_message_signatures` feature flag (`EXPERIMENTAL_FEATURES=http_message_signatures`). This currently only covers verifying such signatures (inbound HTTP requests), not issuing them (outbound HTTP requests).
- Add experimental server-side feature to fetch remote replies (#32615, #34147, #34149, #34151, #34615, #34682, and #34702 by @ClearlyClaire and @sneakers-the-rat)\
This experimental feature causes the server to recursively fetch replies in background tasks whenever a user opens a remote post. This happens asynchronously and the client is currently not notified of the existence of new replies, which will thus only be displayed the next time this posts context gets requested.\
This feature needs to be explicitly enabled server-side by setting `FETCH_REPLIES_ENABLED` environment variable to `true`.
- Add simple feature flag system through the `EXPERIMENTAL_FEATURES` environment variable (#34038 and #34124 by @oneiros)\
This allows enabling comma-separated feature flags for experimental features.\
The current supported feature flags are `inbound_quotes`, `fasp` and `http_message_signatures`.
- Add `dev:populate_sample_data` rake task to populate test data (#34676, #34733, #34771, #34787, and #34791 by @ClearlyClaire and @diondiondion)
- Add support for displaying fallback representation when receiving MathML (#27107 by @4e554c4c)
- Add warning for Elasticsearch index analyzers mismatch (#34515 and #34567 by @ClearlyClaire and @Gargron)
- Add `-only-mapping` option to `tootctl search deploy` (#34466 and #34566 by @Gargron)
- Add server-side support for grouping account sign-up notifications (#34298 by @ClearlyClaire)
- Add `registrations.reason_required` attribute to `/api/v2/instance` response (#34280 by @ClearlyClaire)\
This is documented at https://docs.joinmastodon.org/entities/Instance/#registrations-reason_required
- Add `EXTRA_MEDIA_HOSTS` environment variable to add extra hosts to Content-Security-Policy (#34184 by @shleeable)
- Add `Deprecation` headers on deprecated API endpoints (#34262 and #34397 by @ClearlyClaire)\
This is documented at https://docs.joinmastodon.org/api/guidelines/#deprecations
- Add `about`, `privacy_policy` and `terms_of_service` URLs to `/api/v2/instance` (#33849 by @ClearlyClaire)
- Add API to delete media attachments that are not in use (#33991 and #34035 by @ClearlyClaire and @ThisIsMissEm)\
`DELETE /api/v1/media/:id`: https://docs.joinmastodon.org/methods/media/#delete
- Add optional `delete_media` parameter to `DELETE /api/v1/statuses/:id` (#33988 by @ClearlyClaire)\
This is documented at https://docs.joinmastodon.org/methods/statuses/#delete
- Add `og:locale` to expose status language in OpenGraph previews (#34012 by @ThisIsMissEm)
- Add `-skip-filled-timeline` option to `tootctl feed build` to skip half-filled feeds (#33844 by @ClearlyClaire)
- Add support for changing the base Docker registry with the `BASE_REGISTRY` `ARG` (#33712 by @wolfspyre)
- Add an optional metric exporter (#33734, #33840, #34172, #34192, 34223)\
Optionally enable the `prometheus_exporter` ruby gem (see https://github.com/discourse/prometheus_exporter) to collect and expose metrics. See the documentation for all the details: https://docs.joinmastodon.org/admin/config/#prometheus
- Add `attribution_domains` attribute to `PATCH /api/v1/accounts/update_credentials` (#32730 by @c960657)\
This is documented at https://docs.joinmastodon.org/methods/accounts/#update_credentials
- Add support for standard WebPush in addition to previous draft (#33572, #33528, and #33587 by @ClearlyClaire and @p1gp1g)
- Add support for Active Record query log tags (#33342 by @renchap)
- Add OTel trace & span IDs to logs (#33339 and #33362 by @renchap)
- Add missing `on_delete: :cascade` foreign keys option to various database columns (#33175 by @mjankowski)
- Add explicit migration breakpoints (#33089 by @ClearlyClaire)
- Add rel alternate rss/json links to pages for tags (#33179 by @mjankowski)
- Add media attachment description limit to instance API response (#33153 by @mjankowski)\
This adds the `configuration.media_attachments.description_limit` attribute to the `Instance` entity, documented at https://docs.joinmastodon.org/entities/Instance/#description_limit
- Add `maxlength` to registration reason input (#33162 by @mjankowski)
- Add `REPLICA_PREPARED_STATEMENTS` and `REPLICA_DB_TASKS` environment variables (#32908 by @shleeable)\
See documentation at https://docs.joinmastodon.org/admin/scaling/#read-replicas
- Add a range of reserved usernames to reduce potential misuse by malicious actors (#32828 by @jmking-iftas)
- Add operations on relays to the admin audit log (#32819 by @ThisIsMissEm)
- Add userinfo OAuth endpoint (#32548 by @ThisIsMissEm)
- Add the standard VCS attributes to OpenTelemetry spans (#32904 by @renchap)
- Add endpoint to remove web push subscription (#32626 by @oneiros)\
Mastodon now sets a new `Unsubscribe-URL` request header when performing WebPush requests. This URL can be used by the WebPush server to disable the WebPush subscription on Mastodons side in case of unfixable errors.
- Add missing content warning text to RSS feeds (#32406 by @mjankowski)
- Add Swiss German to languages dropdown (#29281 by @FlohEinstein)
### Changed
- Change design of lists in web UI (#32881, #33054, and #33036 by @Gargron)
- Change design of edit media modal in web UI (#33516, #33702, #33725, #33725, #33771, and #34345 by @Gargron)
- Change design of audio player in web UI (#34520, #34740, and #34865 by @ClearlyClaire, @Gargron, and @diondiondion)
- Change design of interaction modal in web UI (#33278 by @Gargron)
- Change list timelines to reflect added and removed users retroactively (#32930 by @Gargron)
- Change account search to be more forgiving of spaces (#34455 by @Gargron)
- Change unfollow button label from “Mutual” to “Unfollow” in web UI (#34392 by @Gargron)
- Change “Specific people” to “Private mention” in menu in web UI (#33963 by @Gargron)
- Change language names in compose box language picker to be localized (#33402 by @c960657)
- Change onboarding flow in web UI (#32998, #33119, and #33471 by @ClearlyClaire and @Gargron)
- Change emoji categories in admin interface to be ordered by name (#33630 by @ShadowJonathan)
- Change design of rich text elements in web UI (#32633 by @Gargron)
- Change wording of “single choice” to “pick one” in poll authoring form (#32397 by @ThisIsMissEm)
- Change returned favorite and boost counts to use those provided by the remote server, if available (#32620, #34594, #34618, and #34619 by @ClearlyClaire and @sneakers-the-rat)
- Change label of favourite notifications on private mentions (#31659 by @ClearlyClaire)
- Change `libvips` to be enabled by default in place of ImageMagick (#34741 and #34753 by @ClearlyClaire and @diondiondion)
- Change avatar and header size limits from 2MB to 8MB when using libvips (#33002 by @Gargron)
- Change search to use query params in web UI (#32949 and #33670 by @ClearlyClaire and @Gargron)
- Change build system from Webpack to Vite (#34454, #34450, #34758, #34768, #34813, #34808, #34837, and #34732 by @ChaosExAnima, @ClearlyClaire, @mjankowski, and @renchap)\
One known limitation is that themes main style file needs to have a very specific file name: `app/javascript/styles/:name.scss` where `:name` is the name of the theme in `config/themes.yml`
- Change account creation API to forbid creation from user tokens (#34828 by @ThisIsMissEm)
- Change `/api/v2/instance` to be enabled without authentication when limited federation mode is enabled (#34576 by @ClearlyClaire)
- Change `DEFAULT_LOCALE` to not override unauthenticated users browser language (#34535 by @ClearlyClaire)\
If you want to preserve the old behavior, you can add `FORCE_DEFAULT_LOCALE=true`.
- Change size of profile picture on profile page from 90px to 92px (#34807 by @larouxn)
- Change passthrough video processing to emit `moov` atom at start of video (#34726 by @ClearlyClaire)
- Change kerning to be disabled for Japanese text to preserve monospaced alignment for readability (#34448 by @nagutabby)
- Change error handling of various endpoints to return 422 instead of 500 on invalid parameters (#29308, #34434, and #34452 by @danielmbrasil and @mjankowski)
- Change Web UI to use `<time>` tags for various timestamps (#34131 by @scarf005)
- Change devcontainer to be accessible from local network (#34269 by @ChaosExAnima)
- Change video transcoding code to skip re-encoding yuvj420p videos (#34098 by @rinsuki)
- Change web client settings to be saved earlier and more often (#34074 by @ClearlyClaire)
- Change test coverage report generation to be disabled by default, with opt-in through the `COVERAGE` environment variable (#33824 by @mjankowski)
- Change devcontainer to store bootsnap cache outside of bind mounts (#33677 by @c960657)
- Change error handling in the `mastodon:setup` rake task to summarize encountered errors at the end (#33603 by @mjankowski)
- Change tooltip of some moderation interface timestamps to include time in addition to date (#33191 by @ThisIsMissEm)
- Change organization and wording of `README.md`, `CONTRIBUTING.md` and `DEVELOPMENT.md` (#32143, #33328, #33517, #33637, #33728, #34675, and #34761 by @Lamparter, @andypiper, @diondiondion, @larouxn, @mikkelricky, and @mjankowski)
- Change custom CSS to be cached for longer and invalidated based on its contents (#33207 and #33583 by @mjankowski and @tribela)
- Change `tootctl maintenance fix-duplicates` to disable database statement timeouts (#33484 by @mjankowski)
- Change some icons in settings sidebar to avoid “double icon” near each other (#33449 by @mjankowski)
- Change animation on feed generation screen in web UI (#33311 by @Gargron)
- Change OTel instrumentation to not start traces with Redis spans (#33090 by @robbkidd)
- Change new post delivery to skip suspended followers (#27509 and #33030 by @ClearlyClaire and @oneiros)
- Change URL truncation to account for ellipses (#33229 by @FND)
- Change ability to navigate of unconfirmed users (#33209 by @Gargron)
- Change hashtag trends to be stored in the database instead of redis (#32837, #33189, and #34016 by @Gargron and @onekopaka)
- Change “social web” to “fediverse” in a few banners in web UI (#33101 by @Gargron)
- Change server rules to be collapsible (#33039 by @Gargron)
- Change design of modal loading and error screens in web UI (#33092 by @Gargron)
- Change error messages to be more accurate when failing to add an account to a list (#33082 by @Gargron)
- Change timezone picker in the default settings to show the default timezone (#31803 by @c960657)
- Change `tootctl accounts modify --disable-2fa` to remove webauthn credentials (#29883 by @mszpro)
- Change preview card processing to be more liberal in what it accepts (#31357 by @c960657)
- Change scheduled statuses to be discarded if the authors account is frozen (#30729 by @PauloVilarinho)
- Change display of statuses in admin panel (#30813 by @ThisIsMissEm)
- Change parsing of `ALLOWED_PRIVATE_ADDRESSES` to happen at startup (#32850 by @ClearlyClaire)
- Change WebPush delivery to skip notifications older than 2 days old (#32842 by @ThisIsMissEm)
- Change PWA manifest to prefer official mobile apps (#27254 by @jake-anto)
### Removed
- **Remove support for Redis namespaces** (#34664 and #34665 by @ClearlyClaire)\
See https://github.com/mastodon/redis_namespace_migration
- Remove support for imports started on pre-4.2.0 Mastodon versions (#34371 by @mjankowski)
- Remove support for PostgreSQL 12 and earlier (#34744 by @ClearlyClaire)
- Remove support for Node.JS < 20 (#34390 by @renchap)
- Remove support for Redis < 6.2 (#30413 by @ClearlyClaire)
- Remove support for Ruby 3.1 (#32363 by @mjankowski)
- Remove support for OAuth Password Grant Type (#30960 by @ThisIsMissEm)\
https://docs.joinmastodon.org/spec/oauth/#token
- Remove `OTP_SECRET` environment variable and legacy OTP code (#34743, #34757, #34748, and #34810 by @ClearlyClaire and @mjankowski)\
This breaks zero-downtime migrations from versions earlier than 4.3.0.
- Remove broken support for HTTP Basic Authentication (#34501 by @ThisIsMissEm)
- Remove system tooltip for alt text in web UI (#33736 by @Gargron)
- Remove `thing_type` and `thing_id` columns from settings table (#31971 and #33196 by @ClearlyClaire and @mjankowski)
- Remove redundant temporary index creation in `tootctl status remove` (#33023 by @ClearlyClaire)
- Remove duplicate indexes from database (#32454 by @mjankowski)
- Remove redundant title attribute in column links (#32258 by @c960657)
### Fixed
- Fix remote suspension of a user causing local instance to remove remote follows (#27588 by @ShadowJonathan)
- Fix blocked accounts not being automatically removed from trending statuses (#34891 by @ClearlyClaire)
- Fix nested buttons in search popout in web UI (#34871 by @Gargron)
- Fix not being able to scroll dropdown on touch devices in web UI (#34873 by @Gargron)
- Fix inconsistent filtering of silenced accounts for other silenced accounts (#34863 by @ClearlyClaire)
- Fix update checker listing updates older or equal to current running version (#33906 by @ClearlyClaire)
- Fix `NoMethodError` in edge case of emoji cache handling (#34749 by @dariusk)
- Fix handling of inlined `featured` collections in ActivityPub actor objects (#34789 and #34811 by @ClearlyClaire)
- Fix long link names in admin sidebar being truncated (#34727 by @diondiondion)
- Fix admin dashboard crash on specific Elasticsearch connection errors (#34683 by @ClearlyClaire)
- Fix OIDC account creation failing for long display names (#34639 by @defnull)
- Fix use of the deprecated `/api/v1/instance` endpoint in the moderation interface (#34613 by @renchap)
- Fix directory scroll position reset (#34560 by @przucidlo)
- Fix needlessly complex SVG paths for oEmbed and logo (#34538 by @edent)
- Fix avatar sizing with long account name in some UI elements (#34514 by @gomasy)
- Fix empty menu section in status dropdown (#34431 by @ClearlyClaire)
- Fix the delete suggestion button not working (#34396 and #34398 by @ClearlyClaire and @renchap)
- Fix radio buttons not always being correctly centered (#34389 by @ChaosExAnima)
- Fix visual glitches with adding post filters (#34387 by @ChaosExAnima)
- Fix bugs with upload progress (#34325 by @ChaosExAnima)
- Fix being unable to hide controls in full screen video in web UI (#34308 by @Gargron)
- Fix extra space under left-indented vertical videos (#34313 by @ClearlyClaire)
- Fix SASS deprecation notices (#34278 by @ChaosExAnima)
- Fix display of failed-to-load image attachments in web UI (#34217 by @Gargron)
- Fix duplicate REST API requests on submitting account personal note with ctrl+enter (#34213 by @ClearlyClaire)
- Fix unnecessary rerenders in composer dropdown menu (#34133 by @ClearlyClaire)
- Fix behavior of database schema loading with `SKIP_POST_DEPLOYMENT_MIGRATIONS` (#34089 by @ClearlyClaire)
- Fix infinite scroll not working on profile media tab in web UI (#33860 and #34171 by @ClearlyClaire and @Gargron)
- Fix minor inefficiencies in domain suspension code (#33897 by @larouxn)
- Fix potential inefficiency in media privacy system check (#33858 by @ClearlyClaire)
- Fix public timeline inefficiency by adding the `language` column to the public timelines index (#33779 by @ClearlyClaire)
- Fix re-encoding of high-framerate VFR videos with FFmpeg 6+ (#33634 by @ClearlyClaire)
- Fix error when processing invalid `Announce` activity with missing object (#33570 by @ShadowJonathan)
- Fix color contrast in report modal (#33468 by @ClearlyClaire)
- Fix error 500 when passing an invalid `lang` parameter (#33467 by @ClearlyClaire)
- Fix `/share` not using server-set characters limit (#33459 by @kescherCode)
- Fix audio player modal having white-on-white buttons in light theme (#33444 by @ClearlyClaire)
- Fix favorite & bookmark text toggle in timeline, status and image view (#27209 by @gunchleoc)
- Fix Web UI erroneously stopping to offer expanding search results after second page (#33428 by @ClearlyClaire)
- Fix missing value limits for `UserRole` position (#33172 and #33349 by @mjankowski)
- Fix clicking on a profile mention while logged out potentially leading to incorrect account (#33324 by @ClearlyClaire)
- Fix missing `NOT NULL` constraints on various database columns (#33244, #33284, #33308, #33330, #33374, and #34498 by @ClearlyClaire and @mjankowski)
- Fix long account username overflowing on profiles (#33286 by @mjankowski)
- Fix Vagrant failure to sync dangling symlinks (#28101 by @filippog)
- Fix Chromium showing scrollbar on embedded posts (#33237 by @ClearlyClaire)
- Fix missing top border on Admin Hashtags UI (#31443 by @ThisIsMissEm)
- Fix design of search bar on explore screen in light theme in web UI (#33224 by @Gargron)
- Fix various visual sign-up flow issues (#33206 by @Gargron)
- Fix support of bidi text in account profiles (#33088 by @mokazemi)
- Fix wording of the error returned when scheduling a status too soon (#33156 by @mjankowski)
- Fix `inbox_url` presence on Relay not being validated (#32364 by @mjankowski)
- Fix ability to include multiple copies of `embed.js` (#33107 by @YKWeyer)
- Fix `rel="me"` check being case-sensitive (#32238 by @c960657)
- Fix wrong video dimensions for some rotated videos (#33008 and #33261 by @Gargron and @tribela)
- Fix error when viewing statuses to deleted replies in moderation view (#32986 by @ClearlyClaire)
- Fix missing autofocus on boost modal (#32953 by @tribela)
- Fix logic in “last used at per application” OAuth token list (#32912 by @mjankowski)
- Fix admin dashboard linking to pages the user does not have permission to see (#32843 by @ThisIsMissEm)
- Fix backspace navigation hotkey going back two pages instead of one on some browsers (#32826 by @c960657)
- Fix typo in translation string (#32821 by @ThisIsMissEm)
- Fix list of follow requests not having a back button (#32797 by @ClearlyClaire)
- Fix out-of-view post contents being inconsistent with in-view post contents (#32778, #32887, and #32895 by @ClearlyClaire)
- Fix `httplog` gem being used in production (#32776 and #32796 by @ClearlyClaire and @oneiros)
- Fix use of deprecated `execCommand` for copying text by using the `clipboard` API (#32598 by @renchap)
- Fix some translation strings not being properly pluralized (#27094 by @gunchleoc)
## [4.3.8] - 2025-05-06
### Security
- Update dependencies
- Check scheme on account, profile, and media URLs ([GHSA-x2rc-v5wx-g3m5](https://github.com/mastodon/mastodon/security/advisories/GHSA-x2rc-v5wx-g3m5))
### Added
- Add warning for REDIS_NAMESPACE deprecation at startup (#34581 by @ClearlyClaire)
- Add built-in context for interaction policies (#34574 by @ClearlyClaire)
### Changed
- Change activity distribution error handling to skip retrying for deleted accounts (#33617 by @ClearlyClaire)
### Removed
- Remove double-query for signed query strings (#34610 by @ClearlyClaire)
### Fixed
- Fix incorrect redirect in response to unauthenticated API requests in limited federation mode (#34549 by @ClearlyClaire)
- Fix sign-up e-mail confirmation page reloading on error or redirect (#34548 by @ClearlyClaire)
## [4.3.7] - 2025-04-02
### Add
### Added
- Add delay to profile updates to debounce them (#34137 by @ClearlyClaire)
- Add support for paginating partial collections in `SynchronizeFollowersService` (#34272 and #34277 by @ClearlyClaire)

View file

@ -13,7 +13,7 @@ ARG BASE_REGISTRY="docker.io"
# Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.4.x"]
# renovate: datasource=docker depName=docker.io/ruby
ARG RUBY_VERSION="3.4.2"
ARG RUBY_VERSION="3.4.4"
# # Node.js version to use in base image, change with [--build-arg NODE_MAJOR_VERSION="20"]
# renovate: datasource=node-version depName=node
ARG NODE_MAJOR_VERSION="22"
@ -186,7 +186,7 @@ FROM build AS libvips
# libvips version to compile, change with [--build-arg VIPS_VERSION="8.15.2"]
# renovate: datasource=github-releases depName=libvips packageName=libvips/libvips
ARG VIPS_VERSION=8.16.1
ARG VIPS_VERSION=8.17.0
# libvips download URL, change with [--build-arg VIPS_URL="https://github.com/libvips/libvips/releases/download"]
ARG VIPS_URL=https://github.com/libvips/libvips/releases/download

View file

@ -13,6 +13,7 @@
- [FEP-f1d5: NodeInfo in Fediverse Software](https://codeberg.org/fediverse/fep/src/branch/main/fep/f1d5/fep-f1d5.md)
- [FEP-8fcf: Followers collection synchronization across servers](https://codeberg.org/fediverse/fep/src/branch/main/fep/8fcf/fep-8fcf.md)
- [FEP-5feb: Search indexing consent for actors](https://codeberg.org/fediverse/fep/src/branch/main/fep/5feb/fep-5feb.md)
- [FEP-044f: Consent-respecting quote posts](https://codeberg.org/fediverse/fep/src/branch/main/fep/044f/fep-044f.md): partial support for incoming quote-posts
## ActivityPub in Mastodon

28
Gemfile
View file

@ -5,7 +5,6 @@ ruby '>= 3.2.0', '< 3.5.0'
gem 'propshaft'
gem 'puma', '~> 6.3'
gem 'rack', '~> 2.2.7'
gem 'rails', '~> 8.0'
gem 'thor', '~> 1.2'
@ -52,8 +51,9 @@ gem 'faraday-httpclient'
gem 'fast_blank', '~> 1.0'
gem 'fastimage'
gem 'hiredis', '~> 0.6'
gem 'hiredis-client'
gem 'htmlentities', '~> 4.3'
gem 'http', '~> 5.2.0'
gem 'http', '~> 5.3.0'
gem 'http_accept_language', '~> 2.1'
gem 'httplog', '~> 1.7.0', require: false
gem 'i18n'
@ -62,9 +62,9 @@ gem 'inline_svg'
gem 'irb', '~> 1.8'
gem 'kaminari', '~> 1.2'
gem 'link_header', '~> 0.0'
gem 'linzer', '~> 0.6.1'
gem 'linzer', '~> 0.7.2'
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
gem 'mime-types', '~> 3.6.0', require: 'mime/types/columnar'
gem 'mime-types', '~> 3.7.0', require: 'mime/types/columnar'
gem 'mutex_m'
gem 'nokogiri', '~> 1.15'
gem 'oj', '~> 3.14'
@ -74,19 +74,18 @@ gem 'premailer-rails'
gem 'public_suffix', '~> 6.0'
gem 'pundit', '~> 2.3'
gem 'rack-attack', '~> 6.6'
gem 'rack-cors', '~> 2.0', require: 'rack/cors'
gem 'rack-cors', require: 'rack/cors'
gem 'rails-i18n', '~> 8.0'
gem 'redcarpet', '~> 3.6'
gem 'redis', '~> 4.5', require: ['redis', 'redis/connection/hiredis']
gem 'redis-namespace', '~> 1.10'
gem 'rqrcode', '~> 2.2'
gem 'rqrcode', '~> 3.0'
gem 'ruby-progressbar', '~> 1.13'
gem 'sanitize', '~> 7.0'
gem 'scenic', '~> 1.7'
gem 'sidekiq', '~> 6.5'
gem 'sidekiq', '< 8'
gem 'sidekiq-bulk', '~> 0.2.0'
gem 'sidekiq-scheduler', '~> 5.0'
gem 'sidekiq-unique-jobs', '~> 7.1'
gem 'sidekiq-unique-jobs', '> 8'
gem 'simple_form', '~> 5.2'
gem 'simple-navigation', '~> 4.4'
gem 'stoplight', '~> 4.1'
@ -95,7 +94,6 @@ gem 'tty-prompt', '~> 0.23', require: false
gem 'twitter-text', '~> 3.1.0'
gem 'tzinfo-data', '~> 1.2023'
gem 'webauthn', '~> 3.0'
gem 'webpacker', '~> 5.4'
gem 'webpush', github: 'mastodon/webpush', ref: '9631ac63045cfabddacc69fc06e919b4c13eb913'
gem 'json-ld'
@ -112,7 +110,7 @@ group :opentelemetry do
gem 'opentelemetry-instrumentation-active_model_serializers', '~> 0.22.0', require: false
gem 'opentelemetry-instrumentation-concurrent_ruby', '~> 0.22.0', require: false
gem 'opentelemetry-instrumentation-excon', '~> 0.23.0', require: false
gem 'opentelemetry-instrumentation-faraday', '~> 0.26.0', require: false
gem 'opentelemetry-instrumentation-faraday', '~> 0.27.0', require: false
gem 'opentelemetry-instrumentation-http', '~> 0.24.0', require: false
gem 'opentelemetry-instrumentation-http_client', '~> 0.23.0', require: false
gem 'opentelemetry-instrumentation-net_http', '~> 0.23.0', require: false
@ -139,7 +137,7 @@ group :test do
# Browser integration testing
gem 'capybara', '~> 3.39'
gem 'selenium-webdriver'
gem 'capybara-playwright-driver'
# Used to reset the database between system tests
gem 'database_cleaner-active_record'
@ -203,7 +201,7 @@ group :development, :test do
gem 'faker', '~> 3.2'
# Generate factory objects
gem 'fabrication', '~> 2.30'
gem 'fabrication'
# Profiling tools
gem 'memory_profiler', require: false
@ -212,7 +210,7 @@ group :development, :test do
gem 'test-prof', require: false
# RSpec runner for rails
gem 'rspec-rails', '~> 7.0'
gem 'rspec-rails', '~> 8.0'
end
group :production do
@ -230,3 +228,5 @@ gem 'rubyzip', '~> 2.3'
gem 'hcaptcha', '~> 7.1'
gem 'mail', '~> 2.8'
gem 'vite_rails', '~> 3.0.19'

View file

@ -90,11 +90,11 @@ GEM
public_suffix (>= 2.0.2, < 7.0)
aes_key_wrap (1.1.0)
android_key_attestation (0.3.0)
annotaterb (4.14.0)
annotaterb (4.15.0)
ast (2.4.3)
attr_required (1.0.2)
aws-eventstream (1.3.2)
aws-partitions (1.1087.0)
aws-partitions (1.1103.0)
aws-sdk-core (3.215.1)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.992.0)
@ -109,9 +109,9 @@ GEM
aws-sigv4 (~> 1.5)
aws-sigv4 (1.11.0)
aws-eventstream (~> 1, >= 1.0.2)
azure-blob (0.5.7)
azure-blob (0.5.8)
rexml
base64 (0.2.0)
base64 (0.3.0)
bcp47_spec (0.2.1)
bcrypt (3.1.20)
benchmark (0.4.0)
@ -124,14 +124,11 @@ GEM
binding_of_caller (1.0.1)
debug_inspector (>= 1.2.0)
blurhash (0.1.8)
bootsnap (1.18.4)
bootsnap (1.18.6)
msgpack (~> 1.2)
brakeman (7.0.2)
racc
browser (6.2.0)
brpoplpush-redis_script (0.1.3)
concurrent-ruby (~> 1.0, >= 1.0.5)
redis (>= 1.0, < 6)
builder (3.3.0)
bundler-audit (0.9.2)
bundler (>= 1.2.0, < 3)
@ -145,9 +142,14 @@ GEM
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
capybara-playwright-driver (0.5.6)
addressable
capybara
playwright-ruby-client (>= 1.16.0)
case_transform (0.2)
activesupport
cbor (0.5.9.8)
cgi (0.4.2)
charlock_holmes (0.7.9)
chewy (7.6.0)
activesupport (>= 5.2)
@ -160,7 +162,7 @@ GEM
cocoon (1.2.15)
color_diff (0.1)
concurrent-ruby (1.3.5)
connection_pool (2.5.0)
connection_pool (2.5.3)
cose (1.3.1)
cbor (~> 0.5.9)
openssl-signature_algorithm (~> 1.0)
@ -170,8 +172,8 @@ GEM
crass (1.0.6)
css_parser (1.21.1)
addressable
csv (3.3.4)
database_cleaner-active_record (2.2.0)
csv (3.3.5)
database_cleaner-active_record (2.2.1)
activerecord (>= 5.a)
database_cleaner-core (~> 2.0.0)
database_cleaner-core (2.0.1)
@ -194,7 +196,7 @@ GEM
devise_pam_authenticatable2 (9.2.0)
devise (>= 4.0.0)
rpam2 (~> 4.0)
diff-lcs (1.6.1)
diff-lcs (1.6.2)
discard (1.4.0)
activerecord (>= 4.2, < 9.0)
docile (1.4.1)
@ -202,7 +204,8 @@ GEM
doorkeeper (5.8.2)
railties (>= 5)
dotenv (3.1.8)
drb (2.2.1)
drb (2.2.3)
dry-cli (1.2.0)
elasticsearch (7.17.11)
elasticsearch-api (= 7.17.11)
elasticsearch-transport (= 7.17.11)
@ -224,10 +227,10 @@ GEM
tzinfo
excon (1.2.5)
logger
fabrication (2.31.0)
fabrication (3.0.0)
faker (3.5.1)
i18n (>= 1.8.11, < 2)
faraday (2.13.0)
faraday (2.13.1)
faraday-net_http (>= 2.0, < 3.5)
json
logger
@ -261,15 +264,16 @@ GEM
fog-core (~> 2.1)
fog-json (>= 1.0)
formatador (1.1.0)
forwardable (1.3.3)
fugit (1.11.1)
et-orbi (~> 1, >= 1.2.11)
raabro (~> 1.4)
globalid (1.2.1)
activesupport (>= 6.1)
google-protobuf (4.30.2)
google-protobuf (4.31.0)
bigdecimal
rake (>= 13)
googleapis-common-protos-types (1.19.0)
googleapis-common-protos-types (1.20.0)
google-protobuf (>= 3.18, < 5.a)
haml (6.3.0)
temple (>= 0.8.2)
@ -293,11 +297,12 @@ GEM
highline (3.1.2)
reline
hiredis (0.6.3)
hiredis-client (0.24.0)
redis-client (= 0.24.0)
hkdf (0.3.0)
htmlentities (4.3.4)
http (5.2.0)
http (5.3.1)
addressable (~> 2.8)
base64 (~> 0.1)
http-cookie (~> 1.0)
http-form_data (~> 2.2)
llhttp-ffi (~> 0.5.0)
@ -337,7 +342,7 @@ GEM
azure-blob (~> 0.5.2)
hashie (~> 5.0)
jmespath (1.6.2)
json (2.10.2)
json (2.12.2)
json-canonicalization (1.0.0)
json-jwt (1.16.7)
activesupport (>= 4.2)
@ -381,7 +386,7 @@ GEM
marcel (~> 1.0.1)
mime-types
terrapin (>= 0.6.0, < 2.0)
language_server-protocol (3.17.0.4)
language_server-protocol (3.17.0.5)
launchy (3.1.1)
addressable (~> 2.8)
childprocess (~> 5.0)
@ -395,7 +400,11 @@ GEM
rexml
link_header (0.0.8)
lint_roller (1.1.0)
linzer (0.6.5)
linzer (0.7.3)
cgi (~> 0.4.2)
forwardable (~> 1.3, >= 1.3.3)
logger (~> 1.7, >= 1.7.0)
net-http (~> 0.6.0)
openssl (~> 3.0, >= 3.0.0)
rack (>= 2.2, < 4.0)
starry (~> 0.2)
@ -410,7 +419,7 @@ GEM
activesupport (>= 4)
railties (>= 4)
request_store (~> 1.0)
loofah (2.24.0)
loofah (2.24.1)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.8.1)
@ -423,19 +432,19 @@ GEM
redis (>= 3.0.5)
matrix (0.4.2)
memory_profiler (1.1.0)
mime-types (3.6.2)
mime-types (3.7.0)
logger
mime-types-data (~> 3.2015)
mime-types-data (3.2025.0408)
mime-types-data (~> 3.2025, >= 3.2025.0507)
mime-types-data (3.2025.0514)
mini_mime (1.1.5)
mini_portile2 (2.8.8)
mini_portile2 (2.8.9)
minitest (5.25.5)
msgpack (1.8.0)
multi_json (1.15.0)
mutex_m (0.3.0)
net-http (0.6.0)
uri
net-imap (0.5.6)
net-imap (0.5.8)
date
net-protocol
net-ldap (0.19.0)
@ -446,10 +455,10 @@ GEM
net-smtp (0.5.1)
net-protocol
nio4r (2.7.4)
nokogiri (1.18.7)
nokogiri (1.18.8)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
oj (3.16.10)
oj (3.16.11)
bigdecimal (>= 3.0)
ostruct (>= 0.2)
omniauth (2.1.3)
@ -463,7 +472,7 @@ GEM
omniauth-rails_csrf_protection (1.0.2)
actionpack (>= 4.2)
omniauth (~> 2.0)
omniauth-saml (2.2.3)
omniauth-saml (2.2.4)
omniauth (~> 2.1)
ruby-saml (~> 1.18)
omniauth_openid_connect (0.8.0)
@ -495,13 +504,15 @@ GEM
opentelemetry-common (~> 0.20)
opentelemetry-sdk (~> 1.2)
opentelemetry-semantic_conventions
opentelemetry-helpers-sql (0.1.1)
opentelemetry-api (~> 1.0)
opentelemetry-helpers-sql-obfuscation (0.3.0)
opentelemetry-common (~> 0.21)
opentelemetry-instrumentation-action_mailer (0.4.0)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-active_support (~> 0.7)
opentelemetry-instrumentation-base (~> 0.23.0)
opentelemetry-instrumentation-action_pack (0.12.0)
opentelemetry-instrumentation-action_pack (0.12.1)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.23.0)
opentelemetry-instrumentation-rack (~> 0.21)
@ -536,7 +547,7 @@ GEM
opentelemetry-instrumentation-excon (0.23.0)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.23.0)
opentelemetry-instrumentation-faraday (0.26.0)
opentelemetry-instrumentation-faraday (0.27.0)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.23.0)
opentelemetry-instrumentation-http (0.24.0)
@ -548,8 +559,9 @@ GEM
opentelemetry-instrumentation-net_http (0.23.0)
opentelemetry-api (~> 1.0)
opentelemetry-instrumentation-base (~> 0.23.0)
opentelemetry-instrumentation-pg (0.30.0)
opentelemetry-instrumentation-pg (0.30.1)
opentelemetry-api (~> 1.0)
opentelemetry-helpers-sql
opentelemetry-helpers-sql-obfuscation
opentelemetry-instrumentation-base (~> 0.23.0)
opentelemetry-instrumentation-rack (0.26.0)
@ -583,7 +595,7 @@ GEM
opentelemetry-api (~> 1.0)
orm_adapter (0.5.0)
ostruct (0.6.1)
ox (2.14.22)
ox (2.14.23)
bigdecimal (>= 3.0)
parallel (1.27.0)
parser (3.3.8.0)
@ -593,8 +605,11 @@ GEM
pastel (0.8.0)
tty-color (~> 0.5)
pg (1.5.9)
pghero (3.6.2)
activerecord (>= 6.1)
pghero (3.7.0)
activerecord (>= 7.1)
playwright-ruby-client (1.52.0)
concurrent-ruby (>= 1.1.6)
mime-types (>= 3.0)
pp (0.6.2)
prettyprint
premailer (1.27.0)
@ -614,21 +629,22 @@ GEM
activesupport (>= 7.0.0)
rack
railties (>= 7.0.0)
psych (5.2.3)
psych (5.2.6)
date
stringio
public_suffix (6.0.1)
public_suffix (6.0.2)
puma (6.6.0)
nio4r (~> 2.0)
pundit (2.5.0)
activesupport (>= 3.0.0)
raabro (1.4.0)
racc (1.8.1)
rack (2.2.13)
rack (3.1.16)
rack-attack (6.7.0)
rack (>= 1.0, < 4)
rack-cors (2.0.2)
rack (>= 2.0.0)
rack-cors (3.0.0)
logger
rack (>= 3.0.14)
rack-oauth2 (2.2.1)
activesupport
attr_required
@ -636,18 +652,19 @@ GEM
faraday-follow_redirects
json-jwt (>= 1.11.0)
rack (>= 2.1.0)
rack-protection (3.2.0)
rack-protection (4.1.1)
base64 (>= 0.1.0)
rack (~> 2.2, >= 2.2.4)
logger (>= 1.6.0)
rack (>= 3.0.0, < 4)
rack-proxy (0.7.7)
rack
rack-session (1.0.2)
rack (< 3)
rack-session (2.1.1)
base64 (>= 0.1.0)
rack (>= 3.0.0)
rack-test (2.2.0)
rack (>= 1.3)
rackup (1.0.1)
rack (< 3)
webrick
rackup (2.2.1)
rack (>= 3)
rails (8.0.2)
actioncable (= 8.0.2)
actionmailbox (= 8.0.2)
@ -681,7 +698,7 @@ GEM
thor (~> 1.0, >= 1.2.2)
zeitwerk (~> 2.6)
rainbow (3.1.1)
rake (13.2.1)
rake (13.3.0)
rdf (3.3.2)
bcp47_spec (~> 0.2)
bigdecimal (~> 3.1, >= 3.1.5)
@ -692,8 +709,8 @@ GEM
psych (>= 4.0.0)
redcarpet (3.6.1)
redis (4.8.1)
redis-namespace (1.11.0)
redis (>= 4)
redis-client (0.24.0)
connection_pool
redlock (1.3.2)
redis (>= 3.0.0, < 6.0)
regexp_parser (2.10.0)
@ -706,30 +723,30 @@ GEM
railties (>= 5.2)
rexml (3.4.1)
rotp (6.3.0)
rouge (4.5.1)
rouge (4.5.2)
rpam2 (4.0.2)
rqrcode (2.2.0)
rqrcode (3.1.0)
chunky_png (~> 1.0)
rqrcode_core (~> 1.0)
rqrcode_core (1.2.0)
rqrcode_core (~> 2.0)
rqrcode_core (2.0.0)
rspec (3.13.0)
rspec-core (~> 3.13.0)
rspec-expectations (~> 3.13.0)
rspec-mocks (~> 3.13.0)
rspec-core (3.13.3)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.3)
rspec-expectations (3.13.4)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-github (3.0.0)
rspec-core (~> 3.0)
rspec-mocks (3.13.2)
rspec-mocks (3.13.4)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-rails (7.1.1)
actionpack (>= 7.0)
activesupport (>= 7.0)
railties (>= 7.0)
rspec-rails (8.0.0)
actionpack (>= 7.2)
activesupport (>= 7.2)
railties (>= 7.2)
rspec-core (~> 3.13)
rspec-expectations (~> 3.13)
rspec-mocks (~> 3.13)
@ -739,8 +756,8 @@ GEM
rspec-expectations (~> 3.0)
rspec-mocks (~> 3.0)
sidekiq (>= 5, < 9)
rspec-support (3.13.2)
rubocop (1.75.2)
rspec-support (3.13.3)
rubocop (1.76.1)
json (~> 2.3)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
@ -748,10 +765,10 @@ GEM
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.44.0, < 2.0)
rubocop-ast (>= 1.45.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.44.1)
rubocop-ast (1.45.1)
parser (>= 3.3.7.2)
prism (~> 1.4)
rubocop-capybara (2.22.1)
@ -764,25 +781,26 @@ GEM
lint_roller (~> 1.1)
rubocop (>= 1.75.0, < 2.0)
rubocop-ast (>= 1.38.0, < 2.0)
rubocop-rails (2.31.0)
rubocop-rails (2.32.0)
activesupport (>= 4.2.0)
lint_roller (~> 1.1)
rack (>= 1.1)
rubocop (>= 1.75.0, < 2.0)
rubocop-ast (>= 1.38.0, < 2.0)
rubocop-rspec (3.5.0)
rubocop-ast (>= 1.44.0, < 2.0)
rubocop-rspec (3.6.0)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rspec_rails (2.31.0)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rspec (~> 3.5)
ruby-prof (1.7.1)
ruby-prof (1.7.2)
base64
ruby-progressbar (1.13.0)
ruby-saml (1.18.0)
nokogiri (>= 1.13.10)
rexml
ruby-vips (2.2.3)
ruby-vips (2.2.4)
ffi (~> 1.12)
logger
rubyzip (2.4.1)
@ -797,31 +815,24 @@ GEM
activerecord (>= 4.0.0)
railties (>= 4.0.0)
securerandom (0.4.1)
selenium-webdriver (4.31.0)
base64 (~> 0.2)
logger (~> 1.4)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
semantic_range (3.1.0)
shoulda-matchers (6.4.0)
shoulda-matchers (6.5.0)
activesupport (>= 5.2.0)
sidekiq (6.5.12)
connection_pool (>= 2.2.5, < 3)
rack (~> 2.0)
redis (>= 4.5.0, < 5)
sidekiq (7.3.9)
base64
connection_pool (>= 2.3.0)
logger
rack (>= 2.2.4)
redis-client (>= 0.22.2)
sidekiq-bulk (0.2.0)
sidekiq
sidekiq-scheduler (5.0.6)
rufus-scheduler (~> 3.2)
sidekiq (>= 6, < 8)
tilt (>= 1.4.0, < 3)
sidekiq-unique-jobs (7.1.33)
brpoplpush-redis_script (> 0.1.1, <= 2.0.0)
sidekiq-unique-jobs (8.0.11)
concurrent-ruby (~> 1.0, >= 1.0.5)
redis (< 5.0)
sidekiq (>= 5.0, < 7.0)
thor (>= 0.20, < 3.0)
sidekiq (>= 7.0.0, < 9.0.0)
thor (>= 1.0, < 3.0)
simple-navigation (4.4.0)
activesupport (>= 2.3.2)
simple_form (5.3.1)
@ -839,7 +850,7 @@ GEM
base64
stoplight (4.1.1)
redlock (~> 1.0)
stringio (3.1.6)
stringio (3.1.7)
strong_migrations (2.3.0)
activerecord (>= 7)
swd (2.0.3)
@ -889,6 +900,15 @@ GEM
validate_url (1.0.15)
activemodel (>= 3.0.0)
public_suffix
vite_rails (3.0.19)
railties (>= 5.1, < 9)
vite_ruby (~> 3.0, >= 3.2.2)
vite_ruby (3.9.2)
dry-cli (>= 0.7, < 2)
logger (~> 1.6)
mutex_m
rack-proxy (~> 0.6, >= 0.6.1)
zeitwerk (~> 2.2)
warden (1.2.9)
rack (>= 2.0.9)
webauthn (3.4.0)
@ -907,13 +927,7 @@ GEM
addressable (>= 2.8.0)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
webpacker (5.4.4)
activesupport (>= 5.2)
rack-proxy (>= 0.6.1)
railties (>= 5.2)
semantic_range (>= 2.3.0)
webrick (1.9.1)
websocket (1.2.11)
websocket-driver (0.7.7)
base64
websocket-extensions (>= 0.1.0)
@ -941,6 +955,7 @@ DEPENDENCIES
browser
bundler-audit (~> 0.9)
capybara (~> 3.39)
capybara-playwright-driver
charlock_holmes (~> 0.7.7)
chewy (~> 7.3)
climate_control
@ -958,7 +973,7 @@ DEPENDENCIES
doorkeeper (~> 5.6)
dotenv
email_spec
fabrication (~> 2.30)
fabrication
faker (~> 3.2)
faraday-httpclient
fast_blank (~> 1.0)
@ -970,8 +985,9 @@ DEPENDENCIES
haml_lint
hcaptcha (~> 7.1)
hiredis (~> 0.6)
hiredis-client
htmlentities (~> 4.3)
http (~> 5.2.0)
http (~> 5.3.0)
http_accept_language (~> 2.1)
httplog (~> 1.7.0)
i18n
@ -988,12 +1004,12 @@ DEPENDENCIES
letter_opener (~> 1.8)
letter_opener_web (~> 3.0)
link_header (~> 0.0)
linzer (~> 0.6.1)
linzer (~> 0.7.2)
lograge (~> 0.12)
mail (~> 2.8)
mario-redis-lock (~> 1.2)
memory_profiler
mime-types (~> 3.6.0)
mime-types (~> 3.7.0)
mutex_m
net-http (~> 0.6.0)
net-ldap (~> 0.18)
@ -1010,7 +1026,7 @@ DEPENDENCIES
opentelemetry-instrumentation-active_model_serializers (~> 0.22.0)
opentelemetry-instrumentation-concurrent_ruby (~> 0.22.0)
opentelemetry-instrumentation-excon (~> 0.23.0)
opentelemetry-instrumentation-faraday (~> 0.26.0)
opentelemetry-instrumentation-faraday (~> 0.27.0)
opentelemetry-instrumentation-http (~> 0.24.0)
opentelemetry-instrumentation-http_client (~> 0.23.0)
opentelemetry-instrumentation-net_http (~> 0.23.0)
@ -1030,19 +1046,17 @@ DEPENDENCIES
public_suffix (~> 6.0)
puma (~> 6.3)
pundit (~> 2.3)
rack (~> 2.2.7)
rack-attack (~> 6.6)
rack-cors (~> 2.0)
rack-cors
rack-test (~> 2.1)
rails (~> 8.0)
rails-i18n (~> 8.0)
rdf-normalize (~> 0.5)
redcarpet (~> 3.6)
redis (~> 4.5)
redis-namespace (~> 1.10)
rqrcode (~> 2.2)
rqrcode (~> 3.0)
rspec-github (~> 3.0)
rspec-rails (~> 7.0)
rspec-rails (~> 8.0)
rspec-sidekiq (~> 5.0)
rubocop
rubocop-capybara
@ -1057,12 +1071,11 @@ DEPENDENCIES
rubyzip (~> 2.3)
sanitize (~> 7.0)
scenic (~> 1.7)
selenium-webdriver
shoulda-matchers
sidekiq (~> 6.5)
sidekiq (< 8)
sidekiq-bulk (~> 0.2.0)
sidekiq-scheduler (~> 5.0)
sidekiq-unique-jobs (~> 7.1)
sidekiq-unique-jobs (> 8)
simple-navigation (~> 4.4)
simple_form (~> 5.2)
simplecov (~> 0.22)
@ -1075,9 +1088,9 @@ DEPENDENCIES
tty-prompt (~> 0.23)
twitter-text (~> 3.1.0)
tzinfo-data (~> 1.2023)
vite_rails (~> 3.0.19)
webauthn (~> 3.0)
webmock (~> 3.18)
webpacker (~> 5.4)
webpush!
xorcist (~> 1.1)
@ -1085,4 +1098,4 @@ RUBY VERSION
ruby 3.4.1p0
BUNDLED WITH
2.6.8
2.6.9

View file

@ -1,4 +1,4 @@
web: env PORT=3000 RAILS_ENV=development bundle exec puma -C config/puma.rb
sidekiq: env PORT=3000 RAILS_ENV=development bundle exec sidekiq
stream: env PORT=4000 yarn workspace @mastodon/streaming start
webpack: bin/webpack-dev-server
vite: yarn dev

View file

@ -17,10 +17,6 @@
"description": "The secret key base",
"generator": "secret"
},
"OTP_SECRET": {
"description": "One-time password secret",
"generator": "secret"
},
"SINGLE_USER_MODE": {
"description": "Should the instance run in single user mode? (Disable registrations, redirect to front page)",
"value": "false",

View file

@ -2,13 +2,17 @@
module Admin
class RulesController < BaseController
before_action :set_rule, except: [:index, :create]
before_action :set_rule, except: [:index, :new, :create]
def index
authorize :rule, :index?
@rules = Rule.ordered
@rule = Rule.new
@rules = Rule.ordered.includes(:translations)
end
def new
authorize :rule, :create?
@rule = Rule.new
end
def edit
@ -23,8 +27,7 @@ module Admin
if @rule.save
redirect_to admin_rules_path
else
@rules = Rule.ordered
render :index
render :new
end
end
@ -46,6 +49,22 @@ module Admin
redirect_to admin_rules_path
end
def move_up
authorize @rule, :update?
@rule.move!(-1)
redirect_to admin_rules_path
end
def move_down
authorize @rule, :update?
@rule.move!(+1)
redirect_to admin_rules_path
end
private
def set_rule
@ -54,7 +73,7 @@ module Admin
def resource_params
params
.expect(rule: [:text, :hint, :priority])
.expect(rule: [:text, :hint, :priority, translations_attributes: [[:id, :language, :text, :hint, :_destroy]]])
end
end
end

View file

@ -50,6 +50,10 @@ class Api::BaseController < ApplicationController
nil
end
def require_client_credentials!
render json: { error: 'This method requires an client credentials authentication' }, status: 403 if doorkeeper_token.resource_owner_id.present?
end
def require_authenticated_user!
render json: { error: 'This method requires an authenticated user' }, status: 401 unless current_user
end
@ -72,6 +76,13 @@ class Api::BaseController < ApplicationController
end
end
# Redefine `require_functional!` to properly output JSON instead of HTML redirects
def require_functional!
return if current_user.functional?
require_user!
end
def render_empty
render json: {}, status: 200
end

View file

@ -42,37 +42,22 @@ class Api::Fasp::BaseController < ApplicationController
end
def validate_signature!
signature_input = request.headers['signature-input']&.encode('UTF-8')
raise Error, 'signature-input is missing' if signature_input.blank?
raise Error, 'signature-input is missing' if request.headers['signature-input'].blank?
provider = nil
Linzer.verify!(request.rack_request, no_older_than: 5.minutes) do |keyid|
provider = Fasp::Provider.find(keyid)
Linzer.new_ed25519_public_key(provider.provider_public_key_pem, keyid)
end
keyid = signature_input.match(KEYID_PATTERN)[1]
provider = Fasp::Provider.find(keyid)
linzer_request = Linzer.new_request(
request.method,
request.original_url,
{},
{
'content-digest' => request.headers['content-digest'],
'signature-input' => signature_input,
'signature' => request.headers['signature'],
}
)
message = Linzer::Message.new(linzer_request)
key = Linzer.new_ed25519_public_key(provider.provider_public_key_pem, keyid)
signature = Linzer::Signature.build(message.headers)
Linzer.verify(key, message, signature)
@current_provider = provider
end
def sign_response
response.headers['content-digest'] = "sha-256=:#{OpenSSL::Digest.base64digest('sha256', response.body || '')}:"
linzer_response = Linzer.new_response(response.body, response.status, { 'content-digest' => response.headers['content-digest'] })
message = Linzer::Message.new(linzer_response)
key = Linzer.new_ed25519_key(current_provider.server_private_key_pem)
signature = Linzer.sign(key, message, %w(@status content-digest))
response.headers.merge!(signature.to_h)
Linzer.sign!(response, key:, components: %w(@status content-digest))
end
def check_fasp_enabled

View file

@ -0,0 +1,26 @@
# frozen_string_literal: true
class Api::Fasp::DataSharing::V0::BackfillRequestsController < Api::Fasp::BaseController
def create
backfill_request = current_provider.fasp_backfill_requests.new(backfill_request_params)
respond_to do |format|
format.json do
if backfill_request.save
render json: { backfillRequest: { id: backfill_request.id } }, status: 201
else
head 422
end
end
end
end
private
def backfill_request_params
params
.permit(:category, :maxCount)
.to_unsafe_h
.transform_keys { |k| k.to_s.underscore }
end
end

View file

@ -0,0 +1,10 @@
# frozen_string_literal: true
class Api::Fasp::DataSharing::V0::ContinuationsController < Api::Fasp::BaseController
def create
backfill_request = current_provider.fasp_backfill_requests.find(params[:backfill_request_id])
Fasp::BackfillWorker.perform_async(backfill_request.id)
head 204
end
end

View file

@ -0,0 +1,25 @@
# frozen_string_literal: true
class Api::Fasp::DataSharing::V0::EventSubscriptionsController < Api::Fasp::BaseController
def create
subscription = current_provider.fasp_subscriptions.create!(subscription_params)
render json: { subscription: { id: subscription.id } }, status: 201
end
def destroy
subscription = current_provider.fasp_subscriptions.find(params[:id])
subscription.destroy
head 204
end
private
def subscription_params
params
.permit(:category, :subscriptionType, :maxBatchSize, threshold: {})
.to_unsafe_h
.transform_keys { |k| k.to_s.underscore }
end
end

View file

@ -10,6 +10,7 @@ class Api::V1::AccountsController < Api::BaseController
before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, only: [:create]
before_action :require_user!, except: [:index, :show, :create]
before_action :require_client_credentials!, only: [:create]
before_action :set_account, except: [:index, :create]
before_action :set_accounts, only: [:index]
before_action :check_account_approval, except: [:index, :create]

View file

@ -18,7 +18,7 @@ class Api::V1::FeaturedTagsController < Api::BaseController
end
def destroy
RemoveFeaturedTagWorker.perform_async(current_account.id, @featured_tag.id)
RemoveFeaturedTagService.new.call(current_account, @featured_tag)
render_empty
end

View file

@ -56,11 +56,11 @@ class Api::V1::FiltersController < Api::BaseController
end
def resource_params
params.permit(:phrase, :expires_in, :irreversible, :exclude_follows, :exclude_localusers, :with_quote, :with_profile, :whole_word, context: [])
params.permit(:phrase, :expires_in, :irreversible, :exclude_follows, :exclude_localusers, :with_profile, :whole_word, context: [])
end
def filter_params
resource_params.slice(:phrase, :expires_in, :irreversible, :exclude_follows, :exclude_localusers, :with_quote, :with_profile, :context)
resource_params.slice(:phrase, :expires_in, :irreversible, :exclude_follows, :exclude_localusers, :with_profile, :context)
end
def keyword_params

View file

@ -18,6 +18,6 @@ class Api::V1::Instances::RulesController < Api::V1::Instances::BaseController
private
def set_rules
@rules = Rule.ordered
@rules = Rule.ordered.includes(:translations)
end
end

View file

@ -1,7 +1,8 @@
# frozen_string_literal: true
class Api::V1::TagsController < Api::BaseController
before_action -> { doorkeeper_authorize! :follow, :write, :'write:follows' }, except: :show
before_action -> { doorkeeper_authorize! :follow, :write, :'write:follows' }, only: [:follow, :unfollow]
before_action -> { doorkeeper_authorize! :write, :'write:accounts' }, only: [:feature, :unfeature]
before_action :require_user!, except: :show
before_action :set_or_create_tag
@ -23,6 +24,16 @@ class Api::V1::TagsController < Api::BaseController
render json: @tag, serializer: REST::TagSerializer
end
def feature
CreateFeaturedTagService.new.call(current_account, @tag)
render json: @tag, serializer: REST::TagSerializer
end
def unfeature
RemoveFeaturedTagService.new.call(current_account, @tag)
render json: @tag, serializer: REST::TagSerializer
end
private
def set_or_create_tag

View file

@ -43,6 +43,6 @@ class Api::V2::FiltersController < Api::BaseController
end
def resource_params
params.permit(:title, :expires_in, :filter_action, :exclude_follows, :exclude_localusers, :with_quote, :with_profile, context: [], keywords_attributes: [:id, :keyword, :whole_word, :_destroy])
params.permit(:title, :expires_in, :filter_action, :exclude_follows, :exclude_localusers, :with_profile, context: [], keywords_attributes: [:id, :keyword, :whole_word, :_destroy])
end
end

View file

@ -1,7 +1,7 @@
# frozen_string_literal: true
class Api::V2::InstancesController < Api::BaseController
skip_before_action :require_authenticated_user!, unless: :limited_federation_mode?
skip_before_action :require_authenticated_user!
skip_around_action :set_locale
vary_by ''

View file

@ -72,10 +72,24 @@ class ApplicationController < ActionController::Base
def require_functional!
return if current_user.functional?
if current_user.confirmed?
redirect_to edit_user_registration_path
else
redirect_to auth_setup_path
respond_to do |format|
format.any do
if current_user.confirmed?
redirect_to edit_user_registration_path
else
redirect_to auth_setup_path
end
end
format.json do
if !current_user.confirmed?
render json: { error: 'Your login is missing a confirmed e-mail address' }, status: 403
elsif !current_user.approved?
render json: { error: 'Your login is currently pending approval' }, status: 403
elsif !current_user.functional?
render json: { error: 'Your login is currently disabled' }, status: 403
end
end
end
end

View file

@ -126,7 +126,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
end
def set_rules
@rules = Rule.ordered
@rules = Rule.ordered.includes(:translations)
end
def require_rules_acceptance!
@ -138,7 +138,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
set_locale { render :rules }
end
def is_flashing_format? # rubocop:disable Naming/PredicateName
def is_flashing_format? # rubocop:disable Naming/PredicatePrefix
if params[:action] == 'create'
false # Disable flash messages for sign-up
else

View file

@ -197,9 +197,7 @@ class Auth::SessionsController < Devise::SessionsController
)
# Only send a notification email every hour at most
return if redis.get("2fa_failure_notification:#{user.id}").present?
redis.set("2fa_failure_notification:#{user.id}", '1', ex: 1.hour)
return if redis.set("2fa_failure_notification:#{user.id}", '1', ex: 1.hour, get: true).present?
UserMailer.failed_2fa(user, request.remote_ip, request.user_agent, Time.now.utc).deliver_later!
end

View file

@ -16,7 +16,7 @@ module Localized
def requested_locale
requested_locale_name = available_locale_or_nil(params[:lang])
requested_locale_name ||= available_locale_or_nil(current_user.locale) if respond_to?(:user_signed_in?) && user_signed_in?
requested_locale_name ||= http_accept_language if ENV['DEFAULT_LOCALE'].blank?
requested_locale_name ||= http_accept_language unless ENV['FORCE_DEFAULT_LOCALE'] == 'true'
requested_locale_name
end

View file

@ -22,6 +22,18 @@ module SignatureVerification
request.headers['Signature'].present?
end
def signature_key_id
signed_request.key_id
end
private
def signed_request
@signed_request ||= SignedRequest.new(request) if signed_request?
rescue SignatureVerificationError
nil
end
def signature_verification_failure_reason
@signature_verification_failure_reason
end
@ -30,12 +42,6 @@ module SignatureVerification
@signature_verification_failure_code || 401
end
def signature_key_id
signature_params['keyId']
rescue Mastodon::SignatureVerificationError
nil
end
def signed_request_account
signed_request_actor.is_a?(Account) ? signed_request_actor : nil
end
@ -44,38 +50,20 @@ module SignatureVerification
return @signed_request_actor if defined?(@signed_request_actor)
raise Mastodon::SignatureVerificationError, 'Request not signed' unless signed_request?
raise Mastodon::SignatureVerificationError, 'Incompatible request signature. keyId and signature are required' if missing_required_signature_parameters?
raise Mastodon::SignatureVerificationError, 'Unsupported signature algorithm (only rsa-sha256 and hs2019 are supported)' unless %w(rsa-sha256 hs2019).include?(signature_algorithm)
raise Mastodon::SignatureVerificationError, 'Signed request date outside acceptable time window' unless matches_time_window?
verify_signature_strength!
verify_body_digest!
actor = actor_from_key_id
actor = actor_from_key_id(signature_params['keyId'])
raise Mastodon::SignatureVerificationError, "Public key not found for key #{signature_key_id}" if actor.nil?
raise Mastodon::SignatureVerificationError, "Public key not found for key #{signature_params['keyId']}" if actor.nil?
signature = Base64.decode64(signature_params['signature'])
compare_signed_string = build_signed_string(include_query_string: true)
return actor unless verify_signature(actor, signature, compare_signed_string).nil?
# Compatibility quirk with older Mastodon versions
compare_signed_string = build_signed_string(include_query_string: false)
return actor unless verify_signature(actor, signature, compare_signed_string).nil?
return (@signed_request_actor = actor) if signed_request.verified?(actor)
actor = stoplight_wrapper.run { actor_refresh_key!(actor) }
raise Mastodon::SignatureVerificationError, "Could not refresh public key #{signature_params['keyId']}" if actor.nil?
raise Mastodon::SignatureVerificationError, "Could not refresh public key #{signature_key_id}" if actor.nil?
compare_signed_string = build_signed_string(include_query_string: true)
return actor unless verify_signature(actor, signature, compare_signed_string).nil?
return (@signed_request_actor = actor) if signed_request.verified?(actor)
# Compatibility quirk with older Mastodon versions
compare_signed_string = build_signed_string(include_query_string: false)
return actor unless verify_signature(actor, signature, compare_signed_string).nil?
fail_with! "Verification failed for #{actor.to_log_human_identifier} #{actor.uri} using rsa-sha256 (RSASSA-PKCS1-v1_5 with SHA-256)", signed_string: compare_signed_string, signature: signature_params['signature']
fail_with! "Verification failed for #{actor.to_log_human_identifier} #{actor.uri}"
rescue Mastodon::SignatureVerificationError => e
fail_with! e.message
rescue *Mastodon::HTTP_CONNECTION_ERRORS => e
@ -86,12 +74,6 @@ module SignatureVerification
fail_with! 'Fetching attempt skipped because of recent connection failure'
end
def request_body
@request_body ||= request.raw_post
end
private
def fail_with!(message, **options)
Rails.logger.debug { "Signature verification failed: #{message}" }
@ -99,123 +81,8 @@ module SignatureVerification
@signed_request_actor = nil
end
def signature_params
@signature_params ||= SignatureParser.parse(request.headers['Signature'])
rescue SignatureParser::ParsingError
raise Mastodon::SignatureVerificationError, 'Error parsing signature parameters'
end
def signature_algorithm
signature_params.fetch('algorithm', 'hs2019')
end
def signed_headers
signature_params.fetch('headers', signature_algorithm == 'hs2019' ? '(created)' : 'date').downcase.split
end
def verify_signature_strength!
raise Mastodon::SignatureVerificationError, 'Mastodon requires the Date header or (created) pseudo-header to be signed' unless signed_headers.include?('date') || signed_headers.include?('(created)')
raise Mastodon::SignatureVerificationError, 'Mastodon requires the Digest header or (request-target) pseudo-header to be signed' unless signed_headers.include?(HttpSignatureDraft::REQUEST_TARGET) || signed_headers.include?('digest')
raise Mastodon::SignatureVerificationError, 'Mastodon requires the Host header to be signed when doing a GET request' if request.get? && !signed_headers.include?('host')
raise Mastodon::SignatureVerificationError, 'Mastodon requires the Digest header to be signed when doing a POST request' if request.post? && !signed_headers.include?('digest')
end
def verify_body_digest!
return unless signed_headers.include?('digest')
raise Mastodon::SignatureVerificationError, 'Digest header missing' unless request.headers.key?('Digest')
digests = request.headers['Digest'].split(',').map { |digest| digest.split('=', 2) }.map { |key, value| [key.downcase, value] }
sha256 = digests.assoc('sha-256')
raise Mastodon::SignatureVerificationError, "Mastodon only supports SHA-256 in Digest header. Offered algorithms: #{digests.map(&:first).join(', ')}" if sha256.nil?
return if body_digest == sha256[1]
digest_size = begin
Base64.strict_decode64(sha256[1].strip).length
rescue ArgumentError
raise Mastodon::SignatureVerificationError, "Invalid Digest value. The provided Digest value is not a valid base64 string. Given digest: #{sha256[1]}"
end
raise Mastodon::SignatureVerificationError, "Invalid Digest value. The provided Digest value is not a SHA-256 digest. Given digest: #{sha256[1]}" if digest_size != 32
raise Mastodon::SignatureVerificationError, "Invalid Digest value. Computed SHA-256 digest: #{body_digest}; given: #{sha256[1]}"
end
def verify_signature(actor, signature, compare_signed_string)
if actor.keypair.public_key.verify(OpenSSL::Digest.new('SHA256'), signature, compare_signed_string)
@signed_request_actor = actor
@signed_request_actor
end
rescue OpenSSL::PKey::RSAError
nil
end
def build_signed_string(include_query_string: true)
signed_headers.map do |signed_header|
case signed_header
when HttpSignatureDraft::REQUEST_TARGET
if include_query_string
"#{HttpSignatureDraft::REQUEST_TARGET}: #{request.method.downcase} #{request.original_fullpath}"
else
# Current versions of Mastodon incorrectly omit the query string from the (request-target) pseudo-header.
# Therefore, temporarily support such incorrect signatures for compatibility.
# TODO: remove eventually some time after release of the fixed version
"#{HttpSignatureDraft::REQUEST_TARGET}: #{request.method.downcase} #{request.path}"
end
when '(created)'
raise Mastodon::SignatureVerificationError, 'Invalid pseudo-header (created) for rsa-sha256' unless signature_algorithm == 'hs2019'
raise Mastodon::SignatureVerificationError, 'Pseudo-header (created) used but corresponding argument missing' if signature_params['created'].blank?
"(created): #{signature_params['created']}"
when '(expires)'
raise Mastodon::SignatureVerificationError, 'Invalid pseudo-header (expires) for rsa-sha256' unless signature_algorithm == 'hs2019'
raise Mastodon::SignatureVerificationError, 'Pseudo-header (expires) used but corresponding argument missing' if signature_params['expires'].blank?
"(expires): #{signature_params['expires']}"
else
"#{signed_header}: #{request.headers[to_header_name(signed_header)]}"
end
end.join("\n")
end
def matches_time_window?
created_time = nil
expires_time = nil
begin
if signature_algorithm == 'hs2019' && signature_params['created'].present?
created_time = Time.at(signature_params['created'].to_i).utc
elsif request.headers['Date'].present?
created_time = Time.httpdate(request.headers['Date']).utc
end
expires_time = Time.at(signature_params['expires'].to_i).utc if signature_params['expires'].present?
rescue ArgumentError => e
raise Mastodon::SignatureVerificationError, "Invalid Date header: #{e.message}"
end
expires_time ||= created_time + 5.minutes unless created_time.nil?
expires_time = [expires_time, created_time + EXPIRATION_WINDOW_LIMIT].min unless created_time.nil?
return false if created_time.present? && created_time > Time.now.utc + CLOCK_SKEW_MARGIN
return false if expires_time.present? && Time.now.utc > expires_time + CLOCK_SKEW_MARGIN
true
end
def body_digest
@body_digest ||= Digest::SHA256.base64digest(request_body)
end
def to_header_name(name)
name.split('-').map(&:capitalize).join('-')
end
def missing_required_signature_parameters?
signature_params['keyId'].blank? || signature_params['signature'].blank?
end
def actor_from_key_id(key_id)
def actor_from_key_id
key_id = signature_key_id
domain = key_id.start_with?('acct:') ? key_id.split('@').last : key_id
if domain_not_allowed?(domain)

View file

@ -8,6 +8,7 @@ module WebAppControllerConcern
before_action :redirect_unauthenticated_to_permalinks!
before_action :set_referer_header
before_action :redirect_to_tos_interstitial!
content_security_policy do |p|
policy = ContentSecurityPolicy.new
@ -45,6 +46,13 @@ module WebAppControllerConcern
protected
def redirect_to_tos_interstitial!
return unless current_user&.require_tos_interstitial?
@terms_of_service = TermsOfService.published.first
render 'terms_of_service_interstitial/show', layout: 'auth'
end
def set_referer_header
response.set_header('Referrer-Policy', Setting.allow_referrer_origin ? 'strict-origin-when-cross-origin' : 'same-origin')
end

View file

@ -47,6 +47,6 @@ class FiltersController < ApplicationController
end
def resource_params
params.expect(custom_filter: [:title, :expires_in, :filter_action, :exclude_follows, :exclude_localusers, :exclude_quote, :exclude_profile, context: [], keywords_attributes: [[:id, :keyword, :whole_word, :_destroy]]])
params.expect(custom_filter: [:title, :expires_in, :filter_action, :exclude_follows, :exclude_localusers, :exclude_profile, context: [], keywords_attributes: [[:id, :keyword, :whole_word, :_destroy]]])
end
end

View file

@ -12,7 +12,7 @@ class Settings::FeaturedTagsController < Settings::BaseController
end
def create
@featured_tag = CreateFeaturedTagService.new.call(current_account, featured_tag_params[:name], force: false)
@featured_tag = CreateFeaturedTagService.new.call(current_account, featured_tag_params[:name], raise_error: false)
if @featured_tag.valid?
redirect_to settings_featured_tags_path

View file

@ -4,8 +4,19 @@ class TermsOfServiceController < ApplicationController
include WebAppControllerConcern
skip_before_action :require_functional!
skip_before_action :redirect_to_tos_interstitial!
before_action :clear_redirect_interstitial!
def show
expires_in(15.seconds, public: true, stale_while_revalidate: 30.seconds, stale_if_error: 1.day) unless user_signed_in?
end
private
def clear_redirect_interstitial!
return unless user_signed_in?
current_user.update(require_tos_interstitial: false)
end
end

View file

@ -29,12 +29,19 @@ module ContextHelper
limited_scope: { 'kmyblue' => 'http://kmy.blue/ns#', 'limitedScope' => 'kmyblue:limitedScope' },
other_setting: { 'fedibird' => 'http://fedibird.com/ns#', 'otherSetting' => 'fedibird:otherSetting' },
references: { 'fedibird' => 'http://fedibird.com/ns#', 'references' => { '@id' => 'fedibird:references', '@type' => '@id' } },
quote_uri: { 'fedibird' => 'http://fedibird.com/ns#', 'quoteUri' => 'fedibird:quoteUri' },
keywords: { 'schema' => 'http://schema.org#', 'keywords' => 'schema:keywords' },
license: { 'schema' => 'http://schema.org#', 'license' => 'schema:license' },
suspended: { 'toot' => 'http://joinmastodon.org/ns#', 'suspended' => 'toot:suspended' },
attribution_domains: { 'toot' => 'http://joinmastodon.org/ns#', 'attributionDomains' => { '@id' => 'toot:attributionDomains', '@type' => '@id' } },
misskey_license: { 'misskey' => 'https://misskey-hub.net/ns#', '_misskey_license' => 'misskey:_misskey_license' },
quote_requests: { 'QuoteRequest' => 'https://w3id.org/fep/044f#QuoteRequest' },
interaction_policies: {
'gts' => 'https://gotosocial.org/ns#',
'interactionPolicy' => { '@id' => 'gts:interactionPolicy', '@type' => '@id' },
'canQuote' => { '@id' => 'gts:canQuote', '@type' => '@id' },
'automaticApproval' => { '@id' => 'gts:automaticApproval', '@type' => '@id' },
'manualApproval' => { '@id' => 'gts:manualApproval', '@type' => '@id' },
},
}.freeze
def full_context

View file

@ -31,14 +31,7 @@ module FormattingHelper
end
def status_content_format(status)
MastodonOTELTracer.in_span('HtmlAwareFormatter rendering') do |span|
span.add_attributes(
'app.formatter.content.type' => 'status',
'app.formatter.content.origin' => status.local? ? 'local' : 'remote'
)
html_aware_format(status.text, status.local?, markdown: status.markdown, preloaded_accounts: [status.account] + (status.respond_to?(:active_mentions) ? status.active_mentions.map(&:account) : []))
end
html_aware_format(status.text, status.local?, markdown: status.markdown, preloaded_accounts: [status.account] + (status.respond_to?(:active_mentions) ? status.active_mentions.map(&:account) : []))
end
def rss_status_content_format(status)
@ -50,14 +43,7 @@ module FormattingHelper
end
def account_bio_format(account)
MastodonOTELTracer.in_span('HtmlAwareFormatter rendering') do |span|
span.add_attributes(
'app.formatter.content.type' => 'account_bio',
'app.formatter.content.origin' => account.local? ? 'local' : 'remote'
)
html_aware_format(account.note, account.local?, markdown: account.user&.setting_bio_markdown)
end
html_aware_format(account.note, account.local?, markdown: account.user&.setting_bio_markdown)
end
def account_field_value_format(field, with_rel_me: true)

View file

@ -26,6 +26,8 @@ module JsonLdHelper
# The url attribute can be a string, an array of strings, or an array of objects.
# The objects could include a mimeType. Not-included mimeType means it's text/html.
def url_to_href(value, preferred_type = nil)
value = [value] if value.is_a?(Hash)
single_value = if value.is_a?(Array) && !value.first.is_a?(String)
value.find { |link| preferred_type.nil? || ((link['mimeType'].presence || 'text/html') == preferred_type) }
elsif value.is_a?(Array)
@ -41,6 +43,15 @@ module JsonLdHelper
end
end
def url_to_media_type(value, preferred_type = nil)
value = [value] if value.is_a?(Hash)
return unless value.is_a?(Array) && !value.first.is_a?(String)
single_value = value.find { |link| preferred_type.nil? || ((link['mimeType'].presence || 'text/html') == preferred_type) }
single_value['mediaType'] unless single_value.nil?
end
def as_array(value)
if value.nil?
[]
@ -80,6 +91,18 @@ module JsonLdHelper
!haystack.casecmp(needle).zero?
end
def safe_prefetched_embed(account, object, context)
return unless object.is_a?(Hash)
# NOTE: Replacing the object's context by that of the parent activity is
# not sound, but it's consistent with the rest of the codebase
object = object.merge({ '@context' => context })
return if value_or_id(first_of_value(object['attributedTo'])) != account.uri || non_matching_uri_hosts?(account.uri, object['id'])
object
end
def canonicalize(json)
graph = RDF::Graph.new << JSON::LD::API.toRdf(json, documentLoader: method(:load_jsonld_context))
graph.dump(:normalize)

View file

@ -15,7 +15,6 @@ module KmyblueCapabilitiesHelper
kmyblue_limited_scope
kmyblue_antenna
kmyblue_bookmark_category
kmyblue_quote
kmyblue_searchability_limited
kmyblue_circle_history
kmyblue_list_notification
@ -41,7 +40,6 @@ module KmyblueCapabilitiesHelper
capabilities = %i(
enable_wide_emoji
status_reference
quote
emoji_keywords
circle
)

View file

@ -4,7 +4,7 @@ module RoutingHelper
extend ActiveSupport::Concern
include ActionView::Helpers::AssetTagHelper
include Webpacker::Helper
include ViteRails::TagHelpers
included do
include Rails.application.routes.url_helpers
@ -25,7 +25,7 @@ module RoutingHelper
end
def frontend_asset_path(source, **)
asset_pack_path("media/#{source}", **)
vite_asset_path(source, **)
end
def frontend_asset_url(source, **)

View file

@ -4,11 +4,13 @@ module ThemeHelper
def theme_style_tags(theme)
if theme == 'system'
''.html_safe.tap do |tags|
tags << stylesheet_pack_tag('mastodon-light', media: 'not all and (prefers-color-scheme: dark)', crossorigin: 'anonymous')
tags << stylesheet_pack_tag('default', media: '(prefers-color-scheme: dark)', crossorigin: 'anonymous')
tags << vite_stylesheet_tag('styles/mastodon-light.scss', media: 'not all and (prefers-color-scheme: dark)', crossorigin: 'anonymous')
tags << vite_stylesheet_tag('styles/application.scss', media: '(prefers-color-scheme: dark)', crossorigin: 'anonymous')
end
elsif theme == 'default'
vite_stylesheet_tag 'styles/application.scss', media: 'all', crossorigin: 'anonymous'
else
stylesheet_pack_tag theme, media: 'all', crossorigin: 'anonymous'
vite_stylesheet_tag "styles/#{theme}.scss", media: 'all', crossorigin: 'anonymous'
end
end

View file

@ -1,4 +1,3 @@
import './public-path';
import { createRoot } from 'react-dom/client';
import Rails from '@rails/ujs';
@ -345,7 +344,7 @@ async function mountReactComponent(element: Element) {
);
const { default: Component } = (await import(
`@/mastodon/components/admin/${componentName}`
`@/mastodon/components/admin/${componentName}.jsx`
)) as { default: React.ComponentType };
const root = createRoot(element);

View file

@ -1,11 +1,6 @@
import './public-path';
import { loadLocale } from 'mastodon/locales';
import main from 'mastodon/main';
import { start } from '../mastodon/common';
import { loadLocale } from '../mastodon/locales';
import { loadPolyfills } from '../mastodon/polyfills';
start();
import { loadPolyfills } from 'mastodon/polyfills';
loadPolyfills()
.then(loadLocale)

View file

@ -0,0 +1,3 @@
import { start } from 'mastodon/common';
start();

View file

@ -1,15 +1,11 @@
import './public-path';
import { createRoot } from 'react-dom/client';
import { afterInitialRender } from 'mastodon/hooks/useRenderSignal';
import { start } from '../mastodon/common';
import { Status } from '../mastodon/features/standalone/status';
import { loadPolyfills } from '../mastodon/polyfills';
import ready from '../mastodon/ready';
start();
function loaded() {
const mountNode = document.getElementById('mastodon-status');

View file

@ -1,4 +1,3 @@
import './public-path';
import ready from '../mastodon/ready';
ready(() => {

View file

@ -1,4 +0,0 @@
/* Placeholder file to have `inert.scss` compiled by Webpack
This is used by the `wicg-inert` polyfill */
import '../styles/inert.scss';

View file

@ -1,3 +0,0 @@
import '../styles/mailer.scss';
require.context('../icons');

View file

@ -1,23 +0,0 @@
// Dynamically set webpack's loading path depending on a meta header, in order
// to share the same assets regardless of instance configuration.
// See https://webpack.js.org/guides/public-path/#on-the-fly
function removeOuterSlashes(string: string) {
return string.replace(/^\/*/, '').replace(/\/*$/, '');
}
function formatPublicPath(host = '', path = '') {
let formattedHost = removeOuterSlashes(host);
if (formattedHost && !/^http/i.test(formattedHost)) {
formattedHost = `//${formattedHost}`;
}
const formattedPath = removeOuterSlashes(path);
return `${formattedHost}/${formattedPath}/`;
}
const cdnHost = document.querySelector<HTMLMetaElement>('meta[name=cdn-host]');
__webpack_public_path__ = formatPublicPath(
cdnHost ? cdnHost.content : '',
process.env.PUBLIC_OUTPUT_PATH,
);

View file

@ -1,7 +1,5 @@
import { createRoot } from 'react-dom/client';
import './public-path';
import { IntlMessageFormat } from 'intl-messageformat';
import type { MessageDescriptor, PrimitiveType } from 'react-intl';
import { defineMessages } from 'react-intl';
@ -10,7 +8,6 @@ import Rails from '@rails/ujs';
import axios from 'axios';
import { throttle } from 'lodash';
import { start } from '../mastodon/common';
import { timeAgoString } from '../mastodon/components/relative_timestamp';
import emojify from '../mastodon/features/emoji/emoji';
import loadKeyboardExtensions from '../mastodon/load_keyboard_extensions';
@ -20,8 +17,6 @@ import ready from '../mastodon/ready';
import 'cocoon-js-vanilla';
start();
const messages = defineMessages({
usernameTaken: {
id: 'username.taken',
@ -153,9 +148,7 @@ function loaded() {
const reactComponents = document.querySelectorAll('[data-component]');
if (reactComponents.length > 0) {
import(
/* webpackChunkName: "containers/media_container" */ '../mastodon/containers/media_container'
)
import('../mastodon/containers/media_container')
.then(({ default: MediaContainer }) => {
reactComponents.forEach((component) => {
Array.from(component.children).forEach((child) => {

View file

@ -8,8 +8,6 @@ and performs no other task.
*/
import './public-path';
import axios from 'axios';
interface JRDLink {

View file

@ -1,13 +1,9 @@
import './public-path';
import { createRoot } from 'react-dom/client';
import { start } from '../mastodon/common';
import ComposeContainer from '../mastodon/containers/compose_container';
import { loadPolyfills } from '../mastodon/polyfills';
import ready from '../mastodon/ready';
start();
function loaded() {
const mountNode = document.getElementById('mastodon-compose');

View file

@ -1,12 +1,14 @@
import './public-path';
import axios from 'axios';
import ready from '../mastodon/ready';
async function checkConfirmation() {
const response = await axios.get('/api/v1/emails/check_confirmation');
const response = await axios.get('/api/v1/emails/check_confirmation', {
headers: { Accept: 'application/json' },
withCredentials: true,
});
if (response.data) {
if (response.status === 200 && response.data === true) {
window.location.href = '/start';
}
}

View file

@ -1,2 +1,2 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="79" height="79" viewBox="0 0 79 75"><symbol id="logo-symbol-icon"><path d="M74.7135 16.6043C73.6199 8.54587 66.5351 2.19527 58.1366 0.964691C56.7196 0.756754 51.351 0 38.9148 0H38.822C26.3824 0 23.7135 0.756754 22.2966 0.964691C14.1319 2.16118 6.67571 7.86752 4.86669 16.0214C3.99657 20.0369 3.90371 24.4888 4.06535 28.5726C4.29578 34.4289 4.34049 40.275 4.877 46.1075C5.24791 49.9817 5.89495 53.8251 6.81328 57.6088C8.53288 64.5968 15.4938 70.4122 22.3138 72.7848C29.6155 75.259 37.468 75.6697 44.9919 73.971C45.8196 73.7801 46.6381 73.5586 47.4475 73.3063C49.2737 72.7302 51.4164 72.086 52.9915 70.9542C53.0131 70.9384 53.0308 70.9178 53.0433 70.8942C53.0558 70.8706 53.0628 70.8445 53.0637 70.8179V65.1661C53.0634 65.1412 53.0574 65.1167 53.0462 65.0944C53.035 65.0721 53.0189 65.0525 52.9992 65.0371C52.9794 65.0218 52.9564 65.011 52.9318 65.0056C52.9073 65.0002 52.8819 65.0003 52.8574 65.0059C48.0369 66.1472 43.0971 66.7193 38.141 66.7103C29.6118 66.7103 27.3178 62.6981 26.6609 61.0278C26.1329 59.5842 25.7976 58.0784 25.6636 56.5486C25.6622 56.5229 25.667 56.4973 25.6775 56.4738C25.688 56.4502 25.7039 56.4295 25.724 56.4132C25.7441 56.397 25.7678 56.3856 25.7931 56.3801C25.8185 56.3746 25.8448 56.3751 25.8699 56.3816C30.6101 57.5151 35.4693 58.0873 40.3455 58.086C41.5183 58.086 42.6876 58.086 43.8604 58.0553C48.7647 57.919 53.9339 57.6701 58.7591 56.7361C58.8794 56.7123 58.9998 56.6918 59.103 56.6611C66.7139 55.2124 73.9569 50.665 74.6929 39.1501C74.7204 38.6967 74.7892 34.4016 74.7892 33.9312C74.7926 32.3325 75.3085 22.5901 74.7135 16.6043ZM62.9996 45.3371H54.9966V25.9069C54.9966 21.8163 53.277 19.7302 49.7793 19.7302C45.9343 19.7302 44.0083 22.1981 44.0083 27.0727V37.7082H36.0534V27.0727C36.0534 22.1981 34.124 19.7302 30.279 19.7302C26.8019 19.7302 25.0651 21.8163 25.0617 25.9069V45.3371H17.0656V25.3172C17.0656 21.2266 18.1191 17.9769 20.2262 15.568C22.3998 13.1648 25.2509 11.9308 28.7898 11.9308C32.8859 11.9308 35.9812 13.492 38.0447 16.6111L40.036 19.9245L42.0308 16.6111C44.0943 13.492 47.1896 11.9308 51.2788 11.9308C54.8143 11.9308 57.6654 13.1648 59.8459 15.568C61.9529 17.9746 63.0065 21.2243 63.0065 25.3172L62.9996 45.3371Z" fill="currentColor"/></symbol><use xlink:href="#logo-symbol-icon"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="79" height="79" viewBox="0 0 79 75"><symbol id="logo-symbol-icon"><path d="M63 45.3v-20c0-4.1-1-7.3-3.2-9.7-2.1-2.4-5-3.7-8.5-3.7-4.1 0-7.2 1.6-9.3 4.7l-2 3.3-2-3.3c-2-3.1-5.1-4.7-9.2-4.7-3.5 0-6.4 1.3-8.6 3.7-2.1 2.4-3.1 5.6-3.1 9.7v20h8V25.9c0-4.1 1.7-6.2 5.2-6.2 3.8 0 5.8 2.5 5.8 7.4V37.7H44V27.1c0-4.9 1.9-7.4 5.8-7.4 3.5 0 5.2 2.1 5.2 6.2V45.3h8ZM74.7 16.6c.6 6 .1 15.7.1 17.3 0 .5-.1 4.8-.1 5.3-.7 11.5-8 16-15.6 17.5-.1 0-.2 0-.3 0-4.9 1-10 1.2-14.9 1.4-1.2 0-2.4 0-3.6 0-4.8 0-9.7-.6-14.4-1.7-.1 0-.1 0-.1 0s-.1 0-.1 0 0 .1 0 .1 0 0 0 0c.1 1.6.4 3.1 1 4.5.6 1.7 2.9 5.7 11.4 5.7 5 0 9.9-.6 14.8-1.7 0 0 0 0 0 0 .1 0 .1 0 .1 0 0 .1 0 .1 0 .1.1 0 .1 0 .1.1v5.6s0 .1-.1.1c0 0 0 0 0 .1-1.6 1.1-3.7 1.7-5.6 2.3-.8.3-1.6.5-2.4.7-7.5 1.7-15.4 1.3-22.7-1.2-6.8-2.4-13.8-8.2-15.5-15.2-.9-3.8-1.6-7.6-1.9-11.5-.6-5.8-.6-11.7-.8-17.5C3.9 24.5 4 20 4.9 16 6.7 7.9 14.1 2.2 22.3 1c1.4-.2 4.1-1 16.5-1h.1C51.4 0 56.7.8 58.1 1c8.4 1.2 15.5 7.5 16.6 15.6Z" fill="currentColor"/></symbol><use xlink:href="#logo-symbol-icon"/></svg>

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Before After
Before After

View file

@ -2,6 +2,7 @@ import { browserHistory } from 'mastodon/components/router';
import { debounceWithDispatchAndArguments } from 'mastodon/utils/debounce';
import api, { getLinks } from '../api';
import { me } from '../initial_state';
import {
followAccountSuccess, unfollowAccountSuccess,
@ -12,6 +13,7 @@ import {
blockAccountSuccess, unblockAccountSuccess,
pinAccountSuccess, unpinAccountSuccess,
fetchRelationshipsSuccess,
fetchEndorsedAccounts,
} from './accounts_typed';
import { importFetchedAccount, importFetchedAccounts } from './importer';
@ -634,6 +636,7 @@ export function pinAccount(id) {
api().post(`/api/v1/accounts/${id}/pin`).then(response => {
dispatch(pinAccountSuccess({ relationship: response.data }));
dispatch(fetchEndorsedAccounts({ accountId: me }));
}).catch(error => {
dispatch(pinAccountFail(error));
});
@ -646,6 +649,7 @@ export function unpinAccount(id) {
api().post(`/api/v1/accounts/${id}/unpin`).then(response => {
dispatch(unpinAccountSuccess({ relationship: response.data }));
dispatch(fetchEndorsedAccounts({ accountId: me }));
}).catch(error => {
dispatch(unpinAccountFail(error));
});

View file

@ -0,0 +1,22 @@
import { createDataLoadingThunk } from 'mastodon/store/typed_functions';
import { apiGetFamiliarFollowers } from '../api/accounts';
import { importFetchedAccounts } from './importer';
export const fetchAccountsFamiliarFollowers = createDataLoadingThunk(
'accounts_familiar_followers/fetch',
({ id }: { id: string }) => apiGetFamiliarFollowers(id),
([data], { dispatch }) => {
if (!data) {
return null;
}
dispatch(importFetchedAccounts(data.accounts));
return {
id: data.id,
accountIds: data.accounts.map((account) => account.id),
};
},
);

View file

@ -1,16 +1,18 @@
import { createAction } from '@reduxjs/toolkit';
import type { ApiAccountJSON } from 'mastodon/api_types/accounts';
import {
apiRemoveAccountFromFollowers,
apiGetEndorsedAccounts,
} from 'mastodon/api/accounts';
import type { ApiRelationshipJSON } from 'mastodon/api_types/relationships';
import { createDataLoadingThunk } from 'mastodon/store/typed_functions';
import { importFetchedAccounts } from './importer';
export const revealAccount = createAction<{
id: string;
}>('accounts/revealAccount');
export const importAccounts = createAction<{ accounts: ApiAccountJSON[] }>(
'accounts/importAccounts',
);
function actionWithSkipLoadingTrue<Args extends object>(args: Args) {
return {
payload: {
@ -95,3 +97,19 @@ export const fetchRelationshipsSuccess = createAction(
'relationships/fetch/SUCCESS',
actionWithSkipLoadingTrue<{ relationships: ApiRelationshipJSON[] }>,
);
export const removeAccountFromFollowers = createDataLoadingThunk(
'accounts/remove_from_followers',
({ accountId }: { accountId: string }) =>
apiRemoveAccountFromFollowers(accountId),
(relationship) => ({ relationship }),
);
export const fetchEndorsedAccounts = createDataLoadingThunk(
'accounts/endorsements',
({ accountId }: { accountId: string }) => apiGetEndorsedAccounts(accountId),
(data, { dispatch }) => {
dispatch(importFetchedAccounts(data));
return data;
},
);

View file

@ -1,34 +0,0 @@
import api from '../api';
export const FEATURED_TAGS_FETCH_REQUEST = 'FEATURED_TAGS_FETCH_REQUEST';
export const FEATURED_TAGS_FETCH_SUCCESS = 'FEATURED_TAGS_FETCH_SUCCESS';
export const FEATURED_TAGS_FETCH_FAIL = 'FEATURED_TAGS_FETCH_FAIL';
export const fetchFeaturedTags = (id) => (dispatch, getState) => {
if (getState().getIn(['user_lists', 'featured_tags', id, 'items'])) {
return;
}
dispatch(fetchFeaturedTagsRequest(id));
api().get(`/api/v1/accounts/${id}/featured_tags`)
.then(({ data }) => dispatch(fetchFeaturedTagsSuccess(id, data)))
.catch(err => dispatch(fetchFeaturedTagsFail(id, err)));
};
export const fetchFeaturedTagsRequest = (id) => ({
type: FEATURED_TAGS_FETCH_REQUEST,
id,
});
export const fetchFeaturedTagsSuccess = (id, tags) => ({
type: FEATURED_TAGS_FETCH_SUCCESS,
id,
tags,
});
export const fetchFeaturedTagsFail = (id, error) => ({
type: FEATURED_TAGS_FETCH_FAIL,
id,
error,
});

View file

@ -0,0 +1,7 @@
import { apiGetFeaturedTags } from 'mastodon/api/accounts';
import { createDataLoadingThunk } from 'mastodon/store/typed_functions';
export const fetchFeaturedTags = createDataLoadingThunk(
'accounts/featured_tags',
({ accountId }: { accountId: string }) => apiGetFeaturedTags(accountId),
);

View file

@ -0,0 +1,7 @@
import { createAction } from '@reduxjs/toolkit';
import type { ApiAccountJSON } from 'mastodon/api_types/accounts';
export const importAccounts = createAction<{ accounts: ApiAccountJSON[] }>(
'accounts/importAccounts',
);

View file

@ -1,7 +1,6 @@
import { createPollFromServerJSON } from 'mastodon/models/poll';
import { importAccounts } from '../accounts_typed';
import { importAccounts } from './accounts';
import { normalizeStatus } from './normalizer';
import { importPolls } from './polls';
@ -70,8 +69,8 @@ export function importFetchedStatuses(statuses) {
processStatus(status.reblog);
}
if (status.quote?.id && !getState().getIn(['statuses', status.id])) {
processStatus(status.quote);
if (status.quote?.quoted_status) {
processStatus(status.quote.quoted_status);
}
if (status.poll?.id) {

View file

@ -23,12 +23,20 @@ export function normalizeFilterResult(result) {
export function normalizeStatus(status, normalOldStatus) {
const normalStatus = { ...status };
normalStatus.account = status.account.id;
if (status.reblog && status.reblog.id) {
normalStatus.reblog = status.reblog.id;
}
if (status.quote?.quoted_status ?? status.quote?.quoted_status_id) {
normalStatus.quote = {
...status.quote,
quoted_status: status.quote.quoted_status?.id ?? status.quote?.quoted_status_id,
};
}
if (status.poll && status.poll.id) {
normalStatus.poll = status.poll.id;
}
@ -66,11 +74,6 @@ export function normalizeStatus(status, normalOldStatus) {
normalStatus.spoiler_text = normalOldStatus.get('spoiler_text');
normalStatus.hidden = normalOldStatus.get('hidden');
// for quoted post
if (!normalStatus.filtered && normalOldStatus.get('filtered')) {
normalStatus.filtered = normalOldStatus.get('filtered');
}
if (normalOldStatus.get('translation')) {
normalStatus.translation = normalOldStatus.get('translation');
}
@ -94,6 +97,17 @@ export function normalizeStatus(status, normalOldStatus) {
normalStatus.contentHtml = emojify(normalStatus.content, emojiMap);
normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(spoilerText), emojiMap);
normalStatus.hidden = expandSpoilers ? false : spoilerText.length > 0 || normalStatus.sensitive;
if (normalStatus.url && !(normalStatus.url.startsWith('http://') || normalStatus.url.startsWith('https://'))) {
normalStatus.url = null;
}
normalStatus.url ||= normalStatus.uri;
normalStatus.media_attachments.forEach(item => {
if (item.remote_url && !(item.remote_url.startsWith('http://') || item.remote_url.startsWith('https://')))
item.remote_url = null;
});
}
if (normalOldStatus) {

View file

@ -0,0 +1,7 @@
import { createAction } from '@reduxjs/toolkit';
export const openNavigation = createAction('navigation/open');
export const closeNavigation = createAction('navigation/close');
export const toggleNavigation = createAction('navigation/toggle');

View file

@ -33,7 +33,7 @@ const messages = defineMessages({
message_poll: { id: 'notification.poll', defaultMessage: 'A poll you voted in has ended' },
message_reblog: { id: 'notification.reblog', defaultMessage: '{name} boosted your post' },
message_status: { id: 'notification.status', defaultMessage: '{name} just posted' },
message_status_reference: { id: 'notification.status_reference', defaultMessage: '{name} quoted your post' },
message_status_reference: { id: 'notification.status_reference', defaultMessage: '{name} linked your post' },
message_update: { id: 'notification.update', defaultMessage: '{name} edited a post' },
});

View file

@ -121,10 +121,15 @@ export const clickSearchResult = createAppAsyncThunk(
export const forgetSearchResult = createAppAsyncThunk(
'search/forgetResult',
(q: string, { dispatch, getState }) => {
(
{ q, type }: { q: string; type?: RecentSearchType },
{ dispatch, getState },
) => {
const previous = getState().search.recent;
const me = getState().meta.get('me') as string;
const current = previous.filter((result) => result.q !== q);
const current = previous.filter(
(result) => result.q !== q || result.type !== type,
);
searchHistory.set(me, current);
dispatch(updateSearchHistory(current));

View file

@ -6,8 +6,11 @@ import api from '../api';
import { fetchRelationships } from './accounts';
import { ensureComposeIsVisible, setComposeToStatus } from './compose';
import { importFetchedStatus, importFetchedStatuses, importFetchedAccount } from './importer';
import { fetchContext } from './statuses_typed';
import { deleteFromTimelines } from './timelines';
export * from './statuses_typed';
export const STATUS_FETCH_REQUEST = 'STATUS_FETCH_REQUEST';
export const STATUS_FETCH_SUCCESS = 'STATUS_FETCH_SUCCESS';
export const STATUS_FETCH_FAIL = 'STATUS_FETCH_FAIL';
@ -16,10 +19,6 @@ export const STATUS_DELETE_REQUEST = 'STATUS_DELETE_REQUEST';
export const STATUS_DELETE_SUCCESS = 'STATUS_DELETE_SUCCESS';
export const STATUS_DELETE_FAIL = 'STATUS_DELETE_FAIL';
export const CONTEXT_FETCH_REQUEST = 'CONTEXT_FETCH_REQUEST';
export const CONTEXT_FETCH_SUCCESS = 'CONTEXT_FETCH_SUCCESS';
export const CONTEXT_FETCH_FAIL = 'CONTEXT_FETCH_FAIL';
export const STATUS_MUTE_REQUEST = 'STATUS_MUTE_REQUEST';
export const STATUS_MUTE_SUCCESS = 'STATUS_MUTE_SUCCESS';
export const STATUS_MUTE_FAIL = 'STATUS_MUTE_FAIL';
@ -58,7 +57,7 @@ export function fetchStatus(id, forceFetch = false, alsoFetchContext = true) {
const skipLoading = !forceFetch && getState().getIn(['statuses', id], null) !== null;
if (alsoFetchContext) {
dispatch(fetchContext(id));
dispatch(fetchContext({ statusId: id }));
}
if (skipLoading) {
@ -188,51 +187,6 @@ export function deleteStatusFail(id, error) {
export const updateStatus = status => dispatch =>
dispatch(importFetchedStatus(status));
export function fetchContext(id) {
return (dispatch) => {
dispatch(fetchContextRequest(id));
api().get(`/api/v1/statuses/${id}/context?with_reference=1`).then(response => {
dispatch(importFetchedStatuses(response.data.ancestors.concat(response.data.descendants).concat(response.data.references)));
dispatch(fetchContextSuccess(id, response.data.ancestors, response.data.descendants, response.data.references));
}).catch(error => {
if (error.response && error.response.status === 404) {
dispatch(deleteFromTimelines(id));
}
dispatch(fetchContextFail(id, error));
});
};
}
export function fetchContextRequest(id) {
return {
type: CONTEXT_FETCH_REQUEST,
id,
};
}
export function fetchContextSuccess(id, ancestors, descendants, references) {
return {
type: CONTEXT_FETCH_SUCCESS,
id,
ancestors,
descendants,
references,
statuses: ancestors.concat(descendants),
};
}
export function fetchContextFail(id, error) {
return {
type: CONTEXT_FETCH_FAIL,
id,
error,
skipAlert: true,
};
}
export function muteStatus(id) {
return (dispatch) => {
dispatch(muteStatusRequest(id));

View file

@ -0,0 +1,20 @@
import { apiGetContext } from 'mastodon/api/statuses';
import { createDataLoadingThunk } from 'mastodon/store/typed_functions';
import { importFetchedStatuses } from './importer';
export const fetchContext = createDataLoadingThunk(
'status/context',
({ statusId }: { statusId: string }) => apiGetContext(statusId),
(context, { dispatch }) => {
const statuses = context.ancestors
.concat(context.descendants)
.concat(context.references);
dispatch(importFetchedStatuses(statuses));
return {
context,
};
},
);

View file

@ -1,4 +1,10 @@
import { apiGetTag, apiFollowTag, apiUnfollowTag } from 'mastodon/api/tags';
import {
apiGetTag,
apiFollowTag,
apiUnfollowTag,
apiFeatureTag,
apiUnfeatureTag,
} from 'mastodon/api/tags';
import { createDataLoadingThunk } from 'mastodon/store/typed_functions';
export const fetchHashtag = createDataLoadingThunk(
@ -15,3 +21,13 @@ export const unfollowHashtag = createDataLoadingThunk(
'tags/unfollow',
({ tagId }: { tagId: string }) => apiUnfollowTag(tagId),
);
export const featureHashtag = createDataLoadingThunk(
'tags/feature',
({ tagId }: { tagId: string }) => apiFeatureTag(tagId),
);
export const unfeatureHashtag = createDataLoadingThunk(
'tags/unfeature',
({ tagId }: { tagId: string }) => apiUnfeatureTag(tagId),
);

View file

@ -83,6 +83,7 @@ export default function api(withAuthorization = true) {
return instance;
}
type ApiUrl = `v${1 | 2}/${string}`;
type RequestParamsOrData = Record<string, unknown>;
export async function apiRequest<ApiResponse = unknown>(
@ -105,28 +106,28 @@ export async function apiRequest<ApiResponse = unknown>(
}
export async function apiRequestGet<ApiResponse = unknown>(
url: string,
url: ApiUrl,
params?: RequestParamsOrData,
) {
return apiRequest<ApiResponse>('GET', url, { params });
}
export async function apiRequestPost<ApiResponse = unknown>(
url: string,
url: ApiUrl,
data?: RequestParamsOrData,
) {
return apiRequest<ApiResponse>('POST', url, { data });
}
export async function apiRequestPut<ApiResponse = unknown>(
url: string,
url: ApiUrl,
data?: RequestParamsOrData,
) {
return apiRequest<ApiResponse>('PUT', url, { data });
}
export async function apiRequestDelete<ApiResponse = unknown>(
url: string,
url: ApiUrl,
params?: RequestParamsOrData,
) {
return apiRequest<ApiResponse>('DELETE', url, { params });

View file

@ -1,5 +1,10 @@
import { apiRequestPost } from 'mastodon/api';
import { apiRequestPost, apiRequestGet } from 'mastodon/api';
import type {
ApiAccountJSON,
ApiFamiliarFollowersJSON,
} from 'mastodon/api_types/accounts';
import type { ApiRelationshipJSON } from 'mastodon/api_types/relationships';
import type { ApiHashtagJSON } from 'mastodon/api_types/tags';
export const apiSubmitAccountNote = (id: string, value: string) =>
apiRequestPost<ApiRelationshipJSON>(`v1/accounts/${id}/note`, {
@ -18,3 +23,19 @@ export const apiFollowAccount = (
export const apiUnfollowAccount = (id: string) =>
apiRequestPost<ApiRelationshipJSON>(`v1/accounts/${id}/unfollow`);
export const apiRemoveAccountFromFollowers = (id: string) =>
apiRequestPost<ApiRelationshipJSON>(
`v1/accounts/${id}/remove_from_followers`,
);
export const apiGetFeaturedTags = (id: string) =>
apiRequestGet<ApiHashtagJSON>(`v1/accounts/${id}/featured_tags`);
export const apiGetEndorsedAccounts = (id: string) =>
apiRequestGet<ApiAccountJSON>(`v1/accounts/${id}/endorsements`);
export const apiGetFamiliarFollowers = (id: string) =>
apiRequestGet<ApiFamiliarFollowersJSON>('v1/accounts/familiar_followers', {
id,
});

View file

@ -2,9 +2,9 @@ import { apiRequestGet, apiRequestPost } from 'mastodon/api';
import type { ApiPollJSON } from 'mastodon/api_types/polls';
export const apiGetPoll = (pollId: string) =>
apiRequestGet<ApiPollJSON>(`/v1/polls/${pollId}`);
apiRequestGet<ApiPollJSON>(`v1/polls/${pollId}`);
export const apiPollVote = (pollId: string, choices: string[]) =>
apiRequestPost<ApiPollJSON>(`/v1/polls/${pollId}/votes`, {
apiRequestPost<ApiPollJSON>(`v1/polls/${pollId}/votes`, {
choices,
});

View file

@ -0,0 +1,7 @@
import { apiRequestGet } from 'mastodon/api';
import type { ApiContextJSON } from 'mastodon/api_types/statuses';
export const apiGetContext = (statusId: string) =>
apiRequestGet<ApiContextJSON>(
`v1/statuses/${statusId}/context?with_reference=1`,
);

View file

@ -10,6 +10,12 @@ export const apiFollowTag = (tagId: string) =>
export const apiUnfollowTag = (tagId: string) =>
apiRequestPost<ApiHashtagJSON>(`v1/tags/${tagId}/unfollow`);
export const apiFeatureTag = (tagId: string) =>
apiRequestPost<ApiHashtagJSON>(`v1/tags/${tagId}/feature`);
export const apiUnfeatureTag = (tagId: string) =>
apiRequestPost<ApiHashtagJSON>(`v1/tags/${tagId}/unfeature`);
export const apiGetFollowedTags = async (url?: string) => {
const response = await api().request<ApiHashtagJSON[]>({
method: 'GET',

View file

@ -20,7 +20,6 @@ export interface ApiAccountOtherSettingsJSON {
hide_followers_count: boolean;
translatable_private: boolean;
link_preview: boolean;
allow_quote: boolean;
emoji_reaction_policy:
| 'allow'
| 'outside_only'
@ -34,7 +33,6 @@ export interface ApiAccountOtherSettingsJSON {
export interface ApiServerFeaturesJSON {
circle: boolean;
emoji_reaction: boolean;
quote: boolean;
status_reference: boolean;
}
@ -83,3 +81,9 @@ export interface ApiMutedAccountJSON extends BaseApiAccountJSON {
// For now, we have the same type representing both `Account` and `MutedAccount`
// objects, but we should refactor this in the future.
export type ApiAccountJSON = ApiMutedAccountJSON;
// See app/serializers/rest/familiar_followers_serializer.rb
export type ApiFamiliarFollowersJSON = {
id: string;
accounts: ApiAccountJSON[];
}[];

View file

@ -125,3 +125,9 @@ export interface ApiStatusJSON {
card?: ApiPreviewCardJSON;
poll?: ApiPollJSON;
}
export interface ApiContextJSON {
ancestors: ApiStatusJSON[];
descendants: ApiStatusJSON[];
references: ApiStatusJSON[];
}

View file

@ -10,4 +10,5 @@ export interface ApiHashtagJSON {
url: string;
history: [ApiHistoryJSON, ...ApiHistoryJSON[]];
following?: boolean;
featuring?: boolean;
}

View file

@ -96,13 +96,19 @@ export const decode83 = (str: string) => {
return value;
};
export const intToRGB = (int: number) => ({
export interface RGB {
r: number;
g: number;
b: number;
}
export const intToRGB = (int: number): RGB => ({
r: Math.max(0, int >> 16),
g: Math.max(0, (int >> 8) & 255),
b: Math.max(0, int & 255),
});
export const getAverageFromBlurhash = (blurhash: string) => {
export const getAverageFromBlurhash = (blurhash: string | null) => {
if (!blurhash) {
return null;
}

View file

@ -1,8 +1,6 @@
import Rails from '@rails/ujs';
export function start() {
require.context('../images/', true, /\.(jpg|png|svg)$/);
try {
Rails.start();
} catch {

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`<AutosuggestEmoji /> renders emoji with custom url 1`] = `
exports[`<AutosuggestEmoji /> > renders emoji with custom url 1`] = `
<div
className="autosuggest-emoji"
>
@ -17,7 +17,7 @@ exports[`<AutosuggestEmoji /> renders emoji with custom url 1`] = `
</div>
`;
exports[`<AutosuggestEmoji /> renders native emoji 1`] = `
exports[`<AutosuggestEmoji /> > renders native emoji 1`] = `
<div
className="autosuggest-emoji"
>

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`<Avatar /> Autoplay renders a animated avatar 1`] = `
exports[`<Avatar /> > Autoplay > renders a animated avatar 1`] = `
<div
className="account__avatar account__avatar--loading"
onMouseEnter={[Function]}
@ -21,7 +21,7 @@ exports[`<Avatar /> Autoplay renders a animated avatar 1`] = `
</div>
`;
exports[`<Avatar /> Still renders a still avatar 1`] = `
exports[`<Avatar /> > Still > renders a still avatar 1`] = `
<div
className="account__avatar account__avatar--loading"
onMouseEnter={[Function]}

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`<AvatarOverlay renders a overlay avatar 1`] = `
exports[`<AvatarOverlay > renders a overlay avatar 1`] = `
<div
className="account__avatar-overlay"
onMouseEnter={[Function]}

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`<Button /> adds class "button-secondary" if props.secondary given 1`] = `
exports[`<Button /> > adds class "button-secondary" if props.secondary given 1`] = `
<button
className="button button-secondary"
onClick={[Function]}
@ -8,7 +8,7 @@ exports[`<Button /> adds class "button-secondary" if props.secondary given 1`] =
/>
`;
exports[`<Button /> renders a button element 1`] = `
exports[`<Button /> > renders a button element 1`] = `
<button
className="button"
onClick={[Function]}
@ -16,7 +16,7 @@ exports[`<Button /> renders a button element 1`] = `
/>
`;
exports[`<Button /> renders a disabled attribute if props.disabled given 1`] = `
exports[`<Button /> > renders a disabled attribute if props.disabled given 1`] = `
<button
className="button"
disabled={true}
@ -25,7 +25,7 @@ exports[`<Button /> renders a disabled attribute if props.disabled given 1`] = `
/>
`;
exports[`<Button /> renders class="button--block" if props.block given 1`] = `
exports[`<Button /> > renders class="button--block" if props.block given 1`] = `
<button
className="button button--block"
onClick={[Function]}
@ -33,7 +33,7 @@ exports[`<Button /> renders class="button--block" if props.block given 1`] = `
/>
`;
exports[`<Button /> renders the children 1`] = `
exports[`<Button /> > renders the children 1`] = `
<button
className="button"
onClick={[Function]}
@ -45,7 +45,7 @@ exports[`<Button /> renders the children 1`] = `
</button>
`;
exports[`<Button /> renders the given text 1`] = `
exports[`<Button /> > renders the given text 1`] = `
<button
className="button"
onClick={[Function]}
@ -55,7 +55,7 @@ exports[`<Button /> renders the given text 1`] = `
</button>
`;
exports[`<Button /> renders the props.text instead of children 1`] = `
exports[`<Button /> > renders the props.text instead of children 1`] = `
<button
className="button"
onClick={[Function]}

View file

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`<DisplayName /> renders display name + account name 1`] = `
exports[`<DisplayName /> > renders display name + account name 1`] = `
<span
className="display-name"
onMouseEnter={[Function]}

View file

@ -1,11 +1,13 @@
import { fromJS } from 'immutable';
import renderer from 'react-test-renderer';
import { accountDefaultValues, createAccountFromServerJSON } from '@/mastodon/models/account';
import { Avatar } from '../avatar';
describe('<Avatar />', () => {
const account = fromJS({
const account = createAccountFromServerJSON({
...accountDefaultValues,
username: 'alice',
acct: 'alice',
display_name: 'Alice',

View file

@ -21,7 +21,7 @@ describe('<Button />', () => {
});
it('handles click events using the given handler', () => {
const handler = jest.fn();
const handler = vi.fn();
render(<Button onClick={handler}>button</Button>);
fireEvent.click(screen.getByText('button'));
@ -29,7 +29,7 @@ describe('<Button />', () => {
});
it('does not handle click events if props.disabled given', () => {
const handler = jest.fn();
const handler = vi.fn();
render(<Button onClick={handler} disabled>button</Button>);
fireEvent.click(screen.getByText('button'));

Some files were not shown because too many files have changed in this diff Show more