/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at . */ // @flow /** * Threads reducer * @module reducers/threads */ import { sortBy } from "lodash"; import { createSelector } from "reselect"; import type { Selector, State } from "./types"; import type { Thread, ThreadList, Worker } from "../types"; import type { Action } from "../actions/types"; export type ThreadsState = { threads: ThreadList, traits: Object, isWebExtension: boolean, }; export function initialThreadsState(): ThreadsState { return { threads: [], traits: {}, isWebExtension: false, }; } export default function update( state: ThreadsState = initialThreadsState(), action: Action ): ThreadsState { switch (action.type) { case "CONNECT": return { ...state, traits: action.traits, isWebExtension: action.isWebExtension, }; case "INSERT_THREAD": return { ...state, threads: [...state.threads, action.newThread], }; case "REMOVE_THREAD": const { oldThread } = action; return { ...state, threads: state.threads.filter( thread => oldThread.actor != thread.actor ), }; case "UPDATE_SERVICE_WORKER_STATUS": const { thread, status } = action; return { ...state, threads: state.threads.map(t => { if (t.actor == thread) { return { ...t, serviceWorkerStatus: status }; } return t; }), }; default: return state; } } export const getWorkerCount = (state: State) => getThreads(state).length; export function getWorkerByThread(state: State, thread: string): ?Worker { return getThreads(state).find(worker => worker.actor == thread); } function isMainThread(thread: Thread) { return thread.isTopLevel; } export function getMainThread(state: State): ?Thread { return state.threads.threads.find(isMainThread); } export function getDebuggeeUrl(state: State): string { return getMainThread(state)?.url || ""; } export const getThreads: Selector = createSelector( state => state.threads.threads, threads => threads.filter(thread => !isMainThread(thread)) ); export const getAllThreads: Selector = createSelector( getMainThread, getThreads, (mainThread, threads) => [mainThread, ...sortBy(threads, thread => thread.name)].filter(Boolean) ); export function getThread(state: State, threadActor: string) { return getAllThreads(state).find(thread => thread.actor === threadActor); } // checks if a path begins with a thread actor // e.g "server1.conn0.child1/workerTarget22/context1/dbg-workers.glitch.me" export function startsWithThreadActor(state: State, path: string): ?string { const threadActors = getAllThreads(state).map(t => t.actor); const match = path.match(new RegExp(`(${threadActors.join("|")})\/(.*)`)); return match?.[1]; }