switchMap(() => { const proxyLogger = new Subject(); const frameMain = createMainFramer(document, getState, proxyLogger); const buildAndFrameMain = actions.pipe( ofType( types.updateFile, types.executeChallenge, types.challengeMounted ), debounceTime(executeDebounceTimeout), switchMap(() => buildFromFiles(getState(), true).pipe( map(frameMain), ignoreElements(), catchError(err => of(disableJSOnError(err))) ) ) ); return merge(buildAndFrameMain, proxyLogger.map(updateConsole)); })
function registerConsoleExecutor( watchExpressionStore: WatchExpressionStore, registerExecutor: RegisterExecutorFunction, ): IDisposable { const disposables = new UniversalDisposable(); const rawOutput: Subject<?EvaluationResult> = new Subject(); const send = expression => { disposables.add( // We filter here because the first value in the BehaviorSubject is null no matter what, and // we want the console to unsubscribe the stream after the first non-null value. watchExpressionStore .evaluateConsoleExpression(expression) .filter(result => result != null) .first() .subscribe(result => rawOutput.next(result)), ); watchExpressionStore._triggerReevaluation(); }; const output: Observable<{ result?: EvaluationResult, }> = rawOutput.map(result => { invariant(result != null); return {data: result}; }); disposables.add( registerExecutor({ id: 'debugger', name: 'Debugger', send, output, getProperties: watchExpressionStore.getProperties.bind( watchExpressionStore, ), }), ); return disposables; }
console.debug("Pinging reaper server.."); return Rx.Observable.fromPromise($.ajax({ url: `${URL_PREFIX}/ping` }).promise()); }); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Login // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ export const loginSubject = new Rx.Subject(); export const loginResult = loginSubject.map(login => { console.info("Logging in with username: "******"Logging out"); return Rx.Observable.fromPromise($.ajax({ url: `${URL_PREFIX}/logout`, method: 'POST'
}); // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // cluster // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ export const addClusterSubject = new Rx.Subject(); export const deleteClusterSubject = new Rx.Subject(); export const addClusterResult = addClusterSubject.map(seed => { console.info("Adding new cluster with seed node: " + seed); return Rx.Observable.fromPromise($.ajax({ url: `${URL_PREFIX}/cluster?seedHost=${encodeURIComponent(seed)}`, method: 'POST' }).promise()); }).share(); export const deleteClusterResult = deleteClusterSubject.map(name => { console.info("Deleting cluster with name: " + name); return Rx.Observable.fromPromise($.ajax({ url: `${URL_PREFIX}/cluster/${encodeURIComponent(name)}`, method: 'DELETE' }).promise()); }).share(); export const clusterNames = Rx.Observable.merge( Rx.Observable.timer(0, POLLING_INTERVAL).map(t => Rx.Observable.just({})),
_observeSuggestions(): Observable<?HyperclickSuggestion> { return this._fetchStream .map(mouseEvent => { if (mouseEvent == null) { return null; } return this._getMousePositionAsBufferPosition(mouseEvent); }) .distinctUntilChanged((x, y) => { if (x == null || y == null) { return (x == null) === (y == null); } return x.compare(y) === 0; }) .filter(position => { if (position == null) { return true; } // Don't fetch suggestions if the mouse is still in the same 'word', where // 'word' is defined by the wordRegExp at the current position. // // If the last suggestion had multiple ranges, we have no choice but to // fetch suggestions because the new word might be between those ranges. // This should be ok because it will reuse that last suggestion until the // mouse moves off of it. if ( (this._lastSuggestionAtMouse == null || !Array.isArray(this._lastSuggestionAtMouse.range)) && this._isInLastWordRange(position) ) { return false; } // Don't refetch if we're already inside the previously emitted suggestion. if (this._isInLastSuggestion(position)) { return false; } return true; }) .do(position => { if (position == null) { this._lastWordRange = null; } else { const match = wordAtPosition(this._textEditor, position); this._lastWordRange = match != null ? match.range : null; } }) .switchMap(position => { if (position == null) { return Observable.of(null); } return Observable.using( () => this._showLoading(), () => Observable.defer(() => this._hyperclick.getSuggestion(this._textEditor, position), ) .startWith(null) // Clear the previous suggestion immediately. .catch(e => { getLogger('hyperclick').error( 'Error getting Hyperclick suggestion:', e, ); return Observable.of(null); }), ); }) .distinctUntilChanged(); }