prefer arrow functions
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
@ -10,16 +10,16 @@ import { getFetch } from '../api';
|
||||
|
||||
import type { AnyAction } from 'redux';
|
||||
|
||||
export const APP_CREATE_REQUEST = 'APP_CREATE_REQUEST';
|
||||
export const APP_CREATE_SUCCESS = 'APP_CREATE_SUCCESS';
|
||||
export const APP_CREATE_FAIL = 'APP_CREATE_FAIL';
|
||||
const APP_CREATE_REQUEST = 'APP_CREATE_REQUEST';
|
||||
const APP_CREATE_SUCCESS = 'APP_CREATE_SUCCESS';
|
||||
const APP_CREATE_FAIL = 'APP_CREATE_FAIL';
|
||||
|
||||
export const APP_VERIFY_CREDENTIALS_REQUEST = 'APP_VERIFY_CREDENTIALS_REQUEST';
|
||||
export const APP_VERIFY_CREDENTIALS_SUCCESS = 'APP_VERIFY_CREDENTIALS_SUCCESS';
|
||||
export const APP_VERIFY_CREDENTIALS_FAIL = 'APP_VERIFY_CREDENTIALS_FAIL';
|
||||
const APP_VERIFY_CREDENTIALS_REQUEST = 'APP_VERIFY_CREDENTIALS_REQUEST';
|
||||
const APP_VERIFY_CREDENTIALS_SUCCESS = 'APP_VERIFY_CREDENTIALS_SUCCESS';
|
||||
const APP_VERIFY_CREDENTIALS_FAIL = 'APP_VERIFY_CREDENTIALS_FAIL';
|
||||
|
||||
export function createApp(params?: Record<string, string>, baseURL?: string) {
|
||||
return (dispatch: React.Dispatch<AnyAction>) => {
|
||||
const createApp = (params?: Record<string, string>, baseURL?: string) =>
|
||||
(dispatch: React.Dispatch<AnyAction>) => {
|
||||
dispatch({ type: APP_CREATE_REQUEST, params });
|
||||
|
||||
return getFetch(null, baseURL)('/api/v1/apps', { method: 'POST', body: JSON.stringify(params) }).then(({ json: app }) => {
|
||||
@ -30,10 +30,9 @@ export function createApp(params?: Record<string, string>, baseURL?: string) {
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function verifyAppCredentials(token: string) {
|
||||
return (dispatch: React.Dispatch<AnyAction>) => {
|
||||
const verifyAppCredentials = (token: string) =>
|
||||
(dispatch: React.Dispatch<AnyAction>) => {
|
||||
dispatch({ type: APP_VERIFY_CREDENTIALS_REQUEST, token });
|
||||
return getFetch(token)('/api/v1/apps/verify_credentials').then(({ json: app }) => {
|
||||
dispatch({ type: APP_VERIFY_CREDENTIALS_SUCCESS, token, app });
|
||||
@ -43,4 +42,14 @@ export function verifyAppCredentials(token: string) {
|
||||
throw error;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export {
|
||||
APP_CREATE_REQUEST,
|
||||
APP_CREATE_SUCCESS,
|
||||
APP_CREATE_FAIL,
|
||||
APP_VERIFY_CREDENTIALS_REQUEST,
|
||||
APP_VERIFY_CREDENTIALS_SUCCESS,
|
||||
APP_VERIFY_CREDENTIALS_FAIL,
|
||||
createApp,
|
||||
verifyAppCredentials,
|
||||
};
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
import * as BuildConfig from 'soapbox/build-config';
|
||||
|
||||
/** Require a custom JSON file if it exists */
|
||||
export const custom = (filename: string, fallback: any = {}): any => {
|
||||
const custom = (filename: string, fallback: any = {}): any => {
|
||||
if (BuildConfig.NODE_ENV === 'test') return fallback;
|
||||
|
||||
const modules = import.meta.glob('../custom/*.json', { eager: true });
|
||||
@ -12,3 +12,5 @@ export const custom = (filename: string, fallback: any = {}): any => {
|
||||
|
||||
return modules[key] ? modules[key] : fallback;
|
||||
};
|
||||
|
||||
export { custom };
|
||||
|
||||
@ -2,16 +2,14 @@
|
||||
const LAYOUT_BREAKPOINT = 630;
|
||||
|
||||
/** Check if the width is small enough to be considered "mobile". */
|
||||
export function isMobile(width: number) {
|
||||
return width <= LAYOUT_BREAKPOINT;
|
||||
}
|
||||
const isMobile = (width: number) => width <= LAYOUT_BREAKPOINT;
|
||||
|
||||
/** Whether the device is iOS (best guess). */
|
||||
const iOS: boolean = /iPad|iPhone|iPod/.test(navigator.userAgent) && !(window as any).MSStream;
|
||||
|
||||
export const userTouching = window.matchMedia('(pointer: coarse)');
|
||||
const userTouching = window.matchMedia('(pointer: coarse)');
|
||||
|
||||
/** Whether the device is iOS (best guess). */
|
||||
export function isIOS(): boolean {
|
||||
return iOS;
|
||||
}
|
||||
const isIOS = (): boolean => iOS;
|
||||
|
||||
export { isMobile, userTouching, isIOS };
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
export default function ready(loaded: () => void): void {
|
||||
const ready = (loaded: () => void): void => {
|
||||
if (['interactive', 'complete'].includes(document.readyState)) {
|
||||
loaded();
|
||||
} else {
|
||||
document.addEventListener('DOMContentLoaded', loaded);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default ready;
|
||||
15
src/store.ts
15
src/store.ts
@ -7,7 +7,7 @@ import appReducer from './reducers';
|
||||
|
||||
import type { AnyAction } from 'redux';
|
||||
|
||||
export const store = configureStore({
|
||||
const store = configureStore({
|
||||
reducer: appReducer,
|
||||
middleware: () => new Tuple(
|
||||
thunk,
|
||||
@ -17,9 +17,16 @@ export const store = configureStore({
|
||||
devTools: true,
|
||||
});
|
||||
|
||||
export type Store = typeof store;
|
||||
type Store = typeof store;
|
||||
|
||||
// Infer the `RootState` and `AppDispatch` types from the store itself
|
||||
// https://redux.js.org/usage/usage-with-typescript
|
||||
export type RootState = ReturnType<typeof store.getState>;
|
||||
export type AppDispatch = ThunkDispatch<RootState, {}, AnyAction>;
|
||||
type RootState = ReturnType<typeof store.getState>;
|
||||
type AppDispatch = ThunkDispatch<RootState, {}, AnyAction>;
|
||||
|
||||
export {
|
||||
store,
|
||||
type Store,
|
||||
type RootState,
|
||||
type AppDispatch,
|
||||
};
|
||||
|
||||
147
src/stream.ts
147
src/stream.ts
@ -14,86 +14,84 @@ interface ConnectStreamCallbacks {
|
||||
|
||||
type PollingRefreshFn = (dispatch: AppDispatch, done?: () => void) => void
|
||||
|
||||
export function connectStream(
|
||||
const connectStream = (
|
||||
path: string,
|
||||
pollingRefresh: PollingRefreshFn | null = null,
|
||||
callbacks: (dispatch: AppDispatch, getState: () => RootState) => ConnectStreamCallbacks,
|
||||
) {
|
||||
return (dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const streamingAPIBaseURL = getState().instance.configuration.urls.streaming;
|
||||
const accessToken = getAccessToken(getState());
|
||||
const { onConnect, onDisconnect, onReceive } = callbacks(dispatch, getState);
|
||||
) => (dispatch: AppDispatch, getState: () => RootState) => {
|
||||
const streamingAPIBaseURL = getState().instance.configuration.urls.streaming;
|
||||
const accessToken = getAccessToken(getState());
|
||||
const { onConnect, onDisconnect, 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();
|
||||
}
|
||||
|
||||
onConnect();
|
||||
},
|
||||
|
||||
disconnected() {
|
||||
if (pollingRefresh) {
|
||||
polling = setTimeout(() => setupPolling(), randomIntUpTo(40000));
|
||||
}
|
||||
|
||||
onDisconnect();
|
||||
},
|
||||
|
||||
received(data) {
|
||||
onReceive(subscription, data);
|
||||
},
|
||||
|
||||
reconnected() {
|
||||
if (pollingRefresh) {
|
||||
clearPolling();
|
||||
pollingRefresh(dispatch);
|
||||
}
|
||||
|
||||
onConnect();
|
||||
},
|
||||
let polling: NodeJS.Timeout | null = null;
|
||||
|
||||
const setupPolling = () => {
|
||||
if (pollingRefresh) {
|
||||
pollingRefresh(dispatch, () => {
|
||||
polling = setTimeout(() => setupPolling(), 20000 + randomIntUpTo(20000));
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
onConnect();
|
||||
},
|
||||
|
||||
disconnected() {
|
||||
if (pollingRefresh) {
|
||||
polling = setTimeout(() => setupPolling(), randomIntUpTo(40000));
|
||||
}
|
||||
|
||||
onDisconnect();
|
||||
},
|
||||
|
||||
received(data) {
|
||||
onReceive(subscription, data);
|
||||
},
|
||||
|
||||
reconnected() {
|
||||
if (pollingRefresh) {
|
||||
clearPolling();
|
||||
pollingRefresh(dispatch);
|
||||
}
|
||||
|
||||
onConnect();
|
||||
},
|
||||
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
|
||||
const disconnect = () => {
|
||||
if (subscription) {
|
||||
subscription.close();
|
||||
}
|
||||
|
||||
const disconnect = () => {
|
||||
if (subscription) {
|
||||
subscription.close();
|
||||
}
|
||||
|
||||
clearPolling();
|
||||
};
|
||||
|
||||
return disconnect;
|
||||
clearPolling();
|
||||
};
|
||||
}
|
||||
|
||||
export default function getStream(
|
||||
return disconnect;
|
||||
};
|
||||
|
||||
const getStream = (
|
||||
streamingAPIBaseURL: string,
|
||||
accessToken: string,
|
||||
stream: string,
|
||||
@ -103,7 +101,7 @@ export default function getStream(
|
||||
disconnected: ((this: WebSocket, ev: Event) => any) | null;
|
||||
reconnected: ((this: WebSocket, ev: Event) => any);
|
||||
},
|
||||
) {
|
||||
) => {
|
||||
const params = [ `stream=${stream}` ];
|
||||
|
||||
const ws = new WebSocketClient(`${streamingAPIBaseURL}/api/v1/streaming/?${params.join('&')}`, accessToken as any);
|
||||
@ -123,4 +121,9 @@ export default function getStream(
|
||||
};
|
||||
|
||||
return ws;
|
||||
}
|
||||
};
|
||||
|
||||
export {
|
||||
connectStream,
|
||||
getStream as default,
|
||||
};
|
||||
|
||||
@ -26,23 +26,20 @@ const createToast = (type: ToastType, message: ToastText, opts?: IToastOptions)
|
||||
});
|
||||
};
|
||||
|
||||
function info(message: ToastText, opts?: IToastOptions) {
|
||||
const info = (message: ToastText, opts?: IToastOptions) =>
|
||||
createToast('info', message, opts);
|
||||
}
|
||||
|
||||
function success(message: ToastText, opts?: IToastOptions) {
|
||||
const success = (message: ToastText, opts?: IToastOptions) =>
|
||||
createToast('success', message, opts);
|
||||
}
|
||||
|
||||
function error(message: ToastText, opts?: IToastOptions) {
|
||||
const error = (message: ToastText, opts?: IToastOptions) =>
|
||||
createToast('error', message, opts);
|
||||
}
|
||||
|
||||
const messages = defineMessages({
|
||||
unexpectedMessage: { id: 'alert.unexpected.message', defaultMessage: 'Something went wrong.' },
|
||||
});
|
||||
|
||||
function showAlertForError(networkError: { response: Response & { json: any } }) {
|
||||
const showAlertForError = (networkError: { response: Response & { json: any } }) => {
|
||||
if (networkError?.response) {
|
||||
const { json, status, statusText } = networkError.response;
|
||||
|
||||
@ -72,7 +69,7 @@ function showAlertForError(networkError: { response: Response & { json: any } })
|
||||
console.error(networkError);
|
||||
return error(messages.unexpectedMessage);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
info,
|
||||
|
||||
Reference in New Issue
Block a user