diff --git a/README.md b/README.md index 07ba0d7a72..754e68d4c4 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,8 @@ busybox unzip soapbox.zip -o -d /opt/pleroma/instance The change will take effect immediately, just refresh your browser tab. It's not necessary to restart the Pleroma service. +***For OTP releases,*** *unpack to /var/lib/pleroma instead.* + To remove Soapbox and revert to the default pleroma-fe, simply `rm /opt/pleroma/instance/static/index.html` (you can delete other stuff in there too, but be careful not to delete your own HTML files). ## :elephant: Deploy on Mastodon diff --git a/app/application.ts b/app/application.ts index 38dc089935..9610b4f9a5 100644 --- a/app/application.ts +++ b/app/application.ts @@ -1,10 +1,10 @@ -import loadPolyfills from './soapbox/load_polyfills'; +import loadPolyfills from './soapbox/load-polyfills'; // Load iframe event listener require('./soapbox/iframe'); // @ts-ignore -require.context('./images/', true); +require.context('./assets/images/', true); // Load stylesheet require('react-datepicker/dist/react-datepicker.css'); diff --git a/app/fonts/OpenDyslexic/LICENSE b/app/assets/fonts/OpenDyslexic/LICENSE similarity index 100% rename from app/fonts/OpenDyslexic/LICENSE rename to app/assets/fonts/OpenDyslexic/LICENSE diff --git a/app/fonts/OpenDyslexic/OpenDyslexic-Bold-Italic.woff2 b/app/assets/fonts/OpenDyslexic/OpenDyslexic-Bold-Italic.woff2 similarity index 100% rename from app/fonts/OpenDyslexic/OpenDyslexic-Bold-Italic.woff2 rename to app/assets/fonts/OpenDyslexic/OpenDyslexic-Bold-Italic.woff2 diff --git a/app/fonts/OpenDyslexic/OpenDyslexic-Bold.woff2 b/app/assets/fonts/OpenDyslexic/OpenDyslexic-Bold.woff2 similarity index 100% rename from app/fonts/OpenDyslexic/OpenDyslexic-Bold.woff2 rename to app/assets/fonts/OpenDyslexic/OpenDyslexic-Bold.woff2 diff --git a/app/fonts/OpenDyslexic/OpenDyslexic-Italic.woff2 b/app/assets/fonts/OpenDyslexic/OpenDyslexic-Italic.woff2 similarity index 100% rename from app/fonts/OpenDyslexic/OpenDyslexic-Italic.woff2 rename to app/assets/fonts/OpenDyslexic/OpenDyslexic-Italic.woff2 diff --git a/app/fonts/OpenDyslexic/OpenDyslexic-Regular.woff2 b/app/assets/fonts/OpenDyslexic/OpenDyslexic-Regular.woff2 similarity index 100% rename from app/fonts/OpenDyslexic/OpenDyslexic-Regular.woff2 rename to app/assets/fonts/OpenDyslexic/OpenDyslexic-Regular.woff2 diff --git a/app/icons/COPYING.md b/app/assets/icons/COPYING.md similarity index 76% rename from app/icons/COPYING.md rename to app/assets/icons/COPYING.md index 5e84c0b5cc..1dcc928d92 100644 --- a/app/icons/COPYING.md +++ b/app/assets/icons/COPYING.md @@ -1,6 +1,5 @@ # Custom icons -- fediverse.svg - Modified from Wikipedia, CC0 - verified.svg - Created by Alex Gleason. CC0 Fediverse logo: https://en.wikipedia.org/wiki/Fediverse#/media/File:Fediverse_logo_proposal.svg diff --git a/app/icons/verified.svg b/app/assets/icons/verified.svg similarity index 100% rename from app/icons/verified.svg rename to app/assets/icons/verified.svg diff --git a/app/images/audio-placeholder.png b/app/assets/images/audio-placeholder.png similarity index 100% rename from app/images/audio-placeholder.png rename to app/assets/images/audio-placeholder.png diff --git a/app/images/avatar-missing.png b/app/assets/images/avatar-missing.png similarity index 100% rename from app/images/avatar-missing.png rename to app/assets/images/avatar-missing.png diff --git a/app/images/avatar-missing.svg b/app/assets/images/avatar-missing.svg similarity index 100% rename from app/images/avatar-missing.svg rename to app/assets/images/avatar-missing.svg diff --git a/app/images/header-missing.png b/app/assets/images/header-missing.png similarity index 100% rename from app/images/header-missing.png rename to app/assets/images/header-missing.png diff --git a/app/images/soapbox-logo-white.svg b/app/assets/images/soapbox-logo-white.svg similarity index 100% rename from app/images/soapbox-logo-white.svg rename to app/assets/images/soapbox-logo-white.svg diff --git a/app/images/soapbox-logo.svg b/app/assets/images/soapbox-logo.svg similarity index 100% rename from app/images/soapbox-logo.svg rename to app/assets/images/soapbox-logo.svg diff --git a/app/images/video-placeholder.png b/app/assets/images/video-placeholder.png similarity index 100% rename from app/images/video-placeholder.png rename to app/assets/images/video-placeholder.png diff --git a/app/images/void.png b/app/assets/images/void.png similarity index 100% rename from app/images/void.png rename to app/assets/images/void.png diff --git a/app/images/web-push/web-push-icon_expand.png b/app/assets/images/web-push/web-push-icon_expand.png similarity index 100% rename from app/images/web-push/web-push-icon_expand.png rename to app/assets/images/web-push/web-push-icon_expand.png diff --git a/app/images/web-push/web-push-icon_favourite.png b/app/assets/images/web-push/web-push-icon_favourite.png similarity index 100% rename from app/images/web-push/web-push-icon_favourite.png rename to app/assets/images/web-push/web-push-icon_favourite.png diff --git a/app/images/web-push/web-push-icon_reblog.png b/app/assets/images/web-push/web-push-icon_reblog.png similarity index 100% rename from app/images/web-push/web-push-icon_reblog.png rename to app/assets/images/web-push/web-push-icon_reblog.png diff --git a/app/sounds/boop.mp3 b/app/assets/sounds/boop.mp3 similarity index 100% rename from app/sounds/boop.mp3 rename to app/assets/sounds/boop.mp3 diff --git a/app/sounds/boop.ogg b/app/assets/sounds/boop.ogg similarity index 100% rename from app/sounds/boop.ogg rename to app/assets/sounds/boop.ogg diff --git a/app/sounds/chat.mp3 b/app/assets/sounds/chat.mp3 similarity index 100% rename from app/sounds/chat.mp3 rename to app/assets/sounds/chat.mp3 diff --git a/app/sounds/chat.oga b/app/assets/sounds/chat.oga similarity index 100% rename from app/sounds/chat.oga rename to app/assets/sounds/chat.oga diff --git a/app/fonts/soapbox/soapbox.eot b/app/fonts/soapbox/soapbox.eot deleted file mode 100644 index d66bb100ab..0000000000 Binary files a/app/fonts/soapbox/soapbox.eot and /dev/null differ diff --git a/app/fonts/soapbox/soapbox.svg b/app/fonts/soapbox/soapbox.svg deleted file mode 100644 index 20d08a586f..0000000000 --- a/app/fonts/soapbox/soapbox.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - -Generated by IcoMoon - - - - - - - - \ No newline at end of file diff --git a/app/fonts/soapbox/soapbox.ttf b/app/fonts/soapbox/soapbox.ttf deleted file mode 100644 index df64210fb8..0000000000 Binary files a/app/fonts/soapbox/soapbox.ttf and /dev/null differ diff --git a/app/fonts/soapbox/soapbox.woff b/app/fonts/soapbox/soapbox.woff deleted file mode 100644 index 1902dbc363..0000000000 Binary files a/app/fonts/soapbox/soapbox.woff and /dev/null differ diff --git a/app/icons/fediverse.svg b/app/icons/fediverse.svg deleted file mode 100644 index 4cd3cb9380..0000000000 --- a/app/icons/fediverse.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/app/images/halloween/clouds.png b/app/images/halloween/clouds.png deleted file mode 100644 index 29962c1048..0000000000 Binary files a/app/images/halloween/clouds.png and /dev/null differ diff --git a/app/images/halloween/halloween-emblem.svg b/app/images/halloween/halloween-emblem.svg deleted file mode 100644 index ad23be14c9..0000000000 --- a/app/images/halloween/halloween-emblem.svg +++ /dev/null @@ -1,311 +0,0 @@ - - - - Flying Witch during Full Moon - - - - - image/svg+xml - - Flying Witch during Full Moon - 2017-10-10 - - - Urs Roesch - - - - - - OpenClipart - - - - - remix+287475 - remix+288242 - remix+170669 - yellow - moon - yellow moon - full moon - moon - witch - cat - silhouette - bat - bats - flying bat - flying witch - black - dark - night - halloween - walpurgis night - walpurgis - - - Flying witch with cat flying during full moon. - - - gnokii - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/images/halloween/spider.svg b/app/images/halloween/spider.svg deleted file mode 100644 index 077b60d65a..0000000000 --- a/app/images/halloween/spider.svg +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - diff --git a/app/images/halloween/spiderweb.svg b/app/images/halloween/spiderweb.svg deleted file mode 100644 index 16ae81984a..0000000000 --- a/app/images/halloween/spiderweb.svg +++ /dev/null @@ -1,78 +0,0 @@ - - - - - Realistic spider web - - - - - - - image/svg+xml - - - - - Openclipart - - - Realistic spider web - - - - - - - - - diff --git a/app/images/halloween/starfield.png b/app/images/halloween/starfield.png deleted file mode 100644 index 1e79958955..0000000000 Binary files a/app/images/halloween/starfield.png and /dev/null differ diff --git a/app/images/halloween/twinkle.svg b/app/images/halloween/twinkle.svg deleted file mode 100644 index 9869cb094e..0000000000 --- a/app/images/halloween/twinkle.svg +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - diff --git a/app/images/sprite-post-functions.png b/app/images/sprite-post-functions.png deleted file mode 100644 index aea7f57ba9..0000000000 Binary files a/app/images/sprite-post-functions.png and /dev/null differ diff --git a/app/soapbox/__fixtures__/intlMessages.json b/app/soapbox/__fixtures__/intlMessages.json index 54c919e6ad..30ce6f35cf 100644 --- a/app/soapbox/__fixtures__/intlMessages.json +++ b/app/soapbox/__fixtures__/intlMessages.json @@ -87,7 +87,7 @@ "compose_form.poll.add_option": "Add a choice", "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", - "compose_form.poll.remove_option": "Remove this choice", + "compose_form.poll.remove_option": "Delete", "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", "compose_form.publish": "Publish", "compose_form.publish_loud": "{publish}!", @@ -319,6 +319,7 @@ "poll_button.add_poll": "Add a poll", "poll_button.remove_poll": "Remove poll", "preferences.fields.auto_play_gif_label": "Auto-play animated GIFs", + "preferences.fields.auto_play_video_label": "Auto-play videos", "preferences.fields.boost_modal_label": "Show confirmation dialog before reposting", "preferences.fields.delete_modal_label": "Show confirmation dialog before deleting a post", "preferences.fields.demetricator_label": "Use Demetricator", @@ -565,7 +566,7 @@ "compose_form.poll.add_option": "Add a choice", "compose_form.poll.duration": "Poll duration", "compose_form.poll.option_placeholder": "Choice {number}", - "compose_form.poll.remove_option": "Remove this choice", + "compose_form.poll.remove_option": "Delete", "compose_form.poll.type.hint": "Click to toggle poll type. Radio button (default) is single. Checkbox is multiple.", "compose_form.publish": "Publish", "compose_form.publish_loud": "{publish}!", diff --git a/app/soapbox/actions/__tests__/account-notes.test.ts b/app/soapbox/actions/__tests__/account-notes.test.ts index 61e0c20b09..8b85eecc5e 100644 --- a/app/soapbox/actions/__tests__/account-notes.test.ts +++ b/app/soapbox/actions/__tests__/account-notes.test.ts @@ -2,7 +2,7 @@ import { Map as ImmutableMap } from 'immutable'; import { __stub } from 'soapbox/api'; import { mockStore, rootState } from 'soapbox/jest/test-helpers'; -import { ReducerRecord, EditRecord } from 'soapbox/reducers/account_notes'; +import { ReducerRecord, EditRecord } from 'soapbox/reducers/account-notes'; import { normalizeAccount, normalizeRelationship } from '../../normalizers'; import { changeAccountNoteComment, initAccountNoteModal, submitAccountNote } from '../account-notes'; diff --git a/app/soapbox/actions/__tests__/accounts.test.ts b/app/soapbox/actions/__tests__/accounts.test.ts index 0793e36f7b..d9faa02134 100644 --- a/app/soapbox/actions/__tests__/accounts.test.ts +++ b/app/soapbox/actions/__tests__/accounts.test.ts @@ -2,7 +2,7 @@ import { Map as ImmutableMap } from 'immutable'; import { __stub } from 'soapbox/api'; import { mockStore, rootState } from 'soapbox/jest/test-helpers'; -import { ListRecord, ReducerRecord } from 'soapbox/reducers/user_lists'; +import { ListRecord, ReducerRecord } from 'soapbox/reducers/user-lists'; import { normalizeAccount, normalizeInstance, normalizeRelationship } from '../../normalizers'; import { diff --git a/app/soapbox/actions/__tests__/blocks.test.ts b/app/soapbox/actions/__tests__/blocks.test.ts index 8b4c040b3e..49f649ab66 100644 --- a/app/soapbox/actions/__tests__/blocks.test.ts +++ b/app/soapbox/actions/__tests__/blocks.test.ts @@ -1,6 +1,6 @@ import { __stub } from 'soapbox/api'; import { mockStore, rootState } from 'soapbox/jest/test-helpers'; -import { ListRecord, ReducerRecord as UserListsRecord } from 'soapbox/reducers/user_lists'; +import { ListRecord, ReducerRecord as UserListsRecord } from 'soapbox/reducers/user-lists'; import { expandBlocks, fetchBlocks } from '../blocks'; diff --git a/app/soapbox/actions/__tests__/me.test.ts b/app/soapbox/actions/__tests__/me.test.ts index 6d37fc68c2..c75d128f0c 100644 --- a/app/soapbox/actions/__tests__/me.test.ts +++ b/app/soapbox/actions/__tests__/me.test.ts @@ -7,7 +7,7 @@ import { fetchMe, patchMe, } from '../me'; -jest.mock('../../storage/kv_store', () => ({ +jest.mock('../../storage/kv-store', () => ({ __esModule: true, default: { getItemOrError: jest.fn().mockReturnValue(Promise.resolve({})), diff --git a/app/soapbox/actions/auth.ts b/app/soapbox/actions/auth.ts index 5a686d0457..d588db80ae 100644 --- a/app/soapbox/actions/auth.ts +++ b/app/soapbox/actions/auth.ts @@ -16,7 +16,8 @@ import { obtainOAuthToken, revokeOAuthToken } from 'soapbox/actions/oauth'; import { startOnboarding } from 'soapbox/actions/onboarding'; import snackbar from 'soapbox/actions/snackbar'; import { custom } from 'soapbox/custom'; -import KVStore from 'soapbox/storage/kv_store'; +import { queryClient } from 'soapbox/queries/client'; +import KVStore from 'soapbox/storage/kv-store'; import { getLoggedInAccount, parseBaseURL } from 'soapbox/utils/auth'; import sourceCode from 'soapbox/utils/code'; import { getFeatures } from 'soapbox/utils/features'; @@ -239,15 +240,25 @@ export const logOut = () => token: state.auth.getIn(['users', account.url, 'access_token']), }; - return dispatch(revokeOAuthToken(params)).finally(() => { - dispatch({ type: AUTH_LOGGED_OUT, account, standalone }); - return dispatch(snackbar.success(messages.loggedOut)); - }); + return dispatch(revokeOAuthToken(params)) + .finally(() => { + // Clear all stored cache from React Query + queryClient.invalidateQueries(); + queryClient.clear(); + + dispatch({ type: AUTH_LOGGED_OUT, account, standalone }); + + return dispatch(snackbar.success(messages.loggedOut)); + }); }; export const switchAccount = (accountId: string, background = false) => (dispatch: AppDispatch, getState: () => RootState) => { const account = getState().accounts.get(accountId); + // Clear all stored cache from React Query + queryClient.invalidateQueries(); + queryClient.clear(); + return dispatch({ type: SWITCH_ACCOUNT, account, background }); }; diff --git a/app/soapbox/actions/compose.ts b/app/soapbox/actions/compose.ts index 7d451c3212..4519425e1b 100644 --- a/app/soapbox/actions/compose.ts +++ b/app/soapbox/actions/compose.ts @@ -5,12 +5,12 @@ import { defineMessages, IntlShape } from 'react-intl'; import snackbar from 'soapbox/actions/snackbar'; import api from 'soapbox/api'; -import { search as emojiSearch } from 'soapbox/features/emoji/emoji_mart_search_light'; +import { search as emojiSearch } from 'soapbox/features/emoji/emoji-mart-search-light'; import { tagHistory } from 'soapbox/settings'; import { isLoggedIn } from 'soapbox/utils/auth'; import { getFeatures, parseVersion } from 'soapbox/utils/features'; import { formatBytes, getVideoDuration } from 'soapbox/utils/media'; -import resizeImage from 'soapbox/utils/resize_image'; +import resizeImage from 'soapbox/utils/resize-image'; import { showAlert, showAlertForError } from './alerts'; import { useEmoji } from './emojis'; @@ -21,8 +21,8 @@ import { getSettings } from './settings'; import { createStatus } from './statuses'; import type { History } from 'history'; -import type { Emoji } from 'soapbox/components/autosuggest_emoji'; -import type { AutoSuggestion } from 'soapbox/components/autosuggest_input'; +import type { Emoji } from 'soapbox/components/autosuggest-emoji'; +import type { AutoSuggestion } from 'soapbox/components/autosuggest-input'; import type { AppDispatch, RootState } from 'soapbox/store'; import type { Account, APIEntity, Status, Tag } from 'soapbox/types/entities'; diff --git a/app/soapbox/actions/consumer-auth.ts b/app/soapbox/actions/consumer-auth.ts index b669c63931..1719415771 100644 --- a/app/soapbox/actions/consumer-auth.ts +++ b/app/soapbox/actions/consumer-auth.ts @@ -1,6 +1,6 @@ import axios from 'axios'; -import * as BuildConfig from 'soapbox/build_config'; +import * as BuildConfig from 'soapbox/build-config'; import { isURL } from 'soapbox/utils/auth'; import sourceCode from 'soapbox/utils/code'; import { getFeatures } from 'soapbox/utils/features'; diff --git a/app/soapbox/actions/custom_emojis.ts b/app/soapbox/actions/custom-emojis.ts similarity index 100% rename from app/soapbox/actions/custom_emojis.ts rename to app/soapbox/actions/custom-emojis.ts diff --git a/app/soapbox/actions/domain_blocks.ts b/app/soapbox/actions/domain-blocks.ts similarity index 100% rename from app/soapbox/actions/domain_blocks.ts rename to app/soapbox/actions/domain-blocks.ts diff --git a/app/soapbox/actions/dropdown_menu.ts b/app/soapbox/actions/dropdown-menu.ts similarity index 97% rename from app/soapbox/actions/dropdown_menu.ts rename to app/soapbox/actions/dropdown-menu.ts index 2c19735a10..0c6fc85363 100644 --- a/app/soapbox/actions/dropdown_menu.ts +++ b/app/soapbox/actions/dropdown-menu.ts @@ -1,4 +1,4 @@ -import type { DropdownPlacement } from 'soapbox/components/dropdown_menu'; +import type { DropdownPlacement } from 'soapbox/components/dropdown-menu'; const DROPDOWN_MENU_OPEN = 'DROPDOWN_MENU_OPEN'; const DROPDOWN_MENU_CLOSE = 'DROPDOWN_MENU_CLOSE'; diff --git a/app/soapbox/actions/email_list.ts b/app/soapbox/actions/email-list.ts similarity index 100% rename from app/soapbox/actions/email_list.ts rename to app/soapbox/actions/email-list.ts diff --git a/app/soapbox/actions/emoji_reacts.ts b/app/soapbox/actions/emoji-reacts.ts similarity index 100% rename from app/soapbox/actions/emoji_reacts.ts rename to app/soapbox/actions/emoji-reacts.ts diff --git a/app/soapbox/actions/emojis.ts b/app/soapbox/actions/emojis.ts index 04bda6c899..46f591b060 100644 --- a/app/soapbox/actions/emojis.ts +++ b/app/soapbox/actions/emojis.ts @@ -1,6 +1,6 @@ import { saveSettings } from './settings'; -import type { Emoji } from 'soapbox/components/autosuggest_emoji'; +import type { Emoji } from 'soapbox/components/autosuggest-emoji'; import type { AppDispatch } from 'soapbox/store'; const EMOJI_USE = 'EMOJI_USE'; diff --git a/app/soapbox/actions/events.ts b/app/soapbox/actions/events.ts index 21089227b0..cf911e385c 100644 --- a/app/soapbox/actions/events.ts +++ b/app/soapbox/actions/events.ts @@ -2,7 +2,7 @@ import { defineMessages, IntlShape } from 'react-intl'; import api, { getLinks } from 'soapbox/api'; import { formatBytes } from 'soapbox/utils/media'; -import resizeImage from 'soapbox/utils/resize_image'; +import resizeImage from 'soapbox/utils/resize-image'; import { importFetchedAccounts, importFetchedStatus } from './importer'; import { fetchMedia, uploadMedia } from './media'; diff --git a/app/soapbox/actions/export_data.ts b/app/soapbox/actions/export-data.ts similarity index 100% rename from app/soapbox/actions/export_data.ts rename to app/soapbox/actions/export-data.ts diff --git a/app/soapbox/actions/external_auth.ts b/app/soapbox/actions/external-auth.ts similarity index 100% rename from app/soapbox/actions/external_auth.ts rename to app/soapbox/actions/external-auth.ts diff --git a/app/soapbox/actions/familiar_followers.ts b/app/soapbox/actions/familiar-followers.ts similarity index 100% rename from app/soapbox/actions/familiar_followers.ts rename to app/soapbox/actions/familiar-followers.ts diff --git a/app/soapbox/actions/import_data.ts b/app/soapbox/actions/import-data.ts similarity index 100% rename from app/soapbox/actions/import_data.ts rename to app/soapbox/actions/import-data.ts diff --git a/app/soapbox/actions/instance.ts b/app/soapbox/actions/instance.ts index 151ad3672c..ca1fc3ef5e 100644 --- a/app/soapbox/actions/instance.ts +++ b/app/soapbox/actions/instance.ts @@ -1,7 +1,7 @@ import { createAsyncThunk } from '@reduxjs/toolkit'; import get from 'lodash/get'; -import KVStore from 'soapbox/storage/kv_store'; +import KVStore from 'soapbox/storage/kv-store'; import { RootState } from 'soapbox/store'; import { getAuthUserUrl } from 'soapbox/utils/auth'; import { parseVersion } from 'soapbox/utils/features'; diff --git a/app/soapbox/actions/me.ts b/app/soapbox/actions/me.ts index e76399d21c..17beae21d8 100644 --- a/app/soapbox/actions/me.ts +++ b/app/soapbox/actions/me.ts @@ -1,4 +1,4 @@ -import KVStore from 'soapbox/storage/kv_store'; +import KVStore from 'soapbox/storage/kv-store'; import { getAuthUserId, getAuthUserUrl } from 'soapbox/utils/auth'; import api from '../api'; diff --git a/app/soapbox/actions/modals.ts b/app/soapbox/actions/modals.ts index 3e1a106cf9..83b52cb3e2 100644 --- a/app/soapbox/actions/modals.ts +++ b/app/soapbox/actions/modals.ts @@ -1,8 +1,10 @@ +import type { ModalType } from 'soapbox/features/ui/components/modal-root'; + export const MODAL_OPEN = 'MODAL_OPEN'; export const MODAL_CLOSE = 'MODAL_CLOSE'; /** Open a modal of the given type */ -export function openModal(type: string, props?: any) { +export function openModal(type: ModalType, props?: any) { return { type: MODAL_OPEN, modalType: type, @@ -11,7 +13,7 @@ export function openModal(type: string, props?: any) { } /** Close the modal */ -export function closeModal(type?: string) { +export function closeModal(type?: ModalType) { return { type: MODAL_CLOSE, modalType: type, diff --git a/app/soapbox/actions/moderation.tsx b/app/soapbox/actions/moderation.tsx index bf0ccf3327..1791500b5d 100644 --- a/app/soapbox/actions/moderation.tsx +++ b/app/soapbox/actions/moderation.tsx @@ -7,7 +7,7 @@ import { openModal } from 'soapbox/actions/modals'; import snackbar from 'soapbox/actions/snackbar'; import OutlineBox from 'soapbox/components/outline-box'; import { Stack, Text } from 'soapbox/components/ui'; -import AccountContainer from 'soapbox/containers/account_container'; +import AccountContainer from 'soapbox/containers/account-container'; import { isLocal } from 'soapbox/utils/accounts'; import type { AppDispatch, RootState } from 'soapbox/store'; diff --git a/app/soapbox/actions/mrf.ts b/app/soapbox/actions/mrf.ts index e2cef5938f..1b9cbad931 100644 --- a/app/soapbox/actions/mrf.ts +++ b/app/soapbox/actions/mrf.ts @@ -1,11 +1,11 @@ import { Map as ImmutableMap, Set as ImmutableSet } from 'immutable'; -import ConfigDB from 'soapbox/utils/config_db'; +import ConfigDB from 'soapbox/utils/config-db'; import { fetchConfig, updateConfig } from './admin'; import type { AppDispatch, RootState } from 'soapbox/store'; -import type { Policy } from 'soapbox/utils/config_db'; +import type { Policy } from 'soapbox/utils/config-db'; const simplePolicyMerge = (simplePolicy: Policy, host: string, restrictions: ImmutableMap) => { return simplePolicy.map((hosts, key) => { diff --git a/app/soapbox/actions/notifications.ts b/app/soapbox/actions/notifications.ts index db8fd688f0..068e65dc4a 100644 --- a/app/soapbox/actions/notifications.ts +++ b/app/soapbox/actions/notifications.ts @@ -1,14 +1,11 @@ -import { - Map as ImmutableMap, -} from 'immutable'; import IntlMessageFormat from 'intl-messageformat'; import 'intl-pluralrules'; import { defineMessages } from 'react-intl'; import api, { getLinks } from 'soapbox/api'; -import compareId from 'soapbox/compare_id'; import { getFilters, regexFromFilters } from 'soapbox/selectors'; import { isLoggedIn } from 'soapbox/utils/auth'; +import { compareId } from 'soapbox/utils/comparators'; import { getFeatures, parseVersion, PLEROMA } from 'soapbox/utils/features'; import { unescapeHTML } from 'soapbox/utils/html'; import { EXCLUDE_TYPES, NOTIFICATION_TYPES } from 'soapbox/utils/notification'; @@ -149,13 +146,13 @@ const updateNotificationsQueue = (notification: APIEntity, intlMessages: Record< const dequeueNotifications = () => (dispatch: AppDispatch, getState: () => RootState) => { - const queuedNotifications = getState().notifications.get('queuedNotifications'); - const totalQueuedNotificationsCount = getState().notifications.get('totalQueuedNotificationsCount'); + const queuedNotifications = getState().notifications.queuedNotifications; + const totalQueuedNotificationsCount = getState().notifications.totalQueuedNotificationsCount; if (totalQueuedNotificationsCount === 0) { return; } else if (totalQueuedNotificationsCount > 0 && totalQueuedNotificationsCount <= MAX_QUEUED_NOTIFICATIONS) { - queuedNotifications.forEach((block: APIEntity) => { + queuedNotifications.forEach((block) => { dispatch(updateNotifications(block.notification)); }); } else { @@ -184,7 +181,7 @@ const expandNotifications = ({ maxId }: Record = {}, done: () => an const notifications = state.notifications; const isLoadingMore = !!maxId; - if (notifications.get('isLoading')) { + if (notifications.isLoading) { done(); return dispatch(noOp); } @@ -207,7 +204,7 @@ const expandNotifications = ({ maxId }: Record = {}, done: () => an } } - if (!maxId && notifications.get('items').size > 0) { + if (!maxId && notifications.items.size > 0) { params.since_id = notifications.getIn(['items', 0, 'id']); } @@ -306,8 +303,8 @@ const markReadNotifications = () => if (!isLoggedIn(getState)) return; const state = getState(); - const topNotificationId: string | undefined = state.notifications.get('items').first(ImmutableMap()).get('id'); - const lastReadId: string | -1 = state.notifications.get('lastRead'); + const topNotificationId = state.notifications.items.first()?.id; + const lastReadId = state.notifications.lastRead; const v = parseVersion(state.instance.version); if (topNotificationId && (lastReadId === -1 || compareId(topNotificationId, lastReadId) > 0)) { diff --git a/app/soapbox/actions/pin_statuses.ts b/app/soapbox/actions/pin-statuses.ts similarity index 100% rename from app/soapbox/actions/pin_statuses.ts rename to app/soapbox/actions/pin-statuses.ts diff --git a/app/soapbox/actions/profile_hover_card.ts b/app/soapbox/actions/profile-hover-card.ts similarity index 100% rename from app/soapbox/actions/profile_hover_card.ts rename to app/soapbox/actions/profile-hover-card.ts diff --git a/app/soapbox/actions/push_notifications/index.ts b/app/soapbox/actions/push-notifications/index.ts similarity index 100% rename from app/soapbox/actions/push_notifications/index.ts rename to app/soapbox/actions/push-notifications/index.ts diff --git a/app/soapbox/actions/push_notifications/registerer.ts b/app/soapbox/actions/push-notifications/registerer.ts similarity index 99% rename from app/soapbox/actions/push_notifications/registerer.ts rename to app/soapbox/actions/push-notifications/registerer.ts index e66e3a01ac..3a9d4fb9e6 100644 --- a/app/soapbox/actions/push_notifications/registerer.ts +++ b/app/soapbox/actions/push-notifications/registerer.ts @@ -1,4 +1,4 @@ -import { createPushSubscription, updatePushSubscription } from 'soapbox/actions/push_subscriptions'; +import { createPushSubscription, updatePushSubscription } from 'soapbox/actions/push-subscriptions'; import { pushNotificationsSetting } from 'soapbox/settings'; import { getVapidKey } from 'soapbox/utils/auth'; import { decode as decodeBase64 } from 'soapbox/utils/base64'; diff --git a/app/soapbox/actions/push_notifications/setter.ts b/app/soapbox/actions/push-notifications/setter.ts similarity index 100% rename from app/soapbox/actions/push_notifications/setter.ts rename to app/soapbox/actions/push-notifications/setter.ts diff --git a/app/soapbox/actions/push_subscriptions.ts b/app/soapbox/actions/push-subscriptions.ts similarity index 100% rename from app/soapbox/actions/push_subscriptions.ts rename to app/soapbox/actions/push-subscriptions.ts diff --git a/app/soapbox/actions/remote_timeline.ts b/app/soapbox/actions/remote-timeline.ts similarity index 100% rename from app/soapbox/actions/remote_timeline.ts rename to app/soapbox/actions/remote-timeline.ts diff --git a/app/soapbox/actions/scheduled_statuses.ts b/app/soapbox/actions/scheduled-statuses.ts similarity index 100% rename from app/soapbox/actions/scheduled_statuses.ts rename to app/soapbox/actions/scheduled-statuses.ts diff --git a/app/soapbox/actions/soapbox.ts b/app/soapbox/actions/soapbox.ts index 89d3080d83..725ff1ae31 100644 --- a/app/soapbox/actions/soapbox.ts +++ b/app/soapbox/actions/soapbox.ts @@ -2,7 +2,7 @@ import { createSelector } from 'reselect'; import { getHost } from 'soapbox/actions/instance'; import { normalizeSoapboxConfig } from 'soapbox/normalizers'; -import KVStore from 'soapbox/storage/kv_store'; +import KVStore from 'soapbox/storage/kv-store'; import { removeVS16s } from 'soapbox/utils/emoji'; import { getFeatures } from 'soapbox/utils/features'; diff --git a/app/soapbox/actions/trending_statuses.ts b/app/soapbox/actions/trending-statuses.ts similarity index 100% rename from app/soapbox/actions/trending_statuses.ts rename to app/soapbox/actions/trending-statuses.ts diff --git a/app/soapbox/__mocks__/api.ts b/app/soapbox/api/__mocks__/index.ts similarity index 92% rename from app/soapbox/__mocks__/api.ts rename to app/soapbox/api/__mocks__/index.ts index 060846c944..dd2f1ec937 100644 --- a/app/soapbox/__mocks__/api.ts +++ b/app/soapbox/api/__mocks__/index.ts @@ -4,7 +4,7 @@ import LinkHeader from 'http-link-header'; import type { AxiosInstance, AxiosResponse } from 'axios'; -const api = jest.requireActual('../api') as Record; +const api = jest.requireActual('../index') as Record; let mocks: Array = []; export const __stub = (func: (mock: MockAdapter) => void) => mocks.push(func); diff --git a/app/soapbox/api.ts b/app/soapbox/api/index.ts similarity index 75% rename from app/soapbox/api.ts rename to app/soapbox/api/index.ts index bdcaf53d80..97d7d25d71 100644 --- a/app/soapbox/api.ts +++ b/app/soapbox/api/index.ts @@ -9,18 +9,18 @@ import axios, { AxiosInstance, AxiosResponse } from 'axios'; import LinkHeader from 'http-link-header'; import { createSelector } from 'reselect'; -import * as BuildConfig from 'soapbox/build_config'; +import * as BuildConfig from 'soapbox/build-config'; import { RootState } from 'soapbox/store'; import { getAccessToken, getAppToken, isURL, parseBaseURL } from 'soapbox/utils/auth'; import type MockAdapter from 'axios-mock-adapter'; /** - Parse Link headers, mostly for pagination. - @see {@link https://www.npmjs.com/package/http-link-header} - @param {object} response - Axios response object - @returns {object} Link object - */ + Parse Link headers, mostly for pagination. + @see {@link https://www.npmjs.com/package/http-link-header} + @param {object} response - Axios response object + @returns {object} Link object + */ export const getLinks = (response: AxiosResponse): LinkHeader => { return new LinkHeader(response.headers?.link); }; @@ -50,11 +50,11 @@ const getAuthBaseURL = createSelector([ }); /** - * Base client for HTTP requests. - * @param {string} accessToken - * @param {string} baseURL - * @returns {object} Axios instance - */ + * Base client for HTTP requests. + * @param {string} accessToken + * @param {string} baseURL + * @returns {object} Axios instance + */ export const baseClient = (accessToken?: string | null, baseURL: string = ''): AxiosInstance => { return axios.create({ // When BACKEND_URL is set, always use it. @@ -68,22 +68,22 @@ export const baseClient = (accessToken?: string | null, baseURL: string = ''): A }; /** - * Dumb client for grabbing static files. - * It uses FE_SUBDIRECTORY and parses JSON if possible. - * No authorization is needed. - */ + * Dumb client for grabbing static files. + * It uses FE_SUBDIRECTORY and parses JSON if possible. + * No authorization is needed. + */ export const staticClient = axios.create({ baseURL: BuildConfig.FE_SUBDIRECTORY, transformResponse: [maybeParseJSON], }); /** - * Stateful API client. - * Uses credentials from the Redux store if available. - * @param {function} getState - Must return the Redux state - * @param {string} authType - Either 'user' or 'app' - * @returns {object} Axios instance - */ + * Stateful API client. + * Uses credentials from the Redux store if available. + * @param {function} getState - Must return the Redux state + * @param {string} authType - Either 'user' or 'app' + * @returns {object} Axios instance + */ export default (getState: () => RootState, authType: string = 'user'): AxiosInstance => { const state = getState(); const accessToken = getToken(state, authType); diff --git a/app/soapbox/base_polyfills.ts b/app/soapbox/base-polyfills.ts similarity index 100% rename from app/soapbox/base_polyfills.ts rename to app/soapbox/base-polyfills.ts diff --git a/app/soapbox/build_config.js b/app/soapbox/build-config.js similarity index 96% rename from app/soapbox/build_config.js rename to app/soapbox/build-config.js index 04b48bf781..a11faa0e89 100644 Binary files a/app/soapbox/build_config.js and b/app/soapbox/build-config.js differ diff --git a/app/soapbox/components/__mocks__/react-inlinesvg.tsx b/app/soapbox/components/__mocks__/react-inlinesvg.tsx index 367ec0e333..1d4fde154e 100644 --- a/app/soapbox/components/__mocks__/react-inlinesvg.tsx +++ b/app/soapbox/components/__mocks__/react-inlinesvg.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; interface IInlineSVG { loader?: JSX.Element, diff --git a/app/soapbox/components/__tests__/autosuggest_emoji.test.tsx b/app/soapbox/components/__tests__/autosuggest-emoji.test.tsx similarity index 94% rename from app/soapbox/components/__tests__/autosuggest_emoji.test.tsx rename to app/soapbox/components/__tests__/autosuggest-emoji.test.tsx index 8fab0ef8b0..e2f059ff7b 100644 --- a/app/soapbox/components/__tests__/autosuggest_emoji.test.tsx +++ b/app/soapbox/components/__tests__/autosuggest-emoji.test.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { render, screen } from '../../jest/test-helpers'; -import AutosuggestEmoji from '../autosuggest_emoji'; +import AutosuggestEmoji from '../autosuggest-emoji'; describe('', () => { it('renders native emoji', () => { diff --git a/app/soapbox/components/__tests__/avatar_overlay.test.tsx b/app/soapbox/components/__tests__/avatar-overlay.test.tsx similarity index 94% rename from app/soapbox/components/__tests__/avatar_overlay.test.tsx rename to app/soapbox/components/__tests__/avatar-overlay.test.tsx index 1058285565..4e83dd0715 100644 --- a/app/soapbox/components/__tests__/avatar_overlay.test.tsx +++ b/app/soapbox/components/__tests__/avatar-overlay.test.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { normalizeAccount } from 'soapbox/normalizers'; import { render, screen } from '../../jest/test-helpers'; -import AvatarOverlay from '../avatar_overlay'; +import AvatarOverlay from '../avatar-overlay'; import type { ReducerAccount } from 'soapbox/reducers/accounts'; diff --git a/app/soapbox/components/__tests__/display_name.test.tsx b/app/soapbox/components/__tests__/display-name.test.tsx similarity index 100% rename from app/soapbox/components/__tests__/display_name.test.tsx rename to app/soapbox/components/__tests__/display-name.test.tsx diff --git a/app/soapbox/components/__tests__/emoji_selector.test.tsx b/app/soapbox/components/__tests__/emoji-selector.test.tsx similarity index 88% rename from app/soapbox/components/__tests__/emoji_selector.test.tsx rename to app/soapbox/components/__tests__/emoji-selector.test.tsx index c680d156e8..b382a4b94b 100644 --- a/app/soapbox/components/__tests__/emoji_selector.test.tsx +++ b/app/soapbox/components/__tests__/emoji-selector.test.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { render, screen } from '../../jest/test-helpers'; -import EmojiSelector from '../emoji_selector'; +import EmojiSelector from '../emoji-selector'; describe('', () => { it('renders correctly', () => { diff --git a/app/soapbox/components/account_search.tsx b/app/soapbox/components/account-search.tsx similarity index 99% rename from app/soapbox/components/account_search.tsx rename to app/soapbox/components/account-search.tsx index bf9652b66e..883278bcf8 100644 --- a/app/soapbox/components/account_search.tsx +++ b/app/soapbox/components/account-search.tsx @@ -2,7 +2,7 @@ import classNames from 'clsx'; import React, { useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; -import AutosuggestAccountInput from 'soapbox/components/autosuggest_account_input'; +import AutosuggestAccountInput from 'soapbox/components/autosuggest-account-input'; import Icon from 'soapbox/components/icon'; const messages = defineMessages({ diff --git a/app/soapbox/components/account.tsx b/app/soapbox/components/account.tsx index 76bffa9356..5618b8cf84 100644 --- a/app/soapbox/components/account.tsx +++ b/app/soapbox/components/account.tsx @@ -1,8 +1,8 @@ -import * as React from 'react'; +import React from 'react'; import { Link, useHistory } from 'react-router-dom'; -import HoverRefWrapper from 'soapbox/components/hover_ref_wrapper'; -import VerificationBadge from 'soapbox/components/verification_badge'; +import HoverRefWrapper from 'soapbox/components/hover-ref-wrapper'; +import VerificationBadge from 'soapbox/components/verification-badge'; import ActionButton from 'soapbox/features/ui/components/action-button'; import { useAppSelector, useOnScreen } from 'soapbox/hooks'; import { getAcct } from 'soapbox/utils/accounts'; @@ -201,7 +201,7 @@ const Account = ({ title={account.acct} onClick={(event: React.MouseEvent) => event.stopPropagation()} > -
+ {account.verified && } -
+ @@ -264,7 +264,7 @@ const Account = ({ )} diff --git a/app/soapbox/components/announcements/emoji.tsx b/app/soapbox/components/announcements/emoji.tsx index eb9683f082..64266639d5 100644 --- a/app/soapbox/components/announcements/emoji.tsx +++ b/app/soapbox/components/announcements/emoji.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import unicodeMapping from 'soapbox/features/emoji/emoji_unicode_mapping_light'; +import unicodeMapping from 'soapbox/features/emoji/emoji-unicode-mapping-light'; import { useSettings } from 'soapbox/hooks'; import { joinPublicPath } from 'soapbox/utils/static'; diff --git a/app/soapbox/components/announcements/reaction.tsx b/app/soapbox/components/announcements/reaction.tsx index 8e2391aec7..2306137019 100644 --- a/app/soapbox/components/announcements/reaction.tsx +++ b/app/soapbox/components/announcements/reaction.tsx @@ -2,7 +2,7 @@ import classNames from 'clsx'; import React, { useState } from 'react'; import AnimatedNumber from 'soapbox/components/animated-number'; -import unicodeMapping from 'soapbox/features/emoji/emoji_unicode_mapping_light'; +import unicodeMapping from 'soapbox/features/emoji/emoji-unicode-mapping-light'; import Emoji from './emoji'; diff --git a/app/soapbox/components/announcements/reactions-bar.tsx b/app/soapbox/components/announcements/reactions-bar.tsx index 130db2d994..f9569fb903 100644 --- a/app/soapbox/components/announcements/reactions-bar.tsx +++ b/app/soapbox/components/announcements/reactions-bar.tsx @@ -9,7 +9,7 @@ import { useSettings } from 'soapbox/hooks'; import Reaction from './reaction'; import type { List as ImmutableList, Map as ImmutableMap } from 'immutable'; -import type { Emoji } from 'soapbox/components/autosuggest_emoji'; +import type { Emoji } from 'soapbox/components/autosuggest-emoji'; import type { AnnouncementReaction } from 'soapbox/types/entities'; interface IReactionsBar { diff --git a/app/soapbox/components/attachment_list.tsx b/app/soapbox/components/attachment_list.tsx deleted file mode 100644 index 94c496819e..0000000000 --- a/app/soapbox/components/attachment_list.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import React from 'react'; - -import Icon from 'soapbox/components/icon'; - -import type { Attachment as AttachmentEntity } from 'soapbox/types/entities'; - -const filename = (url: string) => url.split('/').pop()!.split('#')[0].split('?')[0]; - -interface IAttachmentList { - media: AttachmentEntity[], - compact?: boolean, -} - -const AttachmentList: React.FC = ({ media, compact }) => { - if (compact) { - return ( -
-
    - {media.map(attachment => { - const displayUrl = attachment.get('remote_url') || attachment.get('url'); - - return ( -
  • - {filename(displayUrl)} -
  • - ); - })} -
-
- ); - } - - return ( -
-
- -
- -
    - {media.map(attachment => { - const displayUrl = attachment.get('remote_url') || attachment.get('url'); - - return ( -
  • - {filename(displayUrl)} -
  • - ); - })} -
-
- ); -}; - -export default AttachmentList; diff --git a/app/soapbox/components/autosuggest_account_input.tsx b/app/soapbox/components/autosuggest-account-input.tsx similarity index 95% rename from app/soapbox/components/autosuggest_account_input.tsx rename to app/soapbox/components/autosuggest-account-input.tsx index e8cd63830c..1be14c3ec0 100644 --- a/app/soapbox/components/autosuggest_account_input.tsx +++ b/app/soapbox/components/autosuggest-account-input.tsx @@ -3,13 +3,13 @@ import throttle from 'lodash/throttle'; import React, { useState, useRef, useCallback, useEffect } from 'react'; import { accountSearch } from 'soapbox/actions/accounts'; -import AutosuggestInput, { AutoSuggestion } from 'soapbox/components/autosuggest_input'; +import AutosuggestInput, { AutoSuggestion } from 'soapbox/components/autosuggest-input'; import { useAppDispatch } from 'soapbox/hooks'; -import type { Menu } from 'soapbox/components/dropdown_menu'; +import type { Menu } from 'soapbox/components/dropdown-menu'; import type { InputThemes } from 'soapbox/components/ui/input/input'; -const noOp = () => {}; +const noOp = () => { }; interface IAutosuggestAccountInput { onChange: React.ChangeEventHandler, diff --git a/app/soapbox/components/autosuggest_emoji.tsx b/app/soapbox/components/autosuggest-emoji.tsx similarity index 92% rename from app/soapbox/components/autosuggest_emoji.tsx rename to app/soapbox/components/autosuggest-emoji.tsx index 22979d4542..7074605a2e 100644 --- a/app/soapbox/components/autosuggest_emoji.tsx +++ b/app/soapbox/components/autosuggest-emoji.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import unicodeMapping from 'soapbox/features/emoji/emoji_unicode_mapping_light'; +import unicodeMapping from 'soapbox/features/emoji/emoji-unicode-mapping-light'; import { joinPublicPath } from 'soapbox/utils/static'; export type Emoji = { diff --git a/app/soapbox/components/autosuggest_input.tsx b/app/soapbox/components/autosuggest-input.tsx similarity index 99% rename from app/soapbox/components/autosuggest_input.tsx rename to app/soapbox/components/autosuggest-input.tsx index 01da067604..b5bc767b11 100644 --- a/app/soapbox/components/autosuggest_input.tsx +++ b/app/soapbox/components/autosuggest-input.tsx @@ -4,13 +4,13 @@ import { List as ImmutableList } from 'immutable'; import React from 'react'; import ImmutablePureComponent from 'react-immutable-pure-component'; -import AutosuggestEmoji, { Emoji } from 'soapbox/components/autosuggest_emoji'; +import AutosuggestEmoji, { Emoji } from 'soapbox/components/autosuggest-emoji'; import Icon from 'soapbox/components/icon'; import { Input } from 'soapbox/components/ui'; -import AutosuggestAccount from 'soapbox/features/compose/components/autosuggest_account'; +import AutosuggestAccount from 'soapbox/features/compose/components/autosuggest-account'; import { isRtl } from 'soapbox/rtl'; -import type { Menu, MenuItem } from 'soapbox/components/dropdown_menu'; +import type { Menu, MenuItem } from 'soapbox/components/dropdown-menu'; import type { InputThemes } from 'soapbox/components/ui/input/input'; type CursorMatch = [ diff --git a/app/soapbox/components/autosuggest_textarea.tsx b/app/soapbox/components/autosuggest-textarea.tsx similarity index 99% rename from app/soapbox/components/autosuggest_textarea.tsx rename to app/soapbox/components/autosuggest-textarea.tsx index 4f80d0b3bc..8e877021f4 100644 --- a/app/soapbox/components/autosuggest_textarea.tsx +++ b/app/soapbox/components/autosuggest-textarea.tsx @@ -4,10 +4,10 @@ import React from 'react'; import ImmutablePureComponent from 'react-immutable-pure-component'; import Textarea from 'react-textarea-autosize'; -import AutosuggestAccount from '../features/compose/components/autosuggest_account'; +import AutosuggestAccount from '../features/compose/components/autosuggest-account'; import { isRtl } from '../rtl'; -import AutosuggestEmoji, { Emoji } from './autosuggest_emoji'; +import AutosuggestEmoji, { Emoji } from './autosuggest-emoji'; import type { List as ImmutableList } from 'immutable'; diff --git a/app/soapbox/components/avatar_overlay.tsx b/app/soapbox/components/avatar-overlay.tsx similarity index 89% rename from app/soapbox/components/avatar_overlay.tsx rename to app/soapbox/components/avatar-overlay.tsx index ae38b5e4c8..a463b35ce4 100644 --- a/app/soapbox/components/avatar_overlay.tsx +++ b/app/soapbox/components/avatar-overlay.tsx @@ -1,6 +1,6 @@ import React from 'react'; -import StillImage from 'soapbox/components/still_image'; +import StillImage from 'soapbox/components/still-image'; import type { Account as AccountEntity } from 'soapbox/types/entities'; diff --git a/app/soapbox/components/avatar.tsx b/app/soapbox/components/avatar.tsx index 4f40d46bb0..4bc5c07748 100644 --- a/app/soapbox/components/avatar.tsx +++ b/app/soapbox/components/avatar.tsx @@ -1,7 +1,7 @@ import classNames from 'clsx'; import React from 'react'; -import StillImage from 'soapbox/components/still_image'; +import StillImage from 'soapbox/components/still-image'; import type { Account } from 'soapbox/types/entities'; diff --git a/app/soapbox/components/birthday_input.tsx b/app/soapbox/components/birthday-input.tsx similarity index 98% rename from app/soapbox/components/birthday_input.tsx rename to app/soapbox/components/birthday-input.tsx index fc9521ca04..21a10a1e59 100644 --- a/app/soapbox/components/birthday_input.tsx +++ b/app/soapbox/components/birthday-input.tsx @@ -1,8 +1,8 @@ import React, { useMemo } from 'react'; import { defineMessages, useIntl } from 'react-intl'; -import IconButton from 'soapbox/components/icon_button'; -import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; +import IconButton from 'soapbox/components/icon-button'; +import BundleContainer from 'soapbox/features/ui/containers/bundle-container'; import { DatePicker } from 'soapbox/features/ui/util/async-components'; import { useAppSelector, useFeatures } from 'soapbox/hooks'; diff --git a/app/soapbox/components/birthday-panel.tsx b/app/soapbox/components/birthday-panel.tsx index 8381203b95..059b8678b3 100644 --- a/app/soapbox/components/birthday-panel.tsx +++ b/app/soapbox/components/birthday-panel.tsx @@ -4,7 +4,7 @@ import { FormattedMessage } from 'react-intl'; import { fetchBirthdayReminders } from 'soapbox/actions/accounts'; import { Widget } from 'soapbox/components/ui'; -import AccountContainer from 'soapbox/containers/account_container'; +import AccountContainer from 'soapbox/containers/account-container'; import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; const timeToMidnight = () => { diff --git a/app/soapbox/components/column_header.js b/app/soapbox/components/column-header.js similarity index 98% rename from app/soapbox/components/column_header.js rename to app/soapbox/components/column-header.js index 83a61b7ea2..2d915c9f81 100644 Binary files a/app/soapbox/components/column_header.js and b/app/soapbox/components/column-header.js differ diff --git a/app/soapbox/components/copyable-input.tsx b/app/soapbox/components/copyable-input.tsx index c38cc8c5b3..24253d7df3 100644 --- a/app/soapbox/components/copyable-input.tsx +++ b/app/soapbox/components/copyable-input.tsx @@ -28,7 +28,7 @@ const CopyableInput: React.FC = ({ value }) => { ref={input} type='text' value={value} - className='rounded-r-none' + className='rounded-r-none rtl:rounded-l-none rtl:rounded-r-lg' outerClassName='flex-grow' onClick={selectInput} readOnly @@ -36,7 +36,7 @@ const CopyableInput: React.FC = ({ value }) => { ); diff --git a/app/soapbox/components/ui/accordion/accordion.tsx b/app/soapbox/components/ui/accordion/accordion.tsx new file mode 100644 index 0000000000..299848d84e --- /dev/null +++ b/app/soapbox/components/ui/accordion/accordion.tsx @@ -0,0 +1,74 @@ +import classNames from 'clsx'; +import React from 'react'; +import { defineMessages, useIntl } from 'react-intl'; + +import { HStack, Icon, Text } from 'soapbox/components/ui'; +import DropdownMenu from 'soapbox/containers/dropdown-menu-container'; + +import type { Menu } from 'soapbox/components/dropdown-menu'; + +const messages = defineMessages({ + collapse: { id: 'accordion.collapse', defaultMessage: 'Collapse' }, + expand: { id: 'accordion.expand', defaultMessage: 'Expand' }, +}); + +interface IAccordion { + headline: React.ReactNode, + children?: React.ReactNode, + menu?: Menu, + expanded?: boolean, + onToggle?: (value: boolean) => void, +} + +/** + * Accordion + * An accordion is a vertically stacked group of collapsible sections. + */ +const Accordion: React.FC = ({ headline, children, menu, expanded = false, onToggle = () => {} }) => { + const intl = useIntl(); + + const handleToggle = (e: React.MouseEvent) => { + onToggle(!expanded); + e.preventDefault(); + }; + + return ( +
+ + +
+ {children} +
+
+ ); +}; + +export default Accordion; diff --git a/app/soapbox/components/ui/avatar/avatar.tsx b/app/soapbox/components/ui/avatar/avatar.tsx index bdd38df9c1..384fa354df 100644 --- a/app/soapbox/components/ui/avatar/avatar.tsx +++ b/app/soapbox/components/ui/avatar/avatar.tsx @@ -1,7 +1,7 @@ import classNames from 'clsx'; -import * as React from 'react'; +import React from 'react'; -import StillImage from 'soapbox/components/still_image'; +import StillImage from 'soapbox/components/still-image'; const AVATAR_SIZE = 42; @@ -25,7 +25,7 @@ const Avatar = (props: IAvatar) => { return ( (({ children, variant = 'def ref={ref} {...filteredProps} className={classNames({ - 'bg-white dark:bg-primary-900 text-gray-900 dark:text-gray-100 shadow-lg dark:shadow-none overflow-hidden': variant === 'rounded', + 'bg-white dark:bg-primary-900 text-gray-900 dark:text-gray-100 shadow-lg dark:shadow-none overflow-hidden isolate': variant === 'rounded', [sizes[size]]: variant === 'rounded', }, className)} > @@ -62,7 +62,7 @@ const CardHeader: React.FC = ({ children, backHref, onBackClick }): const backAttributes = backHref ? { to: backHref } : { onClick: onBackClick }; return ( - + {intl.formatMessage(messages.back)} @@ -70,11 +70,11 @@ const CardHeader: React.FC = ({ children, backHref, onBackClick }): }; return ( -
+ {renderBackButton()} {children} -
+ ); }; diff --git a/app/soapbox/components/ui/emoji/__tests__/emoji.test.tsx b/app/soapbox/components/ui/emoji/__tests__/emoji.test.tsx index 85126806f9..c87ef9040d 100644 --- a/app/soapbox/components/ui/emoji/__tests__/emoji.test.tsx +++ b/app/soapbox/components/ui/emoji/__tests__/emoji.test.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; import { render, screen } from '../../../../jest/test-helpers'; import Emoji from '../emoji'; diff --git a/app/soapbox/components/ui/form-actions/form-actions.tsx b/app/soapbox/components/ui/form-actions/form-actions.tsx index a09fb02dcf..f1480e07c6 100644 --- a/app/soapbox/components/ui/form-actions/form-actions.tsx +++ b/app/soapbox/components/ui/form-actions/form-actions.tsx @@ -1,10 +1,12 @@ import React from 'react'; +import HStack from '../hstack/hstack'; + /** Container element to house form actions. */ const FormActions: React.FC = ({ children }) => ( -
+ {children} -
+ ); export default FormActions; diff --git a/app/soapbox/components/ui/form/form.tsx b/app/soapbox/components/ui/form/form.tsx index 59ca180b1f..466825434c 100644 --- a/app/soapbox/components/ui/form/form.tsx +++ b/app/soapbox/components/ui/form/form.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; interface IForm { /** Form submission event handler. */ diff --git a/app/soapbox/components/ui/hstack/hstack.tsx b/app/soapbox/components/ui/hstack/hstack.tsx index 996320deaa..4f31a3403c 100644 --- a/app/soapbox/components/ui/hstack/hstack.tsx +++ b/app/soapbox/components/ui/hstack/hstack.tsx @@ -21,13 +21,15 @@ const spaces = { 1: 'space-x-1', 1.5: 'space-x-1.5', 2: 'space-x-2', + 2.5: 'space-x-2.5', 3: 'space-x-3', 4: 'space-x-4', + 5: 'space-x-5', 6: 'space-x-6', 8: 'space-x-8', }; -interface IHStack { +interface IHStack extends Pick, 'onClick'> { /** Vertical alignment of children. */ alignItems?: keyof typeof alignItemsOptions /** Extra class names on the
element. */ @@ -58,7 +60,7 @@ const HStack = forwardRef((props, ref) => { ( 'rounded-md bg-white dark:bg-gray-900 border-gray-400 dark:border-gray-800': theme === 'normal', 'rounded-full bg-gray-200 border-gray-200 dark:bg-gray-800 dark:border-gray-800 focus:bg-white': theme === 'search', 'bg-transparent border-none': theme === 'transparent', - 'pr-7': isPassword || append, + 'pr-7 rtl:pl-7 rtl:pr-3': isPassword || append, 'text-red-600 border-red-600': hasError, 'pl-8': typeof icon !== 'undefined', 'pl-16': typeof prepend !== 'undefined', }, className)} /> - {/* eslint-disable-next-line no-nested-ternary */} {append ? ( -
+
{append}
) : null} @@ -111,7 +110,7 @@ const Input = React.forwardRef( intl.formatMessage(messages.showPassword) } > -
+
-
+
)}
diff --git a/app/soapbox/components/ui/radio-button/radio-button.tsx b/app/soapbox/components/ui/radio-button/radio-button.tsx new file mode 100644 index 0000000000..96f2c2ec44 --- /dev/null +++ b/app/soapbox/components/ui/radio-button/radio-button.tsx @@ -0,0 +1,39 @@ +import React, { useMemo } from 'react'; +import { v4 as uuidv4 } from 'uuid'; + +import HStack from '../hstack/hstack'; + +interface IRadioButton { + value: string + checked?: boolean + name: string + onChange: React.ChangeEventHandler + label: React.ReactNode +} + +/** + * A group for radio input with label. + */ +const RadioButton: React.FC = ({ name, value, checked, onChange, label }) => { + const formFieldId: string = useMemo(() => `radio-${uuidv4()}`, []); + + return ( + + + + + + ); +}; + +export default RadioButton; diff --git a/app/soapbox/components/ui/select/select.tsx b/app/soapbox/components/ui/select/select.tsx index b8d05b79da..8c2369ce56 100644 --- a/app/soapbox/components/ui/select/select.tsx +++ b/app/soapbox/components/ui/select/select.tsx @@ -1,4 +1,4 @@ -import * as React from 'react'; +import React from 'react'; interface ISelect extends React.SelectHTMLAttributes { children: Iterable, diff --git a/app/soapbox/components/ui/tabs/tabs.tsx b/app/soapbox/components/ui/tabs/tabs.tsx index 49316529af..2839085799 100644 --- a/app/soapbox/components/ui/tabs/tabs.tsx +++ b/app/soapbox/components/ui/tabs/tabs.tsx @@ -6,7 +6,7 @@ import { useTabsContext, } from '@reach/tabs'; import classNames from 'clsx'; -import * as React from 'react'; +import React from 'react'; import { useHistory } from 'react-router-dom'; import Counter from '../counter/counter'; diff --git a/app/soapbox/components/ui/text/text.tsx b/app/soapbox/components/ui/text/text.tsx index 7669f3d2a8..221c070fc4 100644 --- a/app/soapbox/components/ui/text/text.tsx +++ b/app/soapbox/components/ui/text/text.tsx @@ -54,7 +54,9 @@ export type Sizes = keyof typeof sizes type Tags = 'abbr' | 'p' | 'span' | 'pre' | 'time' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'label' type Directions = 'ltr' | 'rtl' -interface IText extends Pick, 'dangerouslySetInnerHTML'> { +interface IText extends Pick, 'dangerouslySetInnerHTML' | 'tabIndex' | 'lang'> { + /** Text content. */ + children?: React.ReactNode, /** How to align the text. */ align?: keyof typeof alignments, /** Extra class names for the outer element. */ @@ -84,8 +86,8 @@ interface IText extends Pick, 'danger } /** UI-friendly text container with dark mode support. */ -const Text: React.FC = React.forwardRef( - (props: IText, ref: React.LegacyRef) => { +const Text = React.forwardRef( + (props, ref) => { const { align, className, diff --git a/app/soapbox/components/ui/textarea/textarea.tsx b/app/soapbox/components/ui/textarea/textarea.tsx index e93229e6a0..ddf0c9d7d4 100644 --- a/app/soapbox/components/ui/textarea/textarea.tsx +++ b/app/soapbox/components/ui/textarea/textarea.tsx @@ -1,7 +1,7 @@ import classNames from 'clsx'; import React from 'react'; -interface ITextarea extends Pick, 'maxLength' | 'onChange' | 'onKeyDown' | 'required' | 'disabled' | 'rows' | 'readOnly'> { +interface ITextarea extends Pick, 'maxLength' | 'onChange' | 'onKeyDown' | 'onPaste' | 'required' | 'disabled' | 'rows' | 'readOnly'> { /** Put the cursor into the input on mount. */ autoFocus?: boolean, /** The initial text in the input. */ diff --git a/app/soapbox/components/ui/widget/widget.tsx b/app/soapbox/components/ui/widget/widget.tsx index 3bced193fa..16cc33234f 100644 --- a/app/soapbox/components/ui/widget/widget.tsx +++ b/app/soapbox/components/ui/widget/widget.tsx @@ -1,8 +1,6 @@ import React from 'react'; -import { Text, IconButton } from 'soapbox/components/ui'; -import HStack from 'soapbox/components/ui/hstack/hstack'; -import Stack from 'soapbox/components/ui/stack/stack'; +import { HStack, IconButton, Stack, Text } from 'soapbox/components/ui'; interface IWidgetTitle { /** Title text for the widget. */ diff --git a/app/soapbox/components/upload-progress.tsx b/app/soapbox/components/upload-progress.tsx index a7996e1bfd..fe9b84797b 100644 --- a/app/soapbox/components/upload-progress.tsx +++ b/app/soapbox/components/upload-progress.tsx @@ -3,7 +3,7 @@ import { FormattedMessage } from 'react-intl'; import { spring } from 'react-motion'; import { HStack, Icon, Stack, Text } from 'soapbox/components/ui'; -import Motion from 'soapbox/features/ui/util/optional_motion'; +import Motion from 'soapbox/features/ui/util/optional-motion'; interface IUploadProgress { /** Number between 0 and 1 to represent the percentage complete. */ diff --git a/app/soapbox/components/verification_badge.tsx b/app/soapbox/components/verification-badge.tsx similarity index 87% rename from app/soapbox/components/verification_badge.tsx rename to app/soapbox/components/verification-badge.tsx index ce1d3792a7..aea2f5f810 100644 --- a/app/soapbox/components/verification_badge.tsx +++ b/app/soapbox/components/verification-badge.tsx @@ -2,7 +2,7 @@ import classNames from 'clsx'; import React from 'react'; import { useIntl, defineMessages } from 'react-intl'; -import Icon from 'soapbox/components/ui/icon/icon'; +import { Icon } from 'soapbox/components/ui'; import { useSoapboxConfig } from 'soapbox/hooks'; const messages = defineMessages({ @@ -18,7 +18,7 @@ const VerificationBadge: React.FC = ({ className }) => { const soapboxConfig = useSoapboxConfig(); // Prefer a custom icon if found - const icon = soapboxConfig.verifiedIcon || require('icons/verified.svg'); + const icon = soapboxConfig.verifiedIcon || require('assets/icons/verified.svg'); // Render component based on file extension const Element = icon.endsWith('.svg') ? Icon : 'img'; diff --git a/app/soapbox/containers/account_container.js b/app/soapbox/containers/account-container.js similarity index 100% rename from app/soapbox/containers/account_container.js rename to app/soapbox/containers/account-container.js diff --git a/app/soapbox/containers/dropdown_menu_container.ts b/app/soapbox/containers/dropdown-menu-container.ts similarity index 89% rename from app/soapbox/containers/dropdown_menu_container.ts rename to app/soapbox/containers/dropdown-menu-container.ts index b047edfff5..936e3c5c20 100644 --- a/app/soapbox/containers/dropdown_menu_container.ts +++ b/app/soapbox/containers/dropdown-menu-container.ts @@ -1,12 +1,12 @@ import { connect } from 'react-redux'; -import { openDropdownMenu, closeDropdownMenu } from '../actions/dropdown_menu'; +import { openDropdownMenu, closeDropdownMenu } from '../actions/dropdown-menu'; import { openModal, closeModal } from '../actions/modals'; -import DropdownMenu from '../components/dropdown_menu'; -import { isUserTouching } from '../is_mobile'; +import DropdownMenu from '../components/dropdown-menu'; +import { isUserTouching } from '../is-mobile'; import type { Dispatch } from 'redux'; -import type { DropdownPlacement, IDropdown } from 'soapbox/components/dropdown_menu'; +import type { DropdownPlacement, IDropdown } from 'soapbox/components/dropdown-menu'; import type { RootState } from 'soapbox/store'; const mapStateToProps = (state: RootState) => ({ diff --git a/app/soapbox/containers/soapbox.tsx b/app/soapbox/containers/soapbox.tsx index 2841ec3caa..ce02d068df 100644 --- a/app/soapbox/containers/soapbox.tsx +++ b/app/soapbox/containers/soapbox.tsx @@ -13,14 +13,14 @@ import { loadInstance } from 'soapbox/actions/instance'; import { fetchMe } from 'soapbox/actions/me'; import { loadSoapboxConfig, getSoapboxConfig } from 'soapbox/actions/soapbox'; import { fetchVerificationConfig } from 'soapbox/actions/verification'; -import * as BuildConfig from 'soapbox/build_config'; +import * as BuildConfig from 'soapbox/build-config'; import GdprBanner from 'soapbox/components/gdpr-banner'; import Helmet from 'soapbox/components/helmet'; import LoadingScreen from 'soapbox/components/loading-screen'; -import AuthLayout from 'soapbox/features/auth_layout'; +import AuthLayout from 'soapbox/features/auth-layout'; import EmbeddedStatus from 'soapbox/features/embedded-status'; -import PublicLayout from 'soapbox/features/public_layout'; -import BundleContainer from 'soapbox/features/ui/containers/bundle_container'; +import PublicLayout from 'soapbox/features/public-layout'; +import BundleContainer from 'soapbox/features/ui/containers/bundle-container'; import { ModalContainer, NotificationsContainer, @@ -45,10 +45,12 @@ import { generateThemeCss } from 'soapbox/utils/theme'; import { checkOnboardingStatus } from '../actions/onboarding'; import { preload } from '../actions/preload'; -import ErrorBoundary from '../components/error_boundary'; +import ErrorBoundary from '../components/error-boundary'; import UI from '../features/ui'; import { store } from '../store'; +const RTL_LOCALES = ['ar', 'ckb', 'fa', 'he']; + // Configure global functions for developers createGlobals(store); @@ -276,7 +278,7 @@ const SoapboxHead: React.FC = ({ children }) => { <> - + {themeCss && } {darkMode && } diff --git a/app/soapbox/containers/status_container.tsx b/app/soapbox/containers/status-container.tsx similarity index 100% rename from app/soapbox/containers/status_container.tsx rename to app/soapbox/containers/status-container.tsx diff --git a/app/soapbox/custom.ts b/app/soapbox/custom.ts index 4bccb386d5..461f64845e 100644 --- a/app/soapbox/custom.ts +++ b/app/soapbox/custom.ts @@ -1,7 +1,7 @@ /** * Functions for dealing with custom build configuration. */ -import * as BuildConfig from 'soapbox/build_config'; +import * as BuildConfig from 'soapbox/build-config'; /** Require a custom JSON file if it exists */ export const custom = (filename: string, fallback: any = {}): any => { diff --git a/app/soapbox/extra_polyfills.ts b/app/soapbox/extra-polyfills.ts similarity index 100% rename from app/soapbox/extra_polyfills.ts rename to app/soapbox/extra-polyfills.ts diff --git a/app/soapbox/features/about/index.tsx b/app/soapbox/features/about/index.tsx index 5c184a97af..9cc1e92955 100644 --- a/app/soapbox/features/about/index.tsx +++ b/app/soapbox/features/about/index.tsx @@ -35,11 +35,11 @@ const AboutPage: React.FC = () => { }, [locale, slug]); const alsoAvailable = (defaultLocale) && ( -
+
{' '} -
    -
  • +
      +
    • setLocale(defaultLocale)}> {/* @ts-ignore */} {languages[defaultLocale] || defaultLocale} @@ -47,7 +47,7 @@ const AboutPage: React.FC = () => {
    • { pageLocales?.map(locale => ( -
    • +
    • setLocale(locale)}> {/* @ts-ignore */} {languages[locale] || locale} @@ -60,14 +60,10 @@ const AboutPage: React.FC = () => { ); return ( -
      -
      -
      - {alsoAvailable} -
      +
      +
      + + {alsoAvailable}
      ); }; diff --git a/app/soapbox/features/account_gallery/components/media_item.tsx b/app/soapbox/features/account-gallery/components/media-item.tsx similarity index 96% rename from app/soapbox/features/account_gallery/components/media_item.tsx rename to app/soapbox/features/account-gallery/components/media-item.tsx index d98f74363e..4242094b55 100644 --- a/app/soapbox/features/account_gallery/components/media_item.tsx +++ b/app/soapbox/features/account-gallery/components/media-item.tsx @@ -3,9 +3,9 @@ import React, { useState } from 'react'; import Blurhash from 'soapbox/components/blurhash'; import Icon from 'soapbox/components/icon'; -import StillImage from 'soapbox/components/still_image'; +import StillImage from 'soapbox/components/still-image'; import { useSettings } from 'soapbox/hooks'; -import { isIOS } from 'soapbox/is_mobile'; +import { isIOS } from 'soapbox/is-mobile'; import type { Attachment } from 'soapbox/types/entities'; @@ -74,6 +74,7 @@ const MediaItem: React.FC = ({ attachment, displayWidth, onOpenMedia src={attachment.preview_url} alt={attachment.description} style={{ objectPosition: `${x}% ${y}%` }} + className='w-full h-full rounded-lg overflow-hidden' /> ); } else if (['gifv', 'video'].indexOf(attachment.type) !== -1) { diff --git a/app/soapbox/features/account_gallery/index.tsx b/app/soapbox/features/account-gallery/index.tsx similarity index 97% rename from app/soapbox/features/account_gallery/index.tsx rename to app/soapbox/features/account-gallery/index.tsx index ddd2b31606..da6fb226af 100644 --- a/app/soapbox/features/account_gallery/index.tsx +++ b/app/soapbox/features/account-gallery/index.tsx @@ -8,14 +8,14 @@ import { } from 'soapbox/actions/accounts'; import { openModal } from 'soapbox/actions/modals'; import { expandAccountMediaTimeline } from 'soapbox/actions/timelines'; -import LoadMore from 'soapbox/components/load_more'; -import MissingIndicator from 'soapbox/components/missing_indicator'; +import LoadMore from 'soapbox/components/load-more'; +import MissingIndicator from 'soapbox/components/missing-indicator'; import { Column, Spinner } from 'soapbox/components/ui'; import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; import { getAccountGallery, findAccountByUsername } from 'soapbox/selectors'; import { getFeatures } from 'soapbox/utils/features'; -import MediaItem from './components/media_item'; +import MediaItem from './components/media-item'; import type { List as ImmutableList } from 'immutable'; import type { Attachment, Status } from 'soapbox/types/entities'; diff --git a/app/soapbox/features/account-timeline/components/moved-note.tsx b/app/soapbox/features/account-timeline/components/moved-note.tsx new file mode 100644 index 0000000000..cfd752fc1d --- /dev/null +++ b/app/soapbox/features/account-timeline/components/moved-note.tsx @@ -0,0 +1,41 @@ +import React from 'react'; +import { FormattedMessage } from 'react-intl'; + +import Account from 'soapbox/components/account'; +import Icon from 'soapbox/components/icon'; +import { HStack, Text } from 'soapbox/components/ui'; + +import type { Account as AccountEntity } from 'soapbox/types/entities'; + +interface IMovedNote { + from: AccountEntity, + to: AccountEntity, +} + +const MovedNote: React.FC = ({ from, to }) => ( +
      + + + +
      + + , + targetName: to.acct, + }} + /> + +
      +
      + + +
      +); + +export default MovedNote; diff --git a/app/soapbox/features/account_timeline/index.tsx b/app/soapbox/features/account-timeline/index.tsx similarity index 97% rename from app/soapbox/features/account_timeline/index.tsx rename to app/soapbox/features/account-timeline/index.tsx index 3ebe43d1df..fb99ca04c4 100644 --- a/app/soapbox/features/account_timeline/index.tsx +++ b/app/soapbox/features/account-timeline/index.tsx @@ -5,8 +5,8 @@ import { useHistory } from 'react-router-dom'; import { fetchAccountByUsername } from 'soapbox/actions/accounts'; import { fetchPatronAccount } from 'soapbox/actions/patron'; import { expandAccountFeaturedTimeline, expandAccountTimeline } from 'soapbox/actions/timelines'; -import MissingIndicator from 'soapbox/components/missing_indicator'; -import StatusList from 'soapbox/components/status_list'; +import MissingIndicator from 'soapbox/components/missing-indicator'; +import StatusList from 'soapbox/components/status-list'; import { Card, CardBody, Spinner, Text } from 'soapbox/components/ui'; import { useAppDispatch, useAppSelector, useFeatures, useSettings, useSoapboxConfig } from 'soapbox/hooks'; import { makeGetStatusIds, findAccountByUsername } from 'soapbox/selectors'; diff --git a/app/soapbox/features/account/components/header.tsx b/app/soapbox/features/account/components/header.tsx index 91e2685b75..5d42164a62 100644 --- a/app/soapbox/features/account/components/header.tsx +++ b/app/soapbox/features/account/components/header.tsx @@ -8,7 +8,7 @@ import { Link, useHistory } from 'react-router-dom'; import { blockAccount, followAccount, pinAccount, removeFromFollowers, unblockAccount, unmuteAccount, unpinAccount } from 'soapbox/actions/accounts'; import { launchChat } from 'soapbox/actions/chats'; import { mentionCompose, directCompose } from 'soapbox/actions/compose'; -import { blockDomain, unblockDomain } from 'soapbox/actions/domain_blocks'; +import { blockDomain, unblockDomain } from 'soapbox/actions/domain-blocks'; import { openModal } from 'soapbox/actions/modals'; import { initMuteModal } from 'soapbox/actions/mutes'; import { initReport } from 'soapbox/actions/reports'; @@ -16,10 +16,10 @@ import { setSearchAccount } from 'soapbox/actions/search'; import { getSettings } from 'soapbox/actions/settings'; import snackbar from 'soapbox/actions/snackbar'; import Badge from 'soapbox/components/badge'; -import StillImage from 'soapbox/components/still_image'; -import { HStack, IconButton, Menu, MenuButton, MenuItem, MenuList, MenuLink, MenuDivider, Avatar } from 'soapbox/components/ui'; +import StillImage from 'soapbox/components/still-image'; +import { Avatar, HStack, IconButton, Menu, MenuButton, MenuDivider, MenuItem, MenuLink, MenuList } from 'soapbox/components/ui'; import SvgIcon from 'soapbox/components/ui/icon/svg-icon'; -import MovedNote from 'soapbox/features/account_timeline/components/moved_note'; +import MovedNote from 'soapbox/features/account-timeline/components/moved-note'; import ActionButton from 'soapbox/features/ui/components/action-button'; import SubscriptionButton from 'soapbox/features/ui/components/subscription-button'; import { useAppDispatch, useFeatures, useOwnAccount } from 'soapbox/hooks'; @@ -27,7 +27,7 @@ import { normalizeAttachment } from 'soapbox/normalizers'; import { Account } from 'soapbox/types/entities'; import { isRemote } from 'soapbox/utils/accounts'; -import type { Menu as MenuType } from 'soapbox/components/dropdown_menu'; +import type { Menu as MenuType } from 'soapbox/components/dropdown-menu'; const messages = defineMessages({ edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' }, @@ -66,6 +66,8 @@ const messages = defineMessages({ removeFromFollowersConfirm: { id: 'confirmations.remove_from_followers.confirm', defaultMessage: 'Remove' }, userEndorsed: { id: 'account.endorse.success', defaultMessage: 'You are now featuring @{acct} on your profile' }, userUnendorsed: { id: 'account.unendorse.success', defaultMessage: 'You are no longer featuring @{acct}' }, + profileExternal: { id: 'account.profile_external', defaultMessage: 'View profile on {domain}' }, + header: { id: 'account.header.alt', defaultMessage: 'Profile header' }, composeEvent: { od: 'navigation.compose_event', defaultMessage: 'Create new event' }, }); @@ -89,13 +91,13 @@ const Header: React.FC = ({ account }) => {
      -
      +
      -
      +
      ); @@ -174,6 +176,10 @@ const Header: React.FC = ({ account }) => { dispatch(unblockDomain(domain)); }; + const onProfileExternal = (url: string) => { + window.open(url, '_blank'); + }; + const onAddToList = () => { dispatch(openModal('LIST_ADDER', { accountId: account.id, @@ -433,6 +439,14 @@ const Header: React.FC = ({ account }) => { icon: require('@tabler/icons/ban.svg'), }); } + + if (features.federating) { + menu.push({ + text: intl.formatMessage(messages.profileExternal, { domain }), + action: () => onProfileExternal(account.url), + icon: require('@tabler/icons/external-link.svg'), + }); + } } if (ownAccount?.staff) { @@ -550,13 +564,12 @@ const Header: React.FC = ({ account }) => { )}
      -
      +
      {account.header && ( )} @@ -570,19 +583,19 @@ const Header: React.FC = ({ account }) => {
      -
      +
      -
      + {ownAccount && ( @@ -606,13 +619,13 @@ const Header: React.FC = ({ account }) => { return ( -
      + {menuItem.icon && ( - + )}
      {menuItem.text}
      -
      +
      ); } @@ -625,9 +638,9 @@ const Header: React.FC = ({ account }) => { {/* {renderMessageButton()} */} -
      +
      -
      +
      ); diff --git a/app/soapbox/features/account_timeline/components/moved_note.tsx b/app/soapbox/features/account_timeline/components/moved_note.tsx deleted file mode 100644 index 0ba6d8da56..0000000000 --- a/app/soapbox/features/account_timeline/components/moved_note.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; -import { FormattedMessage } from 'react-intl'; -import { NavLink } from 'react-router-dom'; - -import AvatarOverlay from 'soapbox/components/avatar_overlay'; -import DisplayName from 'soapbox/components/display-name'; -import Icon from 'soapbox/components/icon'; - -import type { Account as AccountEntity } from 'soapbox/types/entities'; - -interface IMovedNote { - from: AccountEntity, - to: AccountEntity, -} - -const MovedNote: React.FC = ({ from, to }) => { - const displayNameHtml = { __html: from.display_name_html }; - - return ( -
      -
      -
      - }} /> -
      - - -
      - -
      -
      - ); -}; - -export default MovedNote; diff --git a/app/soapbox/features/admin/components/latest_accounts_panel.tsx b/app/soapbox/features/admin/components/latest-accounts-panel.tsx similarity index 94% rename from app/soapbox/features/admin/components/latest_accounts_panel.tsx rename to app/soapbox/features/admin/components/latest-accounts-panel.tsx index 07b3c3f9d4..81efa7d46b 100644 --- a/app/soapbox/features/admin/components/latest_accounts_panel.tsx +++ b/app/soapbox/features/admin/components/latest-accounts-panel.tsx @@ -4,10 +4,10 @@ import { defineMessages, useIntl } from 'react-intl'; import { useHistory } from 'react-router-dom'; import { fetchUsers } from 'soapbox/actions/admin'; -import compareId from 'soapbox/compare_id'; import { Widget } from 'soapbox/components/ui'; -import AccountContainer from 'soapbox/containers/account_container'; +import AccountContainer from 'soapbox/containers/account-container'; import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; +import { compareId } from 'soapbox/utils/comparators'; const messages = defineMessages({ title: { id: 'admin.latest_accounts_panel.title', defaultMessage: 'Latest Accounts' }, diff --git a/app/soapbox/features/admin/components/registration_mode_picker.tsx b/app/soapbox/features/admin/components/registration-mode-picker.tsx similarity index 100% rename from app/soapbox/features/admin/components/registration_mode_picker.tsx rename to app/soapbox/features/admin/components/registration-mode-picker.tsx diff --git a/app/soapbox/features/admin/components/report_status.tsx b/app/soapbox/features/admin/components/report-status.tsx similarity index 96% rename from app/soapbox/features/admin/components/report_status.tsx rename to app/soapbox/features/admin/components/report-status.tsx index 6300c4e333..c863bda5c3 100644 --- a/app/soapbox/features/admin/components/report_status.tsx +++ b/app/soapbox/features/admin/components/report-status.tsx @@ -4,8 +4,8 @@ import { useIntl, defineMessages } from 'react-intl'; import { openModal } from 'soapbox/actions/modals'; import { deleteStatusModal } from 'soapbox/actions/moderation'; -import StatusContent from 'soapbox/components/status_content'; -import DropdownMenu from 'soapbox/containers/dropdown_menu_container'; +import StatusContent from 'soapbox/components/status-content'; +import DropdownMenu from 'soapbox/containers/dropdown-menu-container'; import Bundle from 'soapbox/features/ui/components/bundle'; import { MediaGallery, Video, Audio } from 'soapbox/features/ui/util/async-components'; import { useAppDispatch } from 'soapbox/hooks'; diff --git a/app/soapbox/features/admin/components/report.tsx b/app/soapbox/features/admin/components/report.tsx index 75c3ecb1d3..4c37b7b61b 100644 --- a/app/soapbox/features/admin/components/report.tsx +++ b/app/soapbox/features/admin/components/report.tsx @@ -6,14 +6,13 @@ import { closeReports } from 'soapbox/actions/admin'; import { deactivateUserModal, deleteUserModal } from 'soapbox/actions/moderation'; import snackbar from 'soapbox/actions/snackbar'; import Avatar from 'soapbox/components/avatar'; -import HoverRefWrapper from 'soapbox/components/hover_ref_wrapper'; -import { Button, HStack } from 'soapbox/components/ui'; -import DropdownMenu from 'soapbox/containers/dropdown_menu_container'; -import Accordion from 'soapbox/features/ui/components/accordion'; +import HoverRefWrapper from 'soapbox/components/hover-ref-wrapper'; +import { Accordion, Button, HStack } from 'soapbox/components/ui'; +import DropdownMenu from 'soapbox/containers/dropdown-menu-container'; import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; import { makeGetReport } from 'soapbox/selectors'; -import ReportStatus from './report_status'; +import ReportStatus from './report-status'; import type { List as ImmutableList } from 'immutable'; import type { Account, AdminReport, Status } from 'soapbox/types/entities'; diff --git a/app/soapbox/features/admin/components/unapproved_account.tsx b/app/soapbox/features/admin/components/unapproved-account.tsx similarity index 97% rename from app/soapbox/features/admin/components/unapproved_account.tsx rename to app/soapbox/features/admin/components/unapproved-account.tsx index a014216434..c1dae46fb8 100644 --- a/app/soapbox/features/admin/components/unapproved_account.tsx +++ b/app/soapbox/features/admin/components/unapproved-account.tsx @@ -4,7 +4,7 @@ import { defineMessages, useIntl } from 'react-intl'; import { approveUsers } from 'soapbox/actions/admin'; import { rejectUserModal } from 'soapbox/actions/moderation'; import snackbar from 'soapbox/actions/snackbar'; -import IconButton from 'soapbox/components/icon_button'; +import IconButton from 'soapbox/components/icon-button'; import { useAppSelector, useAppDispatch } from 'soapbox/hooks'; import { makeGetAccount } from 'soapbox/selectors'; diff --git a/app/soapbox/features/admin/moderation_log.tsx b/app/soapbox/features/admin/moderation-log.tsx similarity index 97% rename from app/soapbox/features/admin/moderation_log.tsx rename to app/soapbox/features/admin/moderation-log.tsx index 606858ec8d..063e3092aa 100644 --- a/app/soapbox/features/admin/moderation_log.tsx +++ b/app/soapbox/features/admin/moderation-log.tsx @@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react'; import { defineMessages, FormattedDate, useIntl } from 'react-intl'; import { fetchModerationLog } from 'soapbox/actions/admin'; -import ScrollableList from 'soapbox/components/scrollable_list'; +import ScrollableList from 'soapbox/components/scrollable-list'; import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; import Column from '../ui/components/column'; diff --git a/app/soapbox/features/admin/tabs/awaiting-approval.tsx b/app/soapbox/features/admin/tabs/awaiting-approval.tsx index 6f79897a6f..0a412f4002 100644 --- a/app/soapbox/features/admin/tabs/awaiting-approval.tsx +++ b/app/soapbox/features/admin/tabs/awaiting-approval.tsx @@ -2,10 +2,10 @@ import React, { useState, useEffect } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { fetchUsers } from 'soapbox/actions/admin'; -import ScrollableList from 'soapbox/components/scrollable_list'; +import ScrollableList from 'soapbox/components/scrollable-list'; import { useAppSelector, useAppDispatch } from 'soapbox/hooks'; -import UnapprovedAccount from '../components/unapproved_account'; +import UnapprovedAccount from '../components/unapproved-account'; const messages = defineMessages({ heading: { id: 'column.admin.awaiting_approval', defaultMessage: 'Awaiting Approval' }, diff --git a/app/soapbox/features/admin/tabs/dashboard.tsx b/app/soapbox/features/admin/tabs/dashboard.tsx index 1be3fe7265..df3f623012 100644 --- a/app/soapbox/features/admin/tabs/dashboard.tsx +++ b/app/soapbox/features/admin/tabs/dashboard.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { FormattedMessage, FormattedNumber } from 'react-intl'; import { Link } from 'react-router-dom'; -import { getSubscribersCsv, getUnsubscribersCsv, getCombinedCsv } from 'soapbox/actions/email_list'; +import { getSubscribersCsv, getUnsubscribersCsv, getCombinedCsv } from 'soapbox/actions/email-list'; import { Text } from 'soapbox/components/ui'; import { useAppSelector, useAppDispatch, useOwnAccount, useFeatures } from 'soapbox/hooks'; import sourceCode from 'soapbox/utils/code'; @@ -10,7 +10,7 @@ import { download } from 'soapbox/utils/download'; import { parseVersion } from 'soapbox/utils/features'; import { isNumber } from 'soapbox/utils/numbers'; -import RegistrationModePicker from '../components/registration_mode_picker'; +import RegistrationModePicker from '../components/registration-mode-picker'; const Dashboard: React.FC = () => { const dispatch = useAppDispatch(); diff --git a/app/soapbox/features/admin/tabs/reports.tsx b/app/soapbox/features/admin/tabs/reports.tsx index 5c2854cc4d..8975fff5c2 100644 --- a/app/soapbox/features/admin/tabs/reports.tsx +++ b/app/soapbox/features/admin/tabs/reports.tsx @@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { fetchReports } from 'soapbox/actions/admin'; -import ScrollableList from 'soapbox/components/scrollable_list'; +import ScrollableList from 'soapbox/components/scrollable-list'; import { useAppSelector, useAppDispatch } from 'soapbox/hooks'; import Report from '../components/report'; diff --git a/app/soapbox/features/admin/user_index.js b/app/soapbox/features/admin/user-index.js similarity index 96% rename from app/soapbox/features/admin/user_index.js rename to app/soapbox/features/admin/user-index.js index 032ed6dc2d..eb91badb1b 100644 Binary files a/app/soapbox/features/admin/user_index.js and b/app/soapbox/features/admin/user-index.js differ diff --git a/app/soapbox/features/ads/components/ad.tsx b/app/soapbox/features/ads/components/ad.tsx index a0db9f78d3..73446989dd 100644 --- a/app/soapbox/features/ads/components/ad.tsx +++ b/app/soapbox/features/ads/components/ad.tsx @@ -2,8 +2,7 @@ import { useQuery, useQueryClient } from '@tanstack/react-query'; import React, { useState, useEffect, useRef } from 'react'; import { FormattedMessage } from 'react-intl'; -import { Stack, HStack, Card, Avatar, Text, Icon } from 'soapbox/components/ui'; -import IconButton from 'soapbox/components/ui/icon-button/icon-button'; +import { Avatar, Card, HStack, Icon, IconButton, Stack, Text } from 'soapbox/components/ui'; import StatusCard from 'soapbox/features/status/components/card'; import { useAppSelector } from 'soapbox/hooks'; diff --git a/app/soapbox/features/aliases/components/account.tsx b/app/soapbox/features/aliases/components/account.tsx index 802d3e0f6b..1687b85e6d 100644 --- a/app/soapbox/features/aliases/components/account.tsx +++ b/app/soapbox/features/aliases/components/account.tsx @@ -2,9 +2,9 @@ import React, { useCallback } from 'react'; import { defineMessages, useIntl } from 'react-intl'; import { addToAliases } from 'soapbox/actions/aliases'; -import Avatar from 'soapbox/components/avatar'; -import DisplayName from 'soapbox/components/display-name'; -import IconButton from 'soapbox/components/icon_button'; +import AccountComponent from 'soapbox/components/account'; +import IconButton from 'soapbox/components/icon-button'; +import { HStack } from 'soapbox/components/ui'; import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; import { makeGetAccount } from 'soapbox/selectors'; import { getFeatures } from 'soapbox/utils/features'; @@ -47,23 +47,17 @@ const Account: React.FC = ({ accountId, aliases }) => { if (!added && accountId !== me) { button = ( -
      - -
      + ); } return ( -
      -
      -
      -
      - -
      - - {button} + +
      +
      -
      + {button} + ); }; diff --git a/app/soapbox/features/aliases/components/search.tsx b/app/soapbox/features/aliases/components/search.tsx index b84d90aa47..f64c4a3323 100644 --- a/app/soapbox/features/aliases/components/search.tsx +++ b/app/soapbox/features/aliases/components/search.tsx @@ -53,7 +53,7 @@ const Search: React.FC = () => { placeholder={intl.formatMessage(messages.search)} /> -
      +
      diff --git a/app/soapbox/features/aliases/index.tsx b/app/soapbox/features/aliases/index.tsx index d76c7988d6..cf5ee3e16e 100644 --- a/app/soapbox/features/aliases/index.tsx +++ b/app/soapbox/features/aliases/index.tsx @@ -4,7 +4,7 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { fetchAliases, removeFromAliases } from 'soapbox/actions/aliases'; import Icon from 'soapbox/components/icon'; -import ScrollableList from 'soapbox/components/scrollable_list'; +import ScrollableList from 'soapbox/components/scrollable-list'; import { CardHeader, CardTitle, Column, HStack, Text } from 'soapbox/components/ui'; import { useAppDispatch, useAppSelector } from 'soapbox/hooks'; import { makeGetAccount } from 'soapbox/selectors'; @@ -63,7 +63,7 @@ const Aliases = () => {
      ) : ( -
      +
      {searchAccountIds.map(accountId => )}
      ) diff --git a/app/soapbox/features/audio/index.tsx b/app/soapbox/features/audio/index.tsx index 0bef3c3d92..ecbae5b166 100644 --- a/app/soapbox/features/audio/index.tsx +++ b/app/soapbox/features/audio/index.tsx @@ -449,6 +449,7 @@ const Audio: React.FC = (props) => { onMouseLeave={handleMouseLeave} tabIndex={0} onKeyDown={handleKeyDown} + onClick={e => e.stopPropagation()} >