refactor: settings page + ui components

This commit is contained in:
Liyas Thomas
2021-07-04 16:59:37 +00:00
committed by GitHub
parent 1b540c0e57
commit fd4f49cf8e
36 changed files with 449 additions and 566 deletions

View File

@@ -63,7 +63,7 @@ body {
.page-leave-active, .page-leave-active,
.layout-enter-active, .layout-enter-active,
.layout-leave-active { .layout-leave-active {
@apply transition-opacity; @apply transition;
} }
.page-enter, .page-enter,
@@ -96,7 +96,6 @@ a {
&.link { &.link {
@apply items-center; @apply items-center;
@apply text-accent; @apply text-accent;
@apply hover:text-accent; @apply hover:text-accent;
@apply focus:text-accent; @apply focus:text-accent;
} }
@@ -153,22 +152,17 @@ button {
@apply items-stretch; @apply items-stretch;
} }
hr {
@apply border-b;
@apply border-divider;
}
.heading { .heading {
@apply font-bold; @apply font-bold;
@apply text-secondaryDark; @apply text-secondaryDark;
@apply text-lg; @apply text-lg;
} }
.info:not(.toasted) {
@apply m-4;
@apply text-secondaryLight;
.material-icons {
@apply align-middle;
@apply mr-2;
}
}
input { input {
@apply truncate; @apply truncate;
} }

View File

@@ -7,30 +7,28 @@
</div> </div>
</template> </template>
<template #body> <template #body>
<p class="info"> <div class="flex flex-col px-2 space-y-2">
{{ $t("extensions_info1") }} <SmartItem
</p>
<div class="px-2">
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
to="https://addons.mozilla.org/en-US/firefox/addon/hoppscotch" to="https://addons.mozilla.org/en-US/firefox/addon/hoppscotch"
blank blank
:title="{ hasFirefoxExtInstalled: $t('installed') }"
svg="firefox" svg="firefox"
label="Firefox" label="Firefox"
:info-icon="hasFirefoxExtInstalled ? 'check_circle' : ''"
/> />
</div> <SmartItem
<div class="px-2">
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
to="https://chrome.google.com/webstore/detail/hoppscotch-browser-extens/amknoiejhlmhancpahfcfcfhllgkpbld" to="https://chrome.google.com/webstore/detail/hoppscotch-browser-extens/amknoiejhlmhancpahfcfcfhllgkpbld"
blank blank
:title="{ hasChromeExtInstalled: $t('installed') }"
svg="chrome" svg="chrome"
label="Chrome" label="Chrome"
:info-icon="hasChromeExtInstalled ? 'check_circle' : ''"
/> />
</div> </div>
</template> </template>
<template #footer>
<div class="px-2 text-secondaryLight text-xs">
{{ $t("extensions_info1") }}
</div>
</template>
</SmartModal> </SmartModal>
</template> </template>

View File

@@ -12,10 +12,11 @@
@click.native="showInstallPrompt()" @click.native="showInstallPrompt()"
/> />
<span tabindex="-1"> <span tabindex="-1">
<span v-if="currentUser === null"> <ButtonPrimary
<ButtonSecondary label="Sign in" @click.native="showLogin = true" /> v-if="currentUser === null"
<ButtonPrimary label="Sign up" @click.native="showLogin = true" /> label="Get Started"
</span> @click.native="showLogin = true"
/>
<tippy v-else tabindex="-1" trigger="click" theme="popover" arrow> <tippy v-else tabindex="-1" trigger="click" theme="popover" arrow>
<template #trigger> <template #trigger>
<ProfilePicture <ProfilePicture
@@ -84,13 +85,12 @@
</tippy> </tippy>
</span> </span>
</div> </div>
<AppLogin :show="showLogin" @hide-modal="showLogin = false" /> <FirebaseLogin :show="showLogin" @hide-modal="showLogin = false" />
<AppExtensions <AppExtensions
:show="showExtensions" :show="showExtensions"
@hide-modal="showExtensions = false" @hide-modal="showExtensions = false"
/> />
<AppShortcuts :show="showShortcuts" @hide-modal="showShortcuts = false" /> <AppShortcuts :show="showShortcuts" @hide-modal="showShortcuts = false" />
<FirebaseEmail :show="showEmail" @hide-modal="showEmail = false" />
</header> </header>
</template> </template>
@@ -110,7 +110,6 @@ export default {
showLogin: false, showLogin: false,
showExtensions: false, showExtensions: false,
showShortcuts: false, showShortcuts: false,
showEmail: false,
navigatorShare: navigator.share, navigatorShare: navigator.share,
} }
}, },
@@ -222,31 +221,3 @@ export default {
}, },
} }
</script> </script>
<style scoped lang="scss">
.logo {
@apply text-xl;
@apply transition-colors;
@apply ease-in-out;
@apply duration-150;
@apply hover:text-accent;
}
@keyframes slideIn {
0% {
@apply opacity-0;
@apply -left-4;
}
100% {
@apply opacity-100;
@apply left-0;
}
}
.slide-in {
@apply relative;
animation: slideIn 0.2s forwards ease-in-out;
}
</style>

View File

@@ -1,26 +0,0 @@
<template>
<SmartModal v-if="show" @close="hideModal">
<template #header>
<h3 class="heading">{{ $t("login") }}</h3>
<div>
<ButtonSecondary icon="close" @click.native="hideModal" />
</div>
</template>
<template #body>
<FirebaseLogin />
</template>
</SmartModal>
</template>
<script>
export default {
props: {
show: Boolean,
},
methods: {
hideModal() {
this.$emit("hide-modal")
},
},
}
</script>

View File

@@ -7,15 +7,15 @@
:to="localePath(navigation.target)" :to="localePath(navigation.target)"
class=" class="
p-4 p-4
text-xs
flex-col flex-1 flex-col flex-1
hover:bg-primaryLight hover:bg-primaryDark hover:text-secondaryDark
items-center items-center
justify-center justify-center
transition
" "
> >
<i class="material-icons">{{ navigation.icon }}</i> <i class="material-icons opacity-75">{{ navigation.icon }}</i>
<span class="mt-2">{{ navigation.title }}</span> <span class="mt-2 text-xs font-semibold">{{ navigation.title }}</span>
</nuxt-link> </nuxt-link>
</nav> </nav>
</aside> </aside>
@@ -36,67 +36,11 @@ export default {
], ],
} }
}, },
computed: {
currentNavigation() {
return this.navigation.filter((item) =>
this.$route.name.includes(item.primary)
)
},
},
mounted() {
window.addEventListener("scroll", () => {
const mainNavLinks = document.querySelectorAll("nav.secondary-nav a")
const fromTop = window.scrollY
mainNavLinks.forEach(({ hash, classList }) => {
const section = document.querySelector(hash)
if (
section &&
section.offsetTop <= fromTop &&
section.offsetTop + section.offsetHeight > fromTop
) {
classList.add("current")
} else {
classList.remove("current")
}
})
})
},
} }
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
nav.secondary-nav { .active {
@apply flex flex-col flex-nowrap; @apply text-accent;
@apply items-center;
@apply justify-center;
@apply border-t-2 border-dashed border-divider;
@apply pt-2;
@apply space-y-2;
a {
@apply inline-flex;
@apply items-center;
@apply justify-center;
@apply flex-shrink-0;
@apply p-4;
@apply rounded-full;
@apply bg-primaryDark;
@apply text-secondaryLight;
@apply fill-current;
@apply outline-none;
@apply ease-in-out;
@apply duration-150;
&:hover {
@apply text-secondary;
@apply fill-current;
}
&.current {
@apply text-accent;
@apply fill-current;
}
}
} }
</style> </style>

View File

@@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<div <div
:class="['row-wrapper ease-in-out', { 'bg-primaryDark': dragging }]" :class="[{ 'bg-primaryDark': dragging }]"
@dragover.prevent @dragover.prevent
@drop.prevent="dropEvent" @drop.prevent="dropEvent"
@dragover="dragging = true" @dragover="dragging = true"

View File

@@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<div <div
:class="['row-wrapper ease-in-out', { 'bg-primaryDark': dragging }]" :class="[{ 'bg-primaryDark': dragging }]"
@dragover.prevent @dragover.prevent
@drop.prevent="dropEvent" @drop.prevent="dropEvent"
@dragover="dragging = true" @dragover="dragging = true"

View File

@@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<div <div
:class="['row-wrapper ease-in-out', { 'bg-primaryDark': dragging }]" :class="[{ 'bg-primaryDark': dragging }]"
draggable="true" draggable="true"
@dragstart="dragStart" @dragstart="dragStart"
@dragover.stop @dragover.stop

View File

@@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<div <div
:class="['row-wrapper ease-in-out', { 'bg-primaryDark': dragging }]" :class="[{ 'bg-primaryDark': dragging }]"
@dragover.prevent @dragover.prevent
@drop.prevent="dropEvent" @drop.prevent="dropEvent"
@dragover="dragging = true" @dragover="dragging = true"

View File

@@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<div <div
:class="['row-wrapper ease-in-out', { 'bg-primaryDark': dragging }]" :class="[{ 'bg-primaryDark': dragging }]"
@dragover.prevent @dragover.prevent
@drop.prevent="dropEvent" @drop.prevent="dropEvent"
@dragover="dragging = true" @dragover="dragging = true"

View File

@@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<div <div
:class="['row-wrapper ease-in-out', { 'bg-primaryDark': dragging }]" :class="[{ 'bg-primaryDark': dragging }]"
draggable="true" draggable="true"
@dragstart="dragStart" @dragstart="dragStart"
@dragover.stop @dragover.stop

View File

@@ -1,6 +1,6 @@
<template> <template>
<div> <div>
<div class="ease-in-out row-wrapper"> <div>
<ButtonSecondary @click.native="toggleShowChildren" /> <ButtonSecondary @click.native="toggleShowChildren" />
<i v-show="!showChildren && !isFiltered" class="material-icons" <i v-show="!showChildren && !isFiltered" class="material-icons"
>arrow_right</i >arrow_right</i

View File

@@ -1,6 +1,6 @@
<template> <template>
<div> <div>
<div class="ease-in-out row-wrapper"> <div>
<div> <div>
<ButtonSecondary @click.native="toggleShowChildren" /> <ButtonSecondary @click.native="toggleShowChildren" />
<i v-show="!showChildren && !isFiltered" class="material-icons" <i v-show="!showChildren && !isFiltered" class="material-icons"

View File

@@ -1,6 +1,6 @@
<template> <template>
<div> <div>
<div class="ease-in-out row-wrapper"> <div>
<div> <div>
<ButtonSecondary <ButtonSecondary
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"

View File

@@ -1,114 +0,0 @@
<template>
<SmartModal v-if="show" @close="hideModal">
<template #header>
<h3 class="heading">{{ $t("login_with") }} {{ $t("email") }}</h3>
<ButtonSecondary icon="close" @click.native="hideModal" />
</template>
<template v-if="mode === 'sign-in'" #body>
<label for="email"> E-mail </label>
<input
id="email"
v-model="form.email"
class="input"
type="email"
name="email"
placeholder="you@mail.com"
autocomplete="email"
required
spellcheck="false"
autofocus
@keyup.enter="signInWithEmail"
/>
</template>
<template v-else #body>
<div class="flex flex-col items-center">
<div class="flex justify-center max-w-md p-4 items-center flex-col">
<i class="material-icons text-accent" style="font-size: 64px">
verified
</i>
<h3 class="font-bold my-2 text-center text-lg">
{{ $t("we_sent_magic_link") }}
</h3>
<p class="text-center">
{{ $t("we_sent_magic_link_description", { email: form.email }) }}
</p>
<p class="info">{{ $t("check_your_inbox") }}</p>
</div>
</div>
</template>
<template v-if="mode === 'sign-in'" #footer>
<span></span>
<span>
<ButtonSPrimary
:loading="signingInWithEmail"
class="rounded-md button"
:disabled="
form.email.length !== 0
? emailRegex.test(form.email)
? false
: true
: true
"
type="button"
tabindex="-1"
:label="$t('send_magic_link')"
@click.native="signInWithEmail"
/></span>
</template>
</SmartModal>
</template>
<script>
import { currentUser$, signInWithEmail } from "~/helpers/fb/auth"
import { setLocalConfig } from "~/newstore/localpersistence"
export default {
props: {
show: Boolean,
},
data() {
return {
form: {
email: "",
},
signingInWithEmail: false,
emailRegex:
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/,
mode: "sign-in",
}
},
mounted() {
this.$subscribeTo(currentUser$, (user) => {
if (user) this.hideModal()
})
},
methods: {
async signInWithEmail() {
this.signingInWithEmail = true
const actionCodeSettings = {
url: `${process.env.BASE_URL}/enter`,
handleCodeInApp: true,
}
await signInWithEmail(this.form.email, actionCodeSettings)
.then(() => {
this.mode = "email"
setLocalConfig("emailForSignIn", this.form.email)
})
.catch((error) => {
this.$toast.error(error.message, {
icon: "error",
})
this.signingInWithEmail = false
})
.finally(() => {
this.signingInWithEmail = false
})
},
hideModal() {
this.mode = "sign-in"
this.$toast.clear()
this.$emit("hide-modal")
},
},
}
</script>

View File

@@ -1,49 +1,52 @@
<template> <template>
<div> <SmartModal v-if="show" @close="hideModal">
<div v-if="mode === 'sign-in'" class="flex flex-col space-y-2"> <template #header>
<SmartItem <h3 class="heading">{{ $t("login_to_hoppscotch") }}</h3>
svg="google" <div>
label="Continue with Google" <ButtonSecondary icon="close" @click.native="hideModal" />
@click.native="signInWithGoogle" </div>
/> </template>
<SmartItem <template #body>
svg="github" <div v-if="mode === 'sign-in'" class="flex flex-col space-y-2">
label="Continue with GitHub" <SmartItem
@click.native="signInWithGithub" :loading="signingInWithGoogle"
/> svg="google"
<SmartItem label="Continue with Google"
icon="mail" @click.native="signInWithGoogle"
label="Continue with Email" />
@click.native="mode = 'email'" <SmartItem
/> :loading="signingInWithGitHub"
</div> svg="github"
<p v-if="mode === 'sign-in'" class="mx-4 mt-8 text-secondaryLight text-xs"> label="Continue with GitHub"
By signing in, you are agreeing to our @click.native="signInWithGithub"
<SmartAnchor class="link" to="/index" label="Terms of Service" /> />
and <SmartItem
<SmartAnchor class="link" to="/index" label="Privacy Policy" />. icon="mail"
</p> label="Continue with Email"
<div v-if="mode === 'email'" class="flex items-center px-4"> @click.native="mode = 'email'"
<label for="email"> Email </label> />
<input </div>
id="email" <div v-if="mode === 'email'" class="flex flex-col space-y-2">
v-model="form.email" <div class="flex items-center">
class="flex flex-1 ml-4 rounded px-4 py-2 outline-none" <label for="email" class="flex items-center px-4">
type="email" <i class="material-icons opacity-75">mail</i>
name="email" </label>
placeholder="you@mail.com" <input
autocomplete="email" id="email"
required v-model="form.email"
spellcheck="false" class="flex flex-1 rounded px-4 py-2 outline-none"
autofocus type="email"
@keyup.enter="signInWithEmail" name="email"
/> placeholder="enter your email"
</div> autocomplete="email"
<div v-if="mode === 'email'"> required
<div class="flex flex-col"> spellcheck="false"
autofocus
@keyup.enter="signInWithEmail"
/>
</div>
<ButtonPrimary <ButtonPrimary
:loading="signingInWithEmail" :loading="signingInWithEmail"
class="mx-4 mt-4"
:disabled=" :disabled="
form.email.length !== 0 form.email.length !== 0
? emailRegex.test(form.email) ? emailRegex.test(form.email)
@@ -57,33 +60,45 @@
@click.native="signInWithEmail" @click.native="signInWithEmail"
/> />
</div> </div>
<p class="mx-4 mt-8 text-secondaryLight text-xs"> <div v-if="mode === 'email-sent'" class="flex flex-col px-4">
Back to <div class="flex justify-center max-w-md items-center flex-col">
<SmartAnchor <i class="material-icons text-accent text-4xl"> verified </i>
class="link" <h3 class="font-bold my-2 text-center text-lg">
to="#"
label="all sign in options"
@click.native="mode = 'sign-in'"
/>.
</p>
</div>
<div v-if="mode === 'email-sent'">
<div class="flex flex-col items-center">
<div class="flex justify-center max-w-md p-4 items-center flex-col">
<i class="material-icons text-accent" style="font-size: 64px">
verified
</i>
<h3 class="font-bold my-2 text-center text-xl">
{{ $t("we_sent_magic_link") }} {{ $t("we_sent_magic_link") }}
</h3> </h3>
<p class="text-center"> <p class="text-center">
{{ $t("we_sent_magic_link_description", { email: form.email }) }} {{ $t("we_sent_magic_link_description", { email: form.email }) }}
</p> </p>
<p class="mt-4 text-secondaryLight">{{ $t("check_your_inbox") }}</p>
</div> </div>
</div> </div>
</div> </template>
</div> <template #footer>
<p v-if="mode === 'sign-in'" class="text-secondaryLight text-xs">
By signing in, you are agreeing to our
<SmartAnchor class="link" to="/index" label="Terms of Service" />
and
<SmartAnchor class="link" to="/index" label="Privacy Policy" />.
</p>
<p v-if="mode === 'email'" class="text-secondaryLight text-xs">
<SmartAnchor
class="link"
label="← All sign in options"
@click.native="mode = 'sign-in'"
/>
</p>
<p
v-if="mode === 'email-sent'"
class="flex flex-1 justify-between text-secondaryLight text-xs"
>
<SmartAnchor
class="link"
label="← Re-enter email"
@click.native="mode = 'email'"
/>
<SmartAnchor class="link" label="Dismiss" @click.native="hideModal" />
</p>
</template>
</SmartModal>
</template> </template>
<script> <script>
@@ -100,11 +115,16 @@ import {
import { setLocalConfig } from "~/newstore/localpersistence" import { setLocalConfig } from "~/newstore/localpersistence"
export default { export default {
props: {
show: Boolean,
},
data() { data() {
return { return {
form: { form: {
email: "", email: "",
}, },
signingInWithGoogle: false,
signingInWithGitHub: false,
signingInWithEmail: false, signingInWithEmail: false,
emailRegex: emailRegex:
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/, /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/,
@@ -123,6 +143,8 @@ export default {
}) })
}, },
async signInWithGoogle() { async signInWithGoogle() {
this.signingInWithGoogle = true
try { try {
const { additionalUserInfo } = await signInUserWithGoogle() const { additionalUserInfo } = await signInUserWithGoogle()
@@ -191,8 +213,12 @@ export default {
}) })
} }
} }
this.signingInWithGoogle = false
}, },
async signInWithGithub() { async signInWithGithub() {
this.signingInWithGitHub = true
try { try {
const { credential, additionalUserInfo } = await signInUserWithGithub() const { credential, additionalUserInfo } = await signInUserWithGithub()
@@ -264,9 +290,12 @@ export default {
}) })
} }
} }
this.signingInWithGitHub = false
}, },
async signInWithEmail() { async signInWithEmail() {
this.signingInWithEmail = true this.signingInWithEmail = true
const actionCodeSettings = { const actionCodeSettings = {
url: `${process.env.BASE_URL}/enter`, url: `${process.env.BASE_URL}/enter`,
handleCodeInApp: true, handleCodeInApp: true,

View File

@@ -5,6 +5,7 @@
<script> <script>
import ThreeGlobe from "three-globe" import ThreeGlobe from "three-globe"
import * as THREE from "three" import * as THREE from "three"
import TrackballControls from "three-trackballcontrols"
import geojson from "~/assets/geojson/ne_110m_admin_0_countries.geojson" import geojson from "~/assets/geojson/ne_110m_admin_0_countries.geojson"
import texture from "~/assets/images/texture.png" import texture from "~/assets/images/texture.png"
@@ -15,6 +16,7 @@ export default {
renderer: null, renderer: null,
scene: null, scene: null,
camera: null, camera: null,
tbControls: null,
arcsData: [...Array(20).keys()].map(() => ({ arcsData: [...Array(20).keys()].map(() => ({
startLat: (Math.random() - 0.5) * 180, startLat: (Math.random() - 0.5) * 180,
startLng: (Math.random() - 0.5) * 360, startLng: (Math.random() - 0.5) * 360,
@@ -32,26 +34,26 @@ export default {
} }
}, },
// computed: { computed: {
// labelsData() { labelsData() {
// const labelsData = [] const labelsData = []
// this.arcsData.forEach( this.arcsData.forEach(
// ({ startLat, startLng, endLat, endLng, color }, linkIdx) => ({ startLat, startLng, endLat, endLng, color }, linkIdx) =>
// [ [
// [startLat, startLng], [startLat, startLng],
// [endLat, endLng], [endLat, endLng],
// ].forEach(([lat, lng], edgeIdx) => ].forEach(([lat, lng], edgeIdx) =>
// labelsData.push({ labelsData.push({
// lat, lat,
// lng, lng,
// color: color[edgeIdx], color: color[edgeIdx],
// text: `${linkIdx} ${edgeIdx ? "tgt" : "src"}`, text: `${linkIdx} ${edgeIdx ? "tgt" : "src"}`,
// }) })
// ) )
// ) )
// return labelsData return labelsData
// }, },
// }, },
mounted() { mounted() {
this.init() this.init()
@@ -76,28 +78,32 @@ export default {
this.globe = new ThreeGlobe() this.globe = new ThreeGlobe()
.globeImageUrl(texture) .globeImageUrl(texture)
.atmosphereColor("#aaaaaa") .atmosphereColor("#aaaaaa")
// arcs layer // arcs layer
.arcsData(this.arcsData) .arcsData(this.arcsData)
.arcColor("color") .arcColor("color")
.arcDashLength(1) .arcDashLength(1)
.arcDashGap(() => Math.random()) .arcDashGap(() => Math.random())
.arcStroke(1) .arcStroke(0.6)
.arcDashInitialGap(() => Math.random() * 5) .arcDashInitialGap(() => Math.random() * 5)
.arcDashAnimateTime(2000) .arcDashAnimateTime(2000)
// hex layer // hex layer
.hexPolygonsData(geojson.features) .hexPolygonsData(geojson.features)
.hexPolygonResolution(3) .hexPolygonResolution(3)
.hexPolygonMargin(0.5) .hexPolygonMargin(0.5)
.hexPolygonColor(() => `#aaaaaa`) .hexPolygonColor(() => `#aaaaaa`)
// labels layer
// .labelsData(this.labelsData)
// .labelLat("lat")
// .labelLng("lng")
// .labelText("text")
// .labelColor("color")
// .labelSize(1.5)
// .labelDotRadius(0.5)
// labels layer
.labelsData(this.labelsData)
.labelLat("lat")
.labelLng("lng")
.labelText("text")
.labelColor("color")
.labelSize(1.2)
.labelDotRadius(0.8)
// Setup renderer
this.renderer = new THREE.WebGLRenderer({ this.renderer = new THREE.WebGLRenderer({
alpha: true, alpha: true,
}) })
@@ -105,26 +111,37 @@ export default {
this.$refs.globe.clientWidth, this.$refs.globe.clientWidth,
this.$refs.globe.clientHeight this.$refs.globe.clientHeight
) )
this.$refs.globe.appendChild(this.renderer.domElement) this.$refs.globe.appendChild(this.renderer.domElement)
// Setup scene
this.scene = new THREE.Scene() this.scene = new THREE.Scene()
this.scene.background = null this.scene.background = null
this.scene.add(this.globe) this.scene.add(this.globe)
this.scene.add(new THREE.AmbientLight(0xffffff)) this.scene.add(new THREE.AmbientLight(0xffffff))
this.scene.add(new THREE.DirectionalLight(0xffffff, 0.8)) this.scene.add(new THREE.DirectionalLight(0xffffff, 0.6))
// Setup camera
this.camera = new THREE.PerspectiveCamera() this.camera = new THREE.PerspectiveCamera()
this.camera.aspect = this.camera.aspect =
this.$refs.globe.clientWidth / this.$refs.globe.clientHeight this.$refs.globe.clientWidth / this.$refs.globe.clientHeight
this.camera.updateProjectionMatrix() this.camera.updateProjectionMatrix()
this.camera.position.z = 300 this.camera.position.z = 300
// Add camera controls
this.tbControls = new TrackballControls(
this.camera,
this.renderer.domElement
)
this.tbControls.rotateSpeed = 5
this.tbControls.noZoom = true
this.tbControls.noPan = true
}, },
animate() { animate() {
this.renderer.render(this.scene, this.camera) this.renderer.render(this.scene, this.camera)
this.tbControls.update()
requestAnimationFrame(this.animate) requestAnimationFrame(this.animate)
this.globe.rotation.y -= 0.005 this.globe.rotation.y -= 0.0025
}, },
}, },
} }

View File

@@ -1,26 +1,23 @@
<template> <template>
<div class="flex flex-col"> <div class="flex">
<label>{{ $t("color") }}: {{ capitalized(active) }}</label> <!-- text-blue-400 -->
<div> <!-- text-green-400 -->
<!-- text-blue-400 --> <!-- text-teal-400 -->
<!-- text-green-400 --> <!-- text-indigo-400 -->
<!-- text-teal-400 --> <!-- text-purple-400 -->
<!-- text-indigo-400 --> <!-- text-orange-400 -->
<!-- text-purple-400 --> <!-- text-pink-400 -->
<!-- text-orange-400 --> <!-- text-red-400 -->
<!-- text-pink-400 --> <!-- text-yellow-400 -->
<!-- text-red-400 --> <ButtonSecondary
<!-- text-yellow-400 --> v-for="(color, index) of accentColors"
<ButtonSecondary :key="`color-${index}`"
v-for="(color, index) of accentColors" v-tippy="{ theme: 'tooltip' }"
:key="`color-${index}`" :title="`${color.charAt(0).toUpperCase()}${color.slice(1)}`"
v-tippy="{ theme: 'tooltip' }" :class="[`text-${color}-400`, { 'bg-primary': color === active }]"
:title="capitalized(color)" icon="lens"
:class="[`text-${color}-400`, { 'bg-primary': color === active }]" @click.native="setActiveColor(color)"
icon="lens" />
@click.native="setActiveColor(color)"
/>
</div>
</div> </div>
</template> </template>
@@ -49,15 +46,11 @@ export default {
setLocalConfig("THEME_COLOR", color) setLocalConfig("THEME_COLOR", color)
}, },
}, },
methods: { methods: {
setActiveColor(color) { setActiveColor(color) {
document.documentElement.setAttribute("data-accent", color) document.documentElement.setAttribute("data-accent", color)
this.active = color this.active = color
}, },
capitalized(color) {
return `${color.charAt(0).toUpperCase()}${color.slice(1)}`
},
}, },
} }
</script> </script>

View File

@@ -277,9 +277,6 @@ export default {
.label { .label {
@apply p-2; @apply p-2;
@apply ease-in-out;
@apply duration-150;
} }
.siblings { .siblings {

View File

@@ -200,9 +200,6 @@ export default {
@apply mx-2; @apply mx-2;
@apply left-0; @apply left-0;
@apply z-50; @apply z-50;
@apply ease-in-out;
@apply duration-150;
@apply shadow-lg; @apply shadow-lg;
top: calc(100% - 8px); top: calc(100% - 8px);

View File

@@ -6,44 +6,26 @@
trigger="click" trigger="click"
theme="popover" theme="popover"
arrow arrow
interactive
:animate-fill="false" :animate-fill="false"
> >
<template #trigger> <template #trigger>
<ButtonSecondary <SmartItem
v-tippy="{ theme: 'tooltip' }" v-tippy="{ theme: 'tooltip' }"
:title="$t('choose_language')" :title="$t('choose_language')"
:label="$i18n.locales.find(({ code }) => code == $i18n.locale).name" :label="`${
/> $i18n.locales.find(({ code }) => code == $i18n.locale).country
{{
$i18n.locales.find(({ code }) => code == $i18n.locale).country
| formatCountry | formatCountry
}} } ${$i18n.locales.find(({ code }) => code == $i18n.locale).name}`"
/>
</template> </template>
<NuxtLink <SmartItem
v-for="locale in $i18n.locales.filter( v-for="locale in $i18n.locales.filter(
({ code }) => code !== $i18n.locale ({ code }) => code !== $i18n.locale
)" )"
:key="locale.code" :key="locale.code"
class=" :to="switchLocalePath(locale.code).toString()"
inline-flex :label="`${locale.country | formatCountry} ${locale.name}`"
items-center />
px-4
py-2
transition
rounded-lg
hover:bg-accentLight hover:text-secondaryDark
focus:bg-accentLight focus:text-secondaryDark focus:outline-none
"
:to="switchLocalePath(locale.code)"
>
<span class="mr-2 text-lg">
{{ locale.country | formatCountry }}
</span>
<span class="font-semibold">
{{ locale.name }}
</span>
</NuxtLink>
</tippy> </tippy>
</span> </span>
</template> </template>

View File

@@ -1,31 +1,17 @@
<template> <template>
<div class="flex flex-col"> <div class="flex">
<label> <ButtonSecondary
<ColorScheme placeholder="..." tag="span"> v-for="(color, index) of colors"
{{ $t("background") }}: :key="`color-${index}`"
{{ v-tippy="{ theme: 'tooltip' }"
$colorMode.preference.charAt(0).toUpperCase() + :title="`${color.charAt(0).toUpperCase()}${color.slice(1)}`"
$colorMode.preference.slice(1) :class="[
}} { 'bg-primary': color === $colorMode.preference },
<span v-if="$colorMode.preference === 'system'"> { 'text-accent hover:text-accent': color === $colorMode.value },
({{ $colorMode.value }} mode detected) ]"
</span> :icon="getIcon(color)"
</ColorScheme> @click.native="$colorMode.preference = color"
</label> />
<div>
<ButtonSecondary
v-for="(color, index) of colors"
:key="`color-${index}`"
v-tippy="{ theme: 'tooltip' }"
:title="`${color.charAt(0).toUpperCase()}${color.slice(1)}`"
:class="[
{ 'bg-primary': color === $colorMode.preference },
{ 'text-accent hover:text-accent': color === $colorMode.value },
]"
:icon="getIcon(color)"
@click.native="$colorMode.preference = color"
/>
</div>
</div> </div>
</template> </template>

View File

@@ -21,8 +21,6 @@
@apply text-secondary; @apply text-secondary;
@apply font-mono; @apply font-mono;
@apply ease-in-out;
@apply duration-150;
@apply border border-divider; @apply border border-divider;
} }

View File

@@ -16,24 +16,29 @@
" "
:class="[ :class="[
{ 'opacity-50 cursor-not-allowed': disabled }, { 'opacity-50 cursor-not-allowed': disabled },
{ 'pointer-events-none': loading },
{ 'flex-1': label }, { 'flex-1': label },
{ 'flex-row-reverse justify-end': reverse }, { 'flex-row-reverse justify-end': reverse },
]" ]"
:disabled="disabled" :disabled="disabled"
:tabindex="loading ? '-1' : '0'"
> >
<i <span v-if="!loading" class="inline-flex items-center">
v-if="icon" <i
:class="label ? (reverse ? 'ml-4 opacity-75' : 'mr-4 opacity-75') : ''" v-if="icon"
class="material-icons" :class="label ? (reverse ? 'ml-4 opacity-75' : 'mr-4 opacity-75') : ''"
> class="material-icons"
{{ icon }} >
</i> {{ icon }}
<SmartIcon </i>
v-if="svg" <SmartIcon
:name="svg" v-if="svg"
:class="label ? (reverse ? 'ml-4 opacity-75' : 'mr-4 opacity-75') : ''" :name="svg"
class="svg-icons" :class="label ? (reverse ? 'ml-4 opacity-75' : 'mr-4 opacity-75') : ''"
/> class="svg-icons"
/>
</span>
<SmartSpinner v-else class="mr-4" />
<div class="inline-flex items-start" :class="{ 'flex-col': description }"> <div class="inline-flex items-start" :class="{ 'flex-col': description }">
<div class="font-semibold"> <div class="font-semibold">
{{ label }} {{ label }}
@@ -42,6 +47,9 @@
{{ description }} {{ description }}
</p> </p>
</div> </div>
<i v-if="infoIcon" class="ml-4 text-accent material-icons">
{{ infoIcon }}
</i>
</SmartLink> </SmartLink>
</template> </template>
@@ -80,14 +88,18 @@ export default {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
infoIcon: { loading: {
type: String, type: Boolean,
default: "", default: false,
}, },
reverse: { reverse: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
infoIcon: {
type: String,
default: "",
},
}, },
} }
</script> </script>

View File

@@ -123,8 +123,8 @@ export default {
@apply flex; @apply flex;
@apply items-center; @apply items-center;
@apply justify-center; @apply justify-center;
@apply ease-in-out; @apply transition;
@apply duration-150;
@apply bg-primaryLight; @apply bg-primaryLight;
} }
@@ -133,13 +133,11 @@ export default {
@apply flex flex-1 flex-col; @apply flex flex-1 flex-col;
@apply m-2; @apply m-2;
@apply p-4; @apply p-4;
@apply ease-in-out; @apply transition;
@apply duration-150;
@apply bg-primary; @apply bg-primary;
@apply rounded-lg; @apply rounded-lg;
@apply shadow-xl; @apply shadow-xl;
@apply max-w-md; @apply max-w-md;
@apply max-h-xl;
} }
.modal-header { .modal-header {
@@ -149,6 +147,7 @@ export default {
.modal-body { .modal-body {
@apply my-4; @apply my-4;
@apply overflow-auto; @apply overflow-auto;
@apply max-h-xl;
} }
.modal-footer { .modal-footer {
@@ -164,7 +163,6 @@ export default {
.modal-leave-active .modal-container { .modal-leave-active .modal-container {
@apply transform; @apply transform;
@apply scale-90; @apply scale-90;
@apply ease-in-out; @apply transition;
@apply duration-150;
} }
</style> </style>

View File

@@ -1,7 +1,6 @@
<template> <template>
<svg <svg
class="animate-spin" class="animate-spin w-5 h-5"
:class="`w-${size} h-${size}`"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
fill="none" fill="none"
viewBox="0 0 24 24" viewBox="0 0 24 24"
@@ -21,14 +20,3 @@
/> />
</svg> </svg>
</template> </template>
<script>
export default {
props: {
size: {
type: Number,
default: 6,
},
},
}
</script>

View File

@@ -45,7 +45,7 @@ $transition: all 0.2s ease-in-out;
@apply align-middle; @apply align-middle;
@apply rounded-full; @apply rounded-full;
@apply p-0; @apply p-0;
@apply m-4; @apply mr-4;
@apply cursor-pointer; @apply cursor-pointer;
@apply flex-shrink-0; @apply flex-shrink-0;

View File

@@ -6,7 +6,11 @@
<div v-else> <div v-else>
<label>{{ $t("login_with") }}</label> <label>{{ $t("login_with") }}</label>
<p> <p>
<FirebaseLogin @show-email="showEmail = true" /> <ButtonPrimary
v-if="currentUser"
label="Get Started"
@click.native="showLogin = true"
/>
</p> </p>
</div> </div>
</div> </div>
@@ -45,7 +49,7 @@
</li> </li>
</ul> </ul>
</div> </div>
<FirebaseEmail :show="showEmail" @hide-modal="showEmail = false" /> <FirebaseLogin :show="showLogin" @hide-modal="showLogin = false" />
</AppSection> </AppSection>
</template> </template>
@@ -62,7 +66,7 @@ export default {
editingteamID: "", editingteamID: "",
me: {}, me: {},
myTeams: [], myTeams: [],
showEmail: false, showLogin: false,
} }
}, },
subscriptions() { subscriptions() {

View File

@@ -2,10 +2,10 @@
<transition <transition
:appear="appear" :appear="appear"
name="translate-fade" name="translate-fade"
enter-active-class="duration-500" enter-active-class="transition"
enter-class="opacity-0" enter-class="opacity-0"
enter-to-class="opacity-100" enter-to-class="opacity-100"
leave-active-class="duration-500" leave-active-class="transition"
leave-class="opacity-100" leave-class="opacity-100"
leave-to-class="opacity-0" leave-to-class="opacity-0"
> >

View File

@@ -2,10 +2,10 @@
<transition <transition
:appear="appear" :appear="appear"
name="translate-slide-right" name="translate-slide-right"
enter-active-class="duration-500 transform" enter-active-class="transition transform"
enter-class="-translate-x-full" enter-class="-translate-x-full"
enter-to-class="translate-x-0" enter-to-class="translate-x-0"
leave-active-class="duration-500 transform" leave-active-class="transition transform"
leave-class="translate-x-0" leave-class="translate-x-0"
leave-to-class="-translate-x-full" leave-to-class="-translate-x-full"
> >

View File

@@ -251,11 +251,12 @@
"extensions_use_toggle": "Use the browser extension to send requests (if present)", "extensions_use_toggle": "Use the browser extension to send requests (if present)",
"extension_version": "Extension Version", "extension_version": "Extension Version",
"extension_ver_not_reported": "Not Reported", "extension_ver_not_reported": "Not Reported",
"extensions_info1": "Browser extension that simplifies access to Hoppscotch", "extensions_info1": "Browser extension simplifies access to Hoppscotch, fix CORS issues, etc.",
"extensions_info2": "Get Hoppscotch browser extension!", "extensions_info2": "Get Hoppscotch browser extension!",
"installed": "Installed", "installed": "Installed",
"login_with": "Login with", "login_with": "Login with",
"login": "Login", "login": "Login",
"login_to_hoppscotch": "Login to Hoppscotch",
"logged_out": "Logged out", "logged_out": "Logged out",
"login_success": "Successfully logged in", "login_success": "Successfully logged in",
"logout": "Logout", "logout": "Logout",
@@ -333,10 +334,9 @@
"import_from_my_collections": "Import from My Collections", "import_from_my_collections": "Import from My Collections",
"export_as_json": "Export as JSON", "export_as_json": "Export as JSON",
"send_magic_link": "Send a magic link", "send_magic_link": "Send a magic link",
"check_your_inbox": "Check your inbox.",
"you_can_dismiss_this_modal": "You can dismiss this ", "you_can_dismiss_this_modal": "You can dismiss this ",
"we_sent_magic_link": "We sent you a magic link!", "we_sent_magic_link": "We sent you a magic link!",
"we_sent_magic_link_description": "We sent an email to {email}. It contains a magic link thatll log you in.", "we_sent_magic_link_description": "Check your inbox - we sent an email to {email}. It contains a magic link that will log you in.",
"hide_sidebar": "Hide sidebar", "hide_sidebar": "Hide sidebar",
"show_sidebar": "Show sidebar", "show_sidebar": "Show sidebar",
"protocols": "Protocols", "protocols": "Protocols",

View File

@@ -443,6 +443,6 @@ export default {
// Router configuration (https://nuxtjs.org/api/configuration-router) // Router configuration (https://nuxtjs.org/api/configuration-router)
router: { router: {
linkExactActiveClass: "text-accent", linkExactActiveClass: "active",
}, },
} }

15
package-lock.json generated
View File

@@ -35,6 +35,7 @@
"tern": "^0.24.3", "tern": "^0.24.3",
"three": "^0.130.0", "three": "^0.130.0",
"three-globe": "^2.18.5", "three-globe": "^2.18.5",
"three-trackballcontrols": "^0.9.0",
"vue-apollo": "^3.0.7", "vue-apollo": "^3.0.7",
"vue-cli-plugin-apollo": "^0.22.2", "vue-cli-plugin-apollo": "^0.22.2",
"vue-functional-data-merge": "^3.1.0", "vue-functional-data-merge": "^3.1.0",
@@ -28000,6 +28001,14 @@
"three": ">=0.88.0" "three": ">=0.88.0"
} }
}, },
"node_modules/three-trackballcontrols": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/three-trackballcontrols/-/three-trackballcontrols-0.9.0.tgz",
"integrity": "sha512-Z6HmIJnP70r5uONvcPCdLEF0SsG1kbGzNb7qQYj3c7b6v2E3XTlbNpZsgTjt36oKm0Z2tU11D6EbW4i8KIHuqA==",
"peerDependencies": {
"three": ">= 0.86 <= 1.0"
}
},
"node_modules/throat": { "node_modules/throat": {
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz",
@@ -55000,6 +55009,12 @@
"tinycolor2": "^1.4" "tinycolor2": "^1.4"
} }
}, },
"three-trackballcontrols": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/three-trackballcontrols/-/three-trackballcontrols-0.9.0.tgz",
"integrity": "sha512-Z6HmIJnP70r5uONvcPCdLEF0SsG1kbGzNb7qQYj3c7b6v2E3XTlbNpZsgTjt36oKm0Z2tU11D6EbW4i8KIHuqA==",
"requires": {}
},
"throat": { "throat": {
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz", "resolved": "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz",

View File

@@ -51,6 +51,7 @@
"tern": "^0.24.3", "tern": "^0.24.3",
"three": "^0.130.0", "three": "^0.130.0",
"three-globe": "^2.18.5", "three-globe": "^2.18.5",
"three-trackballcontrols": "^0.9.0",
"vue-apollo": "^3.0.7", "vue-apollo": "^3.0.7",
"vue-cli-plugin-apollo": "^0.22.2", "vue-cli-plugin-apollo": "^0.22.2",
"vue-functional-data-merge": "^3.1.0", "vue-functional-data-merge": "^3.1.0",

View File

@@ -1,5 +1,27 @@
<template> <template>
<div> <div>
<FirebaseLogin /> <ButtonPrimary
v-if="currentUser === null"
label="Get Started"
@click.native="showLogin = true"
/>
<FirebaseLogin :show="showLogin" @hide-modal="showLogin = false" />
</div> </div>
</template> </template>
<script>
import { currentUser$ } from "~/helpers/fb/auth"
export default {
data() {
return {
showLogin: false,
}
},
subscriptions() {
return {
currentUser: currentUser$,
}
},
}
</script>

View File

@@ -4,74 +4,148 @@
<Teams /> <Teams />
</div> </div>
<AppSection label="account"> <div class="space-y-8">
<div class="flex flex-col"> <div class="md:grid md:grid-cols-3 md:gap-4">
<label>{{ $t("account") }}</label> <div class="md:col-span-1 p-8">
<div v-if="currentUser"> <h3 class="heading">
<ButtonSecondary /> {{ $t("account") }}
<img </h3>
v-if="currentUser.photoURL" <p class="mt-1 text-xs text-secondaryLight">
:src="currentUser.photoURL" Customize your account settings.
class="w-6 h-6 rounded-full material-icons"
/>
<i v-else class="material-icons">account_circle</i>
<span>
{{ currentUser.displayName || $t("nothing_found") }}
</span>
<br />
<ButtonSecondary />
<i class="material-icons">email</i>
<span>
{{ currentUser.email || $t("nothing_found") }}
</span>
<br />
<FirebaseLogout />
<p>
<SmartToggle
:on="SYNC_COLLECTIONS"
@change="toggleSettings('syncCollections', !SYNC_COLLECTIONS)"
>
{{ $t("syncCollections") + " " + $t("sync") }}
{{ SYNC_COLLECTIONS ? $t("enabled") : $t("disabled") }}
</SmartToggle>
</p>
<p>
<SmartToggle
:on="SYNC_ENVIRONMENTS"
@change="toggleSettings('syncEnvironments', !SYNC_ENVIRONMENTS)"
>
{{ $t("syncEnvironments") + " " + $t("sync") }}
{{ SYNC_ENVIRONMENTS ? $t("enabled") : $t("disabled") }}
</SmartToggle>
</p>
<p>
<SmartToggle
:on="SYNC_HISTORY"
@change="toggleSettings('syncHistory', !SYNC_HISTORY)"
>
{{ $t("syncHistory") + " " + $t("sync") }}
{{ SYNC_HISTORY ? $t("enabled") : $t("disabled") }}
</SmartToggle>
</p> </p>
</div> </div>
<div v-else> <div class="md:col-span-2 border border-divider p-8 rounded-lg">
<label>{{ $t("login_with") }}</label> <div v-if="currentUser === null">
<p> <ButtonPrimary label="Log in" @click.native="showLogin = true" />
<FirebaseLogin @show-email="showEmail = true" /> <div class="mt-4 text-xs text-secondaryLight">
</p> Log in to access.
</div>
</div>
<div v-else class="space-y-8">
<fieldset>
<legend class="font-bold text-secondaryDark">User</legend>
<div class="mt-4 space-y-4">
<div class="flex items-start">
<div class="flex items-center">
<img
v-if="currentUser.photoURL"
:src="currentUser.photoURL"
class="w-5 h-5 rounded-full material-icons"
/>
<i v-else class="material-icons">account_circle</i>
</div>
<div class="ml-4">
<label>
{{ currentUser.displayName || $t("nothing_found") }}
</label>
<p class="mt-1 text-xs text-secondaryLight">
This is your display name.
</p>
</div>
</div>
<div class="flex items-start">
<div class="flex items-center">
<i class="material-icons">email</i>
</div>
<div class="ml-4">
<label>
{{ currentUser.email || $t("nothing_found") }}
</label>
<p class="mt-1 text-xs text-secondaryLight">
Your primary email address.
</p>
</div>
</div>
</div>
</fieldset>
<fieldset>
<legend class="font-bold text-secondaryDark">Sync</legend>
<div class="mt-1 text-xs text-secondaryLight">
These settings are synced to cloud.
</div>
<div class="mt-4 space-y-4">
<div class="flex items-center">
<SmartToggle
:on="SYNC_COLLECTIONS"
@change="
toggleSettings('syncCollections', !SYNC_COLLECTIONS)
"
>
{{ $t("syncCollections") }}
</SmartToggle>
</div>
<div class="flex items-center">
<SmartToggle
:on="SYNC_ENVIRONMENTS"
@change="
toggleSettings('syncEnvironments', !SYNC_ENVIRONMENTS)
"
>
{{ $t("syncEnvironments") }}
</SmartToggle>
</div>
<div class="flex items-center">
<SmartToggle
:on="SYNC_HISTORY"
@change="toggleSettings('syncHistory', !SYNC_HISTORY)"
>
{{ $t("syncHistory") }}
</SmartToggle>
</div>
</div>
</fieldset>
</div>
</div> </div>
</div> </div>
</AppSection>
<div class="md:grid md:grid-cols-3 md:gap-4">
<div class="md:col-span-1 p-8">
<h3 class="heading">
{{ $t("theme") }}
</h3>
<p class="mt-1 text-xs text-secondaryLight">
Customize your application theme.
</p>
</div>
<div
class="md:col-span-2 border border-divider p-8 rounded-lg space-y-8"
>
<fieldset>
<legend class="font-bold text-secondaryDark">
{{ $t("background") }}
</legend>
<div class="mt-1 text-xs text-secondaryLight">
<ColorScheme placeholder="..." tag="span">
{{
$colorMode.preference.charAt(0).toUpperCase() +
$colorMode.preference.slice(1)
}}
<span v-if="$colorMode.preference === 'system'">
({{ $colorMode.value }} mode detected)
</span>
</ColorScheme>
</div>
<div class="mt-4">
<SmartColorModePicker />
</div>
</fieldset>
<fieldset>
<legend class="font-bold text-secondaryDark">
{{ $t("color") }}
</legend>
<div class="mt-1 text-xs text-secondaryLight">
{{ active.charAt(0).toUpperCase() + active.slice(1) }}
</div>
<div class="mt-4">
<SmartAccentModePicker />
</div>
</fieldset>
</div>
</div>
</div>
<AppSection label="theme"> <AppSection label="theme">
<div class="flex flex-col"> <div class="flex flex-col">
<label>{{ $t("theme") }}</label>
<SmartColorModePicker />
<SmartAccentModePicker />
<span> <span>
<SmartToggle <SmartToggle
:on="SCROLL_INTO_ENABLED" :on="SCROLL_INTO_ENABLED"
@@ -199,7 +273,7 @@
</div> </div>
</div> </div>
</AppSection> </AppSection>
<FirebaseEmail :show="showEmail" @hide-modal="showEmail = false" /> <FirebaseLogin :show="showLogin" @hide-modal="showLogin = false" />
</div> </div>
</template> </template>
@@ -215,6 +289,7 @@ import {
import type { KeysMatching } from "~/types/ts-utils" import type { KeysMatching } from "~/types/ts-utils"
import { currentUserInfo$ } from "~/helpers/teams/BackendUserInfo" import { currentUserInfo$ } from "~/helpers/teams/BackendUserInfo"
import { currentUser$ } from "~/helpers/fb/auth" import { currentUser$ } from "~/helpers/fb/auth"
import { getLocalConfig } from "~/newstore/localpersistence"
type SettingsType = typeof defaultSettings type SettingsType = typeof defaultSettings
@@ -237,10 +312,12 @@ export default Vue.extend({
EXTENSIONS_ENABLED: true, EXTENSIONS_ENABLED: true,
PROXY_ENABLED: true, PROXY_ENABLED: true,
showEmail: false,
currentBackendUser: null, currentBackendUser: null,
currentUser: null, currentUser: null,
showLogin: false,
active: getLocalConfig("THEME_COLOR") || "green",
} }
}, },
subscriptions() { subscriptions() {