settings.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. <template>
  2. <div>
  3. <div class="container divide-dividerLight space-y-8 divide-y">
  4. <div class="md:grid md:gap-4 md:grid-cols-3">
  5. <div class="p-8 md:col-span-1">
  6. <h3 class="heading">
  7. {{ $t("settings.theme") }}
  8. </h3>
  9. <p class="mt-1 text-secondaryLight">
  10. {{ $t("settings.theme_description") }}
  11. </p>
  12. </div>
  13. <div class="p-8 md:col-span-2 space-y-8">
  14. <section>
  15. <h4 class="font-semibold text-secondaryDark">
  16. {{ $t("settings.background") }}
  17. </h4>
  18. <div class="mt-1 text-secondaryLight">
  19. <ColorScheme placeholder="..." tag="span">
  20. {{ $t(getColorModeName($colorMode.preference)) }}
  21. <span v-if="$colorMode.preference === 'system'">
  22. ({{ $t(getColorModeName($colorMode.value)) }})
  23. </span>
  24. </ColorScheme>
  25. </div>
  26. <div class="mt-4">
  27. <SmartColorModePicker />
  28. </div>
  29. </section>
  30. <section>
  31. <h4 class="font-semibold text-secondaryDark">
  32. {{ $t("settings.accent_color") }}
  33. </h4>
  34. <div class="mt-1 text-secondaryLight">
  35. {{ active.charAt(0).toUpperCase() + active.slice(1) }}
  36. </div>
  37. <div class="mt-4">
  38. <SmartAccentModePicker />
  39. </div>
  40. </section>
  41. <section>
  42. <h4 class="font-semibold text-secondaryDark">
  43. {{ $t("settings.font_size") }}
  44. </h4>
  45. <div class="mt-4">
  46. <SmartFontSizePicker />
  47. </div>
  48. </section>
  49. <section>
  50. <h4 class="font-semibold text-secondaryDark">
  51. {{ $t("settings.language") }}
  52. </h4>
  53. <div class="mt-4">
  54. <SmartChangeLanguage />
  55. </div>
  56. </section>
  57. <section>
  58. <h4 class="font-semibold text-secondaryDark">
  59. {{ $t("settings.experiments") }}
  60. </h4>
  61. <div class="mt-1 text-secondaryLight">
  62. {{ $t("settings.experiments_notice") }}
  63. <SmartLink
  64. class="link"
  65. to="https://github.com/hoppscotch/hoppscotch/issues/new/choose"
  66. blank
  67. >
  68. {{ $t("app.contact_us") }} </SmartLink
  69. >.
  70. </div>
  71. <div class="py-4 space-y-4">
  72. <div class="flex items-center">
  73. <SmartToggle :on="TELEMETRY_ENABLED" @change="showConfirmModal">
  74. {{ $t("settings.telemetry") }}
  75. </SmartToggle>
  76. </div>
  77. <div class="flex items-center">
  78. <SmartToggle
  79. :on="EXPAND_NAVIGATION"
  80. @change="toggleSetting('EXPAND_NAVIGATION')"
  81. >
  82. {{ $t("settings.expand_navigation") }}
  83. </SmartToggle>
  84. </div>
  85. <div class="flex items-center">
  86. <SmartToggle
  87. :on="SIDEBAR_ON_LEFT"
  88. @change="toggleSetting('SIDEBAR_ON_LEFT')"
  89. >
  90. {{ $t("settings.sidebar_on_left") }}
  91. </SmartToggle>
  92. </div>
  93. <div class="flex items-center">
  94. <SmartToggle :on="ZEN_MODE" @change="toggleSetting('ZEN_MODE')">
  95. {{ $t("layout.zen_mode") }}
  96. </SmartToggle>
  97. </div>
  98. </div>
  99. </section>
  100. </div>
  101. </div>
  102. <div class="md:grid md:gap-4 md:grid-cols-3">
  103. <div class="p-8 md:col-span-1">
  104. <h3 class="heading">
  105. {{ $t("settings.interceptor") }}
  106. </h3>
  107. <p class="mt-1 text-secondaryLight">
  108. {{ $t("settings.interceptor_description") }}
  109. </p>
  110. </div>
  111. <div class="p-8 md:col-span-2 space-y-8">
  112. <section>
  113. <h4 class="font-semibold text-secondaryDark">
  114. {{ $t("settings.extensions") }}
  115. </h4>
  116. <div class="mt-1 text-secondaryLight">
  117. <span v-if="extensionVersion != null">
  118. {{
  119. `${$t("settings.extension_version")}: v${
  120. extensionVersion.major
  121. }.${extensionVersion.minor}`
  122. }}
  123. </span>
  124. <span v-else>
  125. {{ $t("settings.extension_version") }}:
  126. {{ $t("settings.extension_ver_not_reported") }}
  127. </span>
  128. </div>
  129. <div class="flex flex-col py-4 space-y-2">
  130. <span>
  131. <SmartItem
  132. to="https://addons.mozilla.org/en-US/firefox/addon/hoppscotch"
  133. blank
  134. svg="brands/firefox"
  135. label="Firefox"
  136. :info-icon="hasFirefoxExtInstalled ? 'check_circle' : ''"
  137. :active-info-icon="hasFirefoxExtInstalled"
  138. outline
  139. />
  140. </span>
  141. <span>
  142. <SmartItem
  143. to="https://chrome.google.com/webstore/detail/hoppscotch-browser-extens/amknoiejhlmhancpahfcfcfhllgkpbld"
  144. blank
  145. svg="brands/chrome"
  146. label="Chrome"
  147. :info-icon="hasChromeExtInstalled ? 'check_circle' : ''"
  148. :active-info-icon="hasChromeExtInstalled"
  149. outline
  150. />
  151. </span>
  152. </div>
  153. <div class="py-4 space-y-4">
  154. <div class="flex items-center">
  155. <SmartToggle
  156. :on="EXTENSIONS_ENABLED"
  157. @change="toggleSetting('EXTENSIONS_ENABLED')"
  158. >
  159. {{ $t("settings.extensions_use_toggle") }}
  160. </SmartToggle>
  161. </div>
  162. </div>
  163. </section>
  164. <section>
  165. <h4 class="font-semibold text-secondaryDark">
  166. {{ $t("settings.proxy") }}
  167. </h4>
  168. <div class="mt-1 text-secondaryLight">
  169. {{
  170. `${$t("settings.official_proxy_hosting")} ${$t(
  171. "settings.read_the"
  172. )}`
  173. }}
  174. <SmartLink
  175. class="link"
  176. to="https://docs.hoppscotch.io/privacy"
  177. blank
  178. >
  179. {{ $t("app.proxy_privacy_policy") }} </SmartLink
  180. >.
  181. </div>
  182. <div class="py-4 space-y-4">
  183. <div class="flex items-center">
  184. <SmartToggle
  185. :on="PROXY_ENABLED"
  186. @change="toggleSetting('PROXY_ENABLED')"
  187. >
  188. {{ $t("settings.proxy_use_toggle") }}
  189. </SmartToggle>
  190. </div>
  191. </div>
  192. <div class="flex items-center py-4 space-x-2">
  193. <div class="relative flex flex-col flex-1">
  194. <input
  195. id="url"
  196. v-model="PROXY_URL"
  197. class="input floating-input"
  198. placeholder=" "
  199. type="url"
  200. autocomplete="off"
  201. :disabled="!PROXY_ENABLED"
  202. />
  203. <label for="url">
  204. {{ $t("settings.proxy_url") }}
  205. </label>
  206. </div>
  207. <ButtonSecondary
  208. v-tippy="{ theme: 'tooltip' }"
  209. :title="$t('settings.reset_default')"
  210. :svg="clearIcon"
  211. outline
  212. class="rounded"
  213. @click.native="resetProxy"
  214. />
  215. </div>
  216. </section>
  217. </div>
  218. </div>
  219. </div>
  220. <SmartConfirmModal
  221. :show="confirmRemove"
  222. :title="`${$t('confirm.remove_telemetry')} ${$t(
  223. 'settings.telemetry_helps_us'
  224. )}`"
  225. @hide-modal="confirmRemove = false"
  226. @resolve="
  227. () => {
  228. toggleSetting('TELEMETRY_ENABLED')
  229. confirmRemove = false
  230. }
  231. "
  232. />
  233. </div>
  234. </template>
  235. <script lang="ts">
  236. import { defineComponent } from "@nuxtjs/composition-api"
  237. import {
  238. hasExtensionInstalled,
  239. hasChromeExtensionInstalled,
  240. hasFirefoxExtensionInstalled,
  241. } from "~/helpers/strategies/ExtensionStrategy"
  242. import {
  243. applySetting,
  244. toggleSetting,
  245. defaultSettings,
  246. useSetting,
  247. } from "~/newstore/settings"
  248. import type { KeysMatching } from "~/types/ts-utils"
  249. import { getLocalConfig } from "~/newstore/localpersistence"
  250. type SettingsType = typeof defaultSettings
  251. export default defineComponent({
  252. setup() {
  253. return {
  254. PROXY_ENABLED: useSetting("PROXY_ENABLED"),
  255. PROXY_URL: useSetting("PROXY_URL"),
  256. EXTENSIONS_ENABLED: useSetting("EXTENSIONS_ENABLED"),
  257. TELEMETRY_ENABLED: useSetting("TELEMETRY_ENABLED"),
  258. EXPAND_NAVIGATION: useSetting("EXPAND_NAVIGATION"),
  259. SIDEBAR_ON_LEFT: useSetting("SIDEBAR_ON_LEFT"),
  260. ZEN_MODE: useSetting("ZEN_MODE"),
  261. }
  262. },
  263. data() {
  264. return {
  265. extensionVersion: hasExtensionInstalled()
  266. ? window.__POSTWOMAN_EXTENSION_HOOK__.getVersion()
  267. : null,
  268. hasChromeExtInstalled: hasChromeExtensionInstalled(),
  269. hasFirefoxExtInstalled: hasFirefoxExtensionInstalled(),
  270. clearIcon: "rotate-ccw",
  271. active: getLocalConfig("THEME_COLOR") || "blue",
  272. confirmRemove: false,
  273. }
  274. },
  275. head() {
  276. return {
  277. title: `${this.$t("navigation.settings")} • Hoppscotch`,
  278. }
  279. },
  280. computed: {
  281. proxySettings(): { url: string } {
  282. return {
  283. url: this.PROXY_URL,
  284. }
  285. },
  286. },
  287. watch: {
  288. ZEN_MODE(ZEN_MODE) {
  289. this.applySetting("EXPAND_NAVIGATION", !ZEN_MODE)
  290. },
  291. proxySettings: {
  292. deep: true,
  293. handler({ url }) {
  294. this.applySetting("PROXY_URL", url)
  295. },
  296. },
  297. },
  298. methods: {
  299. showConfirmModal() {
  300. if (this.TELEMETRY_ENABLED) this.confirmRemove = true
  301. else toggleSetting("TELEMETRY_ENABLED")
  302. },
  303. applySetting<K extends keyof SettingsType>(key: K, value: SettingsType[K]) {
  304. applySetting(key, value)
  305. },
  306. toggleSetting<K extends KeysMatching<SettingsType, boolean>>(key: K) {
  307. if (key === "EXTENSIONS_ENABLED" && this.PROXY_ENABLED) {
  308. toggleSetting("PROXY_ENABLED")
  309. }
  310. if (key === "PROXY_ENABLED" && this.EXTENSIONS_ENABLED) {
  311. toggleSetting("EXTENSIONS_ENABLED")
  312. }
  313. toggleSetting(key)
  314. },
  315. toggleSettings<K extends KeysMatching<SettingsType, boolean>>(
  316. name: K,
  317. value: SettingsType[K]
  318. ) {
  319. this.applySetting(name, value)
  320. },
  321. resetProxy() {
  322. applySetting("PROXY_URL", `https://proxy.hoppscotch.io/`)
  323. this.clearIcon = "check"
  324. this.$toast.success(`${this.$t("state.cleared")}`)
  325. setTimeout(() => (this.clearIcon = "rotate-ccw"), 1000)
  326. },
  327. getColorModeName(colorMode: string) {
  328. switch (colorMode) {
  329. case "system":
  330. return "settings.system_mode"
  331. case "light":
  332. return "settings.light_mode"
  333. case "dark":
  334. return "settings.dark_mode"
  335. case "black":
  336. return "settings.black_mode"
  337. default:
  338. return "settings.system_mode"
  339. }
  340. },
  341. },
  342. })
  343. </script>