Compare commits

...

538 Commits
local ... main

Author SHA1 Message Date
Thor 22e9559aa2 Merge remote-tracking branch 'upstream/main' into main 2 years ago
Claire ad84fd25f1
Merge pull request #1941 from ClearlyClaire/glitch-soc/merge-upstream 2 years ago
Effy Elden 7efe2cf00f
Modify image build workflow for Glitch workflows (#1942) 2 years ago
Claire 1901829f9a Merge branch 'main' into glitch-soc/merge-upstream 2 years ago
Daniel Axtens 4d85c27d1a
Add 'private' to Cache-Control, match Rails expectations (#20608) 2 years ago
dependabot[bot] ac7a29f068
Bump loader-utils from 1.4.1 to 1.4.2 (#20826) 2 years ago
dependabot[bot] f7d261cac7
Bump sidekiq from 6.5.7 to 6.5.8 (#20035) 2 years ago
dependabot[bot] 575bf3fa20
Bump oj from 3.13.21 to 3.13.23 (#20046) 2 years ago
dependabot[bot] dde60e2634
Bump object.values from 1.1.5 to 1.1.6 (#20047) 2 years ago
dependabot[bot] f32c2de6af
Bump pg from 1.4.3 to 1.4.4 (#19597) 2 years ago
dependabot[bot] acbf4d0dfe
Bump jsdom from 20.0.1 to 20.0.2 (#19603) 2 years ago
dependabot[bot] dd360e653e
Bump blurhash from 2.0.3 to 2.0.4 (#19601) 2 years ago
dependabot[bot] ca6106603b
Bump array-includes from 3.1.5 to 3.1.6 (#20680) 2 years ago
dependabot[bot] dba1645bf0
Bump postcss from 8.4.18 to 8.4.19 (#20684) 2 years ago
dependabot[bot] 9f95c419d2
Bump yargs from 17.6.0 to 17.6.2 (#20063) 2 years ago
dependabot[bot] 3301aadba8
Bump redux-thunk from 2.4.1 to 2.4.2 (#20060) 2 years ago
dependabot[bot] 4ef4db2a5a
Bump loader-utils from 1.4.0 to 1.4.1 (#20085) 2 years ago
dependabot[bot] fc4452104c
Bump json-ld-preloaded from 3.2.0 to 3.2.2 (#20058) 2 years ago
dependabot[bot] c76f29ae45
Bump tzinfo-data from 1.2022.4 to 1.2022.6 (#20056) 2 years ago
dependabot[bot] 61264e52cc
Bump memory_profiler from 1.0.0 to 1.0.1 (#20054) 2 years ago
dependabot[bot] 3b82d1ef68
Bump reselect from 4.1.6 to 4.1.7 (#20052) 2 years ago
dependabot[bot] 66a22ab391
Bump promise.prototype.finally from 3.1.3 to 3.1.4 (#20050) 2 years ago
Eugen Rochko a1738f8991
New Crowdin updates (#20580) 2 years ago
Eugen Rochko 03b0f3ac83
Bump version to 4.0.2 (#20725) 2 years ago
Eugen Rochko 43b0b2f3f4
Fix wrong directive `unsafe-wasm-eval` to `wasm-unsafe-eval` (#20729) 2 years ago
prplecake b46b7c3d5e
Use "unsafe-wasm-eval" instead of "unsafe-eval" in script-src CSP (#20606) 2 years ago
dependabot[bot] b59683c156
Bump nokogiri from 1.13.8 to 1.13.9 (#20041) 2 years ago
Eugen Rochko 17bd9a87b9
Fix wrong color on mentions hidden behind content warning in web UI (#20724) 2 years ago
Claire eb675af0fb
Merge pull request #1932 from ClearlyClaire/glitch-soc/merge-upstream 2 years ago
Claire 66461ae79a Merge branch 'main' into glitch-soc/merge-upstream 2 years ago
Claire 8c3c6dcae9
Fix filters from other users being used in the streaming service (#20719) 2 years ago
Claire ceafd1f68f
Fix infinite loop when system emoji font is enabled (#1931) 2 years ago
Claire e589afa0ef
Merge pull request #1929 from ClearlyClaire/glitch-soc/merge-upstream 2 years ago
Claire 8aa56aedfd [Glitch] Fix nodes order being sometimes mangled when rewriting emoji 2 years ago
Claire b5698af25f Merge branch 'main' into glitch-soc/merge-upstream 2 years ago
Eugen Rochko 4415dd6036
Bump version to 4.0.1 (#20696) 2 years ago
Claire ccbca50a25
Fix nodes order being sometimes mangled when rewriting emoji (#20677) 2 years ago
Claire 7a8cd0cb0a
Merge pull request #1928 from ClearlyClaire/glitch-soc/merge-upstream 2 years ago
Claire 71982e5c83 [Glitch] Fix emoji substitution not applying only to text nodes in Web UI 2 years ago
Claire 767630be24 Merge branch 'main' into glitch-soc/merge-upstream 2 years ago
Eugen Rochko fb389bd73c
Bump version to 4.0.0 (#20636) 2 years ago
Eugen Rochko 21fd25a269
Fix rate limiting for paths with formats (#20675) 2 years ago
Claire 71c92d3f56
Fix emoji substitution not applying only to text nodes in backend code (#20641) 2 years ago
Claire 625e086996
Fix emoji substitution not applying only to text nodes in Web UI (#20640) 2 years ago
Claire a34aa2a5f9
Merge pull request #1927 from ClearlyClaire/glitch-soc/merge-upstream 2 years ago
Claire 96c1ef6d50 [Glitch] Fix media metadata being only editable once 2 years ago
Claire 9ab4e3fc6d Merge branch 'main' into glitch-soc/merge-upstream 2 years ago
Claire 2d54986a03
Fix media metadata being only editable once (#20665) 2 years ago
Claire 7233569474
Merge pull request #1923 from ClearlyClaire/glitch-soc/merge-upstream 2 years ago
trwnh c31e756644 [Glitch] Move V2 Filter methods under /api/v2 prefix 2 years ago
Eugen Rochko 9db90d2ebe [Glitch] Fix dropdown menu on profiles not being accessible on narrow screens in web UI 2 years ago
Samuel Kaiser 9fd866f38e [Glitch] Stick batch table toolbar to the top 2 years ago
Claire cd713cac81 Merge branch 'main' into glitch-soc/merge-upstream 2 years ago
Eugen Rochko 75299a042c
Bump version to 4.0.0rc4 (#20634) 2 years ago
Claire 32c70d2f09 Merge branch 'main' into glitch-soc/merge-upstream 2 years ago
trwnh b59ce0a60f
Move V2 Filter methods under /api/v2 prefix (#20622) 2 years ago
Claire 457c37e47a
Fix index name in fix-duplicates task (#20632) 2 years ago
Eugen Rochko 1e83092e47
Update AUTHORS.md (#20630) 2 years ago
Eugen Rochko 552d69ad96
Fix error when invalid domain name is submitted (#19474) 2 years ago
Eugen Rochko 523e106cbf
Fix style of username in navigation bar above compose form in web UI (#20628) 2 years ago
Eugen Rochko b31afc6294
Fix error when passing unknown filter param in REST API (#20626) 2 years ago
Eugen Rochko 5c826c408d
Fix image type not being set after conversion for convertible image types (#20624) 2 years ago
Eugen Rochko 167d86d21d
Fix `role_ids` not accepting arrays in admin API (#20625) 2 years ago
Eugen Rochko 2e2ba39abf
Fix rules with same priority being sorted non-deterministically (#20623) 2 years ago
Eugen Rochko 6da9df774e
Fix dropdown menu on profiles not being accessible on narrow screens in web UI (#20620) 2 years ago
Hampton Lintorn-Catlin 147d8bd8fc
Support UTF-8 Characters in Domains During CSV Import (#20592) 2 years ago
Matt Corallo 9d039209cc
Add `Cache-Control` header to openstack-stored files (#20610) 2 years ago
Eugen Rochko d0b7bd4250
Fix wrong cut-off point for "Read more" in web UI (#20599) 2 years ago
Eugen Rochko 24b2c60beb
Fix icons having an image role (#20600) 2 years ago
Erik Sundell 87fbd08f74
helm: Add helm chart tests (#20394) 2 years ago
trwnh 07229089a6
Change in-app links to keep you in-app (#20540) 2 years ago
Cees-Jan Kiewiet ad66bbed62
Add the option to configure external postgresql port (#20370) 2 years ago
Alex Nordlund 82c663300a
Helm: support statsd publishing (#20455) 2 years ago
Samuel Kaiser e62b514e95
Stick batch table toolbar to the top (#20442) 2 years ago
Emily Strickland c2231539c7
Test blank account field verifiability (#20458) 2 years ago
Claire bd806a3090
Update fix-duplicates (#20502) 2 years ago
Nicholas La Roux a6186da983
Clean up GitHub sourced gem entry (#20542) 2 years ago
Claire cd5e98dbdb
Fix public/local timeline posts not being properly filtered (#20567) 2 years ago
Claire 3d3bd344cb
Fix announcement dates not being validated client-side (#20577) 2 years ago
Arthur Isac 1af482659d
Copied Spaces support from packer .rake (#20573) 2 years ago
Eugen Rochko cf36ee99bb
New Crowdin updates (#20476) 2 years ago
David Hewitt 290d78cea4
Allow unsetting x-amz-acl S3 Permission headers (#20510) 2 years ago
Claire cf77d938f8
Fix saving server registration settings redirecting to branding settings (#20505) 2 years ago
helloworldstack e9e4938bc9
Fix casing and spacing of words (#20504) 2 years ago
Claire 81b1d32d5b
Merge pull request #1920 from ClearlyClaire/glitch-soc/merge-upstream 2 years ago
Claire a808ac1fd8 [Glitch] Fix WebUI crash when listing server blocks and rationale is not available 2 years ago
Claire 9255bfb908 [Glitch] Add the ability to edit media attachment metadata for any unattached media 2 years ago
Cutls e2315876f4 [Glitch] Do not show drag&drop dialog when not logined 2 years ago
Claire 8ac4165c72 [Glitch] Remove “No description added” media warning in edit mode 2 years ago
Eugen Rochko 400d168310 [Glitch] Fix domain blocks on about page not working well on small screens in web UI 2 years ago
Connor Shea d525ae4bdd [Glitch] Only remove padding when listing applications 2 years ago
Yamagishi Kazutoshi 0071582c6d [Glitch] Delay workbox import 2 years ago
Claire 5394ca6807 [Glitch] Fix unnecessary service worker registration and preloading when logged out 2 years ago
Claire 487689f062 [Glitch] Remove preview cards from fav and boost notifications 2 years ago
Claire 3fa6c603ba [Glitch] Fix color of the “No description added“ media upload warning on light theme 2 years ago
Claire 93912f0498 Merge branch 'main' into glitch-soc/merge-upstream 2 years ago
Claire d37f426f95
Add back missing glitch-soc admin settings (#1919) 2 years ago
Jared Allard e88f4f5e57
ci: write permissions to packages (#1906) 2 years ago
Claire 210341fba1
Merge pull request #1918 from ClearlyClaire/glitch-soc/features/glitch-label 2 years ago
Claire af89b14628 Add extended description for glitch-soc only “hide followers count" setting 2 years ago
Claire 6a96b17a2d Add “Glitch-only” label to glitch-specific settings 2 years ago
Claire c813df2ebb
Merge pull request #1917 from ClearlyClaire/glitch-soc/fixes/not-recommended-label 2 years ago
Claire 0d43d9926a Make trendable_by_default not apply to posts 2 years ago
Claire 1ce29aeabf Change "Allow trends without prior review' setting to include statuses 2 years ago
Eugen Rochko d26c1cb2fe
Fix missing "not recommended" label on "Allow trends without review" (#20480) 2 years ago
Claire fdfacb0ec0 Revert "Revert "Change "Allow trends without prior review" setting to include statuses (#17977)"" 2 years ago
Claire 73b68fcabb
Fix styling of advanced options dropdown (#1916) 2 years ago
Eugen Rochko e1af21cfd0
New Crowdin updates (#20258) 2 years ago
Alex Nordlund 628b3fa449
Uppercase chart readme.md to help tools discover it (#20438) 2 years ago
Bearice Ren 28cda42af5
fixes ArgumentError when proxy is used (#20420) 2 years ago
Jeong Arm c4c1bee880
Fix trendable status without review (#20214) 2 years ago
Claire 93a6ebc83d
Fix WebUI crash when listing server blocks and rationale is not available (#20408) 2 years ago
Emily Strickland 96f51e593f
Guard against error extracting `body` from URL (#20428) 2 years ago
Claire 31005aad12
Add the ability to edit media attachment metadata for any unattached media (#20402) 2 years ago
Cutls 553b169d48
Do not show drag&drop dialog when not logined (#20400) 2 years ago
Claire 5e796dc6f8
Remove “No description added” media warning in edit mode (#20393) 2 years ago
Eugen Rochko 9bc0a6c861
Fix metadata scrubbing removing color profile from images (#20389) 2 years ago
Eugen Rochko 53028af10e
Bump version to 4.0.0rc3 (#20378) 2 years ago
Eugen Rochko 6774c339b2
Fix domain blocks on about page not working well on small screens in web UI (#20391) 2 years ago
Pierre Bourdon 36bc90e8aa
blurhash_transcoder: prevent out-of-bound reads with <8bpp images (#20388) 2 years ago
Eugen Rochko 73fecc3358
Change e-mail in SECURITY.md (#20384) 2 years ago
Connor Shea cf4992c918
Only remove padding when listing applications (#20382) 2 years ago
F 97f657f818
Note that CircleCI auth may be required to run PR pipelines (#20371) 2 years ago
Yamagishi Kazutoshi 53d26cfc1c
Delay workbox import (#20376) 2 years ago
Yamagishi Kazutoshi 19a8563905
Fix `ENV` (#20377) 2 years ago
F d4f973227c
Test the native_locale_name of a non-standard locale (#20284) 2 years ago
Erik Sundell 302a58c22b
helm: fix consistent indentation, chomping, and use of with (#19918) 2 years ago
Claire 86f6631d28
Remove dead code and refactor status threading code (#20357) 2 years ago
F a02a453a40
Add Scots to the supported locales (#20283) 2 years ago
Eugen Rochko c6c7c6223d
Change verification to only work for https links (#20304) 2 years ago
F 9feba112a7
Make enable_starttls configurable by envvars (#20321) 2 years ago
Claire 1615c3eb6e
Change logged out /api/v1/statuses/:id/context logged out limits (#20355) 2 years ago
Claire 894ce3726a
Fix unnecessary service worker registration and preloading when logged out (#20341) 2 years ago
Alex Nordlund 397845453e
Update Helm README and bump version (#20346) 2 years ago
Claire 8e1e7fe2e0
Add old logo files back (#20332) 2 years ago
Claire 99734ac936
Remove preview cards from fav and boost notifications (#20335) 2 years ago
Joe Friedl 86232e68a8
Give web container time to start (#19828) 2 years ago
mickkael 6c7cdedb24
Helm chart improved for ingress (#19826) 2 years ago
Alex Nordlund 60c4df3d1d
Bump next Helm chart to 2.1.0 (#20155) 2 years ago
Sheogorath e868f41923
fix(chart): Fix gitops-incompatible random rolling (#20184) 2 years ago
Alex Nordlund 86d4b6f7c9
Helm update readme.md (#20154) 2 years ago
Alex Nordlund b907871604
Helm update readme.md (#20154) 2 years ago
atsuchan 6df9d388e7
Update Flavour 'ja' Translation (#1911) 2 years ago
Eugen Rochko f8e8e622e5
Change incoming activity processing to happen in `ingress` queue (#20264) 2 years ago
Claire 89a6b76f99
Fix color of the “No description added“ media upload warning on light theme (#20328) 2 years ago
Claire ee7e49d1b1
Merge pull request #1910 from ClearlyClaire/glitch-soc/merge-upstream 2 years ago
Eugen Rochko c4d2c72924 [Glitch] Add option to open original page in dropdowns of remote content in web UI 2 years ago
Sasha Sorokin 099b3011aa [Glitch] Remove aria-pressed where it's redundant 2 years ago
Eugen Rochko 65b6c4f6df [Glitch] Change larger reblogs/favourites numbers to be shortened in web UI 2 years ago
Effy Elden c722c4cce8 [Glitch] Remove unused timeline_container to fix linter errors 2 years ago
Eugen Rochko 41ea39903d [Glitch] Fix confusing wording in interaction modal in web UI 2 years ago
Eugen Rochko d3a29a136c [Glitch] Fix profile header being cut off in light theme in web UI 2 years ago
Claire c118918520 Merge branch 'main' into glitch-soc/merge-upstream 2 years ago
Effy Elden 8fdbb4d00d
Remove unused timeline_container to fix linter errors (#20305) 2 years ago
Eugen Rochko 7bdb2433f1
Change larger reblogs/favourites numbers to be shortened in web UI (#20303) 2 years ago
Eugen Rochko 16122761c5
Fix confusing wording in interaction modal in web UI (#20302) 2 years ago
Eugen Rochko ef582dc4f2
Add option to open original page in dropdowns of remote content in web UI (#20299) 2 years ago
Eugen Rochko e37e8deb0f
Fix profile header being cut off in light theme in web UI (#20298) 2 years ago
Eugen Rochko 9965a23b04
Change link verification to ignore IDN domains (#20295) 2 years ago
James Tucker 78a6b871fe
Improve performance by avoiding regex construction (#20215) 2 years ago
Eugen Rochko 0cd0786aef
Revert filtering public timelines by locale by default (#20294) 2 years ago
trwnh b280a255c4
Change `master` branch to `main` branch (#20290) 2 years ago
Eugen Rochko 45ce858fd9
Fix `mailers` queue not being used for mailers (#20274) 2 years ago
Claire a5394980f2
Fix NameError in Webfinger redirect handling in ActivityPub::FetchRemoteActorService (#20260) 2 years ago
Eugen Rochko cd0a87f170
New Crowdin updates (#20016) 2 years ago
Vyr Cossont 104157bd01
Add Balaibalan, Láadan, Lingua Franca Nova, Lojban, Toki Pona to language list (#20168) 2 years ago
trwnh 029b5cd5b1
Fix GET /api/v1/admin/ip_blocks/:id (#20207) 2 years ago
Claire 5333447be0
Change account deletion requests to spread out over time (#20222) 2 years ago
Eugen Rochko e98833748e
Fix being able to spoof link verification (#20217) 2 years ago
keiya 53817294fc
Fix nginx location matching (#20198) 2 years ago
Claire dd7176a4b5
Fix redirects from /web/ discarding everything after a dot (#20148) 2 years ago
luzpaz 6ba52306f9
Fix typos (#19849) 2 years ago
Christian Clauss 6f1559ed0f
CHANGELOG.md: Fix typos (#19838) 2 years ago
Sasha Sorokin d055d75172
Remove aria-pressed where it's redundant (#19912) 2 years ago
Claire d70303bba6
Add server-side route so that legacy /web/statuses/:id URLs keep being supported (#19978) 2 years ago
trwnh b1a48e05b6
Change Report category to "violation" if rule IDs are provided (#20137) 2 years ago
Claire c476dfc725
Fix nodeinfo metadata attribute being an array instead of an object (#20114) 2 years ago
Alex Nordlund 476e74b4c4
Assign unique set of labels to k8s deployments #19703 (#19706) 2 years ago
Sheogorath f4b78028a3
chore(chart): Update appVersion in helm chart (#19653) 2 years ago
Moritz Hedtke f7613febb3
helm: Fix ingress pathType (#19729) 2 years ago
Alex Nordlund fd3c482104
Roll pods to pick up db migrations even if podAnnotations is empty (#19702) 2 years ago
Alex Nordlund d3afd7a2f1
Fix helm postgresql secret (#19678) 2 years ago
k.bigwheel (kazufumi nishida) 9358fd295d
Add postgresql password settings hint (#19112) 2 years ago
trwnh c374729225
Add `sensitized` to Admin::Account serializer (fix #19148) (#20094) 2 years ago
Claire b2a25d446a
Merge pull request #1905 from ClearlyClaire/glitch-soc/merge-upstream 2 years ago
trwnh 89e1974f30
Make account endorsements idempotent (fix #19045) (#20118) 2 years ago
trwnh 455a754081
Fix missing cast of status and rule IDs to string (fix #19048) (#20122) 2 years ago
trwnh 68d9dcd425
Fix uncaught 500 error on invalid `replies_policy` (Fix #19097) (#20126) 2 years ago
Claire c989faaa62
Change Request connection logic to try both IPv6 and IPv4 when available (#20108) 2 years ago
Roni Laukkarinen 36b0ff57b7
Fix grammar (#20106) 2 years ago
Claire 9b6d6a919f [Glitch] Fix redrafting a currently-editing post not leaving edit mode 2 years ago
Claire fe1b694128 [Glitch] Fix opening the language picker scrolling the single-column view to the top 2 years ago
Zach Flanders 6eac1cfccd [Glitch] Fix spoiler buttons css not rendering correct color in light theme 2 years ago
Claire a8c854b3ea Merge branch 'main' into glitch-soc/merge-upstream 2 years ago
Claire 782b6835f7
Fix redrafting a currently-editing post not leaving edit mode (#20023) 2 years ago
James Tucker 833d9c2f1c
Improve performance by avoiding method cache busts (#19957) 2 years ago
Claire 9f4930ec11
Add password autocomplete hints (#20071) 2 years ago
Claire 608343c135
Fix opening the language picker scrolling the single-column view to the top (#19983) 2 years ago
Postmodern ca80beb653
Micro-optimization: use `if`/`else` instead of `Array#compact` and `Array#min` (#19906) 2 years ago
Zach Flanders 0beb095a4b
Fix spoiler buttons css not rendering correct color in light theme (#19960) 2 years ago
Claire bbf74498f5
Fix validation error in SynchronizeFeaturedTagsCollectionWorker (#20018) 2 years ago
Claire ac219dd1f6
Merge pull request #1903 from ClearlyClaire/glitch-soc/merge-upstream 2 years ago
Claire 2bc22be66c [Glitch] Add aria-expanded to content warning toggle button 2 years ago
Claire be7032b9cf Merge branch 'main' into glitch-soc/merge-upstream 2 years ago
Claire 3114c826a7
Fix filter handling in status cache hydration (#19963) 2 years ago
Postmodern 106648b456
Micro-optimization: only split `acct` into two Strings (#19901) 2 years ago
Eugen Rochko 86a80acf40
New Crowdin updates (#19771) 2 years ago
Claire 622f603ac7
Add aria-expanded to content warning toggle button (#19975) 2 years ago
Claire 1e1289b024
Fix crash when external auth provider has no display_name set (#19962) 2 years ago
Claire e1227457f1
Fix links to the Web UI in notifications (#19981) 2 years ago
Sunny Ripert 8515bc7962
Add form element on focal point modal (#19834) 2 years ago
Claire 5925a31b78
Fix followers count not being updated when migrating follows (#19998) 2 years ago
Claire c493c967d6
Fix light theme issues with the favourite modal and some background colors (#1902) 2 years ago
Claire b67e0c94a6
Merge pull request #1899 from ClearlyClaire/glitch-soc/merge-upstream 2 years ago
Sunny Ripert 7ba13dddfa [Glitch] Fix double button to clear emoji search input 2 years ago
Sunny Ripert 71e68dac4e [Glitch] Fix JavaScript console error on Getting Started column 2 years ago
Sunny Ripert d13a2f7901 [Glitch] Fix console log error on column settings load 2 years ago
Claire 6c0a6097ff Merge branch 'main' into glitch-soc/merge-upstream 2 years ago
Chris Rose a70e2cd649
Tag the OTP field with autocomplete for password managers (#19946) 2 years ago
Sunny Ripert 4b7f32a2a6
Fix double button to clear emoji search input (#19888) 2 years ago
Jeremy Kescher 02a34252ba
Add null check on application in dispute viewer (#19851) 2 years ago
Sunny Ripert ffe735344b
Fix JavaScript console error on Getting Started column (#19891) 2 years ago
Sunny Ripert 34c269310d
Fix console log error on column settings load (#19886) 2 years ago
Claire 4cb2323458
Fix crash in legacy filter creation controller (#19878) 2 years ago
nightpool 54f0f1b9ef
Skip Webfinger cache during migrations as well (#19883) 2 years ago
Rob Petti 8c81db5a41
allow /api/v1/streaming to be used as per documentation (#19896) 2 years ago
rcombs e53fc34e9a
Set autocomplete attr for email field on signup page (#19833) 2 years ago
Claire 54101563bb
Merge pull request #1892 from ClearlyClaire/glitch-soc/merge-upstream 2 years ago
Claire 21d6bc1689 Fix status cache hydration discrepancy 2 years ago
Claire 0be6da42d3 Change glitch-soc composer classes to match upstream 2 years ago
Eugen Rochko c199387558 [Glitch] Fix colors in light theme 2 years ago
Eugen Rochko cbfa5ad5dd [Glitch] Fix wrong colors in the high-contrast theme 2 years ago
Eugen Rochko c883799a1f [Glitch] Change design of link footer 2 years ago
Eugen Rochko d29172a682 [Glitch] Fix missing interpolation of domain in disabled account banner in web UI 2 years ago
Claire b6c0ef70a2 [Glitch] Change sign-in banner to reflect disabled or moved account status 2 years ago
Eugen Rochko 0437159056 [Glitch] Fix showing profile's featured tags on individual statuses 2 years ago
Claire fa293f03fa [Glitch] Fix handling of duplicate and out-of-order notifications in WebUI 2 years ago
Yamagishi Kazutoshi bd220c32f1
Update SECURITY.md (#19869) 2 years ago
Eugen Rochko 01e0cb1cd5 [Glitch] Add assets from Twemoji 14.0 2 years ago
Sunny Ripert 8368f4857c [Glitch] Fix JavaScript console warning when loading notifications 2 years ago
Sunny Ripert 93ccb4a29e [Glitch] Fix JavaScript console error on upload editing status 2 years ago
Eugen Rochko 81334e2bfb [Glitch] Fix limited account hint referencing "your" server when logged out 2 years ago
Claire 6b498fae46 [Glitch] Fix being unable to withdraw follow request when confirmation modal is disabled (#19687) 2 years ago
Claire e42875d195 [Glitch] Fix edits not being immediately reflected 2 years ago
Claire 0ad919b192 Merge branch 'main' into glitch-soc/merge-upstream 2 years ago
Eugen Rochko 5187e4e758
Bump version to 4.0.0rc2 (#19831) 2 years ago
Eugen Rochko 3151b260e2
Fix not using GIN index for account search queries (#19830) 2 years ago
Eugen Rochko 58fc889c6f
Update changelog for 4.0.0rc1 (#19814) 2 years ago
Eugen Rochko ca8d52c2a4
Change design of new list form in web UI (#19801) 2 years ago
Justin Thomas 18ac5f1cc8
version emoji-mart (#19715) 2 years ago
Eugen Rochko b5b1a202cc
Fix missing string in admin UI (#19809) 2 years ago
Hayden c8bf6192e4
Heroku fix (#19807) 2 years ago
Eugen Rochko 3a41fccc43
Change `AUTHORIZED_FETCH` to not block unauthenticated REST API access (#19803) 2 years ago
Eugen Rochko d0c9ac3919
Fix indexing scheduler trying to index when Elasticsearch is disabled (#19805) 2 years ago
Eugen Rochko d54e7ee61e
Fix n+1 queries when rendering initial state JSON (#19795) 2 years ago
Moritz Hedtke c64be9758f
helm: Add documentation to run tootctl commands (#19791) 2 years ago
Eugen Rochko d1de7fb7fa
Fix rendering empty avatar in web UI (#19798) 2 years ago
Eugen Rochko a442f481f8
Fix missing interpolation of domain in disabled account banner in web UI (#19788) 2 years ago
Eugen Rochko 7c65f52692
Change design of moved account banner in web UI (#19790) 2 years ago
eai04191 30e786225e
Remove word-break:keep-all from Dismissable banner message (#19799) 2 years ago
Claire 312d616371
Change sign-in banner to reflect disabled or moved account status (#19773) 2 years ago
Alex Nordlund 0498b106c9
Add S3 existing secret to sidekiq (#19778) 2 years ago
Yarden Shoham 29604763d7
Remove broken link references to bug bounty program (#19779) 2 years ago
Sunny Ripert 887976814a
Fix JavaScript console warning when loading notifications (#19772) 2 years ago
Sunny Ripert c95d9aab56
Fix JavaScript console error on upload editing status (#19769) 2 years ago
Claire 9616f5bb22
Fix compose form submission reloading web interface (#19762) 2 years ago
Claire 2f8fb49d13
Fix users not being able to change their hide_followers_count setting (#1889) 2 years ago
Eugen Rochko 1e7ea50f4c
New Crowdin updates (#19627) 2 years ago
prplecake 34ba7612d1
Fix 'App settings' label visible in sidebar on mobile UI (#1888) 2 years ago
Eugen Rochko c4b92b1aee
Fix n+1 query during status removal (#19753) 2 years ago
Claire bb89f83cc0
Fix additional issues with status cache hydration (#19747) 2 years ago
Claire 03b991de6c
Fix various issues with store hydration (#19746) 2 years ago
Sunny Ripert 0165449e3a
A11y: Explicit <form> element around compose area (#19742) 2 years ago
Claire c2170991c7
Fix reblogs being discarded after the reblogged status (#19731) 2 years ago
Eugen Rochko e02812d5b6
Add assets from Twemoji 14.0 (#19733) 2 years ago
Eugen Rochko b1a219552e
Fix featured tags not saving preferred casing (#19732) 2 years ago
Jeong Arm f002878c95
Make word-break: keep-all for dismissable banner (#19719) 2 years ago
Eugen Rochko 5f9e47be34
Add caching for payload serialization during fan-out (#19642) 2 years ago
Claire b8f6f03956
Fix /users/:username/statuses/:id leading to a soft 404 in web app (#19724) 2 years ago
Claire 4fb0aae636
Change mentions of blocked users to not be processed (#19725) 2 years ago
Eugen Rochko 20aa8881dc
Fix colors in light theme (#19714) 2 years ago
Eugen Rochko 139ea4c981
Fix limited account hint referencing "your" server when logged out (#19711) 2 years ago
Eugen Rochko bfafb114a2
Fix showing profile's featured tags on individual statuses (#19712) 2 years ago
Eugen Rochko 1c3192df6b
Fix wrong colors in the high-contrast theme (#19708) 2 years ago
Eugen Rochko 5825402ed5
Fix design of verified links in web UI (#19709) 2 years ago
Claire 7c8e2b9859
Fix handling of duplicate and out-of-order notifications in WebUI (#19693) 2 years ago
SJang1 053dac2afa
Remove meta tag for official iOS app (#19656) 2 years ago
Claire 9387beb3b3
Change flaky AccountSearchService test (#19650) 2 years ago
Claire 1dca08b76f
Fix admin action logs page (#19649) 2 years ago
Claire cbb440bbc2
Fix being unable to withdraw follow request when confirmation modal is disabled (#19687) 2 years ago
Claire 125322718b
Fix inaccurate admin log entry for re-sending confirmation e-mails (#19674) 2 years ago
Claire 74d40c7d8f
Fix edits not being immediately reflected (#19673) 2 years ago
Claire e0eb39d41b
Fix bookmark import stopping at the first failure (#19669) 2 years ago
Claire e91418436a
Fix mastodon:setup not setting the admin's role properly (#19670) 2 years ago
Claire cb27d89997
Change migration to migrate admins to Owner role rather than Admin role (#19671) 2 years ago
prplecake f359b15303
Allow number of trending hashtags to be customizable (#1884) 2 years ago
txt-file 0f5e6dd02b
Add support for AVIF uploads (#19647) 2 years ago
prplecake 56eb1da0f5
Fix CharacterCount in vanilla UI (#1883) 2 years ago
Eugen Rochko ae07cfb868
Add support for HEIC uploads (#19618) 2 years ago
Claire 6804228fdf
Fix N+1 on mentions in PushUpdateWorker (#19637) 2 years ago
Eugen Rochko 15bae3e0e4
Change post-processing to be deferred only for large media types (#19617) 2 years ago
pea-sys c68e6b52d9
png optimization(loss less) (#19630) 2 years ago
Jeong Arm 55f54be23c
Add translatable scripts (js) (#19624) 2 years ago
Eugen Rochko d0ba77047e
Change max. thumbnail dimensions to 640x360px (360p) (#19619) 2 years ago
Claire 03d9618595
Fix UserCleanupScheduler crash when an unconfirmed account has a moderation note (#19629) 2 years ago
Eugen Rochko fea142fb9a
New Crowdin updates (#19517) 2 years ago
prplecake fc340c9154
Change ul, ol margin-left to 2em (#1879) 2 years ago
prplecake c199556f64
Fix 'App settings' link in basic web UI (#1880) 2 years ago
Jeremy Kescher 41885c8715
Remove/update old "tootsuite" references, except those needed for Docker (#1860) 2 years ago
Claire 968f343006
Merge pull request #1876 from ClearlyClaire/glitch-soc/merge-upstream 2 years ago
Claire bb1ef11c30
Change featured hashtag deletion to be done synchronously (#19590) 2 years ago
Eugen Rochko 2d9a85db6e
Change design of link footer (#19562) 2 years ago
Claire 1fe4e5e38c Merge branch 'main' into glitch-soc/merge-upstream 2 years ago
Eugen Rochko 26478f461c
Remove language filtering from hashtag timelines (#19563) 2 years ago
Claire 5fd758fad1 Merge branch 'main' into glitch-soc/merge-upstream 2 years ago
Claire a529d6d93e
Fix invites (#19560) 2 years ago
Eugen Rochko 8048874a3a [Glitch] Fix sidebar and tabs on settings on small screens in admin UI 2 years ago
Eugen Rochko ebfe393e9c [Glitch] Fix upload progress not communicating processing phase in web UI 2 years ago
Eugen Rochko eb307ec1bd [Glitch] Fix logged out search and changed logged-in search placeholder 2 years ago
Claire eee36267d6 Merge branch 'main' into glitch-soc/merge-upstream 2 years ago
Eugen Rochko ac9fb0d654
Add reputation and followers score boost to SQL-only account search (#19251) 2 years ago
Eugen Rochko 40c7f3e830
Fix account action type validation (#19476) 2 years ago
Eugen Rochko 276b85bc91
Fix admin APIs returning deleted object instead of empty object upon delete (#19479) 2 years ago
Eugen Rochko 5724da0780
Fix language not being saved when editing status (#19543) 2 years ago
Eugen Rochko 3b024c563c
Fix not being able to input featured tag with `#` (#19535) 2 years ago
Eugen Rochko ad83e64795
Fix sidebar and tabs on settings on small screens in admin UI (#19533) 2 years ago
Ben Hardill 6094a916b1
Fix helm chart use of Postgres Password (#19537) 2 years ago
Eugen Rochko 30ef110224
Fix upload progress not communicating processing phase in web UI (#19530) 2 years ago
Yurii Izorkin a449ee8654
nginx: optimize locations (#19438) 2 years ago
Eugen Rochko f910f0dc92
Fix wrong host being used for custom.css when asset host configured (#19521) 2 years ago
Matthias Bethke 7926cb1bc7
fix name of Lao language (#19520) 2 years ago
Eugen Rochko 55af04b253
Fix logged out search and changed logged-in search placeholder (#19514) 2 years ago
Eugen Rochko e6d415bb1f
New Crowdin updates (#19425) 2 years ago
Eugen Rochko dc5c86add7
Fix account migration form ever using outdated account data (#18429) 2 years ago
Eugen Rochko 317ec06dc7
Fix error when uploading malformed CSV import (#19509) 2 years ago
Claire 26ff48ee48 Fix domain block export not exporting blocks with only media rejection 2 years ago
Claire bbdf61c9e4 Revert Home controller test to upstream 2 years ago
Eugen Rochko 8814a1b949 [Glitch] Fix closed registrations message not appearing in web UI 2 years ago
Eugen Rochko 9f6c175550 [Glitch] Fix number of uses being shown again on trending hashtags in web UI 2 years ago
Claire 2cb3dd9364 [Glitch] Change admin announcement edition interface to use datetime-local 2 years ago
Robert Laurenz 047a2f1f1b [Glitch] fix(component): adjust style of counter button to fix overflow issue 2 years ago
Claire b514998dc1 Merge branch 'main' into glitch-soc/merge-upstream 2 years ago
Eugen Rochko 5fa340931e
Fix closed registrations message not appearing in web UI (#19508) 2 years ago
Claire 592147b902 Remove local settings items that make no sense anymore 2 years ago
Claire f405ad69b3 [Glitch] Remove navigation links to /explore when trends are disabled 2 years ago
Eugen Rochko 89fdfb8fe6 [Glitch] Fix redirecting to `/publish` when compose form is visible in web UI 2 years ago
Eugen Rochko 80b53623e1 [Glitch] Change settings area to be separated into categories in admin UI 2 years ago
Eugen Rochko 58e2b0973d [Glitch] Fix media, following and followers tabs in web UI 2 years ago
Eugen Rochko c9d3c7d63a [Glitch] Fix too many featured tags causing navigation panel scroll in web UI 2 years ago
Eugen Rochko 7bb1b917b2 [Glitch] Change featured hashtags to be displayed in navigation panel 2 years ago
Eugen Rochko 2cea6e5564 [Glitch] Remove volume number from hashtags in web UI 2 years ago
Takeshi Umeda 8be350cc82 [Glitch] Add featured tags selector for WebUI 2 years ago
Eugen Rochko a2942fd0b8 [Glitch] Fix `nofollow` rel being removed in web UI 2 years ago
Eugen Rochko e9ccee38a7 [Glitch] Change floating action button to be a button in header in web UI 2 years ago
Claire 05c1dd9114 [Glitch] Add closed registrations modal 2 years ago
Eugen Rochko ce27c6502b [Glitch] Fix notifications about deleted reports not being also deleted 2 years ago
Eugen Rochko 5dfb7ba35c [Glitch] Fix missing delete and redraft link in web UI 2 years ago
Eugen Rochko b36c58b99e [Glitch] Change post editing to be enabled in web UI 2 years ago
Eugen Rochko 2d731dbde6 [Glitch] Add ability to view previous edits of a status in admin UI 2 years ago
Claire d9f182e5f3 [Glitch] Fix WebUI notification settings for new user and new report notifications 2 years ago
Eugen Rochko bfa47eb7d6 [Glitch] Fix language dropdown causing zoom on mobile devices in web UI 2 years ago
Eugen Rochko 1315c149c0 [Glitch] Add error boundary around routes in web UI 2 years ago
Eugen Rochko 92385da9c3 [Glitch] Fix reply not opening compose page on certain screen sizes in web UI 2 years ago
Eugen Rochko 7d3acb1f2c [Glitch] Fix error when rendering limited account in web UI 2 years ago
Claire bda5040085 [Glitch] Change landing page to be /about instead of /explore when trends are disabled 2 years ago
Eugen Rochko f9f0949bd3 [Glitch] Fix case-sensitive look-up for profiles in web UI 2 years ago
Eugen Rochko 5f4f37f432 [Glitch] Fix error on profile in web UI 2 years ago
prplecake b9195f8fb7 [Glitch] Don't use "unfollow language" when cancelling follow requests 2 years ago
Claire 7cfb319283 fixup! [Glitch] Fix logged-out web UI on smaller screens 2 years ago
Claire 885389d279 fixup! [Glitch] Change public accounts pages to mount the web UI 2 years ago
Claire 89e9ec8ae2 fixup! [Glitch] Fix intermediary responsive layout, accessibility on navigation in web UI 2 years ago
Eugen Rochko 9363e5c24e [Glitch] Change public accounts pages to mount the web UI 2 years ago
Eugen Rochko 6013eeea4c [Glitch] Fix missing rules in report modal in web UI 2 years ago
Eugen Rochko 2aa70c112a [Glitch] Fix error while server rules are loading in report modal in web UI 2 years ago
Yamagishi Kazutoshi 39ec0e8398 [Glitch] Fix missing `isCancel` 2 years ago
Yamagishi Kazutoshi e301cfb463 [Glitch] Replace `CancelToken` to `AbortSignal` 2 years ago
Eugen Rochko 67b4ecdd21 [Glitch] Change about page to be mounted in the web UI 2 years ago
Yamagishi Kazutoshi 5d4d4a69f6 [Glitch] Redirect non-logged-in user to owner statuses on single user mode 2 years ago
Yamagishi Kazutoshi 1850166de9 [Glitch] Hide list panel from nav bar in mobile layout 2 years ago
Yamagishi Kazutoshi 1e7f819c85 [Glitch] Fix `ColumnLink` labels not disappearing in mobile UI 2 years ago
Yamagishi Kazutoshi 492ceeceb0 [Glitch] Fix fedi/local timeline nav link always hide 2 years ago
Eugen Rochko c36f28ba77 [Glitch] Fix intermediary responsive layout, accessibility on navigation in web UI 2 years ago
Eugen Rochko dea951cce8 [Glitch] Add dismissable hints to various timelines in web UI 2 years ago
Yamagishi Kazutoshi e5720cd540 [Glitch] Add title to pages with missing title in Web UI 2 years ago
Yamagishi Kazutoshi 8491a3532d [Glitch] Remove timeline preview link from nav panel when not signed-in 2 years ago
Eugen Rochko 07df273f37 [Glitch] Change privacy policy to be rendered in web UI, add REST API 2 years ago
Eugen Rochko b68b96a0cc [Glitch] Add server rules to sign-up flow 2 years ago
Eugen Rochko 206e9593ac [Glitch] Fix logged-out web UI on smaller screens 2 years ago
Eugen Rochko 14ddb85c3b [Glitch] Remove code for rendering public and hashtag timelines outside the web UI 2 years ago
Claire 84da970d6b Fix assets compilation 2 years ago
Claire cb19be67d1 Merge branch 'main' into glitch-soc/merge-upstream 2 years ago
Kangwook Lee (이강욱) dae954ef11
Fix PostgreSQL password reference for jobs (#19504) 2 years ago
Kangwook Lee (이강욱) 223e152312
Add option to enable single user mode (#19503) 2 years ago
Kangwook Lee (이강욱) 9bf6a8af82
Fix PostgreSQL password reference (#19502) 2 years ago
Eugen Rochko 923f06a07c
Fix number of uses being shown again on trending hashtags in web UI (#19484) 2 years ago
Claire d9d722d74b
Change admin announcement edition interface to use datetime-local (#18321) 2 years ago
Robert Laurenz 10922294ff
fix(component): adjust style of counter button to fix overflow issue (#19494) 2 years ago
Claire 371563b0e2
Revert notification design (#1875) 2 years ago
Claire 19765216a1
Fix status prepend design (#1874) 2 years ago
Eugen Rochko 8dfe5179ee
Fix avatars not using image tags in web UI (#19488) 2 years ago
Eugen Rochko 07cc201acc
Fix using wrong policy on status-related actions in admin UI (#19490) 2 years ago
Eugen Rochko 8ae0936ddd
Bump version to 4.0.0rc1 (#19473) 2 years ago
Eugen Rochko 5f733ad83a
Remove unused method `searchable?` on accounts (#19489) 2 years ago
Eugen Rochko 09f04d710d
Change `closed_registrations_message` to `message` and add Markdown (#19486) 2 years ago
Eugen Rochko 371d969403
Fix missing delete and redraft link in web UI (#19485) 2 years ago
Shlee c7bab3318e
Remove duplicate HSTS headers from nginx.conf (#19018) 2 years ago
Eugen Rochko d7595adbf4
Add `--remove-role` option to `tootctl accounts modify` (#19477) 2 years ago
Eugen Rochko 3e18e05330
Fix uncaught error when invalid date is supplied to API (#19480) 2 years ago
Eugen Rochko d2eb726962
Fix notifications about deleted reports not being also deleted (#19475) 2 years ago
Eugen Rochko f6bcf86caf
Fix wrong math function used in search query (#19481) 2 years ago
zunda 52ebfb7792
Store integer settings as integer (#19478) 2 years ago
Eugen Rochko 1546538de9
Fix improperly checking for blocked domain on followed hashtags (#19472) 2 years ago
Claire 2277913f3f
Add closed registrations modal (#19437) 2 years ago
Thor 8be9ee756a Merge remote-tracking branch 'upstream/main' into main 2 years ago
prplecake aafbc82d88
Add "unsafe-eval" to script-src CSP (#18817) 2 years ago
Yamagishi Kazutoshi eebbc5439a
Disable media cache on service worker (#19471) 2 years ago
Yamagishi Kazutoshi 31e23269f9
Fix `/web` prefix (#19468) 2 years ago
Eugen Rochko 8ebff0efcb
Change post editing to be enabled in web UI (#19103) 2 years ago
dependabot[bot] d96fac8b93
Bump utf-8-validate from 5.0.9 to 5.0.10 (#19449) 2 years ago
dependabot[bot] 1f986d2e52
Bump @babel/plugin-proposal-decorators from 7.19.3 to 7.19.6 (#19445) 2 years ago
Eugen Rochko ca6e92fdb8
Fix warning about constants in routes (#19466) 2 years ago
dependabot[bot] 1ce17cf316
Bump jest from 29.1.2 to 29.2.2 (#19467) 2 years ago
Eugen Rochko f8ca3bb2a1
Add ability to view previous edits of a status in admin UI (#19462) 2 years ago
dependabot[bot] dee69be60e
Bump jest-environment-jsdom from 29.1.2 to 29.2.1 (#19393) 2 years ago
dependabot[bot] 3de6c9c02d
Bump babel-jest from 29.1.2 to 29.2.1 (#19444) 2 years ago
dependabot[bot] 940e80a81b
Bump ws from 8.9.0 to 8.10.0 (#19450) 2 years ago
dependabot[bot] 945f44fb6e
Bump npmlog from 7.0.0 to 7.0.1 (#19447) 2 years ago
dependabot[bot] 2015e6b331
Bump react-select from 5.5.1 to 5.5.4 (#19451) 2 years ago
dependabot[bot] 1a05258cd1
Bump eslint-plugin-promise from 6.1.0 to 6.1.1 (#19443) 2 years ago
dependabot[bot] 89fbdcdf30
Bump @babel/plugin-transform-runtime from 7.19.1 to 7.19.6 (#19446) 2 years ago
dependabot[bot] 0f02e97c01
Bump @babel/core from 7.19.3 to 7.19.6 (#19448) 2 years ago
dependabot[bot] 54189e9fc4
Bump bufferutil from 4.0.6 to 4.0.7 (#19442) 2 years ago
Eugen Rochko 7d25f72b9f
Fix negatives values in search index causing queries to fail (#19464) 2 years ago
Eugen Rochko bf0ab3e0fa
Fix vacuum scheduler missing lock, locks never expiring (#19458) 2 years ago
Eugen Rochko 1ae508bf2f
Change unauthenticated search to not support pagination in REST API (#19326) 2 years ago
Eugen Rochko 8f07381856
Revert "Remove preference to aggregate reblogs in home/list feeds (#18112)" (#19463) 2 years ago
Eugen Rochko 487d81fb92
Fix IP blocks not having a unique index (#19456) 2 years ago
Eugen Rochko 6f01111863
Fix wrong size of avatars in admin UI (#19457) 2 years ago
Claire 267978d4fe
Remove navigation links to /explore when trends are disabled (#19415) 2 years ago
Eugen Rochko 0ca29eaa3f
Change layout of posts in web UI (#19423) 2 years ago
Eugen Rochko fcca781aae
Change design of translations in web UI (#19453) 2 years ago
Eugen Rochko 9757c917da
Fix `nofollow` rel being removed in web UI (#19455) 2 years ago
Claire 30453fab80
Add mention of the translation provider when translating a post (#19433) 2 years ago
Claire 8046cf34d6
Change “Translate” button to only show up when a translation backend is configured (#19434) 2 years ago
Claire dd76bbf8b7
Fix WebUI notification settings for new user and new report notifications (#19436) 2 years ago
Eugen Rochko 3ad0a2ae3d
Fix language dropdown causing zoom on mobile devices in web UI (#19428) 2 years ago
Eugen Rochko 73de39e632
Fix media, following and followers tabs in web UI (#19426) 2 years ago
Eugen Rochko 5452af2188
Fix redirecting to `/publish` when compose form is visible in web UI (#19427) 2 years ago
Eugen Rochko 3124f946ee
New Crowdin updates (#19405) 2 years ago
Eugen Rochko 1fd6460b02
Change floating action button to be a button in header in web UI (#19422) 2 years ago
Eugen Rochko c2c14331b2
Fix PWA manifest using `/web` paths (#19421) 2 years ago
Eugen Rochko a43a823768
Add error boundary around routes in web UI (#19412) 2 years ago
Eugen Rochko 56efa8d22f
Fix reply not opening compose page on certain screen sizes in web UI (#19417) 2 years ago
Yamagishi Kazutoshi 45d3b32488
Fix `Settings::FeaturedTagsController` (#19418) 2 years ago
Takeshi Umeda 74ead7d106
Change featured tag updates to add/remove activity (#19409) 2 years ago
Eugen Rochko 73a48318a1
Fix error when rendering limited account in web UI (#19413) 2 years ago
Claire 062b3c9090
Change landing page to be /about instead of /explore when trends are disabled (#19414) 2 years ago
Takeshi Umeda 53e86747e4
Fix duplicate featured tags (#19403) 2 years ago
Takeshi Umeda 1d34eff63f
Add featured tag add/remove activity handler (#19408) 2 years ago
Eugen Rochko 7c152acb2c
Change settings area to be separated into categories in admin UI (#19407) 2 years ago
Eugen Rochko abf6c87ee8
Fix remote account in contact account setting not being used (#19351) 2 years ago
dependabot[bot] c60f9cb865
Bump npmlog from 6.0.2 to 7.0.0 (#19376) 2 years ago
Eugen Rochko e623c07372
New Crowdin updates (#19350) 2 years ago
Takeshi Umeda 7777524145
Fix featured tag display name in setting (#19404) 2 years ago
dependabot[bot] 6faa51edc7
Bump regenerator-runtime from 0.13.9 to 0.13.10 (#19371) 2 years ago
dependabot[bot] 6e1be17b61
Bump stackprof from 0.2.21 to 0.2.22 (#19367) 2 years ago
prplecake b3030187a4
Use DEFAULT_FIELDS_SIZE/MAX_PROFILE_FIELDS value in settings form hint (#1870) 2 years ago
Yamagishi Kazutoshi 94feb2b93f
Fix `FetchFeaturedCollectionService` spec (#19401) 2 years ago
Eugen Rochko 5e908c5a95
Fix case-sensitive look-up for profiles in web UI (#19397) 2 years ago
Eugen Rochko 23d367f544
Fix too many featured tags causing navigation panel scroll in web UI (#19398) 2 years ago
dependabot[bot] 9215ad5f19
Bump postcss from 8.4.17 to 8.4.18 (#19375) 2 years ago
dependabot[bot] 21af674fb2
Bump axios from 1.1.2 to 1.1.3 (#19372) 2 years ago
Eugen Rochko 74738b4993
Fix error on profile in web UI (#19396) 2 years ago
Eugen Rochko 839f893168
Change public accounts pages to mount the web UI (#19319) 2 years ago
Takeshi Umeda b0e3f0312c
Add synchronization of remote featured tags (#19380) 2 years ago
dependabot[bot] d19c7f4a4c
Bump eslint-plugin-react from 7.31.9 to 7.31.10 (#19370) 2 years ago
dependabot[bot] 4d9a3f8ab0
Bump react-select from 5.4.0 to 5.5.1 (#19377) 2 years ago
dependabot[bot] 2792184907
Bump stylelint from 14.13.0 to 14.14.0 (#19373) 2 years ago
dependabot[bot] 7d3d29c418
Bump eslint-plugin-promise from 6.0.1 to 6.1.0 (#19369) 2 years ago
Claire 1e772c984b
Actually fix config/locales-glitch not overriding translation strings (#1872) 2 years ago
Claire f7155becd0
Fix config/locales-glitch not overriding translation strings (#1871) 2 years ago
Eugen Rochko aefa9253d6
Change featured hashtags to be displayed in navigation panel (#19382) 2 years ago
prplecake 1b83040bd4
Don't use "unfollow language" when cancelling follow requests (#19363) 2 years ago
Eugen Rochko 4adb267f91
Fix showing translate button when status has no language in web UI (#19388) 2 years ago
Eugen Rochko 9c7f4ab8e8
Fix missing rules in report modal in web UI (#19387) 2 years ago
Eugen Rochko dd5d99f83f
Fix error on migration page (#19386) 2 years ago
Eugen Rochko 8a1d10cb35
Fix error while server rules are loading in report modal in web UI (#19385) 2 years ago
Yamagishi Kazutoshi 3702afec9f
Add detailed description section to issue template (#19365) 2 years ago
Takeshi Umeda 4c7b5fb6c1
Add featured tags selector for WebUI (#19358) 2 years ago
prplecake c618d3a0a5
Make "No $entity selected" errors more accurate (#19356) 2 years ago
Yamagishi Kazutoshi e02bdc14fd
Fix missing `isCancel` (#19354) 2 years ago
Yamagishi Kazutoshi 219c38b921
Replace `CancelToken` to `AbortSignal` (#19352) 2 years ago
Eugen Rochko f01310dadb
Fix trending statuses returning more than one post by the same author (#19349) 2 years ago
Eugen Rochko 8a9d774a84
New Crowdin updates (#19344) 2 years ago
Eugen Rochko 1bd00036c2
Change about page to be mounted in the web UI (#19345) 2 years ago
Eugen Rochko b04633a961
Add image processing and generate blurhash for server thumbnail (#19348) 2 years ago
Yamagishi Kazutoshi 7afc6a630c
Redirect non-logged-in user to owner statuses on single user mode (#19333) 2 years ago
dependabot[bot] 5f6c0d63e3
Bump axios from 0.27.2 to 1.1.2 (#19341) 2 years ago
dependabot[bot] de345e70d8
Bump express from 4.18.1 to 4.18.2 (#19340) 2 years ago
dependabot[bot] 7f036be169
Bump eslint-plugin-react from 7.31.8 to 7.31.9 (#19342) 2 years ago
dependabot[bot] d868c1ced5
Bump @babel/preset-env from 7.19.3 to 7.19.4 (#19339) 2 years ago
dependabot[bot] adf6fdf0a9
Bump @babel/runtime from 7.19.0 to 7.19.4 (#19343) 2 years ago
Eugen Rochko c70bffd89f
New Crowdin updates (#19330) 2 years ago
Yamagishi Kazutoshi d787343325
Hide list panel from nav bar in mobile layout (#19337) 2 years ago
Yamagishi Kazutoshi 05148e2c77
Fix missing `skip_review?` (#19335) 2 years ago
Yamagishi Kazutoshi 3eef8a7a81
Fix `ColumnLink` labels not disappearing in mobile UI (#19334) 2 years ago
Jeremy Kescher 5f79200a5e
Remove/update old "tootsuite" references, except those needed for Docker (#19327) 2 years ago
Yamagishi Kazutoshi 32c3bd3c53
Use pep440 for Docker image tag rules (#19332) 2 years ago
Yamagishi Kazutoshi d3f1a010e5
Fix fedi/local timeline nav link always hide (#19329) 2 years ago
Eugen Rochko f879c42747
New Crowdin updates (#19317) 2 years ago
Eugen Rochko 0765324622
Fix intermediary responsive layout, accessibility on navigation in web UI (#19324) 2 years ago
Claire 2b00ccdbd5
Fix button to dismiss suggestions not showing up in search results (#19325) 2 years ago
Eugen Rochko f41ec9af05
Add dismissable hints to various timelines in web UI (#19315) 2 years ago
Yamagishi Kazutoshi a5112b51fd
Add title to pages with missing title in Web UI (#19322) 2 years ago
Yamagishi Kazutoshi e82467ca41
Remove timeline preview link from nav panel when not signed-in (#19320) 2 years ago
Eugen Rochko 45ebdb72ca
Add support for language preferences for trending statuses and links (#18288) 2 years ago
Eugen Rochko 678fc4d292
Fix privacy policy being empty if custom setting exists but is empty (#19318) 2 years ago
Eugen Rochko d4b0aa7450
Fix trying to connect to streaming API when logged out in web UI (#19316) 2 years ago
dependabot[bot] d84c53e769
Bump sidekiq-scheduler from 4.0.2 to 4.0.3 (#19314) 2 years ago
Eugen Rochko 9a685e2f8c
New Crowdin updates (#19297) 2 years ago
Eugen Rochko a2ba011326
Change privacy policy to be rendered in web UI, add REST API (#19310) 2 years ago
Eugen Rochko 7fb738c837
Add interaction modal to logged-out web UI (#19306) 2 years ago
trwnh 99a43f0282
Fix #19304 (#19305) 2 years ago
dependabot[bot] 402ee73e24
Bump jest from 29.0.3 to 29.1.2 (#19285) 2 years ago
dependabot[bot] 021ccf46af
Bump babel-jest from 29.0.3 to 29.1.2 (#19275) 2 years ago
dependabot[bot] 34c8707dec
Bump jest-environment-jsdom from 29.0.3 to 29.1.2 (#19282) 2 years ago
Eugen Rochko 93f340a4bf
Remove setting that disables account deletes (#17683) 2 years ago
Eugen Rochko 62782babd0
Change public statuses pages to mount the web UI (#19301) 2 years ago
Eugen Rochko 58d5b28cb0
Remove previous landing page (#19300) 2 years ago
Eugen Rochko 5fd46dddd7
Remove unnecessary sections from welcome e-mail (#19299) 2 years ago
Eugen Rochko 679274465b
Add server rules to sign-up flow (#19296) 2 years ago
Eugen Rochko 26f2586b62
New Crowdin updates (#19289) 2 years ago
Eugen Rochko 0e41d360c0
Change font size of active users in server banner to be larger in web UI (#19295) 2 years ago
Eugen Rochko 9f65909f42
Change public timelines to be filtered by current locale by default (#19291) 2 years ago
Eugen Rochko d2528b26b6
Add server banner to web app, add `GET /api/v2/instance` to REST API (#19294) 2 years ago
Claire cedcece0cc
Fix deleted pinned posts potentially counting towards the pinned posts limit (#19005) 2 years ago
Eugen Rochko 02ba9cfa35
Remove code for rendering public and hashtag timelines outside the web UI (#19257) 2 years ago
Eugen Rochko e2b561e3a5
Fix logged-out web UI on smaller screens (#19263) 2 years ago
  1. 8
      .env.production.sample
  2. 14
      .github/ISSUE_TEMPLATE/1.bug_report.yml
  3. 5
      .github/ISSUE_TEMPLATE/config.yml
  4. 11
      .github/workflows/build-image.yml
  5. 138
      .github/workflows/test-chart.yml
  6. 3
      .gitignore
  7. 1065
      AUTHORS.md
  8. 4
      Aptfile
  9. 216
      CHANGELOG.md
  10. 4
      CONTRIBUTING.md
  11. 7
      Gemfile
  12. 29
      Gemfile.lock
  13. 15
      SECURITY.md
  14. 7
      app.json
  15. 61
      app/controllers/about_controller.rb
  16. 12
      app/controllers/account_follow_controller.rb
  17. 12
      app/controllers/account_unfollow_controller.rb
  18. 59
      app/controllers/accounts_controller.rb
  19. 2
      app/controllers/admin/confirmations_controller.rb
  20. 2
      app/controllers/admin/custom_emojis_controller.rb
  21. 2
      app/controllers/admin/export_domain_blocks_controller.rb
  22. 2
      app/controllers/admin/ip_blocks_controller.rb
  23. 9
      app/controllers/admin/settings/about_controller.rb
  24. 9
      app/controllers/admin/settings/appearance_controller.rb
  25. 9
      app/controllers/admin/settings/branding_controller.rb
  26. 9
      app/controllers/admin/settings/content_retention_controller.rb
  27. 9
      app/controllers/admin/settings/discovery_controller.rb
  28. 9
      app/controllers/admin/settings/other_controller.rb
  29. 9
      app/controllers/admin/settings/registrations_controller.rb
  30. 10
      app/controllers/admin/settings_controller.rb
  31. 2
      app/controllers/admin/site_uploads_controller.rb
  32. 16
      app/controllers/admin/statuses_controller.rb
  33. 2
      app/controllers/admin/trends/links/preview_card_providers_controller.rb
  34. 3
      app/controllers/admin/trends/links_controller.rb
  35. 7
      app/controllers/admin/trends/statuses_controller.rb
  36. 2
      app/controllers/admin/trends/tags_controller.rb
  37. 10
      app/controllers/api/base_controller.rb
  38. 2
      app/controllers/api/v1/accounts/pins_controller.rb
  39. 5
      app/controllers/api/v1/admin/accounts_controller.rb
  40. 6
      app/controllers/api/v1/admin/canonical_email_blocks_controller.rb
  41. 2
      app/controllers/api/v1/admin/domain_allows_controller.rb
  42. 3
      app/controllers/api/v1/admin/domain_blocks_controller.rb
  43. 4
      app/controllers/api/v1/admin/email_domain_blocks_controller.rb
  44. 8
      app/controllers/api/v1/admin/ip_blocks_controller.rb
  45. 6
      app/controllers/api/v1/featured_tags_controller.rb
  46. 2
      app/controllers/api/v1/filters_controller.rb
  47. 23
      app/controllers/api/v1/instances/domain_blocks_controller.rb
  48. 18
      app/controllers/api/v1/instances/extended_descriptions_controller.rb
  49. 18
      app/controllers/api/v1/instances/privacy_policies_controller.rb
  50. 4
      app/controllers/api/v1/lists_controller.rb
  51. 23
      app/controllers/api/v1/statuses_controller.rb
  52. 2
      app/controllers/api/v1/tags_controller.rb
  53. 4
      app/controllers/api/v1/trends/links_controller.rb
  54. 2
      app/controllers/api/v1/trends/tags_controller.rb
  55. 2
      app/controllers/api/v2/admin/accounts_controller.rb
  56. 2
      app/controllers/api/v2/filters/keywords_controller.rb
  57. 2
      app/controllers/api/v2/filters/statuses_controller.rb
  58. 2
      app/controllers/api/v2/media_controller.rb
  59. 14
      app/controllers/api/v2/search_controller.rb
  60. 3
      app/controllers/auth/omniauth_callbacks_controller.rb
  61. 19
      app/controllers/auth/registrations_controller.rb
  62. 3
      app/controllers/concerns/account_controller_concern.rb
  63. 87
      app/controllers/concerns/status_controller_concern.rb
  64. 32
      app/controllers/concerns/web_app_controller_concern.rb
  65. 37
      app/controllers/directories_controller.rb
  66. 6
      app/controllers/follower_accounts_controller.rb
  67. 6
      app/controllers/following_accounts_controller.rb
  68. 35
      app/controllers/home_controller.rb
  69. 2
      app/controllers/oauth/authorizations_controller.rb
  70. 19
      app/controllers/privacy_controller.rb
  71. 31
      app/controllers/public_timelines_controller.rb
  72. 46
      app/controllers/remote_follow_controller.rb
  73. 60
      app/controllers/remote_interaction_controller.rb
  74. 2
      app/controllers/settings/base_controller.rb
  75. 5
      app/controllers/settings/deletes_controller.rb
  76. 6
      app/controllers/settings/featured_tags_controller.rb
  77. 15
      app/controllers/statuses_controller.rb
  78. 11
      app/controllers/tags_controller.rb
  79. 50
      app/helpers/accounts_helper.rb
  80. 20
      app/helpers/admin/action_logs_helper.rb
  81. 8
      app/helpers/admin/settings_helper.rb
  82. 20
      app/helpers/application_helper.rb
  83. 2
      app/helpers/home_helper.rb
  84. 11
      app/helpers/languages_helper.rb
  85. 54
      app/javascript/core/admin.js
  86. 22
      app/javascript/core/public.js
  87. 83
      app/javascript/flavours/glitch/actions/compose.js
  88. 34
      app/javascript/flavours/glitch/actions/featured_tags.js
  89. 2
      app/javascript/flavours/glitch/actions/filters.js
  90. 5
      app/javascript/flavours/glitch/actions/search.js
  91. 61
      app/javascript/flavours/glitch/actions/server.js
  92. 4
      app/javascript/flavours/glitch/actions/timelines.js
  93. 53
      app/javascript/flavours/glitch/api.js
  94. 8
      app/javascript/flavours/glitch/components/account.js
  95. 6
      app/javascript/flavours/glitch/components/animated_number.js
  96. 2
      app/javascript/flavours/glitch/components/avatar.js
  97. 3
      app/javascript/flavours/glitch/components/column_header.js
  98. 51
      app/javascript/flavours/glitch/components/dismissable_banner.js
  99. 5
      app/javascript/flavours/glitch/components/error_boundary.js
  100. 50
      app/javascript/flavours/glitch/components/hashtag.js
  101. Some files were not shown because too many files have changed in this diff Show More

@ -17,7 +17,7 @@
LOCAL_DOMAIN=example.com
# Use this only if you need to run mastodon on a different domain than the one used for federation.
# You can read more about this option on https://github.com/tootsuite/documentation/blob/master/Running-Mastodon/Serving_a_different_domain.md
# You can read more about this option on https://docs.joinmastodon.org/admin/config/#web-domain
# DO *NOT* USE THIS UNLESS YOU KNOW *EXACTLY* WHAT YOU ARE DOING.
# WEB_DOMAIN=mastodon.example.com
@ -247,7 +247,7 @@ SMTP_FROM_ADDRESS=notifications@example.com
# ---------------
# Various ways to customize Mastodon's behavior
# ---------------
# Maximum allowed character count
MAX_TOOT_CHARS=500
@ -279,6 +279,10 @@ MAX_POLL_OPTION_CHARS=100
# Only relevant when elasticsearch is installed
# MAX_SEARCH_RESULTS=20
# Maximum hashtags to display
# Customize the number of hashtags shown in 'Explore'
# MAX_TRENDING_TAGS=10
# Maximum custom emoji file sizes
# If undefined or smaller than MAX_EMOJI_SIZE, the value
# of MAX_EMOJI_SIZE will be used for MAX_REMOTE_EMOJI_SIZE

@ -31,6 +31,11 @@ body:
description: What happened?
validations:
required: true
- type: textarea
attributes:
label: Detailed description
validations:
required: false
- type: textarea
attributes:
label: Specifications
@ -38,5 +43,14 @@ body:
What version or commit hash of Mastodon did you find this bug in?
If a front-end issue, what browser and operating systems were you using?
placeholder: |
Mastodon 3.5.3 (or Edge)
Ruby 2.7.6 (or v3.1.2)
Node.js 16.18.0
Google Chrome 106.0.5249.119
Firefox 105.0.3
etc...
validations:
required: true

@ -2,7 +2,4 @@ blank_issues_enabled: false
contact_links:
- name: GitHub Discussions
url: https://github.com/mastodon/mastodon/discussions
about: Please ask and answer questions here.
- name: Bug Bounty Program
url: https://app.intigriti.com/programs/mastodon/mastodonio/detail
about: Please report security vulnerabilities here.
about: Please ask and answer questions here.

@ -4,14 +4,13 @@ on:
push:
branches:
- 'main'
tags:
- '*'
pull_request:
paths:
- .github/workflows/build-image.yml
- Dockerfile
permissions:
contents: read
packages: write
jobs:
build-image:
@ -30,17 +29,15 @@ jobs:
id: meta
with:
images: ghcr.io/${{ github.repository_owner }}/mastodon
flavor: |
latest=auto
tags: |
type=raw,value=latest,enable={{is_default_branch}}
type=edge,branch=main
type=match,pattern=v(.*),group=0
type=ref,event=pr
type=sha,prefix=,format=long
- uses: docker/build-push-action@v3
with:
context: .
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=registry,ref=ghcr.io/${{ github.repository_owner }}/mastodon:latest
cache-from: type=registry,ref=ghcr.io/${{ github.repository_owner }}/mastodon:edge
cache-to: type=inline

@ -0,0 +1,138 @@
# This is a GitHub workflow defining a set of jobs with a set of steps.
# ref: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
#
name: Test chart
on:
pull_request:
paths:
- "chart/**"
- "!**.md"
- ".github/workflows/test-chart.yml"
push:
paths:
- "chart/**"
- "!**.md"
- ".github/workflows/test-chart.yml"
branches-ignore:
- "dependabot/**"
workflow_dispatch:
permissions:
contents: read
defaults:
run:
working-directory: chart
jobs:
lint-templates:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: "3.x"
- name: Install dependencies (yamllint)
run: pip install yamllint
- run: helm dependency update
- name: helm lint
run: |
helm lint . \
--values dev-values.yaml
- name: helm template
run: |
helm template . \
--values dev-values.yaml \
--output-dir rendered-templates
- name: yamllint (only on templates we manage)
run: |
rm -rf rendered-templates/mastodon/charts
yamllint rendered-templates \
--config-data "{rules: {indentation: {spaces: 2}, line-length: disable}}"
# This job helps us validate that rendered templates are valid k8s resources
# against a k8s api-server, via "helm template --validate", but also that a
# basic configuration can be used to successfully startup mastodon.
#
test-install:
runs-on: ubuntu-22.04
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
include:
# k3s-channel reference: https://update.k3s.io/v1-release/channels
- k3s-channel: latest
- k3s-channel: stable
# This represents the oldest configuration we test against.
#
# The k8s version chosen is based on the oldest still supported k8s
# version among two managed k8s services, GKE, EKS.
# - GKE: https://endoflife.date/google-kubernetes-engine
# - EKS: https://endoflife.date/amazon-eks
#
# The helm client's version can influence what helper functions is
# available for use in the templates, currently we need v3.6.0 or
# higher.
#
- k3s-channel: v1.21
helm-version: v3.6.0
steps:
- uses: actions/checkout@v3
# This action starts a k8s cluster with NetworkPolicy enforcement and
# installs both kubectl and helm.
#
# ref: https://github.com/jupyterhub/action-k3s-helm#readme
#
- uses: jupyterhub/action-k3s-helm@v3
with:
k3s-channel: ${{ matrix.k3s-channel }}
helm-version: ${{ matrix.helm-version }}
metrics-enabled: false
traefik-enabled: false
docker-enabled: false
- run: helm dependency update
# Validate rendered helm templates against the k8s api-server
- name: helm template --validate
run: |
helm template --validate mastodon . \
--values dev-values.yaml
- name: helm install
run: |
helm install mastodon . \
--values dev-values.yaml \
--timeout 10m
# This actions provides a report about the state of the k8s cluster,
# providing logs etc on anything that has failed and workloads marked as
# important.
#
# ref: https://github.com/jupyterhub/action-k8s-namespace-report#readme
#
- name: Kubernetes namespace report
uses: jupyterhub/action-k8s-namespace-report@v1
if: always()
with:
important-workloads: >-
deploy/mastodon-sidekiq
deploy/mastodon-streaming
deploy/mastodon-web
job/mastodon-assets-precompile
job/mastodon-chewy-upgrade
job/mastodon-create-admin
job/mastodon-db-migrate

3
.gitignore vendored

@ -44,6 +44,9 @@
/redis
/elasticsearch
# ignore Helm charts
/chart/*.tgz
# ignore Helm dependency charts
/chart/charts/*.tgz

File diff suppressed because it is too large Load Diff

@ -1,8 +1,8 @@
ffmpeg
libicu[0-9][0-9]
libicu-dev
libidn11
libidn11-dev
libidn12
libidn-dev
libpq-dev
libxdamage1
libxfixes3

@ -3,6 +3,216 @@ Changelog
All notable changes to this project will be documented in this file.
## [4.0.2] - 2022-11-15
### Fixed
- Fix wrong color on mentions hidden behind content warning in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/20724))
- Fix filters from other users being used in the streaming service ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20719))
- Fix `unsafe-eval` being used when `wasm-unsafe-eval` is enough in Content Security Policy ([Gargron](https://github.com/mastodon/mastodon/pull/20729), [prplecake](https://github.com/mastodon/mastodon/pull/20606))
## [4.0.1] - 2022-11-14
### Fixed
- Fix nodes order being sometimes mangled when rewriting emoji ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20677))
## [4.0.0] - 2022-11-14
Some of the features in this release have been funded through the [NGI0 Discovery](https://nlnet.nl/discovery) Fund, a fund established by [NLnet](https://nlnet.nl/) with financial support from the European Commission's [Next Generation Internet](https://ngi.eu/) programme, under the aegis of DG Communications Networks, Content and Technology under grant agreement No 825322.
### Added
- Add ability to filter followed accounts' posts by language ([Gargron](https://github.com/mastodon/mastodon/pull/19095), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19268))
- **Add ability to follow hashtags** ([Gargron](https://github.com/mastodon/mastodon/pull/18809), [Gargron](https://github.com/mastodon/mastodon/pull/18862), [Gargron](https://github.com/mastodon/mastodon/pull/19472), [noellabo](https://github.com/mastodon/mastodon/pull/18924))
- Add ability to filter individual posts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18945))
- **Add ability to translate posts** ([Gargron](https://github.com/mastodon/mastodon/pull/19218), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19433), [Gargron](https://github.com/mastodon/mastodon/pull/19453), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19434), [Gargron](https://github.com/mastodon/mastodon/pull/19388), [ykzts](https://github.com/mastodon/mastodon/pull/19244), [Gargron](https://github.com/mastodon/mastodon/pull/19245))
- Add featured tags to web UI ([noellabo](https://github.com/mastodon/mastodon/pull/19408), [noellabo](https://github.com/mastodon/mastodon/pull/19380), [noellabo](https://github.com/mastodon/mastodon/pull/19358), [noellabo](https://github.com/mastodon/mastodon/pull/19409), [Gargron](https://github.com/mastodon/mastodon/pull/19382), [ykzts](https://github.com/mastodon/mastodon/pull/19418), [noellabo](https://github.com/mastodon/mastodon/pull/19403), [noellabo](https://github.com/mastodon/mastodon/pull/19404), [Gargron](https://github.com/mastodon/mastodon/pull/19398), [Gargron](https://github.com/mastodon/mastodon/pull/19712), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/20018))
- **Add support for language preferences for trending statuses and links** ([Gargron](https://github.com/mastodon/mastodon/pull/18288), [Gargron](https://github.com/mastodon/mastodon/pull/19349), [ykzts](https://github.com/mastodon/mastodon/pull/19335))
- Previously, you could only see trends in your current language
- For less popular languages, that meant empty trends
- Now, trends in your preferred languages' are shown on top, with others beneath
- Add server rules to sign-up flow ([Gargron](https://github.com/mastodon/mastodon/pull/19296))
- Add privacy icons to report modal in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19190))
- Add `noopener` to links to remote profiles in web UI ([shleeable](https://github.com/mastodon/mastodon/pull/19014))
- Add option to open original page in dropdowns of remote content in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/20299))
- Add warning for sensitive audio posts in web UI ([rgroothuijsen](https://github.com/mastodon/mastodon/pull/17885))
- Add language attribute to posts in web UI ([tribela](https://github.com/mastodon/mastodon/pull/18544))
- Add support for uploading WebP files ([Saiv46](https://github.com/mastodon/mastodon/pull/18506))
- Add support for uploading `audio/vnd.wave` files ([tribela](https://github.com/mastodon/mastodon/pull/18737))
- Add support for uploading AVIF files ([txt-file](https://github.com/mastodon/mastodon/pull/19647))
- Add support for uploading HEIC files ([Gargron](https://github.com/mastodon/mastodon/pull/19618))
- Add more debug information when processing remote accounts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/15605), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19209))
- **Add retention policy for cached content and media** ([Gargron](https://github.com/mastodon/mastodon/pull/19232), [zunda](https://github.com/mastodon/mastodon/pull/19478), [Gargron](https://github.com/mastodon/mastodon/pull/19458), [Gargron](https://github.com/mastodon/mastodon/pull/19248))
- Set for how long remote posts or media should be cached on your server
- Hands-off alternative to `tootctl` commands
- **Add customizable user roles** ([Gargron](https://github.com/mastodon/mastodon/pull/18641), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18812), [Gargron](https://github.com/mastodon/mastodon/pull/19040), [tribela](https://github.com/mastodon/mastodon/pull/18825), [tribela](https://github.com/mastodon/mastodon/pull/18826), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18776), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18777), [unextro](https://github.com/mastodon/mastodon/pull/18786), [tribela](https://github.com/mastodon/mastodon/pull/18824), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19436))
- Previously, there were 3 hard-coded roles, user, moderator, and admin
- Create your own roles and decide which permissions they should have
- Add notifications for new reports ([Gargron](https://github.com/mastodon/mastodon/pull/18697), [Gargron](https://github.com/mastodon/mastodon/pull/19475))
- Add ability to select all accounts matching search for batch actions in admin UI ([Gargron](https://github.com/mastodon/mastodon/pull/19053), [Gargron](https://github.com/mastodon/mastodon/pull/19054))
- Add ability to view previous edits of a status in admin UI ([Gargron](https://github.com/mastodon/mastodon/pull/19462))
- Add ability to block sign-ups from IP ([Gargron](https://github.com/mastodon/mastodon/pull/19037))
- **Add webhooks to admin UI** ([Gargron](https://github.com/mastodon/mastodon/pull/18510))
- Add admin API for managing domain allows ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18668))
- Add admin API for managing domain blocks ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18247))
- Add admin API for managing e-mail domain blocks ([Gargron](https://github.com/mastodon/mastodon/pull/19066))
- Add admin API for managing canonical e-mail blocks ([Gargron](https://github.com/mastodon/mastodon/pull/19067))
- Add admin API for managing IP blocks ([Gargron](https://github.com/mastodon/mastodon/pull/19065), [trwnh](https://github.com/mastodon/mastodon/pull/20207))
- Add `sensitized` attribute to accounts in admin REST API ([trwnh](https://github.com/mastodon/mastodon/pull/20094))
- Add `services` and `metadata` to the NodeInfo endpoint ([MFTabriz](https://github.com/mastodon/mastodon/pull/18563))
- Add `--remove-role` option to `tootctl accounts modify` ([Gargron](https://github.com/mastodon/mastodon/pull/19477))
- Add `--days` option to `tootctl media refresh` ([tribela](https://github.com/mastodon/mastodon/pull/18425))
- Add `EMAIL_DOMAIN_LISTS_APPLY_AFTER_CONFIRMATION` environment variable ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18642))
- Add `IP_RETENTION_PERIOD` and `SESSION_RETENTION_PERIOD` environment variables ([kescherCode](https://github.com/mastodon/mastodon/pull/18757))
- Add `http_hidden_proxy` environment variable ([tribela](https://github.com/mastodon/mastodon/pull/18427))
- Add `ENABLE_STARTTLS` environment variable ([erbridge](https://github.com/mastodon/mastodon/pull/20321))
- Add caching for payload serialization during fan-out ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19637), [Gargron](https://github.com/mastodon/mastodon/pull/19642), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19746), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19747), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19963))
- Add assets from Twemoji 14.0 ([Gargron](https://github.com/mastodon/mastodon/pull/19733))
- Add reputation and followers score boost to SQL-only account search ([Gargron](https://github.com/mastodon/mastodon/pull/19251))
- Add Scots, Balaibalan, Láadan, Lingua Franca Nova, Lojban, Toki Pona to languages list ([VyrCossont](https://github.com/mastodon/mastodon/pull/20168))
- Set autocomplete hints for e-mail, password and OTP fields ([rcombs](https://github.com/mastodon/mastodon/pull/19833), [offbyone](https://github.com/mastodon/mastodon/pull/19946), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/20071))
- Add support for DigitalOcean Spaces in setup wizard ([v-aisac](https://github.com/mastodon/mastodon/pull/20573))
### Changed
- **Change brand color and logotypes** ([Gargron](https://github.com/mastodon/mastodon/pull/18592), [Gargron](https://github.com/mastodon/mastodon/pull/18639), [Gargron](https://github.com/mastodon/mastodon/pull/18691), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18634), [Gargron](https://github.com/mastodon/mastodon/pull/19254), [mayaeh](https://github.com/mastodon/mastodon/pull/18710))
- **Change post editing to be enabled in web UI** ([Gargron](https://github.com/mastodon/mastodon/pull/19103))
- **Change web UI to work for logged-out users** ([Gargron](https://github.com/mastodon/mastodon/pull/18961), [Gargron](https://github.com/mastodon/mastodon/pull/19250), [Gargron](https://github.com/mastodon/mastodon/pull/19294), [Gargron](https://github.com/mastodon/mastodon/pull/19306), [Gargron](https://github.com/mastodon/mastodon/pull/19315), [ykzts](https://github.com/mastodon/mastodon/pull/19322), [Gargron](https://github.com/mastodon/mastodon/pull/19412), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19437), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19415), [Gargron](https://github.com/mastodon/mastodon/pull/19348), [Gargron](https://github.com/mastodon/mastodon/pull/19295), [Gargron](https://github.com/mastodon/mastodon/pull/19422), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19414), [Gargron](https://github.com/mastodon/mastodon/pull/19319), [Gargron](https://github.com/mastodon/mastodon/pull/19345), [Gargron](https://github.com/mastodon/mastodon/pull/19310), [Gargron](https://github.com/mastodon/mastodon/pull/19301), [Gargron](https://github.com/mastodon/mastodon/pull/19423), [ykzts](https://github.com/mastodon/mastodon/pull/19471), [ykzts](https://github.com/mastodon/mastodon/pull/19333), [ykzts](https://github.com/mastodon/mastodon/pull/19337), [ykzts](https://github.com/mastodon/mastodon/pull/19272), [ykzts](https://github.com/mastodon/mastodon/pull/19468), [Gargron](https://github.com/mastodon/mastodon/pull/19466), [Gargron](https://github.com/mastodon/mastodon/pull/19457), [Gargron](https://github.com/mastodon/mastodon/pull/19426), [Gargron](https://github.com/mastodon/mastodon/pull/19427), [Gargron](https://github.com/mastodon/mastodon/pull/19421), [Gargron](https://github.com/mastodon/mastodon/pull/19417), [Gargron](https://github.com/mastodon/mastodon/pull/19413), [Gargron](https://github.com/mastodon/mastodon/pull/19397), [Gargron](https://github.com/mastodon/mastodon/pull/19387), [Gargron](https://github.com/mastodon/mastodon/pull/19396), [Gargron](https://github.com/mastodon/mastodon/pull/19385), [ykzts](https://github.com/mastodon/mastodon/pull/19334), [ykzts](https://github.com/mastodon/mastodon/pull/19329), [Gargron](https://github.com/mastodon/mastodon/pull/19324), [Gargron](https://github.com/mastodon/mastodon/pull/19318), [Gargron](https://github.com/mastodon/mastodon/pull/19316), [Gargron](https://github.com/mastodon/mastodon/pull/19263), [trwnh](https://github.com/mastodon/mastodon/pull/19305), [ykzts](https://github.com/mastodon/mastodon/pull/19273), [Gargron](https://github.com/mastodon/mastodon/pull/19801), [Gargron](https://github.com/mastodon/mastodon/pull/19790), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19773), [Gargron](https://github.com/mastodon/mastodon/pull/19798), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19724), [Gargron](https://github.com/mastodon/mastodon/pull/19709), [Gargron](https://github.com/mastodon/mastodon/pull/19514), [Gargron](https://github.com/mastodon/mastodon/pull/19562), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19981), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19978), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/20148), [Gargron](https://github.com/mastodon/mastodon/pull/20302), [cutls](https://github.com/mastodon/mastodon/pull/20400))
- The web app can now be accessed without being logged in
- No more `/web` prefix on web app paths
- Profiles, posts, and other public pages now use the same interface for logged in and logged out users
- The web app displays a server information banner
- Pop-up windows for remote interaction have been replaced with a modal window
- No need to type in your username for remote interaction, copy-paste-to-search method explained
- Various hints throughout the app explain what the different timelines are
- New about page design
- New privacy policy page design shows when the policy was last updated
- All sections of the web app now have appropriate window titles
- The layout of the interface has been streamlined between different screen sizes
- Posts now use more horizontal space
- Change label of publish button to be "Publish" again in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/18583))
- Change language to be carried over on reply in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18557))
- Change "Unfollow" to "Cancel follow request" when request still pending in web UI ([prplecake](https://github.com/mastodon/mastodon/pull/19363))
- **Change post filtering system** ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18058), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19050), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18894), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19051), [noellabo](https://github.com/mastodon/mastodon/pull/18923), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18956), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18744), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/19878), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/20567))
- Filtered keywords and phrases can now be grouped into named categories
- Filtered posts show which exact filter was hit
- Individual posts can be added to a filter
- You can peek inside filtered posts anyway
- Change path of privacy policy page from `/terms` to `/privacy-policy` ([Gargron](https://github.com/mastodon/mastodon/pull/19249))
- Change how hashtags are normalized ([Gargron](https://github.com/mastodon/mastodon/pull/18795), [Gargron](https://github.com/mastodon/mastodon/pull/18863), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18854))
- Change settings area to be separated into categories in admin UI ([Gargron](https://github.com/mastodon/mastodon/pull/19407), [Gargron](https://github.com/mastodon/mastodon/pull/19533))
- Change "No accounts selected" errors to use the appropriate noun in admin UI ([prplecake](https://github.com/mastodon/mastodon/pull/19356))
- Change e-mail domain blocks to match subdomains of blocked domains ([Gargron](https://github.com/mastodon/mastodon/pull/18979))
- Change custom emoji file size limit from 50 KB to 256 KB ([Gargron](https://github.com/mastodon/mastodon/pull/18788))
- Change "Allow trends without prior review" setting to also work for trending posts ([Gargron](https://github.com/mastodon/mastodon/pull/17977))
- Change admin announcements form to use single inputs for date and time in admin UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18321))
- Change search API to be accessible without being logged in ([Gargron](https://github.com/mastodon/mastodon/pull/18963), [Gargron](https://github.com/mastodon/mastodon/pull/19326))
- Change following and followers API to be accessible without being logged in ([Gargron](https://github.com/mastodon/mastodon/pull/18964))
- Change `AUTHORIZED_FETCH` to not block unauthenticated REST API access ([Gargron](https://github.com/mastodon/mastodon/pull/19803))
- Change Helm configuration ([deepy](https://github.com/mastodon/mastodon/pull/18997), [jgsmith](https://github.com/mastodon/mastodon/pull/18415), [deepy](https://github.com/mastodon/mastodon/pull/18941))
- Change mentions of blocked users to not be processed ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19725))
- Change max. thumbnail dimensions to 640x360px (360p) ([Gargron](https://github.com/mastodon/mastodon/pull/19619))
- Change post-processing to be deferred only for large media types ([Gargron](https://github.com/mastodon/mastodon/pull/19617))
- Change link verification to only work for https links without unicode ([Gargron](https://github.com/mastodon/mastodon/pull/20304), [Gargron](https://github.com/mastodon/mastodon/pull/20295))
- Change account deletion requests to spread out over time ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20222))
- Change larger reblogs/favourites numbers to be shortened in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/20303))
- Change incoming activity processing to happen in `ingress` queue ([Gargron](https://github.com/mastodon/mastodon/pull/20264))
- Change notifications to not link show preview cards in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20335))
- Change amount of replies returned for logged out users in REST API ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20355))
- Change in-app links to keep you in-app in web UI ([trwnh](https://github.com/mastodon/mastodon/pull/20540), [Gargron](https://github.com/mastodon/mastodon/pull/20628))
- Change table header to be sticky in admin UI ([sk22](https://github.com/mastodon/mastodon/pull/20442))
### Removed
- Remove setting that disables account deletes ([Gargron](https://github.com/mastodon/mastodon/pull/17683))
- Remove digest e-mails ([Gargron](https://github.com/mastodon/mastodon/pull/17985))
- Remove unnecessary sections from welcome e-mail ([Gargron](https://github.com/mastodon/mastodon/pull/19299))
- Remove item titles from RSS feeds ([Gargron](https://github.com/mastodon/mastodon/pull/18640))
- Remove volume number from hashtags in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/19253))
- Remove Nanobox configuration ([tonyjiang](https://github.com/mastodon/mastodon/pull/17881))
### Fixed
- Fix rules with same priority being sorted non-deterministically ([Gargron](https://github.com/mastodon/mastodon/pull/20623))
- Fix error when invalid domain name is submitted ([Gargron](https://github.com/mastodon/mastodon/pull/19474))
- Fix icons having an image role ([Gargron](https://github.com/mastodon/mastodon/pull/20600))
- Fix connections to IPv6-only servers ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20108))
- Fix unnecessary service worker registration and preloading when logged out in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20341))
- Fix unnecessary and slow regex construction ([raggi](https://github.com/mastodon/mastodon/pull/20215))
- Fix `mailers` queue not being used for mailers ([Gargron](https://github.com/mastodon/mastodon/pull/20274))
- Fix error in webfinger redirect handling ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20260))
- Fix report category not being set to `violation` if rule IDs are provided ([trwnh](https://github.com/mastodon/mastodon/pull/20137))
- Fix nodeinfo metadata attribute being an array instead of an object ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20114))
- Fix account endorsements not being idempotent ([trwnh](https://github.com/mastodon/mastodon/pull/20118))
- Fix status and rule IDs not being strings in admin reports REST API ([trwnh](https://github.com/mastodon/mastodon/pull/20122))
- Fix error on invalid `replies_policy` in REST API ([trwnh](https://github.com/mastodon/mastodon/pull/20126))
- Fix redrafting a currently-editing post not leaving edit mode in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20023))
- Fix performance by avoiding method cache busts ([raggi](https://github.com/mastodon/mastodon/pull/19957))
- Fix opening the language picker scrolling the single-column view to the top in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19983))
- Fix content warning button missing `aria-expanded` attribute in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19975))
- Fix redundant `aria-pressed` attributes in web UI ([Brawaru](https://github.com/mastodon/mastodon/pull/19912))
- Fix crash when external auth provider has no display name set ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19962))
- Fix followers count not being updated when migrating follows ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19998))
- Fix double button to clear emoji search input in web UI ([sunny](https://github.com/mastodon/mastodon/pull/19888))
- Fix missing null check on applications on strike disputes ([kescherCode](https://github.com/mastodon/mastodon/pull/19851))
- Fix featured tags not saving preferred casing ([Gargron](https://github.com/mastodon/mastodon/pull/19732))
- Fix language not being saved when editing status ([Gargron](https://github.com/mastodon/mastodon/pull/19543))
- Fix not being able to input featured tag with hash symbol ([Gargron](https://github.com/mastodon/mastodon/pull/19535))
- Fix user clean-up scheduler crash when an unconfirmed account has a moderation note ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19629))
- Fix being unable to withdraw follow request when confirmation modal is disabled in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19687))
- Fix inaccurate admin log entry for re-sending confirmation e-mails ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19674))
- Fix edits not being immediately reflected ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19673))
- Fix bookmark import stopping at the first failure ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19669))
- Fix account action type validation ([Gargron](https://github.com/mastodon/mastodon/pull/19476))
- Fix upload progress not communicating processing phase in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/19530))
- Fix wrong host being used for custom.css when asset host configured ([Gargron](https://github.com/mastodon/mastodon/pull/19521))
- Fix account migration form ever using outdated account data ([Gargron](https://github.com/mastodon/mastodon/pull/18429), [nightpool](https://github.com/mastodon/mastodon/pull/19883))
- Fix error when uploading malformed CSV import ([Gargron](https://github.com/mastodon/mastodon/pull/19509))
- Fix avatars not using image tags in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/19488))
- Fix handling of duplicate and out-of-order notifications in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19693))
- Fix reblogs being discarded after the reblogged status ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19731))
- Fix indexing scheduler trying to index when Elasticsearch is disabled ([Gargron](https://github.com/mastodon/mastodon/pull/19805))
- Fix n+1 queries when rendering initial state JSON ([Gargron](https://github.com/mastodon/mastodon/pull/19795))
- Fix n+1 query during status removal ([Gargron](https://github.com/mastodon/mastodon/pull/19753))
- Fix OCR not working due to Content Security Policy in web UI ([prplecake](https://github.com/mastodon/mastodon/pull/18817))
- Fix `nofollow` rel being removed in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/19455))
- Fix language dropdown causing zoom on mobile devices in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/19428))
- Fix button to dismiss suggestions not showing up in search results in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19325))
- Fix language dropdown sometimes not appearing in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/19246))
- Fix quickly switching notification filters resulting in empty or incorrect list in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19052), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18960))
- Fix media modal link button in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18877))
- Fix error upon successful account migration ([Gargron](https://github.com/mastodon/mastodon/pull/19386))
- Fix negatives values in search index causing queries to fail ([Gargron](https://github.com/mastodon/mastodon/pull/19464), [Gargron](https://github.com/mastodon/mastodon/pull/19481))
- Fix error when searching for invalid URL ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18580))
- Fix IP blocks not having a unique index ([Gargron](https://github.com/mastodon/mastodon/pull/19456))
- Fix remote account in contact account setting not being used ([Gargron](https://github.com/mastodon/mastodon/pull/19351))
- Fix swallowing mentions of unconfirmed/unapproved users ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19191))
- Fix incorrect and slow cache invalidation when blocking domain and removing media attachments ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19062))
- Fix HTTPs redirect behaviour when running as I2P service ([gi-yt](https://github.com/mastodon/mastodon/pull/18929))
- Fix deleted pinned posts potentially counting towards the pinned posts limit ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19005))
- Fix compatibility with OpenSSL 3.0 ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18449))
- Fix error when a remote report includes a private post the server has no access to ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18760))
- Fix suspicious sign-in mails never being sent ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18599))
- Fix fallback locale when somehow user's locale is an empty string ([tribela](https://github.com/mastodon/mastodon/pull/18543))
- Fix avatar/header not being deleted locally when deleted on remote account ([tribela](https://github.com/mastodon/mastodon/pull/18973))
- Fix missing `,` in Blurhash validation ([noellabo](https://github.com/mastodon/mastodon/pull/18660))
- Fix order by most recent not working for relationships page in admin UI ([tribela](https://github.com/mastodon/mastodon/pull/18996))
- Fix uncaught error when invalid date is supplied to API ([Gargron](https://github.com/mastodon/mastodon/pull/19480))
- Fix REST API sometimes returning HTML on error ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/19135))
- Fix ambiguous column names in `tootctl media refresh` ([tribela](https://github.com/mastodon/mastodon/pull/19206))
- Fix ambiguous column names in `tootctl search deploy` ([mashirozx](https://github.com/mastodon/mastodon/pull/18993))
- Fix `CDN_HOST` not being used in some asset URLs ([tribela](https://github.com/mastodon/mastodon/pull/18662))
- Fix `CAS_DISPLAY_NAME`, `SAML_DISPLAY_NAME` and `OIDC_DISPLAY_NAME` being ignored ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18568))
- Fix various typos in comments throughout the codebase ([luzpaz](https://github.com/mastodon/mastodon/pull/18604))
- Fix CSV import error when rows include unicode characters ([HamptonMakes](https://github.com/mastodon/mastodon/pull/20592))
### Security
- Fix being able to spoof link verification ([Gargron](https://github.com/mastodon/mastodon/pull/20217))
- Fix emoji substitution not applying only to text nodes in backend code ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20641))
- Fix emoji substitution not applying only to text nodes in web UI ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/20640))
- Fix rate limiting for paths with formats ([Gargron](https://github.com/mastodon/mastodon/pull/20675))
- Fix out-of-bound reads in blurhash transcoder ([delroth](https://github.com/mastodon/mastodon/pull/20388))
## [3.5.3] - 2022-05-26
### Added
@ -75,7 +285,7 @@ All notable changes to this project will be documented in this file.
- Remove IP matching from e-mail domain blocks ([Gargron](https://github.com/mastodon/mastodon/pull/18190))
- The IPs of the blocked e-mail domain or its MX records are no longer checked
- Previously it was too easy to block e-mail providers by mistake
## Fixed
- Fix compatibility with Friendica's pinned posts ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/18254), [ClearlyClaire](https://github.com/mastodon/mastodon/pull/18260))
@ -122,7 +332,7 @@ All notable changes to this project will be documented in this file.
### Fixed
- Fix error resposes for `from` search prefix ([single-right-quote](https://github.com/mastodon/mastodon/pull/17963))
- Fix error responses for `from` search prefix ([single-right-quote](https://github.com/mastodon/mastodon/pull/17963))
- Fix dangling language-specific trends ([Gargron](https://github.com/mastodon/mastodon/pull/17997))
- Fix extremely rare race condition when deleting a status or account ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17994))
- Fix trends returning less results per page when filtered in REST API ([Gargron](https://github.com/mastodon/mastodon/pull/17996))
@ -257,7 +467,7 @@ All notable changes to this project will be documented in this file.
- Remove profile directory link from main navigation panel in web UI ([Gargron](https://github.com/mastodon/mastodon/pull/17688))
- **Remove language detection through cld3** ([Gargron](https://github.com/mastodon/mastodon/pull/17478), [ykzts](https://github.com/mastodon/mastodon/pull/17539), [Gargron](https://github.com/mastodon/mastodon/pull/17496), [Gargron](https://github.com/mastodon/mastodon/pull/17722))
- cld3 is very inaccurate on short-form content even with unique alphabets
- Post language can be overriden individually using `language` param
- Post language can be overridden individually using `language` param
- Otherwise, it defaults to the user's interface language
- Remove support for `OAUTH_REDIRECT_AT_SIGN_IN` ([ClearlyClaire](https://github.com/mastodon/mastodon/pull/17287))
- Use `OMNIAUTH_ONLY` instead

@ -27,7 +27,7 @@ See the guidelines below.
- - -
You should also try to follow the guidelines set out in the original `CONTRIBUTING.md` from `tootsuite/mastodon`, reproduced below.
You should also try to follow the guidelines set out in the original `CONTRIBUTING.md` from `mastodon/mastodon`, reproduced below.
<blockquote>
@ -76,6 +76,8 @@ It is not always possible to phrase every change in such a manner, but it is des
- Code style rules (rubocop, eslint)
- Normalization of locale files (i18n-tasks)
**Note**: You may need to log in and authorise the GitHub account your fork of this repository belongs to with CircleCI to enable some of the automated checks to run.
## Documentation
The [Mastodon documentation](https://docs.joinmastodon.org) is a statically generated site. You can [submit merge requests to mastodon/documentation](https://github.com/mastodon/documentation).

@ -72,6 +72,7 @@ gem 'rack-attack', '~> 6.6'
gem 'rack-cors', '~> 1.1', require: 'rack/cors'
gem 'rails-i18n', '~> 6.0'
gem 'rails-settings-cached', '~> 0.6'
gem 'redcarpet', '~> 3.5'
gem 'redis', '~> 4.5', require: ['redis', 'redis/connection/hiredis']
gem 'mario-redis-lock', '~> 1.2', require: 'redis_lock'
gem 'rqrcode', '~> 2.1'
@ -91,15 +92,13 @@ gem 'tty-prompt', '~> 0.23', require: false
gem 'twitter-text', '~> 3.1.0'
gem 'tzinfo-data', '~> 1.2022'
gem 'webpacker', '~> 5.4'
gem 'webpush', git: 'https://github.com/ClearlyClaire/webpush.git', ref: 'f14a4d52e201128b1b00245d11b6de80d6cfdcd9'
gem 'webpush', github: 'ClearlyClaire/webpush', ref: 'f14a4d52e201128b1b00245d11b6de80d6cfdcd9'
gem 'webauthn', '~> 2.5'
gem 'json-ld'
gem 'json-ld-preloaded', '~> 3.2'
gem 'rdf-normalize', '~> 0.5'
gem 'redcarpet', '~> 3.5'
group :development, :test do
gem 'fabrication', '~> 2.30'
gem 'fuubar', '~> 2.5'
@ -123,6 +122,7 @@ group :test do
gem 'simplecov', '~> 0.21', require: false
gem 'webmock', '~> 3.18'
gem 'rspec_junit_formatter', '~> 0.6'
gem 'rack-test', '~> 2.0'
end
group :development do
@ -153,7 +153,6 @@ end
gem 'concurrent-ruby', require: false
gem 'connection_pool', require: false
gem 'xorcist', '~> 1.1'
gem 'hcaptcha', '~> 7.1'

@ -272,7 +272,7 @@ GEM
fog-json (>= 1.0)
ipaddress (>= 0.8)
formatador (0.2.5)
fugit (1.5.3)
fugit (1.7.1)
et-orbi (~> 1, >= 1.2.7)
raabro (~> 1.4)
fuubar (2.5.1)
@ -343,7 +343,7 @@ GEM
multi_json (~> 1.15)
rack (~> 2.2)
rdf (~> 3.2, >= 3.2.9)
json-ld-preloaded (3.2.0)
json-ld-preloaded (3.2.2)
json-ld (~> 3.2)
rdf (~> 3.2)
jsonapi-renderer (0.2.2)
@ -395,7 +395,7 @@ GEM
mario-redis-lock (1.2.1)
redis (>= 3.0.5)
matrix (0.4.2)
memory_profiler (1.0.0)
memory_profiler (1.0.1)
method_source (1.0.0)
microformats (4.4.1)
json (~> 2.2)
@ -414,7 +414,7 @@ GEM
net-ssh (>= 2.6.5, < 8.0.0)
net-ssh (7.0.1)
nio4r (2.5.8)
nokogiri (1.13.8)
nokogiri (1.13.9)
mini_portile2 (~> 2.8.0)
racc (~> 1.4)
nsa (0.2.8)
@ -422,7 +422,7 @@ GEM
concurrent-ruby (~> 1.0, >= 1.0.2)
sidekiq (>= 3.5)
statsd-ruby (~> 1.4, >= 1.4.0)
oj (3.13.21)
oj (3.13.23)
omniauth (1.9.2)
hashie (>= 3.4.6)
rack (>= 1.6.2, < 3)
@ -457,7 +457,7 @@ GEM
parslet (2.0.0)
pastel (0.8.0)
tty-color (~> 0.5)
pg (1.4.3)
pg (1.4.4)
pghero (2.8.3)
activerecord (>= 5)
pkg-config (1.4.9)
@ -600,7 +600,7 @@ GEM
nokogiri (>= 1.10.5)
rexml
ruby2_keywords (0.0.5)
rufus-scheduler (3.8.1)
rufus-scheduler (3.8.2)
fugit (~> 1.1, >= 1.1.6)
safety_net_attestation (0.4.0)
jwt (~> 2.0)
@ -611,16 +611,16 @@ GEM
activerecord (>= 4.0.0)
railties (>= 4.0.0)
semantic_range (3.0.0)
sidekiq (6.5.7)
connection_pool (>= 2.2.5)
sidekiq (6.5.8)
connection_pool (>= 2.2.5, < 3)
rack (~> 2.0)
redis (>= 4.5.0, < 5)
sidekiq-bulk (0.2.0)
sidekiq
sidekiq-scheduler (4.0.2)
sidekiq-scheduler (4.0.3)
redis (>= 4.2.0)
rufus-scheduler (~> 3.2)
sidekiq (>= 4)
sidekiq (>= 4, < 7)
tilt (>= 1.4.0)
sidekiq-unique-jobs (7.1.27)
brpoplpush-redis_script (> 0.1.1, <= 2.0.0)
@ -649,7 +649,7 @@ GEM
sshkit (1.21.2)
net-scp (>= 1.1.2)
net-ssh (>= 2.8.0)
stackprof (0.2.21)
stackprof (0.2.22)
statsd-ruby (1.5.0)
stoplight (3.0.0)
strong_migrations (0.7.9)
@ -664,7 +664,7 @@ GEM
terrapin (0.6.0)
climate_control (>= 0.0.3, < 1.0)
thor (1.2.1)
tilt (2.0.10)
tilt (2.0.11)
tpm-key_attestation (0.11.0)
bindata (~> 2.4)
openssl (> 2.0, < 3.1)
@ -684,7 +684,7 @@ GEM
unf (~> 0.1.0)
tzinfo (2.0.5)
concurrent-ruby (~> 1.0)
tzinfo-data (1.2022.4)
tzinfo-data (1.2022.6)
tzinfo (>= 1.0.0)
unf (0.1.4)
unf_ext
@ -818,6 +818,7 @@ DEPENDENCIES
rack (~> 2.2.4)
rack-attack (~> 6.6)
rack-cors (~> 1.1)
rack-test (~> 2.0)
rails (~> 6.1.7)
rails-controller-testing (~> 1.0)
rails-i18n (~> 6.0)

@ -1,6 +1,6 @@
# Security Policy
If you believe you've identified a security vulnerability in Mastodon (a bug that allows something to happen that shouldn't be possible), you should submit the report through our [Bug Bounty Program][bug-bounty]. Alternatively, you can reach us at <hello@joinmastodon.org>.
If you believe you've identified a security vulnerability in Mastodon (a bug that allows something to happen that shouldn't be possible), you can reach us at <security@joinmastodon.org>.
You should *not* report such issues on GitHub or in other public spaces to give us time to publish a fix for the issue without exposing Mastodon's users to increased risk.
@ -10,11 +10,8 @@ A "vulnerability in Mastodon" is a vulnerability in the code distributed through
## Supported Versions
| Version | Supported |
| ------- | ------------------ |
| 3.5.x | Yes |
| 3.4.x | Yes |
| 3.3.x | No |
| < 3.3 | No |
[bug-bounty]: https://app.intigriti.com/programs/mastodon/mastodonio/detail
| Version | Supported |
| ------- | ----------|
| 4.0.x | Yes |
| 3.5.x | Yes |
| < 3.5 | No |

@ -79,8 +79,13 @@
"description": "SMTP server certificate verification mode. Defaults is 'peer'.",
"required": false
},
"SMTP_ENABLE_STARTTLS": {
"description": "Enable STARTTLS? Default is 'auto'.",
"value": "auto",
"required": false
},
"SMTP_ENABLE_STARTTLS_AUTO": {
"description": "Enable STARTTLS if SMTP server supports it? Default is true.",
"description": "Enable STARTTLS if SMTP server supports it? Deprecated by SMTP_ENABLE_STARTTLS.",
"required": false
}
},

@ -1,72 +1,19 @@
# frozen_string_literal: true
class AboutController < ApplicationController
include RegistrationSpamConcern
include WebAppControllerConcern
before_action :set_pack
skip_before_action :require_functional!
layout 'public'
before_action :require_open_federation!, only: [:show, :more]
before_action :set_body_classes, only: :show
before_action :set_instance_presenter
before_action :set_expires_in, only: [:more]
before_action :set_registration_form_time, only: :show
skip_before_action :require_functional!, only: [:more]
def show; end
def more
flash.now[:notice] = I18n.t('about.instance_actor_flash') if params[:instance_actor]
toc_generator = TOCGenerator.new(@instance_presenter.extended_description)
@rules = Rule.ordered
@contents = toc_generator.html
@table_of_contents = toc_generator.toc
@blocks = DomainBlock.with_user_facing_limitations.by_severity if display_blocks?
def show
expires_in 0, public: true unless user_signed_in?
end
helper_method :display_blocks?
helper_method :display_blocks_rationale?
helper_method :public_fetch_mode?
helper_method :new_user
private
def require_open_federation!
not_found if whitelist_mode?
end
def display_blocks?
Setting.show_domain_blocks == 'all' || (Setting.show_domain_blocks == 'users' && user_signed_in?)
end
def display_blocks_rationale?
Setting.show_domain_blocks_rationale == 'all' || (Setting.show_domain_blocks_rationale == 'users' && user_signed_in?)
end
def new_user
User.new.tap do |user|
user.build_account
user.build_invite_request
end
end
def set_pack
use_pack 'public'
end
def set_instance_presenter
@instance_presenter = InstancePresenter.new
end
def set_body_classes
@hide_navbar = true
end
def set_expires_in
expires_in 0, public: true
end
end

@ -1,12 +0,0 @@
# frozen_string_literal: true
class AccountFollowController < ApplicationController
include AccountControllerConcern
before_action :authenticate_user!
def create
FollowService.new.call(current_user.account, @account, with_rate_limit: true)
redirect_to account_path(@account)
end
end

@ -1,12 +0,0 @@
# frozen_string_literal: true
class AccountUnfollowController < ApplicationController
include AccountControllerConcern
before_action :authenticate_user!
def create
UnfollowService.new.call(current_user.account, @account)
redirect_to account_path(@account)
end
end

@ -9,7 +9,6 @@ class AccountsController < ApplicationController
before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
before_action :set_cache_headers
before_action :set_body_classes
skip_around_action :set_locale, if: -> { [:json, :rss].include?(request.format&.to_sym) }
skip_before_action :require_functional!, unless: :whitelist_mode?
@ -17,26 +16,7 @@ class AccountsController < ApplicationController
def show
respond_to do |format|
format.html do
use_pack 'public'
expires_in 0, public: true unless user_signed_in?
@pinned_statuses = []
@endorsed_accounts = @account.endorsed_accounts.to_a.sample(4)
@featured_hashtags = @account.featured_tags.order(statuses_count: :desc)
if current_account && @account.blocking?(current_account)
@statuses = []
return
end
@pinned_statuses = cached_filtered_status_pins if show_pinned_statuses?
@statuses = cached_filtered_status_page
@rss_url = rss_url
unless @statuses.empty?
@older_url = older_url if @statuses.last.id > filtered_statuses.last.id
@newer_url = newer_url if @statuses.first.id < filtered_statuses.first.id
end
end
format.rss do
@ -56,18 +36,6 @@ class AccountsController < ApplicationController
private
def set_body_classes
@body_classes = 'with-modals'
end
def show_pinned_statuses?
[replies_requested?, media_requested?, tag_requested?, params[:max_id].present?, params[:min_id].present?].none?
end
def filtered_pinned_statuses
@account.pinned_statuses.not_local_only.where(visibility: [:public, :unlisted])
end
def filtered_statuses
default_statuses.tap do |statuses|
statuses.merge!(hashtag_scope) if tag_requested?
@ -114,26 +82,6 @@ class AccountsController < ApplicationController
end
end
def older_url
pagination_url(max_id: @statuses.last.id)
end
def newer_url
pagination_url(min_id: @statuses.first.id)
end
def pagination_url(max_id: nil, min_id: nil)
if tag_requested?
short_account_tag_url(@account, params[:tag], max_id: max_id, min_id: min_id)
elsif media_requested?
short_account_media_url(@account, max_id: max_id, min_id: min_id)
elsif replies_requested?
short_account_with_replies_url(@account, max_id: max_id, min_id: min_id)
else
short_account_url(@account, max_id: max_id, min_id: min_id)
end
end
def media_requested?
request.path.split('.').first.end_with?('/media') && !tag_requested?
end
@ -146,13 +94,6 @@ class AccountsController < ApplicationController
request.path.split('.').first.end_with?(Addressable::URI.parse("/tagged/#{params[:tag]}").normalize)
end
def cached_filtered_status_pins
cache_collection(
filtered_pinned_statuses,
Status
)
end
def cached_filtered_status_page
cache_collection_paginated_by_id(
filtered_statuses,

@ -17,7 +17,7 @@ module Admin
@user.resend_confirmation_instructions
log_action :confirm, @user
log_action :resend, @user
flash[:notice] = I18n.t('admin.accounts.resend_confirmation.success')
redirect_to admin_accounts_path

@ -34,7 +34,7 @@ module Admin
@form = Form::CustomEmojiBatch.new(form_custom_emoji_batch_params.merge(current_account: current_account, action: action_from_button))
@form.save
rescue ActionController::ParameterMissing
flash[:alert] = I18n.t('admin.accounts.no_account_selected')
flash[:alert] = I18n.t('admin.custom_emojis.no_emoji_selected')
rescue Mastodon::NotPermittedError
flash[:alert] = I18n.t('admin.custom_emojis.not_permitted')
rescue ActiveRecord::RecordInvalid => e

@ -62,7 +62,7 @@ module Admin
def export_data
CSV.generate(headers: export_headers, write_headers: true) do |content|
DomainBlock.with_user_facing_limitations.each do |instance|
DomainBlock.with_limitations.each do |instance|
content << [instance.domain, instance.severity, instance.reject_media, instance.reject_reports, instance.public_comment, instance.obfuscate]
end
end

@ -5,7 +5,7 @@ module Admin
def index
authorize :ip_block, :index?
@ip_blocks = IpBlock.page(params[:page])
@ip_blocks = IpBlock.order(ip: :asc).page(params[:page])
@form = Form::IpBlockBatch.new
end

@ -0,0 +1,9 @@
# frozen_string_literal: true
class Admin::Settings::AboutController < Admin::SettingsController
private
def after_update_redirect_path
admin_settings_about_path
end
end

@ -0,0 +1,9 @@
# frozen_string_literal: true
class Admin::Settings::AppearanceController < Admin::SettingsController
private
def after_update_redirect_path
admin_settings_appearance_path
end
end

@ -0,0 +1,9 @@
# frozen_string_literal: true
class Admin::Settings::BrandingController < Admin::SettingsController
private
def after_update_redirect_path
admin_settings_branding_path
end
end

@ -0,0 +1,9 @@
# frozen_string_literal: true
class Admin::Settings::ContentRetentionController < Admin::SettingsController
private
def after_update_redirect_path
admin_settings_content_retention_path
end
end

@ -0,0 +1,9 @@
# frozen_string_literal: true
class Admin::Settings::DiscoveryController < Admin::SettingsController
private
def after_update_redirect_path
admin_settings_discovery_path
end
end

@ -0,0 +1,9 @@
# frozen_string_literal: true
class Admin::Settings::OtherController < Admin::SettingsController
private
def after_update_redirect_path
admin_settings_other_path
end
end

@ -0,0 +1,9 @@
# frozen_string_literal: true
class Admin::Settings::RegistrationsController < Admin::SettingsController
private
def after_update_redirect_path
admin_settings_registrations_path
end
end

@ -2,7 +2,7 @@
module Admin
class SettingsController < BaseController
def edit
def show
authorize :settings, :show?
@admin_settings = Form::AdminSettings.new
@ -15,14 +15,18 @@ module Admin
if @admin_settings.save
flash[:notice] = I18n.t('generic.changes_saved_msg')
redirect_to edit_admin_settings_path
redirect_to after_update_redirect_path
else
render :edit
render :show
end
end
private
def after_update_redirect_path
raise NotImplementedError
end
def settings_params
params.require(:form_admin_settings).permit(*Form::AdminSettings::KEYS)
end

@ -9,7 +9,7 @@ module Admin
@site_upload.destroy!
redirect_to edit_admin_settings_path, notice: I18n.t('admin.site_uploads.destroyed_msg')
redirect_to admin_settings_path, notice: I18n.t('admin.site_uploads.destroyed_msg')
end
private

@ -3,18 +3,23 @@
module Admin
class StatusesController < BaseController
before_action :set_account
before_action :set_statuses
before_action :set_statuses, except: :show
before_action :set_status, only: :show
PER_PAGE = 20
def index
authorize :status, :index?
authorize [:admin, :status], :index?
@status_batch_action = Admin::StatusBatchAction.new
end
def show
authorize [:admin, @status], :show?
end
def batch
authorize :status, :index?
authorize [:admin, :status], :index?
@status_batch_action = Admin::StatusBatchAction.new(admin_status_batch_action_params.merge(current_account: current_account, report_id: params[:report_id], type: action_from_button))
@status_batch_action.save!
@ -32,6 +37,7 @@ module Admin
def after_create_redirect_path
report_id = @status_batch_action&.report_id || params[:report_id]
if report_id.present?
admin_report_path(report_id)
else
@ -43,6 +49,10 @@ module Admin
@account = Account.find(params[:account_id])
end
def set_status
@status = @account.statuses.find(params[:id])
end
def set_statuses
@statuses = Admin::StatusFilter.new(@account, filter_params).results.preload(:application, :preloadable_poll, :media_attachments, active_mentions: :account, reblog: [:account, :application, :preloadable_poll, :media_attachments, active_mentions: :account]).page(params[:page]).per(PER_PAGE)
end

@ -14,7 +14,7 @@ class Admin::Trends::Links::PreviewCardProvidersController < Admin::BaseControll
@form = Trends::PreviewCardProviderBatch.new(trends_preview_card_provider_batch_params.merge(current_account: current_account, action: action_from_button))
@form.save
rescue ActionController::ParameterMissing
flash[:alert] = I18n.t('admin.accounts.no_account_selected')
flash[:alert] = I18n.t('admin.trends.links.publishers.no_publisher_selected')
ensure
redirect_to admin_trends_links_preview_card_providers_path(filter_params)
end

@ -4,6 +4,7 @@ class Admin::Trends::LinksController < Admin::BaseController
def index
authorize :preview_card, :review?
@locales = PreviewCardTrend.pluck('distinct language')
@preview_cards = filtered_preview_cards.page(params[:page])
@form = Trends::PreviewCardBatch.new
end
@ -14,7 +15,7 @@ class Admin::Trends::LinksController < Admin::BaseController
@form = Trends::PreviewCardBatch.new(trends_preview_card_batch_params.merge(current_account: current_account, action: action_from_button))
@form.save
rescue ActionController::ParameterMissing
flash[:alert] = I18n.t('admin.accounts.no_account_selected')
flash[:alert] = I18n.t('admin.trends.links.no_link_selected')
ensure
redirect_to admin_trends_links_path(filter_params)
end

@ -2,19 +2,20 @@
class Admin::Trends::StatusesController < Admin::BaseController
def index
authorize :status, :review?
authorize [:admin, :status], :review?
@locales = StatusTrend.pluck('distinct language')
@statuses = filtered_statuses.page(params[:page])
@form = Trends::StatusBatch.new
end
def batch
authorize :status, :review?
authorize [:admin, :status], :review?
@form = Trends::StatusBatch.new(trends_status_batch_params.merge(current_account: current_account, action: action_from_button))
@form.save
rescue ActionController::ParameterMissing
flash[:alert] = I18n.t('admin.accounts.no_account_selected')
flash[:alert] = I18n.t('admin.trends.statuses.no_status_selected')
ensure
redirect_to admin_trends_statuses_path(filter_params)
end

@ -14,7 +14,7 @@ class Admin::Trends::TagsController < Admin::BaseController
@form = Trends::TagBatch.new(trends_tag_batch_params.merge(current_account: current_account, action: action_from_button))
@form.save
rescue ActionController::ParameterMissing
flash[:alert] = I18n.t('admin.accounts.no_account_selected')
flash[:alert] = I18n.t('admin.trends.tags.no_tag_selected')
ensure
redirect_to admin_trends_tags_path(filter_params)
end

@ -24,6 +24,10 @@ class Api::BaseController < ApplicationController
render json: { error: 'Duplicate record' }, status: 422
end
rescue_from Date::Error do
render json: { error: 'Invalid date supplied' }, status: 422
end
rescue_from ActiveRecord::RecordNotFound do
render json: { error: 'Record not found' }, status: 404
end
@ -53,7 +57,7 @@ class Api::BaseController < ApplicationController
render json: { error: I18n.t('errors.429') }, status: 429
end
rescue_from ActionController::ParameterMissing do |e|
rescue_from ActionController::ParameterMissing, Mastodon::InvalidParameterError do |e|
render json: { error: e.to_s }, status: 400
end
@ -125,11 +129,11 @@ class Api::BaseController < ApplicationController
end
def set_cache_headers
response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate'
response.headers['Cache-Control'] = 'private, no-store'
end
def disallow_unauthenticated_api_access?
authorized_fetch_mode?
ENV['DISALLOW_UNAUTHENTICATED_API_ACCESS'] == 'true' || Rails.configuration.x.whitelist_mode
end
private

@ -8,7 +8,7 @@ class Api::V1::Accounts::PinsController < Api::BaseController
before_action :set_account
def create
AccountPin.create!(account: current_account, target_account: @account)
AccountPin.find_or_create_by!(account: current_account, target_account: @account)
render json: @account, serializer: REST::RelationshipSerializer, relationships: relationships_presenter
end

@ -60,14 +60,13 @@ class Api::V1::Admin::AccountsController < Api::BaseController
def reject
authorize @account.user, :reject?
DeleteAccountService.new.call(@account, reserve_email: false, reserve_username: false)
render json: @account, serializer: REST::Admin::AccountSerializer
render_empty
end
def destroy
authorize @account, :destroy?
json = render_to_body json: @account, serializer: REST::Admin::AccountSerializer
Admin::AccountDeletionWorker.perform_async(@account.id)
render json: json
render_empty
end
def unsensitive

@ -35,20 +35,16 @@ class Api::V1::Admin::CanonicalEmailBlocksController < Api::BaseController
def create
authorize :canonical_email_block, :create?
@canonical_email_block = CanonicalEmailBlock.create!(resource_params)
log_action :create, @canonical_email_block
render json: @canonical_email_block, serializer: REST::Admin::CanonicalEmailBlockSerializer
end
def destroy
authorize @canonical_email_block, :destroy?
@canonical_email_block.destroy!
log_action :destroy, @canonical_email_block
render json: @canonical_email_block, serializer: REST::Admin::CanonicalEmailBlockSerializer
render_empty
end
private

@ -43,7 +43,7 @@ class Api::V1::Admin::DomainAllowsController < Api::BaseController
authorize @domain_allow, :destroy?
UnallowDomainService.new.call(@domain_allow)
log_action :destroy, @domain_allow
render json: @domain_allow, serializer: REST::Admin::DomainAllowSerializer
render_empty
end
private

@ -40,7 +40,6 @@ class Api::V1::Admin::DomainBlocksController < Api::BaseController
def update
authorize @domain_block, :update?
@domain_block.update(domain_block_params)
severity_changed = @domain_block.severity_changed?
@domain_block.save!
@ -53,7 +52,7 @@ class Api::V1::Admin::DomainBlocksController < Api::BaseController
authorize @domain_block, :destroy?
UnblockDomainService.new.call(@domain_block)
log_action :destroy, @domain_block
render json: @domain_block, serializer: REST::Admin::DomainBlockSerializer
render_empty
end
private

@ -39,11 +39,9 @@ class Api::V1::Admin::EmailDomainBlocksController < Api::BaseController
def destroy
authorize @email_domain_block, :destroy?
@email_domain_block.destroy!
log_action :destroy, @email_domain_block
render json: @email_domain_block, serializer: REST::Admin::EmailDomainBlockSerializer
render_empty
end
private

@ -20,10 +20,8 @@ class Api::V1::Admin::IpBlocksController < Api::BaseController
def create
authorize :ip_block, :create?
@ip_block = IpBlock.create!(resource_params)
log_action :create, @ip_block
render json: @ip_block, serializer: REST::Admin::IpBlockSerializer
end
@ -39,20 +37,16 @@ class Api::V1::Admin::IpBlocksController < Api::BaseController
def update
authorize @ip_block, :update?
@ip_block.update(resource_params)
log_action :update, @ip_block
render json: @ip_block, serializer: REST::Admin::IpBlockSerializer
end
def destroy
authorize @ip_block, :destroy?
@ip_block.destroy!
log_action :destroy, @ip_block
render json: @ip_block, serializer: REST::Admin::IpBlockSerializer
render_empty
end
private

@ -13,12 +13,12 @@ class Api::V1::FeaturedTagsController < Api::BaseController
end
def create
@featured_tag = current_account.featured_tags.create!(featured_tag_params)
render json: @featured_tag, serializer: REST::FeaturedTagSerializer
featured_tag = CreateFeaturedTagService.new.call(current_account, featured_tag_params[:name])
render json: featured_tag, serializer: REST::FeaturedTagSerializer
end
def destroy
@featured_tag.destroy!
RemoveFeaturedTagWorker.perform_async(current_account.id, @featured_tag.id)
render_empty
end

@ -52,7 +52,7 @@ class Api::V1::FiltersController < Api::BaseController
end
def resource_params
params.permit(:phrase, :expires_in, :irreversible, :whole_word, context: [])
params.permit(:phrase, :expires_in, :irreversible, context: [])
end
def filter_params

@ -0,0 +1,23 @@
# frozen_string_literal: true
class Api::V1::Instances::DomainBlocksController < Api::BaseController
skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
before_action :require_enabled_api!
before_action :set_domain_blocks
def index
expires_in 3.minutes, public: true
render json: @domain_blocks, each_serializer: REST::DomainBlockSerializer, with_comment: (Setting.show_domain_blocks_rationale == 'all' || (Setting.show_domain_blocks_rationale == 'users' && user_signed_in?))
end
private
def require_enabled_api!
head 404 unless Setting.show_domain_blocks == 'all' || (Setting.show_domain_blocks == 'users' && user_signed_in?)
end
def set_domain_blocks
@domain_blocks = DomainBlock.with_user_facing_limitations.by_severity
end
end

@ -0,0 +1,18 @@
# frozen_string_literal: true
class Api::V1::Instances::ExtendedDescriptionsController < Api::BaseController
skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
before_action :set_extended_description
def show
expires_in 3.minutes, public: true
render json: @extended_description, serializer: REST::ExtendedDescriptionSerializer
end
private
def set_extended_description
@extended_description = ExtendedDescription.current
end
end

@ -0,0 +1,18 @@
# frozen_string_literal: true
class Api::V1::Instances::PrivacyPoliciesController < Api::BaseController
skip_before_action :require_authenticated_user!, unless: :whitelist_mode?
before_action :set_privacy_policy
def show
expires_in 1.day, public: true
render json: @privacy_policy, serializer: REST::PrivacyPolicySerializer
end
private
def set_privacy_policy
@privacy_policy = PrivacyPolicy.current
end
end

@ -7,6 +7,10 @@ class Api::V1::ListsController < Api::BaseController
before_action :require_user!
before_action :set_list, except: [:index, :create]
rescue_from ArgumentError do |e|
render json: { error: e.to_s }, status: 422
end
def index
@lists = List.where(account: current_account).all
render json: @lists, each_serializer: REST::ListSerializer

@ -18,14 +18,29 @@ class Api::V1::StatusesController < Api::BaseController
# than this anyway
CONTEXT_LIMIT = 4_096
# This remains expensive and we don't want to show everything to logged-out users
ANCESTORS_LIMIT = 40
DESCENDANTS_LIMIT = 60
DESCENDANTS_DEPTH_LIMIT = 20
def show
@status = cache_collection([@status], Status).first
render json: @status, serializer: REST::StatusSerializer
end
def context
ancestors_results = @status.in_reply_to_id.nil? ? [] : @status.ancestors(CONTEXT_LIMIT, current_account)
descendants_results = @status.descendants(CONTEXT_LIMIT, current_account)
ancestors_limit = CONTEXT_LIMIT
descendants_limit = CONTEXT_LIMIT
descendants_depth_limit = nil
if current_account.nil?
ancestors_limit = ANCESTORS_LIMIT
descendants_limit = DESCENDANTS_LIMIT
descendants_depth_limit = DESCENDANTS_DEPTH_LIMIT
end
ancestors_results = @status.in_reply_to_id.nil? ? [] : @status.ancestors(ancestors_limit, current_account)
descendants_results = @status.descendants(descendants_limit, current_account, descendants_depth_limit)
loaded_ancestors = cache_collection(ancestors_results, Status)
loaded_descendants = cache_collection(descendants_results, Status)
@ -66,6 +81,7 @@ class Api::V1::StatusesController < Api::BaseController
text: status_params[:status],
media_ids: status_params[:media_ids],
sensitive: status_params[:sensitive],
language: status_params[:language],
spoiler_text: status_params[:spoiler_text],
poll: status_params[:poll],
content_type: status_params[:content_type]
@ -78,7 +94,8 @@ class Api::V1::StatusesController < Api::BaseController
@status = Status.where(account: current_account).find(params[:id])
authorize @status, :destroy?
@status.discard
@status.discard_with_reblogs
StatusPin.find_by(status: @status)&.destroy
@status.account.statuses_count = @status.account.statuses_count - 1
json = render_to_body json: @status, serializer: REST::StatusSerializer, source_requested: true

@ -24,7 +24,7 @@ class Api::V1::TagsController < Api::BaseController
private
def set_or_create_tag
return not_found unless /\A(#{Tag::HASHTAG_NAME_RE})\z/.match?(params[:id])
return not_found unless Tag::HASHTAG_NAME_RE.match?(params[:id])
@tag = Tag.find_normalized(params[:id]) || Tag.new(name: Tag.normalize(params[:id]), display_name: params[:id])
end
end

@ -28,7 +28,9 @@ class Api::V1::Trends::LinksController < Api::BaseController
end
def links_from_trends
Trends.links.query.allowed.in_locale(content_locale)
scope = Trends.links.query.allowed.in_locale(content_locale)
scope = scope.filtered_for(current_account) if user_signed_in?
scope
end
def insert_pagination_headers

@ -5,7 +5,7 @@ class Api::V1::Trends::TagsController < Api::BaseController
after_action :insert_pagination_headers
DEFAULT_TAGS_LIMIT = 10
DEFAULT_TAGS_LIMIT = (ENV['MAX_TRENDING_TAGS'] || 10).to_i
def index
render json: @tags, each_serializer: REST::TagSerializer, relationships: TagRelationshipsPresenter.new(@tags, current_user&.account_id)

@ -33,7 +33,7 @@ class Api::V2::Admin::AccountsController < Api::V1::Admin::AccountsController
end
def filter_params
params.permit(*FILTER_PARAMS)
params.permit(*FILTER_PARAMS, role_ids: [])
end
def pagination_params(core_params)

@ -1,6 +1,6 @@
# frozen_string_literal: true
class Api::V1::Filters::KeywordsController < Api::BaseController
class Api::V2::Filters::KeywordsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:filters' }, only: [:index, :show]
before_action -> { doorkeeper_authorize! :write, :'write:filters' }, except: [:index, :show]
before_action :require_user!

@ -1,6 +1,6 @@
# frozen_string_literal: true
class Api::V1::Filters::StatusesController < Api::BaseController
class Api::V2::Filters::StatusesController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:filters' }, only: [:index, :show]
before_action -> { doorkeeper_authorize! :write, :'write:filters' }, except: [:index, :show]
before_action :require_user!

@ -3,7 +3,7 @@
class Api::V2::MediaController < Api::V1::MediaController
def create
@media_attachment = current_account.media_attachments.create!({ delay_processing: true }.merge(media_attachment_params))
render json: @media_attachment, serializer: REST::MediaAttachmentSerializer, status: 202
render json: @media_attachment, serializer: REST::MediaAttachmentSerializer, status: @media_attachment.not_processed? ? 202 : 200
rescue Paperclip::Errors::NotIdentifiedByImageMagickError
render json: file_type_error, status: 422
rescue Paperclip::Error

@ -5,8 +5,8 @@ class Api::V2::SearchController < Api::BaseController
RESULTS_LIMIT = (ENV['MAX_SEARCH_RESULTS'] || 20).to_i
before_action -> { doorkeeper_authorize! :read, :'read:search' }
before_action :require_user!
before_action -> { authorize_if_got_token! :read, :'read:search' }
before_action :validate_search_params!
def index
@search = Search.new(search_results)
@ -19,6 +19,16 @@ class Api::V2::SearchController < Api::BaseController
private
def validate_search_params!
params.require(:q)
return if user_signed_in?
return render json: { error: 'Search queries pagination is not supported without authentication' }, status: 401 if params[:offset].present?
render json: { error: 'Search queries that resolve remote resources are not supported without authentication' }, status: 401 if truthy_param?(:resolve)
end
def search_results
SearchService.new.call(
params[:q],

@ -18,7 +18,8 @@ class Auth::OmniauthCallbacksController < Devise::OmniauthCallbacksController
)
sign_in_and_redirect @user, event: :authentication
set_flash_message(:notice, :success, kind: Devise.omniauth_configs[provider].strategy.display_name.capitalize) if is_navigational_format?
label = Devise.omniauth_configs[provider]&.strategy&.display_name.presence || I18n.t("auth.providers.#{provider}", default: provider.to_s.chomp('_oauth2').capitalize)
set_flash_message(:notice, :success, kind: label) if is_navigational_format?
else
session["devise.#{provider}_data"] = request.env['omniauth.auth']
redirect_to new_user_registration_url

@ -15,6 +15,8 @@ class Auth::RegistrationsController < Devise::RegistrationsController
before_action :set_body_classes, only: [:new, :create, :edit, :update]
before_action :require_not_suspended!, only: [:update]
before_action :set_cache_headers, only: [:edit, :update]
before_action :set_rules, only: :new
before_action :require_rules_acceptance!, only: :new
before_action :set_registration_form_time, only: :new
skip_before_action :require_functional!, only: [:edit, :update]
@ -56,7 +58,7 @@ class Auth::RegistrationsController < Devise::RegistrationsController
def configure_sign_up_params
devise_parameter_sanitizer.permit(:sign_up) do |u|
u.permit({ account_attributes: [:username], invite_request_attributes: [:text] }, :email, :password, :password_confirmation, :invite_code, :agreement, :website, :confirm_password)
u.permit({ account_attributes: [:username, :display_name], invite_request_attributes: [:text] }, :email, :password, :password_confirmation, :invite_code, :agreement, :website, :confirm_password)
end
end
@ -143,7 +145,20 @@ class Auth::RegistrationsController < Devise::RegistrationsController
forbidden if current_account.suspended?
end
def set_rules
@rules = Rule.ordered
end
def require_rules_acceptance!
return if @rules.empty? || (session[:accept_token].present? && params[:accept] == session[:accept_token])
@accept_token = session[:accept_token] = SecureRandom.hex
@invite_code = invite_code
set_locale { render :rules }
end
def set_cache_headers
response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate'
response.headers['Cache-Control'] = 'private, no-store'
end
end

@ -3,13 +3,12 @@
module AccountControllerConcern
extend ActiveSupport::Concern
include WebAppControllerConcern
include AccountOwnedConcern
FOLLOW_PER_PAGE = 12
included do
layout 'public'
before_action :set_instance_presenter
before_action :set_link_headers, if: -> { request.format.nil? || request.format == :html }
end

@ -1,87 +0,0 @@
# frozen_string_literal: true
module StatusControllerConcern
extend ActiveSupport::Concern
ANCESTORS_LIMIT = 40
DESCENDANTS_LIMIT = 60
DESCENDANTS_DEPTH_LIMIT = 20
def create_descendant_thread(starting_depth, statuses)
depth = starting_depth + statuses.size
if depth < DESCENDANTS_DEPTH_LIMIT
{
statuses: statuses,
starting_depth: starting_depth,
}
else
next_status = statuses.pop
{
statuses: statuses,
starting_depth: starting_depth,
next_status: next_status,
}
end
end
def set_ancestors
@ancestors = @status.reply? ? cache_collection(@status.ancestors(ANCESTORS_LIMIT, current_account), Status) : []
@next_ancestor = @ancestors.size < ANCESTORS_LIMIT ? nil : @ancestors.shift
end
def set_descendants
@max_descendant_thread_id = params[:max_descendant_thread_id]&.to_i
@since_descendant_thread_id = params[:since_descendant_thread_id]&.to_i
descendants = cache_collection(
@status.descendants(
DESCENDANTS_LIMIT,
current_account,
@max_descendant_thread_id,
@since_descendant_thread_id,
DESCENDANTS_DEPTH_LIMIT
),
Status
)
@descendant_threads = []
if descendants.present?
statuses = [descendants.first]
starting_depth = 0
descendants.drop(1).each_with_index do |descendant, index|
if descendants[index].id == descendant.in_reply_to_id
statuses << descendant
else
@descendant_threads << create_descendant_thread(starting_depth, statuses)
# The thread is broken, assume it's a reply to the root status
starting_depth = 0
# ... unless we can find its ancestor in one of the already-processed threads
@descendant_threads.reverse_each do |descendant_thread|
statuses = descendant_thread[:statuses]
index = statuses.find_index do |thread_status|
thread_status.id == descendant.in_reply_to_id
end
if index.present?
starting_depth = descendant_thread[:starting_depth] + index + 1
break
end
end
statuses = [descendant]
end
end
@descendant_threads << create_descendant_thread(starting_depth, statuses)
end
@max_descendant_thread_id = @descendant_threads.pop[:statuses].first.id if descendants.size >= DESCENDANTS_LIMIT
end
end

@ -0,0 +1,32 @@
# frozen_string_literal: true
module WebAppControllerConcern
extend ActiveSupport::Concern
included do
before_action :set_pack
before_action :redirect_unauthenticated_to_permalinks!
before_action :set_app_body_class
before_action :set_referrer_policy_header
end
def set_app_body_class
@body_classes = 'app-body'
end
def set_referrer_policy_header
response.headers['Referrer-Policy'] = 'origin'
end
def redirect_unauthenticated_to_permalinks!
return if user_signed_in?
redirect_path = PermalinkRedirector.new(request.path).redirect_path
redirect_to(redirect_path) if redirect_path.present?
end
def set_pack
use_pack 'home'
end
end

@ -1,37 +0,0 @@
# frozen_string_literal: true
class DirectoriesController < ApplicationController
layout 'public'
before_action :authenticate_user!, if: :whitelist_mode?
before_action :require_enabled!
before_action :set_instance_presenter
before_action :set_accounts
before_action :set_pack
skip_before_action :require_functional!, unless: :whitelist_mode?
def index
render :index
end
private
def set_pack
use_pack 'share'
end
def require_enabled!
return not_found unless Setting.profile_directory
end
def set_accounts
@accounts = Account.local.discoverable.by_recent_status.page(params[:page]).per(20).tap do |query|
query.merge!(Account.not_excluded_by_account(current_account)) if current_account
end
end
def set_instance_presenter
@instance_presenter = InstancePresenter.new
end
end

@ -3,6 +3,7 @@
class FollowerAccountsController < ApplicationController
include AccountControllerConcern
include SignatureVerification
include WebAppControllerConcern
before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
before_action :set_cache_headers
@ -13,12 +14,7 @@ class FollowerAccountsController < ApplicationController
def index
respond_to do |format|
format.html do
use_pack 'public'
expires_in 0, public: true unless user_signed_in?
next if @account.hide_collections?
follows
end
format.json do

@ -3,6 +3,7 @@
class FollowingAccountsController < ApplicationController
include AccountControllerConcern
include SignatureVerification
include WebAppControllerConcern
before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
before_action :set_cache_headers
@ -13,12 +14,7 @@ class FollowingAccountsController < ApplicationController
def index
respond_to do |format|
format.html do
use_pack 'public'
expires_in 0, public: true unless user_signed_in?
next if @account.hide_collections?
follows
end
format.json do

@ -1,47 +1,16 @@
# frozen_string_literal: true
class HomeController < ApplicationController
before_action :redirect_unauthenticated_to_permalinks!
include WebAppControllerConcern
before_action :set_pack
before_action :set_referrer_policy_header
before_action :set_instance_presenter
def index
@body_classes = 'app-body'
expires_in 0, public: true unless user_signed_in?
end
private
def redirect_unauthenticated_to_permalinks!
return if user_signed_in?
redirect_path = PermalinkRedirector.new(request.path).redirect_path
redirect_path ||= default_redirect_path
redirect_to(redirect_path) if redirect_path.present?
end
def set_pack
use_pack 'home'
end
def default_redirect_path
if whitelist_mode?
new_user_session_path
elsif request.path.start_with?('/web')
nil
elsif single_user_mode?
short_account_path(Account.local.without_suspended.where('id > 0').first)
else
about_path
end
end
def set_referrer_policy_header
response.headers['Referrer-Policy'] = 'origin'
end
def set_instance_presenter
@instance_presenter = InstancePresenter.new
end

@ -35,6 +35,6 @@ class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
end
def set_cache_headers
response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate'
response.headers['Cache-Control'] = 'private, no-store'
end
end

@ -1,28 +1,19 @@
# frozen_string_literal: true
class PrivacyController < ApplicationController
layout 'public'
include WebAppControllerConcern
before_action :set_pack
skip_before_action :require_functional!
before_action :set_instance_presenter
before_action :set_expires_in
skip_before_action :require_functional!
def show; end
def show
expires_in 0, public: true if current_account.nil?
end
private
def set_pack
use_pack 'public'
end
def set_instance_presenter
@instance_presenter = InstancePresenter.new
end
def set_expires_in
expires_in 0, public: true
end
end

@ -1,31 +0,0 @@
# frozen_string_literal: true
class PublicTimelinesController < ApplicationController
before_action :set_pack
layout 'public'
before_action :authenticate_user!, if: :whitelist_mode?
before_action :require_enabled!
before_action :set_body_classes
before_action :set_instance_presenter
def show; end
private
def require_enabled!
not_found unless Setting.timeline_preview
end
def set_body_classes
@body_classes = 'with-modals'
end
def set_instance_presenter
@instance_presenter = InstancePresenter.new
end
def set_pack
use_pack 'about'
end
end

@ -1,46 +0,0 @@
# frozen_string_literal: true
class RemoteFollowController < ApplicationController
include AccountOwnedConcern
layout 'modal'
before_action :set_pack
before_action :set_body_classes
skip_before_action :require_functional!
def new
@remote_follow = RemoteFollow.new(session_params)
end
def create
@remote_follow = RemoteFollow.new(resource_params)
if @remote_follow.valid?
session[:remote_follow] = @remote_follow.acct
redirect_to @remote_follow.subscribe_address_for(@account)
else
render :new
end
end
private
def resource_params
params.require(:remote_follow).permit(:acct)
end
def session_params
{ acct: session[:remote_follow] || current_account&.username }
end
def set_pack
use_pack 'modal'
end
def set_body_classes
@body_classes = 'modal-layout'
@hide_header = true
end
end

@ -1,60 +0,0 @@
# frozen_string_literal: true
class RemoteInteractionController < ApplicationController
include Authorization
layout 'modal'
before_action :authenticate_user!, if: :whitelist_mode?
before_action :set_interaction_type
before_action :set_status
before_action :set_body_classes
before_action :set_pack
skip_before_action :require_functional!, unless: :whitelist_mode?
def new
@remote_follow = RemoteFollow.new(session_params)
end
def create
@remote_follow = RemoteFollow.new(resource_params)
if @remote_follow.valid?
session[:remote_follow] = @remote_follow.acct
redirect_to @remote_follow.interact_address_for(@status)
else
render :new
end
end
private
def resource_params
params.require(:remote_follow).permit(:acct)
end
def session_params
{ acct: session[:remote_follow] || current_account&.username }
end
def set_status
@status = Status.find(params[:id])
authorize @status, :show?
rescue Mastodon::NotPermittedError
not_found
end
def set_body_classes
@body_classes = 'modal-layout'
@hide_header = true
end
def set_pack
use_pack 'modal'
end
def set_interaction_type
@interaction_type = %w(reply reblog favourite).include?(params[:type]) ? params[:type] : 'reply'
end
end

@ -19,7 +19,7 @@ class Settings::BaseController < ApplicationController
end
def set_cache_headers
response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate'
response.headers['Cache-Control'] = 'private, no-store'
end
def require_not_suspended!

@ -4,7 +4,6 @@ class Settings::DeletesController < Settings::BaseController
skip_before_action :require_functional!
before_action :require_not_suspended!
before_action :check_enabled_deletion
def show
@confirmation = Form::DeleteConfirmation.new
@ -21,10 +20,6 @@ class Settings::DeletesController < Settings::BaseController
private
def check_enabled_deletion
redirect_to root_path unless Setting.open_deletion
end
def resource_params
params.require(:form_delete_confirmation).permit(:password, :username)
end

@ -10,9 +10,9 @@ class Settings::FeaturedTagsController < Settings::BaseController
end
def create
@featured_tag = current_account.featured_tags.new(featured_tag_params)
@featured_tag = CreateFeaturedTagService.new.call(current_account, featured_tag_params[:name], force: false)
if @featured_tag.save
if @featured_tag.valid?
redirect_to settings_featured_tags_path
else
set_featured_tags
@ -23,7 +23,7 @@ class Settings::FeaturedTagsController < Settings::BaseController
end
def destroy
@featured_tag.destroy!
RemoveFeaturedTagService.new.call(current_account, @featured_tag)
redirect_to settings_featured_tags_path
end

@ -1,21 +1,18 @@
# frozen_string_literal: true
class StatusesController < ApplicationController
include StatusControllerConcern
include WebAppControllerConcern
include SignatureAuthentication
include Authorization
include AccountOwnedConcern
layout 'public'
before_action :require_account_signature!, only: [:show, :activity], if: -> { request.format == :json && authorized_fetch_mode? }
before_action :set_status
before_action :set_instance_presenter
before_action :set_link_headers
before_action :redirect_to_original, only: :show
before_action :set_referrer_policy_header, only: :show
before_action :set_cache_headers
before_action :set_body_classes
before_action :set_body_classes, only: :embed
skip_around_action :set_locale, if: -> { request.format == :json }
skip_before_action :require_functional!, only: [:show, :embed], unless: :whitelist_mode?
@ -27,11 +24,7 @@ class StatusesController < ApplicationController
def show
respond_to do |format|
format.html do
use_pack 'public'
expires_in 10.seconds, public: true if current_account.nil?
set_ancestors
set_descendants
end
format.json do
@ -80,8 +73,4 @@ class StatusesController < ApplicationController
def redirect_to_original
redirect_to ActivityPub::TagManager.instance.url_for(@status.reblog) if @status.reblog?
end
def set_referrer_policy_header
response.headers['Referrer-Policy'] = 'origin' unless @status.distributable?
end
end

@ -2,18 +2,16 @@
class TagsController < ApplicationController
include SignatureVerification
include WebAppControllerConcern
PAGE_SIZE = 20
PAGE_SIZE_MAX = 200
layout 'public'
before_action :require_account_signature!, if: -> { request.format == :json && authorized_fetch_mode? }
before_action :authenticate_user!, if: :whitelist_mode?
before_action :set_local
before_action :set_tag
before_action :set_statuses
before_action :set_body_classes
before_action :set_instance_presenter
skip_before_action :require_functional!, unless: :whitelist_mode?
@ -21,8 +19,7 @@ class TagsController < ApplicationController
def show
respond_to do |format|
format.html do
use_pack 'about'
expires_in 0, public: true
expires_in 0, public: true unless user_signed_in?
end
format.rss do
@ -55,10 +52,6 @@ class TagsController < ApplicationController
end
end
def set_body_classes
@body_classes = 'with-modals'
end
def set_instance_presenter
@instance_presenter = InstancePresenter.new
end

@ -20,54 +20,10 @@ module AccountsHelper
end
def account_action_button(account)
if user_signed_in?
if account.id == current_user.account_id
link_to settings_profile_url, class: 'button logo-button' do
safe_join([logo_as_symbol, t('settings.edit_profile')])
end
elsif current_account.following?(account) || current_account.requested?(account)
link_to account_unfollow_path(account), class: 'button logo-button button--destructive', data: { method: :post } do
safe_join([logo_as_symbol, t('accounts.unfollow')])
end
elsif !(account.memorial? || account.moved?)
link_to account_follow_path(account), class: "button logo-button#{account.blocking?(current_account) ? ' disabled' : ''}", data: { method: :post } do
safe_join([logo_as_symbol, t('accounts.follow')])
end
end
elsif !(account.memorial? || account.moved?)
link_to account_remote_follow_path(account), class: 'button logo-button modal-button', target: '_new' do
safe_join([logo_as_symbol, t('accounts.follow')])
end
end
end
def minimal_account_action_button(account)
if user_signed_in?
return if account.id == current_user.account_id
if current_account.following?(account) || current_account.requested?(account)
link_to account_unfollow_path(account), class: 'icon-button active', data: { method: :post }, title: t('accounts.unfollow') do
fa_icon('user-times fw')
end
elsif !(account.memorial? || account.moved?)
link_to account_follow_path(account), class: "icon-button#{account.blocking?(current_account) ? ' disabled' : ''}", data: { method: :post }, title: t('accounts.follow') do
fa_icon('user-plus fw')
end
end
elsif !(account.memorial? || account.moved?)
link_to account_remote_follow_path(account), class: 'icon-button modal-button', target: '_new', title: t('accounts.follow') do
fa_icon('user-plus fw')
end
end
end
return if account.memorial? || account.moved?
def account_badge(account)
if account.bot?
content_tag(:div, content_tag(:div, t('accounts.roles.bot'), class: 'account-role bot'), class: 'roles')
elsif account.group?
content_tag(:div, content_tag(:div, t('accounts.roles.group'), class: 'account-role group'), class: 'roles')
elsif account.user_role&.highlighted?
content_tag(:div, content_tag(:div, account.user_role.name, class: "account-role user-role-#{account.user_role.id}"), class: 'roles')
link_to ActivityPub::TagManager.instance.url_for(account), class: 'button logo-button', target: '_new' do
safe_join([logo_as_symbol, t('accounts.follow')])
end
end

@ -4,15 +4,19 @@ module Admin::ActionLogsHelper
def log_target(log)
case log.target_type
when 'Account'
link_to log.human_identifier, admin_account_path(log.target_id)
link_to (log.human_identifier.presence || I18n.t('admin.action_logs.deleted_account')), admin_account_path(log.target_id)
when 'User'
link_to log.human_identifier, admin_account_path(log.route_param)
if log.route_param.present?
link_to log.human_identifier, admin_account_path(log.route_param)
else
I18n.t('admin.action_logs.deleted_account')
end
when 'UserRole'
link_to log.human_identifier, admin_roles_path(log.target_id)
when 'Report'
link_to "##{log.human_identifier}", admin_report_path(log.target_id)
link_to "##{log.human_identifier.presence || log.target_id}", admin_report_path(log.target_id)
when 'DomainBlock', 'DomainAllow', 'EmailDomainBlock', 'UnavailableDomain'
link_to log.human_identifier, "https://#{log.human_identifier}"
link_to log.human_identifier, "https://#{log.human_identifier.presence}"
when 'Status'
link_to log.human_identifier, log.permalink
when 'AccountWarning'
@ -22,9 +26,13 @@ module Admin::ActionLogsHelper
when 'IpBlock', 'Instance', 'CustomEmoji'
log.human_identifier
when 'CanonicalEmailBlock'
content_tag(:samp, log.human_identifier[0...7], title: log.human_identifier)
content_tag(:samp, (log.human_identifier.presence || '')[0...7], title: log.human_identifier)
when 'Appeal'
link_to log.human_identifier, disputes_strike_path(log.route_param)
if log.route_param.present?
link_to log.human_identifier, disputes_strike_path(log.route_param.presence)
else
I18n.t('admin.action_logs.deleted_account')
end
end
end
end

@ -1,14 +1,6 @@
# frozen_string_literal: true
module Admin::SettingsHelper
def site_upload_delete_hint(hint, var)
upload = SiteUpload.find_by(var: var.to_s)
return hint unless upload
link = link_to t('admin.site_uploads.delete'), admin_site_upload_path(upload), data: { method: :delete }
safe_join([hint, link], '<br/>'.html_safe)
end
def captcha_available?
ENV['HCAPTCHA_SECRET_KEY'].present? && ENV['HCAPTCHA_SITE_KEY'].present?
end

@ -87,10 +87,6 @@ module ApplicationHelper
link_to label, omniauth_authorize_path(:user, provider), class: "button button-#{provider}", method: :post
end
def open_deletion?
Setting.open_deletion
end
def locale_direction
if RTL_LOCALES.include?(I18n.locale)
'rtl'
@ -199,10 +195,7 @@ module ApplicationHelper
def render_initial_state
state_params = {
settings: {
known_fediverse: Setting.show_known_fediverse_at_about_page,
},
settings: {},
text: [params[:title], params[:text], params[:url]].compact.join(' '),
}
@ -211,7 +204,7 @@ module ApplicationHelper
permit_visibilities.shift(permit_visibilities.index(default_privacy) + 1) if default_privacy.present?
state_params[:visibility] = params[:visibility] if permit_visibilities.include? params[:visibility]
if user_signed_in?
if user_signed_in? && current_user.functional?
state_params[:settings] = state_params[:settings].merge(Web::Setting.find_by(user: current_user)&.data || {})
state_params[:push_subscription] = current_account.user.web_push_subscription(current_session)
state_params[:current_account] = current_account
@ -219,6 +212,15 @@ module ApplicationHelper
state_params[:admin] = Account.find_local(Setting.site_contact_username.strip.gsub(/\A@/, ''))
end
if user_signed_in? && !current_user.functional?
state_params[:disabled_account] = current_account
state_params[:moved_to_account] = current_account.moved_to_account
end
if single_user_mode?
state_params[:owner] = Account.local.without_suspended.where('id > 0').first
end
json = ActiveModelSerializers::SerializableResource.new(InitialStatePresenter.new(state_params), serializer: InitialStateSerializer).to_json
# rubocop:disable Rails/OutputSafety
content_tag(:script, json_escape(json).html_safe, id: 'initial-state', type: 'application/json')

@ -23,7 +23,7 @@ module HomeHelper
else
link_to(path || ActivityPub::TagManager.instance.url_for(account), class: 'account__display-name') do
content_tag(:div, class: 'account__avatar-wrapper') do
image_tag(full_asset_url(current_account&.user&.setting_auto_play_gif ? account.avatar_original_url : account.avatar_static_url), class: 'account__avatar')
image_tag(full_asset_url(current_account&.user&.setting_auto_play_gif ? account.avatar_original_url : account.avatar_static_url), class: 'account__avatar', width: 46, height: 46)
end +
content_tag(:span, class: 'display-name') do
content_tag(:bdi) do

@ -1,4 +1,5 @@
# frozen_string_literal: true
# rubocop:disable Metrics/ModuleLength, Style/WordArray
module LanguagesHelper
ISO_639_1 = {
@ -97,7 +98,7 @@ module LanguagesHelper
lg: ['Ganda', 'Luganda'].freeze,
li: ['Limburgish', 'Limburgs'].freeze,
ln: ['Lingala', 'Lingála'].freeze,
lo: ['Lao', 'ພາສາ'].freeze,
lo: ['Lao', 'ລາວ'].freeze,
lt: ['Lithuanian', 'lietuvių kalba'].freeze,
lu: ['Luba-Katanga', 'Tshiluba'].freeze,
lv: ['Latvian', 'latviešu valoda'].freeze,
@ -189,8 +190,14 @@ module LanguagesHelper
ISO_639_3 = {
ast: ['Asturian', 'Asturianu'].freeze,
ckb: ['Sorani (Kurdish)', 'سۆرانی'].freeze,
jbo: ['Lojban', 'la .lojban.'].freeze,
kab: ['Kabyle', 'Taqbaylit'].freeze,
kmr: ['Kurmanji (Kurdish)', 'Kurmancî'].freeze,
ldn: ['Láadan', 'Láadan'].freeze,
lfn: ['Lingua Franca Nova', 'lingua franca nova'].freeze,
sco: ['Scots', 'Scots'].freeze,
tok: ['Toki Pona', 'toki pona'].freeze,
zba: ['Balaibalan', 'باليبلن'].freeze,
zgh: ['Standard Moroccan Tamazight', 'ⵜⴰⵎⴰⵣⵉⵖⵜ'].freeze,
}.freeze
@ -259,3 +266,5 @@ module LanguagesHelper
locale_name.to_sym if locale_name.present? && I18n.available_locales.include?(locale_name.to_sym)
end
end
# rubocop:enable Metrics/ModuleLength, Style/WordArray

@ -4,6 +4,24 @@ import 'packs/public-path';
import { delegate } from '@rails/ujs';
import ready from '../mastodon/ready';
const setAnnouncementEndsAttributes = (target) => {
const valid = target?.value && target?.validity?.valid;
const element = document.querySelector('input[type="datetime-local"]#announcement_ends_at');
if (valid) {
element.classList.remove('optional');
element.required = true;
element.min = target.value;
} else {
element.classList.add('optional');
element.removeAttribute('required');
element.removeAttribute('min');
}
};
delegate(document, 'input[type="datetime-local"]#announcement_starts_at', 'change', ({ target }) => {
setAnnouncementEndsAttributes(target);
});
const batchCheckboxClassName = '.batch-checkbox input[type="checkbox"]';
const showSelectAll = () => {
@ -143,6 +161,20 @@ const onChangeRegistrationMode = (target) => {
});
};
const convertUTCDateTimeToLocal = (value) => {
const date = new Date(value + 'Z');
const twoChars = (x) => (x.toString().padStart(2, '0'));
return `${date.getFullYear()}-${twoChars(date.getMonth()+1)}-${twoChars(date.getDate())}T${twoChars(date.getHours())}:${twoChars(date.getMinutes())}`;
};
const convertLocalDatetimeToUTC = (value) => {
const re = /^([0-9]{4,})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2})/;
const match = re.exec(value);
const date = new Date(match[1], match[2] - 1, match[3], match[4], match[5]);
const fullISO8601 = date.toISOString();
return fullISO8601.slice(0, fullISO8601.indexOf('T') + 6);
};
delegate(document, '#form_admin_settings_registrations_mode', 'change', ({ target }) => onChangeRegistrationMode(target));
ready(() => {
@ -170,4 +202,26 @@ ready(() => {
e.target.href = url;
}
});
[].forEach.call(document.querySelectorAll('input[type="datetime-local"]'), element => {
if (element.value) {
element.value = convertUTCDateTimeToLocal(element.value);
}
if (element.placeholder) {
element.placeholder = convertUTCDateTimeToLocal(element.placeholder);
}
});
delegate(document, 'form', 'submit', ({ target }) => {
[].forEach.call(target.querySelectorAll('input[type="datetime-local"]'), element => {
if (element.value && element.validity.valid) {
element.value = convertLocalDatetimeToUTC(element.value);
}
});
});
const announcementStartsAt = document.querySelector('input[type="datetime-local"]#announcement_starts_at');
if (announcementStartsAt) {
setAnnouncementEndsAttributes(announcementStartsAt);
}
});

@ -6,28 +6,6 @@ import ready from '../mastodon/ready';
const { delegate } = require('@rails/ujs');
const { length } = require('stringz');
delegate(document, '.webapp-btn', 'click', ({ target, button }) => {
if (button !== 0) {
return true;
}
window.location.href = target.href;
return false;
});
delegate(document, '.modal-button', 'click', e => {
e.preventDefault();
let href;
if (e.target.nodeName !== 'A') {
href = e.target.parentNode.href;
} else {
href = e.target.href;
}
window.open(href, 'mastodon-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes');
});
const getProfileAvatarAnimationHandler = (swapTo) => {
//animate avatar gifs on the profile page when moused over
return ({ target }) => {

@ -1,19 +1,21 @@
import api from '../api';
import { CancelToken, isCancel } from 'axios';
import axios from 'axios';
import { throttle } from 'lodash';
import { defineMessages } from 'react-intl';
import api from 'flavours/glitch/api';
import { search as emojiSearch } from 'flavours/glitch/features/emoji/emoji_mart_search_light';
import { useEmoji } from './emojis';
import { tagHistory } from '../settings';
import { tagHistory } from 'flavours/glitch/settings';
import { recoverHashtags } from 'flavours/glitch/utils/hashtag';
import resizeImage from 'flavours/glitch/utils/resize_image';
import { importFetchedAccounts } from './importer';
import { updateTimeline } from './timelines';
import { showAlertForError } from './alerts';
import { showAlert } from './alerts';
import { showAlert, showAlertForError } from './alerts';
import { useEmoji } from './emojis';
import { importFetchedAccounts, importFetchedStatus } from './importer';
import { openModal } from './modal';
import { defineMessages } from 'react-intl';
import { updateTimeline } from './timelines';
let cancelFetchComposeSuggestionsAccounts, cancelFetchComposeSuggestionsTags;
/** @type {AbortController | undefined} */
let fetchComposeSuggestionsAccountsController;
/** @type {AbortController | undefined} */
let fetchComposeSuggestionsTagsController;
export const COMPOSE_CHANGE = 'COMPOSE_CHANGE';
export const COMPOSE_CYCLE_ELEFRIEND = 'COMPOSE_CYCLE_ELEFRIEND';
@ -25,11 +27,13 @@ export const COMPOSE_REPLY_CANCEL = 'COMPOSE_REPLY_CANCEL';
export const COMPOSE_DIRECT = 'COMPOSE_DIRECT';
export const COMPOSE_MENTION = 'COMPOSE_MENTION';
export const COMPOSE_RESET = 'COMPOSE_RESET';
export const COMPOSE_UPLOAD_REQUEST = 'COMPOSE_UPLOAD_REQUEST';
export const COMPOSE_UPLOAD_SUCCESS = 'COMPOSE_UPLOAD_SUCCESS';
export const COMPOSE_UPLOAD_FAIL = 'COMPOSE_UPLOAD_FAIL';
export const COMPOSE_UPLOAD_PROGRESS = 'COMPOSE_UPLOAD_PROGRESS';
export const COMPOSE_UPLOAD_UNDO = 'COMPOSE_UPLOAD_UNDO';
export const COMPOSE_UPLOAD_REQUEST = 'COMPOSE_UPLOAD_REQUEST';
export const COMPOSE_UPLOAD_SUCCESS = 'COMPOSE_UPLOAD_SUCCESS';
export const COMPOSE_UPLOAD_FAIL = 'COMPOSE_UPLOAD_FAIL';
export const COMPOSE_UPLOAD_PROGRESS = 'COMPOSE_UPLOAD_PROGRESS';
export const COMPOSE_UPLOAD_PROCESSING = 'COMPOSE_UPLOAD_PROCESSING';
export const COMPOSE_UPLOAD_UNDO = 'COMPOSE_UPLOAD_UNDO';
export const THUMBNAIL_UPLOAD_REQUEST = 'THUMBNAIL_UPLOAD_REQUEST';
export const THUMBNAIL_UPLOAD_SUCCESS = 'THUMBNAIL_UPLOAD_SUCCESS';
@ -83,10 +87,8 @@ const messages = defineMessages({
uploadErrorPoll: { id: 'upload_error.poll', defaultMessage: 'File upload not allowed with polls.' },
});
const COMPOSE_PANEL_BREAKPOINT = 600 + (285 * 1) + (10 * 1);
export const ensureComposeIsVisible = (getState, routerHistory) => {
if (!getState().getIn(['compose', 'mounted']) && window.innerWidth < COMPOSE_PANEL_BREAKPOINT) {
if (!getState().getIn(['compose', 'mounted'])) {
routerHistory.push('/publish');
}
};
@ -221,6 +223,10 @@ export function submitCompose(routerHistory) {
}
};
if (statusId) {
dispatch(importFetchedStatus({ ...response.data }));
}
if (statusId === null) {
insertIfOnline('home');
}
@ -307,13 +313,16 @@ export function uploadCompose(files) {
if (status === 200) {
dispatch(uploadComposeSuccess(data, f));
} else if (status === 202) {
dispatch(uploadComposeProcessing());
let tryCount = 1;
const poll = () => {
api(getState).get(`/api/v1/media/${data.id}`).then(response => {
if (response.status === 200) {
dispatch(uploadComposeSuccess(response.data, f));
} else if (response.status === 206) {
let retryAfter = (Math.log2(tryCount) || 1) * 1000;
const retryAfter = (Math.log2(tryCount) || 1) * 1000;
tryCount += 1;
setTimeout(() => poll(), retryAfter);
}
@ -328,6 +337,10 @@ export function uploadCompose(files) {
};
};
export const uploadComposeProcessing = () => ({
type: COMPOSE_UPLOAD_PROCESSING,
});
export const uploadThumbnail = (id, file) => (dispatch, getState) => {
dispatch(uploadThumbnailRequest());
@ -472,8 +485,8 @@ export function undoUploadCompose(media_id) {
};
export function clearComposeSuggestions() {
if (cancelFetchComposeSuggestionsAccounts) {
cancelFetchComposeSuggestionsAccounts();
if (fetchComposeSuggestionsAccountsController) {
fetchComposeSuggestionsAccountsController.abort();
}
return {
type: COMPOSE_SUGGESTIONS_CLEAR,
@ -481,14 +494,14 @@ export function clearComposeSuggestions() {
};
const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) => {
if (cancelFetchComposeSuggestionsAccounts) {
cancelFetchComposeSuggestionsAccounts();
if (fetchComposeSuggestionsAccountsController) {
fetchComposeSuggestionsAccountsController.abort();
}
fetchComposeSuggestionsAccountsController = new AbortController();
api(getState).get('/api/v1/accounts/search', {
cancelToken: new CancelToken(cancel => {
cancelFetchComposeSuggestionsAccounts = cancel;
}),
signal: fetchComposeSuggestionsAccountsController.signal,
params: {
q: token.slice(1),
@ -499,9 +512,11 @@ const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) =>
dispatch(importFetchedAccounts(response.data));
dispatch(readyComposeSuggestionsAccounts(token, response.data));
}).catch(error => {
if (!isCancel(error)) {
if (!axios.isCancel(error)) {
dispatch(showAlertForError(error));
}
}).finally(() => {
fetchComposeSuggestionsAccountsController = undefined;
});
}, 200, { leading: true, trailing: true });
@ -511,16 +526,16 @@ const fetchComposeSuggestionsEmojis = (dispatch, getState, token) => {
};
const fetchComposeSuggestionsTags = throttle((dispatch, getState, token) => {
if (cancelFetchComposeSuggestionsTags) {
cancelFetchComposeSuggestionsTags();
if (fetchComposeSuggestionsTagsController) {
fetchComposeSuggestionsTagsController.abort();
}
dispatch(updateSuggestionTags(token));
fetchComposeSuggestionsTagsController = new AbortController();
api(getState).get('/api/v2/search', {
cancelToken: new CancelToken(cancel => {
cancelFetchComposeSuggestionsTags = cancel;
}),
signal: fetchComposeSuggestionsTagsController.signal,
params: {
type: 'hashtags',
@ -531,9 +546,11 @@ const fetchComposeSuggestionsTags = throttle((dispatch, getState, token) => {
}).then(({ data }) => {
dispatch(readyComposeSuggestionsTags(token, data.hashtags));
}).catch(error => {
if (!isCancel(error)) {
if (!axios.isCancel(error)) {
dispatch(showAlertForError(error));
}
}).finally(() => {
fetchComposeSuggestionsTagsController = undefined;
});
}, 200, { leading: true, trailing: true });

@ -0,0 +1,34 @@
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(getState).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,
});

@ -43,7 +43,7 @@ export const fetchFilters = () => (dispatch, getState) => {
export const createFilterStatus = (params, onSuccess, onFail) => (dispatch, getState) => {
dispatch(createFilterStatusRequest());
api(getState).post(`/api/v1/filters/${params.filter_id}/statuses`, params).then(response => {
api(getState).post(`/api/v2/filters/${params.filter_id}/statuses`, params).then(response => {
dispatch(createFilterStatusSuccess(response.data));
if (onSuccess) onSuccess();
}).catch(error => {

@ -29,7 +29,8 @@ export function clearSearch() {
export function submitSearch() {
return (dispatch, getState) => {
const value = getState().getIn(['search', 'value']);
const value = getState().getIn(['search', 'value']);
const signedIn = !!getState().getIn(['meta', 'me']);
if (value.length === 0) {
dispatch(fetchSearchSuccess({ accounts: [], statuses: [], hashtags: [] }, ''));
@ -41,7 +42,7 @@ export function submitSearch() {
api(getState).get('/api/v2/search', {
params: {
q: value,
resolve: true,
resolve: signedIn,
limit: 10,
},
}).then(response => {

@ -5,6 +5,14 @@ export const SERVER_FETCH_REQUEST = 'Server_FETCH_REQUEST';
export const SERVER_FETCH_SUCCESS = 'Server_FETCH_SUCCESS';
export const SERVER_FETCH_FAIL = 'Server_FETCH_FAIL';
export const EXTENDED_DESCRIPTION_REQUEST = 'EXTENDED_DESCRIPTION_REQUEST';
export const EXTENDED_DESCRIPTION_SUCCESS = 'EXTENDED_DESCRIPTION_SUCCESS';
export const EXTENDED_DESCRIPTION_FAIL = 'EXTENDED_DESCRIPTION_FAIL';
export const SERVER_DOMAIN_BLOCKS_FETCH_REQUEST = 'SERVER_DOMAIN_BLOCKS_FETCH_REQUEST';
export const SERVER_DOMAIN_BLOCKS_FETCH_SUCCESS = 'SERVER_DOMAIN_BLOCKS_FETCH_SUCCESS';
export const SERVER_DOMAIN_BLOCKS_FETCH_FAIL = 'SERVER_DOMAIN_BLOCKS_FETCH_FAIL';
export const fetchServer = () => (dispatch, getState) => {
dispatch(fetchServerRequest());
@ -28,3 +36,56 @@ const fetchServerFail = error => ({
type: SERVER_FETCH_FAIL,
error,
});
export const fetchExtendedDescription = () => (dispatch, getState) => {
dispatch(fetchExtendedDescriptionRequest());
api(getState)
.get('/api/v1/instance/extended_description')
.then(({ data }) => dispatch(fetchExtendedDescriptionSuccess(data)))
.catch(err => dispatch(fetchExtendedDescriptionFail(err)));
};
const fetchExtendedDescriptionRequest = () => ({
type: EXTENDED_DESCRIPTION_REQUEST,
});
const fetchExtendedDescriptionSuccess = description => ({
type: EXTENDED_DESCRIPTION_SUCCESS,
description,
});
const fetchExtendedDescriptionFail = error => ({
type: EXTENDED_DESCRIPTION_FAIL,
error,
});
export const fetchDomainBlocks = () => (dispatch, getState) => {
dispatch(fetchDomainBlocksRequest());
api(getState)
.get('/api/v1/instance/domain_blocks')
.then(({ data }) => dispatch(fetchDomainBlocksSuccess(true, data)))
.catch(err => {
if (err.response.status === 404) {
dispatch(fetchDomainBlocksSuccess(false, []));
} else {
dispatch(fetchDomainBlocksFail(err));
}
});
};
const fetchDomainBlocksRequest = () => ({
type: SERVER_DOMAIN_BLOCKS_FETCH_REQUEST,
});
const fetchDomainBlocksSuccess = (isAvailable, blocks) => ({
type: SERVER_DOMAIN_BLOCKS_FETCH_SUCCESS,
isAvailable,
blocks,
});
const fetchDomainBlocksFail = error => ({
type: SERVER_DOMAIN_BLOCKS_FETCH_FAIL,
error,
});

@ -156,8 +156,8 @@ export const expandHomeTimeline = ({ maxId } = {}, done = noOp) => ex
export const expandPublicTimeline = ({ maxId, onlyMedia, onlyRemote, allowLocalOnly } = {}, done = noOp) => expandTimeline(`public${onlyRemote ? ':remote' : (allowLocalOnly ? ':allow_local_only' : '')}${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { remote: !!onlyRemote, allow_local_only: !!allowLocalOnly, max_id: maxId, only_media: !!onlyMedia }, done);
export const expandCommunityTimeline = ({ maxId, onlyMedia } = {}, done = noOp) => expandTimeline(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, max_id: maxId, only_media: !!onlyMedia }, done);
export const expandDirectTimeline = ({ maxId } = {}, done = noOp) => expandTimeline('direct', '/api/v1/timelines/direct', { max_id: maxId }, done);
export const expandAccountTimeline = (accountId, { maxId, withReplies } = {}) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, max_id: maxId });
export const expandAccountFeaturedTimeline = accountId => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true });
export const expandAccountTimeline = (accountId, { maxId, withReplies, tagged } = {}) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}${tagged ? `:${tagged}` : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, tagged, max_id: maxId });
export const expandAccountFeaturedTimeline = (accountId, { tagged } = {}) => expandTimeline(`account:${accountId}:pinned`, `/api/v1/accounts/${accountId}/statuses`, { pinned: true, tagged });
export const expandAccountMediaTimeline = (accountId, { maxId } = {}) => expandTimeline(`account:${accountId}:media`, `/api/v1/accounts/${accountId}/statuses`, { max_id: maxId, only_media: true, limit: 40 });
export const expandListTimeline = (id, { maxId } = {}, done = noOp) => expandTimeline(`list:${id}`, `/api/v1/timelines/list/${id}`, { max_id: maxId }, done);
export const expandHashtagTimeline = (hashtag, { maxId, tags, local } = {}, done = noOp) => {

@ -1,20 +1,31 @@
// @ts-check
import axios from 'axios';
import LinkHeader from 'http-link-header';
import ready from './ready';
/**
* @param {import('axios').AxiosResponse} response
* @returns {LinkHeader}
*/
export const getLinks = response => {
const value = response.headers.link;
if (!value) {
return { refs: [] };
return new LinkHeader();
}
return LinkHeader.parse(value);
};
/** @type {import('axios').RawAxiosRequestHeaders} */
const csrfHeader = {};
/**
* @returns {void}
*/
const setCSRFHeader = () => {
/** @type {HTMLMetaElement | null} */
const csrfToken = document.querySelector('meta[name=csrf-token]');
if (csrfToken) {
@ -24,6 +35,10 @@ const setCSRFHeader = () => {
ready(setCSRFHeader);
/**
* @param {() => import('immutable').Map} getState
* @returns {import('axios').RawAxiosRequestHeaders}
*/
const authorizationHeaderFromState = getState => {
const accessToken = getState && getState().getIn(['meta', 'access_token'], '');
@ -36,17 +51,25 @@ const authorizationHeaderFromState = getState => {
};
};
export default getState => axios.create({
headers: {
...csrfHeader,
...authorizationHeaderFromState(getState),
},
transformResponse: [function (data) {
try {
return JSON.parse(data);
} catch(Exception) {
return data;
}
}],
});
/**
* @param {() => import('immutable').Map} getState
* @returns {import('axios').AxiosInstance}
*/
export default function api(getState) {
return axios.create({
headers: {
...csrfHeader,
...authorizationHeaderFromState(getState),
},
transformResponse: [
function (data) {
try {
return JSON.parse(data);
} catch {
return data;
}
},
],
});
}

@ -27,6 +27,7 @@ export default @injectIntl
class Account extends ImmutablePureComponent {
static propTypes = {
size: PropTypes.number,
account: ImmutablePropTypes.map,
onFollow: PropTypes.func.isRequired,
onBlock: PropTypes.func.isRequired,
@ -41,6 +42,10 @@ class Account extends ImmutablePureComponent {
onActionClick: PropTypes.func,
};
static defaultProps = {
size: 36,
};
handleFollow = () => {
this.props.onFollow(this.props.account);
}
@ -75,6 +80,7 @@ class Account extends ImmutablePureComponent {
actionIcon,
actionTitle,
defaultAction,
size,
} = this.props;
if (!account) {
@ -163,7 +169,7 @@ class Account extends ImmutablePureComponent {
<div className='account'>
<div className='account__wrapper'>
<Permalink key={account.get('id')} className='account__display-name' title={account.get('acct')} href={account.get('url')} to={`/@${account.get('acct')}`}>
<div className='account__avatar-wrapper'><Avatar account={account} size={36} /></div>
<div className='account__avatar-wrapper'><Avatar account={account} size={size} /></div>
{mute_expires_at}
<DisplayName account={account} />
</Permalink>

@ -1,6 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import { FormattedNumber } from 'react-intl';
import ShortNumber from 'mastodon/components/short_number';
import TransitionMotion from 'react-motion/lib/TransitionMotion';
import spring from 'react-motion/lib/spring';
import { reduceMotion } from 'flavours/glitch/initial_state';
@ -51,7 +51,7 @@ export default class AnimatedNumber extends React.PureComponent {
const { direction } = this.state;
if (reduceMotion) {
return obfuscate ? obfuscatedCount(value) : <FormattedNumber value={value} />;
return obfuscate ? obfuscatedCount(value) : <ShortNumber value={value} />;
}
const styles = [{
@ -65,7 +65,7 @@ export default class AnimatedNumber extends React.PureComponent {
{items => (
<span className='animated-number'>
{items.map(({ key, data, style }) => (
<span key={key} style={{ position: (direction * style.y) > 0 ? 'absolute' : 'static', transform: `translateY(${style.y * 100}%)` }}>{obfuscate ? obfuscatedCount(data) : <FormattedNumber value={data} />}</span>
<span key={key} style={{ position: (direction * style.y) > 0 ? 'absolute' : 'static', transform: `translateY(${style.y * 100}%)` }}>{obfuscate ? obfuscatedCount(data) : <ShortNumber value={data} />}</span>
))}
</span>
)}

@ -70,6 +70,8 @@ export default class Avatar extends React.PureComponent {
onMouseLeave={this.handleMouseLeave}
style={style}
data-avatar-of={account && `@${account.get('acct')}`}
role='img'
aria-label={account?.get('acct')}
/>
);
}

@ -63,7 +63,7 @@ class ColumnHeader extends React.PureComponent {
}
handleTitleClick = () => {
this.props.onClick();
this.props.onClick?.();
}
handleMoveLeft = () => {
@ -157,7 +157,6 @@ class ColumnHeader extends React.PureComponent {
className={collapsibleButtonClassName}
title={formatMessage(collapsed ? messages.show : messages.hide)}
aria-label={formatMessage(collapsed ? messages.show : messages.hide)}
aria-pressed={collapsed ? 'false' : 'true'}
onClick={this.handleToggleClick}
>
<i className='icon-with-badge'>

@ -0,0 +1,51 @@
import React from 'react';
import IconButton from './icon_button';
import PropTypes from 'prop-types';
import { injectIntl, defineMessages } from 'react-intl';
import { bannerSettings } from 'flavours/glitch/settings';
const messages = defineMessages({
dismiss: { id: 'dismissable_banner.dismiss', defaultMessage: 'Dismiss' },
});
export default @injectIntl
class DismissableBanner extends React.PureComponent {
static propTypes = {
id: PropTypes.string.isRequired,
children: PropTypes.node,
intl: PropTypes.object.isRequired,
};
state = {
visible: !bannerSettings.get(this.props.id),
};
handleDismiss = () => {
const { id } = this.props;
this.setState({ visible: false }, () => bannerSettings.set(id, true));
}
render () {
const { visible } = this.state;
if (!visible) {
return null;
}
const { children, intl } = this.props;
return (
<div className='dismissable-banner'>
<div className='dismissable-banner__message'>
{children}
</div>
<div className='dismissable-banner__action'>
<IconButton icon='times' title={intl.formatMessage(messages.dismiss)} onClick={this.handleDismiss} />
</div>
</div>
);
}
}

@ -4,6 +4,7 @@ import { FormattedMessage } from 'react-intl';
import { source_url } from 'flavours/glitch/initial_state';
import { preferencesLink } from 'flavours/glitch/utils/backend_links';
import StackTrace from 'stacktrace-js';
import { Helmet } from 'react-helmet';
export default class ErrorBoundary extends React.PureComponent {
@ -122,6 +123,10 @@ export default class ErrorBoundary extends React.PureComponent {
)}
</ul>
</div>
<Helmet>
<meta name='robots' content='noindex' />
</Helmet>
</div>
);
}

@ -1,7 +1,7 @@
// @ts-check
import React from 'react';
import { Sparklines, SparklinesCurve } from 'react-sparklines';
import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
import { FormattedMessage } from 'react-intl';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import Permalink from './permalink';
@ -9,10 +9,6 @@ import ShortNumber from 'flavours/glitch/components/short_number';
import Skeleton from 'flavours/glitch/components/skeleton';
import classNames from 'classnames';
const messages = defineMessages({
totalVolume: { id: 'hashtag.total_volume', defaultMessage: 'Total volume in the last {days, plural, one {day} other {{days} days}}' },
});
class SilentErrorBoundary extends React.Component {
static propTypes = {
@ -60,7 +56,6 @@ export const ImmutableHashtag = ({ hashtag }) => (
href={hashtag.get('url')}
to={`/tags/${hashtag.get('name')}`}
people={hashtag.getIn(['history', 0, 'accounts']) * 1 + hashtag.getIn(['history', 1, 'accounts']) * 1}
uses={hashtag.getIn(['history', 0, 'uses']) * 1 + hashtag.getIn(['history', 1, 'uses']) * 1}
history={hashtag.get('history').reverse().map((day) => day.get('uses')).toArray()}
/>
);
@ -69,39 +64,52 @@ ImmutableHashtag.propTypes = {
hashtag: ImmutablePropTypes.map.isRequired,
};
const Hashtag = injectIntl(({ name, href, to, people, uses, history, className, intl }) => (
const Hashtag = ({ name, href, to, people, uses, history, className, description, withGraph }) => (
<div className={classNames('trends__item', className)}>
<div className='trends__item__name'>
<Permalink href={href} to={to}>
{name ? <React.Fragment>#<span>{name}</span></React.Fragment> : <Skeleton width={50} />}
</Permalink>
{typeof people !== 'undefined' ? <ShortNumber value={people} renderer={accountsCountRenderer} /> : <Skeleton width={100} />}
{description ? (
<span>{description}</span>
) : (
typeof people !== 'undefined' ? <ShortNumber value={people} renderer={accountsCountRenderer} /> : <Skeleton width={100} />
)}
</div>
<abbr className='trends__item__current' title={intl.formatMessage(messages.totalVolume, { days: 2 })}>
{typeof uses !== 'undefined' ? <ShortNumber value={uses} /> : <Skeleton width={42} height={36} />}
<span className='trends__item__current__asterisk'>*</span>
</abbr>
<div className='trends__item__sparkline'>
<SilentErrorBoundary>
<Sparklines width={50} height={28} data={history ? history : Array.from(Array(7)).map(() => 0)}>
<SparklinesCurve style={{ fill: 'none' }} />
</Sparklines>
</SilentErrorBoundary>
</div>
{typeof uses !== 'undefined' && (
<div className='trends__item__current'>
<ShortNumber value={uses} />
</div>
)}
{withGraph && (
<div className='trends__item__sparkline'>
<SilentErrorBoundary>
<Sparklines width={50} height={28} data={history ? history : Array.from(Array(7)).map(() => 0)}>
<SparklinesCurve style={{ fill: 'none' }} />
</Sparklines>
</SilentErrorBoundary>
</div>
)}
</div>
));
);
Hashtag.propTypes = {
name: PropTypes.string,
href: PropTypes.string,
to: PropTypes.string,
people: PropTypes.number,
description: PropTypes.node,
uses: PropTypes.number,
history: PropTypes.arrayOf(PropTypes.number),
className: PropTypes.string,
withGraph: PropTypes.bool,
};
Hashtag.defaultProps = {
withGraph: true,
};
export default Hashtag;

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

Loading…
Cancel
Save