diff --git a/app/soapbox/actions/bookmarks.js b/app/soapbox/actions/bookmarks.js deleted file mode 100644 index a0400ff38..000000000 --- a/app/soapbox/actions/bookmarks.js +++ /dev/null @@ -1,93 +0,0 @@ -import api, { getLinks } from '../api'; - -import { importFetchedStatuses } from './importer'; - -export const BOOKMARKED_STATUSES_FETCH_REQUEST = 'BOOKMARKED_STATUSES_FETCH_REQUEST'; -export const BOOKMARKED_STATUSES_FETCH_SUCCESS = 'BOOKMARKED_STATUSES_FETCH_SUCCESS'; -export const BOOKMARKED_STATUSES_FETCH_FAIL = 'BOOKMARKED_STATUSES_FETCH_FAIL'; - -export const BOOKMARKED_STATUSES_EXPAND_REQUEST = 'BOOKMARKED_STATUSES_EXPAND_REQUEST'; -export const BOOKMARKED_STATUSES_EXPAND_SUCCESS = 'BOOKMARKED_STATUSES_EXPAND_SUCCESS'; -export const BOOKMARKED_STATUSES_EXPAND_FAIL = 'BOOKMARKED_STATUSES_EXPAND_FAIL'; - -const noOp = () => new Promise(f => f()); - -export function fetchBookmarkedStatuses() { - return (dispatch, getState) => { - if (getState().getIn(['status_lists', 'bookmarks', 'isLoading'])) { - return dispatch(noOp); - } - - dispatch(fetchBookmarkedStatusesRequest()); - - return api(getState).get('/api/v1/bookmarks').then(response => { - const next = getLinks(response).refs.find(link => link.rel === 'next'); - dispatch(importFetchedStatuses(response.data)); - dispatch(fetchBookmarkedStatusesSuccess(response.data, next ? next.uri : null)); - }).catch(error => { - dispatch(fetchBookmarkedStatusesFail(error)); - }); - }; -} - -export function fetchBookmarkedStatusesRequest() { - return { - type: BOOKMARKED_STATUSES_FETCH_REQUEST, - }; -} - -export function fetchBookmarkedStatusesSuccess(statuses, next) { - return { - type: BOOKMARKED_STATUSES_FETCH_SUCCESS, - statuses, - next, - }; -} - -export function fetchBookmarkedStatusesFail(error) { - return { - type: BOOKMARKED_STATUSES_FETCH_FAIL, - error, - }; -} - -export function expandBookmarkedStatuses() { - return (dispatch, getState) => { - const url = getState().getIn(['status_lists', 'bookmarks', 'next'], null); - - if (url === null || getState().getIn(['status_lists', 'bookmarks', 'isLoading'])) { - return dispatch(noOp); - } - - dispatch(expandBookmarkedStatusesRequest()); - - return api(getState).get(url).then(response => { - const next = getLinks(response).refs.find(link => link.rel === 'next'); - dispatch(importFetchedStatuses(response.data)); - dispatch(expandBookmarkedStatusesSuccess(response.data, next ? next.uri : null)); - }).catch(error => { - dispatch(expandBookmarkedStatusesFail(error)); - }); - }; -} - -export function expandBookmarkedStatusesRequest() { - return { - type: BOOKMARKED_STATUSES_EXPAND_REQUEST, - }; -} - -export function expandBookmarkedStatusesSuccess(statuses, next) { - return { - type: BOOKMARKED_STATUSES_EXPAND_SUCCESS, - statuses, - next, - }; -} - -export function expandBookmarkedStatusesFail(error) { - return { - type: BOOKMARKED_STATUSES_EXPAND_FAIL, - error, - }; -} diff --git a/app/soapbox/actions/bookmarks.ts b/app/soapbox/actions/bookmarks.ts new file mode 100644 index 000000000..8a0b6e2ab --- /dev/null +++ b/app/soapbox/actions/bookmarks.ts @@ -0,0 +1,100 @@ +import api, { getLinks } from '../api'; + +import { importFetchedStatuses } from './importer'; + +import type { AxiosError } from 'axios'; +import type { AppDispatch, RootState } from 'soapbox/store'; +import type { APIEntity } from 'soapbox/types/entities'; + +const BOOKMARKED_STATUSES_FETCH_REQUEST = 'BOOKMARKED_STATUSES_FETCH_REQUEST'; +const BOOKMARKED_STATUSES_FETCH_SUCCESS = 'BOOKMARKED_STATUSES_FETCH_SUCCESS'; +const BOOKMARKED_STATUSES_FETCH_FAIL = 'BOOKMARKED_STATUSES_FETCH_FAIL'; + +const BOOKMARKED_STATUSES_EXPAND_REQUEST = 'BOOKMARKED_STATUSES_EXPAND_REQUEST'; +const BOOKMARKED_STATUSES_EXPAND_SUCCESS = 'BOOKMARKED_STATUSES_EXPAND_SUCCESS'; +const BOOKMARKED_STATUSES_EXPAND_FAIL = 'BOOKMARKED_STATUSES_EXPAND_FAIL'; + +const noOp = () => new Promise(f => f(undefined)); + +const fetchBookmarkedStatuses = () => + (dispatch: AppDispatch, getState: () => RootState) => { + if (getState().status_lists.getIn(['bookmarks', 'isLoading'])) { + return dispatch(noOp); + } + + dispatch(fetchBookmarkedStatusesRequest()); + + return api(getState).get('/api/v1/bookmarks').then(response => { + const next = getLinks(response).refs.find(link => link.rel === 'next'); + dispatch(importFetchedStatuses(response.data)); + return dispatch(fetchBookmarkedStatusesSuccess(response.data, next ? next.uri : null)); + }).catch(error => { + dispatch(fetchBookmarkedStatusesFail(error)); + }); + }; + +const fetchBookmarkedStatusesRequest = () => ({ + type: BOOKMARKED_STATUSES_FETCH_REQUEST, +}); + +const fetchBookmarkedStatusesSuccess = (statuses: APIEntity[], next: string | null) => ({ + type: BOOKMARKED_STATUSES_FETCH_SUCCESS, + statuses, + next, +}); + +const fetchBookmarkedStatusesFail = (error: AxiosError) => ({ + type: BOOKMARKED_STATUSES_FETCH_FAIL, + error, +}); + +const expandBookmarkedStatuses = () => + (dispatch: AppDispatch, getState: () => RootState) => { + const url = getState().status_lists.get('bookmarks')?.next || null; + + if (url === null || getState().status_lists.getIn(['bookmarks', 'isLoading'])) { + return dispatch(noOp); + } + + dispatch(expandBookmarkedStatusesRequest()); + + return api(getState).get(url).then(response => { + const next = getLinks(response).refs.find(link => link.rel === 'next'); + dispatch(importFetchedStatuses(response.data)); + return dispatch(expandBookmarkedStatusesSuccess(response.data, next ? next.uri : null)); + }).catch(error => { + dispatch(expandBookmarkedStatusesFail(error)); + }); + }; + +const expandBookmarkedStatusesRequest = () => ({ + type: BOOKMARKED_STATUSES_EXPAND_REQUEST, +}); + +const expandBookmarkedStatusesSuccess = (statuses: APIEntity[], next: string | null) => ({ + type: BOOKMARKED_STATUSES_EXPAND_SUCCESS, + statuses, + next, +}); + +const expandBookmarkedStatusesFail = (error: AxiosError) => ({ + type: BOOKMARKED_STATUSES_EXPAND_FAIL, + error, +}); + +export { + BOOKMARKED_STATUSES_FETCH_REQUEST, + BOOKMARKED_STATUSES_FETCH_SUCCESS, + BOOKMARKED_STATUSES_FETCH_FAIL, + BOOKMARKED_STATUSES_EXPAND_REQUEST, + BOOKMARKED_STATUSES_EXPAND_SUCCESS, + BOOKMARKED_STATUSES_EXPAND_FAIL, + fetchBookmarkedStatuses, + fetchBookmarkedStatusesRequest, + fetchBookmarkedStatusesSuccess, + fetchBookmarkedStatusesFail, + expandBookmarkedStatuses, + expandBookmarkedStatusesRequest, + expandBookmarkedStatusesSuccess, + expandBookmarkedStatusesFail, +}; diff --git a/app/soapbox/actions/conversations.js b/app/soapbox/actions/conversations.js deleted file mode 100644 index 4e7eb214f..000000000 --- a/app/soapbox/actions/conversations.js +++ /dev/null @@ -1,91 +0,0 @@ -import { isLoggedIn } from 'soapbox/utils/auth'; - -import api, { getLinks } from '../api'; - -import { - importFetchedAccounts, - importFetchedStatuses, - importFetchedStatus, -} from './importer'; - -export const CONVERSATIONS_MOUNT = 'CONVERSATIONS_MOUNT'; -export const CONVERSATIONS_UNMOUNT = 'CONVERSATIONS_UNMOUNT'; - -export const CONVERSATIONS_FETCH_REQUEST = 'CONVERSATIONS_FETCH_REQUEST'; -export const CONVERSATIONS_FETCH_SUCCESS = 'CONVERSATIONS_FETCH_SUCCESS'; -export const CONVERSATIONS_FETCH_FAIL = 'CONVERSATIONS_FETCH_FAIL'; -export const CONVERSATIONS_UPDATE = 'CONVERSATIONS_UPDATE'; - -export const CONVERSATIONS_READ = 'CONVERSATIONS_READ'; - -export const mountConversations = () => ({ - type: CONVERSATIONS_MOUNT, -}); - -export const unmountConversations = () => ({ - type: CONVERSATIONS_UNMOUNT, -}); - -export const markConversationRead = conversationId => (dispatch, getState) => { - if (!isLoggedIn(getState)) return; - - dispatch({ - type: CONVERSATIONS_READ, - id: conversationId, - }); - - api(getState).post(`/api/v1/conversations/${conversationId}/read`); -}; - -export const expandConversations = ({ maxId } = {}) => (dispatch, getState) => { - if (!isLoggedIn(getState)) return; - - dispatch(expandConversationsRequest()); - - const params = { max_id: maxId }; - - if (!maxId) { - params.since_id = getState().getIn(['conversations', 'items', 0, 'id']); - } - - const isLoadingRecent = !!params.since_id; - - api(getState).get('/api/v1/conversations', { params }) - .then(response => { - const next = getLinks(response).refs.find(link => link.rel === 'next'); - - dispatch(importFetchedAccounts(response.data.reduce((aggr, item) => aggr.concat(item.accounts), []))); - dispatch(importFetchedStatuses(response.data.map(item => item.last_status).filter(x => !!x))); - dispatch(expandConversationsSuccess(response.data, next ? next.uri : null, isLoadingRecent)); - }) - .catch(err => dispatch(expandConversationsFail(err))); -}; - -export const expandConversationsRequest = () => ({ - type: CONVERSATIONS_FETCH_REQUEST, -}); - -export const expandConversationsSuccess = (conversations, next, isLoadingRecent) => ({ - type: CONVERSATIONS_FETCH_SUCCESS, - conversations, - next, - isLoadingRecent, -}); - -export const expandConversationsFail = error => ({ - type: CONVERSATIONS_FETCH_FAIL, - error, -}); - -export const updateConversations = conversation => dispatch => { - dispatch(importFetchedAccounts(conversation.accounts)); - - if (conversation.last_status) { - dispatch(importFetchedStatus(conversation.last_status)); - } - - dispatch({ - type: CONVERSATIONS_UPDATE, - conversation, - }); -}; diff --git a/app/soapbox/actions/conversations.ts b/app/soapbox/actions/conversations.ts new file mode 100644 index 000000000..a56e02d6f --- /dev/null +++ b/app/soapbox/actions/conversations.ts @@ -0,0 +1,113 @@ +import { isLoggedIn } from 'soapbox/utils/auth'; + +import api, { getLinks } from '../api'; + +import { + importFetchedAccounts, + importFetchedStatuses, + importFetchedStatus, +} from './importer'; + +import type { AxiosError } from 'axios'; +import type { AppDispatch, RootState } from 'soapbox/store'; +import type { APIEntity } from 'soapbox/types/entities'; + +const CONVERSATIONS_MOUNT = 'CONVERSATIONS_MOUNT'; +const CONVERSATIONS_UNMOUNT = 'CONVERSATIONS_UNMOUNT'; + +const CONVERSATIONS_FETCH_REQUEST = 'CONVERSATIONS_FETCH_REQUEST'; +const CONVERSATIONS_FETCH_SUCCESS = 'CONVERSATIONS_FETCH_SUCCESS'; +const CONVERSATIONS_FETCH_FAIL = 'CONVERSATIONS_FETCH_FAIL'; +const CONVERSATIONS_UPDATE = 'CONVERSATIONS_UPDATE'; + +const CONVERSATIONS_READ = 'CONVERSATIONS_READ'; + +const mountConversations = () => ({ + type: CONVERSATIONS_MOUNT, +}); + +const unmountConversations = () => ({ + type: CONVERSATIONS_UNMOUNT, +}); + +const markConversationRead = (conversationId: string) => (dispatch: AppDispatch, getState: () => RootState) => { + if (!isLoggedIn(getState)) return; + + dispatch({ + type: CONVERSATIONS_READ, + id: conversationId, + }); + + api(getState).post(`/api/v1/conversations/${conversationId}/read`); +}; + +const expandConversations = ({ maxId }: Record = {}) => (dispatch: AppDispatch, getState: () => RootState) => { + if (!isLoggedIn(getState)) return; + + dispatch(expandConversationsRequest()); + + const params: Record = { max_id: maxId }; + + if (!maxId) { + params.since_id = getState().conversations.getIn(['items', 0, 'id']); + } + + const isLoadingRecent = !!params.since_id; + + api(getState).get('/api/v1/conversations', { params }) + .then(response => { + const next = getLinks(response).refs.find(link => link.rel === 'next'); + + dispatch(importFetchedAccounts(response.data.reduce((aggr: Array, item: APIEntity) => aggr.concat(item.accounts), []))); + dispatch(importFetchedStatuses(response.data.map((item: Record) => item.last_status).filter((x?: APIEntity) => !!x))); + dispatch(expandConversationsSuccess(response.data, next ? next.uri : null, isLoadingRecent)); + }) + .catch(err => dispatch(expandConversationsFail(err))); +}; + +const expandConversationsRequest = () => ({ + type: CONVERSATIONS_FETCH_REQUEST, +}); + +const expandConversationsSuccess = (conversations: APIEntity[], next: string | null, isLoadingRecent: boolean) => ({ + type: CONVERSATIONS_FETCH_SUCCESS, + conversations, + next, + isLoadingRecent, +}); + +const expandConversationsFail = (error: AxiosError) => ({ + type: CONVERSATIONS_FETCH_FAIL, + error, +}); + +const updateConversations = (conversation: APIEntity) => (dispatch: AppDispatch) => { + dispatch(importFetchedAccounts(conversation.accounts)); + + if (conversation.last_status) { + dispatch(importFetchedStatus(conversation.last_status)); + } + + return dispatch({ + type: CONVERSATIONS_UPDATE, + conversation, + }); +}; + +export { + CONVERSATIONS_MOUNT, + CONVERSATIONS_UNMOUNT, + CONVERSATIONS_FETCH_REQUEST, + CONVERSATIONS_FETCH_SUCCESS, + CONVERSATIONS_FETCH_FAIL, + CONVERSATIONS_UPDATE, + CONVERSATIONS_READ, + mountConversations, + unmountConversations, + markConversationRead, + expandConversations, + expandConversationsRequest, + expandConversationsSuccess, + expandConversationsFail, + updateConversations, +}; \ No newline at end of file diff --git a/app/soapbox/actions/reports.js b/app/soapbox/actions/reports.js deleted file mode 100644 index 8e8e45595..000000000 --- a/app/soapbox/actions/reports.js +++ /dev/null @@ -1,116 +0,0 @@ -import api from '../api'; - -import { openModal } from './modals'; - -export const REPORT_INIT = 'REPORT_INIT'; -export const REPORT_CANCEL = 'REPORT_CANCEL'; - -export const REPORT_SUBMIT_REQUEST = 'REPORT_SUBMIT_REQUEST'; -export const REPORT_SUBMIT_SUCCESS = 'REPORT_SUBMIT_SUCCESS'; -export const REPORT_SUBMIT_FAIL = 'REPORT_SUBMIT_FAIL'; - -export const REPORT_STATUS_TOGGLE = 'REPORT_STATUS_TOGGLE'; -export const REPORT_COMMENT_CHANGE = 'REPORT_COMMENT_CHANGE'; -export const REPORT_FORWARD_CHANGE = 'REPORT_FORWARD_CHANGE'; -export const REPORT_BLOCK_CHANGE = 'REPORT_BLOCK_CHANGE'; - -export const REPORT_RULE_CHANGE = 'REPORT_RULE_CHANGE'; - -export function initReport(account, status) { - return dispatch => { - dispatch({ - type: REPORT_INIT, - account, - status, - }); - - dispatch(openModal('REPORT')); - }; -} - -export function initReportById(accountId) { - return (dispatch, getState) => { - dispatch({ - type: REPORT_INIT, - account: getState().getIn(['accounts', accountId]), - }); - - dispatch(openModal('REPORT')); - }; -} - -export function cancelReport() { - return { - type: REPORT_CANCEL, - }; -} - -export function toggleStatusReport(statusId, checked) { - return { - type: REPORT_STATUS_TOGGLE, - statusId, - checked, - }; -} - -export function submitReport() { - return (dispatch, getState) => { - dispatch(submitReportRequest()); - const { reports } = getState(); - - return api(getState).post('/api/v1/reports', { - account_id: reports.getIn(['new', 'account_id']), - status_ids: reports.getIn(['new', 'status_ids']), - rule_ids: reports.getIn(['new', 'rule_ids']), - comment: reports.getIn(['new', 'comment']), - forward: reports.getIn(['new', 'forward']), - }); - }; -} - -export function submitReportRequest() { - return { - type: REPORT_SUBMIT_REQUEST, - }; -} - -export function submitReportSuccess() { - return { - type: REPORT_SUBMIT_SUCCESS, - }; -} - -export function submitReportFail(error) { - return { - type: REPORT_SUBMIT_FAIL, - error, - }; -} - -export function changeReportComment(comment) { - return { - type: REPORT_COMMENT_CHANGE, - comment, - }; -} - -export function changeReportForward(forward) { - return { - type: REPORT_FORWARD_CHANGE, - forward, - }; -} - -export function changeReportBlock(block) { - return { - type: REPORT_BLOCK_CHANGE, - block, - }; -} - -export function changeReportRule(ruleId) { - return { - type: REPORT_RULE_CHANGE, - rule_id: ruleId, - }; -} diff --git a/app/soapbox/actions/reports.ts b/app/soapbox/actions/reports.ts new file mode 100644 index 000000000..40b685ba4 --- /dev/null +++ b/app/soapbox/actions/reports.ts @@ -0,0 +1,124 @@ +import api from '../api'; + +import { openModal } from './modals'; + +import type { AxiosError } from 'axios'; +import type { AppDispatch, RootState } from 'soapbox/store'; +import type { Account, Status } from 'soapbox/types/entities'; + +const REPORT_INIT = 'REPORT_INIT'; +const REPORT_CANCEL = 'REPORT_CANCEL'; + +const REPORT_SUBMIT_REQUEST = 'REPORT_SUBMIT_REQUEST'; +const REPORT_SUBMIT_SUCCESS = 'REPORT_SUBMIT_SUCCESS'; +const REPORT_SUBMIT_FAIL = 'REPORT_SUBMIT_FAIL'; + +const REPORT_STATUS_TOGGLE = 'REPORT_STATUS_TOGGLE'; +const REPORT_COMMENT_CHANGE = 'REPORT_COMMENT_CHANGE'; +const REPORT_FORWARD_CHANGE = 'REPORT_FORWARD_CHANGE'; +const REPORT_BLOCK_CHANGE = 'REPORT_BLOCK_CHANGE'; + +const REPORT_RULE_CHANGE = 'REPORT_RULE_CHANGE'; + +const initReport = (account: Account, status: Status) => + (dispatch: AppDispatch) => { + dispatch({ + type: REPORT_INIT, + account, + status, + }); + + return dispatch(openModal('REPORT')); + }; + +const initReportById = (accountId: string) => + (dispatch: AppDispatch, getState: () => RootState) => { + dispatch({ + type: REPORT_INIT, + account: getState().accounts.get(accountId), + }); + + dispatch(openModal('REPORT')); + }; + +const cancelReport = () => ({ + type: REPORT_CANCEL, +}); + +const toggleStatusReport = (statusId: string, checked: boolean) => ({ + type: REPORT_STATUS_TOGGLE, + statusId, + checked, +}); + +const submitReport = () => + (dispatch: AppDispatch, getState: () => RootState) => { + dispatch(submitReportRequest()); + const { reports } = getState(); + + return api(getState).post('/api/v1/reports', { + account_id: reports.getIn(['new', 'account_id']), + status_ids: reports.getIn(['new', 'status_ids']), + rule_ids: reports.getIn(['new', 'rule_ids']), + comment: reports.getIn(['new', 'comment']), + forward: reports.getIn(['new', 'forward']), + }); + }; + +const submitReportRequest = () => ({ + type: REPORT_SUBMIT_REQUEST, +}); + +const submitReportSuccess = () => ({ + type: REPORT_SUBMIT_SUCCESS, +}); + +const submitReportFail = (error: AxiosError) => ({ + type: REPORT_SUBMIT_FAIL, + error, +}); + +const changeReportComment = (comment: string) => ({ + type: REPORT_COMMENT_CHANGE, + comment, +}); + +const changeReportForward = (forward: boolean) => ({ + type: REPORT_FORWARD_CHANGE, + forward, +}); + +const changeReportBlock = (block: boolean) => ({ + type: REPORT_BLOCK_CHANGE, + block, +}); + +const changeReportRule = (ruleId: string) => ({ + type: REPORT_RULE_CHANGE, + rule_id: ruleId, +}); + +export { + REPORT_INIT, + REPORT_CANCEL, + REPORT_SUBMIT_REQUEST, + REPORT_SUBMIT_SUCCESS, + REPORT_SUBMIT_FAIL, + REPORT_STATUS_TOGGLE, + REPORT_COMMENT_CHANGE, + REPORT_FORWARD_CHANGE, + REPORT_BLOCK_CHANGE, + REPORT_RULE_CHANGE, + initReport, + initReportById, + cancelReport, + toggleStatusReport, + submitReport, + submitReportRequest, + submitReportSuccess, + submitReportFail, + changeReportComment, + changeReportForward, + changeReportBlock, + changeReportRule, +}; \ No newline at end of file diff --git a/app/soapbox/features/status/index.tsx b/app/soapbox/features/status/index.tsx index 7d569190c..313bd3625 100644 --- a/app/soapbox/features/status/index.tsx +++ b/app/soapbox/features/status/index.tsx @@ -423,7 +423,7 @@ class Status extends ImmutablePureComponent { } handleReport = (status: StatusEntity) => { - this.props.dispatch(initReport(status.account, status)); + this.props.dispatch(initReport(status.account as AccountEntity, status)); } handleEmbed = (status: StatusEntity) => {