From 6f1c11b39f33d57e3fc4bce149f2107ac682574f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marcin=20miko=C5=82ajczak?= Date: Fri, 23 Aug 2024 01:21:30 +0200 Subject: [PATCH] cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: marcin mikołajczak --- package.json | 1 - src/actions/accounts.ts | 4 - src/actions/directory.ts | 9 ++ src/actions/importer/index.ts | 13 +-- src/actions/search.ts | 2 +- src/actions/soapbox.ts | 1 - src/actions/statuses.ts | 6 +- src/actions/timelines.ts | 25 ++--- src/api/hooks/accounts/useAccountList.ts | 10 +- src/components/media-gallery.tsx | 2 +- src/features/ui/components/modal-root.tsx | 2 - src/reducers/search.ts | 10 +- src/reducers/user-lists.ts | 11 +- src/stream.ts | 118 ---------------------- yarn.lock | 5 - 15 files changed, 36 insertions(+), 183 deletions(-) delete mode 100644 src/stream.ts diff --git a/package.json b/package.json index a744a7def..d9a116060 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,6 @@ "@fontsource/noto-sans-javanese": "^5.0.16", "@fontsource/roboto-mono": "^5.0.0", "@fontsource/tajawal": "^5.0.8", - "@gamestdio/websocket": "^0.3.2", "@lexical/clipboard": "^0.14.5", "@lexical/code": "^0.14.5", "@lexical/hashtag": "^0.14.5", diff --git a/src/actions/accounts.ts b/src/actions/accounts.ts index a7c52ac42..e3823f9d1 100644 --- a/src/actions/accounts.ts +++ b/src/actions/accounts.ts @@ -10,7 +10,6 @@ import { getClient, type PlfeResponse } from '../api'; import { importFetchedAccount, importFetchedAccounts, - importErrorWhileFetchingAccountByUsername, } from './importer'; import type { Map as ImmutableMap } from 'immutable'; @@ -168,7 +167,6 @@ const fetchAccountByUsername = (username: string, history?: History) => dispatch(fetchAccountSuccess(response)); }).catch(error => { dispatch(fetchAccountFail(null, error)); - dispatch(importErrorWhileFetchingAccountByUsername(username)); }); } else if (features.accountLookup) { return dispatch(accountLookup(username)).then(account => { @@ -176,7 +174,6 @@ const fetchAccountByUsername = (username: string, history?: History) => dispatch(fetchAccountSuccess(account)); }).catch(error => { dispatch(fetchAccountFail(null, error)); - dispatch(importErrorWhileFetchingAccountByUsername(username)); maybeRedirectLogin(error, history); }); } else { @@ -191,7 +188,6 @@ const fetchAccountByUsername = (username: string, history?: History) => } }).catch(error => { dispatch(fetchAccountFail(null, error)); - dispatch(importErrorWhileFetchingAccountByUsername(username)); }); } }; diff --git a/src/actions/directory.ts b/src/actions/directory.ts index b13287e1d..c02dcad74 100644 --- a/src/actions/directory.ts +++ b/src/actions/directory.ts @@ -66,6 +66,14 @@ const expandDirectoryFail = (error: unknown) => ({ error, }); +type DirectoryAction = + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType + | ReturnType; + export { DIRECTORY_FETCH_REQUEST, DIRECTORY_FETCH_SUCCESS, @@ -81,4 +89,5 @@ export { expandDirectoryRequest, expandDirectorySuccess, expandDirectoryFail, + type DirectoryAction, }; diff --git a/src/actions/importer/index.ts b/src/actions/importer/index.ts index 6988ec2e6..87301720b 100644 --- a/src/actions/importer/index.ts +++ b/src/actions/importer/index.ts @@ -1,9 +1,8 @@ -import { accountSchema, groupSchema, type Account as BaseAccount, type Group, type Poll, type Status as BaseStatus } from 'pl-api'; +import { type Account as BaseAccount, type Group, type Poll, type Status as BaseStatus } from 'pl-api'; import { importEntities } from 'soapbox/entity-store/actions'; import { Entities } from 'soapbox/entity-store/entities'; import { normalizeAccount, normalizeGroup } from 'soapbox/normalizers'; -import { filteredArray } from 'soapbox/schemas/utils'; import type { AppDispatch } from 'soapbox/store'; @@ -12,14 +11,13 @@ 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'; const importAccount = (data: BaseAccount) => importAccounts([data]); const importAccounts = (data: Array) => (dispatch: AppDispatch) => { dispatch({ type: ACCOUNTS_IMPORT, accounts: data }); try { - const accounts = filteredArray(accountSchema).parse(data).map(normalizeAccount); + const accounts = data.map(normalizeAccount); dispatch(importEntities(accounts, Entities.ACCOUNTS)); } catch (e) { // @@ -30,7 +28,7 @@ const importGroup = (data: Group) => importGroups([data]); const importGroups = (data: Array) => (dispatch: AppDispatch) => { try { - const groups = filteredArray(groupSchema).parse(data).map(normalizeGroup); + const groups = data.map(normalizeGroup); dispatch(importEntities(groups, Entities.GROUPS)); } catch (e) { // @@ -155,16 +153,12 @@ const importFetchedPoll = (poll: Poll) => dispatch(importPolls([poll])); }; -const importErrorWhileFetchingAccountByUsername = (username: string) => - ({ 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, importAccount, importAccounts, importGroup, @@ -177,5 +171,4 @@ export { importFetchedStatus, importFetchedStatuses, importFetchedPoll, - importErrorWhileFetchingAccountByUsername, }; diff --git a/src/actions/search.ts b/src/actions/search.ts index 6b457a924..eaa0ac532 100644 --- a/src/actions/search.ts +++ b/src/actions/search.ts @@ -130,7 +130,7 @@ const expandSearchRequest = (searchType: SearchFilter) => ({ searchType, }); -const expandSearchSuccess = (results: Search, searchTerm: string, searchType: SearchFilter) => ({ +const expandSearchSuccess = (results: Search, searchTerm: string, searchType: Exclude) => ({ type: SEARCH_EXPAND_SUCCESS, results, searchTerm, diff --git a/src/actions/soapbox.ts b/src/actions/soapbox.ts index 909f9af55..dca508505 100644 --- a/src/actions/soapbox.ts +++ b/src/actions/soapbox.ts @@ -22,7 +22,6 @@ const getSoapboxConfig = createSelector([ ], (soapbox, features) => { // Do some additional normalization with the state return normalizeSoapboxConfig(soapbox).withMutations(soapboxConfig => { - // If displayFqn isn't set, infer it from federation if (soapbox.get('displayFqn') === undefined) { soapboxConfig.set('displayFqn', features.federating); diff --git a/src/actions/statuses.ts b/src/actions/statuses.ts index 67e9718ee..7a46afc9d 100644 --- a/src/actions/statuses.ts +++ b/src/actions/statuses.ts @@ -162,11 +162,7 @@ const fetchContext = (statusId: string, intl?: IntlShape) => } : undefined; return getClient(getState()).statuses.getContext(statusId, params).then(context => { - if (Array.isArray(context)) { - // Mitra: returns a list of statuses - dispatch(importFetchedStatuses(context)); - } else if (typeof context === 'object') { - // Standard Mastodon API returns a map with `ancestors` and `descendants` + if (typeof context === 'object') { const { ancestors, descendants } = context; const statuses = ancestors.concat(descendants); dispatch(importFetchedStatuses(statuses)); diff --git a/src/actions/timelines.ts b/src/actions/timelines.ts index 1d14409f1..c58791b2f 100644 --- a/src/actions/timelines.ts +++ b/src/actions/timelines.ts @@ -25,7 +25,7 @@ const TIMELINE_INSERT = 'TIMELINE_INSERT' as const; const MAX_QUEUED_ITEMS = 40; -const processTimelineUpdate = (timeline: string, status: BaseStatus, accept: ((status: BaseStatus) => boolean) | null = null) => +const processTimelineUpdate = (timeline: string, status: BaseStatus) => (dispatch: AppDispatch, getState: () => RootState) => { const me = getState().me; const ownStatus = status.account?.id === me; @@ -48,26 +48,19 @@ const processTimelineUpdate = (timeline: string, status: BaseStatus, accept: ((s dispatch(importFetchedStatus(status)); if (shouldSkipQueue) { - dispatch(updateTimeline(timeline, status.id, accept)); + dispatch(updateTimeline(timeline, status.id)); } else { - dispatch(updateTimelineQueue(timeline, status.id, accept)); + dispatch(updateTimelineQueue(timeline, status.id)); } }; -const updateTimeline = (timeline: string, statusId: string, accept: ((status: BaseStatus) => boolean) | null) => - (dispatch: AppDispatch) => { - // if (typeof accept === 'function' && !accept(status)) { - // return; - // } +const updateTimeline = (timeline: string, statusId: string) => ({ + type: TIMELINE_UPDATE, + timeline, + statusId, +}); - dispatch({ - type: TIMELINE_UPDATE, - timeline, - statusId, - }); - }; - -const updateTimelineQueue = (timeline: string, statusId: string, accept: ((status: BaseStatus) => boolean) | null) => +const updateTimelineQueue = (timeline: string, statusId: string) => (dispatch: AppDispatch) => { // if (typeof accept === 'function' && !accept(status)) { // return; diff --git a/src/api/hooks/accounts/useAccountList.ts b/src/api/hooks/accounts/useAccountList.ts index b0825b1c1..d87eea410 100644 --- a/src/api/hooks/accounts/useAccountList.ts +++ b/src/api/hooks/accounts/useAccountList.ts @@ -1,5 +1,4 @@ import { useInfiniteQuery } from '@tanstack/react-query'; -import { PaginatedResponse, type Account as BaseAccount } from 'pl-api'; import { Entities } from 'soapbox/entity-store/entities'; import { useClient } from 'soapbox/hooks'; @@ -8,13 +7,10 @@ import { flattenPages } from 'soapbox/utils/queries'; import { useRelationships } from './useRelationships'; +import type { PaginatedResponse, Account as BaseAccount } from 'pl-api'; import type { EntityFn } from 'soapbox/entity-store/hooks/types'; -interface useAccountListOpts { - enabled?: boolean; -} - -const useAccountList = (listKey: string[], entityFn: EntityFn, opts: useAccountListOpts = {}) => { +const useAccountList = (listKey: string[], entityFn: EntityFn) => { const getAccounts = async (pageParam?: Pick, 'next'>) => { const response = await (pageParam?.next ? pageParam.next() : entityFn()) as PaginatedResponse; @@ -63,7 +59,6 @@ const useFollowing = (accountId: string | undefined) => { return useAccountList( [accountId!, 'following'], () => client.accounts.getAccountFollowing(accountId!), - { enabled: !!accountId }, ); }; @@ -73,7 +68,6 @@ const useFollowers = (accountId: string | undefined) => { return useAccountList( [accountId!, 'followers'], () => client.accounts.getAccountFollowers(accountId!), - { enabled: !!accountId }, ); }; diff --git a/src/components/media-gallery.tsx b/src/components/media-gallery.tsx index 3c124c17f..d98a79eb7 100644 --- a/src/components/media-gallery.tsx +++ b/src/components/media-gallery.tsx @@ -1,5 +1,4 @@ import clsx from 'clsx'; -import { MediaAttachment } from 'pl-api'; import React, { useState, useRef, useLayoutEffect } from 'react'; import Blurhash from 'soapbox/components/blurhash'; @@ -13,6 +12,7 @@ import { isIOS } from '../is-mobile'; import { isPanoramic, isPortrait, isNonConformingRatio, minimumAspectRatio, maximumAspectRatio } from '../utils/media-aspect-ratio'; import type { Property } from 'csstype'; +import type { MediaAttachment } from 'pl-api'; const ATTACHMENT_LIMIT = 4; const MAX_FILENAME_LENGTH = 45; diff --git a/src/features/ui/components/modal-root.tsx b/src/features/ui/components/modal-root.tsx index 410dc609c..718516a45 100644 --- a/src/features/ui/components/modal-root.tsx +++ b/src/features/ui/components/modal-root.tsx @@ -67,8 +67,6 @@ const ModalRoot: React.FC = () => { })); const onClickClose = (type?: ModalType) => { - if (!type) return; - switch (type) { case 'COMPOSE': dispatch(cancelReplyCompose()); diff --git a/src/reducers/search.ts b/src/reducers/search.ts index b599de771..4be626f6e 100644 --- a/src/reducers/search.ts +++ b/src/reducers/search.ts @@ -21,7 +21,6 @@ import { } from '../actions/search'; import type { Search, Tag } from 'pl-api'; -import type { APIEntity } from 'soapbox/types/entities'; const ResultsRecord = ImmutableRecord({ accounts: ImmutableOrderedSet(), @@ -48,10 +47,9 @@ const ReducerRecord = ImmutableRecord({ }); type State = ReturnType; -type APIEntities = Array; type SearchFilter = 'accounts' | 'statuses' | 'groups' | 'hashtags' | 'links'; -const toIds = (items: APIEntities = []) => ImmutableOrderedSet(items.map(item => item.id)); +const toIds = (items: Array<{ id: string }> = []) => ImmutableOrderedSet(items.map(item => item.id)); const importResults = (state: State, results: Search, searchTerm: string, searchType: SearchFilter) => state.withMutations(state => { @@ -75,7 +73,7 @@ const importResults = (state: State, results: Search, searchTerm: string, search } }); -const paginateResults = (state: State, searchType: SearchFilter, results: APIEntity, searchTerm: string) => +const paginateResults = (state: State, searchType: Exclude, results: Search, searchTerm: string) => state.withMutations(state => { if (state.submittedValue === searchTerm) { state.setIn(['results', `${searchType}HasMore`], results[searchType].length >= 20); @@ -84,9 +82,9 @@ const paginateResults = (state: State, searchType: SearchFilter, results: APIEnt const data = results[searchType]; // Hashtags are a list of maps. Others are IDs. if (searchType === 'hashtags') { - return (items as ImmutableOrderedSet).concat(data); + return (items as ImmutableOrderedSet).concat(data as Search['hashtags']); } else { - return (items as ImmutableOrderedSet).concat(toIds(data)); + return (items as ImmutableOrderedSet).concat(toIds(data as Search['accounts'])); } }); } diff --git a/src/reducers/user-lists.ts b/src/reducers/user-lists.ts index ffe197cf8..5885a336f 100644 --- a/src/reducers/user-lists.ts +++ b/src/reducers/user-lists.ts @@ -24,6 +24,7 @@ import { DIRECTORY_EXPAND_REQUEST, DIRECTORY_EXPAND_SUCCESS, DIRECTORY_EXPAND_FAIL, + DirectoryAction, } from 'soapbox/actions/directory'; import { EVENT_PARTICIPATIONS_EXPAND_SUCCESS, @@ -116,13 +117,13 @@ type Items = ImmutableOrderedSet; type NestedListPath = ['followers' | 'following' | 'reblogged_by' | 'favourited_by' | 'disliked_by' | 'reactions' | 'pinned' | 'birthday_reminders' | 'familiar_followers' | 'event_participations' | 'event_participation_requests' | 'membership_requests' | 'group_blocks', string]; type ListPath = ['follow_requests' | 'mutes' | 'directory']; -const normalizeList = (state: State, path: NestedListPath | ListPath, accounts: APIEntity[], next?: (() => any) | null) => +const normalizeList = (state: State, path: NestedListPath | ListPath, accounts: Array>, next?: (() => any) | null) => state.setIn(path, ListRecord({ next, items: ImmutableOrderedSet(accounts.map(item => item.id)), })); -const appendToList = (state: State, path: NestedListPath | ListPath, accounts: APIEntity[], next: (() => any) | null) => +const appendToList = (state: State, path: NestedListPath | ListPath, accounts: Array>, next: (() => any) | null) => state.updateIn(path, map => (map as List) .set('next', next) .set('isLoading', false) @@ -139,7 +140,7 @@ const normalizeFollowRequest = (state: State, notification: Notification) => ImmutableOrderedSet([notification.account.id]).union(list as Items), ); -const userLists = (state = ReducerRecord(), action: AnyAction) => { +const userLists = (state = ReducerRecord(), action: DirectoryAction | AnyAction) => { switch (action.type) { case FOLLOWERS_FETCH_SUCCESS: return normalizeList(state, ['followers', action.accountId], action.accounts, action.next); @@ -176,9 +177,9 @@ const userLists = (state = ReducerRecord(), action: AnyAction) => { case FOLLOW_REQUEST_REJECT_SUCCESS: return removeFromList(state, ['follow_requests'], action.accountId); case DIRECTORY_FETCH_SUCCESS: - return normalizeList(state, ['directory'], action.accounts, action.next); + return normalizeList(state, ['directory'], action.accounts); case DIRECTORY_EXPAND_SUCCESS: - return appendToList(state, ['directory'], action.accounts, action.next); + return appendToList(state, ['directory'], action.accounts, null); case DIRECTORY_FETCH_REQUEST: case DIRECTORY_EXPAND_REQUEST: return state.setIn(['directory', 'isLoading'], true); diff --git a/src/stream.ts b/src/stream.ts deleted file mode 100644 index b631a60da..000000000 --- a/src/stream.ts +++ /dev/null @@ -1,118 +0,0 @@ -import WebSocketClient from '@gamestdio/websocket'; - -import { getAccessToken } from 'soapbox/utils/auth'; - -import type { AppDispatch, RootState } from 'soapbox/store'; - -const randomIntUpTo = (max: number) => Math.floor(Math.random() * Math.floor(max)); - -interface ConnectStreamCallbacks { - onReceive(websocket: WebSocket, data: unknown): void; -} - -type PollingRefreshFn = (dispatch: AppDispatch, done?: () => void) => void - -const connectStream = ( - path: string, - pollingRefresh: PollingRefreshFn | null = null, - callbacks: (dispatch: AppDispatch, getState: () => RootState) => ConnectStreamCallbacks, -) => (dispatch: AppDispatch, getState: () => RootState) => { - const streamingAPIBaseURL = getState().instance.configuration.urls.streaming; - const accessToken = getAccessToken(getState()); - const { onReceive } = callbacks(dispatch, getState); - - let polling: NodeJS.Timeout | null = null; - - const setupPolling = () => { - if (pollingRefresh) { - pollingRefresh(dispatch, () => { - polling = setTimeout(() => setupPolling(), 20000 + randomIntUpTo(20000)); - }); - } - }; - - const clearPolling = () => { - if (polling) { - clearTimeout(polling); - polling = null; - } - }; - - let subscription: WebSocket; - - // If the WebSocket fails to be created, don't crash the whole page, - // just proceed without a subscription. - try { - subscription = getStream(streamingAPIBaseURL!, accessToken!, path, { - connected() { - if (pollingRefresh) { - clearPolling(); - } - }, - - disconnected() { - if (pollingRefresh) { - polling = setTimeout(() => setupPolling(), randomIntUpTo(40000)); - } - }, - - received(data) { - onReceive(subscription, data); - }, - - reconnected() { - if (pollingRefresh) { - clearPolling(); - pollingRefresh(dispatch); - } - }, - - }); - } catch (e) { - console.error(e); - } - - const disconnect = () => { - if (subscription) { - subscription.close(); - } - - clearPolling(); - }; - - return disconnect; -}; - -const getStream = ( - streamingAPIBaseURL: string, - accessToken: string, - stream: string, - { connected, received, disconnected, reconnected }: { - connected: ((this: WebSocket, ev: Event) => any) | null; - received: (data: any) => void; - disconnected: ((this: WebSocket, ev: Event) => any) | null; - reconnected: ((this: WebSocket, ev: Event) => any); - }, -) => { - const params = [ `access_token=${accessToken}`, `stream=${stream}` ]; - - const ws = new WebSocketClient(`${streamingAPIBaseURL}/api/v1/streaming/?${params.join('&')}`, accessToken as any); - - ws.onopen = connected; - ws.onclose = disconnected; - ws.onreconnect = reconnected; - - ws.onmessage = (e) => { - if (!e.data) return; - try { - received(JSON.parse(e.data)); - } catch (error) { - console.error(e); - console.error(`Could not parse the above streaming event.\n${error}`); - } - }; - - return ws; -}; - -export { connectStream }; diff --git a/yarn.lock b/yarn.lock index 04f967d12..eb08f253b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1617,11 +1617,6 @@ tslib "^2.4.0" typescript "^4.7 || 5" -"@gamestdio/websocket@^0.3.2": - version "0.3.2" - resolved "https://registry.yarnpkg.com/@gamestdio/websocket/-/websocket-0.3.2.tgz#321ba0976ee30fd14e51dbf8faa85ce7b325f76a" - integrity sha512-J3n5SKim+ZoLbe44hRGI/VYAwSMCeIJuBy+FfP6EZaujEpNchPRFcIsVQLWAwpU1bP2Ji63rC+rEUOd1vjUB6Q== - "@gitbeaker/core@^35.8.0": version "35.8.0" resolved "https://registry.yarnpkg.com/@gitbeaker/core/-/core-35.8.0.tgz#8e55950dd6c45e6b48791432a1fa2c13b9460d39"