|
1 | 1 | import fetch from 'isomorphic-fetch';
|
2 | 2 | import { ThunkAction as ReduxThunkAction } from 'redux-thunk';
|
3 | 3 | import url, { UrlObject } from 'url';
|
| 4 | +import { z } from 'zod'; |
4 | 5 |
|
5 | 6 | import {
|
6 | 7 | clippyRequestSelector,
|
7 | 8 | formatRequestSelector,
|
8 | 9 | getCrateType,
|
9 |
| - isAutoBuildSelector, |
10 | 10 | runAsTest,
|
| 11 | + useWebsocketSelector, |
11 | 12 | } from './selectors';
|
12 | 13 | import State from './state';
|
13 | 14 | import {
|
@@ -62,6 +63,7 @@ const createAction = <T extends string, P extends {}>(type: T, props?: P) => (
|
62 | 63 |
|
63 | 64 | export enum ActionType {
|
64 | 65 | InitializeApplication = 'INITIALIZE_APPLICATION',
|
| 66 | + DisableSyncChangesToStorage = 'DISABLE_SYNC_CHANGES_TO_STORAGE', |
65 | 67 | SetPage = 'SET_PAGE',
|
66 | 68 | ChangeEditor = 'CHANGE_EDITOR',
|
67 | 69 | ChangeKeybinding = 'CHANGE_KEYBINDING',
|
@@ -127,10 +129,38 @@ export enum ActionType {
|
127 | 129 | NotificationSeen = 'NOTIFICATION_SEEN',
|
128 | 130 | BrowserWidthChanged = 'BROWSER_WIDTH_CHANGED',
|
129 | 131 | SplitRatioChanged = 'SPLIT_RATIO_CHANGED',
|
| 132 | + WebSocketError = 'WEBSOCKET_ERROR', |
| 133 | + WebSocketConnected = 'WEBSOCKET_CONNECTED', |
| 134 | + WebSocketDisconnected = 'WEBSOCKET_DISCONNECTED', |
| 135 | + WebSocketFeatureFlagEnabled = 'WEBSOCKET_FEATURE_FLAG_ENABLED', |
| 136 | + WSExecuteRequest = 'WS_EXECUTE_REQUEST', |
| 137 | + WSExecuteResponse = 'WS_EXECUTE_RESPONSE', |
130 | 138 | }
|
131 | 139 |
|
| 140 | +export const WebSocketError = z.object({ |
| 141 | + type: z.literal(ActionType.WebSocketError), |
| 142 | + error: z.string(), |
| 143 | +}); |
| 144 | +export type WebSocketError = z.infer<typeof WebSocketError>; |
| 145 | + |
| 146 | +const ExecuteExtra = z.object({ |
| 147 | + sequenceNumber: z.number(), |
| 148 | +}); |
| 149 | +type ExecuteExtra = z.infer<typeof ExecuteExtra>; |
| 150 | + |
| 151 | +export const WSExecuteResponse = z.object({ |
| 152 | + type: z.literal(ActionType.WSExecuteResponse), |
| 153 | + success: z.boolean(), |
| 154 | + stdout: z.string(), |
| 155 | + stderr: z.string(), |
| 156 | + extra: ExecuteExtra, |
| 157 | +}); |
| 158 | +export type WSExecuteResponse = z.infer<typeof WSExecuteResponse>; |
| 159 | + |
132 | 160 | export const initializeApplication = () => createAction(ActionType.InitializeApplication);
|
133 | 161 |
|
| 162 | +export const disableSyncChangesToStorage = () => createAction(ActionType.DisableSyncChangesToStorage); |
| 163 | + |
134 | 164 | const setPage = (page: Page) =>
|
135 | 165 | createAction(ActionType.SetPage, { page });
|
136 | 166 |
|
@@ -192,22 +222,14 @@ interface ExecuteResponseBody {
|
192 | 222 | stderr: string;
|
193 | 223 | }
|
194 | 224 |
|
195 |
| -interface ExecuteSuccess extends ExecuteResponseBody { |
196 |
| - isAutoBuild: boolean; |
197 |
| -} |
198 |
| - |
199 | 225 | const requestExecute = () =>
|
200 | 226 | createAction(ActionType.ExecuteRequest);
|
201 | 227 |
|
202 |
| -const receiveExecuteSuccess = ({ stdout, stderr, isAutoBuild }: ExecuteSuccess) => |
203 |
| - createAction(ActionType.ExecuteSucceeded, { stdout, stderr, isAutoBuild }); |
| 228 | +const receiveExecuteSuccess = ({ stdout, stderr }: ExecuteResponseBody) => |
| 229 | + createAction(ActionType.ExecuteSucceeded, { stdout, stderr }); |
204 | 230 |
|
205 |
| -const receiveExecuteFailure = ({ |
206 |
| - error, isAutoBuild, |
207 |
| -}: { |
208 |
| - error?: string, isAutoBuild: boolean, |
209 |
| -}) => |
210 |
| - createAction(ActionType.ExecuteFailed, { error, isAutoBuild }); |
| 231 | +const receiveExecuteFailure = ({ error }: { error?: string }) => |
| 232 | + createAction(ActionType.ExecuteFailed, { error }); |
211 | 233 |
|
212 | 234 | function jsonGet(urlObj: string | UrlObject) {
|
213 | 235 | const urlStr = url.format(urlObj);
|
@@ -281,18 +303,21 @@ interface ExecuteRequestBody {
|
281 | 303 | }
|
282 | 304 |
|
283 | 305 | const performCommonExecute = (crateType: string, tests: boolean): ThunkAction => (dispatch, getState) => {
|
284 |
| - dispatch(requestExecute()); |
285 |
| - |
286 | 306 | const state = getState();
|
287 | 307 | const { code, configuration: { channel, mode, edition } } = state;
|
288 | 308 | const backtrace = state.configuration.backtrace === Backtrace.Enabled;
|
289 |
| - const isAutoBuild = isAutoBuildSelector(state); |
290 | 309 |
|
291 |
| - const body: ExecuteRequestBody = { channel, mode, edition, crateType, tests, code, backtrace }; |
| 310 | + if (useWebsocketSelector(state)) { |
| 311 | + return dispatch(wsExecuteRequest(channel, mode, edition, crateType, tests, code, backtrace)); |
| 312 | + } else { |
| 313 | + dispatch(requestExecute()); |
| 314 | + |
| 315 | + const body: ExecuteRequestBody = { channel, mode, edition, crateType, tests, code, backtrace }; |
292 | 316 |
|
293 |
| - return jsonPost<ExecuteResponseBody>(routes.execute, body) |
294 |
| - .then(json => dispatch(receiveExecuteSuccess({ ...json, isAutoBuild }))) |
295 |
| - .catch(json => dispatch(receiveExecuteFailure({ ...json, isAutoBuild }))); |
| 317 | + return jsonPost<ExecuteResponseBody>(routes.execute, body) |
| 318 | + .then(json => dispatch(receiveExecuteSuccess(json))) |
| 319 | + .catch(json => dispatch(receiveExecuteFailure(json))); |
| 320 | + } |
296 | 321 | };
|
297 | 322 |
|
298 | 323 | function performAutoOnly(): ThunkAction {
|
@@ -473,6 +498,32 @@ const PRIMARY_ACTIONS: { [index in PrimaryAction]: () => ThunkAction } = {
|
473 | 498 | [PrimaryActionCore.Wasm]: performCompileToNightlyWasmOnly,
|
474 | 499 | };
|
475 | 500 |
|
| 501 | +let sequenceNumber = 0; |
| 502 | +const nextSequenceNumber = () => sequenceNumber++; |
| 503 | +const makeExtra = (): ExecuteExtra => ({ |
| 504 | + sequenceNumber: nextSequenceNumber(), |
| 505 | +}); |
| 506 | + |
| 507 | +const wsExecuteRequest = ( |
| 508 | + channel: Channel, |
| 509 | + mode: Mode, |
| 510 | + edition: Edition, |
| 511 | + crateType: string, |
| 512 | + tests: boolean, |
| 513 | + code: string, |
| 514 | + backtrace: boolean |
| 515 | +) => |
| 516 | + createAction(ActionType.WSExecuteRequest, { |
| 517 | + channel, |
| 518 | + mode, |
| 519 | + edition, |
| 520 | + crateType, |
| 521 | + tests, |
| 522 | + code, |
| 523 | + backtrace, |
| 524 | + extra: makeExtra(), |
| 525 | + }); |
| 526 | + |
476 | 527 | export const performPrimaryAction = (): ThunkAction => (dispatch, getState) => {
|
477 | 528 | const state = getState();
|
478 | 529 | const primaryAction = PRIMARY_ACTIONS[state.configuration.primaryAction];
|
@@ -810,6 +861,11 @@ export const browserWidthChanged = (isSmall: boolean) =>
|
810 | 861 | export const splitRatioChanged = () =>
|
811 | 862 | createAction(ActionType.SplitRatioChanged);
|
812 | 863 |
|
| 864 | +export const websocketError = (error: string): WebSocketError => createAction(ActionType.WebSocketError, { error }); |
| 865 | +export const websocketConnected = () => createAction(ActionType.WebSocketConnected); |
| 866 | +export const websocketDisconnected = () => createAction(ActionType.WebSocketDisconnected); |
| 867 | +export const websocketFeatureFlagEnabled = () => createAction(ActionType.WebSocketFeatureFlagEnabled); |
| 868 | + |
813 | 869 | function parseChannel(s?: string): Channel | null {
|
814 | 870 | switch (s) {
|
815 | 871 | case 'stable':
|
@@ -897,6 +953,7 @@ export function showExample(code: string): ThunkAction {
|
897 | 953 |
|
898 | 954 | export type Action =
|
899 | 955 | | ReturnType<typeof initializeApplication>
|
| 956 | + | ReturnType<typeof disableSyncChangesToStorage> |
900 | 957 | | ReturnType<typeof setPage>
|
901 | 958 | | ReturnType<typeof changePairCharacters>
|
902 | 959 | | ReturnType<typeof changeAssemblyFlavor>
|
@@ -962,4 +1019,10 @@ export type Action =
|
962 | 1019 | | ReturnType<typeof notificationSeen>
|
963 | 1020 | | ReturnType<typeof browserWidthChanged>
|
964 | 1021 | | ReturnType<typeof splitRatioChanged>
|
| 1022 | + | ReturnType<typeof websocketError> |
| 1023 | + | ReturnType<typeof websocketConnected> |
| 1024 | + | ReturnType<typeof websocketDisconnected> |
| 1025 | + | ReturnType<typeof websocketFeatureFlagEnabled> |
| 1026 | + | ReturnType<typeof wsExecuteRequest> |
| 1027 | + | WSExecuteResponse |
965 | 1028 | ;
|
0 commit comments