From 534fe8030f743ee4d3ddb958854fd48111a5b4e9 Mon Sep 17 00:00:00 2001 From: liyasthomas Date: Sun, 12 Dec 2021 06:19:58 +0530 Subject: [PATCH] fix: subscription streams --- .../helpers/editor/codemirror.ts | 4 +- .../editor/extensions/environmentTooltip.ts | 98 ++++++++++--------- .../helpers/utils/composables.ts | 11 ++- .../hoppscotch-app/newstore/environments.ts | 17 ++-- 4 files changed, 78 insertions(+), 52 deletions(-) diff --git a/packages/hoppscotch-app/helpers/editor/codemirror.ts b/packages/hoppscotch-app/helpers/editor/codemirror.ts index 902c76caa..cd20dee12 100644 --- a/packages/hoppscotch-app/helpers/editor/codemirror.ts +++ b/packages/hoppscotch-app/helpers/editor/codemirror.ts @@ -30,6 +30,7 @@ import { GQLLanguage } from "@hoppscotch/codemirror-lang-graphql" import { pipe } from "fp-ts/function" import * as O from "fp-ts/Option" import { isJSONContentType } from "../utils/contenttypes" +import { useStreamSubscriber } from "../utils/composables" import { Completer } from "./completion" import { LinterDefinition } from "./linting/linter" import { basicSetup, baseTheme, baseHighlightStyle } from "./themes/baseTheme" @@ -152,6 +153,7 @@ export function useCodemirror( value: Ref, options: CodeMirrorOptions ): { cursor: Ref<{ line: number; ch: number }> } { + const { subscribeToStream } = useStreamSubscriber() const language = new Compartment() const lineWrapping = new Compartment() const placeholderConfig = new Compartment() @@ -178,7 +180,7 @@ export function useCodemirror( basicSetup, baseTheme, baseHighlightStyle, - environmentTooltip, + environmentTooltip(subscribeToStream), environmentHighlightStyle, ViewPlugin.fromClass( class { diff --git a/packages/hoppscotch-app/helpers/editor/extensions/environmentTooltip.ts b/packages/hoppscotch-app/helpers/editor/extensions/environmentTooltip.ts index 1e27a4ea8..d14ba18fc 100644 --- a/packages/hoppscotch-app/helpers/editor/extensions/environmentTooltip.ts +++ b/packages/hoppscotch-app/helpers/editor/extensions/environmentTooltip.ts @@ -1,56 +1,64 @@ import { Extension } from "@codemirror/state" import { hoverTooltip } from "@codemirror/tooltip" import { Decoration, MatchDecorator, ViewPlugin } from "@codemirror/view" -import { useReadonlyStream } from "~/helpers/utils/composables" +import { + StreamSubscriberFunc, + useReadonlyStream, +} from "~/helpers/utils/composables" import { aggregateEnvs$ } from "~/newstore/environments" -const cursorTooltipField = hoverTooltip((view, pos, side) => { - const { from, to, text } = view.state.doc.lineAt(pos) - let start = pos - let end = pos +const cursorTooltipField = (subscribeToStream: StreamSubscriberFunc) => + hoverTooltip((view, pos, side) => { + const { from, to, text } = view.state.doc.lineAt(pos) + let start = pos + let end = pos - while (start > from && /\w/.test(text[start - from - 1])) start-- - while (end < to && /\w/.test(text[end - from])) end++ + while (start > from && /\w/.test(text[start - from - 1])) start-- + while (end < to && /\w/.test(text[end - from])) end++ - if ( - (start === pos && side < 0) || - (end === pos && side > 0) || - !/(<<\w+>>)/g.test(text.slice(start - from - 2, end - from + 2)) - ) - return null + if ( + (start === pos && side < 0) || + (end === pos && side > 0) || + !/(<<\w+>>)/g.test(text.slice(start - from - 2, end - from + 2)) + ) + return null - const aggregateEnvs = useReadonlyStream(aggregateEnvs$, null) - const envName = getEnvName( - aggregateEnvs.value?.find( - (env: { key: string }) => env.key === text.slice(start - from, end - from) - )?.sourceEnv - ) - const envValue = getEnvValue( - aggregateEnvs.value?.find( - (env: { key: string }) => env.key === text.slice(start - from, end - from) - )?.value - ) - const textContent = `${envName} ${envValue}` + let textContent: string + subscribeToStream(aggregateEnvs$, (envs) => { + const envName = getEnvName( + envs.find( + (env: { key: string }) => + env.key === text.slice(start - from, end - from) + )?.sourceEnv + ) + const envValue = getEnvValue( + envs.find( + (env: { key: string }) => + env.key === text.slice(start - from, end - from) + )?.value + ) + textContent = `${envName} ${envValue}` + }) - return { - pos: start, - end, - above: true, - create() { - const dom = document.createElement("span") - dom.innerHTML = textContent - dom.className = "tooltip-theme" - return { dom } - }, - } -}) + return { + pos: start, + end, + above: true, + create() { + const dom = document.createElement("span") + dom.innerHTML = textContent + dom.className = "tooltip-theme" + return { dom } + }, + } + }) function getEnvName(name: any) { if (name) return name return "choose an environment" } -function getEnvValue(value: string) { +function getEnvValue(value: string | undefined) { if (value) return value.replace(/"/g, """) // it does not filter special characters before adding them to HTML. return "not found" @@ -63,8 +71,9 @@ function checkEnv(env: string) { const envNotFound = "bg-red-400 text-red-50 hover:bg-red-600" const aggregateEnvs = useReadonlyStream(aggregateEnvs$, null) const className = - aggregateEnvs.value.find((k: { key: string }) => k.key === env.slice(2, -2)) - ?.value === undefined + aggregateEnvs.value?.find( + (k: { key: string }) => k.key === env.slice(2, -2) + )?.value === undefined ? envNotFound : envFound return Decoration.mark({ @@ -89,7 +98,8 @@ export const environmentHighlightStyle = ViewPlugin.define( } ) -export const environmentTooltip: Extension = [ - cursorTooltipField, - environmentHighlightStyle, -] +export const environmentTooltip: ( + subscribeToStream: StreamSubscriberFunc +) => Extension = (subscribeToStream: StreamSubscriberFunc) => { + return [cursorTooltipField(subscribeToStream), environmentHighlightStyle] +} diff --git a/packages/hoppscotch-app/helpers/utils/composables.ts b/packages/hoppscotch-app/helpers/utils/composables.ts index e5ebdb437..482f35c8d 100644 --- a/packages/hoppscotch-app/helpers/utils/composables.ts +++ b/packages/hoppscotch-app/helpers/utils/composables.ts @@ -100,11 +100,20 @@ export function pluckMultipleFromRef>( return Object.fromEntries(keys.map((x) => [x, pluckRef(sourceRef, x)])) as any } +export type StreamSubscriberFunc = ( + stream: Observable, + next?: ((value: T) => void) | undefined, + error?: ((e: any) => void) | undefined, + complete?: (() => void) | undefined +) => void + /** * A composable that provides the ability to run streams * and subscribe to them and respect the component lifecycle. */ -export function useStreamSubscriber() { +export function useStreamSubscriber(): { + subscribeToStream: StreamSubscriberFunc +} { const subs: Subscription[] = [] const runAndSubscribe = ( diff --git a/packages/hoppscotch-app/newstore/environments.ts b/packages/hoppscotch-app/newstore/environments.ts index fdba6d5cb..b735956b1 100644 --- a/packages/hoppscotch-app/newstore/environments.ts +++ b/packages/hoppscotch-app/newstore/environments.ts @@ -1,6 +1,6 @@ import { cloneDeep } from "lodash" import isEqual from "lodash/isEqual" -import { combineLatest } from "rxjs" +import { combineLatest, Observable } from "rxjs" import { distinctUntilChanged, map, pluck } from "rxjs/operators" import DispatchingStore, { defineDispatchers, @@ -285,17 +285,22 @@ export const currentEnvironment$ = combineLatest([ }) ) +type AggregateEnvironment = { + key: string + value: string + sourceEnv: string +} + /** * Stream returning all the environment variables accessible in * the current state (Global + The Selected Environment). * NOTE: The source environment attribute will be "Global" for Global Env as source. */ -export const aggregateEnvs$ = combineLatest([ - currentEnvironment$, - globalEnv$, -]).pipe( +export const aggregateEnvs$: Observable = combineLatest( + [currentEnvironment$, globalEnv$] +).pipe( map(([selectedEnv, globalVars]) => { - const results: { key: string; value: string; sourceEnv: string }[] = [] + const results: AggregateEnvironment[] = [] selectedEnv.variables.forEach(({ key, value }) => results.push({ key, value, sourceEnv: selectedEnv.name })