diff --git a/app/soapbox/actions/chats.js b/app/soapbox/actions/chats.ts similarity index 54% rename from app/soapbox/actions/chats.js rename to app/soapbox/actions/chats.ts index 0a8d1d75c..67b796408 100644 --- a/app/soapbox/actions/chats.js +++ b/app/soapbox/actions/chats.ts @@ -1,4 +1,4 @@ -import { Map as ImmutableMap } from 'immutable'; +import { List as ImmutableList, Map as ImmutableMap } from 'immutable'; import { v4 as uuidv4 } from 'uuid'; import { getSettings, changeSetting } from 'soapbox/actions/settings'; @@ -6,47 +6,49 @@ import { getFeatures } from 'soapbox/utils/features'; import api, { getLinks } from '../api'; -export const CHATS_FETCH_REQUEST = 'CHATS_FETCH_REQUEST'; -export const CHATS_FETCH_SUCCESS = 'CHATS_FETCH_SUCCESS'; -export const CHATS_FETCH_FAIL = 'CHATS_FETCH_FAIL'; +import type { History } from 'history'; +import type { AppDispatch, RootState } from 'soapbox/store'; -export const CHATS_EXPAND_REQUEST = 'CHATS_EXPAND_REQUEST'; -export const CHATS_EXPAND_SUCCESS = 'CHATS_EXPAND_SUCCESS'; -export const CHATS_EXPAND_FAIL = 'CHATS_EXPAND_FAIL'; +const CHATS_FETCH_REQUEST = 'CHATS_FETCH_REQUEST'; +const CHATS_FETCH_SUCCESS = 'CHATS_FETCH_SUCCESS'; +const CHATS_FETCH_FAIL = 'CHATS_FETCH_FAIL'; -export const CHAT_MESSAGES_FETCH_REQUEST = 'CHAT_MESSAGES_FETCH_REQUEST'; -export const CHAT_MESSAGES_FETCH_SUCCESS = 'CHAT_MESSAGES_FETCH_SUCCESS'; -export const CHAT_MESSAGES_FETCH_FAIL = 'CHAT_MESSAGES_FETCH_FAIL'; +const CHATS_EXPAND_REQUEST = 'CHATS_EXPAND_REQUEST'; +const CHATS_EXPAND_SUCCESS = 'CHATS_EXPAND_SUCCESS'; +const CHATS_EXPAND_FAIL = 'CHATS_EXPAND_FAIL'; -export const CHAT_MESSAGE_SEND_REQUEST = 'CHAT_MESSAGE_SEND_REQUEST'; -export const CHAT_MESSAGE_SEND_SUCCESS = 'CHAT_MESSAGE_SEND_SUCCESS'; -export const CHAT_MESSAGE_SEND_FAIL = 'CHAT_MESSAGE_SEND_FAIL'; +const CHAT_MESSAGES_FETCH_REQUEST = 'CHAT_MESSAGES_FETCH_REQUEST'; +const CHAT_MESSAGES_FETCH_SUCCESS = 'CHAT_MESSAGES_FETCH_SUCCESS'; +const CHAT_MESSAGES_FETCH_FAIL = 'CHAT_MESSAGES_FETCH_FAIL'; -export const CHAT_FETCH_REQUEST = 'CHAT_FETCH_REQUEST'; -export const CHAT_FETCH_SUCCESS = 'CHAT_FETCH_SUCCESS'; -export const CHAT_FETCH_FAIL = 'CHAT_FETCH_FAIL'; +const CHAT_MESSAGE_SEND_REQUEST = 'CHAT_MESSAGE_SEND_REQUEST'; +const CHAT_MESSAGE_SEND_SUCCESS = 'CHAT_MESSAGE_SEND_SUCCESS'; +const CHAT_MESSAGE_SEND_FAIL = 'CHAT_MESSAGE_SEND_FAIL'; -export const CHAT_READ_REQUEST = 'CHAT_READ_REQUEST'; -export const CHAT_READ_SUCCESS = 'CHAT_READ_SUCCESS'; -export const CHAT_READ_FAIL = 'CHAT_READ_FAIL'; +const CHAT_FETCH_REQUEST = 'CHAT_FETCH_REQUEST'; +const CHAT_FETCH_SUCCESS = 'CHAT_FETCH_SUCCESS'; +const CHAT_FETCH_FAIL = 'CHAT_FETCH_FAIL'; -export const CHAT_MESSAGE_DELETE_REQUEST = 'CHAT_MESSAGE_DELETE_REQUEST'; -export const CHAT_MESSAGE_DELETE_SUCCESS = 'CHAT_MESSAGE_DELETE_SUCCESS'; -export const CHAT_MESSAGE_DELETE_FAIL = 'CHAT_MESSAGE_DELETE_FAIL'; +const CHAT_READ_REQUEST = 'CHAT_READ_REQUEST'; +const CHAT_READ_SUCCESS = 'CHAT_READ_SUCCESS'; +const CHAT_READ_FAIL = 'CHAT_READ_FAIL'; -export function fetchChatsV1() { - return (dispatch, getState) => +const CHAT_MESSAGE_DELETE_REQUEST = 'CHAT_MESSAGE_DELETE_REQUEST'; +const CHAT_MESSAGE_DELETE_SUCCESS = 'CHAT_MESSAGE_DELETE_SUCCESS'; +const CHAT_MESSAGE_DELETE_FAIL = 'CHAT_MESSAGE_DELETE_FAIL'; + +const fetchChatsV1 = () => + (dispatch: AppDispatch, getState: () => RootState) => api(getState).get('/api/v1/pleroma/chats').then((response) => { dispatch({ type: CHATS_FETCH_SUCCESS, chats: response.data }); }).catch(error => { dispatch({ type: CHATS_FETCH_FAIL, error }); }); -} -export function fetchChatsV2() { - return (dispatch, getState) => +const fetchChatsV2 = () => + (dispatch: AppDispatch, getState: () => RootState) => api(getState).get('/api/v2/pleroma/chats').then((response) => { - let next = getLinks(response).refs.find(link => link.rel === 'next'); + let next: { uri: string } | undefined = getLinks(response).refs.find(link => link.rel === 'next'); if (!next && response.data.length) { next = { uri: `/api/v2/pleroma/chats?max_id=${response.data[response.data.length - 1].id}&offset=0` }; @@ -56,10 +58,9 @@ export function fetchChatsV2() { }).catch(error => { dispatch({ type: CHATS_FETCH_FAIL, error }); }); -} -export function fetchChats() { - return (dispatch, getState) => { +const fetchChats = () => + (dispatch: AppDispatch, getState: () => RootState) => { const state = getState(); const { instance } = state; const features = getFeatures(instance); @@ -71,11 +72,10 @@ export function fetchChats() { return dispatch(fetchChatsV1()); } }; -} -export function expandChats() { - return (dispatch, getState) => { - const url = getState().getIn(['chats', 'next']); +const expandChats = () => + (dispatch: AppDispatch, getState: () => RootState) => { + const url = getState().chats.next; if (url === null) { return; @@ -90,10 +90,9 @@ export function expandChats() { dispatch({ type: CHATS_EXPAND_FAIL, error }); }); }; -} -export function fetchChatMessages(chatId, maxId = null) { - return (dispatch, getState) => { +const fetchChatMessages = (chatId: string, maxId: string | null = null) => + (dispatch: AppDispatch, getState: () => RootState) => { dispatch({ type: CHAT_MESSAGES_FETCH_REQUEST, chatId, maxId }); return api(getState).get(`/api/v1/pleroma/chats/${chatId}/messages`, { params: { max_id: maxId } }).then(({ data }) => { dispatch({ type: CHAT_MESSAGES_FETCH_SUCCESS, chatId, maxId, chatMessages: data }); @@ -101,12 +100,11 @@ export function fetchChatMessages(chatId, maxId = null) { dispatch({ type: CHAT_MESSAGES_FETCH_FAIL, chatId, maxId, error }); }); }; -} -export function sendChatMessage(chatId, params) { - return (dispatch, getState) => { +const sendChatMessage = (chatId: string, params: Record) => + (dispatch: AppDispatch, getState: () => RootState) => { const uuid = `末_${Date.now()}_${uuidv4()}`; - const me = getState().get('me'); + const me = getState().me; dispatch({ type: CHAT_MESSAGE_SEND_REQUEST, chatId, params, uuid, me }); return api(getState).post(`/api/v1/pleroma/chats/${chatId}/messages`, params).then(({ data }) => { dispatch({ type: CHAT_MESSAGE_SEND_SUCCESS, chatId, chatMessage: data, uuid }); @@ -114,28 +112,26 @@ export function sendChatMessage(chatId, params) { dispatch({ type: CHAT_MESSAGE_SEND_FAIL, chatId, error, uuid }); }); }; -} -export function openChat(chatId) { - return (dispatch, getState) => { +const openChat = (chatId: string) => + (dispatch: AppDispatch, getState: () => RootState) => { const state = getState(); - const panes = getSettings(state).getIn(['chats', 'panes']); + const panes = getSettings(state).getIn(['chats', 'panes']) as ImmutableList>; const idx = panes.findIndex(pane => pane.get('chat_id') === chatId); dispatch(markChatRead(chatId)); if (idx > -1) { - return dispatch(changeSetting(['chats', 'panes', idx, 'state'], 'open')); + return dispatch(changeSetting(['chats', 'panes', idx as any, 'state'], 'open')); } else { const newPane = ImmutableMap({ chat_id: chatId, state: 'open' }); return dispatch(changeSetting(['chats', 'panes'], panes.push(newPane))); } }; -} -export function closeChat(chatId) { - return (dispatch, getState) => { - const panes = getSettings(getState()).getIn(['chats', 'panes']); +const closeChat = (chatId: string) => + (dispatch: AppDispatch, getState: () => RootState) => { + const panes = getSettings(getState()).getIn(['chats', 'panes']) as ImmutableList>; const idx = panes.findIndex(pane => pane.get('chat_id') === chatId); if (idx > -1) { @@ -144,33 +140,30 @@ export function closeChat(chatId) { return false; } }; -} -export function toggleChat(chatId) { - return (dispatch, getState) => { - const panes = getSettings(getState()).getIn(['chats', 'panes']); - const [idx, pane] = panes.findEntry(pane => pane.get('chat_id') === chatId); +const toggleChat = (chatId: string) => + (dispatch: AppDispatch, getState: () => RootState) => { + const panes = getSettings(getState()).getIn(['chats', 'panes']) as ImmutableList>; + const [idx, pane] = panes.findEntry(pane => pane.get('chat_id') === chatId)!; if (idx > -1) { const state = pane.get('state') === 'minimized' ? 'open' : 'minimized'; if (state === 'open') dispatch(markChatRead(chatId)); - return dispatch(changeSetting(['chats', 'panes', idx, 'state'], state)); + return dispatch(changeSetting(['chats', 'panes', idx as any, 'state'], state)); } else { return false; } }; -} -export function toggleMainWindow() { - return (dispatch, getState) => { - const main = getSettings(getState()).getIn(['chats', 'mainWindow']); +const toggleMainWindow = () => + (dispatch: AppDispatch, getState: () => RootState) => { + const main = getSettings(getState()).getIn(['chats', 'mainWindow']) as 'minimized' | 'open'; const state = main === 'minimized' ? 'open' : 'minimized'; return dispatch(changeSetting(['chats', 'mainWindow'], state)); }; -} -export function fetchChat(chatId) { - return (dispatch, getState) => { +const fetchChat = (chatId: string) => + (dispatch: AppDispatch, getState: () => RootState) => { dispatch({ type: CHAT_FETCH_REQUEST, chatId }); return api(getState).get(`/api/v1/pleroma/chats/${chatId}`).then(({ data }) => { dispatch({ type: CHAT_FETCH_SUCCESS, chat: data }); @@ -178,10 +171,9 @@ export function fetchChat(chatId) { dispatch({ type: CHAT_FETCH_FAIL, chatId, error }); }); }; -} -export function startChat(accountId) { - return (dispatch, getState) => { +const startChat = (accountId: string) => + (dispatch: AppDispatch, getState: () => RootState) => { dispatch({ type: CHAT_FETCH_REQUEST, accountId }); return api(getState).post(`/api/v1/pleroma/chats/by-account-id/${accountId}`).then(({ data }) => { dispatch({ type: CHAT_FETCH_SUCCESS, chat: data }); @@ -190,12 +182,11 @@ export function startChat(accountId) { dispatch({ type: CHAT_FETCH_FAIL, accountId, error }); }); }; -} -export function markChatRead(chatId, lastReadId) { - return (dispatch, getState) => { - const chat = getState().getIn(['chats', 'items', chatId]); - if (!lastReadId) lastReadId = chat.get('last_message'); +const markChatRead = (chatId: string, lastReadId?: string | null) => + (dispatch: AppDispatch, getState: () => RootState) => { + const chat = getState().chats.items.get(chatId)!; + if (!lastReadId) lastReadId = chat.last_message; if (chat.get('unread') < 1) return; if (!lastReadId) return; @@ -207,10 +198,9 @@ export function markChatRead(chatId, lastReadId) { dispatch({ type: CHAT_READ_FAIL, chatId, error, lastReadId }); }); }; -} -export function deleteChatMessage(chatId, messageId) { - return (dispatch, getState) => { +const deleteChatMessage = (chatId: string, messageId: string) => + (dispatch: AppDispatch, getState: () => RootState) => { dispatch({ type: CHAT_MESSAGE_DELETE_REQUEST, chatId, messageId }); api(getState).delete(`/api/v1/pleroma/chats/${chatId}/messages/${messageId}`).then(({ data }) => { dispatch({ type: CHAT_MESSAGE_DELETE_SUCCESS, chatId, messageId, chatMessage: data }); @@ -218,13 +208,12 @@ export function deleteChatMessage(chatId, messageId) { dispatch({ type: CHAT_MESSAGE_DELETE_FAIL, chatId, messageId, error }); }); }; -} /** Start a chat and launch it in the UI */ -export function launchChat(accountId, router, forceNavigate = false) { - const isMobile = width => width <= 1190; +const launchChat = (accountId: string, router: History, forceNavigate = false) => { + const isMobile = (width: number) => width <= 1190; - return (dispatch, getState) => { + return (dispatch: AppDispatch) => { // TODO: make this faster return dispatch(startChat(accountId)).then(chat => { if (forceNavigate || isMobile(window.innerWidth)) { @@ -234,4 +223,43 @@ export function launchChat(accountId, router, forceNavigate = false) { } }); }; -} +}; + +export { + CHATS_FETCH_REQUEST, + CHATS_FETCH_SUCCESS, + CHATS_FETCH_FAIL, + CHATS_EXPAND_REQUEST, + CHATS_EXPAND_SUCCESS, + CHATS_EXPAND_FAIL, + CHAT_MESSAGES_FETCH_REQUEST, + CHAT_MESSAGES_FETCH_SUCCESS, + CHAT_MESSAGES_FETCH_FAIL, + CHAT_MESSAGE_SEND_REQUEST, + CHAT_MESSAGE_SEND_SUCCESS, + CHAT_MESSAGE_SEND_FAIL, + CHAT_FETCH_REQUEST, + CHAT_FETCH_SUCCESS, + CHAT_FETCH_FAIL, + CHAT_READ_REQUEST, + CHAT_READ_SUCCESS, + CHAT_READ_FAIL, + CHAT_MESSAGE_DELETE_REQUEST, + CHAT_MESSAGE_DELETE_SUCCESS, + CHAT_MESSAGE_DELETE_FAIL, + fetchChatsV1, + fetchChatsV2, + fetchChats, + expandChats, + fetchChatMessages, + sendChatMessage, + openChat, + closeChat, + toggleChat, + toggleMainWindow, + fetchChat, + startChat, + markChatRead, + deleteChatMessage, + launchChat, +}; diff --git a/app/soapbox/actions/importer/index.js b/app/soapbox/actions/importer/index.ts similarity index 62% rename from app/soapbox/actions/importer/index.js rename to app/soapbox/actions/importer/index.ts index cb4305901..87c6cca85 100644 --- a/app/soapbox/actions/importer/index.js +++ b/app/soapbox/actions/importer/index.ts @@ -1,46 +1,49 @@ import { getSettings } from '../settings'; -export const ACCOUNT_IMPORT = 'ACCOUNT_IMPORT'; -export const ACCOUNTS_IMPORT = 'ACCOUNTS_IMPORT'; -export const STATUS_IMPORT = 'STATUS_IMPORT'; -export const STATUSES_IMPORT = 'STATUSES_IMPORT'; -export const POLLS_IMPORT = 'POLLS_IMPORT'; -export const ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP = 'ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP'; +import type { AppDispatch, RootState } from 'soapbox/store'; +import type { APIEntity } from 'soapbox/types/entities'; -export function importAccount(account) { +const ACCOUNT_IMPORT = 'ACCOUNT_IMPORT'; +const ACCOUNTS_IMPORT = 'ACCOUNTS_IMPORT'; +const STATUS_IMPORT = 'STATUS_IMPORT'; +const STATUSES_IMPORT = 'STATUSES_IMPORT'; +const POLLS_IMPORT = 'POLLS_IMPORT'; +const ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP = 'ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP'; + +export function importAccount(account: APIEntity) { return { type: ACCOUNT_IMPORT, account }; } -export function importAccounts(accounts) { +export function importAccounts(accounts: APIEntity[]) { return { type: ACCOUNTS_IMPORT, accounts }; } -export function importStatus(status, idempotencyKey) { - return (dispatch, getState) => { +export function importStatus(status: APIEntity, idempotencyKey?: string) { + return (dispatch: AppDispatch, getState: () => RootState) => { const expandSpoilers = getSettings(getState()).get('expandSpoilers'); return dispatch({ type: STATUS_IMPORT, status, idempotencyKey, expandSpoilers }); }; } -export function importStatuses(statuses) { - return (dispatch, getState) => { +export function importStatuses(statuses: APIEntity[]) { + return (dispatch: AppDispatch, getState: () => RootState) => { const expandSpoilers = getSettings(getState()).get('expandSpoilers'); return dispatch({ type: STATUSES_IMPORT, statuses, expandSpoilers }); }; } -export function importPolls(polls) { +export function importPolls(polls: APIEntity[]) { return { type: POLLS_IMPORT, polls }; } -export function importFetchedAccount(account) { +export function importFetchedAccount(account: APIEntity) { return importFetchedAccounts([account]); } -export function importFetchedAccounts(accounts) { - const normalAccounts = []; +export function importFetchedAccounts(accounts: APIEntity[]) { + const normalAccounts: APIEntity[] = []; - function processAccount(account) { + const processAccount = (account: APIEntity) => { if (!account.id) return; normalAccounts.push(account); @@ -48,15 +51,15 @@ export function importFetchedAccounts(accounts) { if (account.moved) { processAccount(account.moved); } - } + }; accounts.forEach(processAccount); return importAccounts(normalAccounts); } -export function importFetchedStatus(status, idempotencyKey) { - return (dispatch, getState) => { +export function importFetchedStatus(status: APIEntity, idempotencyKey?: string) { + return (dispatch: AppDispatch) => { // Skip broken statuses if (isBroken(status)) return; @@ -95,7 +98,7 @@ export function importFetchedStatus(status, idempotencyKey) { // Sometimes Pleroma can return an empty account, // or a repost can appear of a deleted account. Skip these statuses. -const isBroken = status => { +const isBroken = (status: APIEntity) => { try { // Skip empty accounts // https://gitlab.com/soapbox-pub/soapbox-fe/-/issues/424 @@ -109,13 +112,13 @@ const isBroken = status => { } }; -export function importFetchedStatuses(statuses) { - return (dispatch, getState) => { - const accounts = []; - const normalStatuses = []; - const polls = []; +export function importFetchedStatuses(statuses: APIEntity[]) { + return (dispatch: AppDispatch, getState: () => RootState) => { + const accounts: APIEntity[] = []; + const normalStatuses: APIEntity[] = []; + const polls: APIEntity[] = []; - function processStatus(status) { + function processStatus(status: APIEntity) { // Skip broken statuses if (isBroken(status)) return; @@ -148,12 +151,21 @@ export function importFetchedStatuses(statuses) { }; } -export function importFetchedPoll(poll) { - return dispatch => { +export function importFetchedPoll(poll: APIEntity) { + return (dispatch: AppDispatch) => { dispatch(importPolls([poll])); }; } -export function importErrorWhileFetchingAccountByUsername(username) { +export function importErrorWhileFetchingAccountByUsername(username: string) { return { type: ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP, username }; } + +export { + ACCOUNT_IMPORT, + ACCOUNTS_IMPORT, + STATUS_IMPORT, + STATUSES_IMPORT, + POLLS_IMPORT, + ACCOUNT_FETCH_FAIL_FOR_USERNAME_LOOKUP, +};