diff --git a/app/soapbox/actions/bundles.js b/app/soapbox/actions/bundles.js deleted file mode 100644 index ecc9c8f7d..000000000 --- a/app/soapbox/actions/bundles.js +++ /dev/null @@ -1,25 +0,0 @@ -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 { - type: BUNDLE_FETCH_REQUEST, - skipLoading, - }; -} - -export function fetchBundleSuccess(skipLoading) { - return { - type: BUNDLE_FETCH_SUCCESS, - skipLoading, - }; -} - -export function fetchBundleFail(error, skipLoading) { - return { - type: BUNDLE_FETCH_FAIL, - error, - skipLoading, - }; -} diff --git a/app/soapbox/actions/bundles.ts b/app/soapbox/actions/bundles.ts new file mode 100644 index 000000000..cdc032cdd --- /dev/null +++ b/app/soapbox/actions/bundles.ts @@ -0,0 +1,28 @@ +const BUNDLE_FETCH_REQUEST = 'BUNDLE_FETCH_REQUEST'; +const BUNDLE_FETCH_SUCCESS = 'BUNDLE_FETCH_SUCCESS'; +const BUNDLE_FETCH_FAIL = 'BUNDLE_FETCH_FAIL'; + +const fetchBundleRequest = (skipLoading?: boolean) => ({ + type: BUNDLE_FETCH_REQUEST, + skipLoading, +}); + +const fetchBundleSuccess = (skipLoading?: boolean) => ({ + type: BUNDLE_FETCH_SUCCESS, + skipLoading, +}); + +const fetchBundleFail = (error, skipLoading?: boolean) => ({ + type: BUNDLE_FETCH_FAIL, + error, + skipLoading, +}); + +export { + BUNDLE_FETCH_REQUEST, + BUNDLE_FETCH_SUCCESS, + BUNDLE_FETCH_FAIL, + fetchBundleRequest, + fetchBundleSuccess, + fetchBundleFail, +}; diff --git a/app/soapbox/actions/custom_emojis.js b/app/soapbox/actions/custom_emojis.js deleted file mode 100644 index 49e903f37..000000000 --- a/app/soapbox/actions/custom_emojis.js +++ /dev/null @@ -1,43 +0,0 @@ -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 function fetchCustomEmojis() { - return (dispatch, getState) => { - const me = getState().get('me'); - if (!me) return; - - dispatch(fetchCustomEmojisRequest()); - - api(getState).get('/api/v1/custom_emojis').then(response => { - dispatch(fetchCustomEmojisSuccess(response.data)); - }).catch(error => { - dispatch(fetchCustomEmojisFail(error)); - }); - }; -} - -export function fetchCustomEmojisRequest() { - return { - type: CUSTOM_EMOJIS_FETCH_REQUEST, - skipLoading: true, - }; -} - -export function fetchCustomEmojisSuccess(custom_emojis) { - return { - type: CUSTOM_EMOJIS_FETCH_SUCCESS, - custom_emojis, - skipLoading: true, - }; -} - -export function fetchCustomEmojisFail(error) { - return { - type: CUSTOM_EMOJIS_FETCH_FAIL, - error, - skipLoading: true, - }; -} diff --git a/app/soapbox/actions/custom_emojis.ts b/app/soapbox/actions/custom_emojis.ts new file mode 100644 index 000000000..f6e14eea3 --- /dev/null +++ b/app/soapbox/actions/custom_emojis.ts @@ -0,0 +1,50 @@ +import api from '../api'; + +import type { AxiosError } from 'axios'; +import type { AppDispatch, RootState } from 'soapbox/store'; +import type { APIEntity } from 'soapbox/types/entities'; + +const CUSTOM_EMOJIS_FETCH_REQUEST = 'CUSTOM_EMOJIS_FETCH_REQUEST'; +const CUSTOM_EMOJIS_FETCH_SUCCESS = 'CUSTOM_EMOJIS_FETCH_SUCCESS'; +const CUSTOM_EMOJIS_FETCH_FAIL = 'CUSTOM_EMOJIS_FETCH_FAIL'; + +const fetchCustomEmojis = () => + (dispatch: AppDispatch, getState: () => RootState) => { + const me = getState().me; + if (!me) return; + + dispatch(fetchCustomEmojisRequest()); + + api(getState).get('/api/v1/custom_emojis').then(response => { + dispatch(fetchCustomEmojisSuccess(response.data)); + }).catch(error => { + dispatch(fetchCustomEmojisFail(error)); + }); + }; + +const fetchCustomEmojisRequest = () => ({ + type: CUSTOM_EMOJIS_FETCH_REQUEST, + skipLoading: true, +}); + +const fetchCustomEmojisSuccess = (custom_emojis: APIEntity[]) => ({ + type: CUSTOM_EMOJIS_FETCH_SUCCESS, + custom_emojis, + skipLoading: true, +}); + +const fetchCustomEmojisFail = (error: AxiosError) => ({ + type: CUSTOM_EMOJIS_FETCH_FAIL, + error, + skipLoading: true, +}); + +export { + CUSTOM_EMOJIS_FETCH_REQUEST, + CUSTOM_EMOJIS_FETCH_SUCCESS, + CUSTOM_EMOJIS_FETCH_FAIL, + fetchCustomEmojis, + fetchCustomEmojisRequest, + fetchCustomEmojisSuccess, + fetchCustomEmojisFail, +}; diff --git a/app/soapbox/actions/directory.js b/app/soapbox/actions/directory.js deleted file mode 100644 index 0ee15386b..000000000 --- a/app/soapbox/actions/directory.js +++ /dev/null @@ -1,62 +0,0 @@ -import api from '../api'; - -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_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 }) => { - dispatch(importFetchedAccounts(data)); - dispatch(fetchDirectorySuccess(data)); - dispatch(fetchRelationships(data.map(x => x.id))); - }).catch(error => dispatch(fetchDirectoryFail(error))); -}; - -export const fetchDirectoryRequest = () => ({ - type: DIRECTORY_FETCH_REQUEST, -}); - -export const fetchDirectorySuccess = accounts => ({ - type: DIRECTORY_FETCH_SUCCESS, - accounts, -}); - -export const fetchDirectoryFail = error => ({ - type: DIRECTORY_FETCH_FAIL, - error, -}); - -export const expandDirectory = params => (dispatch, getState) => { - dispatch(expandDirectoryRequest()); - - const loadedItems = getState().getIn(['user_lists', 'directory', 'items']).size; - - 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))); - }).catch(error => dispatch(expandDirectoryFail(error))); -}; - -export const expandDirectoryRequest = () => ({ - type: DIRECTORY_EXPAND_REQUEST, -}); - -export const expandDirectorySuccess = accounts => ({ - type: DIRECTORY_EXPAND_SUCCESS, - accounts, -}); - -export const expandDirectoryFail = error => ({ - type: DIRECTORY_EXPAND_FAIL, - error, -}); \ No newline at end of file diff --git a/app/soapbox/actions/directory.ts b/app/soapbox/actions/directory.ts new file mode 100644 index 000000000..e9e309de4 --- /dev/null +++ b/app/soapbox/actions/directory.ts @@ -0,0 +1,84 @@ +import api from '../api'; + +import { fetchRelationships } from './accounts'; +import { importFetchedAccounts } from './importer'; + +import type { AppDispatch, RootState } from 'soapbox/store'; +import type { APIEntity } from 'soapbox/types/entities'; + +const DIRECTORY_FETCH_REQUEST = 'DIRECTORY_FETCH_REQUEST'; +const DIRECTORY_FETCH_SUCCESS = 'DIRECTORY_FETCH_SUCCESS'; +const DIRECTORY_FETCH_FAIL = 'DIRECTORY_FETCH_FAIL'; + +const DIRECTORY_EXPAND_REQUEST = 'DIRECTORY_EXPAND_REQUEST'; +const DIRECTORY_EXPAND_SUCCESS = 'DIRECTORY_EXPAND_SUCCESS'; +const DIRECTORY_EXPAND_FAIL = 'DIRECTORY_EXPAND_FAIL'; + +const fetchDirectory = params => + (dispatch: AppDispatch, getState: () => RootState) => { + dispatch(fetchDirectoryRequest()); + + 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))); + }).catch(error => dispatch(fetchDirectoryFail(error))); + }; + +const fetchDirectoryRequest = () => ({ + type: DIRECTORY_FETCH_REQUEST, +}); + +const fetchDirectorySuccess = accounts => ({ + type: DIRECTORY_FETCH_SUCCESS, + accounts, +}); + +const fetchDirectoryFail = error => ({ + type: DIRECTORY_FETCH_FAIL, + error, +}); + +const expandDirectory = params => + (dispatch: AppDispatch, getState: () => RootState) => { + dispatch(expandDirectoryRequest()); + + const loadedItems = getState().user_lists.getIn(['directory', 'items']).size; + + 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: APIEntity) => x.id))); + }).catch(error => dispatch(expandDirectoryFail(error))); + }; + +const expandDirectoryRequest = () => ({ + type: DIRECTORY_EXPAND_REQUEST, +}); + +const expandDirectorySuccess = accounts => ({ + type: DIRECTORY_EXPAND_SUCCESS, + accounts, +}); + +const expandDirectoryFail = error => ({ + type: DIRECTORY_EXPAND_FAIL, + error, +}); + +export { + DIRECTORY_FETCH_REQUEST, + DIRECTORY_FETCH_SUCCESS, + DIRECTORY_FETCH_FAIL, + DIRECTORY_EXPAND_REQUEST, + DIRECTORY_EXPAND_SUCCESS, + DIRECTORY_EXPAND_FAIL, + fetchDirectory, + fetchDirectoryRequest, + fetchDirectorySuccess, + fetchDirectoryFail, + expandDirectory, + expandDirectoryRequest, + expandDirectorySuccess, + expandDirectoryFail, +}; \ No newline at end of file diff --git a/app/soapbox/actions/domain_blocks.js b/app/soapbox/actions/domain_blocks.js deleted file mode 100644 index 4597f1afa..000000000 --- a/app/soapbox/actions/domain_blocks.js +++ /dev/null @@ -1,181 +0,0 @@ -import { isLoggedIn } from 'soapbox/utils/auth'; - -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_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_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) => { - if (!isLoggedIn(getState)) return; - - 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')); - dispatch(blockDomainSuccess(domain, accounts)); - }).catch(err => { - dispatch(blockDomainFail(domain, err)); - }); - }; -} - -export function blockDomainRequest(domain) { - return { - type: DOMAIN_BLOCK_REQUEST, - domain, - }; -} - -export function blockDomainSuccess(domain, accounts) { - return { - type: DOMAIN_BLOCK_SUCCESS, - domain, - accounts, - }; -} - -export function blockDomainFail(domain, error) { - return { - type: DOMAIN_BLOCK_FAIL, - domain, - error, - }; -} - -export function unblockDomain(domain) { - return (dispatch, getState) => { - if (!isLoggedIn(getState)) return; - - dispatch(unblockDomainRequest(domain)); - - // Do it both ways for maximum compatibility - const params = { - params: { domain }, - data: { domain }, - }; - - api(getState).delete('/api/v1/domain_blocks', params).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)); - }); - }; -} - -export function unblockDomainRequest(domain) { - return { - type: DOMAIN_UNBLOCK_REQUEST, - domain, - }; -} - -export function unblockDomainSuccess(domain, accounts) { - return { - type: DOMAIN_UNBLOCK_SUCCESS, - domain, - accounts, - }; -} - -export function unblockDomainFail(domain, error) { - return { - type: DOMAIN_UNBLOCK_FAIL, - domain, - error, - }; -} - -export function fetchDomainBlocks() { - return (dispatch, getState) => { - if (!isLoggedIn(getState)) return; - - dispatch(fetchDomainBlocksRequest()); - - 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)); - }); - }; -} - -export function fetchDomainBlocksRequest() { - return { - type: DOMAIN_BLOCKS_FETCH_REQUEST, - }; -} - -export function fetchDomainBlocksSuccess(domains, next) { - return { - type: DOMAIN_BLOCKS_FETCH_SUCCESS, - domains, - next, - }; -} - -export function fetchDomainBlocksFail(error) { - return { - type: DOMAIN_BLOCKS_FETCH_FAIL, - error, - }; -} - -export function expandDomainBlocks() { - return (dispatch, getState) => { - if (!isLoggedIn(getState)) return; - - const url = getState().domain_lists.blocks.next; - - if (!url) { - return; - } - - dispatch(expandDomainBlocksRequest()); - - api(getState).get(url).then(response => { - const next = getLinks(response).refs.find(link => link.rel === 'next'); - dispatch(expandDomainBlocksSuccess(response.data, next ? next.uri : null)); - }).catch(err => { - dispatch(expandDomainBlocksFail(err)); - }); - }; -} - -export function expandDomainBlocksRequest() { - return { - type: DOMAIN_BLOCKS_EXPAND_REQUEST, - }; -} - -export function expandDomainBlocksSuccess(domains, next) { - return { - type: DOMAIN_BLOCKS_EXPAND_SUCCESS, - domains, - next, - }; -} - -export function expandDomainBlocksFail(error) { - return { - type: DOMAIN_BLOCKS_EXPAND_FAIL, - error, - }; -} diff --git a/app/soapbox/actions/domain_blocks.ts b/app/soapbox/actions/domain_blocks.ts new file mode 100644 index 000000000..4308edec7 --- /dev/null +++ b/app/soapbox/actions/domain_blocks.ts @@ -0,0 +1,188 @@ +import { isLoggedIn } from 'soapbox/utils/auth'; + +import api, { getLinks } from '../api'; + +import type { AxiosError } from 'axios'; +import type { List as ImmutableList } from 'immutable'; +import type { AppDispatch, RootState } from 'soapbox/store'; + +const DOMAIN_BLOCK_REQUEST = 'DOMAIN_BLOCK_REQUEST'; +const DOMAIN_BLOCK_SUCCESS = 'DOMAIN_BLOCK_SUCCESS'; +const DOMAIN_BLOCK_FAIL = 'DOMAIN_BLOCK_FAIL'; + +const DOMAIN_UNBLOCK_REQUEST = 'DOMAIN_UNBLOCK_REQUEST'; +const DOMAIN_UNBLOCK_SUCCESS = 'DOMAIN_UNBLOCK_SUCCESS'; +const DOMAIN_UNBLOCK_FAIL = 'DOMAIN_UNBLOCK_FAIL'; + +const DOMAIN_BLOCKS_FETCH_REQUEST = 'DOMAIN_BLOCKS_FETCH_REQUEST'; +const DOMAIN_BLOCKS_FETCH_SUCCESS = 'DOMAIN_BLOCKS_FETCH_SUCCESS'; +const DOMAIN_BLOCKS_FETCH_FAIL = 'DOMAIN_BLOCKS_FETCH_FAIL'; + +const DOMAIN_BLOCKS_EXPAND_REQUEST = 'DOMAIN_BLOCKS_EXPAND_REQUEST'; +const DOMAIN_BLOCKS_EXPAND_SUCCESS = 'DOMAIN_BLOCKS_EXPAND_SUCCESS'; +const DOMAIN_BLOCKS_EXPAND_FAIL = 'DOMAIN_BLOCKS_EXPAND_FAIL'; + +const blockDomain = (domain: string) => + (dispatch: AppDispatch, getState: () => RootState) => { + if (!isLoggedIn(getState)) return; + + dispatch(blockDomainRequest(domain)); + + api(getState).post('/api/v1/domain_blocks', { domain }).then(() => { + const at_domain = '@' + domain; + const accounts = getState().accounts.filter(item => item.acct.endsWith(at_domain)).valueSeq().map(item => item.id); + dispatch(blockDomainSuccess(domain, accounts.toList())); + }).catch(err => { + dispatch(blockDomainFail(domain, err)); + }); + }; + +const blockDomainRequest = (domain: string) => ({ + type: DOMAIN_BLOCK_REQUEST, + domain, +}); + +const blockDomainSuccess = (domain: string, accounts: ImmutableList) => ({ + type: DOMAIN_BLOCK_SUCCESS, + domain, + accounts, +}); + +const blockDomainFail = (domain: string, error: AxiosError) => ({ + type: DOMAIN_BLOCK_FAIL, + domain, + error, +}); + +const unblockDomain = (domain: string) => + (dispatch: AppDispatch, getState: () => RootState) => { + if (!isLoggedIn(getState)) return; + + dispatch(unblockDomainRequest(domain)); + + // Do it both ways for maximum compatibility + const params = { + params: { domain }, + data: { domain }, + }; + + api(getState).delete('/api/v1/domain_blocks', params).then(() => { + const at_domain = '@' + domain; + const accounts = getState().accounts.filter(item => item.get('acct').endsWith(at_domain)).valueSeq().map(item => item.get('id')); + dispatch(unblockDomainSuccess(domain, accounts.toList())); + }).catch(err => { + dispatch(unblockDomainFail(domain, err)); + }); + }; + +const unblockDomainRequest = (domain: string) => ({ + type: DOMAIN_UNBLOCK_REQUEST, + domain, +}); + +const unblockDomainSuccess = (domain: string, accounts: ImmutableList) => ({ + type: DOMAIN_UNBLOCK_SUCCESS, + domain, + accounts, +}); + +const unblockDomainFail = (domain: string, error: AxiosError) => ({ + type: DOMAIN_UNBLOCK_FAIL, + domain, + error, +}); + +const fetchDomainBlocks = () => + (dispatch: AppDispatch, getState: () => RootState) => { + if (!isLoggedIn(getState)) return; + + dispatch(fetchDomainBlocksRequest()); + + 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)); + }); + }; + +const fetchDomainBlocksRequest = () => ({ + type: DOMAIN_BLOCKS_FETCH_REQUEST, +}); + +const fetchDomainBlocksSuccess = (domains: string[], next: string | null) => ({ + type: DOMAIN_BLOCKS_FETCH_SUCCESS, + domains, + next, +}); + +const fetchDomainBlocksFail = (error: AxiosError) => ({ + type: DOMAIN_BLOCKS_FETCH_FAIL, + error, +}); + +const expandDomainBlocks = () => + (dispatch: AppDispatch, getState: () => RootState) => { + if (!isLoggedIn(getState)) return; + + const url = getState().domain_lists.blocks.next; + + if (!url) { + return; + } + + dispatch(expandDomainBlocksRequest()); + + api(getState).get(url).then(response => { + const next = getLinks(response).refs.find(link => link.rel === 'next'); + dispatch(expandDomainBlocksSuccess(response.data, next ? next.uri : null)); + }).catch(err => { + dispatch(expandDomainBlocksFail(err)); + }); + }; + +const expandDomainBlocksRequest = () => ({ + type: DOMAIN_BLOCKS_EXPAND_REQUEST, +}); + +const expandDomainBlocksSuccess = (domains: string[], next: string | null) => ({ + type: DOMAIN_BLOCKS_EXPAND_SUCCESS, + domains, + next, +}); + +const expandDomainBlocksFail = (error: AxiosError) => ({ + type: DOMAIN_BLOCKS_EXPAND_FAIL, + error, +}); + +export { + DOMAIN_BLOCK_REQUEST, + DOMAIN_BLOCK_SUCCESS, + DOMAIN_BLOCK_FAIL, + DOMAIN_UNBLOCK_REQUEST, + DOMAIN_UNBLOCK_SUCCESS, + DOMAIN_UNBLOCK_FAIL, + DOMAIN_BLOCKS_FETCH_REQUEST, + DOMAIN_BLOCKS_FETCH_SUCCESS, + DOMAIN_BLOCKS_FETCH_FAIL, + DOMAIN_BLOCKS_EXPAND_REQUEST, + DOMAIN_BLOCKS_EXPAND_SUCCESS, + DOMAIN_BLOCKS_EXPAND_FAIL, + blockDomain, + blockDomainRequest, + blockDomainSuccess, + blockDomainFail, + unblockDomain, + unblockDomainRequest, + unblockDomainSuccess, + unblockDomainFail, + fetchDomainBlocks, + fetchDomainBlocksRequest, + fetchDomainBlocksSuccess, + fetchDomainBlocksFail, + expandDomainBlocks, + expandDomainBlocksRequest, + expandDomainBlocksSuccess, + expandDomainBlocksFail, +}; diff --git a/app/soapbox/actions/dropdown_menu.js b/app/soapbox/actions/dropdown_menu.js deleted file mode 100644 index 14f2939c7..000000000 --- a/app/soapbox/actions/dropdown_menu.js +++ /dev/null @@ -1,10 +0,0 @@ -export const DROPDOWN_MENU_OPEN = 'DROPDOWN_MENU_OPEN'; -export const DROPDOWN_MENU_CLOSE = 'DROPDOWN_MENU_CLOSE'; - -export function openDropdownMenu(id, placement, keyboard) { - return { type: DROPDOWN_MENU_OPEN, id, placement, keyboard }; -} - -export function closeDropdownMenu(id) { - return { type: DROPDOWN_MENU_CLOSE, id }; -} diff --git a/app/soapbox/actions/dropdown_menu.ts b/app/soapbox/actions/dropdown_menu.ts new file mode 100644 index 000000000..2c19735a1 --- /dev/null +++ b/app/soapbox/actions/dropdown_menu.ts @@ -0,0 +1,17 @@ +import type { DropdownPlacement } from 'soapbox/components/dropdown_menu'; + +const DROPDOWN_MENU_OPEN = 'DROPDOWN_MENU_OPEN'; +const DROPDOWN_MENU_CLOSE = 'DROPDOWN_MENU_CLOSE'; + +const openDropdownMenu = (id: number, placement: DropdownPlacement, keyboard: boolean) => + ({ type: DROPDOWN_MENU_OPEN, id, placement, keyboard }); + +const closeDropdownMenu = (id: number) => + ({ type: DROPDOWN_MENU_CLOSE, id }); + +export { + DROPDOWN_MENU_OPEN, + DROPDOWN_MENU_CLOSE, + openDropdownMenu, + closeDropdownMenu, +}; diff --git a/app/soapbox/actions/email_list.js b/app/soapbox/actions/email_list.js deleted file mode 100644 index 9f440b001..000000000 --- a/app/soapbox/actions/email_list.js +++ /dev/null @@ -1,19 +0,0 @@ -import api from '../api'; - -export function getSubscribersCsv() { - return (dispatch, getState) => { - return api(getState).get('/api/v1/pleroma/admin/email_list/subscribers.csv'); - }; -} - -export function getUnsubscribersCsv() { - return (dispatch, getState) => { - return api(getState).get('/api/v1/pleroma/admin/email_list/unsubscribers.csv'); - }; -} - -export function getCombinedCsv() { - return (dispatch, getState) => { - return api(getState).get('/api/v1/pleroma/admin/email_list/combined.csv'); - }; -} diff --git a/app/soapbox/actions/email_list.ts b/app/soapbox/actions/email_list.ts new file mode 100644 index 000000000..561f13a2d --- /dev/null +++ b/app/soapbox/actions/email_list.ts @@ -0,0 +1,21 @@ +import api from '../api'; + +import type { RootState } from 'soapbox/store'; + +const getSubscribersCsv = () => + (dispatch, getState: () => RootState) => + api(getState).get('/api/v1/pleroma/admin/email_list/subscribers.csv'); + +const getUnsubscribersCsv = () => + (dispatch, getState: () => RootState) => + api(getState).get('/api/v1/pleroma/admin/email_list/unsubscribers.csv'); + +const getCombinedCsv = () => + (dispatch, getState: () => RootState) => + api(getState).get('/api/v1/pleroma/admin/email_list/combined.csv'); + +export { + getSubscribersCsv, + getUnsubscribersCsv, + getCombinedCsv, +}; diff --git a/app/soapbox/actions/emojis.js b/app/soapbox/actions/emojis.js deleted file mode 100644 index 3b5d53996..000000000 --- a/app/soapbox/actions/emojis.js +++ /dev/null @@ -1,14 +0,0 @@ -import { saveSettings } from './settings'; - -export const EMOJI_USE = 'EMOJI_USE'; - -export function useEmoji(emoji) { - return dispatch => { - dispatch({ - type: EMOJI_USE, - emoji, - }); - - dispatch(saveSettings()); - }; -} diff --git a/app/soapbox/actions/emojis.ts b/app/soapbox/actions/emojis.ts new file mode 100644 index 000000000..69d3c1691 --- /dev/null +++ b/app/soapbox/actions/emojis.ts @@ -0,0 +1,20 @@ +import { saveSettings } from './settings'; + +import type { AppDispatch } from 'soapbox/store'; + +const EMOJI_USE = 'EMOJI_USE'; + +const useEmoji = (emoji: string) => + (dispatch: AppDispatch) => { + dispatch({ + type: EMOJI_USE, + emoji, + }); + + dispatch(saveSettings()); + }; + +export { + EMOJI_USE, + useEmoji, +}; diff --git a/app/soapbox/actions/filters.js b/app/soapbox/actions/filters.js deleted file mode 100644 index 9c351442a..000000000 --- a/app/soapbox/actions/filters.js +++ /dev/null @@ -1,77 +0,0 @@ -import { defineMessages } from 'react-intl'; - -import snackbar from 'soapbox/actions/snackbar'; -import { isLoggedIn } from 'soapbox/utils/auth'; - -import api from '../api'; - -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_CREATE_REQUEST = 'FILTERS_CREATE_REQUEST'; -export const FILTERS_CREATE_SUCCESS = 'FILTERS_CREATE_SUCCESS'; -export const FILTERS_CREATE_FAIL = 'FILTERS_CREATE_FAIL'; - -export const FILTERS_DELETE_REQUEST = 'FILTERS_DELETE_REQUEST'; -export const FILTERS_DELETE_SUCCESS = 'FILTERS_DELETE_SUCCESS'; -export const FILTERS_DELETE_FAIL = 'FILTERS_DELETE_FAIL'; - -const messages = defineMessages({ - added: { id: 'filters.added', defaultMessage: 'Filter added.' }, - removed: { id: 'filters.removed', defaultMessage: 'Filter deleted.' }, -}); - -export const fetchFilters = () => (dispatch, getState) => { - if (!isLoggedIn(getState)) return; - - dispatch({ - type: FILTERS_FETCH_REQUEST, - skipLoading: true, - }); - - api(getState) - .get('/api/v1/filters') - .then(({ data }) => dispatch({ - type: FILTERS_FETCH_SUCCESS, - filters: data, - skipLoading: true, - })) - .catch(err => dispatch({ - type: FILTERS_FETCH_FAIL, - err, - skipLoading: true, - skipAlert: true, - })); -}; - -export function createFilter(intl, phrase, expires_at, context, whole_word, irreversible) { - return (dispatch, getState) => { - dispatch({ type: FILTERS_CREATE_REQUEST }); - return api(getState).post('/api/v1/filters', { - phrase, - context, - irreversible, - whole_word, - expires_at, - }).then(response => { - dispatch({ type: FILTERS_CREATE_SUCCESS, filter: response.data }); - dispatch(snackbar.success(intl.formatMessage(messages.added))); - }).catch(error => { - dispatch({ type: FILTERS_CREATE_FAIL, error }); - }); - }; -} - - -export function deleteFilter(intl, id) { - return (dispatch, getState) => { - dispatch({ type: FILTERS_DELETE_REQUEST }); - return api(getState).delete('/api/v1/filters/' + id).then(response => { - dispatch({ type: FILTERS_DELETE_SUCCESS, filter: response.data }); - dispatch(snackbar.success(intl.formatMessage(messages.removed))); - }).catch(error => { - dispatch({ type: FILTERS_DELETE_FAIL, error }); - }); - }; -} diff --git a/app/soapbox/actions/filters.ts b/app/soapbox/actions/filters.ts new file mode 100644 index 000000000..97e445425 --- /dev/null +++ b/app/soapbox/actions/filters.ts @@ -0,0 +1,93 @@ +import { defineMessages } from 'react-intl'; + +import snackbar from 'soapbox/actions/snackbar'; +import { isLoggedIn } from 'soapbox/utils/auth'; + +import api from '../api'; + +import type { AppDispatch, RootState } from 'soapbox/store'; + +const FILTERS_FETCH_REQUEST = 'FILTERS_FETCH_REQUEST'; +const FILTERS_FETCH_SUCCESS = 'FILTERS_FETCH_SUCCESS'; +const FILTERS_FETCH_FAIL = 'FILTERS_FETCH_FAIL'; + +const FILTERS_CREATE_REQUEST = 'FILTERS_CREATE_REQUEST'; +const FILTERS_CREATE_SUCCESS = 'FILTERS_CREATE_SUCCESS'; +const FILTERS_CREATE_FAIL = 'FILTERS_CREATE_FAIL'; + +const FILTERS_DELETE_REQUEST = 'FILTERS_DELETE_REQUEST'; +const FILTERS_DELETE_SUCCESS = 'FILTERS_DELETE_SUCCESS'; +const FILTERS_DELETE_FAIL = 'FILTERS_DELETE_FAIL'; + +const messages = defineMessages({ + added: { id: 'filters.added', defaultMessage: 'Filter added.' }, + removed: { id: 'filters.removed', defaultMessage: 'Filter deleted.' }, +}); + +const fetchFilters = () => + (dispatch: AppDispatch, getState: () => RootState) => { + if (!isLoggedIn(getState)) return; + + dispatch({ + type: FILTERS_FETCH_REQUEST, + skipLoading: true, + }); + + api(getState) + .get('/api/v1/filters') + .then(({ data }) => dispatch({ + type: FILTERS_FETCH_SUCCESS, + filters: data, + skipLoading: true, + })) + .catch(err => dispatch({ + type: FILTERS_FETCH_FAIL, + err, + skipLoading: true, + skipAlert: true, + })); + }; + +const createFilter = (phrase: string, expires_at: string, context: Array, whole_word: boolean, irreversible: boolean) => + (dispatch: AppDispatch, getState: () => RootState) => { + dispatch({ type: FILTERS_CREATE_REQUEST }); + return api(getState).post('/api/v1/filters', { + phrase, + context, + irreversible, + whole_word, + expires_at, + }).then(response => { + dispatch({ type: FILTERS_CREATE_SUCCESS, filter: response.data }); + dispatch(snackbar.success(messages.added)); + }).catch(error => { + dispatch({ type: FILTERS_CREATE_FAIL, error }); + }); + }; + + +const deleteFilter = (id) => + (dispatch: AppDispatch, getState: () => RootState) => { + dispatch({ type: FILTERS_DELETE_REQUEST }); + return api(getState).delete(`/api/v1/filters/${id}`).then(response => { + dispatch({ type: FILTERS_DELETE_SUCCESS, filter: response.data }); + dispatch(snackbar.success(messages.removed)); + }).catch(error => { + dispatch({ type: FILTERS_DELETE_FAIL, error }); + }); + }; + +export { + FILTERS_FETCH_REQUEST, + FILTERS_FETCH_SUCCESS, + FILTERS_FETCH_FAIL, + FILTERS_CREATE_REQUEST, + FILTERS_CREATE_SUCCESS, + FILTERS_CREATE_FAIL, + FILTERS_DELETE_REQUEST, + FILTERS_DELETE_SUCCESS, + FILTERS_DELETE_FAIL, + fetchFilters, + createFilter, + deleteFilter, +}; \ No newline at end of file diff --git a/app/soapbox/actions/history.js b/app/soapbox/actions/history.js deleted file mode 100644 index e668d315e..000000000 --- a/app/soapbox/actions/history.js +++ /dev/null @@ -1,38 +0,0 @@ -import api from 'soapbox/api'; - -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 fetchHistory = statusId => (dispatch, getState) => { - const loading = getState().getIn(['history', statusId, 'loading']); - - if (loading) { - return; - } - - dispatch(fetchHistoryRequest(statusId)); - - api(getState).get(`/api/v1/statuses/${statusId}/history`).then(({ data }) => { - dispatch(importFetchedAccounts(data.map(x => x.account))); - dispatch(fetchHistorySuccess(statusId, data)); - }).catch(error => dispatch(fetchHistoryFail(error))); -}; - -export const fetchHistoryRequest = statusId => ({ - type: HISTORY_FETCH_REQUEST, - statusId, -}); - -export const fetchHistorySuccess = (statusId, history) => ({ - type: HISTORY_FETCH_SUCCESS, - statusId, - history, -}); - -export const fetchHistoryFail = error => ({ - type: HISTORY_FETCH_FAIL, - error, -}); \ No newline at end of file diff --git a/app/soapbox/actions/history.ts b/app/soapbox/actions/history.ts new file mode 100644 index 000000000..d38d94ee0 --- /dev/null +++ b/app/soapbox/actions/history.ts @@ -0,0 +1,53 @@ +import api from 'soapbox/api'; + +import { importFetchedAccounts } from './importer'; + +import type { AxiosError } from 'axios'; +import type { AppDispatch, RootState } from 'soapbox/store'; +import type { APIEntity } from 'soapbox/types/entities'; + +const HISTORY_FETCH_REQUEST = 'HISTORY_FETCH_REQUEST'; +const HISTORY_FETCH_SUCCESS = 'HISTORY_FETCH_SUCCESS'; +const HISTORY_FETCH_FAIL = 'HISTORY_FETCH_FAIL'; + +const fetchHistory = (statusId: string) => + (dispatch: AppDispatch, getState: () => RootState) => { + const loading = getState().history.getIn([statusId, 'loading']); + + if (loading) { + return; + } + + dispatch(fetchHistoryRequest(statusId)); + + api(getState).get(`/api/v1/statuses/${statusId}/history`).then(({ data }) => { + dispatch(importFetchedAccounts(data.map((x: APIEntity) => x.account))); + dispatch(fetchHistorySuccess(statusId, data)); + }).catch(error => dispatch(fetchHistoryFail(error))); + }; + +const fetchHistoryRequest = (statusId: string) => ({ + type: HISTORY_FETCH_REQUEST, + statusId, +}); + +const fetchHistorySuccess = (statusId: String, history: APIEntity[]) => ({ + type: HISTORY_FETCH_SUCCESS, + statusId, + history, +}); + +const fetchHistoryFail = (error: AxiosError) => ({ + type: HISTORY_FETCH_FAIL, + error, +}); + +export { + HISTORY_FETCH_REQUEST, + HISTORY_FETCH_SUCCESS, + HISTORY_FETCH_FAIL, + fetchHistory, + fetchHistoryRequest, + fetchHistorySuccess, + fetchHistoryFail, +}; \ No newline at end of file diff --git a/app/soapbox/actions/markers.js b/app/soapbox/actions/markers.js deleted file mode 100644 index 3d7d12c7e..000000000 --- a/app/soapbox/actions/markers.js +++ /dev/null @@ -1,33 +0,0 @@ -import api from '../api'; - -export const MARKER_FETCH_REQUEST = 'MARKER_FETCH_REQUEST'; -export const MARKER_FETCH_SUCCESS = 'MARKER_FETCH_SUCCESS'; -export const MARKER_FETCH_FAIL = 'MARKER_FETCH_FAIL'; - -export const MARKER_SAVE_REQUEST = 'MARKER_SAVE_REQUEST'; -export const MARKER_SAVE_SUCCESS = 'MARKER_SAVE_SUCCESS'; -export const MARKER_SAVE_FAIL = 'MARKER_SAVE_FAIL'; - -export function fetchMarker(timeline) { - return (dispatch, getState) => { - dispatch({ type: MARKER_FETCH_REQUEST }); - return api(getState).get('/api/v1/markers', { - params: { timeline }, - }).then(({ data: marker }) => { - dispatch({ type: MARKER_FETCH_SUCCESS, marker }); - }).catch(error => { - dispatch({ type: MARKER_FETCH_FAIL, error }); - }); - }; -} - -export function saveMarker(marker) { - return (dispatch, getState) => { - dispatch({ type: MARKER_SAVE_REQUEST, marker }); - return api(getState).post('/api/v1/markers', marker).then(({ data: marker }) => { - dispatch({ type: MARKER_SAVE_SUCCESS, marker }); - }).catch(error => { - dispatch({ type: MARKER_SAVE_FAIL, error }); - }); - }; -} diff --git a/app/soapbox/actions/markers.ts b/app/soapbox/actions/markers.ts new file mode 100644 index 000000000..96ba12349 --- /dev/null +++ b/app/soapbox/actions/markers.ts @@ -0,0 +1,45 @@ +import api from '../api'; + +import type { AppDispatch, RootState } from 'soapbox/store'; +import type { APIEntity } from 'soapbox/types/entities'; + +const MARKER_FETCH_REQUEST = 'MARKER_FETCH_REQUEST'; +const MARKER_FETCH_SUCCESS = 'MARKER_FETCH_SUCCESS'; +const MARKER_FETCH_FAIL = 'MARKER_FETCH_FAIL'; + +const MARKER_SAVE_REQUEST = 'MARKER_SAVE_REQUEST'; +const MARKER_SAVE_SUCCESS = 'MARKER_SAVE_SUCCESS'; +const MARKER_SAVE_FAIL = 'MARKER_SAVE_FAIL'; + +const fetchMarker = (timeline: Array) => + (dispatch: AppDispatch, getState: () => RootState) => { + dispatch({ type: MARKER_FETCH_REQUEST }); + return api(getState).get('/api/v1/markers', { + params: { timeline }, + }).then(({ data: marker }) => { + dispatch({ type: MARKER_FETCH_SUCCESS, marker }); + }).catch(error => { + dispatch({ type: MARKER_FETCH_FAIL, error }); + }); + }; + +const saveMarker = (marker: APIEntity) => + (dispatch: AppDispatch, getState: () => RootState) => { + dispatch({ type: MARKER_SAVE_REQUEST, marker }); + return api(getState).post('/api/v1/markers', marker).then(({ data: marker }) => { + dispatch({ type: MARKER_SAVE_SUCCESS, marker }); + }).catch(error => { + dispatch({ type: MARKER_SAVE_FAIL, error }); + }); + }; + +export { + MARKER_FETCH_REQUEST, + MARKER_FETCH_SUCCESS, + MARKER_FETCH_FAIL, + MARKER_SAVE_REQUEST, + MARKER_SAVE_SUCCESS, + MARKER_SAVE_FAIL, + fetchMarker, + saveMarker, +}; diff --git a/app/soapbox/actions/media.js b/app/soapbox/actions/media.js deleted file mode 100644 index 460c2f079..000000000 --- a/app/soapbox/actions/media.js +++ /dev/null @@ -1,47 +0,0 @@ -import { getFeatures } from 'soapbox/utils/features'; - -import api from '../api'; - -const noOp = () => {}; - -export function fetchMedia(mediaId) { - return (dispatch, getState) => { - return api(getState).get(`/api/v1/media/${mediaId}`); - }; -} - -export function updateMedia(mediaId, params) { - return (dispatch, getState) => { - return api(getState).put(`/api/v1/media/${mediaId}`, params); - }; -} - -export function uploadMediaV1(data, onUploadProgress = noOp) { - return (dispatch, getState) => { - return api(getState).post('/api/v1/media', data, { - onUploadProgress: onUploadProgress, - }); - }; -} - -export function uploadMediaV2(data, onUploadProgress = noOp) { - return (dispatch, getState) => { - return api(getState).post('/api/v2/media', data, { - onUploadProgress: onUploadProgress, - }); - }; -} - -export function uploadMedia(data, onUploadProgress = noOp) { - return (dispatch, getState) => { - const state = getState(); - const instance = state.get('instance'); - const features = getFeatures(instance); - - if (features.mediaV2) { - return dispatch(uploadMediaV2(data, onUploadProgress)); - } else { - return dispatch(uploadMediaV1(data, onUploadProgress)); - } - }; -} diff --git a/app/soapbox/actions/media.ts b/app/soapbox/actions/media.ts new file mode 100644 index 000000000..910123016 --- /dev/null +++ b/app/soapbox/actions/media.ts @@ -0,0 +1,52 @@ +import { getFeatures } from 'soapbox/utils/features'; + +import api from '../api'; + +import type { AppDispatch, RootState } from 'soapbox/store'; + +const noOp = () => {}; + +const fetchMedia = (mediaId: string) => + (dispatch: any, getState: () => RootState) => { + return api(getState).get(`/api/v1/media/${mediaId}`); + }; + +const updateMedia = (mediaId: string, params: Record) => + (dispatch: any, getState: () => RootState) => { + return api(getState).put(`/api/v1/media/${mediaId}`, params); + }; + +const uploadMediaV1 = (data: FormData, onUploadProgress = noOp) => + (dispatch: any, getState: () => RootState) => + api(getState).post('/api/v1/media', data, { + onUploadProgress: onUploadProgress, + }); + + +const uploadMediaV2 = (data: FormData, onUploadProgress = noOp) => + (dispatch: any, getState: () => RootState) => + api(getState).post('/api/v2/media', data, { + onUploadProgress: onUploadProgress, + }); + + +const uploadMedia = (data: FormData, onUploadProgress = noOp) => + (dispatch: AppDispatch, getState: () => RootState) => { + const state = getState(); + const instance = state.instance; + const features = getFeatures(instance); + + if (features.mediaV2) { + return dispatch(uploadMediaV2(data, onUploadProgress)); + } else { + return dispatch(uploadMediaV1(data, onUploadProgress)); + } + }; + +export { + fetchMedia, + updateMedia, + uploadMediaV1, + uploadMediaV2, + uploadMedia, +}; diff --git a/app/soapbox/actions/mobile.js b/app/soapbox/actions/mobile.ts similarity index 51% rename from app/soapbox/actions/mobile.js rename to app/soapbox/actions/mobile.ts index c7707c8f9..1e11f473d 100644 --- a/app/soapbox/actions/mobile.js +++ b/app/soapbox/actions/mobile.ts @@ -1,11 +1,13 @@ import { staticClient } from '../api'; -export const FETCH_MOBILE_PAGE_REQUEST = 'FETCH_MOBILE_PAGE_REQUEST'; -export const FETCH_MOBILE_PAGE_SUCCESS = 'FETCH_MOBILE_PAGE_SUCCESS'; -export const FETCH_MOBILE_PAGE_FAIL = 'FETCH_MOBILE_PAGE_FAIL'; +import type { AppDispatch } from 'soapbox/store'; -export function fetchMobilePage(slug = 'index', locale) { - return (dispatch, getState) => { +const FETCH_MOBILE_PAGE_REQUEST = 'FETCH_MOBILE_PAGE_REQUEST'; +const FETCH_MOBILE_PAGE_SUCCESS = 'FETCH_MOBILE_PAGE_SUCCESS'; +const FETCH_MOBILE_PAGE_FAIL = 'FETCH_MOBILE_PAGE_FAIL'; + +const fetchMobilePage = (slug = 'index', locale?: string) => + (dispatch: AppDispatch) => { dispatch({ type: FETCH_MOBILE_PAGE_REQUEST, slug, locale }); const filename = `${slug}${locale ? `.${locale}` : ''}.html`; return staticClient.get(`/instance/mobile/${filename}`).then(({ data: html }) => { @@ -16,4 +18,10 @@ export function fetchMobilePage(slug = 'index', locale) { throw error; }); }; -} + +export { + FETCH_MOBILE_PAGE_REQUEST, + FETCH_MOBILE_PAGE_SUCCESS, + FETCH_MOBILE_PAGE_FAIL, + fetchMobilePage, +}; \ No newline at end of file diff --git a/app/soapbox/actions/mrf.js b/app/soapbox/actions/mrf.js deleted file mode 100644 index 39359e965..000000000 --- a/app/soapbox/actions/mrf.js +++ /dev/null @@ -1,30 +0,0 @@ -import { Set as ImmutableSet } from 'immutable'; - -import ConfigDB from 'soapbox/utils/config_db'; - -import { fetchConfig, updateConfig } from './admin'; - -const simplePolicyMerge = (simplePolicy, host, restrictions) => { - return simplePolicy.map((hosts, key) => { - const isRestricted = restrictions.get(key); - - if (isRestricted) { - return ImmutableSet(hosts).add(host); - } else { - return ImmutableSet(hosts).delete(host); - } - }); -}; - -export function updateMrf(host, restrictions) { - return (dispatch, getState) => { - return dispatch(fetchConfig()) - .then(() => { - const configs = getState().getIn(['admin', 'configs']); - const simplePolicy = ConfigDB.toSimplePolicy(configs); - const merged = simplePolicyMerge(simplePolicy, host, restrictions); - const config = ConfigDB.fromSimplePolicy(merged); - dispatch(updateConfig(config)); - }); - }; -} diff --git a/app/soapbox/actions/mrf.ts b/app/soapbox/actions/mrf.ts new file mode 100644 index 000000000..a2a315733 --- /dev/null +++ b/app/soapbox/actions/mrf.ts @@ -0,0 +1,33 @@ +import { Map as ImmutableMap, Set as ImmutableSet } from 'immutable'; + +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'; + +const simplePolicyMerge = (simplePolicy: Policy, host: string, restrictions: ImmutableMap) => { + return simplePolicy.map((hosts, key) => { + const isRestricted = restrictions.get(key); + + if (isRestricted) { + return ImmutableSet(hosts).add(host); + } else { + return ImmutableSet(hosts).delete(host); + } + }); +}; + +const updateMrf = (host: string, restrictions: ImmutableMap) => + (dispatch: AppDispatch, getState: () => RootState) => + dispatch(fetchConfig()) + .then(() => { + const configs = getState().admin.get('configs'); + const simplePolicy = ConfigDB.toSimplePolicy(configs); + const merged = simplePolicyMerge(simplePolicy, host, restrictions); + const config = ConfigDB.fromSimplePolicy(merged); + return dispatch(updateConfig(config)); + }); + +export { updateMrf }; diff --git a/app/soapbox/actions/patron.js b/app/soapbox/actions/patron.js deleted file mode 100644 index a9a8ff4d5..000000000 --- a/app/soapbox/actions/patron.js +++ /dev/null @@ -1,62 +0,0 @@ -import api from '../api'; - -export const PATRON_INSTANCE_FETCH_REQUEST = 'PATRON_INSTANCE_FETCH_REQUEST'; -export const PATRON_INSTANCE_FETCH_SUCCESS = 'PATRON_INSTANCE_FETCH_SUCCESS'; -export const PATRON_INSTANCE_FETCH_FAIL = 'PATRON_INSTANCE_FETCH_FAIL'; - -export const PATRON_ACCOUNT_FETCH_REQUEST = 'PATRON_ACCOUNT_FETCH_REQUEST'; -export const PATRON_ACCOUNT_FETCH_SUCCESS = 'PATRON_ACCOUNT_FETCH_SUCCESS'; -export const PATRON_ACCOUNT_FETCH_FAIL = 'PATRON_ACCOUNT_FETCH_FAIL'; - -export function fetchPatronInstance() { - return (dispatch, getState) => { - dispatch({ type: PATRON_INSTANCE_FETCH_REQUEST }); - api(getState).get('/api/patron/v1/instance').then(response => { - dispatch(importFetchedInstance(response.data)); - }).catch(error => { - dispatch(fetchInstanceFail(error)); - }); - }; -} - -export function fetchPatronAccount(apId) { - return (dispatch, getState) => { - apId = encodeURIComponent(apId); - dispatch({ type: PATRON_ACCOUNT_FETCH_REQUEST }); - api(getState).get(`/api/patron/v1/accounts/${apId}`).then(response => { - dispatch(importFetchedAccount(response.data)); - }).catch(error => { - dispatch(fetchAccountFail(error)); - }); - }; -} - -function importFetchedInstance(instance) { - return { - type: PATRON_INSTANCE_FETCH_SUCCESS, - instance, - }; -} - -function fetchInstanceFail(error) { - return { - type: PATRON_INSTANCE_FETCH_FAIL, - error, - skipAlert: true, - }; -} - -function importFetchedAccount(account) { - return { - type: PATRON_ACCOUNT_FETCH_SUCCESS, - account, - }; -} - -function fetchAccountFail(error) { - return { - type: PATRON_ACCOUNT_FETCH_FAIL, - error, - skipAlert: true, - }; -} diff --git a/app/soapbox/actions/patron.ts b/app/soapbox/actions/patron.ts new file mode 100644 index 000000000..f2ecca5d1 --- /dev/null +++ b/app/soapbox/actions/patron.ts @@ -0,0 +1,71 @@ +import api from '../api'; + +import type { AxiosError } from 'axios'; +import type { AppDispatch, RootState } from 'soapbox/store'; +import type { APIEntity } from 'soapbox/types/entities'; + +const PATRON_INSTANCE_FETCH_REQUEST = 'PATRON_INSTANCE_FETCH_REQUEST'; +const PATRON_INSTANCE_FETCH_SUCCESS = 'PATRON_INSTANCE_FETCH_SUCCESS'; +const PATRON_INSTANCE_FETCH_FAIL = 'PATRON_INSTANCE_FETCH_FAIL'; + +const PATRON_ACCOUNT_FETCH_REQUEST = 'PATRON_ACCOUNT_FETCH_REQUEST'; +const PATRON_ACCOUNT_FETCH_SUCCESS = 'PATRON_ACCOUNT_FETCH_SUCCESS'; +const PATRON_ACCOUNT_FETCH_FAIL = 'PATRON_ACCOUNT_FETCH_FAIL'; + +const fetchPatronInstance = () => + (dispatch: AppDispatch, getState: () => RootState) => { + dispatch({ type: PATRON_INSTANCE_FETCH_REQUEST }); + return api(getState).get('/api/patron/v1/instance').then(response => { + dispatch(importFetchedInstance(response.data)); + }).catch(error => { + dispatch(fetchInstanceFail(error)); + }); + }; + +const fetchPatronAccount = (apId: string) => + (dispatch: AppDispatch, getState: () => RootState) => { + apId = encodeURIComponent(apId); + dispatch({ type: PATRON_ACCOUNT_FETCH_REQUEST }); + api(getState).get(`/api/patron/v1/accounts/${apId}`).then(response => { + dispatch(importFetchedAccount(response.data)); + }).catch(error => { + dispatch(fetchAccountFail(error)); + }); + }; + +const importFetchedInstance = (instance: APIEntity) => ({ + type: PATRON_INSTANCE_FETCH_SUCCESS, + instance, +}); + +const fetchInstanceFail = (error: AxiosError) => ({ + type: PATRON_INSTANCE_FETCH_FAIL, + error, + skipAlert: true, +}); + +const importFetchedAccount = (account: APIEntity) => ({ + type: PATRON_ACCOUNT_FETCH_SUCCESS, + account, +}); + +const fetchAccountFail = (error: AxiosError) => ({ + type: PATRON_ACCOUNT_FETCH_FAIL, + error, + skipAlert: true, +}); + +export { + PATRON_INSTANCE_FETCH_REQUEST, + PATRON_INSTANCE_FETCH_SUCCESS, + PATRON_INSTANCE_FETCH_FAIL, + PATRON_ACCOUNT_FETCH_REQUEST, + PATRON_ACCOUNT_FETCH_SUCCESS, + PATRON_ACCOUNT_FETCH_FAIL, + fetchPatronInstance, + fetchPatronAccount, + importFetchedInstance, + fetchInstanceFail, + importFetchedAccount, + fetchAccountFail, +}; diff --git a/app/soapbox/actions/pin_statuses.js b/app/soapbox/actions/pin_statuses.js deleted file mode 100644 index 26194f553..000000000 --- a/app/soapbox/actions/pin_statuses.js +++ /dev/null @@ -1,46 +0,0 @@ -import { isLoggedIn } from 'soapbox/utils/auth'; - -import api from '../api'; - -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 function fetchPinnedStatuses() { - return (dispatch, getState) => { - if (!isLoggedIn(getState)) return; - const me = getState().get('me'); - - dispatch(fetchPinnedStatusesRequest()); - - api(getState).get(`/api/v1/accounts/${me}/statuses`, { params: { pinned: true } }).then(response => { - dispatch(importFetchedStatuses(response.data)); - dispatch(fetchPinnedStatusesSuccess(response.data, null)); - }).catch(error => { - dispatch(fetchPinnedStatusesFail(error)); - }); - }; -} - -export function fetchPinnedStatusesRequest() { - return { - type: PINNED_STATUSES_FETCH_REQUEST, - }; -} - -export function fetchPinnedStatusesSuccess(statuses, next) { - return { - type: PINNED_STATUSES_FETCH_SUCCESS, - statuses, - next, - }; -} - -export function fetchPinnedStatusesFail(error) { - return { - type: PINNED_STATUSES_FETCH_FAIL, - error, - }; -} diff --git a/app/soapbox/actions/pin_statuses.ts b/app/soapbox/actions/pin_statuses.ts new file mode 100644 index 000000000..8df193472 --- /dev/null +++ b/app/soapbox/actions/pin_statuses.ts @@ -0,0 +1,52 @@ +import { isLoggedIn } from 'soapbox/utils/auth'; + +import api from '../api'; + +import { importFetchedStatuses } from './importer'; + +import type { AppDispatch, RootState } from 'soapbox/store'; +import type { APIEntity } from 'soapbox/types/entities'; + +const PINNED_STATUSES_FETCH_REQUEST = 'PINNED_STATUSES_FETCH_REQUEST'; +const PINNED_STATUSES_FETCH_SUCCESS = 'PINNED_STATUSES_FETCH_SUCCESS'; +const PINNED_STATUSES_FETCH_FAIL = 'PINNED_STATUSES_FETCH_FAIL'; + +const fetchPinnedStatuses = () => + (dispatch: AppDispatch, getState: () => RootState) => { + if (!isLoggedIn(getState)) return; + const me = getState().me; + + dispatch(fetchPinnedStatusesRequest()); + + api(getState).get(`/api/v1/accounts/${me}/statuses`, { params: { pinned: true } }).then(response => { + dispatch(importFetchedStatuses(response.data)); + dispatch(fetchPinnedStatusesSuccess(response.data, null)); + }).catch(error => { + dispatch(fetchPinnedStatusesFail(error)); + }); + }; + +const fetchPinnedStatusesRequest = () => ({ + type: PINNED_STATUSES_FETCH_REQUEST, +}); + +const fetchPinnedStatusesSuccess = (statuses: APIEntity[], next: string | null) => ({ + type: PINNED_STATUSES_FETCH_SUCCESS, + statuses, + next, +}); + +const fetchPinnedStatusesFail = (error) => ({ + type: PINNED_STATUSES_FETCH_FAIL, + error, +}); + +export { + PINNED_STATUSES_FETCH_REQUEST, + PINNED_STATUSES_FETCH_SUCCESS, + PINNED_STATUSES_FETCH_FAIL, + fetchPinnedStatuses, + fetchPinnedStatusesRequest, + fetchPinnedStatusesSuccess, + fetchPinnedStatusesFail, +}; diff --git a/app/soapbox/actions/polls.js b/app/soapbox/actions/polls.js deleted file mode 100644 index a37410dc9..000000000 --- a/app/soapbox/actions/polls.js +++ /dev/null @@ -1,61 +0,0 @@ -import api from '../api'; - -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_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()); - - api(getState).post(`/api/v1/polls/${pollId}/votes`, { choices }) - .then(({ data }) => { - dispatch(importFetchedPoll(data)); - dispatch(voteSuccess(data)); - }) - .catch(err => dispatch(voteFail(err))); -}; - -export const fetchPoll = pollId => (dispatch, getState) => { - dispatch(fetchPollRequest()); - - api(getState).get(`/api/v1/polls/${pollId}`) - .then(({ data }) => { - dispatch(importFetchedPoll(data)); - dispatch(fetchPollSuccess(data)); - }) - .catch(err => dispatch(fetchPollFail(err))); -}; - -export const voteRequest = () => ({ - type: POLL_VOTE_REQUEST, -}); - -export const voteSuccess = poll => ({ - type: POLL_VOTE_SUCCESS, - poll, -}); - -export const voteFail = error => ({ - type: POLL_VOTE_FAIL, - error, -}); - -export const fetchPollRequest = () => ({ - type: POLL_FETCH_REQUEST, -}); - -export const fetchPollSuccess = poll => ({ - type: POLL_FETCH_SUCCESS, - poll, -}); - -export const fetchPollFail = error => ({ - type: POLL_FETCH_FAIL, - error, -}); diff --git a/app/soapbox/actions/polls.ts b/app/soapbox/actions/polls.ts new file mode 100644 index 000000000..0bf03219b --- /dev/null +++ b/app/soapbox/actions/polls.ts @@ -0,0 +1,82 @@ +import api from '../api'; + +import { importFetchedPoll } from './importer'; + +import type { AppDispatch, RootState } from 'soapbox/store'; + +const POLL_VOTE_REQUEST = 'POLL_VOTE_REQUEST'; +const POLL_VOTE_SUCCESS = 'POLL_VOTE_SUCCESS'; +const POLL_VOTE_FAIL = 'POLL_VOTE_FAIL'; + +const POLL_FETCH_REQUEST = 'POLL_FETCH_REQUEST'; +const POLL_FETCH_SUCCESS = 'POLL_FETCH_SUCCESS'; +const POLL_FETCH_FAIL = 'POLL_FETCH_FAIL'; + +const vote = (pollId: string, choices: string[]) => + (dispatch: AppDispatch, getState: () => RootState) => { + dispatch(voteRequest()); + + api(getState).post(`/api/v1/polls/${pollId}/votes`, { choices }) + .then(({ data }) => { + dispatch(importFetchedPoll(data)); + dispatch(voteSuccess(data)); + }) + .catch(err => dispatch(voteFail(err))); + }; + +const fetchPoll = (pollId: string) => + (dispatch: AppDispatch, getState: () => RootState) => { + dispatch(fetchPollRequest()); + + api(getState).get(`/api/v1/polls/${pollId}`) + .then(({ data }) => { + dispatch(importFetchedPoll(data)); + dispatch(fetchPollSuccess(data)); + }) + .catch(err => dispatch(fetchPollFail(err))); + }; + +const voteRequest = () => ({ + type: POLL_VOTE_REQUEST, +}); + +const voteSuccess = poll => ({ + type: POLL_VOTE_SUCCESS, + poll, +}); + +const voteFail = error => ({ + type: POLL_VOTE_FAIL, + error, +}); + +const fetchPollRequest = () => ({ + type: POLL_FETCH_REQUEST, +}); + +const fetchPollSuccess = poll => ({ + type: POLL_FETCH_SUCCESS, + poll, +}); + +const fetchPollFail = error => ({ + type: POLL_FETCH_FAIL, + error, +}); + +export { + POLL_VOTE_REQUEST, + POLL_VOTE_SUCCESS, + POLL_VOTE_FAIL, + POLL_FETCH_REQUEST, + POLL_FETCH_SUCCESS, + POLL_FETCH_FAIL, + vote, + fetchPoll, + voteRequest, + voteSuccess, + voteFail, + fetchPollRequest, + fetchPollSuccess, + fetchPollFail, +}; diff --git a/app/soapbox/actions/profile_hover_card.js b/app/soapbox/actions/profile_hover_card.js deleted file mode 100644 index 90543148d..000000000 --- a/app/soapbox/actions/profile_hover_card.js +++ /dev/null @@ -1,24 +0,0 @@ -export const PROFILE_HOVER_CARD_OPEN = 'PROFILE_HOVER_CARD_OPEN'; -export const PROFILE_HOVER_CARD_UPDATE = 'PROFILE_HOVER_CARD_UPDATE'; -export const PROFILE_HOVER_CARD_CLOSE = 'PROFILE_HOVER_CARD_CLOSE'; - -export function openProfileHoverCard(ref, accountId) { - return { - type: PROFILE_HOVER_CARD_OPEN, - ref, - accountId, - }; -} - -export function updateProfileHoverCard() { - return { - type: PROFILE_HOVER_CARD_UPDATE, - }; -} - -export function closeProfileHoverCard(force = false) { - return { - type: PROFILE_HOVER_CARD_CLOSE, - force, - }; -} diff --git a/app/soapbox/actions/profile_hover_card.ts b/app/soapbox/actions/profile_hover_card.ts new file mode 100644 index 000000000..3675d7517 --- /dev/null +++ b/app/soapbox/actions/profile_hover_card.ts @@ -0,0 +1,27 @@ +const PROFILE_HOVER_CARD_OPEN = 'PROFILE_HOVER_CARD_OPEN'; +const PROFILE_HOVER_CARD_UPDATE = 'PROFILE_HOVER_CARD_UPDATE'; +const PROFILE_HOVER_CARD_CLOSE = 'PROFILE_HOVER_CARD_CLOSE'; + +const openProfileHoverCard = (ref: React.MutableRefObject, accountId: string) => ({ + type: PROFILE_HOVER_CARD_OPEN, + ref, + accountId, +}); + +const updateProfileHoverCard = () => ({ + type: PROFILE_HOVER_CARD_UPDATE, +}); + +const closeProfileHoverCard = (force = false) => ({ + type: PROFILE_HOVER_CARD_CLOSE, + force, +}); + +export { + PROFILE_HOVER_CARD_OPEN, + PROFILE_HOVER_CARD_UPDATE, + PROFILE_HOVER_CARD_CLOSE, + openProfileHoverCard, + updateProfileHoverCard, + closeProfileHoverCard, +}; diff --git a/app/soapbox/actions/push_notifications/index.ts b/app/soapbox/actions/push_notifications/index.ts index 973dca919..69fdf2787 100644 --- a/app/soapbox/actions/push_notifications/index.ts +++ b/app/soapbox/actions/push_notifications/index.ts @@ -15,9 +15,10 @@ export { CLEAR_SUBSCRIPTION, SET_ALERTS, register, + changeAlerts, }; -export const changeAlerts = (path: Array, value: any) => +const changeAlerts = (path: Array, value: any) => (dispatch: AppDispatch) => { dispatch(setAlerts(path, value)); dispatch(saveSettings() as any); diff --git a/app/soapbox/actions/push_notifications/registerer.ts b/app/soapbox/actions/push_notifications/registerer.ts index 8a79ffdd2..b8d12caa4 100644 --- a/app/soapbox/actions/push_notifications/registerer.ts +++ b/app/soapbox/actions/push_notifications/registerer.ts @@ -54,7 +54,7 @@ const sendSubscriptionToBackend = (subscription: PushSubscription, me: Me) => // 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); -export const register = () => +const register = () => (dispatch: AppDispatch, getState: () => RootState) => { const me = getState().me; const vapidKey = getVapidKey(getState()); @@ -133,7 +133,7 @@ export const register = () => .catch(console.warn); }; -export const saveSettings = () => +const saveSettings = () => (dispatch: AppDispatch, getState: () => RootState) => { const state = getState().push_notifications; const alerts = state.get('alerts'); @@ -146,3 +146,8 @@ export const saveSettings = () => } }).catch(console.warn); }; + +export { + register, + saveSettings, +}; diff --git a/app/soapbox/actions/push_notifications/setter.ts b/app/soapbox/actions/push_notifications/setter.ts index a46bd4427..739427e7e 100644 --- a/app/soapbox/actions/push_notifications/setter.ts +++ b/app/soapbox/actions/push_notifications/setter.ts @@ -1,28 +1,39 @@ import type { AnyAction } from 'redux'; -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'; +const SET_BROWSER_SUPPORT = 'PUSH_NOTIFICATIONS_SET_BROWSER_SUPPORT'; +const SET_SUBSCRIPTION = 'PUSH_NOTIFICATIONS_SET_SUBSCRIPTION'; +const CLEAR_SUBSCRIPTION = 'PUSH_NOTIFICATIONS_CLEAR_SUBSCRIPTION'; +const SET_ALERTS = 'PUSH_NOTIFICATIONS_SET_ALERTS'; -export const setBrowserSupport = (value: boolean) => ({ +const setBrowserSupport = (value: boolean) => ({ type: SET_BROWSER_SUPPORT, value, }); -export const setSubscription = (subscription: PushSubscription) => ({ +const setSubscription = (subscription: PushSubscription) => ({ type: SET_SUBSCRIPTION, subscription, }); -export const clearSubscription = () => ({ +const clearSubscription = () => ({ type: CLEAR_SUBSCRIPTION, }); -export const setAlerts = (path: Array, value: any) => +const setAlerts = (path: Array, value: any) => (dispatch: React.Dispatch) => dispatch({ type: SET_ALERTS, path, value, }); + +export { + SET_BROWSER_SUPPORT, + SET_SUBSCRIPTION, + CLEAR_SUBSCRIPTION, + SET_ALERTS, + setBrowserSupport, + setSubscription, + clearSubscription, + setAlerts, +}; diff --git a/app/soapbox/actions/push_subscriptions.ts b/app/soapbox/actions/push_subscriptions.ts index d44b064cc..129637a20 100644 --- a/app/soapbox/actions/push_subscriptions.ts +++ b/app/soapbox/actions/push_subscriptions.ts @@ -1,24 +1,24 @@ import api from '../api'; -export const PUSH_SUBSCRIPTION_CREATE_REQUEST = 'PUSH_SUBSCRIPTION_CREATE_REQUEST'; -export const PUSH_SUBSCRIPTION_CREATE_SUCCESS = 'PUSH_SUBSCRIPTION_CREATE_SUCCESS'; -export const PUSH_SUBSCRIPTION_CREATE_FAIL = 'PUSH_SUBSCRIPTION_CREATE_FAIL'; +const PUSH_SUBSCRIPTION_CREATE_REQUEST = 'PUSH_SUBSCRIPTION_CREATE_REQUEST'; +const PUSH_SUBSCRIPTION_CREATE_SUCCESS = 'PUSH_SUBSCRIPTION_CREATE_SUCCESS'; +const PUSH_SUBSCRIPTION_CREATE_FAIL = 'PUSH_SUBSCRIPTION_CREATE_FAIL'; -export const PUSH_SUBSCRIPTION_FETCH_REQUEST = 'PUSH_SUBSCRIPTION_FETCH_REQUEST'; -export const PUSH_SUBSCRIPTION_FETCH_SUCCESS = 'PUSH_SUBSCRIPTION_FETCH_SUCCESS'; -export const PUSH_SUBSCRIPTION_FETCH_FAIL = 'PUSH_SUBSCRIPTION_FETCH_FAIL'; +const PUSH_SUBSCRIPTION_FETCH_REQUEST = 'PUSH_SUBSCRIPTION_FETCH_REQUEST'; +const PUSH_SUBSCRIPTION_FETCH_SUCCESS = 'PUSH_SUBSCRIPTION_FETCH_SUCCESS'; +const PUSH_SUBSCRIPTION_FETCH_FAIL = 'PUSH_SUBSCRIPTION_FETCH_FAIL'; -export const PUSH_SUBSCRIPTION_UPDATE_REQUEST = 'PUSH_SUBSCRIPTION_UPDATE_REQUEST'; -export const PUSH_SUBSCRIPTION_UPDATE_SUCCESS = 'PUSH_SUBSCRIPTION_UPDATE_SUCCESS'; -export const PUSH_SUBSCRIPTION_UPDATE_FAIL = 'PUSH_SUBSCRIPTION_UPDATE_FAIL'; +const PUSH_SUBSCRIPTION_UPDATE_REQUEST = 'PUSH_SUBSCRIPTION_UPDATE_REQUEST'; +const PUSH_SUBSCRIPTION_UPDATE_SUCCESS = 'PUSH_SUBSCRIPTION_UPDATE_SUCCESS'; +const PUSH_SUBSCRIPTION_UPDATE_FAIL = 'PUSH_SUBSCRIPTION_UPDATE_FAIL'; -export const PUSH_SUBSCRIPTION_DELETE_REQUEST = 'PUSH_SUBSCRIPTION_DELETE_REQUEST'; -export const PUSH_SUBSCRIPTION_DELETE_SUCCESS = 'PUSH_SUBSCRIPTION_DELETE_SUCCESS'; -export const PUSH_SUBSCRIPTION_DELETE_FAIL = 'PUSH_SUBSCRIPTION_DELETE_FAIL'; +const PUSH_SUBSCRIPTION_DELETE_REQUEST = 'PUSH_SUBSCRIPTION_DELETE_REQUEST'; +const PUSH_SUBSCRIPTION_DELETE_SUCCESS = 'PUSH_SUBSCRIPTION_DELETE_SUCCESS'; +const PUSH_SUBSCRIPTION_DELETE_FAIL = 'PUSH_SUBSCRIPTION_DELETE_FAIL'; import type { AppDispatch, RootState } from 'soapbox/store'; -export const createPushSubscription = (params: Record) => +const createPushSubscription = (params: Record) => (dispatch: AppDispatch, getState: () => RootState) => { dispatch({ type: PUSH_SUBSCRIPTION_CREATE_REQUEST, params }); return api(getState).post('/api/v1/push/subscription', params).then(({ data: subscription }) => @@ -28,7 +28,7 @@ export const createPushSubscription = (params: Record) => ); }; -export const fetchPushSubscription = () => +const fetchPushSubscription = () => (dispatch: AppDispatch, getState: () => RootState) => { dispatch({ type: PUSH_SUBSCRIPTION_FETCH_REQUEST }); return api(getState).get('/api/v1/push/subscription').then(({ data: subscription }) => @@ -38,7 +38,7 @@ export const fetchPushSubscription = () => ); }; -export const updatePushSubscription = (params: Record) => +const updatePushSubscription = (params: Record) => (dispatch: AppDispatch, getState: () => any) => { dispatch({ type: PUSH_SUBSCRIPTION_UPDATE_REQUEST, params }); return api(getState).put('/api/v1/push/subscription', params).then(({ data: subscription }) => @@ -48,7 +48,7 @@ export const updatePushSubscription = (params: Record) => ); }; -export const deletePushSubscription = () => +const deletePushSubscription = () => (dispatch: AppDispatch, getState: () => RootState) => { dispatch({ type: PUSH_SUBSCRIPTION_DELETE_REQUEST }); return api(getState).delete('/api/v1/push/subscription').then(() => @@ -57,3 +57,22 @@ export const deletePushSubscription = () => dispatch({ type: PUSH_SUBSCRIPTION_DELETE_FAIL, error }), ); }; + +export { + PUSH_SUBSCRIPTION_CREATE_REQUEST, + PUSH_SUBSCRIPTION_CREATE_SUCCESS, + PUSH_SUBSCRIPTION_CREATE_FAIL, + PUSH_SUBSCRIPTION_FETCH_REQUEST, + PUSH_SUBSCRIPTION_FETCH_SUCCESS, + PUSH_SUBSCRIPTION_FETCH_FAIL, + PUSH_SUBSCRIPTION_UPDATE_REQUEST, + PUSH_SUBSCRIPTION_UPDATE_SUCCESS, + PUSH_SUBSCRIPTION_UPDATE_FAIL, + PUSH_SUBSCRIPTION_DELETE_REQUEST, + PUSH_SUBSCRIPTION_DELETE_SUCCESS, + PUSH_SUBSCRIPTION_DELETE_FAIL, + createPushSubscription, + fetchPushSubscription, + updatePushSubscription, + deletePushSubscription, +}; diff --git a/app/soapbox/actions/remote_timeline.js b/app/soapbox/actions/remote_timeline.ts similarity index 63% rename from app/soapbox/actions/remote_timeline.js rename to app/soapbox/actions/remote_timeline.ts index 8238c3326..6cbcc2869 100644 --- a/app/soapbox/actions/remote_timeline.js +++ b/app/soapbox/actions/remote_timeline.ts @@ -1,24 +1,29 @@ import { getSettings, changeSetting } from 'soapbox/actions/settings'; -const getPinnedHosts = state => { +import type { AppDispatch, RootState } from 'soapbox/store'; + +const getPinnedHosts = (state: RootState) => { const settings = getSettings(state); return settings.getIn(['remote_timeline', 'pinnedHosts']); }; -export function pinHost(host) { - return (dispatch, getState) => { +const pinHost = (host: string) => + (dispatch: AppDispatch, getState: () => RootState) => { const state = getState(); const pinnedHosts = getPinnedHosts(state); return dispatch(changeSetting(['remote_timeline', 'pinnedHosts'], pinnedHosts.push(host))); }; -} -export function unpinHost(host) { - return (dispatch, getState) => { +const unpinHost = (host) => + (dispatch: AppDispatch, getState: () => RootState) => { const state = getState(); const pinnedHosts = getPinnedHosts(state); return dispatch(changeSetting(['remote_timeline', 'pinnedHosts'], pinnedHosts.filter((value) => value !== host))); }; -} + +export { + pinHost, + unpinHost, +}; diff --git a/app/soapbox/actions/settings.js b/app/soapbox/actions/settings.js index 05f8f310b..45b5759be 100644 --- a/app/soapbox/actions/settings.js +++ b/app/soapbox/actions/settings.js @@ -187,7 +187,7 @@ export function changeSettingImmediate(path, value) { }; } -export function changeSetting(path, value, intl) { +export function changeSetting(path, value) { return dispatch => { dispatch({ type: SETTING_CHANGE, @@ -195,11 +195,11 @@ export function changeSetting(path, value, intl) { value, }); - return dispatch(saveSettings(intl)); + return dispatch(saveSettings()); }; } -export function saveSettingsImmediate(intl) { +export function saveSettingsImmediate() { return (dispatch, getState) => { if (!isLoggedIn(getState)) return; @@ -215,15 +215,13 @@ export function saveSettingsImmediate(intl) { })).then(response => { dispatch({ type: SETTING_SAVE }); - if (intl) { - dispatch(snackbar.success(intl.formatMessage(messages.saveSuccess))); - } + dispatch(snackbar.success(messages.saveSuccess)); }).catch(error => { dispatch(showAlertForError(error)); }); }; } -export function saveSettings(intl) { - return (dispatch, getState) => dispatch(saveSettingsImmediate(intl)); +export function saveSettings() { + return (dispatch, getState) => dispatch(saveSettingsImmediate()); } diff --git a/app/soapbox/actions/sidebar.js b/app/soapbox/actions/sidebar.js deleted file mode 100644 index 247c6df83..000000000 --- a/app/soapbox/actions/sidebar.js +++ /dev/null @@ -1,14 +0,0 @@ -export const SIDEBAR_OPEN = 'SIDEBAR_OPEN'; -export const SIDEBAR_CLOSE = 'SIDEBAR_CLOSE'; - -export function openSidebar() { - return { - type: SIDEBAR_OPEN, - }; -} - -export function closeSidebar() { - return { - type: SIDEBAR_CLOSE, - }; -} diff --git a/app/soapbox/actions/sidebar.ts b/app/soapbox/actions/sidebar.ts new file mode 100644 index 000000000..3c9d05cff --- /dev/null +++ b/app/soapbox/actions/sidebar.ts @@ -0,0 +1,17 @@ +const SIDEBAR_OPEN = 'SIDEBAR_OPEN'; +const SIDEBAR_CLOSE = 'SIDEBAR_CLOSE'; + +const openSidebar = () => ({ + type: SIDEBAR_OPEN, +}); + +const closeSidebar = () => ({ + type: SIDEBAR_CLOSE, +}); + +export { + SIDEBAR_OPEN, + SIDEBAR_CLOSE, + openSidebar, + closeSidebar, +}; diff --git a/app/soapbox/actions/suggestions.js b/app/soapbox/actions/suggestions.js deleted file mode 100644 index c804c4855..000000000 --- a/app/soapbox/actions/suggestions.js +++ /dev/null @@ -1,92 +0,0 @@ -import { isLoggedIn } from 'soapbox/utils/auth'; -import { getFeatures } from 'soapbox/utils/features'; - -import api, { getLinks } from '../api'; - -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_DISMISS = 'SUGGESTIONS_DISMISS'; - -export const SUGGESTIONS_V2_FETCH_REQUEST = 'SUGGESTIONS_V2_FETCH_REQUEST'; -export const SUGGESTIONS_V2_FETCH_SUCCESS = 'SUGGESTIONS_V2_FETCH_SUCCESS'; -export const SUGGESTIONS_V2_FETCH_FAIL = 'SUGGESTIONS_V2_FETCH_FAIL'; - -export function fetchSuggestionsV1(params = {}) { - return (dispatch, getState) => { - dispatch({ type: SUGGESTIONS_FETCH_REQUEST, skipLoading: true }); - return api(getState).get('/api/v1/suggestions', { params }).then(({ data: accounts }) => { - dispatch(importFetchedAccounts(accounts)); - dispatch({ type: SUGGESTIONS_FETCH_SUCCESS, accounts, skipLoading: true }); - return accounts; - }).catch(error => { - dispatch({ type: SUGGESTIONS_FETCH_FAIL, error, skipLoading: true, skipAlert: true }); - throw error; - }); - }; -} - -export function fetchSuggestionsV2(params = {}) { - return (dispatch, getState) => { - const next = getState().getIn(['suggestions', 'next']); - - dispatch({ type: SUGGESTIONS_V2_FETCH_REQUEST, skipLoading: true }); - - return api(getState).get(next ? next.uri : '/api/v2/suggestions', next ? {} : { params }).then((response) => { - const suggestions = response.data; - const accounts = suggestions.map(({ account }) => account); - const next = getLinks(response).refs.find(link => link.rel === 'next'); - - dispatch(importFetchedAccounts(accounts)); - dispatch({ type: SUGGESTIONS_V2_FETCH_SUCCESS, suggestions, next, skipLoading: true }); - return suggestions; - }).catch(error => { - dispatch({ type: SUGGESTIONS_V2_FETCH_FAIL, error, skipLoading: true, skipAlert: true }); - throw error; - }); - }; -} - -export function fetchSuggestions(params = { limit: 50 }) { - return (dispatch, getState) => { - const state = getState(); - const me = state.get('me'); - const instance = state.get('instance'); - const features = getFeatures(instance); - - if (!me) return; - - if (features.suggestionsV2) { - dispatch(fetchSuggestionsV2(params)) - .then(suggestions => { - const accountIds = suggestions.map(({ account }) => account.id); - dispatch(fetchRelationships(accountIds)); - }) - .catch(() => { }); - } else if (features.suggestions) { - dispatch(fetchSuggestionsV1(params)) - .then(accounts => { - const accountIds = accounts.map(({ id }) => id); - dispatch(fetchRelationships(accountIds)); - }) - .catch(() => { }); - } else { - // Do nothing - } - }; -} - -export const dismissSuggestion = accountId => (dispatch, getState) => { - if (!isLoggedIn(getState)) return; - - dispatch({ - type: SUGGESTIONS_DISMISS, - id: accountId, - }); - - api(getState).delete(`/api/v1/suggestions/${accountId}`); -}; diff --git a/app/soapbox/actions/suggestions.ts b/app/soapbox/actions/suggestions.ts new file mode 100644 index 000000000..d82f81f40 --- /dev/null +++ b/app/soapbox/actions/suggestions.ts @@ -0,0 +1,107 @@ +import { isLoggedIn } from 'soapbox/utils/auth'; +import { getFeatures } from 'soapbox/utils/features'; + +import api, { getLinks } from '../api'; + +import { fetchRelationships } from './accounts'; +import { importFetchedAccounts } from './importer'; + +import type { AppDispatch, RootState } from 'soapbox/store'; +import type { APIEntity } from 'soapbox/types/entities'; + +const SUGGESTIONS_FETCH_REQUEST = 'SUGGESTIONS_FETCH_REQUEST'; +const SUGGESTIONS_FETCH_SUCCESS = 'SUGGESTIONS_FETCH_SUCCESS'; +const SUGGESTIONS_FETCH_FAIL = 'SUGGESTIONS_FETCH_FAIL'; + +const SUGGESTIONS_DISMISS = 'SUGGESTIONS_DISMISS'; + +const SUGGESTIONS_V2_FETCH_REQUEST = 'SUGGESTIONS_V2_FETCH_REQUEST'; +const SUGGESTIONS_V2_FETCH_SUCCESS = 'SUGGESTIONS_V2_FETCH_SUCCESS'; +const SUGGESTIONS_V2_FETCH_FAIL = 'SUGGESTIONS_V2_FETCH_FAIL'; + +const fetchSuggestionsV1 = (params: Record = {}) => + (dispatch: AppDispatch, getState: () => RootState) => { + dispatch({ type: SUGGESTIONS_FETCH_REQUEST, skipLoading: true }); + return api(getState).get('/api/v1/suggestions', { params }).then(({ data: accounts }) => { + dispatch(importFetchedAccounts(accounts)); + dispatch({ type: SUGGESTIONS_FETCH_SUCCESS, accounts, skipLoading: true }); + return accounts; + }).catch(error => { + dispatch({ type: SUGGESTIONS_FETCH_FAIL, error, skipLoading: true, skipAlert: true }); + throw error; + }); + }; + +const fetchSuggestionsV2 = (params: Record = {}) => + (dispatch: AppDispatch, getState: () => RootState) => { + const next = getState().suggestions.next; + + dispatch({ type: SUGGESTIONS_V2_FETCH_REQUEST, skipLoading: true }); + + return api(getState).get(next ? next : '/api/v2/suggestions', next ? {} : { params }).then((response) => { + const suggestions: APIEntity[] = response.data; + const accounts = suggestions.map(({ account }) => account); + const next = getLinks(response).refs.find(link => link.rel === 'next')?.uri; + + dispatch(importFetchedAccounts(accounts)); + dispatch({ type: SUGGESTIONS_V2_FETCH_SUCCESS, suggestions, next, skipLoading: true }); + return suggestions; + }).catch(error => { + dispatch({ type: SUGGESTIONS_V2_FETCH_FAIL, error, skipLoading: true, skipAlert: true }); + throw error; + }); + }; + +const fetchSuggestions = (params: Record = { limit: 50 }) => + (dispatch: AppDispatch, getState: () => RootState) => { + const state = getState(); + const me = state.me; + const instance = state.instance; + const features = getFeatures(instance); + + if (!me) return; + + if (features.suggestionsV2) { + dispatch(fetchSuggestionsV2(params)) + .then((suggestions: APIEntity[]) => { + const accountIds = suggestions.map(({ account }) => account.id); + dispatch(fetchRelationships(accountIds)); + }) + .catch(() => { }); + } else if (features.suggestions) { + dispatch(fetchSuggestionsV1(params)) + .then((accounts: APIEntity[]) => { + const accountIds = accounts.map(({ id }) => id); + dispatch(fetchRelationships(accountIds)); + }) + .catch(() => { }); + } else { + // Do nothing + } + }; + +const dismissSuggestion = (accountId: string) => + (dispatch: AppDispatch, getState: () => RootState) => { + if (!isLoggedIn(getState)) return; + + dispatch({ + type: SUGGESTIONS_DISMISS, + id: accountId, + }); + + api(getState).delete(`/api/v1/suggestions/${accountId}`); + }; + +export { + SUGGESTIONS_FETCH_REQUEST, + SUGGESTIONS_FETCH_SUCCESS, + SUGGESTIONS_FETCH_FAIL, + SUGGESTIONS_DISMISS, + SUGGESTIONS_V2_FETCH_REQUEST, + SUGGESTIONS_V2_FETCH_SUCCESS, + SUGGESTIONS_V2_FETCH_FAIL, + fetchSuggestionsV1, + fetchSuggestionsV2, + fetchSuggestions, + dismissSuggestion, +}; diff --git a/app/soapbox/actions/trending_statuses.js b/app/soapbox/actions/trending_statuses.ts similarity index 54% rename from app/soapbox/actions/trending_statuses.js rename to app/soapbox/actions/trending_statuses.ts index 23cf56977..435fcf6df 100644 --- a/app/soapbox/actions/trending_statuses.js +++ b/app/soapbox/actions/trending_statuses.ts @@ -4,15 +4,17 @@ import api from '../api'; import { importFetchedStatuses } from './importer'; -export const TRENDING_STATUSES_FETCH_REQUEST = 'TRENDING_STATUSES_FETCH_REQUEST'; -export const TRENDING_STATUSES_FETCH_SUCCESS = 'TRENDING_STATUSES_FETCH_SUCCESS'; -export const TRENDING_STATUSES_FETCH_FAIL = 'TRENDING_STATUSES_FETCH_FAIL'; +import type { AppDispatch, RootState } from 'soapbox/store'; -export function fetchTrendingStatuses() { - return (dispatch, getState) => { +const TRENDING_STATUSES_FETCH_REQUEST = 'TRENDING_STATUSES_FETCH_REQUEST'; +const TRENDING_STATUSES_FETCH_SUCCESS = 'TRENDING_STATUSES_FETCH_SUCCESS'; +const TRENDING_STATUSES_FETCH_FAIL = 'TRENDING_STATUSES_FETCH_FAIL'; + +const fetchTrendingStatuses = () => + (dispatch: AppDispatch, getState: () => RootState) => { const state = getState(); - const instance = state.get('instance'); + const instance = state.instance; const features = getFeatures(instance); dispatch({ type: TRENDING_STATUSES_FETCH_REQUEST }); @@ -24,4 +26,10 @@ export function fetchTrendingStatuses() { dispatch({ type: TRENDING_STATUSES_FETCH_FAIL, error }); }); }; -} + +export { + TRENDING_STATUSES_FETCH_REQUEST, + TRENDING_STATUSES_FETCH_SUCCESS, + TRENDING_STATUSES_FETCH_FAIL, + fetchTrendingStatuses, +}; diff --git a/app/soapbox/actions/trends.js b/app/soapbox/actions/trends.js deleted file mode 100644 index 36f801adf..000000000 --- a/app/soapbox/actions/trends.js +++ /dev/null @@ -1,39 +0,0 @@ -import api from '../api'; - -export const TRENDS_FETCH_REQUEST = 'TRENDS_FETCH_REQUEST'; -export const TRENDS_FETCH_SUCCESS = 'TRENDS_FETCH_SUCCESS'; -export const TRENDS_FETCH_FAIL = 'TRENDS_FETCH_FAIL'; - -export function fetchTrends() { - return (dispatch, getState) => { - dispatch(fetchTrendsRequest()); - - api(getState).get('/api/v1/trends').then(response => { - dispatch(fetchTrendsSuccess(response.data)); - }).catch(error => dispatch(fetchTrendsFail(error))); - }; -} - -export function fetchTrendsRequest() { - return { - type: TRENDS_FETCH_REQUEST, - skipLoading: true, - }; -} - -export function fetchTrendsSuccess(tags) { - return { - type: TRENDS_FETCH_SUCCESS, - tags, - skipLoading: true, - }; -} - -export function fetchTrendsFail(error) { - return { - type: TRENDS_FETCH_FAIL, - error, - skipLoading: true, - skipAlert: true, - }; -} diff --git a/app/soapbox/actions/trends.ts b/app/soapbox/actions/trends.ts new file mode 100644 index 000000000..dc45a5c38 --- /dev/null +++ b/app/soapbox/actions/trends.ts @@ -0,0 +1,46 @@ +import api from '../api'; + +import type { AxiosError } from 'axios'; +import type { AppDispatch, RootState } from 'soapbox/store'; +import type { APIEntity } from 'soapbox/types/entities'; + +const TRENDS_FETCH_REQUEST = 'TRENDS_FETCH_REQUEST'; +const TRENDS_FETCH_SUCCESS = 'TRENDS_FETCH_SUCCESS'; +const TRENDS_FETCH_FAIL = 'TRENDS_FETCH_FAIL'; + +const fetchTrends = () => + (dispatch: AppDispatch, getState: () => RootState) => { + dispatch(fetchTrendsRequest()); + + api(getState).get('/api/v1/trends').then(response => { + dispatch(fetchTrendsSuccess(response.data)); + }).catch(error => dispatch(fetchTrendsFail(error))); + }; + +const fetchTrendsRequest = () => ({ + type: TRENDS_FETCH_REQUEST, + skipLoading: true, +}); + +const fetchTrendsSuccess = (tags: APIEntity[]) => ({ + type: TRENDS_FETCH_SUCCESS, + tags, + skipLoading: true, +}); + +const fetchTrendsFail = (error: AxiosError) => ({ + type: TRENDS_FETCH_FAIL, + error, + skipLoading: true, + skipAlert: true, +}); + +export { + TRENDS_FETCH_REQUEST, + TRENDS_FETCH_SUCCESS, + TRENDS_FETCH_FAIL, + fetchTrends, + fetchTrendsRequest, + fetchTrendsSuccess, + fetchTrendsFail, +}; diff --git a/app/soapbox/features/filters/index.tsx b/app/soapbox/features/filters/index.tsx index d71adb96e..31fa728fb 100644 --- a/app/soapbox/features/filters/index.tsx +++ b/app/soapbox/features/filters/index.tsx @@ -63,7 +63,7 @@ const Filters = () => { const handleAddNew: React.FormEventHandler = e => { e.preventDefault(); - const context = []; + const context: Array = []; if (homeTimeline) { context.push('home'); @@ -78,7 +78,7 @@ const Filters = () => { context.push('thread'); } - dispatch(createFilter(intl, phrase, expiresAt, context, wholeWord, irreversible)).then(() => { + dispatch(createFilter(phrase, expiresAt, context, wholeWord, irreversible)).then(() => { return dispatch(fetchFilters()); }).catch(error => { dispatch(snackbar.error(intl.formatMessage(messages.create_error))); @@ -86,7 +86,7 @@ const Filters = () => { }; const handleFilterDelete: React.MouseEventHandler = e => { - dispatch(deleteFilter(intl, e.currentTarget.dataset.value)).then(() => { + dispatch(deleteFilter(e.currentTarget.dataset.value)).then(() => { return dispatch(fetchFilters()); }).catch(() => { dispatch(snackbar.error(intl.formatMessage(messages.delete_error))); diff --git a/app/soapbox/features/preferences/index.tsx b/app/soapbox/features/preferences/index.tsx index 593978dbc..c666a847e 100644 --- a/app/soapbox/features/preferences/index.tsx +++ b/app/soapbox/features/preferences/index.tsx @@ -96,11 +96,11 @@ const Preferences = () => { const settings = useAppSelector((state) => getSettings(state)); const onSelectChange = (event: React.ChangeEvent, path: string[]) => { - dispatch(changeSetting(path, event.target.value, intl)); + dispatch(changeSetting(path, event.target.value)); }; const onToggleChange = (key: string[], checked: boolean) => { - dispatch(changeSetting(key, checked, intl)); + dispatch(changeSetting(key, checked)); }; const displayMediaOptions = React.useMemo(() => ({