30 Commits

Author SHA1 Message Date
Zoë Bijl 42542a1618 [refactor] replace sass variable with css variable 2025-10-17 00:54:35 +02:00
Zoë Bijl e6d9057e49 [chore] update mini-css-extract-plugin to 2.9.4 2025-10-17 00:52:48 +02:00
Zoë Bijl e4d1ab0063 [chore] update scss files for Dart Sass 2.0.0 2025-10-17 00:21:14 +02:00
Zoë Bijl ff91bfe260 [chore] lint 2025-10-16 23:10:23 +02:00
Zoë Bijl db7fd70ae2 [chore] update scss files for Dart Sass 2.0.0
https://sass-lang.com/documentation/breaking-changes/import/
https://sass-lang.com/documentation/breaking-changes/color-functions/

# Conflicts:
#	app/javascript/flavours/glitch/styles/basics.scss
2025-10-16 23:10:23 +02:00
Zoë Bijl da628d9417 [chore] update login.scss for Dart Sass 2.0.0
https://sass-lang.com/documentation/breaking-changes/import/
https://sass-lang.com/documentation/breaking-changes/color-functions/

# Conflicts:
#	app/javascript/flavours/glitch/styles/login.scss
2025-10-16 23:10:23 +02:00
Zoë Bijl 4b4b4b9d38 [bugfix] correct lock-open-simple direction
the lock opened the wrong way; it was pointing left when it should’ve pointed right to be consistent with GTS.
2025-10-16 15:21:46 +02:00
Zoë Bijl 7f073ccd59 [docs] update changelog 2025-10-16 14:40:54 +02:00
Zoë Bijl 02c368b22a [chore] remove last reference to font-awesome 2025-10-16 12:57:43 +02:00
Zoë Bijl 39720bf7d2 [chore] remove unused assets
searched the repo for references to these and found none
2025-10-16 00:26:57 +02:00
Zoë Bijl 2dc019f1e9 [chore] remove unused font files
i missed these in 7c51ea30a4
2025-10-15 21:15:15 +02:00
Zoë Bijl 25af845912 [chore] lint sass files (#103)
commit c811679128
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 15 21:02:39 2025 +0200

    [chore] remove unused override

commit a3e56447aa
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 15 18:57:22 2025 +0200

    [chore] lint Sass files
2025-10-15 21:08:31 +02:00
prinlu 59c8cb987f [feature] change mastodon logo with the sloth (#96)
replace mastodon logo to gotosocial icon

Reviewed-on: https://codeberg.org/superseriousbusiness/masto-fe-standalone/pulls/96
Co-authored-by: prinlu <prinlu@noreply.codeberg.org>
Co-committed-by: prinlu <prinlu@noreply.codeberg.org>
2025-10-15 18:23:17 +02:00
Zoë Bijl 39b0552b6a [bugfix] various CSS fixes (#100)
Some fixes for the CSS / Phosphor revamp

- Corrected avatar position
- Corrected various button/icon sizes
- Change the way a status background is set
- Improved icon-button disabled state
- Improved contrast and light theme colours

commit b307fa93b4
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 15 17:49:11 2025 +0200

    [chore] lint

commit 1352425b81
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 15 17:46:42 2025 +0200

    [chore] lint

commit 276480b5a4
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 15 17:46:32 2025 +0200

    [bugfix] set direct message background

commit 4e5764a70b
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 15 17:44:46 2025 +0200

    [bugfix] improve obviousness of disabled icon button state

commit dec5bb66e7
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 15 16:52:55 2025 +0200

    [chore] lint

commit 72869917ab
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 15 16:52:44 2025 +0200

    [bugfix] start work on status content spacing

commit 5aa8333f71
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 15 15:57:56 2025 +0200

    lint

commit df0bb84ce4
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 15 15:57:48 2025 +0200

    [bugfix] correctly set status background (on focus)

    fixes an issue where a weird gradient would show up in the status__info section

commit 2fab5ff2e7
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 15 09:40:28 2025 +0200

    [bugfix] fix lint issues

commit 5d823b2195
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 15 01:19:01 2025 +0200

    [bugfix] set avatars to cover available space

    no more squashed avatars
2025-10-15 18:10:58 +02:00
tobi 075b46d050 [chore] Update runtime docker container with apk upgrade (#102)
Reviewed-on: https://codeberg.org/superseriousbusiness/masto-fe-standalone/pulls/102
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
2025-10-15 11:24:54 +02:00
Zoë Bijl 633352118b [chore] remove singleQuote options from prettierrc
commit a35874f6456efcdccc4d8439518094de0002ab11
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 15 09:26:04 2025 +0200

    [chore] remove singleQuote options from prettierrc

    These default to false, which is inline with the changes made in #88 / 1ff70886a1
2025-10-15 09:45:31 +02:00
Zoë Bijl fd5f6f60cc [bugfix] improve icon badge contrast
The icon badge text had a contrast of below 3:1 in some cases. This puts it at 5:1.
2025-10-14 18:53:13 +02:00
Zoë Bijl 7c51ea30a4 [chore] remove old font formats and unused css (#99)
Removes a bunch of unused files:

- Removed old font formats such as .otf, .woff, and .ttf; WOFF2 has baseline support
- Removed mailer.js/.scss (no mailer functionality in masto-fe)
- Removed vanilla reset
- Removed vanilla/Win95 theme
- Removed all vanilla styles (contrast, mastodon, mastodon-light)
- Removed FontAwesome (from package.json and common.js)
- Fixed some lint issues

commit 53242a3967
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 17:08:47 2025 +0200

    [chore] remove font-awesome

commit 3cc1792b8e
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 16:32:28 2025 +0200

    [chore] remove old font formats

    WOFF2 has baseline support: https://caniuse.com/woff2

commit e7b495de1f
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 16:17:59 2025 +0200

    [chore] remove font-awesome from common.css

commit 3913415ca6
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 16:17:32 2025 +0200

    [chore] remove mailer.js/.scss

    there’s no mailer functionality in masto-fe

commit fa9f9a758b
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 16:07:21 2025 +0200

    [chore] remove unused css files from “styles”

commit 49a7820b99
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 15:38:37 2025 +0200

    [bugfix] remove unused css

commit 84025f44c7
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 15:38:19 2025 +0200

    [bugfix] lint issues
2025-10-14 17:22:01 +02:00
Zoë Bijl 4aeb935250 [chore] remove vanilla flavours and skins (#94)
These files aren’t used as far as I can tell.

Reviewed-on: https://codeberg.org/superseriousbusiness/masto-fe-standalone/pulls/94
Co-authored-by: Zoë Bijl <code@moiety.me>
Co-committed-by: Zoë Bijl <code@moiety.me>
2025-10-14 15:34:23 +02:00
Zoë Bijl cb0ad15138 [feature] replace icons with Phosphor (#77)
Replaces all icons with the [Phosphor icon set](https://phosphoricons.com/). To accomodate these icons this also touches general style of buttons, headings, and other containers of icons.

I want to give a massive shout out to [Niléane](https://nileane.fr/@nileane) and her project [Tangerine UI](https://github.com/nileane/TangerineUI-for-Mastodon). Most of the icons/adjustments I’ve made are based on her choices and work.

Reviewed-on: https://codeberg.org/superseriousbusiness/masto-fe-standalone/pulls/77

Contains:

commit 4cd78295dd
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 13:57:50 2025 +0200

    [bugfix] increase contrast for spoiler link

commit 4594e776e0
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 13:48:05 2025 +0200

    [bugfix] increase contrast for “secondary” in light mode

    Increase the contrast for icons, usernames, and some other places

commit 7db3518be7
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 13:39:36 2025 +0200

    [bugfix] increase size of overlayed buttons

    …such as the hide sensitive content button

commit 3fd37bbfa5
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 13:29:22 2025 +0200

    [bugfix] resize three dot menu next to user

commit 82a4b2b8d9
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 13:23:29 2025 +0200

    [bugfix] use correct icon name

commit 470cb995f9
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 12:55:27 2025 +0200

    [bugfix] add back translation for pin/unpin button

    https://codeberg.org/superseriousbusiness/masto-fe-standalone/pulls/77#issuecomment-7718876

commit 255b64c8f7
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 12:22:34 2025 +0200

    [bugfix] restore title functionality for icons

    the `title`-attribute doesn’t work on `<SVG>`-elements. the way to do it is with a nested `<title>`-element. this adds this functionality

commit 9c25c362fb
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 11:54:44 2025 +0200

    [bugfix] remove import of Icon

    This gave me an error yesterday i think, but seems fine now, so 🤷🏻‍♀️.

    From review: https://codeberg.org/superseriousbusiness/masto-fe-standalone/pulls/77#issuecomment-7719077

commit 36065d03fb
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 10:43:02 2025 +0200

    [docs] update changelog

commit 80cb9ef0c5
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 10:09:10 2025 +0200

    [bugfix] first pass at deduping and sorting

commit 59beb08921
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 01:59:50 2025 +0200

    fix lint issues

commit 3ffcdffdf1
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 01:53:24 2025 +0200

    liint

commit cda2a62ee5
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 01:46:50 2025 +0200

    lint

commit 373b756e8a
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 00:55:35 2025 +0200

    rename calls

commit d53ca0d990
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 00:52:25 2025 +0200

    rename icon components

commit 07a1e149e1
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 14 00:45:21 2025 +0200

    [feature] change _all_ remaining icons

commit 53fdc6b82f
Author: Zoë Bijl <code@moiety.me>
Date:   Mon Oct 13 20:17:04 2025 +0200

    [feature] change upload form icons

commit d143b433b2
Author: Zoë Bijl <code@moiety.me>
Date:   Mon Oct 13 13:56:27 2025 +0200

    [bugfix] allow icon with badge to expand horizontally

    This allows it to contain more numbers / text. Getting double digit notifications for example. Or the follow request cap '40+' text.

commit b737f07676
Author: Zoë Bijl <code@moiety.me>
Date:   Mon Oct 13 13:46:13 2025 +0200

    [bugfix] import correct component for “follow request” menu item

commit 03205b05a9
Author: Zoë Bijl <code@moiety.me>
Date:   Mon Oct 13 13:07:40 2025 +0200

    [feature] update follow request icons

commit 199db8b9af
Author: Zoë Bijl <code@moiety.me>
Date:   Mon Oct 13 01:40:23 2025 +0200

    [feature] change video player controls

commit 9fcbf23274
Author: Zoë Bijl <code@moiety.me>
Date:   Sun Oct 12 14:07:37 2025 +0200

    [feature] change unlisted status icon to an open padlock

    Custom made icon based on Phosphor. I flipped the “lock” bit so it’s easier to distinguish.

commit a359bf4ab1
Author: Zoë Bijl <code@moiety.me>
Date:   Fri Oct 10 17:30:10 2025 +0200

    [build] add regex for stylelint/custom-property-pattern

    Example: https://regex101.com/r/eITX54/1

commit 972624b360
Author: Zoë Bijl <code@moiety.me>
Date:   Fri Oct 10 15:52:28 2025 +0200

    [build] edit custom-property-pattern

commit caf3c1e41a
Author: Zoë Bijl <code@moiety.me>
Date:   Fri Oct 10 15:46:05 2025 +0200

    [bugfix] fix media modal icons

commit 3d2df89ab5
Author: Zoë Bijl <code@moiety.me>
Date:   Fri Oct 10 15:35:59 2025 +0200

    [bugfix] correct notification filter bar colours

commit 36308a2234
Author: Zoë Bijl <code@moiety.me>
Date:   Fri Oct 10 15:30:48 2025 +0200

    [bugfix] fix account search result styling

commit eea1c0315b
Author: Zoë Bijl <code@moiety.me>
Date:   Fri Oct 10 15:30:17 2025 +0200

    [bugfix] fix drawer colours

commit c2140a4be1
Author: Zoë Bijl <code@moiety.me>
Date:   Fri Oct 10 15:29:37 2025 +0200

    [bugfix] fix search styling

commit 22c7fc2491
Author: Zoë Bijl <code@moiety.me>
Date:   Fri Oct 10 15:28:48 2025 +0200

    [feature] change icons to Phosphor

commit f1eeb89908
Author: Zoë Bijl <code@moiety.me>
Date:   Fri Oct 10 14:23:29 2025 +0200

    [bugfix] properly set colors for lightmode

commit 7138e11984
Author: Zoë Bijl <code@moiety.me>
Date:   Fri Oct 10 14:22:59 2025 +0200

    [feature] use css variables for select component

    - Search field
    - Notifications filter bar/account post bar
    - Status prepend part ('x' boosted)
    - body background color

commit b91f194012
Author: Zoë Bijl <code@moiety.me>
Date:   Fri Oct 10 13:58:45 2025 +0200

    [bugfix] set font-weight on account portion of the display name

commit 49ebf988a4
Author: Zoë Bijl <code@moiety.me>
Date:   Fri Oct 10 12:16:41 2025 +0200

    [chore] correct path to login.css

commit 6433626943
Author: Zoë Bijl <code@moiety.me>
Date:   Fri Oct 10 12:10:54 2025 +0200

    [chore] fix lint issues

commit 9034a3d103
Author: Zoë Bijl <code@moiety.me>
Date:   Fri Oct 10 12:10:38 2025 +0200

    [chore] update stylelint rules

commit 5d5325d067
Author: Zoë Bijl <code@moiety.me>
Date:   Fri Oct 10 12:02:52 2025 +0200

    [bugfix] style `.gts-icon-with-badge`

    Fixes styling for the notification badge

commit fbd22639d9
Author: Zoë Bijl <code@moiety.me>
Date:   Fri Oct 10 09:30:14 2025 +0200

    icon badge style

commit 7f1c3fd388
Author: Zoë Bijl <code@moiety.me>
Date:   Fri Oct 10 09:03:07 2025 +0200

    [chore] fix lint issues

commit 5e063da784
Author: Zoë Bijl <code@moiety.me>
Date:   Fri Oct 10 01:01:35 2025 +0200

    [feature] change icon for “new list” button

commit c22c8ea097
Author: Zoë Bijl <code@moiety.me>
Date:   Thu Oct 9 23:50:28 2025 +0200

    [chore] add debug style for `.fa`

    I want to remove all FontAwesome from the project. This will help find any that are left over.

commit f236962403
Author: Zoë Bijl <code@moiety.me>
Date:   Thu Oct 9 23:49:39 2025 +0200

    [feature] change “local only” status icon

commit 94a1ec45c2
Author: Zoë Bijl <code@moiety.me>
Date:   Thu Oct 9 23:31:42 2025 +0200

    [bugfix] properly align account buttons

commit 7adcf93c80
Author: Zoë Bijl <code@moiety.me>
Date:   Thu Oct 9 23:31:25 2025 +0200

    [bugfix] set border radius on smaller screens

commit 8ad4c08069
Author: Zoë Bijl <code@moiety.me>
Date:   Thu Oct 9 23:03:15 2025 +0200

    [feature] remove icons from notification purge bar

commit 457c3c2910
Author: Zoë Bijl <code@moiety.me>
Date:   Thu Oct 9 19:49:49 2025 +0200

    [feature] change list edit buttons

commit 046be63ed6
Author: Zoë Bijl <code@moiety.me>
Date:   Thu Oct 9 18:15:14 2025 +0200

    [feature] update dismissible banner icon

commit 506e59034b
Author: Zoë Bijl <code@moiety.me>
Date:   Thu Oct 9 15:08:15 2025 +0200

    [feature] change header pin state/move icons

commit d97df4b87f
Author: Zoë Bijl <code@moiety.me>
Date:   Thu Oct 9 11:42:55 2025 +0200

    [chore] fix lint:js errors

commit b418204ae3
Author: Zoë Bijl <code@moiety.me>
Date:   Thu Oct 9 09:50:37 2025 +0200

    [chore] fix lint:js errors

    …related to the icons

commit 415b05d20a
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 8 13:44:51 2025 +0200

    [feature] replace column move icons

commit 14f119be65
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 8 13:38:18 2025 +0200

    [bugfix] hide overflow text

commit 6fb2dd73be
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 8 12:05:25 2025 +0200

    [feature] improve status-prepend display name hover state

commit f8f0b403af
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 8 11:55:57 2025 +0200

    [bugfix] uncomment slim back button styles

commit 8b254ae288
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 8 11:44:54 2025 +0200

    [feature] refactor status styling

    This does a bunch of stuff:

    - split out status components into their own file
    - unify spacing within a status
    - outline all icons
    - neatly fade the overflow part of a username
    - add underlines to username links when appropriate
    - correctly size all icons in a status
    - restyle spoiler link (content warning button)

commit ebfbed0553
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 8 11:40:18 2025 +0200

    [feature] change content warning state icon

commit f70946ef48
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 8 11:26:22 2025 +0200

    [bugfix] remove unnecessary `<span>`

commit 312b157581
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 8 11:15:07 2025 +0200

    [bugfix] correctly align status prepend

commit 2cd3a82fc7
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 8 11:04:39 2025 +0200

    [bugfix] set correct icon state in detailed status view

    This change was already made for the normal status view. It sets the icon to be filled when a status is boosted or favourited. Also forgoing the need for the Glitch checkmark.

commit e1c1325905
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 8 11:02:58 2025 +0200

    [feature] replace load-gap icon

commit d483cab118
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 8 11:00:05 2025 +0200

    [feature] align `drawer` and `compose-panel` components

    - Neatly aligns both the `.drawer` and `.compose-panel` components
    - Fixes `.search__input` padding  when inside the `.compose-panel`

commit 3c85b02b51
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 8 10:52:37 2025 +0200

    [feature] add “sizes” variables file

commit 7a4b9c6634
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 7 17:26:30 2025 +0200

    [feature] space out status action bar items

commit ebfd05be3d
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 7 17:25:49 2025 +0200

    [bugfix] remove “sticky” background on focus

commit a977011b34
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 7 17:24:52 2025 +0200

    [feature] refactor status prepend box

commit 52fbda27ed
Author: Zoë Bijl <code@moiety.me>
Date:   Tue Oct 7 17:20:44 2025 +0200

    [feature] add GTS specific CSS

    provides a space to place rewritten CSS; should help keep track of what has been done.

commit 7209169ba9
Author: Zoë Bijl <code@moiety.me>
Date:   Mon Oct 6 13:02:02 2025 +0200

    [feature] add animations to status bar icons

    When activated the status bar (under a toot) icons now do a cute lil animation, courtesy of Tangerine UI.

commit c0ea21299f
Author: Zoë Bijl <code@moiety.me>
Date:   Sun Oct 5 01:36:12 2025 +0200

    [feature] refactor search box / add drawer outlines

    - add outlines to some UI elements like the timeline and drawers
    - search “clear” button is now an actual `<button>`

commit 82cc610ab7
Author: Zoë Bijl <code@moiety.me>
Date:   Sat Oct 4 20:34:17 2025 +0200

    [feature] set icons for lists

commit 004404dc83
Author: Zoë Bijl <code@moiety.me>
Date:   Sat Oct 4 20:33:39 2025 +0200

    [feature] refactor local settings navigation item

commit 9dbc200fd6
Author: Zoë Bijl <code@moiety.me>
Date:   Sat Oct 4 20:32:27 2025 +0200

    [feature] refactor column/drawer header

commit beb7a68b5e
Author: Zoë Bijl <code@moiety.me>
Date:   Sat Oct 4 20:30:29 2025 +0200

    [fix] set correct icon size for action-bar

commit 6fb994abe6
Author: Zoë Bijl <code@moiety.me>
Date:   Sat Oct 4 20:29:35 2025 +0200

    [feature] refactor notifications filter bar

commit efaeb5d969
Author: Zoë Bijl <code@moiety.me>
Date:   Sat Oct 4 01:25:42 2025 +0200

    [refactor] compose form button bar CSS

    Complete rewrite of the CSS for the compose form button bar. This makes the buttons and icons sit nicely in the available space.

commit 18fd2ef39a
Author: Zoë Bijl <code@moiety.me>
Date:   Sat Oct 4 01:14:03 2025 +0200

    [feat] change unlisted icon from lock to moon

    Makes easier to distinguish.

commit 5e16246d56
Author: Zoë Bijl <code@moiety.me>
Date:   Sat Oct 4 01:00:54 2025 +0200

    [fix] use `<button>` for emoji button

    No idea why this was a `<div>`; this works fine in my testing.

commit 250b415a9d
Author: Zoë Bijl <code@moiety.me>
Date:   Sat Oct 4 00:58:16 2025 +0200

    [fix] remove inline styling for icon button

commit ea3106c635
Author: Zoë Bijl <code@moiety.me>
Date:   Fri Oct 3 23:11:38 2025 +0200

    [feature] set toot footer icons based on state

    When you favourite, boost, or bookmark a toot the icons turns into a filled version.

commit 5a6fd18ec2
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 1 23:48:22 2025 +0200

    [feature] add SVG icons

commit b62c1f4fc6
Author: Zoë Bijl <code@moiety.me>
Date:   Wed Oct 1 00:56:51 2025 +0200

    [feature] add SVG icons

    # Conflicts:
    #	.editorconfig

    # Conflicts:
    #	app/javascript/flavours/glitch/components/account.jsx
    #	app/javascript/flavours/glitch/components/column_back_button.jsx
    #	app/javascript/flavours/glitch/components/column_back_button_slim.jsx
    #	app/javascript/flavours/glitch/components/column_header.jsx
    #	app/javascript/flavours/glitch/components/dropdown_menu.jsx
    #	app/javascript/flavours/glitch/components/media_gallery.jsx
    #	app/javascript/flavours/glitch/components/status.jsx
    #	app/javascript/flavours/glitch/components/status_action_bar.jsx
    #	app/javascript/flavours/glitch/components/status_icons.jsx
    #	app/javascript/flavours/glitch/components/status_prepend.jsx
    #	app/javascript/flavours/glitch/components/status_visibility_icon.jsx
    #	app/javascript/flavours/glitch/features/account/components/header.jsx
    #	app/javascript/flavours/glitch/features/audio/index.jsx
    #	app/javascript/flavours/glitch/features/compose/components/dropdown.jsx
    #	app/javascript/flavours/glitch/features/compose/components/dropdown_menu.jsx
    #	app/javascript/flavours/glitch/features/compose/components/emoji_picker_dropdown.jsx
    #	app/javascript/flavours/glitch/features/compose/components/header.jsx
    #	app/javascript/flavours/glitch/features/compose/components/options.jsx
    #	app/javascript/flavours/glitch/features/compose/components/poll_form.jsx
    #	app/javascript/flavours/glitch/features/compose/components/privacy_dropdown.jsx
    #	app/javascript/flavours/glitch/features/compose/components/publisher.jsx
    #	app/javascript/flavours/glitch/features/compose/components/reply_indicator.jsx
    #	app/javascript/flavours/glitch/features/compose/components/search.jsx
    #	app/javascript/flavours/glitch/features/compose/components/textarea_icons.jsx
    #	app/javascript/flavours/glitch/features/favourites/index.jsx
    #	app/javascript/flavours/glitch/features/getting_started/index.jsx
    #	app/javascript/flavours/glitch/features/interaction_modal/index.jsx
    #	app/javascript/flavours/glitch/features/local_settings/navigation/item/index.jsx
    #	app/javascript/flavours/glitch/features/notifications/components/admin_report.jsx
    #	app/javascript/flavours/glitch/features/notifications/components/admin_signup.jsx
    #	app/javascript/flavours/glitch/features/notifications/components/clear_column_button.jsx
    #	app/javascript/flavours/glitch/features/notifications/components/filter_bar.jsx
    #	app/javascript/flavours/glitch/features/notifications/components/follow.jsx
    #	app/javascript/flavours/glitch/features/notifications/components/follow_request.jsx
    #	app/javascript/flavours/glitch/features/notifications/index.jsx
    #	app/javascript/flavours/glitch/features/picture_in_picture/components/footer.jsx
    #	app/javascript/flavours/glitch/features/reblogs/index.jsx
    #	app/javascript/flavours/glitch/features/status/components/action_bar.jsx
    #	app/javascript/flavours/glitch/features/status/components/detailed_status.jsx
    #	app/javascript/flavours/glitch/features/status/index.jsx
    #	app/javascript/flavours/glitch/features/ui/components/column_header.jsx
    #	app/javascript/flavours/glitch/features/ui/components/column_link.jsx
    #	app/javascript/flavours/glitch/features/ui/components/doodle_modal.jsx
    #	app/javascript/flavours/glitch/features/ui/components/embed_modal.jsx
    #	app/javascript/flavours/glitch/features/ui/components/filter_modal.jsx
    #	app/javascript/flavours/glitch/features/ui/components/focal_point_modal.jsx
    #	app/javascript/flavours/glitch/features/ui/components/image_modal.jsx
    #	app/javascript/flavours/glitch/features/ui/components/media_modal.jsx
    #	app/javascript/flavours/glitch/features/ui/components/notifications_counter_icon.js
    #	app/javascript/flavours/glitch/features/ui/components/report_modal.jsx
2025-10-14 14:00:10 +02:00
Zoë Bijl 1ff70886a1 [build] upgrade eslint to 9.37.0 (#88)
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Reviewed-on: https://codeberg.org/superseriousbusiness/masto-fe-standalone/pulls/88
Co-authored-by: Zoë Bijl <moiety@noreply.codeberg.org>
Co-committed-by: Zoë Bijl <moiety@noreply.codeberg.org>
2025-10-12 13:42:02 +02:00
Zoë Bijl 75d7a62693 [feature] decouple login.scss from variables (#93)
Preparing for a switch to CSS variables

- decouple login.scss from variables.scss
- move scrollbar css to separate file

Reviewed-on: https://codeberg.org/superseriousbusiness/masto-fe-standalone/pulls/93
Co-authored-by: Zoë Bijl <code@moiety.me>
Co-committed-by: Zoë Bijl <code@moiety.me>
2025-10-10 21:17:25 +02:00
Zoë Bijl 6301ae8023 Upgrade to Webpack 5 (#83)
Reviewed-on: https://codeberg.org/superseriousbusiness/masto-fe-standalone/pulls/83
Co-authored-by: Zoë Bijl <code@moiety.me>
Co-committed-by: Zoë Bijl <code@moiety.me>
2025-10-10 19:11:00 +02:00
Zoë Bijl 496fd5987e [bugfix] correct import of @rails/ujs / fix lint issues (#92)
Details: https://github.com/rails/rails/issues/49768
Reviewed-on: https://codeberg.org/superseriousbusiness/masto-fe-standalone/pulls/92
Co-authored-by: Zoë Bijl <code@moiety.me>
Co-committed-by: Zoë Bijl <code@moiety.me>
2025-10-10 10:54:11 +02:00
tobi 4b4a9f981f [chore] Update to yarn 4 (#90)
Update to yarn 4 and use `masto-fe-standalone-woodpecker-build` container for builds.

Reviewed-on: https://codeberg.org/superseriousbusiness/masto-fe-standalone/pulls/90
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
2025-10-09 16:13:26 +02:00
Zoë Bijl 3faabb8280 [docs] update AUTHORS.md (#89)
Removes Mastodon authors and replaces it with Sloth Flavour authors. Also adds a special thanks section to attribute the original project authors.

Reviewed-on: https://codeberg.org/superseriousbusiness/masto-fe-standalone/pulls/89
Co-authored-by: Zoë Bijl <code@moiety.me>
Co-committed-by: Zoë Bijl <code@moiety.me>
2025-10-09 15:02:45 +02:00
Zoë Bijl 5f9a92953f [docs] update changelog (#87)
Reviewed-on: https://codeberg.org/superseriousbusiness/masto-fe-standalone/pulls/87
Co-authored-by: Zoë Bijl <code@moiety.me>
Co-committed-by: Zoë Bijl <code@moiety.me>
2025-10-09 11:59:01 +02:00
Zoë Bijl 81445f0afd [build] upgrade to Prettier 3.6.2 (#86)
Upgrades Prettier to 3.6.2 and pins it there. Prettier [recommends pinning the version](https://prettier.io/docs/install#summary):

> Install an exact version of Prettier locally in your project. This makes sure that everyone in the project gets the exact same version of Prettier. Even a patch release of Prettier can result in slightly different formatting, so you wouldn’t want different team members using different versions and formatting each other’s changes back and forth.

---

Should probably merge after #85.

Co-authored-by: tobi <kipvandenbos@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/superseriousbusiness/masto-fe-standalone/pulls/86
Co-authored-by: Zoë Bijl <code@moiety.me>
Co-committed-by: Zoë Bijl <code@moiety.me>
2025-10-09 11:52:50 +02:00
Zoë Bijl adf075d19f [bugfix] Fix linter issues (#85)
- [x] .js
- [x] .json
- [x] .md
- [x] .scss
- [x] .yml

Reviewed-on: https://codeberg.org/superseriousbusiness/masto-fe-standalone/pulls/85
Co-authored-by: Zoë Bijl <code@moiety.me>
Co-committed-by: Zoë Bijl <code@moiety.me>
2025-10-09 11:11:42 +02:00
Zoë Bijl 8a26776492 [docs] Add changelog based on “Keep a Changelog” (#80)
Reviewed-on: https://codeberg.org/superseriousbusiness/masto-fe-standalone/pulls/80
Co-authored-by: Zoë Bijl <code@moiety.me>
Co-committed-by: Zoë Bijl <code@moiety.me>
2025-10-09 11:10:00 +02:00
1119 changed files with 41160 additions and 125521 deletions
+1 -1
View File
@@ -3,5 +3,5 @@ root = true
[*.scss]
indent_size = 2
[login.scss]
[{**/login.scss,**/tangerine/**/*.scss,**/gts/**/*.scss}]
indent_size = 4
-13
View File
@@ -1,13 +0,0 @@
/build/**
/coverage/**
/db/**
/lib/**
/log/**
/node_modules/**
/nonobox/**
/public/**
!/public/embed.js
/spec/**
/tmp/**
/vendor/**
!.eslintrc.js
-402
View File
@@ -1,402 +0,0 @@
module.exports = {
root: true,
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:jsx-a11y/recommended',
'plugin:import/recommended',
'plugin:promise/recommended',
'plugin:jsdoc/recommended',
],
env: {
browser: true,
node: true,
es6: true,
},
globals: {
ATTACHMENT_HOST: false,
},
parser: '@typescript-eslint/parser',
plugins: [
'react',
'jsx-a11y',
'import',
'promise',
'@typescript-eslint',
'formatjs',
],
parserOptions: {
sourceType: 'module',
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 2021,
requireConfigFile: false,
babelOptions: {
configFile: false,
presets: ['@babel/react', '@babel/env'],
},
},
settings: {
react: {
version: 'detect',
},
'import/ignore': [
'node_modules',
'\\.(css|scss|json)$',
],
'import/resolver': {
typescript: {},
},
},
rules: {
'consistent-return': 'error',
'dot-notation': 'error',
eqeqeq: ['error', 'always', { 'null': 'ignore' }],
'indent': ['error', 2],
'jsx-quotes': ['error', 'prefer-single'],
'semi': ['error', 'always'],
'no-case-declarations': 'off',
'no-catch-shadow': 'error',
'no-console': [
'warn',
{
allow: [
'error',
'warn',
],
},
],
'no-empty': 'off',
'no-restricted-properties': [
'error',
{ property: 'substring', message: 'Use .slice instead of .substring.' },
{ property: 'substr', message: 'Use .slice instead of .substr.' },
],
'no-restricted-syntax': [
'error',
{
// eslint-disable-next-line no-restricted-syntax
selector: 'Literal[value=/•/], JSXText[value=/•/]',
// eslint-disable-next-line no-restricted-syntax
message: "Use '·' (middle dot) instead of '•' (bullet)",
},
],
'no-self-assign': 'off',
'no-unused-expressions': 'error',
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': [
'error',
{
vars: 'all',
args: 'after-used',
destructuredArrayIgnorePattern: '^_',
ignoreRestSiblings: true,
},
],
'valid-typeof': 'error',
'react/jsx-filename-extension': ['error', { extensions: ['.jsx', 'tsx'] }],
'react/jsx-boolean-value': 'error',
'react/display-name': 'off',
'react/jsx-fragments': ['error', 'syntax'],
'react/jsx-equals-spacing': 'error',
'react/jsx-no-bind': 'error',
'react/jsx-no-useless-fragment': 'error',
'react/jsx-no-target-blank': 'off',
'react/jsx-tag-spacing': 'error',
'react/jsx-uses-react': 'off', // not needed with new JSX transform
'react/jsx-wrap-multilines': 'error',
'react/no-deprecated': 'off',
'react/no-unknown-property': 'off',
'react/react-in-jsx-scope': 'off', // not needed with new JSX transform
'react/self-closing-comp': 'error',
// recommended values found in https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/src/index.js
'jsx-a11y/accessible-emoji': 'warn',
'jsx-a11y/click-events-have-key-events': 'off',
'jsx-a11y/label-has-associated-control': 'off',
'jsx-a11y/media-has-caption': 'off',
'jsx-a11y/no-autofocus': 'off',
// recommended rule is:
// 'jsx-a11y/no-interactive-element-to-noninteractive-role': [
// 'error',
// {
// tr: ['none', 'presentation'],
// canvas: ['img'],
// },
// ],
'jsx-a11y/no-interactive-element-to-noninteractive-role': 'off',
// recommended rule is:
// 'jsx-a11y/no-noninteractive-element-interactions': [
// 'error',
// {
// body: ['onError', 'onLoad'],
// iframe: ['onError', 'onLoad'],
// img: ['onError', 'onLoad'],
// },
// ],
'jsx-a11y/no-noninteractive-element-interactions': [
'warn',
{
handlers: [
'onClick',
],
},
],
// recommended rule is:
// 'jsx-a11y/no-noninteractive-tabindex': [
// 'error',
// {
// tags: [],
// roles: ['tabpanel'],
// allowExpressionValues: true,
// },
// ],
'jsx-a11y/no-noninteractive-tabindex': 'off',
'jsx-a11y/no-onchange': 'warn',
// recommended is full 'error'
'jsx-a11y/no-static-element-interactions': [
'warn',
{
handlers: [
'onClick',
],
},
],
// See https://github.com/import-js/eslint-plugin-import/blob/main/config/recommended.js
'import/extensions': [
'error',
'always',
{
js: 'never',
jsx: 'never',
mjs: 'never',
ts: 'never',
tsx: 'never',
},
],
'import/first': 'error',
'import/newline-after-import': 'error',
'import/no-anonymous-default-export': 'error',
'import/no-extraneous-dependencies': [
'error',
{
devDependencies: [
'config/webpack/**',
'app/javascript/mastodon/performance.js',
'app/javascript/mastodon/test_setup.js',
'app/javascript/**/__tests__/**',
],
},
],
'import/no-amd': 'error',
'import/no-commonjs': 'error',
'import/no-import-module-exports': 'error',
'import/no-relative-packages': 'error',
'import/no-self-import': 'error',
'import/no-useless-path-segments': 'error',
'import/no-webpack-loader-syntax': 'error',
'import/order': [
'error',
{
alphabetize: { order: 'asc' },
'newlines-between': 'always',
groups: [
'builtin',
'external',
'internal',
'parent',
['index', 'sibling'],
'object',
],
pathGroups: [
// React core packages
{
pattern: '{react,react-dom,react-dom/client,prop-types}',
group: 'builtin',
position: 'after',
},
// I18n
{
pattern: '{react-intl,intl-messageformat}',
group: 'builtin',
position: 'after',
},
// Common React utilities
{
pattern: '{classnames,react-helmet,react-router-dom}',
group: 'external',
position: 'before',
},
// Immutable / Redux / data store
{
pattern: '{immutable,react-redux,react-immutable-proptypes,react-immutable-pure-component,reselect}',
group: 'external',
position: 'before',
},
// Internal packages
{
pattern: '{mastodon/**}',
group: 'internal',
position: 'after',
},
{
pattern: '{flavours/glitch-soc/**}',
group: 'internal',
position: 'after',
},
],
pathGroupsExcludedImportTypes: [],
},
],
// Forbid imports from vanilla in glitch flavour
'import/no-restricted-paths': [
'error',
{
zones: [{
target: 'app/javascript/flavours/glitch/',
from: 'app/javascript/mastodon/',
message: 'Import from /flavours/glitch/ instead'
}]
}
],
'promise/always-return': 'off',
'promise/catch-or-return': [
'error',
{
allowFinally: true,
},
],
'promise/no-callback-in-promise': 'off',
'promise/no-nesting': 'off',
'promise/no-promise-in-callback': 'off',
'formatjs/blocklist-elements': 'error',
'formatjs/enforce-default-message': ['error', 'literal'],
'formatjs/enforce-description': 'off', // description values not currently used
'formatjs/enforce-id': 'off', // Explicit IDs are used in the project
'formatjs/enforce-placeholders': 'off', // Issues in short_number.jsx
'formatjs/enforce-plural-rules': 'error',
'formatjs/no-camel-case': 'off', // disabledAccount is only non-conforming
'formatjs/no-complex-selectors': 'error',
'formatjs/no-emoji': 'error',
'formatjs/no-id': 'off', // IDs are used for translation keys
'formatjs/no-invalid-icu': 'error',
'formatjs/no-literal-string-in-jsx': 'off', // Should be looked at, but mainly flagging punctuation outside of strings
'formatjs/no-multiple-plurals': 'off', // Only used by hashtag.jsx
'formatjs/no-multiple-whitespaces': 'error',
'formatjs/no-offset': 'error',
'formatjs/no-useless-message': 'error',
'formatjs/prefer-formatted-message': 'error',
'formatjs/prefer-pound-in-plural': 'error',
'jsdoc/check-types': 'off',
'jsdoc/no-undefined-types': 'off',
'jsdoc/require-jsdoc': 'off',
'jsdoc/require-param-description': 'off',
'jsdoc/require-property-description': 'off',
'jsdoc/require-returns-description': 'off',
'jsdoc/require-returns': 'off',
},
overrides: [
{
files: [
'*.config.js',
'.*rc.js',
'ide-helper.js',
'config/webpack/**/*',
'config/formatjs-formatter.js',
],
env: {
commonjs: true,
},
parserOptions: {
sourceType: 'script',
},
rules: {
'import/no-commonjs': 'off',
},
},
{
files: [
'**/*.ts',
'**/*.tsx',
],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/strict-type-checked',
'plugin:@typescript-eslint/stylistic-type-checked',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:jsx-a11y/recommended',
'plugin:import/recommended',
'plugin:import/typescript',
'plugin:promise/recommended',
'plugin:jsdoc/recommended-typescript',
'plugin:prettier/recommended',
],
parserOptions: {
project: true,
tsconfigRootDir: __dirname,
},
rules: {
'import/consistent-type-specifier-style': ['error', 'prefer-top-level'],
'@typescript-eslint/consistent-type-definitions': ['warn', 'interface'],
'@typescript-eslint/consistent-type-exports': 'error',
'@typescript-eslint/consistent-type-imports': 'error',
"@typescript-eslint/prefer-nullish-coalescing": ['error', {ignorePrimitives: {boolean: true}}],
'jsdoc/require-jsdoc': 'off',
// Those rules set stricter rules for TS files
// to enforce better practices when converting from JS
'import/no-default-export': 'warn',
'react/prefer-stateless-function': 'warn',
'react/function-component-definition': ['error', { namedComponents: 'arrow-function' }],
'react/jsx-uses-react': 'off', // not needed with new JSX transform
'react/react-in-jsx-scope': 'off', // not needed with new JSX transform
'react/prop-types': 'off',
},
},
{
files: [
'**/__tests__/*.js',
'**/__tests__/*.jsx',
],
env: {
jest: true,
},
},
{
files: [
'streaming/**/*',
],
rules: {
'import/no-commonjs': 'off',
},
},
],
};
+3
View File
@@ -55,6 +55,9 @@ npm-debug.log
yarn-error.log
yarn-debug.log
# Ignore yarn state file
.yarn/install-state.gz
# Ignore vagrant log files
*-cloudimg-console.log
-1
View File
@@ -1 +0,0 @@
20.8
+1 -3
View File
@@ -1,4 +1,2 @@
module.exports = {
singleQuote: true,
jsxSingleQuote: true
}
};
+5 -5
View File
@@ -1,23 +1,23 @@
steps:
lint:
image: node:22-alpine
image: docker.io/superseriousbusiness/masto-fe-standalone-woodpecker-build:0.1.0
pull: true
# https://woodpecker-ci.org/docs/usage/volumes
volumes:
- /woodpecker/masto-fe-standalone/node_modules:/woodpecker/src/codeberg.org/superseriousbusiness/masto-fe-standalone/node_modules
- /woodpecker/masto-fe-standalone/.eslintcache:/woodpecker/src/codeberg.org/superseriousbusiness/masto-fe-standalone/.eslintcache
# https://woodpecker-ci.org/docs/administration/configuration/backends/docker#run-user
backend_options:
docker:
user: 1000:1000
# https://woodpecker-ci.org/docs/usage/workflow-syntax#commands
commands:
- yarn
- yarn lint:js
# https://woodpecker-ci.org/docs/usage/workflow-syntax#when---conditional-execution
when:
- event: pull_request
+1
View File
@@ -0,0 +1 @@
nodeLinker: node-modules
+15 -1884
View File
File diff suppressed because it is too large Load Diff
+65 -3182
View File
File diff suppressed because it is too large Load Diff
+5 -1
View File
@@ -4,7 +4,11 @@
## Dependencies
To work on the code decently, you should have Node and Yarn installed. To avoid fuckery, Node Version Manager is **highly recommended**: https://github.com/nvm-sh/nvm.
To work on the code, you must have Node installed.
To avoid fuckery, Node Version Manager is **highly recommended**: https://github.com/nvm-sh/nvm. You can then install the latest `lts` version of node with `nvm install --lts && nvm use --lts`.
You should install yarn as described [here](https://yarnpkg.com/getting-started/install) and/or [here](https://yarnpkg.com/migration/guide).
## Testing Locally
+9 -6
View File
@@ -1,13 +1,13 @@
### BUILDER IMAGE ###
FROM node:lts-alpine AS builder
FROM docker.io/superseriousbusiness/masto-fe-standalone-woodpecker-build:0.1.0 AS builder
# Prepare the build directory, copy
# relevant source + config files over.
WORKDIR /build
COPY app /build/app
COPY config /build/config
COPY public /build/public
COPY \
COPY --chown=node:node app /build/app
COPY --chown=node:node config /build/config
COPY --chown=node:node public /build/public
COPY --chown=node:node \
.browserslistrc \
babel.config.js \
jsconfig.json \
@@ -20,7 +20,10 @@ COPY \
RUN yarn && yarn build:production
### RUNTIME IMAGE ###
FROM nginx:1.28.0-alpine AS runtime
FROM nginx:alpine AS runtime
# Ensure deps up to date.
RUN apk upgrade --update --no-cache
# Copy bigger nested stuff.
COPY --from=builder /build/public/packs/js/flavours/glitch /usr/share/nginx/html/packs/js/flavours/glitch
+82 -76
View File
@@ -1,49 +1,49 @@
// This file will be loaded on admin pages, regardless of theme.
import 'packs/public-path';
import { delegate } from '@rails/ujs';
import "packs/public-path";
import Rails from "@rails/ujs";
import ready from '../mastodon/ready';
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');
const element = document.querySelector("input[type=\"datetime-local\"]#announcement_ends_at");
if (valid) {
element.classList.remove('optional');
element.classList.remove("optional");
element.required = true;
element.min = target.value;
} else {
element.classList.add('optional');
element.removeAttribute('required');
element.removeAttribute('min');
element.classList.add("optional");
element.removeAttribute("required");
element.removeAttribute("min");
}
};
delegate(document, 'input[type="datetime-local"]#announcement_starts_at', 'change', ({ target }) => {
Rails.delegate(document, "input[type=\"datetime-local\"]#announcement_starts_at", "change", ({ target }) => {
setAnnouncementEndsAttributes(target);
});
const batchCheckboxClassName = '.batch-checkbox input[type="checkbox"]';
const batchCheckboxClassName = ".batch-checkbox input[type=\"checkbox\"]";
const showSelectAll = () => {
const selectAllMatchingElement = document.querySelector('.batch-table__select-all');
selectAllMatchingElement.classList.add('active');
const selectAllMatchingElement = document.querySelector(".batch-table__select-all");
selectAllMatchingElement.classList.add("active");
};
const hideSelectAll = () => {
const selectAllMatchingElement = document.querySelector('.batch-table__select-all');
const hiddenField = document.querySelector('#select_all_matching');
const selectedMsg = document.querySelector('.batch-table__select-all .selected');
const notSelectedMsg = document.querySelector('.batch-table__select-all .not-selected');
const selectAllMatchingElement = document.querySelector(".batch-table__select-all");
const hiddenField = document.querySelector("#select_all_matching");
const selectedMsg = document.querySelector(".batch-table__select-all .selected");
const notSelectedMsg = document.querySelector(".batch-table__select-all .not-selected");
selectAllMatchingElement.classList.remove('active');
selectedMsg.classList.remove('active');
notSelectedMsg.classList.add('active');
hiddenField.value = '0';
selectAllMatchingElement.classList.remove("active");
selectedMsg.classList.remove("active");
notSelectedMsg.classList.add("active");
hiddenField.value = "0";
};
delegate(document, '#batch_checkbox_all', 'change', ({ target }) => {
const selectAllMatchingElement = document.querySelector('.batch-table__select-all');
Rails.delegate(document, "#batch_checkbox_all", "change", ({ target }) => {
const selectAllMatchingElement = document.querySelector(".batch-table__select-all");
[].forEach.call(document.querySelectorAll(batchCheckboxClassName), (content) => {
content.checked = target.checked;
@@ -58,26 +58,26 @@ delegate(document, '#batch_checkbox_all', 'change', ({ target }) => {
}
});
delegate(document, '.batch-table__select-all button', 'click', () => {
const hiddenField = document.querySelector('#select_all_matching');
const active = hiddenField.value === '1';
const selectedMsg = document.querySelector('.batch-table__select-all .selected');
const notSelectedMsg = document.querySelector('.batch-table__select-all .not-selected');
Rails.delegate(document, ".batch-table__select-all button", "click", () => {
const hiddenField = document.querySelector("#select_all_matching");
const active = hiddenField.value === "1";
const selectedMsg = document.querySelector(".batch-table__select-all .selected");
const notSelectedMsg = document.querySelector(".batch-table__select-all .not-selected");
if (active) {
hiddenField.value = '0';
selectedMsg.classList.remove('active');
notSelectedMsg.classList.add('active');
hiddenField.value = "0";
selectedMsg.classList.remove("active");
notSelectedMsg.classList.add("active");
} else {
hiddenField.value = '1';
notSelectedMsg.classList.remove('active');
selectedMsg.classList.add('active');
hiddenField.value = "1";
notSelectedMsg.classList.remove("active");
selectedMsg.classList.add("active");
}
});
delegate(document, batchCheckboxClassName, 'change', () => {
const checkAllElement = document.querySelector('#batch_checkbox_all');
const selectAllMatchingElement = document.querySelector('.batch-table__select-all');
Rails.delegate(document, batchCheckboxClassName, "change", () => {
const checkAllElement = document.querySelector("#batch_checkbox_all");
const selectAllMatchingElement = document.querySelector(".batch-table__select-all");
if (checkAllElement) {
checkAllElement.checked = [].every.call(document.querySelectorAll(batchCheckboxClassName), (content) => content.checked);
@@ -93,78 +93,78 @@ delegate(document, batchCheckboxClassName, 'change', () => {
}
});
delegate(document, '.media-spoiler-show-button', 'click', () => {
[].forEach.call(document.querySelectorAll('button.media-spoiler'), (element) => {
Rails.delegate(document, ".media-spoiler-show-button", "click", () => {
[].forEach.call(document.querySelectorAll("button.media-spoiler"), (element) => {
element.click();
});
});
delegate(document, '.media-spoiler-hide-button', 'click', () => {
[].forEach.call(document.querySelectorAll('.spoiler-button.spoiler-button--visible button'), (element) => {
Rails.delegate(document, ".media-spoiler-hide-button", "click", () => {
[].forEach.call(document.querySelectorAll(".spoiler-button.spoiler-button--visible button"), (element) => {
element.click();
});
});
delegate(document, '.filter-subset--with-select select', 'change', ({ target }) => {
Rails.delegate(document, ".filter-subset--with-select select", "change", ({ target }) => {
target.form.submit();
});
const onDomainBlockSeverityChange = (target) => {
const rejectMediaDiv = document.querySelector('.input.with_label.domain_block_reject_media');
const rejectReportsDiv = document.querySelector('.input.with_label.domain_block_reject_reports');
const rejectMediaDiv = document.querySelector(".input.with_label.domain_block_reject_media");
const rejectReportsDiv = document.querySelector(".input.with_label.domain_block_reject_reports");
if (rejectMediaDiv) {
rejectMediaDiv.style.display = (target.value === 'suspend') ? 'none' : 'block';
rejectMediaDiv.style.display = (target.value === "suspend") ? "none" : "block";
}
if (rejectReportsDiv) {
rejectReportsDiv.style.display = (target.value === 'suspend') ? 'none' : 'block';
rejectReportsDiv.style.display = (target.value === "suspend") ? "none" : "block";
}
};
delegate(document, '#domain_block_severity', 'change', ({ target }) => onDomainBlockSeverityChange(target));
Rails.delegate(document, "#domain_block_severity", "change", ({ target }) => onDomainBlockSeverityChange(target));
const onEnableBootstrapTimelineAccountsChange = (target) => {
const bootstrapTimelineAccountsField = document.querySelector('#form_admin_settings_bootstrap_timeline_accounts');
const bootstrapTimelineAccountsField = document.querySelector("#form_admin_settings_bootstrap_timeline_accounts");
if (bootstrapTimelineAccountsField) {
bootstrapTimelineAccountsField.disabled = !target.checked;
if (target.checked) {
bootstrapTimelineAccountsField.parentElement.classList.remove('disabled');
bootstrapTimelineAccountsField.parentElement.parentElement.classList.remove('disabled');
bootstrapTimelineAccountsField.parentElement.classList.remove("disabled");
bootstrapTimelineAccountsField.parentElement.parentElement.classList.remove("disabled");
} else {
bootstrapTimelineAccountsField.parentElement.classList.add('disabled');
bootstrapTimelineAccountsField.parentElement.parentElement.classList.add('disabled');
bootstrapTimelineAccountsField.parentElement.classList.add("disabled");
bootstrapTimelineAccountsField.parentElement.parentElement.classList.add("disabled");
}
}
};
delegate(document, '#form_admin_settings_enable_bootstrap_timeline_accounts', 'change', ({ target }) => onEnableBootstrapTimelineAccountsChange(target));
Rails.delegate(document, "#form_admin_settings_enable_bootstrap_timeline_accounts", "change", ({ target }) => onEnableBootstrapTimelineAccountsChange(target));
const onChangeRegistrationMode = (target) => {
const enabled = target.value === 'approved';
const enabled = target.value === "approved";
[].forEach.call(document.querySelectorAll('#form_admin_settings_require_invite_text'), (input) => {
[].forEach.call(document.querySelectorAll("#form_admin_settings_require_invite_text"), (input) => {
input.disabled = !enabled;
if (enabled) {
let element = input;
do {
element.classList.remove('disabled');
element.classList.remove("disabled");
element = element.parentElement;
} while (element && !element.classList.contains('fields-group'));
} while (element && !element.classList.contains("fields-group"));
} else {
let element = input;
do {
element.classList.add('disabled');
element.classList.add("disabled");
element = element.parentElement;
} while (element && !element.classList.contains('fields-group'));
} while (element && !element.classList.contains("fields-group"));
}
});
};
const convertUTCDateTimeToLocal = (value) => {
const date = new Date(value + 'Z');
const twoChars = (x) => (x.toString().padStart(2, '0'));
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())}`;
};
@@ -173,38 +173,44 @@ const convertLocalDatetimeToUTC = (value) => {
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);
return fullISO8601.slice(0, fullISO8601.indexOf("T") + 6);
};
delegate(document, '#form_admin_settings_registrations_mode', 'change', ({ target }) => onChangeRegistrationMode(target));
Rails.delegate(document, "#form_admin_settings_registrations_mode", "change", ({ target }) => onChangeRegistrationMode(target));
ready(() => {
const domainBlockSeverityInput = document.getElementById('domain_block_severity');
if (domainBlockSeverityInput) onDomainBlockSeverityChange(domainBlockSeverityInput);
const domainBlockSeverityInput = document.getElementById("domain_block_severity");
if (domainBlockSeverityInput) {
onDomainBlockSeverityChange(domainBlockSeverityInput);
}
const enableBootstrapTimelineAccounts = document.getElementById('form_admin_settings_enable_bootstrap_timeline_accounts');
if (enableBootstrapTimelineAccounts) onEnableBootstrapTimelineAccountsChange(enableBootstrapTimelineAccounts);
const enableBootstrapTimelineAccounts = document.getElementById("form_admin_settings_enable_bootstrap_timeline_accounts");
if (enableBootstrapTimelineAccounts) {
onEnableBootstrapTimelineAccountsChange(enableBootstrapTimelineAccounts);
}
const registrationMode = document.getElementById('form_admin_settings_registrations_mode');
if (registrationMode) onChangeRegistrationMode(registrationMode);
const registrationMode = document.getElementById("form_admin_settings_registrations_mode");
if (registrationMode) {
onChangeRegistrationMode(registrationMode);
}
const checkAllElement = document.querySelector('#batch_checkbox_all');
const checkAllElement = document.querySelector("#batch_checkbox_all");
if (checkAllElement) {
checkAllElement.checked = [].every.call(document.querySelectorAll(batchCheckboxClassName), (content) => content.checked);
checkAllElement.indeterminate = !checkAllElement.checked && [].some.call(document.querySelectorAll(batchCheckboxClassName), (content) => content.checked);
}
document.querySelector('a#add-instance-button')?.addEventListener('click', (e) => {
const domain = document.querySelector('input[type="text"]#by_domain')?.value;
document.querySelector("a#add-instance-button")?.addEventListener("click", (e) => {
const domain = document.querySelector("input[type=\"text\"]#by_domain")?.value;
if (domain) {
const url = new URL(event.target.href);
url.searchParams.set('_domain', domain);
url.searchParams.set("_domain", domain);
e.target.href = url;
}
});
[].forEach.call(document.querySelectorAll('input[type="datetime-local"]'), element => {
[].forEach.call(document.querySelectorAll("input[type=\"datetime-local\"]"), element => {
if (element.value) {
element.value = convertUTCDateTimeToLocal(element.value);
}
@@ -213,15 +219,15 @@ ready(() => {
}
});
delegate(document, 'form', 'submit', ({ target }) => {
[].forEach.call(target.querySelectorAll('input[type="datetime-local"]'), element => {
Rails.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');
const announcementStartsAt = document.querySelector("input[type=\"datetime-local\"]#announcement_starts_at");
if (announcementStartsAt) {
setAnnouncementEndsAttributes(announcementStartsAt);
}
+3 -3
View File
@@ -1,3 +1,3 @@
import 'packs/public-path';
import './settings';
import './two_factor_authentication';
import "packs/public-path";
import "./settings";
import "./two_factor_authentication";
+2 -3
View File
@@ -1,6 +1,5 @@
// This file will be loaded on all pages, regardless of theme.
import 'packs/public-path';
import 'font-awesome/css/font-awesome.css';
import "packs/public-path";
require.context('../images/', true);
require.context("../images/", true);
+8 -8
View File
@@ -1,25 +1,25 @@
// This file will be loaded on embed pages, regardless of theme.
import 'packs/public-path';
import "packs/public-path";
window.addEventListener('message', e => {
window.addEventListener("message", e => {
const data = e.data || {};
if (!window.parent || data.type !== 'setHeight') {
if (!window.parent || data.type !== "setHeight") {
return;
}
function setEmbedHeight () {
window.parent.postMessage({
type: 'setHeight',
type: "setHeight",
id: data.id,
height: document.getElementsByTagName('html')[0].scrollHeight,
}, '*');
height: document.getElementsByTagName("html")[0].scrollHeight,
}, "*");
}
if (['interactive', 'complete'].includes(document.readyState)) {
if (["interactive", "complete"].includes(document.readyState)) {
setEmbedHeight();
} else {
document.addEventListener('DOMContentLoaded', setEmbedHeight);
document.addEventListener("DOMContentLoaded", setEmbedHeight);
}
});
-3
View File
@@ -1,3 +0,0 @@
import '../styles/mailer.scss';
require.context('../icons');
@@ -8,29 +8,29 @@ and performs no other task.
*/
import 'packs/public-path';
import "packs/public-path";
import axios from 'axios';
import axios from "axios";
interface JRDLink {
rel: string;
template?: string;
href?: string;
rel: string,
template?: string,
href?: string,
}
const isJRDLink = (link: unknown): link is JRDLink =>
typeof link === 'object' &&
typeof link === "object" &&
link !== null &&
'rel' in link &&
typeof link.rel === 'string' &&
(!('template' in link) || typeof link.template === 'string') &&
(!('href' in link) || typeof link.href === 'string');
"rel" in link &&
typeof link.rel === "string" &&
(!("template" in link) || typeof link.template === "string") &&
(!("href" in link) || typeof link.href === "string");
const findLink = (rel: string, data: unknown): JRDLink | undefined => {
if (
typeof data === 'object' &&
typeof data === "object" &&
data !== null &&
'links' in data &&
"links" in data &&
data.links instanceof Array
) {
return data.links.find(
@@ -42,7 +42,7 @@ const findLink = (rel: string, data: unknown): JRDLink | undefined => {
};
const findTemplateLink = (data: unknown) =>
findLink('http://ostatus.org/schema/1.0/subscribe', data)?.template;
findLink("http://ostatus.org/schema/1.0/subscribe", data)?.template;
const fetchInteractionURLSuccess = (
uri_or_domain: string,
@@ -50,7 +50,7 @@ const fetchInteractionURLSuccess = (
) => {
window.parent.postMessage(
{
type: 'fetchInteractionURL-success',
type: "fetchInteractionURL-success",
uri_or_domain,
template,
},
@@ -61,14 +61,14 @@ const fetchInteractionURLSuccess = (
const fetchInteractionURLFailure = () => {
window.parent.postMessage(
{
type: 'fetchInteractionURL-failure',
type: "fetchInteractionURL-failure",
},
window.origin,
);
};
const isValidDomain = (value: string) => {
const url = new URL('https:///path');
const url = new URL("https:///path");
url.hostname = value;
return url.hostname === value;
};
@@ -112,9 +112,9 @@ const fromURL = (url: string) => {
// Attempt to find a remote interaction URL from a `user@domain` string
const fromAcct = (acct: string) => {
acct = acct.replace(/^@/, '');
acct = acct.replace(/^@/, "");
const segments = acct.split('@');
const segments = acct.split("@");
if (segments.length !== 2 || !segments[0] || !isValidDomain(segments[1])) {
fetchInteractionURLFailure();
@@ -140,18 +140,18 @@ const fromAcct = (acct: string) => {
};
const fetchInteractionURL = (uri_or_domain: string) => {
if (uri_or_domain === '') {
if (uri_or_domain === "") {
fetchInteractionURLFailure();
} else if (/^https?:\/\//.test(uri_or_domain)) {
fromURL(uri_or_domain);
} else if (uri_or_domain.includes('@')) {
} else if (uri_or_domain.includes("@")) {
fromAcct(uri_or_domain);
} else {
fromDomain(uri_or_domain);
}
};
window.addEventListener('message', (event: MessageEvent<unknown>) => {
window.addEventListener("message", (event: MessageEvent<unknown>) => {
// Check message origin
if (
!window.origin ||
@@ -163,11 +163,11 @@ window.addEventListener('message', (event: MessageEvent<unknown>) => {
if (
event.data &&
typeof event.data === 'object' &&
'type' in event.data &&
event.data.type === 'fetchInteractionURL' &&
'uri_or_domain' in event.data &&
typeof event.data.uri_or_domain === 'string'
typeof event.data === "object" &&
"type" in event.data &&
event.data.type === "fetchInteractionURL" &&
"uri_or_domain" in event.data &&
typeof event.data.uri_or_domain === "string"
) {
fetchInteractionURL(event.data.uri_or_domain);
}
+10 -10
View File
@@ -1,24 +1,24 @@
// This file will be loaded on settings pages, regardless of theme.
import 'packs/public-path';
import { delegate } from '@rails/ujs';
import "packs/public-path";
import Rails from "@rails/ujs";
delegate(document, '#edit_profile input[type=file]', 'change', ({ target }) => {
const avatar = document.getElementById(target.id + '-preview');
Rails.delegate(document, "#edit_profile input[type=file]", "change", ({ target }) => {
const avatar = document.getElementById(target.id + "-preview");
const [file] = target.files || [];
const url = file ? URL.createObjectURL(file) : avatar.dataset.originalSrc;
avatar.src = url;
});
delegate(document, '.input-copy input', 'click', ({ target }) => {
Rails.delegate(document, ".input-copy input", "click", ({ target }) => {
target.focus();
target.select();
target.setSelectionRange(0, target.value.length);
});
delegate(document, '.input-copy button', 'click', ({ target }) => {
const input = target.parentNode.querySelector('.input-copy__wrapper input');
Rails.delegate(document, ".input-copy button", "click", ({ target }) => {
const input = target.parentNode.querySelector(".input-copy__wrapper input");
const oldReadOnly = input.readonly;
@@ -28,12 +28,12 @@ delegate(document, '.input-copy button', 'click', ({ target }) => {
input.setSelectionRange(0, input.value.length);
try {
if (document.execCommand('copy')) {
if (document.execCommand("copy")) {
input.blur();
target.parentNode.classList.add('copied');
target.parentNode.classList.add("copied");
setTimeout(() => {
target.parentNode.classList.remove('copied');
target.parentNode.classList.remove("copied");
}, 700);
}
} catch (err) {
-3
View File
@@ -10,9 +10,6 @@ pack:
embed: embed.js
error:
home:
mailer:
filename: mailer.js
stylesheet: true
modal:
public:
settings: settings.js
@@ -1,40 +1,40 @@
import 'packs/public-path';
import "packs/public-path";
import * as WebAuthnJSON from '@github/webauthn-json';
import axios from 'axios';
import * as WebAuthnJSON from "@github/webauthn-json";
import axios from "axios";
import ready from '../mastodon/ready';
import 'regenerator-runtime/runtime';
import ready from "../mastodon/ready";
import "regenerator-runtime/runtime";
function getCSRFToken() {
var CSRFSelector = document.querySelector('meta[name="csrf-token"]');
var CSRFSelector = document.querySelector("meta[name=\"csrf-token\"]");
if (CSRFSelector) {
return CSRFSelector.getAttribute('content');
return CSRFSelector.getAttribute("content");
} else {
return null;
}
}
function hideFlashMessages() {
Array.from(document.getElementsByClassName('flash-message')).forEach(function(flashMessage) {
flashMessage.classList.add('hidden');
Array.from(document.getElementsByClassName("flash-message")).forEach(function(flashMessage) {
flashMessage.classList.add("hidden");
});
}
function callback(url, body) {
axios.post(url, JSON.stringify(body), {
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'X-CSRF-Token': getCSRFToken(),
"Content-Type": "application/json",
"Accept": "application/json",
"X-CSRF-Token": getCSRFToken(),
},
credentials: 'same-origin',
credentials: "same-origin",
}).then(function(response) {
window.location.replace(response.data.redirect_path);
}).catch(function(error) {
if (error.response.status === 422) {
const errorMessage = document.getElementById('security-key-error-message');
errorMessage.classList.remove('hidden');
const errorMessage = document.getElementById("security-key-error-message");
errorMessage.classList.remove("hidden");
console.error(error.response.data.error);
} else {
console.error(error);
@@ -44,31 +44,31 @@ function callback(url, body) {
ready(() => {
if (!WebAuthnJSON.supported()) {
const unsupported_browser_message = document.getElementById('unsupported-browser-message');
const unsupported_browser_message = document.getElementById("unsupported-browser-message");
if (unsupported_browser_message) {
unsupported_browser_message.classList.remove('hidden');
document.querySelector('.btn.js-webauthn').disabled = true;
unsupported_browser_message.classList.remove("hidden");
document.querySelector(".btn.js-webauthn").disabled = true;
}
}
const webAuthnCredentialRegistrationForm = document.getElementById('new_webauthn_credential');
const webAuthnCredentialRegistrationForm = document.getElementById("new_webauthn_credential");
if (webAuthnCredentialRegistrationForm) {
webAuthnCredentialRegistrationForm.addEventListener('submit', (event) => {
webAuthnCredentialRegistrationForm.addEventListener("submit", (event) => {
event.preventDefault();
var nickname = event.target.querySelector('input[name="new_webauthn_credential[nickname]"]');
var nickname = event.target.querySelector("input[name=\"new_webauthn_credential[nickname]\"]");
if (nickname.value) {
axios.get('/settings/security_keys/options')
axios.get("/settings/security_keys/options")
.then((response) => {
const credentialOptions = response.data;
WebAuthnJSON.create({ 'publicKey': credentialOptions }).then((credential) => {
var params = { 'credential': credential, 'nickname': nickname.value };
callback('/settings/security_keys', params);
WebAuthnJSON.create({ "publicKey": credentialOptions }).then((credential) => {
var params = { "credential": credential, "nickname": nickname.value };
callback("/settings/security_keys", params);
}).catch((error) => {
const errorMessage = document.getElementById('security-key-error-message');
errorMessage.classList.remove('hidden');
const errorMessage = document.getElementById("security-key-error-message");
errorMessage.classList.remove("hidden");
console.error(error);
});
}).catch((error) => {
@@ -80,21 +80,21 @@ ready(() => {
});
}
const webAuthnCredentialAuthenticationForm = document.getElementById('webauthn-form');
const webAuthnCredentialAuthenticationForm = document.getElementById("webauthn-form");
if (webAuthnCredentialAuthenticationForm) {
webAuthnCredentialAuthenticationForm.addEventListener('submit', (event) => {
webAuthnCredentialAuthenticationForm.addEventListener("submit", (event) => {
event.preventDefault();
axios.get('sessions/security_key_options')
axios.get("sessions/security_key_options")
.then((response) => {
const credentialOptions = response.data;
WebAuthnJSON.get({ 'publicKey': credentialOptions }).then((credential) => {
var params = { 'user': { 'credential': credential } };
callback('sign_in', params);
WebAuthnJSON.get({ "publicKey": credentialOptions }).then((credential) => {
var params = { "user": { "credential": credential } };
callback("sign_in", params);
}).catch((error) => {
const errorMessage = document.getElementById('security-key-error-message');
errorMessage.classList.remove('hidden');
const errorMessage = document.getElementById("security-key-error-message");
errorMessage.classList.remove("hidden");
console.error(error);
});
}).catch((error) => {
@@ -102,19 +102,19 @@ ready(() => {
});
});
const otpAuthenticationForm = document.getElementById('otp-authentication-form');
const otpAuthenticationForm = document.getElementById("otp-authentication-form");
const linkToOtp = document.getElementById('link-to-otp');
linkToOtp.addEventListener('click', () => {
webAuthnCredentialAuthenticationForm.classList.add('hidden');
otpAuthenticationForm.classList.remove('hidden');
const linkToOtp = document.getElementById("link-to-otp");
linkToOtp.addEventListener("click", () => {
webAuthnCredentialAuthenticationForm.classList.add("hidden");
otpAuthenticationForm.classList.remove("hidden");
hideFlashMessages();
});
const linkToWebAuthn = document.getElementById('link-to-webauthn');
linkToWebAuthn.addEventListener('click', () => {
otpAuthenticationForm.classList.add('hidden');
webAuthnCredentialAuthenticationForm.classList.remove('hidden');
const linkToWebAuthn = document.getElementById("link-to-webauthn");
linkToWebAuthn.addEventListener("click", () => {
otpAuthenticationForm.classList.add("hidden");
webAuthnCredentialAuthenticationForm.classList.remove("hidden");
hideFlashMessages();
});
}
@@ -1,22 +1,22 @@
import api from '../api';
import api from "../api";
export const ACCOUNT_NOTE_SUBMIT_REQUEST = 'ACCOUNT_NOTE_SUBMIT_REQUEST';
export const ACCOUNT_NOTE_SUBMIT_SUCCESS = 'ACCOUNT_NOTE_SUBMIT_SUCCESS';
export const ACCOUNT_NOTE_SUBMIT_FAIL = 'ACCOUNT_NOTE_SUBMIT_FAIL';
export const ACCOUNT_NOTE_SUBMIT_REQUEST = "ACCOUNT_NOTE_SUBMIT_REQUEST";
export const ACCOUNT_NOTE_SUBMIT_SUCCESS = "ACCOUNT_NOTE_SUBMIT_SUCCESS";
export const ACCOUNT_NOTE_SUBMIT_FAIL = "ACCOUNT_NOTE_SUBMIT_FAIL";
export const ACCOUNT_NOTE_INIT_EDIT = 'ACCOUNT_NOTE_INIT_EDIT';
export const ACCOUNT_NOTE_CANCEL = 'ACCOUNT_NOTE_CANCEL';
export const ACCOUNT_NOTE_INIT_EDIT = "ACCOUNT_NOTE_INIT_EDIT";
export const ACCOUNT_NOTE_CANCEL = "ACCOUNT_NOTE_CANCEL";
export const ACCOUNT_NOTE_CHANGE_COMMENT = 'ACCOUNT_NOTE_CHANGE_COMMENT';
export const ACCOUNT_NOTE_CHANGE_COMMENT = "ACCOUNT_NOTE_CHANGE_COMMENT";
export function submitAccountNote() {
return (dispatch, getState) => {
dispatch(submitAccountNoteRequest());
const id = getState().getIn(['account_notes', 'edit', 'account_id']);
const id = getState().getIn(["account_notes", "edit", "account_id"]);
api(getState).post(`/api/v1/accounts/${id}/note`, {
comment: getState().getIn(['account_notes', 'edit', 'comment']),
comment: getState().getIn(["account_notes", "edit", "comment"]),
}).then(response => {
dispatch(submitAccountNoteSuccess(response.data));
}).catch(error => dispatch(submitAccountNoteFail(error)));
@@ -45,7 +45,7 @@ export function submitAccountNoteFail(error) {
export function initEditAccountNote(account) {
return (dispatch, getState) => {
const comment = getState().getIn(['relationships', account.get('id'), 'note']);
const comment = getState().getIn(["relationships", account.get("id"), "note"]);
dispatch({
type: ACCOUNT_NOTE_INIT_EDIT,
@@ -1,104 +1,104 @@
import api, { getLinks } from '../api';
import api, { getLinks } from "../api";
import { importFetchedAccount, importFetchedAccounts } from './importer';
import { importFetchedAccount, importFetchedAccounts } from "./importer";
export const ACCOUNT_FETCH_REQUEST = 'ACCOUNT_FETCH_REQUEST';
export const ACCOUNT_FETCH_SUCCESS = 'ACCOUNT_FETCH_SUCCESS';
export const ACCOUNT_FETCH_FAIL = 'ACCOUNT_FETCH_FAIL';
export const ACCOUNT_FETCH_REQUEST = "ACCOUNT_FETCH_REQUEST";
export const ACCOUNT_FETCH_SUCCESS = "ACCOUNT_FETCH_SUCCESS";
export const ACCOUNT_FETCH_FAIL = "ACCOUNT_FETCH_FAIL";
export const ACCOUNT_LOOKUP_REQUEST = 'ACCOUNT_LOOKUP_REQUEST';
export const ACCOUNT_LOOKUP_SUCCESS = 'ACCOUNT_LOOKUP_SUCCESS';
export const ACCOUNT_LOOKUP_FAIL = 'ACCOUNT_LOOKUP_FAIL';
export const ACCOUNT_LOOKUP_REQUEST = "ACCOUNT_LOOKUP_REQUEST";
export const ACCOUNT_LOOKUP_SUCCESS = "ACCOUNT_LOOKUP_SUCCESS";
export const ACCOUNT_LOOKUP_FAIL = "ACCOUNT_LOOKUP_FAIL";
export const ACCOUNT_FOLLOW_REQUEST = 'ACCOUNT_FOLLOW_REQUEST';
export const ACCOUNT_FOLLOW_SUCCESS = 'ACCOUNT_FOLLOW_SUCCESS';
export const ACCOUNT_FOLLOW_FAIL = 'ACCOUNT_FOLLOW_FAIL';
export const ACCOUNT_FOLLOW_REQUEST = "ACCOUNT_FOLLOW_REQUEST";
export const ACCOUNT_FOLLOW_SUCCESS = "ACCOUNT_FOLLOW_SUCCESS";
export const ACCOUNT_FOLLOW_FAIL = "ACCOUNT_FOLLOW_FAIL";
export const ACCOUNT_UNFOLLOW_REQUEST = 'ACCOUNT_UNFOLLOW_REQUEST';
export const ACCOUNT_UNFOLLOW_SUCCESS = 'ACCOUNT_UNFOLLOW_SUCCESS';
export const ACCOUNT_UNFOLLOW_FAIL = 'ACCOUNT_UNFOLLOW_FAIL';
export const ACCOUNT_UNFOLLOW_REQUEST = "ACCOUNT_UNFOLLOW_REQUEST";
export const ACCOUNT_UNFOLLOW_SUCCESS = "ACCOUNT_UNFOLLOW_SUCCESS";
export const ACCOUNT_UNFOLLOW_FAIL = "ACCOUNT_UNFOLLOW_FAIL";
export const ACCOUNT_BLOCK_REQUEST = 'ACCOUNT_BLOCK_REQUEST';
export const ACCOUNT_BLOCK_SUCCESS = 'ACCOUNT_BLOCK_SUCCESS';
export const ACCOUNT_BLOCK_FAIL = 'ACCOUNT_BLOCK_FAIL';
export const ACCOUNT_BLOCK_REQUEST = "ACCOUNT_BLOCK_REQUEST";
export const ACCOUNT_BLOCK_SUCCESS = "ACCOUNT_BLOCK_SUCCESS";
export const ACCOUNT_BLOCK_FAIL = "ACCOUNT_BLOCK_FAIL";
export const ACCOUNT_UNBLOCK_REQUEST = 'ACCOUNT_UNBLOCK_REQUEST';
export const ACCOUNT_UNBLOCK_SUCCESS = 'ACCOUNT_UNBLOCK_SUCCESS';
export const ACCOUNT_UNBLOCK_FAIL = 'ACCOUNT_UNBLOCK_FAIL';
export const ACCOUNT_UNBLOCK_REQUEST = "ACCOUNT_UNBLOCK_REQUEST";
export const ACCOUNT_UNBLOCK_SUCCESS = "ACCOUNT_UNBLOCK_SUCCESS";
export const ACCOUNT_UNBLOCK_FAIL = "ACCOUNT_UNBLOCK_FAIL";
export const ACCOUNT_MUTE_REQUEST = 'ACCOUNT_MUTE_REQUEST';
export const ACCOUNT_MUTE_SUCCESS = 'ACCOUNT_MUTE_SUCCESS';
export const ACCOUNT_MUTE_FAIL = 'ACCOUNT_MUTE_FAIL';
export const ACCOUNT_MUTE_REQUEST = "ACCOUNT_MUTE_REQUEST";
export const ACCOUNT_MUTE_SUCCESS = "ACCOUNT_MUTE_SUCCESS";
export const ACCOUNT_MUTE_FAIL = "ACCOUNT_MUTE_FAIL";
export const ACCOUNT_UNMUTE_REQUEST = 'ACCOUNT_UNMUTE_REQUEST';
export const ACCOUNT_UNMUTE_SUCCESS = 'ACCOUNT_UNMUTE_SUCCESS';
export const ACCOUNT_UNMUTE_FAIL = 'ACCOUNT_UNMUTE_FAIL';
export const ACCOUNT_UNMUTE_REQUEST = "ACCOUNT_UNMUTE_REQUEST";
export const ACCOUNT_UNMUTE_SUCCESS = "ACCOUNT_UNMUTE_SUCCESS";
export const ACCOUNT_UNMUTE_FAIL = "ACCOUNT_UNMUTE_FAIL";
export const ACCOUNT_PIN_REQUEST = 'ACCOUNT_PIN_REQUEST';
export const ACCOUNT_PIN_SUCCESS = 'ACCOUNT_PIN_SUCCESS';
export const ACCOUNT_PIN_FAIL = 'ACCOUNT_PIN_FAIL';
export const ACCOUNT_PIN_REQUEST = "ACCOUNT_PIN_REQUEST";
export const ACCOUNT_PIN_SUCCESS = "ACCOUNT_PIN_SUCCESS";
export const ACCOUNT_PIN_FAIL = "ACCOUNT_PIN_FAIL";
export const ACCOUNT_UNPIN_REQUEST = 'ACCOUNT_UNPIN_REQUEST';
export const ACCOUNT_UNPIN_SUCCESS = 'ACCOUNT_UNPIN_SUCCESS';
export const ACCOUNT_UNPIN_FAIL = 'ACCOUNT_UNPIN_FAIL';
export const ACCOUNT_UNPIN_REQUEST = "ACCOUNT_UNPIN_REQUEST";
export const ACCOUNT_UNPIN_SUCCESS = "ACCOUNT_UNPIN_SUCCESS";
export const ACCOUNT_UNPIN_FAIL = "ACCOUNT_UNPIN_FAIL";
export const FOLLOWERS_FETCH_REQUEST = 'FOLLOWERS_FETCH_REQUEST';
export const FOLLOWERS_FETCH_SUCCESS = 'FOLLOWERS_FETCH_SUCCESS';
export const FOLLOWERS_FETCH_FAIL = 'FOLLOWERS_FETCH_FAIL';
export const FOLLOWERS_FETCH_REQUEST = "FOLLOWERS_FETCH_REQUEST";
export const FOLLOWERS_FETCH_SUCCESS = "FOLLOWERS_FETCH_SUCCESS";
export const FOLLOWERS_FETCH_FAIL = "FOLLOWERS_FETCH_FAIL";
export const FOLLOWERS_EXPAND_REQUEST = 'FOLLOWERS_EXPAND_REQUEST';
export const FOLLOWERS_EXPAND_SUCCESS = 'FOLLOWERS_EXPAND_SUCCESS';
export const FOLLOWERS_EXPAND_FAIL = 'FOLLOWERS_EXPAND_FAIL';
export const FOLLOWERS_EXPAND_REQUEST = "FOLLOWERS_EXPAND_REQUEST";
export const FOLLOWERS_EXPAND_SUCCESS = "FOLLOWERS_EXPAND_SUCCESS";
export const FOLLOWERS_EXPAND_FAIL = "FOLLOWERS_EXPAND_FAIL";
export const FOLLOWING_FETCH_REQUEST = 'FOLLOWING_FETCH_REQUEST';
export const FOLLOWING_FETCH_SUCCESS = 'FOLLOWING_FETCH_SUCCESS';
export const FOLLOWING_FETCH_FAIL = 'FOLLOWING_FETCH_FAIL';
export const FOLLOWING_FETCH_REQUEST = "FOLLOWING_FETCH_REQUEST";
export const FOLLOWING_FETCH_SUCCESS = "FOLLOWING_FETCH_SUCCESS";
export const FOLLOWING_FETCH_FAIL = "FOLLOWING_FETCH_FAIL";
export const FOLLOWING_EXPAND_REQUEST = 'FOLLOWING_EXPAND_REQUEST';
export const FOLLOWING_EXPAND_SUCCESS = 'FOLLOWING_EXPAND_SUCCESS';
export const FOLLOWING_EXPAND_FAIL = 'FOLLOWING_EXPAND_FAIL';
export const FOLLOWING_EXPAND_REQUEST = "FOLLOWING_EXPAND_REQUEST";
export const FOLLOWING_EXPAND_SUCCESS = "FOLLOWING_EXPAND_SUCCESS";
export const FOLLOWING_EXPAND_FAIL = "FOLLOWING_EXPAND_FAIL";
export const RELATIONSHIPS_FETCH_REQUEST = 'RELATIONSHIPS_FETCH_REQUEST';
export const RELATIONSHIPS_FETCH_SUCCESS = 'RELATIONSHIPS_FETCH_SUCCESS';
export const RELATIONSHIPS_FETCH_FAIL = 'RELATIONSHIPS_FETCH_FAIL';
export const RELATIONSHIPS_FETCH_REQUEST = "RELATIONSHIPS_FETCH_REQUEST";
export const RELATIONSHIPS_FETCH_SUCCESS = "RELATIONSHIPS_FETCH_SUCCESS";
export const RELATIONSHIPS_FETCH_FAIL = "RELATIONSHIPS_FETCH_FAIL";
export const FOLLOW_REQUESTS_FETCH_REQUEST = 'FOLLOW_REQUESTS_FETCH_REQUEST';
export const FOLLOW_REQUESTS_FETCH_SUCCESS = 'FOLLOW_REQUESTS_FETCH_SUCCESS';
export const FOLLOW_REQUESTS_FETCH_FAIL = 'FOLLOW_REQUESTS_FETCH_FAIL';
export const FOLLOW_REQUESTS_FETCH_REQUEST = "FOLLOW_REQUESTS_FETCH_REQUEST";
export const FOLLOW_REQUESTS_FETCH_SUCCESS = "FOLLOW_REQUESTS_FETCH_SUCCESS";
export const FOLLOW_REQUESTS_FETCH_FAIL = "FOLLOW_REQUESTS_FETCH_FAIL";
export const FOLLOW_REQUESTS_EXPAND_REQUEST = 'FOLLOW_REQUESTS_EXPAND_REQUEST';
export const FOLLOW_REQUESTS_EXPAND_SUCCESS = 'FOLLOW_REQUESTS_EXPAND_SUCCESS';
export const FOLLOW_REQUESTS_EXPAND_FAIL = 'FOLLOW_REQUESTS_EXPAND_FAIL';
export const FOLLOW_REQUESTS_EXPAND_REQUEST = "FOLLOW_REQUESTS_EXPAND_REQUEST";
export const FOLLOW_REQUESTS_EXPAND_SUCCESS = "FOLLOW_REQUESTS_EXPAND_SUCCESS";
export const FOLLOW_REQUESTS_EXPAND_FAIL = "FOLLOW_REQUESTS_EXPAND_FAIL";
export const FOLLOW_REQUEST_AUTHORIZE_REQUEST = 'FOLLOW_REQUEST_AUTHORIZE_REQUEST';
export const FOLLOW_REQUEST_AUTHORIZE_SUCCESS = 'FOLLOW_REQUEST_AUTHORIZE_SUCCESS';
export const FOLLOW_REQUEST_AUTHORIZE_FAIL = 'FOLLOW_REQUEST_AUTHORIZE_FAIL';
export const FOLLOW_REQUEST_AUTHORIZE_REQUEST = "FOLLOW_REQUEST_AUTHORIZE_REQUEST";
export const FOLLOW_REQUEST_AUTHORIZE_SUCCESS = "FOLLOW_REQUEST_AUTHORIZE_SUCCESS";
export const FOLLOW_REQUEST_AUTHORIZE_FAIL = "FOLLOW_REQUEST_AUTHORIZE_FAIL";
export const FOLLOW_REQUEST_REJECT_REQUEST = 'FOLLOW_REQUEST_REJECT_REQUEST';
export const FOLLOW_REQUEST_REJECT_SUCCESS = 'FOLLOW_REQUEST_REJECT_SUCCESS';
export const FOLLOW_REQUEST_REJECT_FAIL = 'FOLLOW_REQUEST_REJECT_FAIL';
export const FOLLOW_REQUEST_REJECT_REQUEST = "FOLLOW_REQUEST_REJECT_REQUEST";
export const FOLLOW_REQUEST_REJECT_SUCCESS = "FOLLOW_REQUEST_REJECT_SUCCESS";
export const FOLLOW_REQUEST_REJECT_FAIL = "FOLLOW_REQUEST_REJECT_FAIL";
export const PINNED_ACCOUNTS_FETCH_REQUEST = 'PINNED_ACCOUNTS_FETCH_REQUEST';
export const PINNED_ACCOUNTS_FETCH_SUCCESS = 'PINNED_ACCOUNTS_FETCH_SUCCESS';
export const PINNED_ACCOUNTS_FETCH_FAIL = 'PINNED_ACCOUNTS_FETCH_FAIL';
export const PINNED_ACCOUNTS_FETCH_REQUEST = "PINNED_ACCOUNTS_FETCH_REQUEST";
export const PINNED_ACCOUNTS_FETCH_SUCCESS = "PINNED_ACCOUNTS_FETCH_SUCCESS";
export const PINNED_ACCOUNTS_FETCH_FAIL = "PINNED_ACCOUNTS_FETCH_FAIL";
export const PINNED_ACCOUNTS_SUGGESTIONS_FETCH_REQUEST = 'PINNED_ACCOUNTS_SUGGESTIONS_FETCH_REQUEST';
export const PINNED_ACCOUNTS_SUGGESTIONS_FETCH_SUCCESS = 'PINNED_ACCOUNTS_SUGGESTIONS_FETCH_SUCCESS';
export const PINNED_ACCOUNTS_SUGGESTIONS_FETCH_FAIL = 'PINNED_ACCOUNTS_SUGGESTIONS_FETCH_FAIL';
export const PINNED_ACCOUNTS_SUGGESTIONS_FETCH_REQUEST = "PINNED_ACCOUNTS_SUGGESTIONS_FETCH_REQUEST";
export const PINNED_ACCOUNTS_SUGGESTIONS_FETCH_SUCCESS = "PINNED_ACCOUNTS_SUGGESTIONS_FETCH_SUCCESS";
export const PINNED_ACCOUNTS_SUGGESTIONS_FETCH_FAIL = "PINNED_ACCOUNTS_SUGGESTIONS_FETCH_FAIL";
export const PINNED_ACCOUNTS_EDITOR_SUGGESTIONS_CLEAR = 'PINNED_ACCOUNTS_EDITOR_SUGGESTIONS_CLEAR';
export const PINNED_ACCOUNTS_EDITOR_SUGGESTIONS_CHANGE = 'PINNED_ACCOUNTS_EDITOR_SUGGESTIONS_CHANGE';
export const PINNED_ACCOUNTS_EDITOR_SUGGESTIONS_CLEAR = "PINNED_ACCOUNTS_EDITOR_SUGGESTIONS_CLEAR";
export const PINNED_ACCOUNTS_EDITOR_SUGGESTIONS_CHANGE = "PINNED_ACCOUNTS_EDITOR_SUGGESTIONS_CHANGE";
export const PINNED_ACCOUNTS_EDITOR_RESET = 'PINNED_ACCOUNTS_EDITOR_RESET';
export const PINNED_ACCOUNTS_EDITOR_RESET = "PINNED_ACCOUNTS_EDITOR_RESET";
export const ACCOUNT_REVEAL = 'ACCOUNT_REVEAL';
export const ACCOUNT_REVEAL = "ACCOUNT_REVEAL";
export function fetchAccount(id) {
return (dispatch, getState) => {
dispatch(fetchRelationships([id]));
if (getState().getIn(['accounts', id], null) !== null) {
if (getState().getIn(["accounts", id], null) !== null) {
return;
}
@@ -117,7 +117,7 @@ export function fetchAccount(id) {
export const lookupAccount = acct => (dispatch, getState) => {
dispatch(lookupAccountRequest(acct));
api(getState).get('/api/v1/accounts/lookup', { params: { acct } }).then(response => {
api(getState).get("/api/v1/accounts/lookup", { params: { acct } }).then(response => {
dispatch(fetchRelationships([response.data.id]));
dispatch(importFetchedAccount(response.data));
dispatch(lookupAccountSuccess());
@@ -166,8 +166,8 @@ export function fetchAccountFail(id, error) {
export function followAccount(id, options = { reblogs: true }) {
return (dispatch, getState) => {
const alreadyFollowing = getState().getIn(['relationships', id, 'following']);
const locked = getState().getIn(['accounts', id, 'locked'], false);
const alreadyFollowing = getState().getIn(["relationships", id, "following"]);
const locked = getState().getIn(["accounts", id, "locked"], false);
dispatch(followAccountRequest(id, locked));
@@ -184,7 +184,7 @@ export function unfollowAccount(id) {
dispatch(unfollowAccountRequest(id));
api(getState).post(`/api/v1/accounts/${id}/unfollow`).then(response => {
dispatch(unfollowAccountSuccess(response.data, getState().get('statuses')));
dispatch(unfollowAccountSuccess(response.data, getState().get("statuses")));
}).catch(error => {
dispatch(unfollowAccountFail(error));
});
@@ -249,7 +249,7 @@ export function blockAccount(id) {
api(getState).post(`/api/v1/accounts/${id}/block`).then(response => {
// Pass in entire statuses map so we can use it to filter stuff in different parts of the reducers
dispatch(blockAccountSuccess(response.data, getState().get('statuses')));
dispatch(blockAccountSuccess(response.data, getState().get("statuses")));
}).catch(error => {
dispatch(blockAccountFail(id, error));
});
@@ -318,7 +318,7 @@ export function muteAccount(id, notifications, duration=0) {
api(getState).post(`/api/v1/accounts/${id}/mute`, { notifications, duration }).then(response => {
// Pass in entire statuses map so we can use it to filter stuff in different parts of the reducers
dispatch(muteAccountSuccess(response.data, getState().get('statuses')));
dispatch(muteAccountSuccess(response.data, getState().get("statuses")));
}).catch(error => {
dispatch(muteAccountFail(id, error));
});
@@ -386,7 +386,7 @@ export function fetchFollowers(id) {
dispatch(fetchFollowersRequest(id));
api(getState).get(`/api/v1/accounts/${id}/followers`).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedAccounts(response.data));
dispatch(fetchFollowersSuccess(id, response.data, next ? next.uri : null));
@@ -424,7 +424,7 @@ export function fetchFollowersFail(id, error) {
export function expandFollowers(id) {
return (dispatch, getState) => {
const url = getState().getIn(['user_lists', 'followers', id, 'next']);
const url = getState().getIn(["user_lists", "followers", id, "next"]);
if (url === null) {
return;
@@ -433,7 +433,7 @@ export function expandFollowers(id) {
dispatch(expandFollowersRequest(id));
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedAccounts(response.data));
dispatch(expandFollowersSuccess(id, response.data, next ? next.uri : null));
@@ -473,7 +473,7 @@ export function fetchFollowing(id) {
dispatch(fetchFollowingRequest(id));
api(getState).get(`/api/v1/accounts/${id}/following`).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedAccounts(response.data));
dispatch(fetchFollowingSuccess(id, response.data, next ? next.uri : null));
@@ -511,7 +511,7 @@ export function fetchFollowingFail(id, error) {
export function expandFollowing(id) {
return (dispatch, getState) => {
const url = getState().getIn(['user_lists', 'following', id, 'next']);
const url = getState().getIn(["user_lists", "following", id, "next"]);
if (url === null) {
return;
@@ -520,7 +520,7 @@ export function expandFollowing(id) {
dispatch(expandFollowingRequest(id));
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedAccounts(response.data));
dispatch(expandFollowingSuccess(id, response.data, next ? next.uri : null));
@@ -558,9 +558,9 @@ export function expandFollowingFail(id, error) {
export function fetchRelationships(accountIds) {
return (dispatch, getState) => {
const state = getState();
const loadedRelationships = state.get('relationships');
const loadedRelationships = state.get("relationships");
const newAccountIds = accountIds.filter(id => loadedRelationships.get(id, null) === null);
const signedIn = !!state.getIn(['meta', 'me']);
const signedIn = !!state.getIn(["meta", "me"]);
if (!signedIn || newAccountIds.length === 0) {
return;
@@ -568,7 +568,7 @@ export function fetchRelationships(accountIds) {
dispatch(fetchRelationshipsRequest(newAccountIds));
api(getState).get(`/api/v1/accounts/relationships?${newAccountIds.map(id => `id[]=${id}`).join('&')}`).then(response => {
api(getState).get(`/api/v1/accounts/relationships?${newAccountIds.map(id => `id[]=${id}`).join("&")}`).then(response => {
dispatch(fetchRelationshipsSuccess(response.data));
}).catch(error => {
dispatch(fetchRelationshipsFail(error));
@@ -605,8 +605,8 @@ export function fetchFollowRequests() {
return (dispatch, getState) => {
dispatch(fetchFollowRequestsRequest());
api(getState).get('/api/v1/follow_requests').then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
api(getState).get("/api/v1/follow_requests").then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedAccounts(response.data));
dispatch(fetchFollowRequestsSuccess(response.data, next ? next.uri : null));
}).catch(error => dispatch(fetchFollowRequestsFail(error)));
@@ -636,7 +636,7 @@ export function fetchFollowRequestsFail(error) {
export function expandFollowRequests() {
return (dispatch, getState) => {
const url = getState().getIn(['user_lists', 'follow_requests', 'next']);
const url = getState().getIn(["user_lists", "follow_requests", "next"]);
if (url === null) {
return;
@@ -645,7 +645,7 @@ export function expandFollowRequests() {
dispatch(expandFollowRequestsRequest());
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedAccounts(response.data));
dispatch(expandFollowRequestsSuccess(response.data, next ? next.uri : null));
}).catch(error => dispatch(expandFollowRequestsFail(error)));
@@ -815,7 +815,7 @@ export function fetchPinnedAccounts() {
return (dispatch, getState) => {
dispatch(fetchPinnedAccountsRequest());
api(getState).get('/api/v1/endorsements', { params: { limit: 0 } }).then(response => {
api(getState).get("/api/v1/endorsements", { params: { limit: 0 } }).then(response => {
dispatch(importFetchedAccounts(response.data));
dispatch(fetchPinnedAccountsSuccess(response.data));
}).catch(err => dispatch(fetchPinnedAccountsFail(err)));
@@ -854,7 +854,7 @@ export function fetchPinnedAccountsSuggestions(q) {
following: true,
};
api(getState).get('/api/v1/accounts/search', { params }).then(response => {
api(getState).get("/api/v1/accounts/search", { params }).then(response => {
dispatch(importFetchedAccounts(response.data));
dispatch(fetchPinnedAccountsSuggestionsSuccess(q, response.data));
}).catch(err => dispatch(fetchPinnedAccountsSuggestionsFail(err)));
@@ -1,16 +1,16 @@
import { defineMessages } from 'react-intl';
import { defineMessages } from "react-intl";
const messages = defineMessages({
unexpectedTitle: { id: 'alert.unexpected.title', defaultMessage: 'Oops!' },
unexpectedMessage: { id: 'alert.unexpected.message', defaultMessage: 'An unexpected error occurred.' },
rateLimitedTitle: { id: 'alert.rate_limited.title', defaultMessage: 'Rate limited' },
rateLimitedMessage: { id: 'alert.rate_limited.message', defaultMessage: 'Please retry after {retry_time, time, medium}.' },
unexpectedTitle: { id: "alert.unexpected.title", defaultMessage: "Oops!" },
unexpectedMessage: { id: "alert.unexpected.message", defaultMessage: "An unexpected error occurred." },
rateLimitedTitle: { id: "alert.rate_limited.title", defaultMessage: "Rate limited" },
rateLimitedMessage: { id: "alert.rate_limited.message", defaultMessage: "Please retry after {retry_time, time, medium}." },
});
export const ALERT_SHOW = 'ALERT_SHOW';
export const ALERT_DISMISS = 'ALERT_DISMISS';
export const ALERT_CLEAR = 'ALERT_CLEAR';
export const ALERT_NOOP = 'ALERT_NOOP';
export const ALERT_SHOW = "ALERT_SHOW";
export const ALERT_DISMISS = "ALERT_DISMISS";
export const ALERT_CLEAR = "ALERT_CLEAR";
export const ALERT_NOOP = "ALERT_NOOP";
export function dismissAlert(alert) {
return {
@@ -43,9 +43,9 @@ export function showAlertForError(error, skipNotFound = false) {
return { type: ALERT_NOOP };
}
if (status === 429 && headers['x-ratelimit-reset']) {
const reset_date = new Date(headers['x-ratelimit-reset']);
return showAlert(messages.rateLimitedTitle, messages.rateLimitedMessage, { 'retry_time': reset_date });
if (status === 429 && headers["x-ratelimit-reset"]) {
const reset_date = new Date(headers["x-ratelimit-reset"]);
return showAlert(messages.rateLimitedTitle, messages.rateLimitedMessage, { "retry_time": reset_date });
}
let message = statusText;
@@ -1,35 +1,35 @@
import api from '../api';
import api from "../api";
import { normalizeAnnouncement } from './importer/normalizer';
import { normalizeAnnouncement } from "./importer/normalizer";
export const ANNOUNCEMENTS_FETCH_REQUEST = 'ANNOUNCEMENTS_FETCH_REQUEST';
export const ANNOUNCEMENTS_FETCH_SUCCESS = 'ANNOUNCEMENTS_FETCH_SUCCESS';
export const ANNOUNCEMENTS_FETCH_FAIL = 'ANNOUNCEMENTS_FETCH_FAIL';
export const ANNOUNCEMENTS_UPDATE = 'ANNOUNCEMENTS_UPDATE';
export const ANNOUNCEMENTS_DELETE = 'ANNOUNCEMENTS_DELETE';
export const ANNOUNCEMENTS_FETCH_REQUEST = "ANNOUNCEMENTS_FETCH_REQUEST";
export const ANNOUNCEMENTS_FETCH_SUCCESS = "ANNOUNCEMENTS_FETCH_SUCCESS";
export const ANNOUNCEMENTS_FETCH_FAIL = "ANNOUNCEMENTS_FETCH_FAIL";
export const ANNOUNCEMENTS_UPDATE = "ANNOUNCEMENTS_UPDATE";
export const ANNOUNCEMENTS_DELETE = "ANNOUNCEMENTS_DELETE";
export const ANNOUNCEMENTS_DISMISS_REQUEST = 'ANNOUNCEMENTS_DISMISS_REQUEST';
export const ANNOUNCEMENTS_DISMISS_SUCCESS = 'ANNOUNCEMENTS_DISMISS_SUCCESS';
export const ANNOUNCEMENTS_DISMISS_FAIL = 'ANNOUNCEMENTS_DISMISS_FAIL';
export const ANNOUNCEMENTS_DISMISS_REQUEST = "ANNOUNCEMENTS_DISMISS_REQUEST";
export const ANNOUNCEMENTS_DISMISS_SUCCESS = "ANNOUNCEMENTS_DISMISS_SUCCESS";
export const ANNOUNCEMENTS_DISMISS_FAIL = "ANNOUNCEMENTS_DISMISS_FAIL";
export const ANNOUNCEMENTS_REACTION_ADD_REQUEST = 'ANNOUNCEMENTS_REACTION_ADD_REQUEST';
export const ANNOUNCEMENTS_REACTION_ADD_SUCCESS = 'ANNOUNCEMENTS_REACTION_ADD_SUCCESS';
export const ANNOUNCEMENTS_REACTION_ADD_FAIL = 'ANNOUNCEMENTS_REACTION_ADD_FAIL';
export const ANNOUNCEMENTS_REACTION_ADD_REQUEST = "ANNOUNCEMENTS_REACTION_ADD_REQUEST";
export const ANNOUNCEMENTS_REACTION_ADD_SUCCESS = "ANNOUNCEMENTS_REACTION_ADD_SUCCESS";
export const ANNOUNCEMENTS_REACTION_ADD_FAIL = "ANNOUNCEMENTS_REACTION_ADD_FAIL";
export const ANNOUNCEMENTS_REACTION_REMOVE_REQUEST = 'ANNOUNCEMENTS_REACTION_REMOVE_REQUEST';
export const ANNOUNCEMENTS_REACTION_REMOVE_SUCCESS = 'ANNOUNCEMENTS_REACTION_REMOVE_SUCCESS';
export const ANNOUNCEMENTS_REACTION_REMOVE_FAIL = 'ANNOUNCEMENTS_REACTION_REMOVE_FAIL';
export const ANNOUNCEMENTS_REACTION_REMOVE_REQUEST = "ANNOUNCEMENTS_REACTION_REMOVE_REQUEST";
export const ANNOUNCEMENTS_REACTION_REMOVE_SUCCESS = "ANNOUNCEMENTS_REACTION_REMOVE_SUCCESS";
export const ANNOUNCEMENTS_REACTION_REMOVE_FAIL = "ANNOUNCEMENTS_REACTION_REMOVE_FAIL";
export const ANNOUNCEMENTS_REACTION_UPDATE = 'ANNOUNCEMENTS_REACTION_UPDATE';
export const ANNOUNCEMENTS_REACTION_UPDATE = "ANNOUNCEMENTS_REACTION_UPDATE";
export const ANNOUNCEMENTS_TOGGLE_SHOW = 'ANNOUNCEMENTS_TOGGLE_SHOW';
export const ANNOUNCEMENTS_TOGGLE_SHOW = "ANNOUNCEMENTS_TOGGLE_SHOW";
const noOp = () => {};
export const fetchAnnouncements = (done = noOp) => (dispatch, getState) => {
dispatch(fetchAnnouncementsRequest());
api(getState).get('/api/v1/announcements').then(response => {
api(getState).get("/api/v1/announcements").then(response => {
dispatch(fetchAnnouncementsSuccess(response.data.map(x => normalizeAnnouncement(x))));
}).catch(error => {
dispatch(fetchAnnouncementsFail(error));
@@ -88,13 +88,13 @@ export const dismissAnnouncementFail = (announcementId, error) => ({
});
export const addReaction = (announcementId, name) => (dispatch, getState) => {
const announcement = getState().getIn(['announcements', 'items']).find(x => x.get('id') === announcementId);
const announcement = getState().getIn(["announcements", "items"]).find(x => x.get("id") === announcementId);
let alreadyAdded = false;
if (announcement) {
const reaction = announcement.get('reactions').find(x => x.get('name') === name);
if (reaction && reaction.get('me')) {
const reaction = announcement.get("reactions").find(x => x.get("name") === name);
if (reaction && reaction.get("me")) {
alreadyAdded = true;
}
}
@@ -1,9 +1,9 @@
import { createAction } from '@reduxjs/toolkit';
import { createAction } from "@reduxjs/toolkit";
import type { LayoutType } from '../is_mobile';
import { type LayoutType } from "../is_mobile";
interface ChangeLayoutPayload {
layout: LayoutType;
layout: LayoutType,
}
export const changeLayout =
createAction<ChangeLayoutPayload>('APP_LAYOUT_CHANGE');
createAction<ChangeLayoutPayload>("APP_LAYOUT_CHANGE");
@@ -1,25 +1,25 @@
import api, { getLinks } from '../api';
import api, { getLinks } from "../api";
import { fetchRelationships } from './accounts';
import { importFetchedAccounts } from './importer';
import { openModal } from './modal';
import { fetchRelationships } from "./accounts";
import { importFetchedAccounts } from "./importer";
import { openModal } from "./modal";
export const BLOCKS_FETCH_REQUEST = 'BLOCKS_FETCH_REQUEST';
export const BLOCKS_FETCH_SUCCESS = 'BLOCKS_FETCH_SUCCESS';
export const BLOCKS_FETCH_FAIL = 'BLOCKS_FETCH_FAIL';
export const BLOCKS_FETCH_REQUEST = "BLOCKS_FETCH_REQUEST";
export const BLOCKS_FETCH_SUCCESS = "BLOCKS_FETCH_SUCCESS";
export const BLOCKS_FETCH_FAIL = "BLOCKS_FETCH_FAIL";
export const BLOCKS_EXPAND_REQUEST = 'BLOCKS_EXPAND_REQUEST';
export const BLOCKS_EXPAND_SUCCESS = 'BLOCKS_EXPAND_SUCCESS';
export const BLOCKS_EXPAND_FAIL = 'BLOCKS_EXPAND_FAIL';
export const BLOCKS_EXPAND_REQUEST = "BLOCKS_EXPAND_REQUEST";
export const BLOCKS_EXPAND_SUCCESS = "BLOCKS_EXPAND_SUCCESS";
export const BLOCKS_EXPAND_FAIL = "BLOCKS_EXPAND_FAIL";
export const BLOCKS_INIT_MODAL = 'BLOCKS_INIT_MODAL';
export const BLOCKS_INIT_MODAL = "BLOCKS_INIT_MODAL";
export function fetchBlocks() {
return (dispatch, getState) => {
dispatch(fetchBlocksRequest());
api(getState).get('/api/v1/blocks').then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
api(getState).get("/api/v1/blocks").then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedAccounts(response.data));
dispatch(fetchBlocksSuccess(response.data, next ? next.uri : null));
dispatch(fetchRelationships(response.data.map(item => item.id)));
@@ -50,7 +50,7 @@ export function fetchBlocksFail(error) {
export function expandBlocks() {
return (dispatch, getState) => {
const url = getState().getIn(['user_lists', 'blocks', 'next']);
const url = getState().getIn(["user_lists", "blocks", "next"]);
if (url === null) {
return;
@@ -59,7 +59,7 @@ export function expandBlocks() {
dispatch(expandBlocksRequest());
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedAccounts(response.data));
dispatch(expandBlocksSuccess(response.data, next ? next.uri : null));
dispatch(fetchRelationships(response.data.map(item => item.id)));
@@ -95,6 +95,6 @@ export function initBlockModal(account) {
account,
});
dispatch(openModal({ modalType: 'BLOCK' }));
dispatch(openModal({ modalType: "BLOCK" }));
};
}
@@ -1,25 +1,25 @@
import api, { getLinks } from '../api';
import api, { getLinks } from "../api";
import { importFetchedStatuses } from './importer';
import { importFetchedStatuses } from "./importer";
export const BOOKMARKED_STATUSES_FETCH_REQUEST = 'BOOKMARKED_STATUSES_FETCH_REQUEST';
export const BOOKMARKED_STATUSES_FETCH_SUCCESS = 'BOOKMARKED_STATUSES_FETCH_SUCCESS';
export const BOOKMARKED_STATUSES_FETCH_FAIL = 'BOOKMARKED_STATUSES_FETCH_FAIL';
export const BOOKMARKED_STATUSES_FETCH_REQUEST = "BOOKMARKED_STATUSES_FETCH_REQUEST";
export const BOOKMARKED_STATUSES_FETCH_SUCCESS = "BOOKMARKED_STATUSES_FETCH_SUCCESS";
export const BOOKMARKED_STATUSES_FETCH_FAIL = "BOOKMARKED_STATUSES_FETCH_FAIL";
export const BOOKMARKED_STATUSES_EXPAND_REQUEST = 'BOOKMARKED_STATUSES_EXPAND_REQUEST';
export const BOOKMARKED_STATUSES_EXPAND_SUCCESS = 'BOOKMARKED_STATUSES_EXPAND_SUCCESS';
export const BOOKMARKED_STATUSES_EXPAND_FAIL = 'BOOKMARKED_STATUSES_EXPAND_FAIL';
export const BOOKMARKED_STATUSES_EXPAND_REQUEST = "BOOKMARKED_STATUSES_EXPAND_REQUEST";
export const BOOKMARKED_STATUSES_EXPAND_SUCCESS = "BOOKMARKED_STATUSES_EXPAND_SUCCESS";
export const BOOKMARKED_STATUSES_EXPAND_FAIL = "BOOKMARKED_STATUSES_EXPAND_FAIL";
export function fetchBookmarkedStatuses() {
return (dispatch, getState) => {
if (getState().getIn(['status_lists', 'bookmarks', 'isLoading'])) {
if (getState().getIn(["status_lists", "bookmarks", "isLoading"])) {
return;
}
dispatch(fetchBookmarkedStatusesRequest());
api(getState).get('/api/v1/bookmarks').then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
api(getState).get("/api/v1/bookmarks").then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedStatuses(response.data));
dispatch(fetchBookmarkedStatusesSuccess(response.data, next ? next.uri : null));
}).catch(error => {
@@ -51,16 +51,16 @@ export function fetchBookmarkedStatusesFail(error) {
export function expandBookmarkedStatuses() {
return (dispatch, getState) => {
const url = getState().getIn(['status_lists', 'bookmarks', 'next'], null);
const url = getState().getIn(["status_lists", "bookmarks", "next"], null);
if (url === null || getState().getIn(['status_lists', 'bookmarks', 'isLoading'])) {
if (url === null || getState().getIn(["status_lists", "bookmarks", "isLoading"])) {
return;
}
dispatch(expandBookmarkedStatusesRequest());
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedStatuses(response.data));
dispatch(expandBookmarkedStatusesSuccess(response.data, next ? next.uri : null));
}).catch(error => {
@@ -1,13 +1,13 @@
import { openModal } from './modal';
import { openModal } from "./modal";
export const BOOSTS_INIT_MODAL = 'BOOSTS_INIT_MODAL';
export const BOOSTS_CHANGE_PRIVACY = 'BOOSTS_CHANGE_PRIVACY';
export const BOOSTS_INIT_MODAL = "BOOSTS_INIT_MODAL";
export const BOOSTS_CHANGE_PRIVACY = "BOOSTS_CHANGE_PRIVACY";
export function initBoostModal(props) {
return (dispatch, getState) => {
const default_privacy = getState().getIn(['compose', 'default_privacy']);
const default_privacy = getState().getIn(["compose", "default_privacy"]);
const privacy = props.status.get('visibility') === 'private' ? 'private' : default_privacy;
const privacy = props.status.get("visibility") === "private" ? "private" : default_privacy;
dispatch({
type: BOOSTS_INIT_MODAL,
@@ -15,7 +15,7 @@ export function initBoostModal(props) {
});
dispatch(openModal({
modalType: 'BOOST',
modalType: "BOOST",
modalProps: props,
}));
};
@@ -1,6 +1,6 @@
export const BUNDLE_FETCH_REQUEST = 'BUNDLE_FETCH_REQUEST';
export const BUNDLE_FETCH_SUCCESS = 'BUNDLE_FETCH_SUCCESS';
export const BUNDLE_FETCH_FAIL = 'BUNDLE_FETCH_FAIL';
export const BUNDLE_FETCH_REQUEST = "BUNDLE_FETCH_REQUEST";
export const BUNDLE_FETCH_SUCCESS = "BUNDLE_FETCH_SUCCESS";
export const BUNDLE_FETCH_FAIL = "BUNDLE_FETCH_FAIL";
export function fetchBundleRequest(skipLoading) {
return {
@@ -1,9 +1,9 @@
import { saveSettings } from './settings';
import { saveSettings } from "./settings";
export const COLUMN_ADD = 'COLUMN_ADD';
export const COLUMN_REMOVE = 'COLUMN_REMOVE';
export const COLUMN_MOVE = 'COLUMN_MOVE';
export const COLUMN_PARAMS_CHANGE = 'COLUMN_PARAMS_CHANGE';
export const COLUMN_ADD = "COLUMN_ADD";
export const COLUMN_REMOVE = "COLUMN_REMOVE";
export const COLUMN_MOVE = "COLUMN_MOVE";
export const COLUMN_PARAMS_CHANGE = "COLUMN_PARAMS_CHANGE";
export function addColumn(id, params) {
return dispatch => {
+134 -132
View File
@@ -1,99 +1,99 @@
import { defineMessages } from 'react-intl';
import { defineMessages } from "react-intl";
import axios from 'axios';
import { throttle } from 'lodash';
import axios from "axios";
import { throttle } from "lodash";
import api from 'flavours/glitch/api';
import { search as emojiSearch } from 'flavours/glitch/features/emoji/emoji_mart_search_light';
import { maxMediaAttachments } from 'flavours/glitch/initial_state';
import { tagHistory } from 'flavours/glitch/settings';
import { recoverHashtags } from 'flavours/glitch/utils/hashtag';
import resizeImage from 'flavours/glitch/utils/resize_image';
import api from "flavours/glitch/api";
import { search as emojiSearch } from "flavours/glitch/features/emoji/emoji_mart_search_light";
import { maxMediaAttachments } from "flavours/glitch/initial_state";
import { tagHistory } from "flavours/glitch/settings";
import { recoverHashtags } from "flavours/glitch/utils/hashtag";
import resizeImage from "flavours/glitch/utils/resize_image";
import { showAlert, showAlertForError } from './alerts';
import { useEmoji } from './emojis';
import { importFetchedAccounts, importFetchedStatus } from './importer';
import { openModal } from './modal';
import { updateTimeline } from './timelines';
import { showAlert, showAlertForError } from "./alerts";
import { useEmoji } from "./emojis";
import { importFetchedAccounts, importFetchedStatus } from "./importer";
import { openModal } from "./modal";
import { updateTimeline } from "./timelines";
/** @type {AbortController | undefined} */
let fetchComposeSuggestionsAccountsController;
/** @type {AbortController | undefined} */
let fetchComposeSuggestionsTagsController;
export const COMPOSE_CHANGE = 'COMPOSE_CHANGE';
export const COMPOSE_CYCLE_ELEFRIEND = 'COMPOSE_CYCLE_ELEFRIEND';
export const COMPOSE_SUBMIT_REQUEST = 'COMPOSE_SUBMIT_REQUEST';
export const COMPOSE_SUBMIT_SUCCESS = 'COMPOSE_SUBMIT_SUCCESS';
export const COMPOSE_SUBMIT_FAIL = 'COMPOSE_SUBMIT_FAIL';
export const COMPOSE_REPLY = 'COMPOSE_REPLY';
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_CHANGE = "COMPOSE_CHANGE";
export const COMPOSE_CYCLE_ELEFRIEND = "COMPOSE_CYCLE_ELEFRIEND";
export const COMPOSE_SUBMIT_REQUEST = "COMPOSE_SUBMIT_REQUEST";
export const COMPOSE_SUBMIT_SUCCESS = "COMPOSE_SUBMIT_SUCCESS";
export const COMPOSE_SUBMIT_FAIL = "COMPOSE_SUBMIT_FAIL";
export const COMPOSE_REPLY = "COMPOSE_REPLY";
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_PROCESSING = 'COMPOSE_UPLOAD_PROCESSING';
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';
export const THUMBNAIL_UPLOAD_FAIL = 'THUMBNAIL_UPLOAD_FAIL';
export const THUMBNAIL_UPLOAD_PROGRESS = 'THUMBNAIL_UPLOAD_PROGRESS';
export const THUMBNAIL_UPLOAD_REQUEST = "THUMBNAIL_UPLOAD_REQUEST";
export const THUMBNAIL_UPLOAD_SUCCESS = "THUMBNAIL_UPLOAD_SUCCESS";
export const THUMBNAIL_UPLOAD_FAIL = "THUMBNAIL_UPLOAD_FAIL";
export const THUMBNAIL_UPLOAD_PROGRESS = "THUMBNAIL_UPLOAD_PROGRESS";
export const COMPOSE_SUGGESTIONS_CLEAR = 'COMPOSE_SUGGESTIONS_CLEAR';
export const COMPOSE_SUGGESTIONS_READY = 'COMPOSE_SUGGESTIONS_READY';
export const COMPOSE_SUGGESTION_SELECT = 'COMPOSE_SUGGESTION_SELECT';
export const COMPOSE_SUGGESTION_IGNORE = 'COMPOSE_SUGGESTION_IGNORE';
export const COMPOSE_SUGGESTION_TAGS_UPDATE = 'COMPOSE_SUGGESTION_TAGS_UPDATE';
export const COMPOSE_SUGGESTIONS_CLEAR = "COMPOSE_SUGGESTIONS_CLEAR";
export const COMPOSE_SUGGESTIONS_READY = "COMPOSE_SUGGESTIONS_READY";
export const COMPOSE_SUGGESTION_SELECT = "COMPOSE_SUGGESTION_SELECT";
export const COMPOSE_SUGGESTION_IGNORE = "COMPOSE_SUGGESTION_IGNORE";
export const COMPOSE_SUGGESTION_TAGS_UPDATE = "COMPOSE_SUGGESTION_TAGS_UPDATE";
export const COMPOSE_TAG_HISTORY_UPDATE = 'COMPOSE_TAG_HISTORY_UPDATE';
export const COMPOSE_TAG_HISTORY_UPDATE = "COMPOSE_TAG_HISTORY_UPDATE";
export const COMPOSE_MOUNT = 'COMPOSE_MOUNT';
export const COMPOSE_UNMOUNT = 'COMPOSE_UNMOUNT';
export const COMPOSE_MOUNT = "COMPOSE_MOUNT";
export const COMPOSE_UNMOUNT = "COMPOSE_UNMOUNT";
export const COMPOSE_ADVANCED_OPTIONS_CHANGE = 'COMPOSE_ADVANCED_OPTIONS_CHANGE';
export const COMPOSE_SENSITIVITY_CHANGE = 'COMPOSE_SENSITIVITY_CHANGE';
export const COMPOSE_SPOILERNESS_CHANGE = 'COMPOSE_SPOILERNESS_CHANGE';
export const COMPOSE_SPOILER_TEXT_CHANGE = 'COMPOSE_SPOILER_TEXT_CHANGE';
export const COMPOSE_VISIBILITY_CHANGE = 'COMPOSE_VISIBILITY_CHANGE';
export const COMPOSE_LISTABILITY_CHANGE = 'COMPOSE_LISTABILITY_CHANGE';
export const COMPOSE_CONTENT_TYPE_CHANGE = 'COMPOSE_CONTENT_TYPE_CHANGE';
export const COMPOSE_LANGUAGE_CHANGE = 'COMPOSE_LANGUAGE_CHANGE';
export const COMPOSE_ADVANCED_OPTIONS_CHANGE = "COMPOSE_ADVANCED_OPTIONS_CHANGE";
export const COMPOSE_SENSITIVITY_CHANGE = "COMPOSE_SENSITIVITY_CHANGE";
export const COMPOSE_SPOILERNESS_CHANGE = "COMPOSE_SPOILERNESS_CHANGE";
export const COMPOSE_SPOILER_TEXT_CHANGE = "COMPOSE_SPOILER_TEXT_CHANGE";
export const COMPOSE_VISIBILITY_CHANGE = "COMPOSE_VISIBILITY_CHANGE";
export const COMPOSE_LISTABILITY_CHANGE = "COMPOSE_LISTABILITY_CHANGE";
export const COMPOSE_CONTENT_TYPE_CHANGE = "COMPOSE_CONTENT_TYPE_CHANGE";
export const COMPOSE_LANGUAGE_CHANGE = "COMPOSE_LANGUAGE_CHANGE";
export const COMPOSE_EMOJI_INSERT = 'COMPOSE_EMOJI_INSERT';
export const COMPOSE_EMOJI_INSERT = "COMPOSE_EMOJI_INSERT";
export const COMPOSE_UPLOAD_CHANGE_REQUEST = 'COMPOSE_UPLOAD_UPDATE_REQUEST';
export const COMPOSE_UPLOAD_CHANGE_SUCCESS = 'COMPOSE_UPLOAD_UPDATE_SUCCESS';
export const COMPOSE_UPLOAD_CHANGE_FAIL = 'COMPOSE_UPLOAD_UPDATE_FAIL';
export const COMPOSE_UPLOAD_CHANGE_REQUEST = "COMPOSE_UPLOAD_UPDATE_REQUEST";
export const COMPOSE_UPLOAD_CHANGE_SUCCESS = "COMPOSE_UPLOAD_UPDATE_SUCCESS";
export const COMPOSE_UPLOAD_CHANGE_FAIL = "COMPOSE_UPLOAD_UPDATE_FAIL";
export const COMPOSE_DOODLE_SET = 'COMPOSE_DOODLE_SET';
export const COMPOSE_DOODLE_SET = "COMPOSE_DOODLE_SET";
export const COMPOSE_POLL_ADD = 'COMPOSE_POLL_ADD';
export const COMPOSE_POLL_REMOVE = 'COMPOSE_POLL_REMOVE';
export const COMPOSE_POLL_OPTION_ADD = 'COMPOSE_POLL_OPTION_ADD';
export const COMPOSE_POLL_OPTION_CHANGE = 'COMPOSE_POLL_OPTION_CHANGE';
export const COMPOSE_POLL_OPTION_REMOVE = 'COMPOSE_POLL_OPTION_REMOVE';
export const COMPOSE_POLL_SETTINGS_CHANGE = 'COMPOSE_POLL_SETTINGS_CHANGE';
export const COMPOSE_POLL_ADD = "COMPOSE_POLL_ADD";
export const COMPOSE_POLL_REMOVE = "COMPOSE_POLL_REMOVE";
export const COMPOSE_POLL_OPTION_ADD = "COMPOSE_POLL_OPTION_ADD";
export const COMPOSE_POLL_OPTION_CHANGE = "COMPOSE_POLL_OPTION_CHANGE";
export const COMPOSE_POLL_OPTION_REMOVE = "COMPOSE_POLL_OPTION_REMOVE";
export const COMPOSE_POLL_SETTINGS_CHANGE = "COMPOSE_POLL_SETTINGS_CHANGE";
export const INIT_MEDIA_EDIT_MODAL = 'INIT_MEDIA_EDIT_MODAL';
export const INIT_MEDIA_EDIT_MODAL = "INIT_MEDIA_EDIT_MODAL";
export const COMPOSE_CHANGE_MEDIA_DESCRIPTION = 'COMPOSE_CHANGE_MEDIA_DESCRIPTION';
export const COMPOSE_CHANGE_MEDIA_FOCUS = 'COMPOSE_CHANGE_MEDIA_FOCUS';
export const COMPOSE_CHANGE_MEDIA_DESCRIPTION = "COMPOSE_CHANGE_MEDIA_DESCRIPTION";
export const COMPOSE_CHANGE_MEDIA_FOCUS = "COMPOSE_CHANGE_MEDIA_FOCUS";
export const COMPOSE_SET_STATUS = 'COMPOSE_SET_STATUS';
export const COMPOSE_SET_STATUS = "COMPOSE_SET_STATUS";
const messages = defineMessages({
uploadErrorLimit: { id: 'upload_error.limit', defaultMessage: 'File upload limit exceeded.' },
uploadErrorPoll: { id: 'upload_error.poll', defaultMessage: 'File upload not allowed with polls.' },
uploadErrorLimit: { id: "upload_error.limit", defaultMessage: "File upload limit exceeded." },
uploadErrorPoll: { id: "upload_error.poll", defaultMessage: "File upload not allowed with polls." },
});
export const ensureComposeIsVisible = (getState, routerHistory) => {
if (!getState().getIn(['compose', 'mounted'])) {
routerHistory.push('/publish');
if (!getState().getIn(["compose", "mounted"])) {
routerHistory.push("/publish");
}
};
@@ -122,7 +122,7 @@ export function cycleElefriendCompose() {
export function replyCompose(status, routerHistory) {
return (dispatch, getState) => {
const prependCWRe = getState().getIn(['local_settings', 'prepend_cw_re']);
const prependCWRe = getState().getIn(["local_settings", "prepend_cw_re"]);
dispatch({
type: COMPOSE_REPLY,
status: status,
@@ -169,11 +169,11 @@ export function directCompose(account, routerHistory) {
export function submitCompose(routerHistory) {
return function (dispatch, getState) {
let status = getState().getIn(['compose', 'text'], '');
const media = getState().getIn(['compose', 'media_attachments']);
const statusId = getState().getIn(['compose', 'id'], null);
const spoilers = getState().getIn(['compose', 'spoiler']) || getState().getIn(['local_settings', 'always_show_spoilers_field']);
let spoilerText = spoilers ? getState().getIn(['compose', 'spoiler_text'], '') : '';
let status = getState().getIn(["compose", "text"], "");
const media = getState().getIn(["compose", "media_attachments"]);
const statusId = getState().getIn(["compose", "id"], null);
const spoilers = getState().getIn(["compose", "spoiler"]) || getState().getIn(["local_settings", "always_show_spoilers_field"]);
let spoilerText = spoilers ? getState().getIn(["compose", "spoiler_text"], "") : "";
if ((!status || !status.length) && media.size === 0) {
return;
@@ -189,42 +189,42 @@ export function submitCompose(routerHistory) {
media_attributes = media.map(item => {
let focus;
if (item.getIn(['meta', 'focus'])) {
focus = `${item.getIn(['meta', 'focus', 'x']).toFixed(2)},${item.getIn(['meta', 'focus', 'y']).toFixed(2)}`;
if (item.getIn(["meta", "focus"])) {
focus = `${item.getIn(["meta", "focus", "x"]).toFixed(2)},${item.getIn(["meta", "focus", "y"]).toFixed(2)}`;
}
return {
id: item.get('id'),
description: item.get('description'),
id: item.get("id"),
description: item.get("description"),
focus,
};
});
}
api(getState).request({
url: statusId === null ? '/api/v1/statuses' : `/api/v1/statuses/${statusId}`,
method: statusId === null ? 'post' : 'put',
url: statusId === null ? "/api/v1/statuses" : `/api/v1/statuses/${statusId}`,
method: statusId === null ? "post" : "put",
data: {
status,
content_type: getState().getIn(['compose', 'content_type']),
in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null),
media_ids: media.map(item => item.get('id')),
content_type: getState().getIn(["compose", "content_type"]),
in_reply_to_id: getState().getIn(["compose", "in_reply_to"], null),
media_ids: media.map(item => item.get("id")),
media_attributes,
sensitive: getState().getIn(['compose', 'sensitive']) || (spoilerText.length > 0 && media.size !== 0),
sensitive: getState().getIn(["compose", "sensitive"]) || (spoilerText.length > 0 && media.size !== 0),
spoiler_text: spoilerText,
visibility: getState().getIn(['compose', 'privacy']),
poll: getState().getIn(['compose', 'poll'], null),
language: getState().getIn(['compose', 'language']),
local_only: getState().getIn(['compose', 'advanced_options', 'do_not_federate']),
visibility: getState().getIn(["compose", "privacy"]),
poll: getState().getIn(["compose", "poll"], null),
language: getState().getIn(["compose", "language"]),
local_only: getState().getIn(["compose", "advanced_options", "do_not_federate"]),
},
headers: {
'Idempotency-Key': getState().getIn(['compose', 'idempotencyKey']),
"Idempotency-Key": getState().getIn(["compose", "idempotencyKey"]),
},
}).then(function (response) {
if (routerHistory
&& (routerHistory.location.pathname === '/publish' || routerHistory.location.pathname === '/statuses/new')
&& (routerHistory.location.pathname === "/publish" || routerHistory.location.pathname === "/statuses/new")
&& window.history.state
&& !getState().getIn(['compose', 'advanced_options', 'threaded_mode'])) {
&& !getState().getIn(["compose", "advanced_options", "threaded_mode"])) {
routerHistory.goBack();
}
@@ -239,9 +239,9 @@ export function submitCompose(routerHistory) {
// To make the app more responsive, immediately get the status into the columns
const insertIfOnline = (timelineId) => {
const timeline = getState().getIn(['timelines', timelineId]);
const timeline = getState().getIn(["timelines", timelineId]);
if (timeline && timeline.get('items').size > 0 && timeline.getIn(['items', 0]) !== null && timeline.get('online')) {
if (timeline && timeline.get("items").size > 0 && timeline.getIn(["items", 0]) !== null && timeline.get("online")) {
dispatch(updateTimeline(timelineId, { ...response.data }));
}
};
@@ -251,16 +251,16 @@ export function submitCompose(routerHistory) {
}
if (statusId === null) {
insertIfOnline('home');
insertIfOnline("home");
}
if (statusId === null && response.data.in_reply_to_id === null && response.data.visibility === 'public') {
insertIfOnline('community');
if (statusId === null && response.data.in_reply_to_id === null && response.data.visibility === "public") {
insertIfOnline("community");
if (!response.data.local_only) {
insertIfOnline('public');
insertIfOnline("public");
}
} else if (statusId === null && response.data.visibility === 'direct') {
insertIfOnline('direct');
} else if (statusId === null && response.data.visibility === "direct") {
insertIfOnline("direct");
}
}).catch(function (error) {
dispatch(submitComposeFail(error));
@@ -298,8 +298,8 @@ export function doodleSet(options) {
export function uploadCompose(files) {
return function (dispatch, getState) {
const uploadLimit = maxMediaAttachments;
const media = getState().getIn(['compose', 'media_attachments']);
const pending = getState().getIn(['compose', 'pending_media_attachments']);
const media = getState().getIn(["compose", "media_attachments"]);
const pending = getState().getIn(["compose", "pending_media_attachments"]);
const progress = new Array(files.length).fill(0);
let total = Array.from(files).reduce((a, v) => a + v.size, 0);
@@ -308,7 +308,7 @@ export function uploadCompose(files) {
return;
}
if (getState().getIn(['compose', 'poll'])) {
if (getState().getIn(["compose", "poll"])) {
dispatch(showAlert(undefined, messages.uploadErrorPoll));
return;
}
@@ -316,15 +316,17 @@ export function uploadCompose(files) {
dispatch(uploadComposeRequest());
for (const [i, f] of Array.from(files).entries()) {
if (media.size + i >= uploadLimit) break;
if (media.size + i >= uploadLimit) {
break;
}
resizeImage(f).then(file => {
const data = new FormData();
data.append('file', file);
data.append("file", file);
// Account for disparity in size of original image and resized data
total += file.size - f.size;
return api(getState).post('/api/v2/media', data, {
return api(getState).post("/api/v2/media", data, {
onUploadProgress: function({ loaded }){
progress[i] = loaded;
dispatch(uploadComposeProgress(progress.reduce((a, v) => a + v, 0), total));
@@ -370,7 +372,7 @@ export const uploadThumbnail = (id, file) => (dispatch, getState) => {
const total = file.size;
const data = new FormData();
data.append('thumbnail', file);
data.append("thumbnail", file);
api(getState).put(`/api/v1/media/${id}`, data, {
onUploadProgress: ({ loaded }) => {
@@ -415,7 +417,7 @@ export function initMediaEditModal(id) {
});
dispatch(openModal({
modalType: 'FOCAL_POINT',
modalType: "FOCAL_POINT",
modalProps: { id },
}));
};
@@ -440,16 +442,16 @@ export function changeUploadCompose(id, params) {
return (dispatch, getState) => {
dispatch(changeUploadComposeRequest());
let media = getState().getIn(['compose', 'media_attachments']).find((item) => item.get('id') === id);
let media = getState().getIn(["compose", "media_attachments"]).find((item) => item.get("id") === id);
// Editing already-attached media is deferred to editing the post itself.
// For simplicity's sake, fake an API reply.
if (media && !media.get('unattached')) {
if (media && !media.get("unattached")) {
const { focus, ...other } = params;
const data = { ...media.toJS(), ...other };
if (focus) {
const [x, y] = focus.split(',');
const [x, y] = focus.split(",");
data.meta = { focus: { x: parseFloat(x), y: parseFloat(y) } };
}
@@ -543,7 +545,7 @@ const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) =>
fetchComposeSuggestionsAccountsController = new AbortController();
api(getState).get('/api/v1/accounts/search', {
api(getState).get("/api/v1/accounts/search", {
signal: fetchComposeSuggestionsAccountsController.signal,
params: {
@@ -564,7 +566,7 @@ const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) =>
}, 200, { leading: true, trailing: true });
const fetchComposeSuggestionsEmojis = (dispatch, getState, token) => {
const results = emojiSearch(token.replace(':', ''), { maxResults: 5 });
const results = emojiSearch(token.replace(":", ""), { maxResults: 5 });
dispatch(readyComposeSuggestionsEmojis(token, results));
};
@@ -577,11 +579,11 @@ const fetchComposeSuggestionsTags = throttle((dispatch, getState, token) => {
fetchComposeSuggestionsTagsController = new AbortController();
api(getState).get('/api/v2/search', {
api(getState).get("/api/v2/search", {
signal: fetchComposeSuggestionsTagsController.signal,
params: {
type: 'hashtags',
type: "hashtags",
q: token.slice(1),
resolve: false,
limit: 4,
@@ -600,15 +602,15 @@ const fetchComposeSuggestionsTags = throttle((dispatch, getState, token) => {
export function fetchComposeSuggestions(token) {
return (dispatch, getState) => {
switch (token[0]) {
case ':':
fetchComposeSuggestionsEmojis(dispatch, getState, token);
break;
case '#':
fetchComposeSuggestionsTags(dispatch, getState, token);
break;
default:
fetchComposeSuggestionsAccounts(dispatch, getState, token);
break;
case ":":
fetchComposeSuggestionsEmojis(dispatch, getState, token);
break;
case "#":
fetchComposeSuggestionsTags(dispatch, getState, token);
break;
default:
fetchComposeSuggestionsAccounts(dispatch, getState, token);
break;
}
};
}
@@ -638,18 +640,18 @@ export const readyComposeSuggestionsTags = (token, tags) => ({
export function selectComposeSuggestion(position, token, suggestion, path) {
return (dispatch, getState) => {
let completion;
if (suggestion.type === 'emoji') {
if (suggestion.type === "emoji") {
dispatch(useEmoji(suggestion));
completion = suggestion.native || suggestion.colons;
} else if (suggestion.type === 'hashtag') {
} else if (suggestion.type === "hashtag") {
completion = `#${suggestion.name}`;
} else if (suggestion.type === 'account') {
completion = '@' + getState().getIn(['accounts', suggestion.id, 'acct']);
} else if (suggestion.type === "account") {
completion = "@" + getState().getIn(["accounts", suggestion.id, "acct"]);
}
// We don't want to replace hashtags that vary only in case due to accessibility, but we need to fire off an event so that
// the suggestions are dismissed and the cursor moves forward.
if (suggestion.type !== 'hashtag' || token.slice(1).localeCompare(suggestion.name, undefined, { sensitivity: 'accent' }) !== 0) {
if (suggestion.type !== "hashtag" || token.slice(1).localeCompare(suggestion.name, undefined, { sensitivity: "accent" }) !== 0) {
dispatch({
type: COMPOSE_SUGGESTION_SELECT,
position,
@@ -685,7 +687,7 @@ export function updateTagHistory(tags) {
export function hydrateCompose() {
return (dispatch, getState) => {
const me = getState().getIn(['meta', 'me']);
const me = getState().getIn(["meta", "me"]);
const history = tagHistory.get(me);
if (history !== null) {
@@ -697,8 +699,8 @@ export function hydrateCompose() {
function insertIntoTagHistory(recognizedTags, text) {
return (dispatch, getState) => {
const state = getState();
const oldHistory = state.getIn(['compose', 'tagHistory']);
const me = state.getIn(['meta', 'me']);
const oldHistory = state.getIn(["compose", "tagHistory"]);
const me = state.getIn(["meta", "me"]);
const names = recoverHashtags(recognizedTags, text);
const intersectedOldHistory = oldHistory.filter(name => names.findIndex(newName => newName.toLowerCase() === name.toLowerCase()) === -1);
@@ -1,24 +1,24 @@
import api, { getLinks } from '../api';
import api, { getLinks } from "../api";
import {
importFetchedAccounts,
importFetchedStatuses,
importFetchedStatus,
} from './importer';
} from "./importer";
export const CONVERSATIONS_MOUNT = 'CONVERSATIONS_MOUNT';
export const CONVERSATIONS_UNMOUNT = 'CONVERSATIONS_UNMOUNT';
export const CONVERSATIONS_MOUNT = "CONVERSATIONS_MOUNT";
export const CONVERSATIONS_UNMOUNT = "CONVERSATIONS_UNMOUNT";
export const CONVERSATIONS_FETCH_REQUEST = 'CONVERSATIONS_FETCH_REQUEST';
export const CONVERSATIONS_FETCH_SUCCESS = 'CONVERSATIONS_FETCH_SUCCESS';
export const CONVERSATIONS_FETCH_FAIL = 'CONVERSATIONS_FETCH_FAIL';
export const CONVERSATIONS_UPDATE = 'CONVERSATIONS_UPDATE';
export const CONVERSATIONS_FETCH_REQUEST = "CONVERSATIONS_FETCH_REQUEST";
export const CONVERSATIONS_FETCH_SUCCESS = "CONVERSATIONS_FETCH_SUCCESS";
export const CONVERSATIONS_FETCH_FAIL = "CONVERSATIONS_FETCH_FAIL";
export const CONVERSATIONS_UPDATE = "CONVERSATIONS_UPDATE";
export const CONVERSATIONS_READ = 'CONVERSATIONS_READ';
export const CONVERSATIONS_READ = "CONVERSATIONS_READ";
export const CONVERSATIONS_DELETE_REQUEST = 'CONVERSATIONS_DELETE_REQUEST';
export const CONVERSATIONS_DELETE_SUCCESS = 'CONVERSATIONS_DELETE_SUCCESS';
export const CONVERSATIONS_DELETE_FAIL = 'CONVERSATIONS_DELETE_FAIL';
export const CONVERSATIONS_DELETE_REQUEST = "CONVERSATIONS_DELETE_REQUEST";
export const CONVERSATIONS_DELETE_SUCCESS = "CONVERSATIONS_DELETE_SUCCESS";
export const CONVERSATIONS_DELETE_FAIL = "CONVERSATIONS_DELETE_FAIL";
export const mountConversations = () => ({
type: CONVERSATIONS_MOUNT,
@@ -43,14 +43,14 @@ export const expandConversations = ({ maxId } = {}) => (dispatch, getState) => {
const params = { max_id: maxId };
if (!maxId) {
params.since_id = getState().getIn(['conversations', 'items', 0, 'last_status']);
params.since_id = getState().getIn(["conversations", "items", 0, "last_status"]);
}
const isLoadingRecent = !!params.since_id;
api(getState).get('/api/v1/conversations', { params })
api(getState).get("/api/v1/conversations", { params })
.then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedAccounts(response.data.reduce((aggr, item) => aggr.concat(item.accounts), [])));
dispatch(importFetchedStatuses(response.data.map(item => item.last_status).filter(x => !!x)));
@@ -1,14 +1,14 @@
import api from '../api';
import api from "../api";
export const CUSTOM_EMOJIS_FETCH_REQUEST = 'CUSTOM_EMOJIS_FETCH_REQUEST';
export const CUSTOM_EMOJIS_FETCH_SUCCESS = 'CUSTOM_EMOJIS_FETCH_SUCCESS';
export const CUSTOM_EMOJIS_FETCH_FAIL = 'CUSTOM_EMOJIS_FETCH_FAIL';
export const CUSTOM_EMOJIS_FETCH_REQUEST = "CUSTOM_EMOJIS_FETCH_REQUEST";
export const CUSTOM_EMOJIS_FETCH_SUCCESS = "CUSTOM_EMOJIS_FETCH_SUCCESS";
export const CUSTOM_EMOJIS_FETCH_FAIL = "CUSTOM_EMOJIS_FETCH_FAIL";
export function fetchCustomEmojis() {
return (dispatch, getState) => {
dispatch(fetchCustomEmojisRequest());
api(getState).get('/api/v1/custom_emojis').then(response => {
api(getState).get("/api/v1/custom_emojis").then(response => {
dispatch(fetchCustomEmojisSuccess(response.data));
}).catch(error => {
dispatch(fetchCustomEmojisFail(error));
@@ -1,20 +1,20 @@
import api from '../api';
import api from "../api";
import { fetchRelationships } from './accounts';
import { importFetchedAccounts } from './importer';
import { fetchRelationships } from "./accounts";
import { importFetchedAccounts } from "./importer";
export const DIRECTORY_FETCH_REQUEST = 'DIRECTORY_FETCH_REQUEST';
export const DIRECTORY_FETCH_SUCCESS = 'DIRECTORY_FETCH_SUCCESS';
export const DIRECTORY_FETCH_FAIL = 'DIRECTORY_FETCH_FAIL';
export const DIRECTORY_FETCH_REQUEST = "DIRECTORY_FETCH_REQUEST";
export const DIRECTORY_FETCH_SUCCESS = "DIRECTORY_FETCH_SUCCESS";
export const DIRECTORY_FETCH_FAIL = "DIRECTORY_FETCH_FAIL";
export const DIRECTORY_EXPAND_REQUEST = 'DIRECTORY_EXPAND_REQUEST';
export const DIRECTORY_EXPAND_SUCCESS = 'DIRECTORY_EXPAND_SUCCESS';
export const DIRECTORY_EXPAND_FAIL = 'DIRECTORY_EXPAND_FAIL';
export const DIRECTORY_EXPAND_REQUEST = "DIRECTORY_EXPAND_REQUEST";
export const DIRECTORY_EXPAND_SUCCESS = "DIRECTORY_EXPAND_SUCCESS";
export const DIRECTORY_EXPAND_FAIL = "DIRECTORY_EXPAND_FAIL";
export const fetchDirectory = params => (dispatch, getState) => {
dispatch(fetchDirectoryRequest());
api(getState).get('/api/v1/directory', { params: { ...params, limit: 20 } }).then(({ data }) => {
api(getState).get("/api/v1/directory", { params: { ...params, limit: 20 } }).then(({ data }) => {
dispatch(importFetchedAccounts(data));
dispatch(fetchDirectorySuccess(data));
dispatch(fetchRelationships(data.map(x => x.id)));
@@ -38,9 +38,9 @@ export const fetchDirectoryFail = error => ({
export const expandDirectory = params => (dispatch, getState) => {
dispatch(expandDirectoryRequest());
const loadedItems = getState().getIn(['user_lists', 'directory', 'items']).size;
const loadedItems = getState().getIn(["user_lists", "directory", "items"]).size;
api(getState).get('/api/v1/directory', { params: { ...params, offset: loadedItems, limit: 20 } }).then(({ data }) => {
api(getState).get("/api/v1/directory", { params: { ...params, offset: loadedItems, limit: 20 } }).then(({ data }) => {
dispatch(importFetchedAccounts(data));
dispatch(expandDirectorySuccess(data));
dispatch(fetchRelationships(data.map(x => x.id)));
@@ -1,28 +1,28 @@
import api, { getLinks } from '../api';
import api, { getLinks } from "../api";
export const DOMAIN_BLOCK_REQUEST = 'DOMAIN_BLOCK_REQUEST';
export const DOMAIN_BLOCK_SUCCESS = 'DOMAIN_BLOCK_SUCCESS';
export const DOMAIN_BLOCK_FAIL = 'DOMAIN_BLOCK_FAIL';
export const DOMAIN_BLOCK_REQUEST = "DOMAIN_BLOCK_REQUEST";
export const DOMAIN_BLOCK_SUCCESS = "DOMAIN_BLOCK_SUCCESS";
export const DOMAIN_BLOCK_FAIL = "DOMAIN_BLOCK_FAIL";
export const DOMAIN_UNBLOCK_REQUEST = 'DOMAIN_UNBLOCK_REQUEST';
export const DOMAIN_UNBLOCK_SUCCESS = 'DOMAIN_UNBLOCK_SUCCESS';
export const DOMAIN_UNBLOCK_FAIL = 'DOMAIN_UNBLOCK_FAIL';
export const DOMAIN_UNBLOCK_REQUEST = "DOMAIN_UNBLOCK_REQUEST";
export const DOMAIN_UNBLOCK_SUCCESS = "DOMAIN_UNBLOCK_SUCCESS";
export const DOMAIN_UNBLOCK_FAIL = "DOMAIN_UNBLOCK_FAIL";
export const DOMAIN_BLOCKS_FETCH_REQUEST = 'DOMAIN_BLOCKS_FETCH_REQUEST';
export const DOMAIN_BLOCKS_FETCH_SUCCESS = 'DOMAIN_BLOCKS_FETCH_SUCCESS';
export const DOMAIN_BLOCKS_FETCH_FAIL = 'DOMAIN_BLOCKS_FETCH_FAIL';
export const DOMAIN_BLOCKS_FETCH_REQUEST = "DOMAIN_BLOCKS_FETCH_REQUEST";
export const DOMAIN_BLOCKS_FETCH_SUCCESS = "DOMAIN_BLOCKS_FETCH_SUCCESS";
export const DOMAIN_BLOCKS_FETCH_FAIL = "DOMAIN_BLOCKS_FETCH_FAIL";
export const DOMAIN_BLOCKS_EXPAND_REQUEST = 'DOMAIN_BLOCKS_EXPAND_REQUEST';
export const DOMAIN_BLOCKS_EXPAND_SUCCESS = 'DOMAIN_BLOCKS_EXPAND_SUCCESS';
export const DOMAIN_BLOCKS_EXPAND_FAIL = 'DOMAIN_BLOCKS_EXPAND_FAIL';
export const DOMAIN_BLOCKS_EXPAND_REQUEST = "DOMAIN_BLOCKS_EXPAND_REQUEST";
export const DOMAIN_BLOCKS_EXPAND_SUCCESS = "DOMAIN_BLOCKS_EXPAND_SUCCESS";
export const DOMAIN_BLOCKS_EXPAND_FAIL = "DOMAIN_BLOCKS_EXPAND_FAIL";
export function blockDomain(domain) {
return (dispatch, getState) => {
dispatch(blockDomainRequest(domain));
api(getState).post('/api/v1/domain_blocks', { domain }).then(() => {
const at_domain = '@' + domain;
const accounts = getState().get('accounts').filter(item => item.get('acct').endsWith(at_domain)).valueSeq().map(item => item.get('id'));
api(getState).post("/api/v1/domain_blocks", { domain }).then(() => {
const at_domain = "@" + domain;
const accounts = getState().get("accounts").filter(item => item.get("acct").endsWith(at_domain)).valueSeq().map(item => item.get("id"));
dispatch(blockDomainSuccess(domain, accounts));
}).catch(err => {
@@ -58,9 +58,9 @@ export function unblockDomain(domain) {
return (dispatch, getState) => {
dispatch(unblockDomainRequest(domain));
api(getState).delete('/api/v1/domain_blocks', { params: { domain } }).then(() => {
const at_domain = '@' + domain;
const accounts = getState().get('accounts').filter(item => item.get('acct').endsWith(at_domain)).valueSeq().map(item => item.get('id'));
api(getState).delete("/api/v1/domain_blocks", { params: { domain } }).then(() => {
const at_domain = "@" + domain;
const accounts = getState().get("accounts").filter(item => item.get("acct").endsWith(at_domain)).valueSeq().map(item => item.get("id"));
dispatch(unblockDomainSuccess(domain, accounts));
}).catch(err => {
dispatch(unblockDomainFail(domain, err));
@@ -95,8 +95,8 @@ export function fetchDomainBlocks() {
return (dispatch, getState) => {
dispatch(fetchDomainBlocksRequest());
api(getState).get('/api/v1/domain_blocks').then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
api(getState).get("/api/v1/domain_blocks").then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(fetchDomainBlocksSuccess(response.data, next ? next.uri : null));
}).catch(err => {
dispatch(fetchDomainBlocksFail(err));
@@ -127,7 +127,7 @@ export function fetchDomainBlocksFail(error) {
export function expandDomainBlocks() {
return (dispatch, getState) => {
const url = getState().getIn(['domain_lists', 'blocks', 'next']);
const url = getState().getIn(["domain_lists", "blocks", "next"]);
if (!url) {
return;
@@ -136,7 +136,7 @@ export function expandDomainBlocks() {
dispatch(expandDomainBlocksRequest());
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(expandDomainBlocksSuccess(response.data, next ? next.uri : null));
}).catch(err => {
dispatch(expandDomainBlocksFail(err));
@@ -1,11 +1,11 @@
import { createAction } from '@reduxjs/toolkit';
import { createAction } from "@reduxjs/toolkit";
export const openDropdownMenu = createAction<{
id: string;
keyboard: boolean;
scrollKey: string;
}>('dropdownMenu/open');
id: string,
keyboard: boolean,
scrollKey: string,
}>("dropdownMenu/open");
export const closeDropdownMenu = createAction<{ id: string }>(
'dropdownMenu/close',
"dropdownMenu/close",
);
@@ -1,6 +1,6 @@
import { saveSettings } from './settings';
import { saveSettings } from "./settings";
export const EMOJI_USE = 'EMOJI_USE';
export const EMOJI_USE = "EMOJI_USE";
export function useEmoji(emoji) {
return dispatch => {
@@ -1,25 +1,25 @@
import api, { getLinks } from '../api';
import api, { getLinks } from "../api";
import { importFetchedStatuses } from './importer';
import { importFetchedStatuses } from "./importer";
export const FAVOURITED_STATUSES_FETCH_REQUEST = 'FAVOURITED_STATUSES_FETCH_REQUEST';
export const FAVOURITED_STATUSES_FETCH_SUCCESS = 'FAVOURITED_STATUSES_FETCH_SUCCESS';
export const FAVOURITED_STATUSES_FETCH_FAIL = 'FAVOURITED_STATUSES_FETCH_FAIL';
export const FAVOURITED_STATUSES_FETCH_REQUEST = "FAVOURITED_STATUSES_FETCH_REQUEST";
export const FAVOURITED_STATUSES_FETCH_SUCCESS = "FAVOURITED_STATUSES_FETCH_SUCCESS";
export const FAVOURITED_STATUSES_FETCH_FAIL = "FAVOURITED_STATUSES_FETCH_FAIL";
export const FAVOURITED_STATUSES_EXPAND_REQUEST = 'FAVOURITED_STATUSES_EXPAND_REQUEST';
export const FAVOURITED_STATUSES_EXPAND_SUCCESS = 'FAVOURITED_STATUSES_EXPAND_SUCCESS';
export const FAVOURITED_STATUSES_EXPAND_FAIL = 'FAVOURITED_STATUSES_EXPAND_FAIL';
export const FAVOURITED_STATUSES_EXPAND_REQUEST = "FAVOURITED_STATUSES_EXPAND_REQUEST";
export const FAVOURITED_STATUSES_EXPAND_SUCCESS = "FAVOURITED_STATUSES_EXPAND_SUCCESS";
export const FAVOURITED_STATUSES_EXPAND_FAIL = "FAVOURITED_STATUSES_EXPAND_FAIL";
export function fetchFavouritedStatuses() {
return (dispatch, getState) => {
if (getState().getIn(['status_lists', 'favourites', 'isLoading'])) {
if (getState().getIn(["status_lists", "favourites", "isLoading"])) {
return;
}
dispatch(fetchFavouritedStatusesRequest());
api(getState).get('/api/v1/favourites').then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
api(getState).get("/api/v1/favourites").then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedStatuses(response.data));
dispatch(fetchFavouritedStatusesSuccess(response.data, next ? next.uri : null));
}).catch(error => {
@@ -54,16 +54,16 @@ export function fetchFavouritedStatusesFail(error) {
export function expandFavouritedStatuses() {
return (dispatch, getState) => {
const url = getState().getIn(['status_lists', 'favourites', 'next'], null);
const url = getState().getIn(["status_lists", "favourites", "next"], null);
if (url === null || getState().getIn(['status_lists', 'favourites', 'isLoading'])) {
if (url === null || getState().getIn(["status_lists", "favourites", "isLoading"])) {
return;
}
dispatch(expandFavouritedStatusesRequest());
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedStatuses(response.data));
dispatch(expandFavouritedStatusesSuccess(response.data, next ? next.uri : null));
}).catch(error => {
@@ -1,11 +1,11 @@
import api from '../api';
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 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'])) {
if (getState().getIn(["user_lists", "featured_tags", id, "items"])) {
return;
}
@@ -1,24 +1,24 @@
import api from '../api';
import api from "../api";
import { openModal } from './modal';
import { openModal } from "./modal";
export const FILTERS_FETCH_REQUEST = 'FILTERS_FETCH_REQUEST';
export const FILTERS_FETCH_SUCCESS = 'FILTERS_FETCH_SUCCESS';
export const FILTERS_FETCH_FAIL = 'FILTERS_FETCH_FAIL';
export const FILTERS_FETCH_REQUEST = "FILTERS_FETCH_REQUEST";
export const FILTERS_FETCH_SUCCESS = "FILTERS_FETCH_SUCCESS";
export const FILTERS_FETCH_FAIL = "FILTERS_FETCH_FAIL";
export const FILTERS_STATUS_CREATE_REQUEST = 'FILTERS_STATUS_CREATE_REQUEST';
export const FILTERS_STATUS_CREATE_SUCCESS = 'FILTERS_STATUS_CREATE_SUCCESS';
export const FILTERS_STATUS_CREATE_FAIL = 'FILTERS_STATUS_CREATE_FAIL';
export const FILTERS_STATUS_CREATE_REQUEST = "FILTERS_STATUS_CREATE_REQUEST";
export const FILTERS_STATUS_CREATE_SUCCESS = "FILTERS_STATUS_CREATE_SUCCESS";
export const FILTERS_STATUS_CREATE_FAIL = "FILTERS_STATUS_CREATE_FAIL";
export const FILTERS_CREATE_REQUEST = 'FILTERS_CREATE_REQUEST';
export const FILTERS_CREATE_SUCCESS = 'FILTERS_CREATE_SUCCESS';
export const FILTERS_CREATE_FAIL = 'FILTERS_CREATE_FAIL';
export const FILTERS_CREATE_REQUEST = "FILTERS_CREATE_REQUEST";
export const FILTERS_CREATE_SUCCESS = "FILTERS_CREATE_SUCCESS";
export const FILTERS_CREATE_FAIL = "FILTERS_CREATE_FAIL";
export const initAddFilter = (status, { contextType }) => dispatch =>
dispatch(openModal({
modalType: 'FILTER',
modalType: "FILTER",
modalProps: {
statusId: status?.get('id'),
statusId: status?.get("id"),
contextType: contextType,
},
}));
@@ -30,7 +30,7 @@ export const fetchFilters = () => (dispatch, getState) => {
});
api(getState)
.get('/api/v2/filters')
.get("/api/v2/filters")
.then(({ data }) => dispatch({
type: FILTERS_FETCH_SUCCESS,
filters: data,
@@ -49,10 +49,14 @@ export const createFilterStatus = (params, onSuccess, onFail) => (dispatch, getS
api(getState).post(`/api/v2/filters/${params.filter_id}/statuses`, params).then(response => {
dispatch(createFilterStatusSuccess(response.data));
if (onSuccess) onSuccess();
if (onSuccess) {
onSuccess();
}
}).catch(error => {
dispatch(createFilterStatusFail(error));
if (onFail) onFail();
if (onFail) {
onFail();
}
});
};
@@ -73,12 +77,16 @@ export const createFilterStatusFail = error => ({
export const createFilter = (params, onSuccess, onFail) => (dispatch, getState) => {
dispatch(createFilterRequest());
api(getState).post('/api/v2/filters', params).then(response => {
api(getState).post("/api/v2/filters", params).then(response => {
dispatch(createFilterSuccess(response.data));
if (onSuccess) onSuccess(response.data);
if (onSuccess) {
onSuccess(response.data);
}
}).catch(error => {
dispatch(createFilterFail(error));
if (onFail) onFail();
if (onFail) {
onFail();
}
});
};
@@ -1,5 +1,5 @@
export const HEIGHT_CACHE_SET = 'HEIGHT_CACHE_SET';
export const HEIGHT_CACHE_CLEAR = 'HEIGHT_CACHE_CLEAR';
export const HEIGHT_CACHE_SET = "HEIGHT_CACHE_SET";
export const HEIGHT_CACHE_CLEAR = "HEIGHT_CACHE_CLEAR";
export function setHeight (key, id, height) {
return {
@@ -1,13 +1,13 @@
import api from '../api';
import api from "../api";
import { importFetchedAccounts } from './importer';
import { importFetchedAccounts } from "./importer";
export const HISTORY_FETCH_REQUEST = 'HISTORY_FETCH_REQUEST';
export const HISTORY_FETCH_SUCCESS = 'HISTORY_FETCH_SUCCESS';
export const HISTORY_FETCH_FAIL = 'HISTORY_FETCH_FAIL';
export const HISTORY_FETCH_REQUEST = "HISTORY_FETCH_REQUEST";
export const HISTORY_FETCH_SUCCESS = "HISTORY_FETCH_SUCCESS";
export const HISTORY_FETCH_FAIL = "HISTORY_FETCH_FAIL";
export const fetchHistory = statusId => (dispatch, getState) => {
const loading = getState().getIn(['history', statusId, 'loading']);
const loading = getState().getIn(["history", statusId, "loading"]);
if (loading) {
return;
@@ -1,8 +1,8 @@
import api from '../api';
import api from "../api";
export const IDENTITY_PROOFS_ACCOUNT_FETCH_REQUEST = 'IDENTITY_PROOFS_ACCOUNT_FETCH_REQUEST';
export const IDENTITY_PROOFS_ACCOUNT_FETCH_SUCCESS = 'IDENTITY_PROOFS_ACCOUNT_FETCH_SUCCESS';
export const IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL = 'IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL';
export const IDENTITY_PROOFS_ACCOUNT_FETCH_REQUEST = "IDENTITY_PROOFS_ACCOUNT_FETCH_REQUEST";
export const IDENTITY_PROOFS_ACCOUNT_FETCH_SUCCESS = "IDENTITY_PROOFS_ACCOUNT_FETCH_SUCCESS";
export const IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL = "IDENTITY_PROOFS_ACCOUNT_FETCH_FAIL";
export const fetchAccountIdentityProofs = accountId => (dispatch, getState) => {
dispatch(fetchAccountIdentityProofsRequest(accountId));
@@ -1,11 +1,11 @@
import { normalizeAccount, normalizeStatus, normalizePoll } from './normalizer';
import { normalizeAccount, normalizeStatus, normalizePoll } from "./normalizer";
export const ACCOUNT_IMPORT = 'ACCOUNT_IMPORT';
export const ACCOUNTS_IMPORT = 'ACCOUNTS_IMPORT';
export const STATUS_IMPORT = 'STATUS_IMPORT';
export const STATUSES_IMPORT = 'STATUSES_IMPORT';
export const POLLS_IMPORT = 'POLLS_IMPORT';
export const FILTERS_IMPORT = 'FILTERS_IMPORT';
export const ACCOUNT_IMPORT = "ACCOUNT_IMPORT";
export const ACCOUNTS_IMPORT = "ACCOUNTS_IMPORT";
export const STATUS_IMPORT = "STATUS_IMPORT";
export const STATUSES_IMPORT = "STATUSES_IMPORT";
export const POLLS_IMPORT = "POLLS_IMPORT";
export const FILTERS_IMPORT = "FILTERS_IMPORT";
function pushUnique(array, object) {
if (array.every(element => element.id !== object.id)) {
@@ -69,7 +69,7 @@ export function importFetchedStatuses(statuses) {
const filters = [];
function processStatus(status) {
pushUnique(normalStatuses, normalizeStatus(status, getState().getIn(['statuses', status.id]), getState().get('local_settings')));
pushUnique(normalStatuses, normalizeStatus(status, getState().getIn(["statuses", status.id]), getState().get("local_settings")));
pushUnique(accounts, status.account);
if (status.filtered) {
@@ -81,7 +81,7 @@ export function importFetchedStatuses(statuses) {
}
if (status.poll && status.poll.id) {
pushUnique(polls, normalizePoll(status.poll, getState().getIn(['polls', status.poll.id])));
pushUnique(polls, normalizePoll(status.poll, getState().getIn(["polls", status.poll.id])));
}
}
@@ -96,6 +96,6 @@ export function importFetchedStatuses(statuses) {
export function importFetchedPoll(poll) {
return (dispatch, getState) => {
dispatch(importPolls([normalizePoll(poll, getState().getIn(['polls', poll.id]))]));
dispatch(importPolls([normalizePoll(poll, getState().getIn(["polls", poll.id]))]));
};
}
@@ -1,8 +1,8 @@
import escapeTextContentForBrowser from 'escape-html';
import escapeTextContentForBrowser from "escape-html";
import emojify from 'flavours/glitch/features/emoji/emoji';
import { autoHideCW } from 'flavours/glitch/utils/content_warning';
import { unescapeHTML } from 'flavours/glitch/utils/html';
import emojify from "flavours/glitch/features/emoji/emoji";
import { autoHideCW } from "flavours/glitch/utils/content_warning";
import { unescapeHTML } from "flavours/glitch/utils/html";
const domParser = new DOMParser();
@@ -12,9 +12,9 @@ const makeEmojiMap = emojis => emojis.reduce((obj, emoji) => {
}, {});
export function searchTextFromRawStatus (status) {
const spoilerText = status.spoiler_text || '';
const searchContent = ([spoilerText, status.content].concat((status.poll && status.poll.options) ? status.poll.options.map(option => option.title) : [])).concat(status.media_attachments.map(att => att.description)).join('\n\n').replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n');
return domParser.parseFromString(searchContent, 'text/html').documentElement.textContent;
const spoilerText = status.spoiler_text || "";
const searchContent = ([spoilerText, status.content].concat((status.poll && status.poll.options) ? status.poll.options.map(option => option.title) : [])).concat(status.media_attachments.map(att => att.description)).join("\n\n").replace(/<br\s*\/?>/g, "\n").replace(/<\/p><p>/g, "\n\n");
return domParser.parseFromString(searchContent, "text/html").documentElement.textContent;
}
export function normalizeAccount(account) {
@@ -70,33 +70,33 @@ export function normalizeStatus(status, normalOldStatus, settings) {
// Only calculate these values when status first encountered and
// when the underlying values change. Otherwise keep the ones
// already in the reducer
if (normalOldStatus && normalOldStatus.get('content') === normalStatus.content && normalOldStatus.get('spoiler_text') === normalStatus.spoiler_text) {
normalStatus.search_index = normalOldStatus.get('search_index');
normalStatus.contentHtml = normalOldStatus.get('contentHtml');
normalStatus.spoilerHtml = normalOldStatus.get('spoilerHtml');
normalStatus.hidden = normalOldStatus.get('hidden');
if (normalOldStatus && normalOldStatus.get("content") === normalStatus.content && normalOldStatus.get("spoiler_text") === normalStatus.spoiler_text) {
normalStatus.search_index = normalOldStatus.get("search_index");
normalStatus.contentHtml = normalOldStatus.get("contentHtml");
normalStatus.spoilerHtml = normalOldStatus.get("spoilerHtml");
normalStatus.hidden = normalOldStatus.get("hidden");
if (normalOldStatus.get('translation')) {
normalStatus.translation = normalOldStatus.get('translation');
if (normalOldStatus.get("translation")) {
normalStatus.translation = normalOldStatus.get("translation");
}
} else {
const spoilerText = normalStatus.spoiler_text || '';
const searchContent = ([spoilerText, status.content].concat((status.poll && status.poll.options) ? status.poll.options.map(option => option.title) : [])).concat(status.media_attachments.map(att => att.description)).join('\n\n').replace(/<br\s*\/?>/g, '\n').replace(/<\/p><p>/g, '\n\n');
const spoilerText = normalStatus.spoiler_text || "";
const searchContent = ([spoilerText, status.content].concat((status.poll && status.poll.options) ? status.poll.options.map(option => option.title) : [])).concat(status.media_attachments.map(att => att.description)).join("\n\n").replace(/<br\s*\/?>/g, "\n").replace(/<\/p><p>/g, "\n\n");
const emojiMap = makeEmojiMap(normalStatus.emojis);
normalStatus.search_index = domParser.parseFromString(searchContent, 'text/html').documentElement.textContent;
normalStatus.search_index = domParser.parseFromString(searchContent, "text/html").documentElement.textContent;
normalStatus.contentHtml = emojify(normalStatus.content, emojiMap);
normalStatus.spoilerHtml = emojify(escapeTextContentForBrowser(spoilerText), emojiMap);
normalStatus.hidden = (spoilerText.length > 0 || normalStatus.sensitive) && autoHideCW(settings, spoilerText);
}
if (normalOldStatus) {
const list = normalOldStatus.get('media_attachments');
const list = normalOldStatus.get("media_attachments");
if (normalStatus.media_attachments && list) {
normalStatus.media_attachments.forEach(item => {
const oldItem = list.find(i => i.get('id') === item.id);
if (oldItem && oldItem.get('description') === item.description) {
item.translation = oldItem.get('translation');
const oldItem = list.find(i => i.get("id") === item.id);
if (oldItem && oldItem.get("description") === item.description) {
item.translation = oldItem.get("translation");
}
});
}
@@ -106,7 +106,7 @@ export function normalizeStatus(status, normalOldStatus, settings) {
}
export function normalizeStatusTranslation(translation, status) {
const emojiMap = makeEmojiMap(status.get('emojis').toJS());
const emojiMap = makeEmojiMap(status.get("emojis").toJS());
const normalTranslation = {
detected_source_language: translation.detected_source_language,
@@ -131,8 +131,8 @@ export function normalizePoll(poll, normalOldPoll) {
titleHtml: emojify(escapeTextContentForBrowser(option.title), emojiMap),
};
if (normalOldPoll && normalOldPoll.getIn(['options', index, 'title']) === option.title) {
normalOption.translation = normalOldPoll.getIn(['options', index, 'translation']);
if (normalOldPoll && normalOldPoll.getIn(["options", index, "title"]) === option.title) {
normalOption.translation = normalOldPoll.getIn(["options", index, "translation"]);
}
return normalOption;
@@ -142,7 +142,7 @@ export function normalizePoll(poll, normalOldPoll) {
}
export function normalizePollOptionTranslation(translation, poll) {
const emojiMap = makeEmojiMap(poll.get('emojis').toJS());
const emojiMap = makeEmojiMap(poll.get("emojis").toJS());
const normalTranslation = {
...translation,
@@ -1,61 +1,61 @@
import api, { getLinks } from '../api';
import api, { getLinks } from "../api";
import { fetchRelationships } from './accounts';
import { importFetchedAccounts, importFetchedStatus } from './importer';
import { fetchRelationships } from "./accounts";
import { importFetchedAccounts, importFetchedStatus } from "./importer";
export const REBLOG_REQUEST = 'REBLOG_REQUEST';
export const REBLOG_SUCCESS = 'REBLOG_SUCCESS';
export const REBLOG_FAIL = 'REBLOG_FAIL';
export const REBLOG_REQUEST = "REBLOG_REQUEST";
export const REBLOG_SUCCESS = "REBLOG_SUCCESS";
export const REBLOG_FAIL = "REBLOG_FAIL";
export const REBLOGS_EXPAND_REQUEST = 'REBLOGS_EXPAND_REQUEST';
export const REBLOGS_EXPAND_SUCCESS = 'REBLOGS_EXPAND_SUCCESS';
export const REBLOGS_EXPAND_FAIL = 'REBLOGS_EXPAND_FAIL';
export const REBLOGS_EXPAND_REQUEST = "REBLOGS_EXPAND_REQUEST";
export const REBLOGS_EXPAND_SUCCESS = "REBLOGS_EXPAND_SUCCESS";
export const REBLOGS_EXPAND_FAIL = "REBLOGS_EXPAND_FAIL";
export const FAVOURITE_REQUEST = 'FAVOURITE_REQUEST';
export const FAVOURITE_SUCCESS = 'FAVOURITE_SUCCESS';
export const FAVOURITE_FAIL = 'FAVOURITE_FAIL';
export const FAVOURITE_REQUEST = "FAVOURITE_REQUEST";
export const FAVOURITE_SUCCESS = "FAVOURITE_SUCCESS";
export const FAVOURITE_FAIL = "FAVOURITE_FAIL";
export const UNREBLOG_REQUEST = 'UNREBLOG_REQUEST';
export const UNREBLOG_SUCCESS = 'UNREBLOG_SUCCESS';
export const UNREBLOG_FAIL = 'UNREBLOG_FAIL';
export const UNREBLOG_REQUEST = "UNREBLOG_REQUEST";
export const UNREBLOG_SUCCESS = "UNREBLOG_SUCCESS";
export const UNREBLOG_FAIL = "UNREBLOG_FAIL";
export const UNFAVOURITE_REQUEST = 'UNFAVOURITE_REQUEST';
export const UNFAVOURITE_SUCCESS = 'UNFAVOURITE_SUCCESS';
export const UNFAVOURITE_FAIL = 'UNFAVOURITE_FAIL';
export const UNFAVOURITE_REQUEST = "UNFAVOURITE_REQUEST";
export const UNFAVOURITE_SUCCESS = "UNFAVOURITE_SUCCESS";
export const UNFAVOURITE_FAIL = "UNFAVOURITE_FAIL";
export const REBLOGS_FETCH_REQUEST = 'REBLOGS_FETCH_REQUEST';
export const REBLOGS_FETCH_SUCCESS = 'REBLOGS_FETCH_SUCCESS';
export const REBLOGS_FETCH_FAIL = 'REBLOGS_FETCH_FAIL';
export const REBLOGS_FETCH_REQUEST = "REBLOGS_FETCH_REQUEST";
export const REBLOGS_FETCH_SUCCESS = "REBLOGS_FETCH_SUCCESS";
export const REBLOGS_FETCH_FAIL = "REBLOGS_FETCH_FAIL";
export const FAVOURITES_FETCH_REQUEST = 'FAVOURITES_FETCH_REQUEST';
export const FAVOURITES_FETCH_SUCCESS = 'FAVOURITES_FETCH_SUCCESS';
export const FAVOURITES_FETCH_FAIL = 'FAVOURITES_FETCH_FAIL';
export const FAVOURITES_FETCH_REQUEST = "FAVOURITES_FETCH_REQUEST";
export const FAVOURITES_FETCH_SUCCESS = "FAVOURITES_FETCH_SUCCESS";
export const FAVOURITES_FETCH_FAIL = "FAVOURITES_FETCH_FAIL";
export const FAVOURITES_EXPAND_REQUEST = 'FAVOURITES_EXPAND_REQUEST';
export const FAVOURITES_EXPAND_SUCCESS = 'FAVOURITES_EXPAND_SUCCESS';
export const FAVOURITES_EXPAND_FAIL = 'FAVOURITES_EXPAND_FAIL';
export const FAVOURITES_EXPAND_REQUEST = "FAVOURITES_EXPAND_REQUEST";
export const FAVOURITES_EXPAND_SUCCESS = "FAVOURITES_EXPAND_SUCCESS";
export const FAVOURITES_EXPAND_FAIL = "FAVOURITES_EXPAND_FAIL";
export const PIN_REQUEST = 'PIN_REQUEST';
export const PIN_SUCCESS = 'PIN_SUCCESS';
export const PIN_FAIL = 'PIN_FAIL';
export const PIN_REQUEST = "PIN_REQUEST";
export const PIN_SUCCESS = "PIN_SUCCESS";
export const PIN_FAIL = "PIN_FAIL";
export const UNPIN_REQUEST = 'UNPIN_REQUEST';
export const UNPIN_SUCCESS = 'UNPIN_SUCCESS';
export const UNPIN_FAIL = 'UNPIN_FAIL';
export const UNPIN_REQUEST = "UNPIN_REQUEST";
export const UNPIN_SUCCESS = "UNPIN_SUCCESS";
export const UNPIN_FAIL = "UNPIN_FAIL";
export const BOOKMARK_REQUEST = 'BOOKMARK_REQUEST';
export const BOOKMARK_SUCCESS = 'BOOKMARKED_SUCCESS';
export const BOOKMARK_FAIL = 'BOOKMARKED_FAIL';
export const BOOKMARK_REQUEST = "BOOKMARK_REQUEST";
export const BOOKMARK_SUCCESS = "BOOKMARKED_SUCCESS";
export const BOOKMARK_FAIL = "BOOKMARKED_FAIL";
export const UNBOOKMARK_REQUEST = 'UNBOOKMARKED_REQUEST';
export const UNBOOKMARK_SUCCESS = 'UNBOOKMARKED_SUCCESS';
export const UNBOOKMARK_FAIL = 'UNBOOKMARKED_FAIL';
export const UNBOOKMARK_REQUEST = "UNBOOKMARKED_REQUEST";
export const UNBOOKMARK_SUCCESS = "UNBOOKMARKED_SUCCESS";
export const UNBOOKMARK_FAIL = "UNBOOKMARKED_FAIL";
export function reblog(status, visibility) {
return function (dispatch, getState) {
dispatch(reblogRequest(status));
api(getState).post(`/api/v1/statuses/${status.get('id')}/reblog`, { visibility }).then(function (response) {
api(getState).post(`/api/v1/statuses/${status.get("id")}/reblog`, { visibility }).then(function (response) {
// The reblog API method returns a new status wrapped around the original. In this case we are only
// interested in how the original is modified, hence passing it skipping the wrapper
dispatch(importFetchedStatus(response.data.reblog));
@@ -70,7 +70,7 @@ export function unreblog(status) {
return (dispatch, getState) => {
dispatch(unreblogRequest(status));
api(getState).post(`/api/v1/statuses/${status.get('id')}/unreblog`).then(response => {
api(getState).post(`/api/v1/statuses/${status.get("id")}/unreblog`).then(response => {
dispatch(importFetchedStatus(response.data));
dispatch(unreblogSuccess(status));
}).catch(error => {
@@ -127,7 +127,7 @@ export function favourite(status) {
return function (dispatch, getState) {
dispatch(favouriteRequest(status));
api(getState).post(`/api/v1/statuses/${status.get('id')}/favourite`).then(function (response) {
api(getState).post(`/api/v1/statuses/${status.get("id")}/favourite`).then(function (response) {
dispatch(importFetchedStatus(response.data));
dispatch(favouriteSuccess(status));
}).catch(function (error) {
@@ -140,7 +140,7 @@ export function unfavourite(status) {
return (dispatch, getState) => {
dispatch(unfavouriteRequest(status));
api(getState).post(`/api/v1/statuses/${status.get('id')}/unfavourite`).then(response => {
api(getState).post(`/api/v1/statuses/${status.get("id")}/unfavourite`).then(response => {
dispatch(importFetchedStatus(response.data));
dispatch(unfavouriteSuccess(status));
}).catch(error => {
@@ -197,7 +197,7 @@ export function bookmark(status) {
return function (dispatch, getState) {
dispatch(bookmarkRequest(status));
api(getState).post(`/api/v1/statuses/${status.get('id')}/bookmark`).then(function (response) {
api(getState).post(`/api/v1/statuses/${status.get("id")}/bookmark`).then(function (response) {
dispatch(importFetchedStatus(response.data));
dispatch(bookmarkSuccess(status));
}).catch(function (error) {
@@ -210,7 +210,7 @@ export function unbookmark(status) {
return (dispatch, getState) => {
dispatch(unbookmarkRequest(status));
api(getState).post(`/api/v1/statuses/${status.get('id')}/unbookmark`).then(response => {
api(getState).post(`/api/v1/statuses/${status.get("id")}/unbookmark`).then(response => {
dispatch(importFetchedStatus(response.data));
dispatch(unbookmarkSuccess(status));
}).catch(error => {
@@ -268,7 +268,7 @@ export function fetchReblogs(id) {
dispatch(fetchReblogsRequest(id));
api(getState).get(`/api/v1/statuses/${id}/reblogged_by`).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedAccounts(response.data));
dispatch(fetchReblogsSuccess(id, response.data, next ? next.uri : null));
dispatch(fetchRelationships(response.data.map(item => item.id)));
@@ -304,7 +304,7 @@ export function fetchReblogsFail(id, error) {
export function expandReblogs(id) {
return (dispatch, getState) => {
const url = getState().getIn(['user_lists', 'reblogged_by', id, 'next']);
const url = getState().getIn(["user_lists", "reblogged_by", id, "next"]);
if (url === null) {
return;
}
@@ -312,7 +312,7 @@ export function expandReblogs(id) {
dispatch(expandReblogsRequest(id));
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedAccounts(response.data));
dispatch(expandReblogsSuccess(id, response.data, next ? next.uri : null));
@@ -350,7 +350,7 @@ export function fetchFavourites(id) {
dispatch(fetchFavouritesRequest(id));
api(getState).get(`/api/v1/statuses/${id}/favourited_by`).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedAccounts(response.data));
dispatch(fetchFavouritesSuccess(id, response.data, next ? next.uri : null));
dispatch(fetchRelationships(response.data.map(item => item.id)));
@@ -386,7 +386,7 @@ export function fetchFavouritesFail(id, error) {
export function expandFavourites(id) {
return (dispatch, getState) => {
const url = getState().getIn(['user_lists', 'favourited_by', id, 'next']);
const url = getState().getIn(["user_lists", "favourited_by", id, "next"]);
if (url === null) {
return;
}
@@ -394,7 +394,7 @@ export function expandFavourites(id) {
dispatch(expandFavouritesRequest(id));
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedAccounts(response.data));
dispatch(expandFavouritesSuccess(id, response.data, next ? next.uri : null));
@@ -431,7 +431,7 @@ export function pin(status) {
return (dispatch, getState) => {
dispatch(pinRequest(status));
api(getState).post(`/api/v1/statuses/${status.get('id')}/pin`).then(response => {
api(getState).post(`/api/v1/statuses/${status.get("id")}/pin`).then(response => {
dispatch(importFetchedStatus(response.data));
dispatch(pinSuccess(status));
}).catch(error => {
@@ -466,7 +466,7 @@ export function unpin (status) {
return (dispatch, getState) => {
dispatch(unpinRequest(status));
api(getState).post(`/api/v1/statuses/${status.get('id')}/unpin`).then(response => {
api(getState).post(`/api/v1/statuses/${status.get("id")}/unpin`).then(response => {
dispatch(importFetchedStatus(response.data));
dispatch(unpinSuccess(status));
}).catch(error => {
@@ -1,6 +1,6 @@
import { saveSettings } from './settings';
import { saveSettings } from "./settings";
export const LANGUAGE_USE = 'LANGUAGE_USE';
export const LANGUAGE_USE = "LANGUAGE_USE";
export const useLanguage = language => dispatch => {
dispatch({
+51 -51
View File
@@ -1,57 +1,57 @@
import api from '../api';
import api from "../api";
import { showAlertForError } from './alerts';
import { importFetchedAccounts } from './importer';
import { showAlertForError } from "./alerts";
import { importFetchedAccounts } from "./importer";
export const LIST_FETCH_REQUEST = 'LIST_FETCH_REQUEST';
export const LIST_FETCH_SUCCESS = 'LIST_FETCH_SUCCESS';
export const LIST_FETCH_FAIL = 'LIST_FETCH_FAIL';
export const LIST_FETCH_REQUEST = "LIST_FETCH_REQUEST";
export const LIST_FETCH_SUCCESS = "LIST_FETCH_SUCCESS";
export const LIST_FETCH_FAIL = "LIST_FETCH_FAIL";
export const LISTS_FETCH_REQUEST = 'LISTS_FETCH_REQUEST';
export const LISTS_FETCH_SUCCESS = 'LISTS_FETCH_SUCCESS';
export const LISTS_FETCH_FAIL = 'LISTS_FETCH_FAIL';
export const LISTS_FETCH_REQUEST = "LISTS_FETCH_REQUEST";
export const LISTS_FETCH_SUCCESS = "LISTS_FETCH_SUCCESS";
export const LISTS_FETCH_FAIL = "LISTS_FETCH_FAIL";
export const LIST_EDITOR_TITLE_CHANGE = 'LIST_EDITOR_TITLE_CHANGE';
export const LIST_EDITOR_RESET = 'LIST_EDITOR_RESET';
export const LIST_EDITOR_SETUP = 'LIST_EDITOR_SETUP';
export const LIST_EDITOR_TITLE_CHANGE = "LIST_EDITOR_TITLE_CHANGE";
export const LIST_EDITOR_RESET = "LIST_EDITOR_RESET";
export const LIST_EDITOR_SETUP = "LIST_EDITOR_SETUP";
export const LIST_CREATE_REQUEST = 'LIST_CREATE_REQUEST';
export const LIST_CREATE_SUCCESS = 'LIST_CREATE_SUCCESS';
export const LIST_CREATE_FAIL = 'LIST_CREATE_FAIL';
export const LIST_CREATE_REQUEST = "LIST_CREATE_REQUEST";
export const LIST_CREATE_SUCCESS = "LIST_CREATE_SUCCESS";
export const LIST_CREATE_FAIL = "LIST_CREATE_FAIL";
export const LIST_UPDATE_REQUEST = 'LIST_UPDATE_REQUEST';
export const LIST_UPDATE_SUCCESS = 'LIST_UPDATE_SUCCESS';
export const LIST_UPDATE_FAIL = 'LIST_UPDATE_FAIL';
export const LIST_UPDATE_REQUEST = "LIST_UPDATE_REQUEST";
export const LIST_UPDATE_SUCCESS = "LIST_UPDATE_SUCCESS";
export const LIST_UPDATE_FAIL = "LIST_UPDATE_FAIL";
export const LIST_DELETE_REQUEST = 'LIST_DELETE_REQUEST';
export const LIST_DELETE_SUCCESS = 'LIST_DELETE_SUCCESS';
export const LIST_DELETE_FAIL = 'LIST_DELETE_FAIL';
export const LIST_DELETE_REQUEST = "LIST_DELETE_REQUEST";
export const LIST_DELETE_SUCCESS = "LIST_DELETE_SUCCESS";
export const LIST_DELETE_FAIL = "LIST_DELETE_FAIL";
export const LIST_ACCOUNTS_FETCH_REQUEST = 'LIST_ACCOUNTS_FETCH_REQUEST';
export const LIST_ACCOUNTS_FETCH_SUCCESS = 'LIST_ACCOUNTS_FETCH_SUCCESS';
export const LIST_ACCOUNTS_FETCH_FAIL = 'LIST_ACCOUNTS_FETCH_FAIL';
export const LIST_ACCOUNTS_FETCH_REQUEST = "LIST_ACCOUNTS_FETCH_REQUEST";
export const LIST_ACCOUNTS_FETCH_SUCCESS = "LIST_ACCOUNTS_FETCH_SUCCESS";
export const LIST_ACCOUNTS_FETCH_FAIL = "LIST_ACCOUNTS_FETCH_FAIL";
export const LIST_EDITOR_SUGGESTIONS_CHANGE = 'LIST_EDITOR_SUGGESTIONS_CHANGE';
export const LIST_EDITOR_SUGGESTIONS_READY = 'LIST_EDITOR_SUGGESTIONS_READY';
export const LIST_EDITOR_SUGGESTIONS_CLEAR = 'LIST_EDITOR_SUGGESTIONS_CLEAR';
export const LIST_EDITOR_SUGGESTIONS_CHANGE = "LIST_EDITOR_SUGGESTIONS_CHANGE";
export const LIST_EDITOR_SUGGESTIONS_READY = "LIST_EDITOR_SUGGESTIONS_READY";
export const LIST_EDITOR_SUGGESTIONS_CLEAR = "LIST_EDITOR_SUGGESTIONS_CLEAR";
export const LIST_EDITOR_ADD_REQUEST = 'LIST_EDITOR_ADD_REQUEST';
export const LIST_EDITOR_ADD_SUCCESS = 'LIST_EDITOR_ADD_SUCCESS';
export const LIST_EDITOR_ADD_FAIL = 'LIST_EDITOR_ADD_FAIL';
export const LIST_EDITOR_ADD_REQUEST = "LIST_EDITOR_ADD_REQUEST";
export const LIST_EDITOR_ADD_SUCCESS = "LIST_EDITOR_ADD_SUCCESS";
export const LIST_EDITOR_ADD_FAIL = "LIST_EDITOR_ADD_FAIL";
export const LIST_EDITOR_REMOVE_REQUEST = 'LIST_EDITOR_REMOVE_REQUEST';
export const LIST_EDITOR_REMOVE_SUCCESS = 'LIST_EDITOR_REMOVE_SUCCESS';
export const LIST_EDITOR_REMOVE_FAIL = 'LIST_EDITOR_REMOVE_FAIL';
export const LIST_EDITOR_REMOVE_REQUEST = "LIST_EDITOR_REMOVE_REQUEST";
export const LIST_EDITOR_REMOVE_SUCCESS = "LIST_EDITOR_REMOVE_SUCCESS";
export const LIST_EDITOR_REMOVE_FAIL = "LIST_EDITOR_REMOVE_FAIL";
export const LIST_ADDER_RESET = 'LIST_ADDER_RESET';
export const LIST_ADDER_SETUP = 'LIST_ADDER_SETUP';
export const LIST_ADDER_RESET = "LIST_ADDER_RESET";
export const LIST_ADDER_SETUP = "LIST_ADDER_SETUP";
export const LIST_ADDER_LISTS_FETCH_REQUEST = 'LIST_ADDER_LISTS_FETCH_REQUEST';
export const LIST_ADDER_LISTS_FETCH_SUCCESS = 'LIST_ADDER_LISTS_FETCH_SUCCESS';
export const LIST_ADDER_LISTS_FETCH_FAIL = 'LIST_ADDER_LISTS_FETCH_FAIL';
export const LIST_ADDER_LISTS_FETCH_REQUEST = "LIST_ADDER_LISTS_FETCH_REQUEST";
export const LIST_ADDER_LISTS_FETCH_SUCCESS = "LIST_ADDER_LISTS_FETCH_SUCCESS";
export const LIST_ADDER_LISTS_FETCH_FAIL = "LIST_ADDER_LISTS_FETCH_FAIL";
export const fetchList = id => (dispatch, getState) => {
if (getState().getIn(['lists', id])) {
if (getState().getIn(["lists", id])) {
return;
}
@@ -81,7 +81,7 @@ export const fetchListFail = (id, error) => ({
export const fetchLists = () => (dispatch, getState) => {
dispatch(fetchListsRequest());
api(getState).get('/api/v1/lists')
api(getState).get("/api/v1/lists")
.then(({ data }) => dispatch(fetchListsSuccess(data)))
.catch(err => dispatch(fetchListsFail(err)));
};
@@ -101,8 +101,8 @@ export const fetchListsFail = error => ({
});
export const submitListEditor = shouldReset => (dispatch, getState) => {
const listId = getState().getIn(['listEditor', 'listId']);
const title = getState().getIn(['listEditor', 'title']);
const listId = getState().getIn(["listEditor", "listId"]);
const title = getState().getIn(["listEditor", "title"]);
if (listId === null) {
dispatch(createList(title, shouldReset));
@@ -114,7 +114,7 @@ export const submitListEditor = shouldReset => (dispatch, getState) => {
export const setupListEditor = listId => (dispatch, getState) => {
dispatch({
type: LIST_EDITOR_SETUP,
list: getState().getIn(['lists', listId]),
list: getState().getIn(["lists", listId]),
});
dispatch(fetchListAccounts(listId));
@@ -128,7 +128,7 @@ export const changeListEditorTitle = value => ({
export const createList = (title, shouldReset) => (dispatch, getState) => {
dispatch(createListRequest());
api(getState).post('/api/v1/lists', { title }).then(({ data }) => {
api(getState).post("/api/v1/lists", { title }).then(({ data }) => {
dispatch(createListSuccess(data));
if (shouldReset) {
@@ -154,7 +154,7 @@ export const createListFail = error => ({
export const updateList = (id, title, shouldReset, isExclusive, replies_policy) => (dispatch, getState) => {
dispatch(updateListRequest(id));
api(getState).put(`/api/v1/lists/${id}`, { title, replies_policy, exclusive: typeof isExclusive === 'undefined' ? undefined : !!isExclusive }).then(({ data }) => {
api(getState).put(`/api/v1/lists/${id}`, { title, replies_policy, exclusive: typeof isExclusive === "undefined" ? undefined : !!isExclusive }).then(({ data }) => {
dispatch(updateListSuccess(data));
if (shouldReset) {
@@ -242,7 +242,7 @@ export const fetchListSuggestions = q => (dispatch, getState) => {
following: true,
};
api(getState).get('/api/v1/accounts/search', { params }).then(({ data }) => {
api(getState).get("/api/v1/accounts/search", { params }).then(({ data }) => {
dispatch(importFetchedAccounts(data));
dispatch(fetchListSuggestionsReady(q, data));
}).catch(error => dispatch(showAlertForError(error)));
@@ -264,7 +264,7 @@ export const changeListSuggestions = value => ({
});
export const addToListEditor = accountId => (dispatch, getState) => {
dispatch(addToList(getState().getIn(['listEditor', 'listId']), accountId));
dispatch(addToList(getState().getIn(["listEditor", "listId"]), accountId));
};
export const addToList = (listId, accountId) => (dispatch, getState) => {
@@ -295,7 +295,7 @@ export const addToListFail = (listId, accountId, error) => ({
});
export const removeFromListEditor = accountId => (dispatch, getState) => {
dispatch(removeFromList(getState().getIn(['listEditor', 'listId']), accountId));
dispatch(removeFromList(getState().getIn(["listEditor", "listId"]), accountId));
};
export const removeFromList = (listId, accountId) => (dispatch, getState) => {
@@ -332,7 +332,7 @@ export const resetListAdder = () => ({
export const setupListAdder = accountId => (dispatch, getState) => {
dispatch({
type: LIST_ADDER_SETUP,
account: getState().getIn(['accounts', accountId]),
account: getState().getIn(["accounts", accountId]),
});
dispatch(fetchLists());
dispatch(fetchAccountLists(accountId));
@@ -364,10 +364,10 @@ export const fetchAccountListsFail = (id, err) => ({
});
export const addToListAdder = listId => (dispatch, getState) => {
dispatch(addToList(listId, getState().getIn(['listAdder', 'accountId'])));
dispatch(addToList(listId, getState().getIn(["listAdder", "accountId"])));
};
export const removeFromListAdder = listId => (dispatch, getState) => {
dispatch(removeFromList(listId, getState().getIn(['listAdder', 'accountId'])));
dispatch(removeFromList(listId, getState().getIn(["listAdder", "accountId"])));
};
@@ -1,26 +1,26 @@
import { disableSwiping } from 'flavours/glitch/initial_state';
import { disableSwiping } from "flavours/glitch/initial_state";
import { openModal } from './modal';
import { openModal } from "./modal";
export const LOCAL_SETTING_CHANGE = 'LOCAL_SETTING_CHANGE';
export const LOCAL_SETTING_DELETE = 'LOCAL_SETTING_DELETE';
export const LOCAL_SETTING_CHANGE = "LOCAL_SETTING_CHANGE";
export const LOCAL_SETTING_DELETE = "LOCAL_SETTING_DELETE";
export function checkDeprecatedLocalSettings() {
return (dispatch, getState) => {
const local_swipe_to_change_columns = getState().getIn(['local_settings', 'swipe_to_change_columns']);
const local_swipe_to_change_columns = getState().getIn(["local_settings", "swipe_to_change_columns"]);
let changed_settings = [];
if (local_swipe_to_change_columns !== null && local_swipe_to_change_columns !== undefined) {
if (local_swipe_to_change_columns === !disableSwiping) {
dispatch(deleteLocalSetting(['swipe_to_change_columns']));
dispatch(deleteLocalSetting(["swipe_to_change_columns"]));
} else {
changed_settings.push('user_setting_disable_swiping');
changed_settings.push("user_setting_disable_swiping");
}
}
if (changed_settings.length > 0) {
dispatch(openModal({
modalType: 'DEPRECATED_SETTINGS',
modalType: "DEPRECATED_SETTINGS",
modalProps: {
settings: changed_settings,
onConfirm: () => dispatch(clearDeprecatedLocalSettings()),
@@ -32,8 +32,8 @@ export function checkDeprecatedLocalSettings() {
export function clearDeprecatedLocalSettings() {
return (dispatch) => {
dispatch(deleteLocalSetting(['content_warnings', 'auto_unfold']));
dispatch(deleteLocalSetting(['swipe_to_change_columns']));
dispatch(deleteLocalSetting(["content_warnings", "auto_unfold"]));
dispatch(deleteLocalSetting(["swipe_to_change_columns"]));
};
}
@@ -66,7 +66,7 @@ export function deleteLocalSetting(key) {
// their *own* local settings.
export function saveLocalSettings() {
return (_, getState) => {
const localSettings = getState().get('local_settings').toJS();
localStorage.setItem('mastodon-settings', JSON.stringify(localSettings));
const localSettings = getState().get("local_settings").toJS();
localStorage.setItem("mastodon-settings", JSON.stringify(localSettings));
};
}
@@ -1,33 +1,33 @@
import { List as ImmutableList } from 'immutable';
import { List as ImmutableList } from "immutable";
import { debounce } from 'lodash';
import { debounce } from "lodash";
import api from '../api';
import { compareId } from '../compare_id';
import api from "../api";
import { compareId } from "../compare_id";
export const MARKERS_FETCH_REQUEST = 'MARKERS_FETCH_REQUEST';
export const MARKERS_FETCH_SUCCESS = 'MARKERS_FETCH_SUCCESS';
export const MARKERS_FETCH_FAIL = 'MARKERS_FETCH_FAIL';
export const MARKERS_SUBMIT_SUCCESS = 'MARKERS_SUBMIT_SUCCESS';
export const MARKERS_FETCH_REQUEST = "MARKERS_FETCH_REQUEST";
export const MARKERS_FETCH_SUCCESS = "MARKERS_FETCH_SUCCESS";
export const MARKERS_FETCH_FAIL = "MARKERS_FETCH_FAIL";
export const MARKERS_SUBMIT_SUCCESS = "MARKERS_SUBMIT_SUCCESS";
export const synchronouslySubmitMarkers = () => (dispatch, getState) => {
const accessToken = getState().getIn(['meta', 'access_token'], '');
const accessToken = getState().getIn(["meta", "access_token"], "");
const params = _buildParams(getState());
if (Object.keys(params).length === 0 || accessToken === '') {
if (Object.keys(params).length === 0 || accessToken === "") {
return;
}
// The Fetch API allows us to perform requests that will be carried out
// after the page closes. But that only works if the `keepalive` attribute
// is supported.
if (window.fetch && 'keepalive' in new Request('')) {
fetch('/api/v1/markers', {
if (window.fetch && "keepalive" in new Request("")) {
fetch("/api/v1/markers", {
keepalive: true,
method: 'POST',
method: "POST",
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${accessToken}`,
"Content-Type": "application/json",
"Authorization": `Bearer ${accessToken}`,
},
body: JSON.stringify(params),
});
@@ -38,13 +38,13 @@ export const synchronouslySubmitMarkers = () => (dispatch, getState) => {
// FormData for DoorKeeper to recognize the token.
const formData = new FormData();
formData.append('bearer_token', accessToken);
formData.append("bearer_token", accessToken);
for (const [id, value] of Object.entries(params)) {
formData.append(`${id}[last_read_id]`, value.last_read_id);
}
if (navigator.sendBeacon('/api/v1/markers', formData)) {
if (navigator.sendBeacon("/api/v1/markers", formData)) {
return;
}
}
@@ -54,9 +54,9 @@ export const synchronouslySubmitMarkers = () => (dispatch, getState) => {
try {
const client = new XMLHttpRequest();
client.open('POST', '/api/v1/markers', false);
client.setRequestHeader('Content-Type', 'application/json');
client.setRequestHeader('Authorization', `Bearer ${accessToken}`);
client.open("POST", "/api/v1/markers", false);
client.setRequestHeader("Content-Type", "application/json");
client.setRequestHeader("Authorization", `Bearer ${accessToken}`);
client.send(JSON.stringify(params));
} catch (e) {
// Do not make the BeforeUnload handler error out
@@ -66,16 +66,16 @@ export const synchronouslySubmitMarkers = () => (dispatch, getState) => {
const _buildParams = (state) => {
const params = {};
const lastHomeId = state.getIn(['timelines', 'home', 'items'], ImmutableList()).find(item => item !== null);
const lastNotificationId = state.getIn(['notifications', 'lastReadId']);
const lastHomeId = state.getIn(["timelines", "home", "items"], ImmutableList()).find(item => item !== null);
const lastNotificationId = state.getIn(["notifications", "lastReadId"]);
if (lastHomeId && compareId(lastHomeId, state.getIn(['markers', 'home'])) > 0) {
if (lastHomeId && compareId(lastHomeId, state.getIn(["markers", "home"])) > 0) {
params.home = {
last_read_id: lastHomeId,
};
}
if (lastNotificationId && lastNotificationId !== '0' && compareId(lastNotificationId, state.getIn(['markers', 'notifications'])) > 0) {
if (lastNotificationId && lastNotificationId !== "0" && compareId(lastNotificationId, state.getIn(["markers", "notifications"])) > 0) {
params.notifications = {
last_read_id: lastNotificationId,
};
@@ -85,14 +85,14 @@ const _buildParams = (state) => {
};
const debouncedSubmitMarkers = debounce((dispatch, getState) => {
const accessToken = getState().getIn(['meta', 'access_token'], '');
const accessToken = getState().getIn(["meta", "access_token"], "");
const params = _buildParams(getState());
if (Object.keys(params).length === 0 || accessToken === '') {
if (Object.keys(params).length === 0 || accessToken === "") {
return;
}
api(getState).post('/api/v1/markers', params).then(() => {
api(getState).post("/api/v1/markers", params).then(() => {
dispatch(submitMarkersSuccess(params));
}).catch(() => {});
}, 300000, { leading: true, trailing: true });
@@ -116,11 +116,11 @@ export function submitMarkers(params = {}) {
}
export const fetchMarkers = () => (dispatch, getState) => {
const params = { timeline: ['notifications'] };
const params = { timeline: ["notifications"] };
dispatch(fetchMarkersRequest());
api(getState).get('/api/v1/markers', { params }).then(response => {
api(getState).get("/api/v1/markers", { params }).then(response => {
dispatch(fetchMarkersSuccess(response.data));
}).catch(error => {
dispatch(fetchMarkersFail(error));
@@ -1,19 +1,19 @@
import { createAction } from '@reduxjs/toolkit';
import { createAction } from "@reduxjs/toolkit";
import type { ModalProps } from 'flavours/glitch/reducers/modal';
import { type ModalProps } from "flavours/glitch/reducers/modal";
import type { MODAL_COMPONENTS } from '../features/ui/components/modal_root';
import { type MODAL_COMPONENTS } from "../features/ui/components/modal_root";
export type ModalType = keyof typeof MODAL_COMPONENTS;
interface OpenModalPayload {
modalType: ModalType;
modalProps: ModalProps;
modalType: ModalType,
modalProps: ModalProps,
}
export const openModal = createAction<OpenModalPayload>('MODAL_OPEN');
export const openModal = createAction<OpenModalPayload>("MODAL_OPEN");
interface CloseModalPayload {
modalType: ModalType | undefined;
ignoreFocus: boolean;
modalType: ModalType | undefined,
ignoreFocus: boolean,
}
export const closeModal = createAction<CloseModalPayload>('MODAL_CLOSE');
export const closeModal = createAction<CloseModalPayload>("MODAL_CLOSE");
+18 -18
View File
@@ -1,28 +1,28 @@
import { openModal } from 'flavours/glitch/actions/modal';
import { openModal } from "flavours/glitch/actions/modal";
import api, { getLinks } from '../api';
import api, { getLinks } from "../api";
import { fetchRelationships } from './accounts';
import { importFetchedAccounts } from './importer';
import { fetchRelationships } from "./accounts";
import { importFetchedAccounts } from "./importer";
export const MUTES_FETCH_REQUEST = 'MUTES_FETCH_REQUEST';
export const MUTES_FETCH_SUCCESS = 'MUTES_FETCH_SUCCESS';
export const MUTES_FETCH_FAIL = 'MUTES_FETCH_FAIL';
export const MUTES_FETCH_REQUEST = "MUTES_FETCH_REQUEST";
export const MUTES_FETCH_SUCCESS = "MUTES_FETCH_SUCCESS";
export const MUTES_FETCH_FAIL = "MUTES_FETCH_FAIL";
export const MUTES_EXPAND_REQUEST = 'MUTES_EXPAND_REQUEST';
export const MUTES_EXPAND_SUCCESS = 'MUTES_EXPAND_SUCCESS';
export const MUTES_EXPAND_FAIL = 'MUTES_EXPAND_FAIL';
export const MUTES_EXPAND_REQUEST = "MUTES_EXPAND_REQUEST";
export const MUTES_EXPAND_SUCCESS = "MUTES_EXPAND_SUCCESS";
export const MUTES_EXPAND_FAIL = "MUTES_EXPAND_FAIL";
export const MUTES_INIT_MODAL = 'MUTES_INIT_MODAL';
export const MUTES_TOGGLE_HIDE_NOTIFICATIONS = 'MUTES_TOGGLE_HIDE_NOTIFICATIONS';
export const MUTES_CHANGE_DURATION = 'MUTES_CHANGE_DURATION';
export const MUTES_INIT_MODAL = "MUTES_INIT_MODAL";
export const MUTES_TOGGLE_HIDE_NOTIFICATIONS = "MUTES_TOGGLE_HIDE_NOTIFICATIONS";
export const MUTES_CHANGE_DURATION = "MUTES_CHANGE_DURATION";
export function fetchMutes() {
return (dispatch, getState) => {
dispatch(fetchMutesRequest());
api(getState).get('/api/v1/mutes').then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
api(getState).get("/api/v1/mutes").then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedAccounts(response.data));
dispatch(fetchMutesSuccess(response.data, next ? next.uri : null));
dispatch(fetchRelationships(response.data.map(item => item.id)));
@@ -53,7 +53,7 @@ export function fetchMutesFail(error) {
export function expandMutes() {
return (dispatch, getState) => {
const url = getState().getIn(['user_lists', 'mutes', 'next']);
const url = getState().getIn(["user_lists", "mutes", "next"]);
if (url === null) {
return;
@@ -62,7 +62,7 @@ export function expandMutes() {
dispatch(expandMutesRequest());
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedAccounts(response.data));
dispatch(expandMutesSuccess(response.data, next ? next.uri : null));
dispatch(fetchRelationships(response.data.map(item => item.id)));
@@ -98,7 +98,7 @@ export function initMuteModal(account) {
account,
});
dispatch(openModal({ modalType: 'MUTE' }));
dispatch(openModal({ modalType: "MUTE" }));
};
}
@@ -1,69 +1,69 @@
import { IntlMessageFormat } from 'intl-messageformat';
import { defineMessages } from 'react-intl';
import { IntlMessageFormat } from "intl-messageformat";
import { defineMessages } from "react-intl";
import { List as ImmutableList } from 'immutable';
import { List as ImmutableList } from "immutable";
import { compareId } from 'flavours/glitch/compare_id';
import { usePendingItems as preferPendingItems } from 'flavours/glitch/initial_state';
import { unescapeHTML } from 'flavours/glitch/utils/html';
import { requestNotificationPermission } from 'flavours/glitch/utils/notifications';
import { compareId } from "flavours/glitch/compare_id";
import { usePendingItems as preferPendingItems } from "flavours/glitch/initial_state";
import { unescapeHTML } from "flavours/glitch/utils/html";
import { requestNotificationPermission } from "flavours/glitch/utils/notifications";
import api, { getLinks } from '../api';
import api, { getLinks } from "../api";
import { fetchFollowRequests, fetchRelationships } from './accounts';
import { fetchFollowRequests, fetchRelationships } from "./accounts";
import {
importFetchedAccount,
importFetchedAccounts,
importFetchedStatus,
importFetchedStatuses,
} from './importer';
import { submitMarkers } from './markers';
import { register as registerPushNotifications } from './push_notifications';
import { saveSettings } from './settings';
} from "./importer";
import { submitMarkers } from "./markers";
import { register as registerPushNotifications } from "./push_notifications";
import { saveSettings } from "./settings";
export const NOTIFICATIONS_UPDATE = 'NOTIFICATIONS_UPDATE';
export const NOTIFICATIONS_UPDATE_NOOP = 'NOTIFICATIONS_UPDATE_NOOP';
export const NOTIFICATIONS_UPDATE = "NOTIFICATIONS_UPDATE";
export const NOTIFICATIONS_UPDATE_NOOP = "NOTIFICATIONS_UPDATE_NOOP";
// tracking the notif cleaning request
export const NOTIFICATIONS_DELETE_MARKED_REQUEST = 'NOTIFICATIONS_DELETE_MARKED_REQUEST';
export const NOTIFICATIONS_DELETE_MARKED_SUCCESS = 'NOTIFICATIONS_DELETE_MARKED_SUCCESS';
export const NOTIFICATIONS_DELETE_MARKED_FAIL = 'NOTIFICATIONS_DELETE_MARKED_FAIL';
export const NOTIFICATIONS_MARK_ALL_FOR_DELETE = 'NOTIFICATIONS_MARK_ALL_FOR_DELETE';
export const NOTIFICATIONS_ENTER_CLEARING_MODE = 'NOTIFICATIONS_ENTER_CLEARING_MODE'; // arg: yes
export const NOTIFICATIONS_DELETE_MARKED_REQUEST = "NOTIFICATIONS_DELETE_MARKED_REQUEST";
export const NOTIFICATIONS_DELETE_MARKED_SUCCESS = "NOTIFICATIONS_DELETE_MARKED_SUCCESS";
export const NOTIFICATIONS_DELETE_MARKED_FAIL = "NOTIFICATIONS_DELETE_MARKED_FAIL";
export const NOTIFICATIONS_MARK_ALL_FOR_DELETE = "NOTIFICATIONS_MARK_ALL_FOR_DELETE";
export const NOTIFICATIONS_ENTER_CLEARING_MODE = "NOTIFICATIONS_ENTER_CLEARING_MODE"; // arg: yes
// Unmark notifications (when the cleaning mode is left)
export const NOTIFICATIONS_UNMARK_ALL_FOR_DELETE = 'NOTIFICATIONS_UNMARK_ALL_FOR_DELETE';
export const NOTIFICATIONS_UNMARK_ALL_FOR_DELETE = "NOTIFICATIONS_UNMARK_ALL_FOR_DELETE";
// Mark one for delete
export const NOTIFICATION_MARK_FOR_DELETE = 'NOTIFICATION_MARK_FOR_DELETE';
export const NOTIFICATION_MARK_FOR_DELETE = "NOTIFICATION_MARK_FOR_DELETE";
export const NOTIFICATIONS_EXPAND_REQUEST = 'NOTIFICATIONS_EXPAND_REQUEST';
export const NOTIFICATIONS_EXPAND_SUCCESS = 'NOTIFICATIONS_EXPAND_SUCCESS';
export const NOTIFICATIONS_EXPAND_FAIL = 'NOTIFICATIONS_EXPAND_FAIL';
export const NOTIFICATIONS_EXPAND_REQUEST = "NOTIFICATIONS_EXPAND_REQUEST";
export const NOTIFICATIONS_EXPAND_SUCCESS = "NOTIFICATIONS_EXPAND_SUCCESS";
export const NOTIFICATIONS_EXPAND_FAIL = "NOTIFICATIONS_EXPAND_FAIL";
export const NOTIFICATIONS_FILTER_SET = 'NOTIFICATIONS_FILTER_SET';
export const NOTIFICATIONS_FILTER_SET = "NOTIFICATIONS_FILTER_SET";
export const NOTIFICATIONS_CLEAR = 'NOTIFICATIONS_CLEAR';
export const NOTIFICATIONS_SCROLL_TOP = 'NOTIFICATIONS_SCROLL_TOP';
export const NOTIFICATIONS_LOAD_PENDING = 'NOTIFICATIONS_LOAD_PENDING';
export const NOTIFICATIONS_CLEAR = "NOTIFICATIONS_CLEAR";
export const NOTIFICATIONS_SCROLL_TOP = "NOTIFICATIONS_SCROLL_TOP";
export const NOTIFICATIONS_LOAD_PENDING = "NOTIFICATIONS_LOAD_PENDING";
export const NOTIFICATIONS_MOUNT = 'NOTIFICATIONS_MOUNT';
export const NOTIFICATIONS_UNMOUNT = 'NOTIFICATIONS_UNMOUNT';
export const NOTIFICATIONS_MOUNT = "NOTIFICATIONS_MOUNT";
export const NOTIFICATIONS_UNMOUNT = "NOTIFICATIONS_UNMOUNT";
export const NOTIFICATIONS_SET_VISIBILITY = 'NOTIFICATIONS_SET_VISIBILITY';
export const NOTIFICATIONS_SET_VISIBILITY = "NOTIFICATIONS_SET_VISIBILITY";
export const NOTIFICATIONS_MARK_AS_READ = 'NOTIFICATIONS_MARK_AS_READ';
export const NOTIFICATIONS_MARK_AS_READ = "NOTIFICATIONS_MARK_AS_READ";
export const NOTIFICATIONS_SET_BROWSER_SUPPORT = 'NOTIFICATIONS_SET_BROWSER_SUPPORT';
export const NOTIFICATIONS_SET_BROWSER_PERMISSION = 'NOTIFICATIONS_SET_BROWSER_PERMISSION';
export const NOTIFICATIONS_SET_BROWSER_SUPPORT = "NOTIFICATIONS_SET_BROWSER_SUPPORT";
export const NOTIFICATIONS_SET_BROWSER_PERMISSION = "NOTIFICATIONS_SET_BROWSER_PERMISSION";
defineMessages({
mention: { id: 'notification.mention', defaultMessage: '{name} mentioned you' },
mention: { id: "notification.mention", defaultMessage: "{name} mentioned you" },
});
const fetchRelatedRelationships = (dispatch, notifications) => {
const accountIds = notifications.filter(item => ['follow', 'follow_request', 'admin.sign_up'].indexOf(item.type) !== -1).map(item => item.account.id);
const accountIds = notifications.filter(item => ["follow", "follow_request", "admin.sign_up"].indexOf(item.type) !== -1).map(item => item.account.id);
if (accountIds > 0) {
dispatch(fetchRelationships(accountIds));
@@ -76,24 +76,24 @@ export const loadPending = () => ({
export function updateNotifications(notification, intlMessages, intlLocale) {
return (dispatch, getState) => {
const activeFilter = getState().getIn(['settings', 'notifications', 'quickFilter', 'active']);
const showInColumn = activeFilter === 'all' ? getState().getIn(['settings', 'notifications', 'shows', notification.type], true) : activeFilter === notification.type;
const showAlert = getState().getIn(['settings', 'notifications', 'alerts', notification.type], true);
const playSound = getState().getIn(['settings', 'notifications', 'sounds', notification.type], true);
const activeFilter = getState().getIn(["settings", "notifications", "quickFilter", "active"]);
const showInColumn = activeFilter === "all" ? getState().getIn(["settings", "notifications", "shows", notification.type], true) : activeFilter === notification.type;
const showAlert = getState().getIn(["settings", "notifications", "alerts", notification.type], true);
const playSound = getState().getIn(["settings", "notifications", "sounds", notification.type], true);
let filtered = false;
if (['mention', 'status'].includes(notification.type) && notification.status.filtered) {
const filters = notification.status.filtered.filter(result => result.filter.context.includes('notifications'));
if (["mention", "status"].includes(notification.type) && notification.status.filtered) {
const filters = notification.status.filtered.filter(result => result.filter.context.includes("notifications"));
if (filters.some(result => result.filter.filter_action === 'hide')) {
if (filters.some(result => result.filter.filter_action === "hide")) {
return;
}
filtered = filters.length > 0;
}
if (['follow_request'].includes(notification.type)) {
if (["follow_request"].includes(notification.type)) {
dispatch(fetchFollowRequests());
}
@@ -114,24 +114,24 @@ export function updateNotifications(notification, intlMessages, intlLocale) {
type: NOTIFICATIONS_UPDATE,
notification,
usePendingItems: preferPendingItems,
meta: (playSound && !filtered) ? { sound: 'boop' } : undefined,
meta: (playSound && !filtered) ? { sound: "boop" } : undefined,
});
fetchRelatedRelationships(dispatch, [notification]);
} else if (playSound && !filtered) {
dispatch({
type: NOTIFICATIONS_UPDATE_NOOP,
meta: { sound: 'boop' },
meta: { sound: "boop" },
});
}
// Desktop notifications
if (typeof window.Notification !== 'undefined' && showAlert && !filtered) {
if (typeof window.Notification !== "undefined" && showAlert && !filtered) {
const title = new IntlMessageFormat(intlMessages[`notification.${notification.type}`], intlLocale).format({ name: notification.account.display_name.length > 0 ? notification.account.display_name : notification.account.username });
const body = (notification.status && notification.status.spoiler_text.length > 0) ? notification.status.spoiler_text : unescapeHTML(notification.status ? notification.status.content : '');
const body = (notification.status && notification.status.spoiler_text.length > 0) ? notification.status.spoiler_text : unescapeHTML(notification.status ? notification.status.content : "");
const notify = new Notification(title, { body, icon: notification.account.avatar, tag: notification.id });
notify.addEventListener('click', () => {
notify.addEventListener("click", () => {
window.focus();
notify.close();
});
@@ -139,21 +139,21 @@ export function updateNotifications(notification, intlMessages, intlLocale) {
};
}
const excludeTypesFromSettings = state => state.getIn(['settings', 'notifications', 'shows']).filter(enabled => !enabled).keySeq().toJS();
const excludeTypesFromSettings = state => state.getIn(["settings", "notifications", "shows"]).filter(enabled => !enabled).keySeq().toJS();
const excludeTypesFromFilter = filter => {
const allTypes = ImmutableList([
'follow',
'follow_request',
'favourite',
'reblog',
'mention',
'poll',
'status',
'update',
'admin.sign_up',
'admin.report',
"follow",
"follow_request",
"favourite",
"reblog",
"mention",
"poll",
"status",
"update",
"admin.sign_up",
"admin.report",
]);
return allTypes.filterNot(item => item === filter).toJS();
@@ -165,11 +165,11 @@ let expandNotificationsController = new AbortController();
export function expandNotifications({ maxId, forceLoad } = {}, done = noOp) {
return (dispatch, getState) => {
const activeFilter = getState().getIn(['settings', 'notifications', 'quickFilter', 'active']);
const notifications = getState().get('notifications');
const activeFilter = getState().getIn(["settings", "notifications", "quickFilter", "active"]);
const notifications = getState().get("notifications");
const isLoadingMore = !!maxId;
if (notifications.get('isLoading')) {
if (notifications.get("isLoading")) {
if (forceLoad) {
expandNotificationsController.abort();
expandNotificationsController = new AbortController();
@@ -181,14 +181,14 @@ export function expandNotifications({ maxId, forceLoad } = {}, done = noOp) {
const params = {
max_id: maxId,
exclude_types: activeFilter === 'all'
exclude_types: activeFilter === "all"
? excludeTypesFromSettings(getState())
: excludeTypesFromFilter(activeFilter),
};
if (!params.max_id && (notifications.get('items', ImmutableList()).size + notifications.get('pendingItems', ImmutableList()).size) > 0) {
const a = notifications.getIn(['pendingItems', 0, 'id']);
const b = notifications.getIn(['items', 0, 'id']);
if (!params.max_id && (notifications.get("items", ImmutableList()).size + notifications.get("pendingItems", ImmutableList()).size) > 0) {
const a = notifications.getIn(["pendingItems", 0, "id"]);
const b = notifications.getIn(["items", 0, "id"]);
if (a && b && compareId(a, b) > 0) {
params.since_id = a;
@@ -201,8 +201,8 @@ export function expandNotifications({ maxId, forceLoad } = {}, done = noOp) {
dispatch(expandNotificationsRequest(isLoadingMore));
api(getState).get('/api/v1/notifications', { params, signal: expandNotificationsController.signal }).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
api(getState).get("/api/v1/notifications", { params, signal: expandNotificationsController.signal }).then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedAccounts(response.data.map(item => item.account)));
dispatch(importFetchedStatuses(response.data.map(item => item.status).filter(status => !!status)));
@@ -242,7 +242,7 @@ export function expandNotificationsFail(error, isLoadingMore) {
type: NOTIFICATIONS_EXPAND_FAIL,
error,
skipLoading: !isLoadingMore,
skipAlert: !isLoadingMore || error.name === 'AbortError',
skipAlert: !isLoadingMore || error.name === "AbortError",
};
}
@@ -252,7 +252,7 @@ export function clearNotifications() {
type: NOTIFICATIONS_CLEAR,
});
api(getState).post('/api/v1/notifications/clear');
api(getState).post("/api/v1/notifications/clear");
};
}
@@ -268,9 +268,9 @@ export function deleteMarkedNotifications() {
dispatch(deleteMarkedNotificationsRequest());
let ids = [];
getState().getIn(['notifications', 'items']).forEach((n) => {
if (n.get('markedForDelete')) {
ids.push(n.get('id'));
getState().getIn(["notifications", "items"]).forEach((n) => {
if (n.get("markedForDelete")) {
ids.push(n.get("id"));
}
});
@@ -278,7 +278,7 @@ export function deleteMarkedNotifications() {
return;
}
api(getState).delete(`/api/v1/notifications/destroy_multiple?ids[]=${ids.join('&ids[]=')}`).then(() => {
api(getState).delete(`/api/v1/notifications/destroy_multiple?ids[]=${ids.join("&ids[]=")}`).then(() => {
dispatch(deleteMarkedNotificationsSuccess());
}).catch(error => {
console.error(error);
@@ -350,7 +350,7 @@ export function setFilter (filterType) {
return dispatch => {
dispatch({
type: NOTIFICATIONS_FILTER_SET,
path: ['notifications', 'quickFilter', 'active'],
path: ["notifications", "quickFilter", "active"],
value: filterType,
});
dispatch(expandNotifications({ forceLoad: true }));
@@ -367,13 +367,13 @@ export function markNotificationsAsRead() {
// Browser support
export function setupBrowserNotifications() {
return dispatch => {
dispatch(setBrowserSupport('Notification' in window));
if ('Notification' in window) {
dispatch(setBrowserSupport("Notification" in window));
if ("Notification" in window) {
dispatch(setBrowserPermission(Notification.permission));
}
if ('Notification' in window && 'permissions' in navigator) {
navigator.permissions.query({ name: 'notifications' }).then((status) => {
if ("Notification" in window && "permissions" in navigator) {
navigator.permissions.query({ name: "notifications" }).then((status) => {
status.onchange = () => dispatch(setBrowserPermission(Notification.permission));
}).catch(console.warn);
}
@@ -386,7 +386,7 @@ export function requestBrowserPermission(callback = noOp) {
dispatch(setBrowserPermission(permission));
callback(permission);
if (permission === 'granted') {
if (permission === "granted") {
dispatch(registerPushNotifications());
}
});
@@ -1,15 +1,15 @@
import { openModal } from './modal';
import { changeSetting, saveSettings } from './settings';
import { openModal } from "./modal";
import { changeSetting, saveSettings } from "./settings";
export function showOnboardingOnce() {
return (dispatch, getState) => {
const alreadySeen = getState().getIn(['settings', 'onboarded']);
const alreadySeen = getState().getIn(["settings", "onboarded"]);
if (!alreadySeen) {
dispatch(openModal({
modalType: 'ONBOARDING',
modalType: "ONBOARDING",
}));
dispatch(changeSetting(['onboarded'], true));
dispatch(changeSetting(["onboarded"], true));
dispatch(saveSettings());
}
};
@@ -1,7 +1,7 @@
// @ts-check
export const PICTURE_IN_PICTURE_DEPLOY = 'PICTURE_IN_PICTURE_DEPLOY';
export const PICTURE_IN_PICTURE_REMOVE = 'PICTURE_IN_PICTURE_REMOVE';
export const PICTURE_IN_PICTURE_DEPLOY = "PICTURE_IN_PICTURE_DEPLOY";
export const PICTURE_IN_PICTURE_REMOVE = "PICTURE_IN_PICTURE_REMOVE";
/**
* @typedef MediaProps
@@ -26,7 +26,7 @@ export const deployPictureInPicture = (statusId, accountId, playerType, props) =
// @ts-expect-error
return (dispatch, getState) => {
// Do not open a player for a toot that does not exist
if (getState().hasIn(['statuses', statusId])) {
if (getState().hasIn(["statuses", statusId])) {
dispatch({
type: PICTURE_IN_PICTURE_DEPLOY,
statusId,
@@ -1,13 +1,13 @@
import { me } from 'flavours/glitch/initial_state';
import { me } from "flavours/glitch/initial_state";
import api from '../api';
import api from "../api";
import { importFetchedStatuses } from './importer';
import { importFetchedStatuses } from "./importer";
export const PINNED_STATUSES_FETCH_REQUEST = 'PINNED_STATUSES_FETCH_REQUEST';
export const PINNED_STATUSES_FETCH_SUCCESS = 'PINNED_STATUSES_FETCH_SUCCESS';
export const PINNED_STATUSES_FETCH_FAIL = 'PINNED_STATUSES_FETCH_FAIL';
export const PINNED_STATUSES_FETCH_REQUEST = "PINNED_STATUSES_FETCH_REQUEST";
export const PINNED_STATUSES_FETCH_SUCCESS = "PINNED_STATUSES_FETCH_SUCCESS";
export const PINNED_STATUSES_FETCH_FAIL = "PINNED_STATUSES_FETCH_FAIL";
export function fetchPinnedStatuses() {
return (dispatch, getState) => {
@@ -1,14 +1,14 @@
import api from '../api';
import api from "../api";
import { importFetchedPoll } from './importer';
import { importFetchedPoll } from "./importer";
export const POLL_VOTE_REQUEST = 'POLL_VOTE_REQUEST';
export const POLL_VOTE_SUCCESS = 'POLL_VOTE_SUCCESS';
export const POLL_VOTE_FAIL = 'POLL_VOTE_FAIL';
export const POLL_VOTE_REQUEST = "POLL_VOTE_REQUEST";
export const POLL_VOTE_SUCCESS = "POLL_VOTE_SUCCESS";
export const POLL_VOTE_FAIL = "POLL_VOTE_FAIL";
export const POLL_FETCH_REQUEST = 'POLL_FETCH_REQUEST';
export const POLL_FETCH_SUCCESS = 'POLL_FETCH_SUCCESS';
export const POLL_FETCH_FAIL = 'POLL_FETCH_FAIL';
export const POLL_FETCH_REQUEST = "POLL_FETCH_REQUEST";
export const POLL_FETCH_SUCCESS = "POLL_FETCH_SUCCESS";
export const POLL_FETCH_FAIL = "POLL_FETCH_FAIL";
export const vote = (pollId, choices) => (dispatch, getState) => {
dispatch(voteRequest());
@@ -1,5 +1,5 @@
import { saveSettings } from './registerer';
import { setAlerts } from './setter';
import { saveSettings } from "./registerer";
import { setAlerts } from "./setter";
export function changeAlerts(path, value) {
return dispatch => {
@@ -13,5 +13,5 @@ export {
SET_BROWSER_SUPPORT,
SET_SUBSCRIPTION,
SET_ALERTS,
} from './setter';
export { register } from './registerer';
} from "./setter";
export { register } from "./registerer";
@@ -1,14 +1,14 @@
import api from '../../api';
import { pushNotificationsSetting } from '../../settings';
import api from "../../api";
import { pushNotificationsSetting } from "../../settings";
import { setBrowserSupport, setSubscription, clearSubscription } from './setter';
import { setBrowserSupport, setSubscription, clearSubscription } from "./setter";
// Taken from https://www.npmjs.com/package/web-push
const urlBase64ToUint8Array = (base64String) => {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const padding = "=".repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/-/g, '+')
.replace(/_/g, '/');
.replace(/-/g, "+")
.replace(/_/g, "/");
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
@@ -19,7 +19,7 @@ const urlBase64ToUint8Array = (base64String) => {
return outputArray;
};
const getApplicationServerKey = () => document.querySelector('[name="applicationServerKey"]').getAttribute('content');
const getApplicationServerKey = () => document.querySelector("[name=\"applicationServerKey\"]").getAttribute("content");
const getRegistration = () => navigator.serviceWorker.ready;
@@ -46,20 +46,20 @@ const sendSubscriptionToBackend = (getState, subscription, me) => {
}
}
return api(getState).post('/api/web/push_subscriptions', params).then(response => response.data);
return api(getState).post("/api/web/push_subscriptions", params).then(response => response.data);
};
// Last one checks for payload support: https://web-push-book.gauntface.com/chapter-06/01-non-standards-browsers/#no-payload
const supportsPushNotifications = ('serviceWorker' in navigator && 'PushManager' in window && 'getKey' in PushSubscription.prototype);
const supportsPushNotifications = ("serviceWorker" in navigator && "PushManager" in window && "getKey" in PushSubscription.prototype);
export function register () {
return (dispatch, getState) => {
dispatch(setBrowserSupport(supportsPushNotifications));
const me = getState().getIn(['meta', 'me']);
const me = getState().getIn(["meta", "me"]);
if (supportsPushNotifications) {
if (!getApplicationServerKey()) {
console.error('The VAPID public key is not set. You will not be able to receive Web Push Notifications.');
console.error("The VAPID public key is not set. You will not be able to receive Web Push Notifications.");
return;
}
@@ -70,7 +70,7 @@ export function register () {
// We have a subscription, check if it is still valid
const currentServerKey = (new Uint8Array(subscription.options.applicationServerKey)).toString();
const subscriptionServerKey = urlBase64ToUint8Array(getApplicationServerKey()).toString();
const serverEndpoint = getState().getIn(['push_notifications', 'subscription', 'endpoint']);
const serverEndpoint = getState().getIn(["push_notifications", "subscription", "endpoint"]);
// If the VAPID public key did not change and the endpoint corresponds
// to the endpoint saved in the backend, the subscription is valid
@@ -98,10 +98,10 @@ export function register () {
}
})
.catch(error => {
if (error.code === 20 && error.name === 'AbortError') {
console.warn('Your browser supports Web Push Notifications, but does not seem to implement the VAPID protocol.');
} else if (error.code === 5 && error.name === 'InvalidCharacterError') {
console.error('The VAPID public key seems to be invalid:', getApplicationServerKey());
if (error.code === 20 && error.name === "AbortError") {
console.warn("Your browser supports Web Push Notifications, but does not seem to implement the VAPID protocol.");
} else if (error.code === 5 && error.name === "InvalidCharacterError") {
console.error("The VAPID public key seems to be invalid:", getApplicationServerKey());
}
// Clear alerts and hide UI settings
@@ -116,22 +116,22 @@ export function register () {
})
.catch(console.warn);
} else {
console.warn('Your browser does not support Web Push Notifications.');
console.warn("Your browser does not support Web Push Notifications.");
}
};
}
export function saveSettings() {
return (_, getState) => {
const state = getState().get('push_notifications');
const subscription = state.get('subscription');
const alerts = state.get('alerts');
const state = getState().get("push_notifications");
const subscription = state.get("subscription");
const alerts = state.get("alerts");
const data = { alerts };
api(getState).put(`/api/web/push_subscriptions/${subscription.get('id')}`, {
api(getState).put(`/api/web/push_subscriptions/${subscription.get("id")}`, {
data,
}).then(() => {
const me = getState().getIn(['meta', 'me']);
const me = getState().getIn(["meta", "me"]);
if (me) {
pushNotificationsSetting.set(me, data);
}
@@ -1,7 +1,7 @@
export const SET_BROWSER_SUPPORT = 'PUSH_NOTIFICATIONS_SET_BROWSER_SUPPORT';
export const SET_SUBSCRIPTION = 'PUSH_NOTIFICATIONS_SET_SUBSCRIPTION';
export const CLEAR_SUBSCRIPTION = 'PUSH_NOTIFICATIONS_CLEAR_SUBSCRIPTION';
export const SET_ALERTS = 'PUSH_NOTIFICATIONS_SET_ALERTS';
export const SET_BROWSER_SUPPORT = "PUSH_NOTIFICATIONS_SET_BROWSER_SUPPORT";
export const SET_SUBSCRIPTION = "PUSH_NOTIFICATIONS_SET_SUBSCRIPTION";
export const CLEAR_SUBSCRIPTION = "PUSH_NOTIFICATIONS_CLEAR_SUBSCRIPTION";
export const SET_ALERTS = "PUSH_NOTIFICATIONS_SET_ALERTS";
export function setBrowserSupport (value) {
return {
@@ -1,29 +1,33 @@
import api from '../api';
import api from "../api";
import { openModal } from './modal';
import { openModal } from "./modal";
export const REPORT_SUBMIT_REQUEST = 'REPORT_SUBMIT_REQUEST';
export const REPORT_SUBMIT_SUCCESS = 'REPORT_SUBMIT_SUCCESS';
export const REPORT_SUBMIT_FAIL = 'REPORT_SUBMIT_FAIL';
export const REPORT_SUBMIT_REQUEST = "REPORT_SUBMIT_REQUEST";
export const REPORT_SUBMIT_SUCCESS = "REPORT_SUBMIT_SUCCESS";
export const REPORT_SUBMIT_FAIL = "REPORT_SUBMIT_FAIL";
export const initReport = (account, status) => dispatch =>
dispatch(openModal({
modalType: 'REPORT',
modalType: "REPORT",
modalProps: {
accountId: account.get('id'),
statusId: status?.get('id'),
accountId: account.get("id"),
statusId: status?.get("id"),
},
}));
export const submitReport = (params, onSuccess, onFail) => (dispatch, getState) => {
dispatch(submitReportRequest());
api(getState).post('/api/v1/reports', params).then(response => {
api(getState).post("/api/v1/reports", params).then(response => {
dispatch(submitReportSuccess(response.data));
if (onSuccess) onSuccess();
if (onSuccess) {
onSuccess();
}
}).catch(error => {
dispatch(submitReportFail(error));
if (onFail) onFail();
if (onFail) {
onFail();
}
});
};
@@ -1,25 +1,25 @@
import { fromJS } from 'immutable';
import { fromJS } from "immutable";
import { searchHistory } from 'flavours/glitch/settings';
import { searchHistory } from "flavours/glitch/settings";
import api from '../api';
import api from "../api";
import { fetchRelationships } from './accounts';
import { importFetchedAccounts, importFetchedStatuses } from './importer';
import { fetchRelationships } from "./accounts";
import { importFetchedAccounts, importFetchedStatuses } from "./importer";
export const SEARCH_CHANGE = 'SEARCH_CHANGE';
export const SEARCH_CLEAR = 'SEARCH_CLEAR';
export const SEARCH_SHOW = 'SEARCH_SHOW';
export const SEARCH_CHANGE = "SEARCH_CHANGE";
export const SEARCH_CLEAR = "SEARCH_CLEAR";
export const SEARCH_SHOW = "SEARCH_SHOW";
export const SEARCH_FETCH_REQUEST = 'SEARCH_FETCH_REQUEST';
export const SEARCH_FETCH_SUCCESS = 'SEARCH_FETCH_SUCCESS';
export const SEARCH_FETCH_FAIL = 'SEARCH_FETCH_FAIL';
export const SEARCH_FETCH_REQUEST = "SEARCH_FETCH_REQUEST";
export const SEARCH_FETCH_SUCCESS = "SEARCH_FETCH_SUCCESS";
export const SEARCH_FETCH_FAIL = "SEARCH_FETCH_FAIL";
export const SEARCH_EXPAND_REQUEST = 'SEARCH_EXPAND_REQUEST';
export const SEARCH_EXPAND_SUCCESS = 'SEARCH_EXPAND_SUCCESS';
export const SEARCH_EXPAND_FAIL = 'SEARCH_EXPAND_FAIL';
export const SEARCH_EXPAND_REQUEST = "SEARCH_EXPAND_REQUEST";
export const SEARCH_EXPAND_SUCCESS = "SEARCH_EXPAND_SUCCESS";
export const SEARCH_EXPAND_FAIL = "SEARCH_EXPAND_FAIL";
export const SEARCH_HISTORY_UPDATE = 'SEARCH_HISTORY_UPDATE';
export const SEARCH_HISTORY_UPDATE = "SEARCH_HISTORY_UPDATE";
export function changeSearch(value) {
return {
@@ -36,17 +36,17 @@ export function clearSearch() {
export function submitSearch(type) {
return (dispatch, getState) => {
const value = getState().getIn(['search', 'value']);
const signedIn = !!getState().getIn(['meta', 'me']);
const value = getState().getIn(["search", "value"]);
const signedIn = !!getState().getIn(["meta", "me"]);
if (value.length === 0) {
dispatch(fetchSearchSuccess({ accounts: [], statuses: [], hashtags: [] }, '', type));
dispatch(fetchSearchSuccess({ accounts: [], statuses: [], hashtags: [] }, "", type));
return;
}
dispatch(fetchSearchRequest(type));
api(getState).get('/api/v2/search', {
api(getState).get("/api/v2/search", {
params: {
q: value,
resolve: signedIn,
@@ -94,12 +94,12 @@ export function fetchSearchFail(error) {
}
export const expandSearch = type => (dispatch, getState) => {
const value = getState().getIn(['search', 'value']);
const offset = getState().getIn(['search', 'results', type]).size - 1;
const value = getState().getIn(["search", "value"]);
const offset = getState().getIn(["search", "results", type]).size - 1;
dispatch(expandSearchRequest(type));
api(getState).get('/api/v2/search', {
api(getState).get("/api/v2/search", {
params: {
q: value,
type,
@@ -144,8 +144,8 @@ export const showSearch = () => ({
});
export const openURL = routerHistory => (dispatch, getState) => {
const value = getState().getIn(['search', 'value']);
const signedIn = !!getState().getIn(['meta', 'me']);
const value = getState().getIn(["search", "value"]);
const signedIn = !!getState().getIn(["meta", "me"]);
if (!signedIn) {
return;
@@ -153,7 +153,7 @@ export const openURL = routerHistory => (dispatch, getState) => {
dispatch(fetchSearchRequest());
api(getState).get('/api/v2/search', { params: { q: value, resolve: true } }).then(response => {
api(getState).get("/api/v2/search", { params: { q: value, resolve: true } }).then(response => {
if (response.data.accounts?.length > 0) {
dispatch(importFetchedAccounts(response.data.accounts));
routerHistory.push(`/@${response.data.accounts[0].acct}`);
@@ -169,8 +169,8 @@ export const openURL = routerHistory => (dispatch, getState) => {
};
export const clickSearchResult = (q, type) => (dispatch, getState) => {
const previous = getState().getIn(['search', 'recent']);
const me = getState().getIn(['meta', 'me']);
const previous = getState().getIn(["search", "recent"]);
const me = getState().getIn(["meta", "me"]);
const current = previous.add(fromJS({ type, q })).takeLast(4);
searchHistory.set(me, current.toJS());
@@ -178,9 +178,9 @@ export const clickSearchResult = (q, type) => (dispatch, getState) => {
};
export const forgetSearchResult = q => (dispatch, getState) => {
const previous = getState().getIn(['search', 'recent']);
const me = getState().getIn(['meta', 'me']);
const current = previous.filterNot(result => result.get('q') === q);
const previous = getState().getIn(["search", "recent"]);
const me = getState().getIn(["meta", "me"]);
const current = previous.filterNot(result => result.get("q") === q);
searchHistory.set(me, current.toJS());
dispatch(updateSearchHistory(current));
@@ -192,7 +192,7 @@ export const updateSearchHistory = recent => ({
});
export const hydrateSearch = () => (dispatch, getState) => {
const me = getState().getIn(['meta', 'me']);
const me = getState().getIn(["meta", "me"]);
const history = searchHistory.get(me);
if (history !== null) {
@@ -1,37 +1,44 @@
import api from '../api';
import api from "../api";
import { importFetchedAccount } from './importer';
import { importFetchedAccount } from "./importer";
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 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 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 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) => {
if (getState().getIn(['server', 'server', 'isLoading'])) {
if (getState().getIn(["server", "server", "isLoading"])) {
return;
}
dispatch(fetchServerRequest());
/* global data */
try {
api(getState)
.get('/api/v2/instance').then({ data })
if (data.contact.account) dispatch(importFetchedAccount(data.contact.account));
dispatch(fetchServerSuccess(data));
.get("/api/v2/instance").then({ data }).catch(error => {
console.error(error);
});
if (data.contact.account) {
dispatch(importFetchedAccount(data.contact.account));
}
dispatch(fetchServerSuccess(data));
} catch (e) {
api(getState)
.get('/api/v1/instance').then(({ data }) => {
if (data.contact_account) dispatch(importFetchedAccount(data.contact_account));
.get("/api/v1/instance").then(({ data }) => {
if (data.contact_account) {
dispatch(importFetchedAccount(data.contact_account));
}
dispatch(fetchServerSuccess(data));
}).catch(err => dispatch(fetchServerFail(err)));
}).catch(err => dispatch(fetchServerFail(err)));
}
};
@@ -50,14 +57,14 @@ const fetchServerFail = error => ({
});
export const fetchDomainBlocks = () => (dispatch, getState) => {
if (getState().getIn(['server', 'domainBlocks', 'isLoading'])) {
if (getState().getIn(["server", "domainBlocks", "isLoading"])) {
return;
}
dispatch(fetchDomainBlocksRequest());
api(getState)
.get('/api/v1/instance/domain_blocks')
.get("/api/v1/instance/domain_blocks")
.then(({ data }) => dispatch(fetchDomainBlocksSuccess(true, data)))
.catch(err => {
if (err.response.status === 404) {
@@ -1,7 +1,7 @@
import { debounce } from 'lodash';
import { debounce } from "lodash";
export const SETTING_CHANGE = 'SETTING_CHANGE';
export const SETTING_SAVE = 'SETTING_SAVE';
export const SETTING_CHANGE = "SETTING_CHANGE";
export const SETTING_SAVE = "SETTING_SAVE";
export function changeSetting(path, value) {
return dispatch => {
@@ -16,13 +16,13 @@ export function changeSetting(path, value) {
}
const debouncedSave = debounce((dispatch, getState) => {
if (getState().getIn(['settings', 'saved'])) {
if (getState().getIn(["settings", "saved"])) {
return;
}
const data = getState().get('settings').filter((_, path) => path !== 'saved').toJS();
const data = getState().get("settings").filter((_, path) => path !== "saved").toJS();
localStorage.setItem('web_settings', JSON.stringify(data));
localStorage.setItem("web_settings", JSON.stringify(data));
dispatch({ type: SETTING_SAVE });
}, 5000, { trailing: true });
@@ -1,43 +1,43 @@
import api from '../api';
import api from "../api";
import { ensureComposeIsVisible, setComposeToStatus } from './compose';
import { importFetchedStatus, importFetchedStatuses } from './importer';
import { deleteFromTimelines } from './timelines';
import { ensureComposeIsVisible, setComposeToStatus } from "./compose";
import { importFetchedStatus, importFetchedStatuses } from "./importer";
import { deleteFromTimelines } from "./timelines";
export const STATUS_FETCH_REQUEST = 'STATUS_FETCH_REQUEST';
export const STATUS_FETCH_SUCCESS = 'STATUS_FETCH_SUCCESS';
export const STATUS_FETCH_FAIL = 'STATUS_FETCH_FAIL';
export const STATUS_FETCH_REQUEST = "STATUS_FETCH_REQUEST";
export const STATUS_FETCH_SUCCESS = "STATUS_FETCH_SUCCESS";
export const STATUS_FETCH_FAIL = "STATUS_FETCH_FAIL";
export const STATUS_DELETE_REQUEST = 'STATUS_DELETE_REQUEST';
export const STATUS_DELETE_SUCCESS = 'STATUS_DELETE_SUCCESS';
export const STATUS_DELETE_FAIL = 'STATUS_DELETE_FAIL';
export const STATUS_DELETE_REQUEST = "STATUS_DELETE_REQUEST";
export const STATUS_DELETE_SUCCESS = "STATUS_DELETE_SUCCESS";
export const STATUS_DELETE_FAIL = "STATUS_DELETE_FAIL";
export const CONTEXT_FETCH_REQUEST = 'CONTEXT_FETCH_REQUEST';
export const CONTEXT_FETCH_SUCCESS = 'CONTEXT_FETCH_SUCCESS';
export const CONTEXT_FETCH_FAIL = 'CONTEXT_FETCH_FAIL';
export const CONTEXT_FETCH_REQUEST = "CONTEXT_FETCH_REQUEST";
export const CONTEXT_FETCH_SUCCESS = "CONTEXT_FETCH_SUCCESS";
export const CONTEXT_FETCH_FAIL = "CONTEXT_FETCH_FAIL";
export const STATUS_MUTE_REQUEST = 'STATUS_MUTE_REQUEST';
export const STATUS_MUTE_SUCCESS = 'STATUS_MUTE_SUCCESS';
export const STATUS_MUTE_FAIL = 'STATUS_MUTE_FAIL';
export const STATUS_MUTE_REQUEST = "STATUS_MUTE_REQUEST";
export const STATUS_MUTE_SUCCESS = "STATUS_MUTE_SUCCESS";
export const STATUS_MUTE_FAIL = "STATUS_MUTE_FAIL";
export const STATUS_UNMUTE_REQUEST = 'STATUS_UNMUTE_REQUEST';
export const STATUS_UNMUTE_SUCCESS = 'STATUS_UNMUTE_SUCCESS';
export const STATUS_UNMUTE_FAIL = 'STATUS_UNMUTE_FAIL';
export const STATUS_UNMUTE_REQUEST = "STATUS_UNMUTE_REQUEST";
export const STATUS_UNMUTE_SUCCESS = "STATUS_UNMUTE_SUCCESS";
export const STATUS_UNMUTE_FAIL = "STATUS_UNMUTE_FAIL";
export const STATUS_REVEAL = 'STATUS_REVEAL';
export const STATUS_HIDE = 'STATUS_HIDE';
export const STATUS_COLLAPSE = 'STATUS_COLLAPSE';
export const STATUS_REVEAL = "STATUS_REVEAL";
export const STATUS_HIDE = "STATUS_HIDE";
export const STATUS_COLLAPSE = "STATUS_COLLAPSE";
export const REDRAFT = 'REDRAFT';
export const REDRAFT = "REDRAFT";
export const STATUS_FETCH_SOURCE_REQUEST = 'STATUS_FETCH_SOURCE_REQUEST';
export const STATUS_FETCH_SOURCE_SUCCESS = 'STATUS_FETCH_SOURCE_SUCCESS';
export const STATUS_FETCH_SOURCE_FAIL = 'STATUS_FETCH_SOURCE_FAIL';
export const STATUS_FETCH_SOURCE_REQUEST = "STATUS_FETCH_SOURCE_REQUEST";
export const STATUS_FETCH_SOURCE_SUCCESS = "STATUS_FETCH_SOURCE_SUCCESS";
export const STATUS_FETCH_SOURCE_FAIL = "STATUS_FETCH_SOURCE_FAIL";
export const STATUS_TRANSLATE_REQUEST = 'STATUS_TRANSLATE_REQUEST';
export const STATUS_TRANSLATE_SUCCESS = 'STATUS_TRANSLATE_SUCCESS';
export const STATUS_TRANSLATE_FAIL = 'STATUS_TRANSLATE_FAIL';
export const STATUS_TRANSLATE_UNDO = 'STATUS_TRANSLATE_UNDO';
export const STATUS_TRANSLATE_REQUEST = "STATUS_TRANSLATE_REQUEST";
export const STATUS_TRANSLATE_SUCCESS = "STATUS_TRANSLATE_SUCCESS";
export const STATUS_TRANSLATE_FAIL = "STATUS_TRANSLATE_FAIL";
export const STATUS_TRANSLATE_UNDO = "STATUS_TRANSLATE_UNDO";
export function fetchStatusRequest(id, skipLoading) {
return {
@@ -49,7 +49,7 @@ export function fetchStatusRequest(id, skipLoading) {
export function fetchStatus(id, forceFetch = false) {
return (dispatch, getState) => {
const skipLoading = !forceFetch && getState().getIn(['statuses', id], null) !== null;
const skipLoading = !forceFetch && getState().getIn(["statuses", id], null) !== null;
dispatch(fetchContext(id));
@@ -95,10 +95,10 @@ export function redraft(status, raw_text, content_type) {
}
export const editStatus = (id, routerHistory) => (dispatch, getState) => {
let status = getState().getIn(['statuses', id]);
let status = getState().getIn(["statuses", id]);
if (status.get('poll')) {
status = status.set('poll', getState().getIn(['polls', status.get('poll')]));
if (status.get("poll")) {
status = status.set("poll", getState().getIn(["polls", status.get("poll")]));
}
dispatch(fetchStatusSourceRequest());
@@ -127,10 +127,10 @@ export const fetchStatusSourceFail = error => ({
export function deleteStatus(id, routerHistory, withRedraft = false) {
return (dispatch, getState) => {
let status = getState().getIn(['statuses', id]);
let status = getState().getIn(["statuses", id]);
if (status.get('poll')) {
status = status.set('poll', getState().getIn(['polls', status.get('poll')]));
if (status.get("poll")) {
status = status.set("poll", getState().getIn(["polls", status.get("poll")]));
}
dispatch(deleteStatusRequest(id));
+11 -11
View File
@@ -1,12 +1,12 @@
import { Iterable, fromJS } from 'immutable';
import { Iterable, fromJS } from "immutable";
import { hydrateCompose } from './compose';
import { importFetchedAccounts } from './importer';
import { hydrateSearch } from './search';
import { saveSettings } from './settings';
import { hydrateCompose } from "./compose";
import { importFetchedAccounts } from "./importer";
import { hydrateSearch } from "./search";
import { saveSettings } from "./settings";
export const STORE_HYDRATE = 'STORE_HYDRATE';
export const STORE_HYDRATE_LAZY = 'STORE_HYDRATE_LAZY';
export const STORE_HYDRATE = "STORE_HYDRATE";
export const STORE_HYDRATE_LAZY = "STORE_HYDRATE_LAZY";
const convertState = rawState =>
fromJS(rawState, (k, v) =>
@@ -15,12 +15,12 @@ const convertState = rawState =>
const applyMigrations = (state) => {
return state.withMutations(state => {
// Migrate glitch-soc local-only “Show unread marker” setting to Mastodon's setting
if (state.getIn(['local_settings', 'notifications', 'show_unread']) !== undefined) {
if (state.getIn(["local_settings", "notifications", "show_unread"]) !== undefined) {
// Only change if the Mastodon setting does not deviate from default
if (state.getIn(['settings', 'notifications', 'showUnread']) !== false) {
state.setIn(['settings', 'notifications', 'showUnread'], state.getIn(['local_settings', 'notifications', 'show_unread']));
if (state.getIn(["settings", "notifications", "showUnread"]) !== false) {
state.setIn(["settings", "notifications", "showUnread"], state.getIn(["local_settings", "notifications", "show_unread"]));
}
state.removeIn(['local_settings', 'notifications', 'show_unread']);
state.removeIn(["local_settings", "notifications", "show_unread"]);
}
});
};
@@ -1,18 +1,18 @@
// @ts-check
import { getLocale } from 'flavours/glitch/locales';
import { getLocale } from "flavours/glitch/locales";
import { connectStream } from '../stream';
import { connectStream } from "../stream";
import {
fetchAnnouncements,
updateAnnouncements,
updateReaction as updateAnnouncementsReaction,
deleteAnnouncement,
} from './announcements';
import { updateConversations } from './conversations';
import { updateNotifications, expandNotifications } from './notifications';
import { updateStatus } from './statuses';
} from "./announcements";
import { updateConversations } from "./conversations";
import { updateNotifications, expandNotifications } from "./notifications";
import { updateStatus } from "./statuses";
import {
updateTimeline,
deleteFromTimelines,
@@ -23,7 +23,7 @@ import {
fillPublicTimelineGaps,
fillCommunityTimelineGaps,
fillListTimelineGaps,
} from './timelines';
} from "./timelines";
/**
* @param {number} max
@@ -46,7 +46,7 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti
const { messages } = getLocale();
return connectStream(channelName, params, (dispatch, getState) => {
const locale = getState().getIn(['meta', 'locale']);
const locale = getState().getIn(["meta", "locale"]);
// @ts-expect-error
let pollingId;
@@ -57,7 +57,7 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti
const useFallback = fallback => {
fallback(dispatch, () => {
// eslint-disable-next-line react-hooks/rules-of-hooks -- this is not a react hook
// eslint-disable-next-line react-hooks/rules-of-hooks
pollingId = setTimeout(() => useFallback(fallback), 20000 + randomUpTo(20000));
});
};
@@ -88,36 +88,36 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti
onReceive (data) {
switch(data.event) {
case 'update':
case "update":
// @ts-expect-error
dispatch(updateTimeline(timelineId, JSON.parse(data.payload), options.accept));
break;
case 'status.update':
dispatch(updateTimeline(timelineId, JSON.parse(data.payload), options.accept));
break;
case "status.update":
// @ts-expect-error
dispatch(updateStatus(JSON.parse(data.payload)));
break;
case 'delete':
dispatch(deleteFromTimelines(data.payload));
break;
case 'notification':
dispatch(updateStatus(JSON.parse(data.payload)));
break;
case "delete":
dispatch(deleteFromTimelines(data.payload));
break;
case "notification":
// @ts-expect-error
dispatch(updateNotifications(JSON.parse(data.payload), messages, locale));
break;
case 'conversation':
dispatch(updateNotifications(JSON.parse(data.payload), messages, locale));
break;
case "conversation":
// @ts-expect-error
dispatch(updateConversations(JSON.parse(data.payload)));
break;
case 'announcement':
dispatch(updateConversations(JSON.parse(data.payload)));
break;
case "announcement":
// @ts-expect-error
dispatch(updateAnnouncements(JSON.parse(data.payload)));
break;
case 'announcement.reaction':
dispatch(updateAnnouncements(JSON.parse(data.payload)));
break;
case "announcement.reaction":
// @ts-expect-error
dispatch(updateAnnouncementsReaction(JSON.parse(data.payload)));
break;
case 'announcement.delete':
dispatch(deleteAnnouncement(data.payload));
break;
dispatch(updateAnnouncementsReaction(JSON.parse(data.payload)));
break;
case "announcement.delete":
dispatch(deleteAnnouncement(data.payload));
break;
}
},
};
@@ -129,9 +129,7 @@ export const connectTimelineStream = (timelineId, channelName, params = {}, opti
* @param {function(): void} done
*/
const refreshHomeTimelineAndNotification = (dispatch, done) => {
// @ts-expect-error
dispatch(expandHomeTimeline({}, () =>
// @ts-expect-error
dispatch(expandNotifications({}, () =>
dispatch(fetchAnnouncements(done))))));
};
@@ -141,7 +139,7 @@ const refreshHomeTimelineAndNotification = (dispatch, done) => {
*/
export const connectUserStream = () =>
// @ts-expect-error
connectTimelineStream('home', 'user', {}, { fallback: refreshHomeTimelineAndNotification, fillGaps: fillHomeTimelineGaps });
connectTimelineStream("home", "user", {}, { fallback: refreshHomeTimelineAndNotification, fillGaps: fillHomeTimelineGaps });
/**
* @param {Object} options
@@ -149,7 +147,7 @@ export const connectUserStream = () =>
* @returns {function(): void}
*/
export const connectCommunityStream = ({ onlyMedia } = {}) =>
connectTimelineStream(`community${onlyMedia ? ':media' : ''}`, `public:local${onlyMedia ? ':media' : ''}`, {}, { fillGaps: () => (fillCommunityTimelineGaps({ onlyMedia })) });
connectTimelineStream(`community${onlyMedia ? ":media" : ""}`, `public:local${onlyMedia ? ":media" : ""}`, {}, { fillGaps: () => (fillCommunityTimelineGaps({ onlyMedia })) });
/**
* @param {Object} options
@@ -159,7 +157,7 @@ export const connectCommunityStream = ({ onlyMedia } = {}) =>
* @returns {function(): void}
*/
export const connectPublicStream = ({ onlyMedia, onlyRemote, allowLocalOnly } = {}) =>
connectTimelineStream(`public${onlyRemote ? ':remote' : (allowLocalOnly ? ':allow_local_only' : '')}${onlyMedia ? ':media' : ''}`, `public${onlyRemote ? ':remote' : (allowLocalOnly ? ':allow_local_only' : '')}${onlyMedia ? ':media' : ''}`, {}, { fillGaps: () => fillPublicTimelineGaps({ onlyMedia, onlyRemote, allowLocalOnly }) });
connectTimelineStream(`public${onlyRemote ? ":remote" : (allowLocalOnly ? ":allow_local_only" : "")}${onlyMedia ? ":media" : ""}`, `public${onlyRemote ? ":remote" : (allowLocalOnly ? ":allow_local_only" : "")}${onlyMedia ? ":media" : ""}`, {}, { fillGaps: () => fillPublicTimelineGaps({ onlyMedia, onlyRemote, allowLocalOnly }) });
/**
* @param {string} columnId
@@ -169,17 +167,17 @@ export const connectPublicStream = ({ onlyMedia, onlyRemote, allowLocalOnly } =
* @returns {function(): void}
*/
export const connectHashtagStream = (columnId, tagName, onlyLocal, accept) =>
connectTimelineStream(`hashtag:${columnId}${onlyLocal ? ':local' : ''}`, `hashtag${onlyLocal ? ':local' : ''}`, { tag: tagName }, { accept });
connectTimelineStream(`hashtag:${columnId}${onlyLocal ? ":local" : ""}`, `hashtag${onlyLocal ? ":local" : ""}`, { tag: tagName }, { accept });
/**
* @returns {function(): void}
*/
export const connectDirectStream = () =>
connectTimelineStream('direct', 'direct');
connectTimelineStream("direct", "direct");
/**
* @param {string} listId
* @returns {function(): void}
*/
export const connectListStream = listId =>
connectTimelineStream(`list:${listId}`, 'list', { list: listId }, { fillGaps: () => fillListTimelineGaps(listId) });
connectTimelineStream(`list:${listId}`, "list", { list: listId }, { fillGaps: () => fillListTimelineGaps(listId) });
@@ -1,19 +1,19 @@
import api from '../api';
import api from "../api";
import { fetchRelationships } from './accounts';
import { importFetchedAccounts } from './importer';
import { fetchRelationships } from "./accounts";
import { importFetchedAccounts } from "./importer";
export const SUGGESTIONS_FETCH_REQUEST = 'SUGGESTIONS_FETCH_REQUEST';
export const SUGGESTIONS_FETCH_SUCCESS = 'SUGGESTIONS_FETCH_SUCCESS';
export const SUGGESTIONS_FETCH_FAIL = 'SUGGESTIONS_FETCH_FAIL';
export const SUGGESTIONS_FETCH_REQUEST = "SUGGESTIONS_FETCH_REQUEST";
export const SUGGESTIONS_FETCH_SUCCESS = "SUGGESTIONS_FETCH_SUCCESS";
export const SUGGESTIONS_FETCH_FAIL = "SUGGESTIONS_FETCH_FAIL";
export const SUGGESTIONS_DISMISS = 'SUGGESTIONS_DISMISS';
export const SUGGESTIONS_DISMISS = "SUGGESTIONS_DISMISS";
export function fetchSuggestions(withRelationships = false) {
return (dispatch, getState) => {
dispatch(fetchSuggestionsRequest());
api(getState).get('/api/v2/suggestions', { params: { limit: 20 } }).then(response => {
api(getState).get("/api/v2/suggestions", { params: { limit: 20 } }).then(response => {
dispatch(importFetchedAccounts(response.data.map(x => x.account)));
dispatch(fetchSuggestionsSuccess(response.data));
@@ -57,7 +57,7 @@ export const dismissSuggestion = accountId => (dispatch, getState) => {
api(getState).delete(`/api/v1/suggestions/${accountId}`).then(() => {
dispatch(fetchSuggestionsRequest());
api(getState).get('/api/v2/suggestions').then(response => {
api(getState).get("/api/v2/suggestions").then(response => {
dispatch(importFetchedAccounts(response.data.map(x => x.account)));
dispatch(fetchSuggestionsSuccess(response.data));
}).catch(error => dispatch(fetchSuggestionsFail(error)));
+20 -20
View File
@@ -1,24 +1,24 @@
import api, { getLinks } from '../api';
import api, { getLinks } from "../api";
export const HASHTAG_FETCH_REQUEST = 'HASHTAG_FETCH_REQUEST';
export const HASHTAG_FETCH_SUCCESS = 'HASHTAG_FETCH_SUCCESS';
export const HASHTAG_FETCH_FAIL = 'HASHTAG_FETCH_FAIL';
export const HASHTAG_FETCH_REQUEST = "HASHTAG_FETCH_REQUEST";
export const HASHTAG_FETCH_SUCCESS = "HASHTAG_FETCH_SUCCESS";
export const HASHTAG_FETCH_FAIL = "HASHTAG_FETCH_FAIL";
export const FOLLOWED_HASHTAGS_FETCH_REQUEST = 'FOLLOWED_HASHTAGS_FETCH_REQUEST';
export const FOLLOWED_HASHTAGS_FETCH_SUCCESS = 'FOLLOWED_HASHTAGS_FETCH_SUCCESS';
export const FOLLOWED_HASHTAGS_FETCH_FAIL = 'FOLLOWED_HASHTAGS_FETCH_FAIL';
export const FOLLOWED_HASHTAGS_FETCH_REQUEST = "FOLLOWED_HASHTAGS_FETCH_REQUEST";
export const FOLLOWED_HASHTAGS_FETCH_SUCCESS = "FOLLOWED_HASHTAGS_FETCH_SUCCESS";
export const FOLLOWED_HASHTAGS_FETCH_FAIL = "FOLLOWED_HASHTAGS_FETCH_FAIL";
export const FOLLOWED_HASHTAGS_EXPAND_REQUEST = 'FOLLOWED_HASHTAGS_EXPAND_REQUEST';
export const FOLLOWED_HASHTAGS_EXPAND_SUCCESS = 'FOLLOWED_HASHTAGS_EXPAND_SUCCESS';
export const FOLLOWED_HASHTAGS_EXPAND_FAIL = 'FOLLOWED_HASHTAGS_EXPAND_FAIL';
export const FOLLOWED_HASHTAGS_EXPAND_REQUEST = "FOLLOWED_HASHTAGS_EXPAND_REQUEST";
export const FOLLOWED_HASHTAGS_EXPAND_SUCCESS = "FOLLOWED_HASHTAGS_EXPAND_SUCCESS";
export const FOLLOWED_HASHTAGS_EXPAND_FAIL = "FOLLOWED_HASHTAGS_EXPAND_FAIL";
export const HASHTAG_FOLLOW_REQUEST = 'HASHTAG_FOLLOW_REQUEST';
export const HASHTAG_FOLLOW_SUCCESS = 'HASHTAG_FOLLOW_SUCCESS';
export const HASHTAG_FOLLOW_FAIL = 'HASHTAG_FOLLOW_FAIL';
export const HASHTAG_FOLLOW_REQUEST = "HASHTAG_FOLLOW_REQUEST";
export const HASHTAG_FOLLOW_SUCCESS = "HASHTAG_FOLLOW_SUCCESS";
export const HASHTAG_FOLLOW_FAIL = "HASHTAG_FOLLOW_FAIL";
export const HASHTAG_UNFOLLOW_REQUEST = 'HASHTAG_UNFOLLOW_REQUEST';
export const HASHTAG_UNFOLLOW_SUCCESS = 'HASHTAG_UNFOLLOW_SUCCESS';
export const HASHTAG_UNFOLLOW_FAIL = 'HASHTAG_UNFOLLOW_FAIL';
export const HASHTAG_UNFOLLOW_REQUEST = "HASHTAG_UNFOLLOW_REQUEST";
export const HASHTAG_UNFOLLOW_SUCCESS = "HASHTAG_UNFOLLOW_SUCCESS";
export const HASHTAG_UNFOLLOW_FAIL = "HASHTAG_UNFOLLOW_FAIL";
export const fetchHashtag = name => (dispatch, getState) => {
dispatch(fetchHashtagRequest());
@@ -48,8 +48,8 @@ export const fetchHashtagFail = error => ({
export const fetchFollowedHashtags = () => (dispatch, getState) => {
dispatch(fetchFollowedHashtagsRequest());
api(getState).get('/api/v1/followed_tags').then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
api(getState).get("/api/v1/followed_tags").then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(fetchFollowedHashtagsSuccess(response.data, next ? next.uri : null));
}).catch(err => {
dispatch(fetchFollowedHashtagsFail(err));
@@ -79,7 +79,7 @@ export function fetchFollowedHashtagsFail(error) {
export function expandFollowedHashtags() {
return (dispatch, getState) => {
const url = getState().getIn(['followed_tags', 'next']);
const url = getState().getIn(["followed_tags", "next"]);
if (url === null) {
return;
@@ -88,7 +88,7 @@ export function expandFollowedHashtags() {
dispatch(expandFollowedHashtagsRequest());
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(expandFollowedHashtagsSuccess(response.data, next ? next.uri : null));
}).catch(error => {
dispatch(expandFollowedHashtagsFail(error));
@@ -1,27 +1,27 @@
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
import { Map as ImmutableMap, List as ImmutableList } from "immutable";
import api, { getLinks } from 'flavours/glitch/api';
import { compareId } from 'flavours/glitch/compare_id';
import { usePendingItems as preferPendingItems } from 'flavours/glitch/initial_state';
import { toServerSideType } from 'flavours/glitch/utils/filters';
import api, { getLinks } from "flavours/glitch/api";
import { compareId } from "flavours/glitch/compare_id";
import { usePendingItems as preferPendingItems } from "flavours/glitch/initial_state";
import { toServerSideType } from "flavours/glitch/utils/filters";
import { importFetchedStatus, importFetchedStatuses } from './importer';
import { submitMarkers } from './markers';
import { importFetchedStatus, importFetchedStatuses } from "./importer";
import { submitMarkers } from "./markers";
export const TIMELINE_UPDATE = 'TIMELINE_UPDATE';
export const TIMELINE_DELETE = 'TIMELINE_DELETE';
export const TIMELINE_CLEAR = 'TIMELINE_CLEAR';
export const TIMELINE_UPDATE = "TIMELINE_UPDATE";
export const TIMELINE_DELETE = "TIMELINE_DELETE";
export const TIMELINE_CLEAR = "TIMELINE_CLEAR";
export const TIMELINE_EXPAND_REQUEST = 'TIMELINE_EXPAND_REQUEST';
export const TIMELINE_EXPAND_SUCCESS = 'TIMELINE_EXPAND_SUCCESS';
export const TIMELINE_EXPAND_FAIL = 'TIMELINE_EXPAND_FAIL';
export const TIMELINE_EXPAND_REQUEST = "TIMELINE_EXPAND_REQUEST";
export const TIMELINE_EXPAND_SUCCESS = "TIMELINE_EXPAND_SUCCESS";
export const TIMELINE_EXPAND_FAIL = "TIMELINE_EXPAND_FAIL";
export const TIMELINE_SCROLL_TOP = 'TIMELINE_SCROLL_TOP';
export const TIMELINE_LOAD_PENDING = 'TIMELINE_LOAD_PENDING';
export const TIMELINE_DISCONNECT = 'TIMELINE_DISCONNECT';
export const TIMELINE_CONNECT = 'TIMELINE_CONNECT';
export const TIMELINE_SCROLL_TOP = "TIMELINE_SCROLL_TOP";
export const TIMELINE_LOAD_PENDING = "TIMELINE_LOAD_PENDING";
export const TIMELINE_DISCONNECT = "TIMELINE_DISCONNECT";
export const TIMELINE_CONNECT = "TIMELINE_CONNECT";
export const TIMELINE_MARK_AS_PARTIAL = 'TIMELINE_MARK_AS_PARTIAL';
export const TIMELINE_MARK_AS_PARTIAL = "TIMELINE_MARK_AS_PARTIAL";
export const loadPending = timeline => ({
type: TIMELINE_LOAD_PENDING,
@@ -30,11 +30,11 @@ export const loadPending = timeline => ({
export function updateTimeline(timeline, status, accept) {
return (dispatch, getState) => {
if (typeof accept === 'function' && !accept(status)) {
if (typeof accept === "function" && !accept(status)) {
return;
}
if (getState().getIn(['timelines', timeline, 'isPartial'])) {
if (getState().getIn(["timelines", timeline, "isPartial"])) {
// Prevent new items from being added to a partial timeline,
// since it will be reloaded anyway
@@ -60,7 +60,7 @@ export function updateTimeline(timeline, status, accept) {
filtered,
});
if (timeline === 'home') {
if (timeline === "home") {
dispatch(submitMarkers());
}
};
@@ -68,9 +68,9 @@ export function updateTimeline(timeline, status, accept) {
export function deleteFromTimelines(id) {
return (dispatch, getState) => {
const accountId = getState().getIn(['statuses', id, 'account']);
const references = getState().get('statuses').filter(status => status.get('reblog') === id).map(status => status.get('id'));
const reblogOf = getState().getIn(['statuses', id, 'reblog'], null);
const accountId = getState().getIn(["statuses", id, "account"]);
const references = getState().get("statuses").filter(status => status.get("reblog") === id).map(status => status.get("id"));
const reblogOf = getState().getIn(["statuses", id, "reblog"], null);
dispatch({
type: TIMELINE_DELETE,
@@ -98,17 +98,17 @@ const parseTags = (tags = {}, mode) => {
export function expandTimeline(timelineId, path, params = {}, done = noOp) {
return (dispatch, getState) => {
const timeline = getState().getIn(['timelines', timelineId], ImmutableMap());
const timeline = getState().getIn(["timelines", timelineId], ImmutableMap());
const isLoadingMore = !!params.max_id;
if (timeline.get('isLoading')) {
if (timeline.get("isLoading")) {
done();
return;
}
if (!params.max_id && !params.pinned && (timeline.get('items', ImmutableList()).size + timeline.get('pendingItems', ImmutableList()).size) > 0) {
const a = timeline.getIn(['pendingItems', 0]);
const b = timeline.getIn(['items', 0]);
if (!params.max_id && !params.pinned && (timeline.get("items", ImmutableList()).size + timeline.get("pendingItems", ImmutableList()).size) > 0) {
const a = timeline.getIn(["pendingItems", 0]);
const b = timeline.getIn(["items", 0]);
if (a && b && compareId(a, b) > 0) {
params.since_id = a;
@@ -122,11 +122,11 @@ export function expandTimeline(timelineId, path, params = {}, done = noOp) {
dispatch(expandTimelineRequest(timelineId, isLoadingMore));
api(getState).get(path, { params }).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedStatuses(response.data));
dispatch(expandTimelineSuccess(timelineId, response.data, next ? next.uri : null, response.status === 206, isLoadingRecent, isLoadingMore, isLoadingRecent && preferPendingItems));
if (timelineId === 'home') {
if (timelineId === "home") {
dispatch(submitMarkers());
}
}).catch(error => {
@@ -139,8 +139,8 @@ export function expandTimeline(timelineId, path, params = {}, done = noOp) {
export function fillTimelineGaps(timelineId, path, params = {}, done = noOp) {
return (dispatch, getState) => {
const timeline = getState().getIn(['timelines', timelineId], ImmutableMap());
const items = timeline.get('items');
const timeline = getState().getIn(["timelines", timelineId], ImmutableMap());
const items = timeline.get("items");
const nullIndexes = items.map((statusId, index) => statusId === null ? index : null);
const gaps = nullIndexes.map(index => index > 0 ? items.get(index - 1) : null);
@@ -153,27 +153,27 @@ export function fillTimelineGaps(timelineId, path, params = {}, done = noOp) {
};
}
export const expandHomeTimeline = ({ maxId } = {}, done = noOp) => expandTimeline('home', '/api/v1/timelines/home', { max_id: maxId }, done);
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, tagged } = {}) => expandTimeline(`account:${accountId}${withReplies ? ':with_replies' : ''}${tagged ? `:${tagged}` : ''}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, exclude_reblogs: withReplies, tagged, max_id: maxId });
export const expandHomeTimeline = ({ maxId } = {}, done = noOp) => expandTimeline("home", "/api/v1/timelines/home", { max_id: maxId }, done);
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, tagged } = {}) => expandTimeline(`account:${accountId}${withReplies ? ":with_replies" : ""}${tagged ? `:${tagged}` : ""}`, `/api/v1/accounts/${accountId}/statuses`, { exclude_replies: !withReplies, exclude_reblogs: 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) => {
return expandTimeline(`hashtag:${hashtag}${local ? ':local' : ''}`, `/api/v1/timelines/tag/${hashtag}`, {
return expandTimeline(`hashtag:${hashtag}${local ? ":local" : ""}`, `/api/v1/timelines/tag/${hashtag}`, {
max_id: maxId,
any: parseTags(tags, 'any'),
all: parseTags(tags, 'all'),
none: parseTags(tags, 'none'),
any: parseTags(tags, "any"),
all: parseTags(tags, "all"),
none: parseTags(tags, "none"),
local: local,
}, done);
};
export const fillHomeTimelineGaps = (done = noOp) => fillTimelineGaps('home', '/api/v1/timelines/home', {}, done);
export const fillPublicTimelineGaps = ({ onlyMedia, onlyRemote, allowLocalOnly } = {}, done = noOp) => fillTimelineGaps(`public${onlyRemote ? ':remote' : (allowLocalOnly ? ':allow_local_only' : '')}${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { remote: !!onlyRemote, only_media: !!onlyMedia, allow_local_only: !!allowLocalOnly }, done);
export const fillCommunityTimelineGaps = ({ onlyMedia } = {}, done = noOp) => fillTimelineGaps(`community${onlyMedia ? ':media' : ''}`, '/api/v1/timelines/public', { local: true, only_media: !!onlyMedia }, done);
export const fillHomeTimelineGaps = (done = noOp) => fillTimelineGaps("home", "/api/v1/timelines/home", {}, done);
export const fillPublicTimelineGaps = ({ onlyMedia, onlyRemote, allowLocalOnly } = {}, done = noOp) => fillTimelineGaps(`public${onlyRemote ? ":remote" : (allowLocalOnly ? ":allow_local_only" : "")}${onlyMedia ? ":media" : ""}`, "/api/v1/timelines/public", { remote: !!onlyRemote, only_media: !!onlyMedia, allow_local_only: !!allowLocalOnly }, done);
export const fillCommunityTimelineGaps = ({ onlyMedia } = {}, done = noOp) => fillTimelineGaps(`community${onlyMedia ? ":media" : ""}`, "/api/v1/timelines/public", { local: true, only_media: !!onlyMedia }, done);
export const fillListTimelineGaps = (id, done = noOp) => fillTimelineGaps(`list:${id}`, `/api/v1/timelines/list/${id}`, {}, done);
export function expandTimelineRequest(timeline, isLoadingMore) {
@@ -203,7 +203,7 @@ export function expandTimelineFail(timeline, error, isLoadingMore) {
timeline,
error,
skipLoading: !isLoadingMore,
skipNotFound: timeline.startsWith('account:'),
skipNotFound: timeline.startsWith("account:"),
};
}
@@ -1,28 +1,28 @@
import api, { getLinks } from '../api';
import api, { getLinks } from "../api";
import { importFetchedStatuses } from './importer';
import { importFetchedStatuses } from "./importer";
export const TRENDS_TAGS_FETCH_REQUEST = 'TRENDS_TAGS_FETCH_REQUEST';
export const TRENDS_TAGS_FETCH_SUCCESS = 'TRENDS_TAGS_FETCH_SUCCESS';
export const TRENDS_TAGS_FETCH_FAIL = 'TRENDS_TAGS_FETCH_FAIL';
export const TRENDS_TAGS_FETCH_REQUEST = "TRENDS_TAGS_FETCH_REQUEST";
export const TRENDS_TAGS_FETCH_SUCCESS = "TRENDS_TAGS_FETCH_SUCCESS";
export const TRENDS_TAGS_FETCH_FAIL = "TRENDS_TAGS_FETCH_FAIL";
export const TRENDS_LINKS_FETCH_REQUEST = 'TRENDS_LINKS_FETCH_REQUEST';
export const TRENDS_LINKS_FETCH_SUCCESS = 'TRENDS_LINKS_FETCH_SUCCESS';
export const TRENDS_LINKS_FETCH_FAIL = 'TRENDS_LINKS_FETCH_FAIL';
export const TRENDS_LINKS_FETCH_REQUEST = "TRENDS_LINKS_FETCH_REQUEST";
export const TRENDS_LINKS_FETCH_SUCCESS = "TRENDS_LINKS_FETCH_SUCCESS";
export const TRENDS_LINKS_FETCH_FAIL = "TRENDS_LINKS_FETCH_FAIL";
export const TRENDS_STATUSES_FETCH_REQUEST = 'TRENDS_STATUSES_FETCH_REQUEST';
export const TRENDS_STATUSES_FETCH_SUCCESS = 'TRENDS_STATUSES_FETCH_SUCCESS';
export const TRENDS_STATUSES_FETCH_FAIL = 'TRENDS_STATUSES_FETCH_FAIL';
export const TRENDS_STATUSES_FETCH_REQUEST = "TRENDS_STATUSES_FETCH_REQUEST";
export const TRENDS_STATUSES_FETCH_SUCCESS = "TRENDS_STATUSES_FETCH_SUCCESS";
export const TRENDS_STATUSES_FETCH_FAIL = "TRENDS_STATUSES_FETCH_FAIL";
export const TRENDS_STATUSES_EXPAND_REQUEST = 'TRENDS_STATUSES_EXPAND_REQUEST';
export const TRENDS_STATUSES_EXPAND_SUCCESS = 'TRENDS_STATUSES_EXPAND_SUCCESS';
export const TRENDS_STATUSES_EXPAND_FAIL = 'TRENDS_STATUSES_EXPAND_FAIL';
export const TRENDS_STATUSES_EXPAND_REQUEST = "TRENDS_STATUSES_EXPAND_REQUEST";
export const TRENDS_STATUSES_EXPAND_SUCCESS = "TRENDS_STATUSES_EXPAND_SUCCESS";
export const TRENDS_STATUSES_EXPAND_FAIL = "TRENDS_STATUSES_EXPAND_FAIL";
export const fetchTrendingHashtags = () => (dispatch, getState) => {
dispatch(fetchTrendingHashtagsRequest());
api(getState)
.get('/api/v1/trends/tags')
.get("/api/v1/trends/tags")
.then(({ data }) => dispatch(fetchTrendingHashtagsSuccess(data)))
.catch(err => dispatch(fetchTrendingHashtagsFail(err)));
};
@@ -49,7 +49,7 @@ export const fetchTrendingLinks = () => (dispatch, getState) => {
dispatch(fetchTrendingLinksRequest());
api(getState)
.get('/api/v1/trends/links')
.get("/api/v1/trends/links")
.then(({ data }) => dispatch(fetchTrendingLinksSuccess(data)))
.catch(err => dispatch(fetchTrendingLinksFail(err)));
};
@@ -73,14 +73,14 @@ export const fetchTrendingLinksFail = error => ({
});
export const fetchTrendingStatuses = () => (dispatch, getState) => {
if (getState().getIn(['status_lists', 'trending', 'isLoading'])) {
if (getState().getIn(["status_lists", "trending", "isLoading"])) {
return;
}
dispatch(fetchTrendingStatusesRequest());
api(getState).get('/api/v1/trends/statuses').then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
api(getState).get("/api/v1/trends/statuses").then(response => {
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedStatuses(response.data));
dispatch(fetchTrendingStatusesSuccess(response.data, next ? next.uri : null));
}).catch(err => dispatch(fetchTrendingStatusesFail(err)));
@@ -107,16 +107,16 @@ export const fetchTrendingStatusesFail = error => ({
export const expandTrendingStatuses = () => (dispatch, getState) => {
const url = getState().getIn(['status_lists', 'trending', 'next'], null);
const url = getState().getIn(["status_lists", "trending", "next"], null);
if (url === null || getState().getIn(['status_lists', 'trending', 'isLoading'])) {
if (url === null || getState().getIn(["status_lists", "trending", "isLoading"])) {
return;
}
dispatch(expandTrendingStatusesRequest());
api(getState).get(url).then(response => {
const next = getLinks(response).refs.find(link => link.rel === 'next');
const next = getLinks(response).refs.find(link => link.rel === "next");
dispatch(importFetchedStatuses(response.data));
dispatch(expandTrendingStatusesSuccess(response.data, next ? next.uri : null));
}).catch(error => {
+8 -8
View File
@@ -1,9 +1,9 @@
// @ts-check
import axios from 'axios';
import LinkHeader from 'http-link-header';
import axios from "axios";
import LinkHeader from "http-link-header";
import ready from './ready';
import ready from "./ready";
/**
* @param {import('axios').AxiosResponse} response
* @returns {LinkHeader}
@@ -26,10 +26,10 @@ const csrfHeader = {};
*/
const setCSRFHeader = () => {
/** @type {HTMLMetaElement | null} */
const csrfToken = document.querySelector('meta[name=csrf-token]');
const csrfToken = document.querySelector("meta[name=csrf-token]");
if (csrfToken) {
csrfHeader['X-CSRF-Token'] = csrfToken.content;
csrfHeader["X-CSRF-Token"] = csrfToken.content;
}
};
@@ -40,14 +40,14 @@ ready(setCSRFHeader);
* @returns {import('axios').RawAxiosRequestHeaders}
*/
const authorizationHeaderFromState = getState => {
const accessToken = getState && getState().getIn(['meta', 'access_token'], '');
const accessToken = getState && getState().getIn(["meta", "access_token"], "");
if (!accessToken) {
return {};
}
return {
'Authorization': `Bearer ${accessToken}`,
"Authorization": `Bearer ${accessToken}`,
};
};
@@ -56,7 +56,7 @@ const authorizationHeaderFromState = getState => {
* @returns {string}
*/
const baseUrlFromState = getState => {
const baseUrl = getState && getState().getIn(['meta', 'base_url'], '');
const baseUrl = getState && getState().getIn(["meta", "base_url"], "");
return `${baseUrl}`;
};
+83 -83
View File
@@ -1,87 +1,87 @@
const DIGIT_CHARACTERS = [
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z',
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z',
'#',
'$',
'%',
'*',
'+',
',',
'-',
'.',
':',
';',
'=',
'?',
'@',
'[',
']',
'^',
'_',
'{',
'|',
'}',
'~',
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
"#",
"$",
"%",
"*",
"+",
",",
"-",
".",
":",
";",
"=",
"?",
"@",
"[",
"]",
"^",
"_",
"{",
"|",
"}",
"~",
];
export const decode83 = (str: string) => {
@@ -1,30 +1,30 @@
import PropTypes from 'prop-types';
import PropTypes from "prop-types";
import { defineMessages, injectIntl } from 'react-intl';
import { defineMessages, injectIntl } from "react-intl";
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import ImmutablePropTypes from "react-immutable-proptypes";
import ImmutablePureComponent from "react-immutable-pure-component";
import { Skeleton } from 'flavours/glitch/components/skeleton';
import { me } from 'flavours/glitch/initial_state';
import { Skeleton } from "flavours/glitch/components/skeleton";
import { me } from "flavours/glitch/initial_state";
import { Avatar } from './avatar';
import { DisplayName } from './display_name';
import { IconButton } from './icon_button';
import Permalink from './permalink';
import { RelativeTimestamp } from './relative_timestamp';
import { Avatar } from "./avatar";
import { DisplayName } from "./display_name";
import { IconButton } from "./icon_button";
import Permalink from "./permalink";
import { RelativeTimestamp } from "./relative_timestamp";
const messages = defineMessages({
follow: { id: 'account.follow', defaultMessage: 'Follow' },
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
requested: { id: 'account.requested', defaultMessage: 'Awaiting approval. Click to cancel follow request' },
unblock: { id: 'account.unblock', defaultMessage: 'Unblock @{name}' },
unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' },
mute_notifications: { id: 'account.mute_notifications', defaultMessage: 'Mute notifications from @{name}' },
unmute_notifications: { id: 'account.unmute_notifications', defaultMessage: 'Unmute notifications from @{name}' },
mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' },
block: { id: 'account.block', defaultMessage: 'Block @{name}' },
follow: { id: "account.follow", defaultMessage: "Follow" },
unfollow: { id: "account.unfollow", defaultMessage: "Unfollow" },
requested: { id: "account.requested", defaultMessage: "Awaiting approval. Click to cancel follow request" },
unblock: { id: "account.unblock", defaultMessage: "Unblock @{name}" },
unmute: { id: "account.unmute", defaultMessage: "Unmute @{name}" },
mute_notifications: { id: "account.mute_notifications", defaultMessage: "Mute notifications from @{name}" },
unmute_notifications: { id: "account.unmute_notifications", defaultMessage: "Unmute notifications from @{name}" },
mute: { id: "account.mute", defaultMessage: "Mute @{name}" },
block: { id: "account.block", defaultMessage: "Block @{name}" },
});
class Account extends ImmutablePureComponent {
@@ -102,8 +102,8 @@ class Account extends ImmutablePureComponent {
if (hidden) {
return (
<>
{account.get('display_name')}
{account.get('username')}
{account.get("display_name")}
{account.get("username")}
</>
);
}
@@ -114,48 +114,48 @@ class Account extends ImmutablePureComponent {
if (actionIcon) {
buttons = <IconButton icon={actionIcon} title={actionTitle} onClick={this.handleAction} />;
}
} else if (account.get('id') !== me && !small && account.get('relationship', null) !== null) {
const following = account.getIn(['relationship', 'following']);
const requested = account.getIn(['relationship', 'requested']);
const blocking = account.getIn(['relationship', 'blocking']);
const muting = account.getIn(['relationship', 'muting']);
} else if (account.get("id") !== me && !small && account.get("relationship", null) !== null) {
const following = account.getIn(["relationship", "following"]);
const requested = account.getIn(["relationship", "requested"]);
const blocking = account.getIn(["relationship", "blocking"]);
const muting = account.getIn(["relationship", "muting"]);
if (requested) {
buttons = <IconButton disabled icon='hourglass' title={intl.formatMessage(messages.requested)} />;
} else if (blocking) {
buttons = <IconButton active icon='unlock' title={intl.formatMessage(messages.unblock, { name: account.get('username') })} onClick={this.handleBlock} />;
buttons = <IconButton active icon='lock-open-simple' title={intl.formatMessage(messages.unblock, { name: account.get("username") })} onClick={this.handleBlock} />;
} else if (muting) {
let hidingNotificationsButton;
if (account.getIn(['relationship', 'muting_notifications'])) {
hidingNotificationsButton = <IconButton active icon='bell' title={intl.formatMessage(messages.unmute_notifications, { name: account.get('username') })} onClick={this.handleUnmuteNotifications} />;
if (account.getIn(["relationship", "muting_notifications"])) {
hidingNotificationsButton = <IconButton active icon='bell' title={intl.formatMessage(messages.unmute_notifications, { name: account.get("username") })} onClick={this.handleUnmuteNotifications} />;
} else {
hidingNotificationsButton = <IconButton active icon='bell-slash' title={intl.formatMessage(messages.mute_notifications, { name: account.get('username') })} onClick={this.handleMuteNotifications} />;
hidingNotificationsButton = <IconButton active icon='bell-slash' title={intl.formatMessage(messages.mute_notifications, { name: account.get("username") })} onClick={this.handleMuteNotifications} />;
}
buttons = (
<>
<IconButton active icon='volume-up' title={intl.formatMessage(messages.unmute, { name: account.get('username') })} onClick={this.handleMute} />
<IconButton active icon='speaker-high' title={intl.formatMessage(messages.unmute, { name: account.get("username") })} onClick={this.handleMute} />
{hidingNotificationsButton}
</>
);
} else if (defaultAction === 'mute') {
buttons = <IconButton icon='volume-off' title={intl.formatMessage(messages.mute, { name: account.get('username') })} onClick={this.handleMute} />;
} else if (defaultAction === 'block') {
buttons = <IconButton icon='lock' title={intl.formatMessage(messages.block, { name: account.get('username') })} onClick={this.handleBlock} />;
} else if (!account.get('moved') || following) {
buttons = <IconButton icon={following ? 'user-times' : 'user-plus'} title={intl.formatMessage(following ? messages.unfollow : messages.follow)} onClick={this.handleFollow} active={following} />;
} else if (defaultAction === "mute") {
buttons = <IconButton icon='speaker-slash' title={intl.formatMessage(messages.mute, { name: account.get("username") })} onClick={this.handleMute} />;
} else if (defaultAction === "block") {
buttons = <IconButton icon='lock-simple' title={intl.formatMessage(messages.block, { name: account.get("username") })} onClick={this.handleBlock} />;
} else if (!account.get("moved") || following) {
buttons = <IconButton icon={following ? "user-minus" : "user-plus"} title={intl.formatMessage(following ? messages.unfollow : messages.follow)} onClick={this.handleFollow} className={following ? "destructive" : ""} active={following} />;
}
}
let mute_expires_at;
if (account.get('mute_expires_at')) {
mute_expires_at = <div><RelativeTimestamp timestamp={account.get('mute_expires_at')} futureDate /></div>;
if (account.get("mute_expires_at")) {
mute_expires_at = <div><RelativeTimestamp timestamp={account.get("mute_expires_at")} futureDate /></div>;
}
return small ? (
<Permalink
className='account small'
href={account.get('url')}
to={`/@${account.get('acct')}`}
href={account.get("url")}
to={`/@${account.get("acct")}`}
>
<div className='account__avatar-wrapper'>
<Avatar
@@ -171,7 +171,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')}`}>
<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={size} /></div>
{mute_expires_at}
<DisplayName account={account} />
@@ -1,14 +1,14 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import PropTypes from "prop-types";
import { PureComponent } from "react";
import { FormattedNumber } from 'react-intl';
import { FormattedNumber } from "react-intl";
import classNames from 'classnames';
import classNames from "classnames";
import { Sparklines, SparklinesCurve } from 'react-sparklines';
import { Sparklines, SparklinesCurve } from "react-sparklines";
import api from 'flavours/glitch/api';
import { Skeleton } from 'flavours/glitch/components/skeleton';
import api from "flavours/glitch/api";
import { Skeleton } from "flavours/glitch/components/skeleton";
const percIncrease = (a, b) => {
let percent;
@@ -48,7 +48,7 @@ export default class Counter extends PureComponent {
componentDidMount () {
const { measure, start_at, end_at, params } = this.props;
api().post('/api/v1/admin/measures', { keys: [measure], start_at, end_at, [measure]: params }).then(res => {
api().post("/api/v1/admin/measures", { keys: [measure], start_at, end_at, [measure]: params }).then(res => {
this.setState({
loading: false,
data: res.data,
@@ -78,7 +78,7 @@ export default class Counter extends PureComponent {
content = (
<>
<span className='sparkline__value__total'>{measure.human_value || <FormattedNumber value={measure.total} />}</span>
{measure.previous_total && (<span className={classNames('sparkline__value__change', { positive: percentChange > 0, negative: percentChange < 0 })}>{percentChange > 0 && '+'}<FormattedNumber value={percentChange} style='percent' /></span>)}
{measure.previous_total && (<span className={classNames("sparkline__value__change", { positive: percentChange > 0, negative: percentChange < 0 })}>{percentChange > 0 && "+"}<FormattedNumber value={percentChange} style='percent' /></span>)}
</>
);
}
@@ -1,11 +1,11 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import PropTypes from "prop-types";
import { PureComponent } from "react";
import { FormattedNumber } from 'react-intl';
import { FormattedNumber } from "react-intl";
import api from 'flavours/glitch/api';
import { Skeleton } from 'flavours/glitch/components/skeleton';
import { roundTo10 } from 'flavours/glitch/utils/numbers';
import api from "flavours/glitch/api";
import { Skeleton } from "flavours/glitch/components/skeleton";
import { roundTo10 } from "flavours/glitch/utils/numbers";
export default class Dimension extends PureComponent {
@@ -26,7 +26,7 @@ export default class Dimension extends PureComponent {
componentDidMount () {
const { start_at, end_at, dimension, limit, params } = this.props;
api().post('/api/v1/admin/dimensions', { keys: [dimension], start_at, end_at, limit, [dimension]: params }).then(res => {
api().post("/api/v1/admin/dimensions", { keys: [dimension], start_at, end_at, limit, [dimension]: params }).then(res => {
this.setState({
loading: false,
data: res.data,
@@ -74,7 +74,7 @@ export default class Dimension extends PureComponent {
</td>
<td className='dimension__item__value'>
{typeof item.human_value !== 'undefined' ? item.human_value : <FormattedNumber value={item.value} />}
{typeof item.human_value !== "undefined" ? item.human_value : <FormattedNumber value={item.value} />}
</td>
</tr>
))}
@@ -1,12 +1,12 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import PropTypes from "prop-types";
import { PureComponent } from "react";
import { FormattedNumber, FormattedMessage } from 'react-intl';
import { FormattedNumber, FormattedMessage } from "react-intl";
import classNames from 'classnames';
import classNames from "classnames";
import api from 'flavours/glitch/api';
import { Skeleton } from 'flavours/glitch/components/skeleton';
import api from "flavours/glitch/api";
import { Skeleton } from "flavours/glitch/components/skeleton";
export default class ImpactReport extends PureComponent {
@@ -27,8 +27,8 @@ export default class ImpactReport extends PureComponent {
include_subdomains: true,
};
api().post('/api/v1/admin/measures', {
keys: ['instance_accounts', 'instance_follows', 'instance_followers'],
api().post("/api/v1/admin/measures", {
keys: ["instance_accounts", "instance_follows", "instance_followers"],
start_at: null,
end_at: null,
instance_accounts: params,
@@ -63,7 +63,7 @@ export default class ImpactReport extends PureComponent {
</td>
</tr>
<tr className={classNames('dimension__item', { negative: !loading && data[1].total > 0 })}>
<tr className={classNames("dimension__item", { negative: !loading && data[1].total > 0 })}>
<td className='dimension__item__key'>
<FormattedMessage id='admin.impact_report.instance_follows' defaultMessage='Followers their users would lose' />
</td>
@@ -73,7 +73,7 @@ export default class ImpactReport extends PureComponent {
</td>
</tr>
<tr className={classNames('dimension__item', { negative: !loading && data[2].total > 0 })}>
<tr className={classNames("dimension__item", { negative: !loading && data[2].total > 0 })}>
<td className='dimension__item__key'>
<FormattedMessage id='admin.impact_report.instance_followers' defaultMessage='Followers our users would lose' />
</td>
@@ -1,17 +1,17 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import PropTypes from "prop-types";
import { PureComponent } from "react";
import { injectIntl, defineMessages } from 'react-intl';
import { injectIntl, defineMessages } from "react-intl";
import classNames from 'classnames';
import classNames from "classnames";
import api from 'flavours/glitch/api';
import api from "flavours/glitch/api";
const messages = defineMessages({
legal: { id: 'report.categories.legal', defaultMessage: 'Legal' },
other: { id: 'report.categories.other', defaultMessage: 'Other' },
spam: { id: 'report.categories.spam', defaultMessage: 'Spam' },
violation: { id: 'report.categories.violation', defaultMessage: 'Content violates one or more server rules' },
legal: { id: "report.categories.legal", defaultMessage: "Legal" },
other: { id: "report.categories.other", defaultMessage: "Other" },
spam: { id: "report.categories.spam", defaultMessage: "Spam" },
violation: { id: "report.categories.violation", defaultMessage: "Content violates one or more server rules" },
});
class Category extends PureComponent {
@@ -37,11 +37,11 @@ class Category extends PureComponent {
const { id, text, disabled, selected, children } = this.props;
return (
<div tabIndex={0} role='button' className={classNames('report-reason-selector__category', { selected, disabled })} onClick={this.handleClick}>
<div tabIndex={0} role='button' className={classNames("report-reason-selector__category", { selected, disabled })} onClick={this.handleClick}>
{selected && <input type='hidden' name='report[category]' value={id} />}
<div className='report-reason-selector__category__label'>
<span className={classNames('poll__input', { active: selected, disabled })} />
<span className={classNames("poll__input", { active: selected, disabled })} />
{text}
</div>
@@ -78,8 +78,8 @@ class Rule extends PureComponent {
const { id, text, disabled, selected } = this.props;
return (
<div tabIndex={0} role='button' className={classNames('report-reason-selector__rule', { selected, disabled })} onClick={this.handleClick}>
<span className={classNames('poll__input', { checkbox: true, active: selected, disabled })} />
<div tabIndex={0} role='button' className={classNames("report-reason-selector__rule", { selected, disabled })} onClick={this.handleClick}>
<span className={classNames("poll__input", { checkbox: true, active: selected, disabled })} />
{selected && <input type='hidden' name='report[rule_ids][]' value={id} />}
{text}
</div>
@@ -105,7 +105,7 @@ class ReportReasonSelector extends PureComponent {
};
componentDidMount() {
api().get('/api/v1/instance').then(res => {
api().get("/api/v1/instance").then(res => {
this.setState({
rules: res.data.rules,
});
@@ -150,10 +150,10 @@ class ReportReasonSelector extends PureComponent {
return (
<div className='report-reason-selector'>
<Category id='other' text={intl.formatMessage(messages.other)} selected={category === 'other'} onSelect={this.handleSelect} disabled={disabled} />
<Category id='legal' text={intl.formatMessage(messages.legal)} selected={category === 'legal'} onSelect={this.handleSelect} disabled={disabled} />
<Category id='spam' text={intl.formatMessage(messages.spam)} selected={category === 'spam'} onSelect={this.handleSelect} disabled={disabled} />
<Category id='violation' text={intl.formatMessage(messages.violation)} selected={category === 'violation'} onSelect={this.handleSelect} disabled={disabled}>
<Category id='other' text={intl.formatMessage(messages.other)} selected={category === "other"} onSelect={this.handleSelect} disabled={disabled} />
<Category id='legal' text={intl.formatMessage(messages.legal)} selected={category === "legal"} onSelect={this.handleSelect} disabled={disabled} />
<Category id='spam' text={intl.formatMessage(messages.spam)} selected={category === "spam"} onSelect={this.handleSelect} disabled={disabled} />
<Category id='violation' text={intl.formatMessage(messages.violation)} selected={category === "violation"} onSelect={this.handleSelect} disabled={disabled}>
{rules.map(rule => <Rule key={rule.id} id={rule.id} text={rule.text} selected={rule_ids.includes(rule.id)} onToggle={this.handleToggle} disabled={disabled} />)}
</Category>
</div>
@@ -1,20 +1,20 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import PropTypes from "prop-types";
import { PureComponent } from "react";
import { FormattedMessage, FormattedNumber, FormattedDate } from 'react-intl';
import { FormattedMessage, FormattedNumber, FormattedDate } from "react-intl";
import classNames from 'classnames';
import classNames from "classnames";
import api from 'flavours/glitch/api';
import { roundTo10 } from 'flavours/glitch/utils/numbers';
import api from "flavours/glitch/api";
import { roundTo10 } from "flavours/glitch/utils/numbers";
const dateForCohort = cohort => {
const timeZone = 'UTC';
const timeZone = "UTC";
switch(cohort.frequency) {
case 'day':
return <FormattedDate value={cohort.period} month='long' day='2-digit' timeZone={timeZone} />;
default:
return <FormattedDate value={cohort.period} month='long' year='numeric' timeZone={timeZone} />;
case "day":
return <FormattedDate value={cohort.period} month='long' day='2-digit' timeZone={timeZone} />;
default:
return <FormattedDate value={cohort.period} month='long' year='numeric' timeZone={timeZone} />;
}
};
@@ -34,7 +34,7 @@ export default class Retention extends PureComponent {
componentDidMount () {
const { start_at, end_at, frequency } = this.props;
api().post('/api/v1/admin/retention', { start_at, end_at, frequency }).then(res => {
api().post("/api/v1/admin/retention", { start_at, end_at, frequency }).then(res => {
this.setState({
loading: false,
data: res.data,
@@ -96,7 +96,7 @@ export default class Retention extends PureComponent {
return (
<td key={retention.date}>
<div className={classNames('retention__table__box', 'retention__table__average', `retention__table__box--${roundTo10(average * 100)}`)}>
<div className={classNames("retention__table__box", "retention__table__average", `retention__table__box--${roundTo10(average * 100)}`)}>
<FormattedNumber value={average} style='percent' />
</div>
</td>
@@ -122,7 +122,7 @@ export default class Retention extends PureComponent {
{cohort.data.slice(1).map(retention => (
<td key={retention.date}>
<div className={classNames('retention__table__box', `retention__table__box--${roundTo10(retention.rate * 100)}`)}>
<div className={classNames("retention__table__box", `retention__table__box--${roundTo10(retention.rate * 100)}`)}>
<FormattedNumber value={retention.rate} style='percent' />
</div>
</td>
@@ -134,13 +134,13 @@ export default class Retention extends PureComponent {
);
}
let title = null;
let title;
switch(frequency) {
case 'day':
title = <FormattedMessage id='admin.dashboard.daily_retention' defaultMessage='User retention rate by day after sign-up' />;
break;
default:
title = <FormattedMessage id='admin.dashboard.monthly_retention' defaultMessage='User retention rate by month after sign-up' />;
case "day":
title = <FormattedMessage id='admin.dashboard.daily_retention' defaultMessage='User retention rate by day after sign-up' />;
break;
default:
title = <FormattedMessage id='admin.dashboard.monthly_retention' defaultMessage='User retention rate by month after sign-up' />;
}
return (
@@ -1,12 +1,12 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import PropTypes from "prop-types";
import { PureComponent } from "react";
import { FormattedMessage } from 'react-intl';
import { FormattedMessage } from "react-intl";
import classNames from 'classnames';
import classNames from "classnames";
import api from 'flavours/glitch/api';
import Hashtag from 'flavours/glitch/components/hashtag';
import api from "flavours/glitch/api";
import Hashtag from "flavours/glitch/components/hashtag";
export default class Trends extends PureComponent {
@@ -22,7 +22,7 @@ export default class Trends extends PureComponent {
componentDidMount () {
const { limit } = this.props;
api().get('/api/v1/admin/trends/tags', { params: { limit } }).then(res => {
api().get("/api/v1/admin/trends/tags", { params: { limit } }).then(res => {
this.setState({
loading: false,
data: res.data,
@@ -57,7 +57,7 @@ export default class Trends extends PureComponent {
people={hashtag.history[0].accounts * 1 + hashtag.history[1].accounts * 1}
uses={hashtag.history[0].uses * 1 + hashtag.history[1].uses * 1}
history={hashtag.history.reverse().map(day => day.uses)}
className={classNames(hashtag.requires_review && 'trends__item--requires-review', !hashtag.trendable && !hashtag.requires_review && 'trends__item--disabled')}
className={classNames(hashtag.requires_review && "trends__item--requires-review", !hashtag.trendable && !hashtag.requires_review && "trends__item--disabled")}
/>
))}
</div>
@@ -1,11 +1,11 @@
import { useCallback, useState } from 'react';
import * as React from 'react';
import { useCallback, useState } from "react";
import * as React from "react";
import { TransitionMotion, spring } from 'react-motion';
import { TransitionMotion, spring } from "react-motion";
import { reduceMotion } from '../initial_state';
import { reduceMotion } from "../initial_state";
import { ShortNumber } from './short_number';
import { ShortNumber } from "./short_number";
const obfuscatedCount = (count: number) => {
if (count < 0) {
@@ -13,13 +13,13 @@ const obfuscatedCount = (count: number) => {
} else if (count <= 1) {
return count;
} else {
return '1+';
return "1+";
}
};
interface Props {
value: number;
obfuscate?: boolean;
value: number,
obfuscate?: boolean,
}
export const AnimatedNumber: React.FC<Props> = ({ value, obfuscate }) => {
const [previousValue, setPreviousValue] = useState(value);
@@ -64,7 +64,7 @@ export const AnimatedNumber: React.FC<Props> = ({ value, obfuscate }) => {
<span
key={key}
style={{
position: direction * style.y > 0 ? 'absolute' : 'static',
position: direction * style.y > 0 ? "absolute" : "static",
transform: `translateY(${style.y * 100}%)`,
}}
>
@@ -1,15 +1,15 @@
import PropTypes from 'prop-types';
import PropTypes from "prop-types";
import { FormattedMessage } from 'react-intl';
import { FormattedMessage } from "react-intl";
import classNames from 'classnames';
import classNames from "classnames";
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import ImmutablePropTypes from "react-immutable-proptypes";
import ImmutablePureComponent from "react-immutable-pure-component";
import { Icon } from 'flavours/glitch/components/icon';
import { Icon } from "flavours/glitch/components/icon";
const filename = url => url.split('/').pop().split('#')[0].split('?')[0];
const filename = url => url.split("/").pop().split("#")[0].split("?")[0];
export default class AttachmentList extends ImmutablePureComponent {
@@ -22,7 +22,7 @@ export default class AttachmentList extends ImmutablePureComponent {
const { media, compact } = this.props;
return (
<div className={classNames('attachment-list', { compact })}>
<div className={classNames("attachment-list", { compact })}>
{!compact && (
<div className='attachment-list__icon'>
<Icon id='link' />
@@ -31,13 +31,13 @@ export default class AttachmentList extends ImmutablePureComponent {
<ul className='attachment-list__list'>
{media.map(attachment => {
const displayUrl = attachment.get('remote_url') || attachment.get('url');
const displayUrl = attachment.get("remote_url") || attachment.get("url");
return (
<li key={attachment.get('id')}>
<li key={attachment.get("id")}>
<a href={displayUrl} target='_blank' rel='noopener noreferrer'>
{compact && <Icon id='link' />}
{compact && ' ' }
{compact && " " }
{displayUrl ? filename(displayUrl) : <FormattedMessage id='attachments_list.unprocessed' defaultMessage='(unprocessed)' />}
</a>
</li>
@@ -1,8 +1,8 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import PropTypes from "prop-types";
import { PureComponent } from "react";
import unicodeMapping from 'flavours/glitch/features/emoji/emoji_unicode_mapping_light';
import { assetHost } from 'flavours/glitch/utils/config';
import unicodeMapping from "flavours/glitch/features/emoji/emoji_unicode_mapping_light";
import { assetHost } from "flavours/glitch/utils/config";
export default class AutosuggestEmoji extends PureComponent {
@@ -17,7 +17,7 @@ export default class AutosuggestEmoji extends PureComponent {
if (emoji.custom) {
url = emoji.imageUrl;
} else {
const mapping = unicodeMapping[emoji.native] || unicodeMapping[emoji.native.replace(/\uFE0F$/, '')];
const mapping = unicodeMapping[emoji.native] || unicodeMapping[emoji.native.replace(/\uFE0F$/, "")];
if (!mapping) {
return null;
@@ -1,19 +1,19 @@
import { FormattedMessage } from 'react-intl';
import { FormattedMessage } from "react-intl";
import { ShortNumber } from 'flavours/glitch/components/short_number';
import { ShortNumber } from "flavours/glitch/components/short_number";
interface Props {
tag: {
name: string;
url?: string;
name: string,
url?: string,
history?: {
uses: number;
accounts: string;
day: string;
}[];
following?: boolean;
type: 'hashtag';
};
uses: number,
accounts: string,
day: string,
}[],
following?: boolean,
type: "hashtag",
},
}
export const AutosuggestHashtag: React.FC<Props> = ({ tag }) => {
@@ -1,14 +1,14 @@
import PropTypes from 'prop-types';
import PropTypes from "prop-types";
import classNames from 'classnames';
import classNames from "classnames";
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import ImmutablePropTypes from "react-immutable-proptypes";
import ImmutablePureComponent from "react-immutable-pure-component";
import AutosuggestAccountContainer from 'flavours/glitch/features/compose/containers/autosuggest_account_container';
import AutosuggestAccountContainer from "flavours/glitch/features/compose/containers/autosuggest_account_container";
import AutosuggestEmoji from './autosuggest_emoji';
import { AutosuggestHashtag } from './autosuggest_hashtag';
import AutosuggestEmoji from "./autosuggest_emoji";
import { AutosuggestHashtag } from "./autosuggest_hashtag";
const textAtCursorMatchesToken = (str, caretPosition, searchTokens) => {
let word;
@@ -59,7 +59,7 @@ export default class AutosuggestInput extends ImmutablePureComponent {
static defaultProps = {
autoFocus: true,
searchTokens: ['@', ':', '#'],
searchTokens: ["@", ":", "#"],
};
state = {
@@ -100,39 +100,39 @@ export default class AutosuggestInput extends ImmutablePureComponent {
}
switch(e.key) {
case 'Escape':
if (suggestions.size === 0 || suggestionsHidden) {
document.querySelector('.ui').parentElement.focus();
} else {
e.preventDefault();
this.setState({ suggestionsHidden: true });
}
case "Escape":
if (suggestions.size === 0 || suggestionsHidden) {
document.querySelector(".ui").parentElement.focus();
} else {
e.preventDefault();
this.setState({ suggestionsHidden: true });
}
break;
case 'ArrowDown':
if (suggestions.size > 0 && !suggestionsHidden) {
e.preventDefault();
this.setState({ selectedSuggestion: Math.min(selectedSuggestion + 1, suggestions.size - 1) });
}
break;
case "ArrowDown":
if (suggestions.size > 0 && !suggestionsHidden) {
e.preventDefault();
this.setState({ selectedSuggestion: Math.min(selectedSuggestion + 1, suggestions.size - 1) });
}
break;
case 'ArrowUp':
if (suggestions.size > 0 && !suggestionsHidden) {
e.preventDefault();
this.setState({ selectedSuggestion: Math.max(selectedSuggestion - 1, 0) });
}
break;
case "ArrowUp":
if (suggestions.size > 0 && !suggestionsHidden) {
e.preventDefault();
this.setState({ selectedSuggestion: Math.max(selectedSuggestion - 1, 0) });
}
break;
case 'Enter':
case 'Tab':
break;
case "Enter":
case "Tab":
// Select suggestion
if (this.state.lastToken !== null && suggestions.size > 0 && !suggestionsHidden) {
e.preventDefault();
e.stopPropagation();
this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestions.get(selectedSuggestion));
}
if (this.state.lastToken !== null && suggestions.size > 0 && !suggestionsHidden) {
e.preventDefault();
e.stopPropagation();
this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestions.get(selectedSuggestion));
}
break;
break;
}
if (e.defaultPrevented || !this.props.onKeyDown) {
@@ -151,7 +151,7 @@ export default class AutosuggestInput extends ImmutablePureComponent {
};
onSuggestionClick = (e) => {
const suggestion = this.props.suggestions.get(e.currentTarget.getAttribute('data-index'));
const suggestion = this.props.suggestions.get(e.currentTarget.getAttribute("data-index"));
e.preventDefault();
this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestion);
this.input.focus();
@@ -171,19 +171,19 @@ export default class AutosuggestInput extends ImmutablePureComponent {
const { selectedSuggestion } = this.state;
let inner, key;
if (suggestion.type === 'emoji') {
if (suggestion.type === "emoji") {
inner = <AutosuggestEmoji emoji={suggestion} />;
key = suggestion.id;
} else if (suggestion.type ==='hashtag') {
} else if (suggestion.type ==="hashtag") {
inner = <AutosuggestHashtag tag={suggestion} />;
key = suggestion.name;
} else if (suggestion.type === 'account') {
} else if (suggestion.type === "account") {
inner = <AutosuggestAccountContainer id={suggestion.id} />;
key = suggestion.id;
}
return (
<div role='button' tabIndex={0} key={key} data-index={i} className={classNames('autosuggest-textarea__suggestions__item', { selected: i === selectedSuggestion })} onMouseDown={this.onSuggestionClick}>
<div role='button' tabIndex={0} key={key} data-index={i} className={classNames("autosuggest-textarea__suggestions__item", { selected: i === selectedSuggestion })} onMouseDown={this.onSuggestionClick}>
{inner}
</div>
);
@@ -196,7 +196,7 @@ export default class AutosuggestInput extends ImmutablePureComponent {
return (
<div className='autosuggest-input'>
<label>
<span style={{ display: 'none' }}>{placeholder}</span>
<span style={{ display: "none" }}>{placeholder}</span>
<input
type='text'
@@ -220,7 +220,7 @@ export default class AutosuggestInput extends ImmutablePureComponent {
/>
</label>
<div className={`autosuggest-textarea__suggestions ${suggestionsHidden || suggestions.isEmpty() ? '' : 'autosuggest-textarea__suggestions--visible'}`}>
<div className={`autosuggest-textarea__suggestions ${suggestionsHidden || suggestions.isEmpty() ? "" : "autosuggest-textarea__suggestions--visible"}`}>
{suggestions.map(this.renderSuggestion)}
</div>
</div>
@@ -1,16 +1,16 @@
import PropTypes from 'prop-types';
import PropTypes from "prop-types";
import classNames from 'classnames';
import classNames from "classnames";
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import ImmutablePropTypes from "react-immutable-proptypes";
import ImmutablePureComponent from "react-immutable-pure-component";
import Textarea from 'react-textarea-autosize';
import Textarea from "react-textarea-autosize";
import AutosuggestAccountContainer from 'flavours/glitch/features/compose/containers/autosuggest_account_container';
import AutosuggestAccountContainer from "flavours/glitch/features/compose/containers/autosuggest_account_container";
import AutosuggestEmoji from './autosuggest_emoji';
import { AutosuggestHashtag } from './autosuggest_hashtag';
import AutosuggestEmoji from "./autosuggest_emoji";
import { AutosuggestHashtag } from "./autosuggest_hashtag";
const textAtCursorMatchesToken = (str, caretPosition) => {
let word;
@@ -24,7 +24,7 @@ const textAtCursorMatchesToken = (str, caretPosition) => {
word = str.slice(left, right + caretPosition);
}
if (!word || word.trim().length < 3 || ['@', ':', '#'].indexOf(word[0]) === -1) {
if (!word || word.trim().length < 3 || ["@", ":", "#"].indexOf(word[0]) === -1) {
return [null, null];
}
@@ -97,39 +97,39 @@ export default class AutosuggestTextarea extends ImmutablePureComponent {
}
switch(e.key) {
case 'Escape':
if (suggestions.size === 0 || suggestionsHidden) {
document.querySelector('.ui').parentElement.focus();
} else {
e.preventDefault();
this.setState({ suggestionsHidden: true });
}
case "Escape":
if (suggestions.size === 0 || suggestionsHidden) {
document.querySelector(".ui").parentElement.focus();
} else {
e.preventDefault();
this.setState({ suggestionsHidden: true });
}
break;
case 'ArrowDown':
if (suggestions.size > 0 && !suggestionsHidden) {
e.preventDefault();
this.setState({ selectedSuggestion: Math.min(selectedSuggestion + 1, suggestions.size - 1) });
}
break;
case "ArrowDown":
if (suggestions.size > 0 && !suggestionsHidden) {
e.preventDefault();
this.setState({ selectedSuggestion: Math.min(selectedSuggestion + 1, suggestions.size - 1) });
}
break;
case 'ArrowUp':
if (suggestions.size > 0 && !suggestionsHidden) {
e.preventDefault();
this.setState({ selectedSuggestion: Math.max(selectedSuggestion - 1, 0) });
}
break;
case "ArrowUp":
if (suggestions.size > 0 && !suggestionsHidden) {
e.preventDefault();
this.setState({ selectedSuggestion: Math.max(selectedSuggestion - 1, 0) });
}
break;
case 'Enter':
case 'Tab':
break;
case "Enter":
case "Tab":
// Select suggestion
if (this.state.lastToken !== null && suggestions.size > 0 && !suggestionsHidden) {
e.preventDefault();
e.stopPropagation();
this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestions.get(selectedSuggestion));
}
if (this.state.lastToken !== null && suggestions.size > 0 && !suggestionsHidden) {
e.preventDefault();
e.stopPropagation();
this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestions.get(selectedSuggestion));
}
break;
break;
}
if (e.defaultPrevented || !this.props.onKeyDown) {
@@ -151,7 +151,7 @@ export default class AutosuggestTextarea extends ImmutablePureComponent {
};
onSuggestionClick = (e) => {
const suggestion = this.props.suggestions.get(e.currentTarget.getAttribute('data-index'));
const suggestion = this.props.suggestions.get(e.currentTarget.getAttribute("data-index"));
e.preventDefault();
this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestion);
this.textarea.focus();
@@ -178,19 +178,19 @@ export default class AutosuggestTextarea extends ImmutablePureComponent {
const { selectedSuggestion } = this.state;
let inner, key;
if (suggestion.type === 'emoji') {
if (suggestion.type === "emoji") {
inner = <AutosuggestEmoji emoji={suggestion} />;
key = suggestion.id;
} else if (suggestion.type === 'hashtag') {
} else if (suggestion.type === "hashtag") {
inner = <AutosuggestHashtag tag={suggestion} />;
key = suggestion.name;
} else if (suggestion.type === 'account') {
} else if (suggestion.type === "account") {
inner = <AutosuggestAccountContainer id={suggestion.id} />;
key = suggestion.id;
}
return (
<div role='button' tabIndex={0} key={key} data-index={i} className={classNames('autosuggest-textarea__suggestions__item', { selected: i === selectedSuggestion })} onMouseDown={this.onSuggestionClick}>
<div role='button' tabIndex={0} key={key} data-index={i} className={classNames("autosuggest-textarea__suggestions__item", { selected: i === selectedSuggestion })} onMouseDown={this.onSuggestionClick}>
{inner}
</div>
);
@@ -204,7 +204,7 @@ export default class AutosuggestTextarea extends ImmutablePureComponent {
<div className='compose-form__autosuggest-wrapper' key='autosuggest-wrapper'>
<div className='autosuggest-textarea'>
<label>
<span style={{ display: 'none' }}>{placeholder}</span>
<span style={{ display: "none" }}>{placeholder}</span>
<Textarea
ref={this.setTextarea}
@@ -229,7 +229,7 @@ export default class AutosuggestTextarea extends ImmutablePureComponent {
</div>,
<div className='autosuggest-textarea__suggestions-wrapper' key='suggestions-wrapper'>
<div className={`autosuggest-textarea__suggestions ${suggestionsHidden || suggestions.isEmpty() ? '' : 'autosuggest-textarea__suggestions--visible'}`}>
<div className={`autosuggest-textarea__suggestions ${suggestionsHidden || suggestions.isEmpty() ? "" : "autosuggest-textarea__suggestions--visible"}`}>
{suggestions.map(this.renderSuggestion)}
</div>
</div>,
@@ -1,17 +1,17 @@
import * as React from 'react';
import * as React from "react";
import classNames from 'classnames';
import classNames from "classnames";
import { useHovering } from 'flavours/glitch/hooks/useHovering';
import { autoPlayGif } from 'flavours/glitch/initial_state';
import type { Account } from 'flavours/glitch/types/resources';
import { useHovering } from "flavours/glitch/hooks/useHovering";
import { autoPlayGif } from "flavours/glitch/initial_state";
import { type Account } from "flavours/glitch/types/resources";
interface Props {
account: Account | undefined;
className?: string;
size: number;
style?: React.CSSProperties;
inline?: boolean;
account: Account | undefined,
className?: string,
size: number,
style?: React.CSSProperties,
inline?: boolean,
}
export const Avatar: React.FC<Props> = ({
@@ -28,28 +28,29 @@ export const Avatar: React.FC<Props> = ({
...styleFromParent,
width: `${size}px`,
height: `${size}px`,
backgroundSize: `${size}px ${size}px`,
backgroundSize: "cover",
backgroundPosition: "center",
};
if (account) {
style.backgroundImage = `url(${account.get(
hovering ? 'avatar' : 'avatar_static',
hovering ? "avatar" : "avatar_static",
)})`;
}
return (
<div
className={classNames(
'account__avatar',
{ 'account__avatar-inline': inline },
"account__avatar",
{ "account__avatar-inline": inline },
className,
)}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
style={style}
data-avatar-of={account && `@${account.get('acct')}`}
data-avatar-of={account && `@${account.get("acct")}`}
role='img'
aria-label={account?.get('acct')}
aria-label={account?.get("acct")}
/>
);
};
@@ -1,9 +1,9 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import PropTypes from "prop-types";
import { PureComponent } from "react";
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePropTypes from "react-immutable-proptypes";
import { autoPlayGif } from 'flavours/glitch/initial_state';
import { autoPlayGif } from "flavours/glitch/initial_state";
export default class AvatarComposite extends PureComponent {
@@ -22,10 +22,10 @@ export default class AvatarComposite extends PureComponent {
let width = 50;
let height = 100;
let top = 'auto';
let left = 'auto';
let bottom = 'auto';
let right = 'auto';
let top = "auto";
let left = "auto";
let bottom = "auto";
let right = "auto";
if (size === 1) {
width = 100;
@@ -37,35 +37,35 @@ export default class AvatarComposite extends PureComponent {
if (size === 2) {
if (index === 0) {
right = '1px';
right = "1px";
} else {
left = '1px';
left = "1px";
}
} else if (size === 3) {
if (index === 0) {
right = '1px';
right = "1px";
} else if (index > 0) {
left = '1px';
left = "1px";
}
if (index === 1) {
bottom = '1px';
bottom = "1px";
} else if (index > 1) {
top = '1px';
top = "1px";
}
} else if (size === 4) {
if (index === 0 || index === 2) {
right = '1px';
right = "1px";
}
if (index === 1 || index === 3) {
left = '1px';
left = "1px";
}
if (index < 2) {
bottom = '1px';
bottom = "1px";
} else {
top = '1px';
top = "1px";
}
}
@@ -76,12 +76,12 @@ export default class AvatarComposite extends PureComponent {
bottom: bottom,
width: `${width}%`,
height: `${height}%`,
backgroundSize: 'cover',
backgroundImage: `url(${account.get(animate ? 'avatar' : 'avatar_static')})`,
backgroundSize: "cover",
backgroundImage: `url(${account.get(animate ? "avatar" : "avatar_static")})`,
};
return (
<div key={account.get('id')} style={style} data-avatar-of={`@${account.get('acct')}`} />
<div key={account.get("id")} style={style} data-avatar-of={`@${account.get("acct")}`} />
);
}
@@ -1,9 +1,9 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import PropTypes from "prop-types";
import { PureComponent } from "react";
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePropTypes from "react-immutable-proptypes";
import { autoPlayGif } from 'flavours/glitch/initial_state';
import { autoPlayGif } from "flavours/glitch/initial_state";
export default class AvatarOverlay extends PureComponent {
@@ -21,17 +21,17 @@ export default class AvatarOverlay extends PureComponent {
const { account, friend, animate } = this.props;
const baseStyle = {
backgroundImage: `url(${account.get(animate ? 'avatar' : 'avatar_static')})`,
backgroundImage: `url(${account.get(animate ? "avatar" : "avatar_static")})`,
};
const overlayStyle = {
backgroundImage: `url(${friend.get(animate ? 'avatar' : 'avatar_static')})`,
backgroundImage: `url(${friend.get(animate ? "avatar" : "avatar_static")})`,
};
return (
<div className='account__avatar-overlay'>
<div className='account__avatar-overlay-base' style={baseStyle} data-avatar-of={`@${account.get('acct')}`} />
<div className='account__avatar-overlay-overlay' style={overlayStyle} data-avatar-of={`@${friend.get('acct')}`} />
<div className='account__avatar-overlay-base' style={baseStyle} data-avatar-of={`@${account.get("acct")}`} />
<div className='account__avatar-overlay-overlay' style={overlayStyle} data-avatar-of={`@${friend.get("acct")}`} />
</div>
);
}
@@ -1,14 +1,14 @@
import { useRef, useEffect } from 'react';
import * as React from 'react';
import { useRef, useEffect } from "react";
import * as React from "react";
import { decode } from 'blurhash';
import { decode } from "blurhash";
interface Props extends React.HTMLAttributes<HTMLCanvasElement> {
hash: string;
width?: number;
height?: number;
dummy?: boolean; // Whether dummy mode is enabled. If enabled, nothing is rendered and canvas left untouched
children?: never;
hash: string,
width?: number,
height?: number,
dummy?: boolean, // Whether dummy mode is enabled. If enabled, nothing is rendered and canvas left untouched
children?: never,
}
const Blurhash: React.FC<Props> = ({
hash,
@@ -26,16 +26,18 @@ const Blurhash: React.FC<Props> = ({
// eslint-disable-next-line no-self-assign
canvas.width = canvas.width; // resets canvas
if (dummy || !hash) return;
if (dummy || !hash) {
return;
}
try {
const pixels = decode(hash, width, height);
const ctx = canvas.getContext('2d');
const ctx = canvas.getContext("2d");
const imageData = new ImageData(pixels, width, height);
ctx?.putImageData(imageData, 0, 0);
} catch (err) {
console.error('Blurhash decoding failure', { err, hash });
console.error("Blurhash decoding failure", { err, hash });
}
}, [dummy, hash, width, height]);
@@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import PropTypes from "prop-types";
import { PureComponent } from "react";
import classNames from 'classnames';
import classNames from "classnames";
export default class Button extends PureComponent {
@@ -32,16 +32,18 @@ export default class Button extends PureComponent {
render () {
let attrs = {
className: classNames('button', this.props.className, {
'button-secondary': this.props.secondary,
'button--block': this.props.block,
className: classNames("button", this.props.className, {
"button-secondary": this.props.secondary,
"button--block": this.props.block,
}),
disabled: this.props.disabled,
onClick: this.handleClick,
ref: this.setRef,
};
if (this.props.title) attrs.title = this.props.title;
if (this.props.title) {
attrs.title = this.props.title;
}
return (
<button {...attrs}>
@@ -1,6 +1,6 @@
interface Props {
size: number;
strokeWidth: number;
size: number,
strokeWidth: number,
}
export const CircularProgress: React.FC<Props> = ({ size, strokeWidth }) => {
@@ -1,9 +1,9 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import PropTypes from "prop-types";
import { PureComponent } from "react";
import { supportsPassiveEvents } from 'detect-passive-events';
import { supportsPassiveEvents } from "detect-passive-events";
import { scrollTop } from '../scroll';
import { scrollTop } from "../scroll";
const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
@@ -23,12 +23,12 @@ export default class Column extends PureComponent {
if (this.props.bindToDocument) {
scrollable = document.scrollingElement;
} else {
scrollable = this.node.querySelector('.scrollable');
scrollable = this.node.querySelector(".scrollable");
// Some columns have nested `.scrollable` containers, with the outer one
// being a wrapper while the actual scrollable content is deeper.
if (scrollable.classList.contains('scrollable--flex')) {
scrollable = scrollable?.querySelector('.scrollable') || scrollable;
if (scrollable.classList.contains("scrollable--flex")) {
scrollable = scrollable?.querySelector(".scrollable") || scrollable;
}
}
@@ -40,7 +40,7 @@ export default class Column extends PureComponent {
}
handleWheel = () => {
if (typeof this._interruptScrollAnimation !== 'function') {
if (typeof this._interruptScrollAnimation !== "function") {
return;
}
@@ -53,17 +53,17 @@ export default class Column extends PureComponent {
componentDidMount () {
if (this.props.bindToDocument) {
document.addEventListener('wheel', this.handleWheel, listenerOptions);
document.addEventListener("wheel", this.handleWheel, listenerOptions);
} else {
this.node.addEventListener('wheel', this.handleWheel, listenerOptions);
this.node.addEventListener("wheel", this.handleWheel, listenerOptions);
}
}
componentWillUnmount () {
if (this.props.bindToDocument) {
document.removeEventListener('wheel', this.handleWheel, listenerOptions);
document.removeEventListener("wheel", this.handleWheel, listenerOptions);
} else {
this.node.removeEventListener('wheel', this.handleWheel, listenerOptions);
this.node.removeEventListener("wheel", this.handleWheel, listenerOptions);
}
}
@@ -71,7 +71,7 @@ export default class Column extends PureComponent {
const { children, extraClasses, name, label } = this.props;
return (
<div role='region' aria-label={label} data-column={name} className={`column ${extraClasses || ''}`} ref={this.setRef}>
<div role='region' aria-label={label} data-column={name} className={`column ${extraClasses || ""}`} ref={this.setRef}>
{children}
</div>
);
@@ -1,10 +1,10 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import { createPortal } from 'react-dom';
import PropTypes from "prop-types";
import { PureComponent } from "react";
import { createPortal } from "react-dom";
import { FormattedMessage } from 'react-intl';
import { FormattedMessage } from "react-intl";
import { Icon } from 'flavours/glitch/components/icon';
import { Icon } from "flavours/glitch/components/icon";
export default class ColumnBackButton extends PureComponent {
@@ -23,7 +23,7 @@ export default class ColumnBackButton extends PureComponent {
if (router.history.location?.state?.fromMastodon) {
router.history.goBack();
} else {
router.history.push('/');
router.history.push("/");
}
};
@@ -32,7 +32,7 @@ export default class ColumnBackButton extends PureComponent {
const component = (
<button onClick={this.handleClick} className='column-back-button'>
<Icon id='chevron-left' className='column-back-button__icon' fixedWidth />
<Icon id='arrow-left' className='column-back-button__icon' fixedWidth />
<FormattedMessage id='column_back_button.label' defaultMessage='Back' />
</button>
);
@@ -43,7 +43,7 @@ export default class ColumnBackButton extends PureComponent {
// The portal container and the component may be rendered to the DOM in
// the same React render pass, so the container might not be available at
// the time `render()` is called.
const container = document.getElementById('tabs-bar__portal');
const container = document.getElementById("tabs-bar__portal");
if (container === null) {
// The container wasn't available, force a re-render so that the
// component can eventually be inserted in the container and not scroll
@@ -1,9 +1,9 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import PropTypes from "prop-types";
import { PureComponent } from "react";
import { FormattedMessage } from 'react-intl';
import { FormattedMessage } from "react-intl";
import { Icon } from 'flavours/glitch/components/icon';
import { Icon } from "flavours/glitch/components/icon";
export default class ColumnBackButtonSlim extends PureComponent {
@@ -19,7 +19,7 @@ export default class ColumnBackButtonSlim extends PureComponent {
if (router.route.location.key) {
router.history.goBack();
} else {
router.history.push('/');
router.history.push("/");
}
};
@@ -27,7 +27,7 @@ export default class ColumnBackButtonSlim extends PureComponent {
return (
<div className='column-back-button--slim'>
<div role='button' tabIndex={0} onClick={this.handleClick} className='column-back-button column-back-button--slim-button'>
<Icon id='chevron-left' className='column-back-button__icon' fixedWidth />
<Icon id='arrow-left' className='column-back-button__icon' fixedWidth />
<FormattedMessage id='column_back_button.label' defaultMessage='Back' />
</div>
</div>
@@ -1,18 +1,19 @@
import PropTypes from 'prop-types';
import { PureComponent } from 'react';
import { createPortal } from 'react-dom';
import PropTypes from "prop-types";
import { PureComponent } from "react";
import { createPortal } from "react-dom";
import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
import { FormattedMessage, injectIntl, defineMessages } from "react-intl";
import classNames from 'classnames';
import classNames from "classnames";
import { Icon } from 'flavours/glitch/components/icon';
import { Icon } from "flavours/glitch/components/icon";
import { IconButton } from "flavours/glitch/components/icon_button";
const messages = defineMessages({
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
hide: { id: 'column_header.hide_settings', defaultMessage: 'Hide settings' },
moveLeft: { id: 'column_header.moveLeft_settings', defaultMessage: 'Move column to the left' },
moveRight: { id: 'column_header.moveRight_settings', defaultMessage: 'Move column to the right' },
show: { id: "column_header.show_settings", defaultMessage: "Show settings" },
hide: { id: "column_header.hide_settings", defaultMessage: "Hide settings" },
moveLeft: { id: "column_header.moveLeft_settings", defaultMessage: "Move column to the left" },
moveRight: { id: "column_header.moveRight_settings", defaultMessage: "Move column to the right" },
});
class ColumnHeader extends PureComponent {
@@ -68,7 +69,7 @@ class ColumnHeader extends PureComponent {
if (router.history.location?.state?.fromMastodon) {
router.history.goBack();
} else {
router.history.push('/');
router.history.push("/");
}
};
@@ -78,7 +79,7 @@ class ColumnHeader extends PureComponent {
handlePin = () => {
if (!this.props.pinned) {
this.context.router.history.replace('/');
this.context.router.history.replace("/");
}
this.props.onPin();
@@ -89,21 +90,21 @@ class ColumnHeader extends PureComponent {
const { title, icon, active, children, pinned, multiColumn, extraButton, showBackButton, intl: { formatMessage }, placeholder, appendContent, collapseIssues } = this.props;
const { collapsed, animating } = this.state;
const wrapperClassName = classNames('column-header__wrapper', {
'active': active,
const wrapperClassName = classNames("column-header__wrapper", {
"active": active,
});
const buttonClassName = classNames('column-header', {
'active': active,
const buttonClassName = classNames("column-header", {
"active": active,
});
const collapsibleClassName = classNames('column-header__collapsible', {
'collapsed': collapsed,
'animating': animating,
const collapsibleClassName = classNames("column-header__collapsible", {
"collapsed": collapsed,
"animating": animating,
});
const collapsibleButtonClassName = classNames('column-header__button', {
'active': !collapsed,
const collapsibleButtonClassName = classNames("column-header__button", {
"active": !collapsed,
});
let extraContent, pinButton, moveButtons, backButton, collapseButton;
@@ -117,34 +118,39 @@ class ColumnHeader extends PureComponent {
}
if (multiColumn && pinned) {
pinButton = <button key='pin-button' className='text-btn column-header__setting-btn' onClick={this.handlePin}><Icon id='times' /> <FormattedMessage id='column_header.unpin' defaultMessage='Unpin' /></button>;
pinButton = (<IconButton key='pin-button' onClick={this.handlePin} className='column-header__footer-button' label='Unpin' icon='push-pin-slash' title={formatMessage({id: "column_header.unpin", defaultMessage: "Unpin"})} />);
moveButtons = (
<div key='move-buttons' className='column-header__setting-arrows'>
<button title={formatMessage(messages.moveLeft)} aria-label={formatMessage(messages.moveLeft)} className='icon-button column-header__setting-btn' onClick={this.handleMoveLeft}><Icon id='chevron-left' /></button>
<button title={formatMessage(messages.moveRight)} aria-label={formatMessage(messages.moveRight)} className='icon-button column-header__setting-btn' onClick={this.handleMoveRight}><Icon id='chevron-right' /></button>
<div key='move-buttons' className='column-header__footer-arrows'>
<button title={formatMessage(messages.moveLeft)} aria-label={formatMessage(messages.moveLeft)} className='column-header__footer-button' onClick={this.handleMoveLeft}><Icon id='caret-left' /></button>
<button title={formatMessage(messages.moveRight)} aria-label={formatMessage(messages.moveRight)} className='column-header__footer-button' onClick={this.handleMoveRight}><Icon id='caret-right' /></button>
</div>
);
} else if (multiColumn && this.props.onPin) {
pinButton = <button key='pin-button' className='text-btn column-header__setting-btn' onClick={this.handlePin}><Icon id='plus' /> <FormattedMessage id='column_header.pin' defaultMessage='Pin' /></button>;
pinButton = (<IconButton key='pin-button' onClick={this.handlePin} className='column-header__footer-button' label='Pin' icon='push-pin' title={formatMessage({id: "column_header.pin", defaultMessage: "Pin"})} />);
}
if (!pinned && ((multiColumn && router.history.location?.state?.fromMastodon) || showBackButton)) {
backButton = (
<button onClick={this.handleBackClick} className='column-header__back-button'>
<Icon id='chevron-left' className='column-back-button__icon' fixedWidth />
<Icon id='arrow-left' className='column-back-button__icon' fixedWidth />
<FormattedMessage id='column_back_button.label' defaultMessage='Back' />
</button>
);
}
const columnHeaderFooter = (
<div className='column-header__footer'>
{pinButton} {moveButtons}
</div>
);
const collapsedContent = [
extraContent,
];
if (multiColumn) {
collapsedContent.push(pinButton);
collapsedContent.push(moveButtons);
collapsedContent.push(columnHeaderFooter);
}
if (this.context.identity.signedIn && (children || (multiColumn && this.props.onPin))) {
@@ -155,10 +161,10 @@ class ColumnHeader extends PureComponent {
aria-label={formatMessage(collapsed ? messages.show : messages.hide)}
onClick={this.handleToggleClick}
>
<i className='icon-with-badge'>
<Icon id='sliders' />
{collapseIssues && <i className='icon-with-badge__issue-badge' />}
</i>
<div className='gts-icon-with-badge'>
<Icon id='slider-horizontal' />
{collapseIssues && <i className='gts-icon-with-badge__issue-badge' />}
</div>
</button>
);
}
@@ -200,7 +206,7 @@ class ColumnHeader extends PureComponent {
// The portal container and the component may be rendered to the DOM in
// the same React render pass, so the container might not be available at
// the time `render()` is called.
const container = document.getElementById('tabs-bar__portal');
const container = document.getElementById("tabs-bar__portal");
if (container === null) {
// The container wasn't available, force a re-render so that the
// component can eventually be inserted in the container and not scroll
@@ -1,6 +1,6 @@
import React from 'react';
import React from "react";
import { FormattedMessage } from 'react-intl';
import { FormattedMessage } from "react-intl";
export const StatusesCounter = (
displayNumber: React.ReactNode,
@@ -1,18 +1,18 @@
import type { PropsWithChildren } from 'react';
import { useCallback, useState } from 'react';
import { type PropsWithChildren } from "react";
import { useCallback, useState } from "react";
import { defineMessages, useIntl } from 'react-intl';
import { defineMessages, useIntl } from "react-intl";
import { bannerSettings } from 'flavours/glitch/settings';
import { bannerSettings } from "flavours/glitch/settings";
import { IconButton } from './icon_button';
import { IconButton } from "./icon_button";
const messages = defineMessages({
dismiss: { id: 'dismissable_banner.dismiss', defaultMessage: 'Dismiss' },
dismiss: { id: "dismissable_banner.dismiss", defaultMessage: "Dismiss" },
});
interface Props {
id: string;
id: string,
}
export const DismissableBanner: React.FC<PropsWithChildren<Props>> = ({
@@ -35,7 +35,8 @@ export const DismissableBanner: React.FC<PropsWithChildren<Props>> = ({
<div className='dismissable-banner'>
<div className='dismissable-banner__action'>
<IconButton
icon='times'
icon='x'
className='dismissable-banner__action-button'
title={intl.formatMessage(messages.dismiss)}
onClick={handleDismiss}
/>
@@ -1,20 +1,20 @@
import React from 'react';
import React from "react";
import classNames from 'classnames';
import classNames from "classnames";
import type { List } from 'immutable';
import { type List } from "immutable";
import type { Account } from 'flavours/glitch/types/resources';
import { type Account } from "flavours/glitch/types/resources";
import { autoPlayGif } from '../initial_state';
import { autoPlayGif } from "../initial_state";
import { Skeleton } from './skeleton';
import { Skeleton } from "./skeleton";
interface Props {
account?: Account;
others?: List<Account>;
localDomain?: string;
inline?: boolean;
account?: Account,
others?: List<Account>,
localDomain?: string,
inline?: boolean,
}
export class DisplayName extends React.PureComponent<Props> {
@@ -26,11 +26,13 @@ export class DisplayName extends React.PureComponent<Props> {
}
const emojis =
currentTarget.querySelectorAll<HTMLImageElement>('img.custom-emoji');
currentTarget.querySelectorAll<HTMLImageElement>("img.custom-emoji");
emojis.forEach((emoji) => {
const originalSrc = emoji.getAttribute('data-original');
if (originalSrc != null) emoji.src = originalSrc;
const originalSrc = emoji.getAttribute("data-original");
if (originalSrc != null) {
emoji.src = originalSrc;
}
});
};
@@ -42,11 +44,13 @@ export class DisplayName extends React.PureComponent<Props> {
}
const emojis =
currentTarget.querySelectorAll<HTMLImageElement>('img.custom-emoji');
currentTarget.querySelectorAll<HTMLImageElement>("img.custom-emoji");
emojis.forEach((emoji) => {
const staticSrc = emoji.getAttribute('data-static');
if (staticSrc != null) emoji.src = staticSrc;
const staticSrc = emoji.getAttribute("data-static");
if (staticSrc != null) {
emoji.src = staticSrc;
}
});
};
@@ -67,22 +71,22 @@ export class DisplayName extends React.PureComponent<Props> {
displayName = others
.take(2)
.map((a) => (
<bdi key={a.get('id')}>
<bdi key={a.get("id")}>
<strong
className='display-name__html'
dangerouslySetInnerHTML={{ __html: a.get('display_name_html') }}
dangerouslySetInnerHTML={{ __html: a.get("display_name_html") }}
/>
</bdi>
))
.reduce((prev, cur) => [prev, ', ', cur]);
.reduce((prev, cur) => [prev, ", ", cur]);
if (others.size - 2 > 0) {
suffix = `+${others.size - 2}`;
}
} else if (account) {
let acct = account.get('acct');
let acct = account.get("acct");
if (!acct.includes('@') && localDomain) {
if (!acct.includes("@") && localDomain) {
acct = `${acct}@${localDomain}`;
}
@@ -91,7 +95,7 @@ export class DisplayName extends React.PureComponent<Props> {
<strong
className='display-name__html'
dangerouslySetInnerHTML={{
__html: account.get('display_name_html'),
__html: account.get("display_name_html"),
}}
/>
</bdi>
@@ -114,12 +118,12 @@ export class DisplayName extends React.PureComponent<Props> {
return (
<span
className={classNames('display-name', { inline })}
className={classNames("display-name", { inline })}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
>
{displayName}
{inline ? ' ' : null}
{inline ? " " : null}
{suffix}
</span>
);

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