feat: interceptor selector in bottom bar
This commit is contained in:
4
packages/hoppscotch-app/assets/icons/shield-check.svg
Normal file
4
packages/hoppscotch-app/assets/icons/shield-check.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path>
|
||||||
|
<path d="M9 12l2 2 4-4"></path>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 286 B |
@@ -22,112 +22,126 @@
|
|||||||
}"
|
}"
|
||||||
@click.native="ZEN_MODE = !ZEN_MODE"
|
@click.native="ZEN_MODE = !ZEN_MODE"
|
||||||
/>
|
/>
|
||||||
|
<tippy
|
||||||
|
ref="interceptorOptions"
|
||||||
|
interactive
|
||||||
|
trigger="click"
|
||||||
|
theme="popover"
|
||||||
|
arrow
|
||||||
|
>
|
||||||
|
<template #trigger>
|
||||||
|
<ButtonSecondary
|
||||||
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
:title="t('settings.interceptor')"
|
||||||
|
svg="shield-check"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<AppInterceptor />
|
||||||
|
</tippy>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<span>
|
<tippy
|
||||||
<tippy
|
ref="options"
|
||||||
ref="options"
|
interactive
|
||||||
interactive
|
trigger="click"
|
||||||
trigger="click"
|
theme="popover"
|
||||||
theme="popover"
|
arrow
|
||||||
arrow
|
:on-shown="() => tippyActions.focus()"
|
||||||
:on-shown="() => tippyActions.focus()"
|
>
|
||||||
|
<template #trigger>
|
||||||
|
<ButtonSecondary
|
||||||
|
svg="help-circle"
|
||||||
|
class="!rounded-none"
|
||||||
|
:label="`${t('app.help')}`"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<div
|
||||||
|
ref="tippyActions"
|
||||||
|
class="flex flex-col focus:outline-none"
|
||||||
|
tabindex="0"
|
||||||
|
@keyup.d="documentation.$el.click()"
|
||||||
|
@keyup.s="shortcuts.$el.click()"
|
||||||
|
@keyup.c="chat.$el.click()"
|
||||||
|
@keyup.escape="options.tippy().hide()"
|
||||||
>
|
>
|
||||||
<template #trigger>
|
<SmartItem
|
||||||
<ButtonSecondary
|
ref="documentation"
|
||||||
svg="help-circle"
|
svg="book"
|
||||||
class="!rounded-none"
|
:label="`${t('app.documentation')}`"
|
||||||
:label="`${t('app.help')}`"
|
to="https://docs.hoppscotch.io"
|
||||||
/>
|
blank
|
||||||
</template>
|
:shortcut="['D']"
|
||||||
<div
|
@click.native="options.tippy().hide()"
|
||||||
ref="tippyActions"
|
/>
|
||||||
class="flex flex-col focus:outline-none"
|
<SmartItem
|
||||||
tabindex="0"
|
ref="shortcuts"
|
||||||
@keyup.d="documentation.$el.click()"
|
svg="zap"
|
||||||
@keyup.s="shortcuts.$el.click()"
|
:label="`${t('app.keyboard_shortcuts')}`"
|
||||||
@keyup.c="chat.$el.click()"
|
:shortcut="['S']"
|
||||||
@keyup.escape="options.tippy().hide()"
|
@click.native="
|
||||||
>
|
() => {
|
||||||
<SmartItem
|
showShortcuts = true
|
||||||
ref="documentation"
|
options.tippy().hide()
|
||||||
svg="book"
|
}
|
||||||
:label="`${t('app.documentation')}`"
|
"
|
||||||
to="https://docs.hoppscotch.io"
|
/>
|
||||||
blank
|
<SmartItem
|
||||||
:shortcut="['D']"
|
ref="chat"
|
||||||
@click.native="options.tippy().hide()"
|
svg="message-circle"
|
||||||
/>
|
:label="`${t('app.chat_with_us')}`"
|
||||||
<SmartItem
|
:shortcut="['C']"
|
||||||
ref="shortcuts"
|
@click.native="
|
||||||
svg="zap"
|
() => {
|
||||||
:label="`${t('app.keyboard_shortcuts')}`"
|
chatWithUs()
|
||||||
:shortcut="['S']"
|
options.tippy().hide()
|
||||||
@click.native="
|
}
|
||||||
() => {
|
"
|
||||||
showShortcuts = true
|
/>
|
||||||
options.tippy().hide()
|
<hr />
|
||||||
}
|
<SmartItem
|
||||||
"
|
svg="github"
|
||||||
/>
|
:label="`${t('app.github')}`"
|
||||||
<SmartItem
|
to="https://github.com/hoppscotch/hoppscotch"
|
||||||
ref="chat"
|
blank
|
||||||
svg="message-circle"
|
@click.native="options.tippy().hide()"
|
||||||
:label="`${t('app.chat_with_us')}`"
|
/>
|
||||||
:shortcut="['C']"
|
<SmartItem
|
||||||
@click.native="
|
svg="twitter"
|
||||||
() => {
|
:label="`${t('app.twitter')}`"
|
||||||
chatWithUs()
|
to="https://hoppscotch.io/twitter"
|
||||||
options.tippy().hide()
|
blank
|
||||||
}
|
@click.native="options.tippy().hide()"
|
||||||
"
|
/>
|
||||||
/>
|
<SmartItem
|
||||||
<hr />
|
svg="user-plus"
|
||||||
<SmartItem
|
:label="`${t('app.invite')}`"
|
||||||
svg="github"
|
@click.native="
|
||||||
:label="`${t('app.github')}`"
|
() => {
|
||||||
to="https://github.com/hoppscotch/hoppscotch"
|
showShare = true
|
||||||
blank
|
options.tippy().hide()
|
||||||
@click.native="options.tippy().hide()"
|
}
|
||||||
/>
|
"
|
||||||
<SmartItem
|
/>
|
||||||
svg="twitter"
|
<SmartItem
|
||||||
:label="`${t('app.twitter')}`"
|
svg="lock"
|
||||||
to="https://hoppscotch.io/twitter"
|
:label="`${t('app.terms_and_privacy')}`"
|
||||||
blank
|
to="https://docs.hoppscotch.io/privacy"
|
||||||
@click.native="options.tippy().hide()"
|
blank
|
||||||
/>
|
@click.native="options.tippy().hide()"
|
||||||
<SmartItem
|
/>
|
||||||
svg="user-plus"
|
<SmartItem
|
||||||
:label="`${t('app.invite')}`"
|
svg="gift"
|
||||||
@click.native="
|
:label="`${t('app.whats_new')}`"
|
||||||
() => {
|
to="https://docs.hoppscotch.io/changelog"
|
||||||
showShare = true
|
blank
|
||||||
options.tippy().hide()
|
@click.native="options.tippy().hide()"
|
||||||
}
|
/>
|
||||||
"
|
<!-- <SmartItem :label="t('app.status')" /> -->
|
||||||
/>
|
<div class="flex opacity-50 py-2 px-4">
|
||||||
<SmartItem
|
{{ `${t("app.name")} ${t("app.version")}` }}
|
||||||
svg="lock"
|
|
||||||
:label="`${t('app.terms_and_privacy')}`"
|
|
||||||
to="https://docs.hoppscotch.io/privacy"
|
|
||||||
blank
|
|
||||||
@click.native="options.tippy().hide()"
|
|
||||||
/>
|
|
||||||
<SmartItem
|
|
||||||
svg="gift"
|
|
||||||
:label="`${t('app.whats_new')}`"
|
|
||||||
to="https://docs.hoppscotch.io/changelog"
|
|
||||||
blank
|
|
||||||
@click.native="options.tippy().hide()"
|
|
||||||
/>
|
|
||||||
<!-- <SmartItem :label="t('app.status')" /> -->
|
|
||||||
<div class="flex opacity-50 py-2 px-4">
|
|
||||||
{{ `${t("app.name")} ${t("app.version")}` }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</tippy>
|
</div>
|
||||||
</span>
|
</tippy>
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
svg="zap"
|
svg="zap"
|
||||||
|
|||||||
@@ -8,59 +8,84 @@
|
|||||||
{{ t("settings.interceptor_description") }}
|
{{ t("settings.interceptor_description") }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<SmartToggle
|
<SmartRadioGroup
|
||||||
:on="PROXY_ENABLED"
|
:radios="interceptors"
|
||||||
@change="toggleSettingKey('PROXY_ENABLED')"
|
:selected="interceptorSelection"
|
||||||
>
|
@change="toggleSettingKey"
|
||||||
{{ t("settings.proxy") }}
|
/>
|
||||||
</SmartToggle>
|
|
||||||
<SmartToggle
|
|
||||||
:on="EXTENSIONS_ENABLED"
|
|
||||||
@change="toggleSettingKey('EXTENSIONS_ENABLED')"
|
|
||||||
>
|
|
||||||
{{ t("settings.extensions") }}:
|
|
||||||
{{
|
|
||||||
extensionVersion != null
|
|
||||||
? `v${extensionVersion.major}.${extensionVersion.minor}`
|
|
||||||
: t("settings.extension_ver_not_reported")
|
|
||||||
}}
|
|
||||||
</SmartToggle>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { defineComponent } from "@nuxtjs/composition-api"
|
import { computed, ref, watchEffect } from "@nuxtjs/composition-api"
|
||||||
import { KeysMatching } from "~/types/ts-utils"
|
import { KeysMatching } from "~/types/ts-utils"
|
||||||
import { SettingsType, toggleSetting, useSetting } from "~/newstore/settings"
|
import {
|
||||||
|
applySetting,
|
||||||
|
SettingsType,
|
||||||
|
toggleSetting,
|
||||||
|
useSetting,
|
||||||
|
} from "~/newstore/settings"
|
||||||
import { hasExtensionInstalled } from "~/helpers/strategies/ExtensionStrategy"
|
import { hasExtensionInstalled } from "~/helpers/strategies/ExtensionStrategy"
|
||||||
import { useI18n } from "~/helpers/utils/composables"
|
import { useI18n, usePolled } from "~/helpers/utils/composables"
|
||||||
|
|
||||||
const t = useI18n()
|
const t = useI18n()
|
||||||
|
|
||||||
const PROXY_ENABLED = useSetting("PROXY_ENABLED")
|
const PROXY_ENABLED = useSetting("PROXY_ENABLED")
|
||||||
const EXTENSIONS_ENABLED = useSetting("EXTENSIONS_ENABLED")
|
const EXTENSIONS_ENABLED = useSetting("EXTENSIONS_ENABLED")
|
||||||
|
|
||||||
const toggleSettingKey = <K extends KeysMatching<SettingsType, boolean>>(
|
const toggleSettingKey = <
|
||||||
|
K extends KeysMatching<SettingsType | "BROWSER_ENABLED", boolean>
|
||||||
|
>(
|
||||||
key: K
|
key: K
|
||||||
) => {
|
) => {
|
||||||
if (key === "EXTENSIONS_ENABLED" && PROXY_ENABLED.value) {
|
interceptorSelection.value = key
|
||||||
toggleSetting("PROXY_ENABLED")
|
if (key === "EXTENSIONS_ENABLED") {
|
||||||
|
applySetting("EXTENSIONS_ENABLED", true)
|
||||||
|
if (PROXY_ENABLED.value) toggleSetting("PROXY_ENABLED")
|
||||||
}
|
}
|
||||||
if (key === "PROXY_ENABLED" && EXTENSIONS_ENABLED.value) {
|
if (key === "PROXY_ENABLED") {
|
||||||
toggleSetting("EXTENSIONS_ENABLED")
|
applySetting("PROXY_ENABLED", true)
|
||||||
|
if (EXTENSIONS_ENABLED.value) toggleSetting("EXTENSIONS_ENABLED")
|
||||||
|
}
|
||||||
|
if (key === "BROWSER_ENABLED") {
|
||||||
|
applySetting("PROXY_ENABLED", false)
|
||||||
|
applySetting("EXTENSIONS_ENABLED", false)
|
||||||
}
|
}
|
||||||
toggleSetting(key)
|
|
||||||
}
|
}
|
||||||
</script>
|
|
||||||
|
|
||||||
<script lang="ts">
|
const extensionVersion = usePolled(5000, (stopPolling) => {
|
||||||
export default defineComponent({
|
const result = hasExtensionInstalled()
|
||||||
data() {
|
? window.__POSTWOMAN_EXTENSION_HOOK__.getVersion()
|
||||||
return {
|
: null
|
||||||
extensionVersion: hasExtensionInstalled()
|
|
||||||
? window.__POSTWOMAN_EXTENSION_HOOK__.getVersion()
|
// We don't need to poll anymore after we get value
|
||||||
: null,
|
if (result) stopPolling()
|
||||||
}
|
|
||||||
|
return result
|
||||||
|
})
|
||||||
|
|
||||||
|
const interceptors = computed(() => [
|
||||||
|
{ value: "BROWSER_ENABLED", label: t("state.none") },
|
||||||
|
{ value: "PROXY_ENABLED", label: t("settings.proxy") },
|
||||||
|
{
|
||||||
|
value: "EXTENSIONS_ENABLED",
|
||||||
|
label:
|
||||||
|
`${t("settings.extensions")}: ` +
|
||||||
|
(extensionVersion.value !== null
|
||||||
|
? `v${extensionVersion.value.major}.${extensionVersion.value.minor}`
|
||||||
|
: t("settings.extension_ver_not_reported")),
|
||||||
},
|
},
|
||||||
|
])
|
||||||
|
|
||||||
|
const interceptorSelection = ref("")
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
if (PROXY_ENABLED.value) {
|
||||||
|
interceptorSelection.value = "PROXY_ENABLED"
|
||||||
|
} else if (EXTENSIONS_ENABLED.value) {
|
||||||
|
interceptorSelection.value = "EXTENSIONS_ENABLED"
|
||||||
|
} else {
|
||||||
|
interceptorSelection.value = "BROWSER_ENABLED"
|
||||||
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -122,25 +122,6 @@
|
|||||||
{{ `${response.meta.responseSize} B` }}
|
{{ `${response.meta.responseSize} B` }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="inline-flex">
|
|
||||||
<tippy
|
|
||||||
ref="options"
|
|
||||||
interactive
|
|
||||||
trigger="click"
|
|
||||||
theme="popover"
|
|
||||||
arrow
|
|
||||||
>
|
|
||||||
<template #trigger>
|
|
||||||
<ButtonSecondary
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
:title="t('settings.interceptor')"
|
|
||||||
svg="globe"
|
|
||||||
class="!p-0"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<AppInterceptor />
|
|
||||||
</tippy>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
35
packages/hoppscotch-app/components/smart/Radio.vue
Normal file
35
packages/hoppscotch-app/components/smart/Radio.vue
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
<template>
|
||||||
|
<label
|
||||||
|
class="cursor-pointer flex-nowrap transition inline-flex items-center justify-center group hover:text-secondaryDark"
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
:value="value"
|
||||||
|
:checked="value === selected"
|
||||||
|
class="appearance-none cursor-pointer mr-4 transition rounded-full h-4 w-4 border-2 border-divider group-hover:border-accentDark checked:border-4 checked:border-accent focus:outline-none"
|
||||||
|
@change="$emit('change', value)"
|
||||||
|
/>
|
||||||
|
<span class="font-semibold transition">{{ label }}</span>
|
||||||
|
</label>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { defineComponent } from "@nuxtjs/composition-api"
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
selected: {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
22
packages/hoppscotch-app/components/smart/RadioGroup.vue
Normal file
22
packages/hoppscotch-app/components/smart/RadioGroup.vue
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<template>
|
||||||
|
<div class="flex flex-col space-y-4 items-start">
|
||||||
|
<SmartRadio
|
||||||
|
v-for="(radio, index) in radios"
|
||||||
|
:key="`radio-${index}`"
|
||||||
|
:value="radio.value"
|
||||||
|
:label="radio.label"
|
||||||
|
:selected="selected"
|
||||||
|
@change="$emit('change', radio.value)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
defineProps<{
|
||||||
|
radios: Array<{
|
||||||
|
value: string
|
||||||
|
label: string
|
||||||
|
}>
|
||||||
|
selected: string
|
||||||
|
}>()
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user