-
-
Notifications
You must be signed in to change notification settings - Fork 65
fix: layout fixes #782
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
fix: layout fixes #782
Changes from 1 commit
c4f263b
90fddb0
d91640d
f067767
0a1accd
d983e02
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,98 +1,103 @@ | ||
<template> | ||
<v-row justify="center" no-gutters :class="`${className} pa-4`"> | ||
<container> | ||
<div :class="`${className}__buttons`"> | ||
<div class="text-right"> | ||
<language-switcher :prepend-icon="mdiChevronRight" /> | ||
</div> | ||
<div :class="`${className}__settings-button`"> | ||
<v-btn @click="$router.push('/options/nodes')" icon variant="plain" :size="32"> | ||
<v-icon :icon="mdiCog" /> | ||
</v-btn> | ||
<component :is="layout"> | ||
<v-row justify="center" no-gutters :class="className"> | ||
<container> | ||
<div :class="`${className}__buttons`"> | ||
<div class="text-right"> | ||
<language-switcher :prepend-icon="mdiChevronRight" /> | ||
</div> | ||
<div :class="`${className}__settings-button`"> | ||
<v-btn @click="$router.push('/options/nodes')" icon variant="plain" :size="32"> | ||
<v-icon :icon="mdiCog" /> | ||
</v-btn> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<v-sheet class="text-center mt-4" color="transparent"> | ||
<logo style="width: 300px" /> | ||
<v-sheet class="text-center mt-4" color="transparent"> | ||
<logo style="width: 300px" /> | ||
|
||
<h1 :class="`${className}__title`"> | ||
{{ t('login.brand_title') }} | ||
</h1> | ||
<h2 :class="`${className}__subtitle`" class="hidden-sm-and-down mt-4"> | ||
{{ t('login.subheader') }} | ||
</h2> | ||
</v-sheet> | ||
<h1 :class="`${className}__title`"> | ||
{{ t('login.brand_title') }} | ||
</h1> | ||
<h2 :class="`${className}__subtitle`" class="hidden-sm-and-down mt-4"> | ||
{{ t('login.subheader') }} | ||
</h2> | ||
</v-sheet> | ||
|
||
<v-sheet v-if="!isLoginViaPassword" class="text-center mt-4" color="transparent"> | ||
<v-row justify="center" no-gutters> | ||
<v-col sm="8" md="8" lg="8"> | ||
<login-form | ||
ref="loginForm" | ||
v-model="passphrase" | ||
@login="onLogin" | ||
@error="onLoginError" | ||
/> | ||
</v-col> | ||
</v-row> | ||
<v-sheet v-if="!isLoginViaPassword" class="text-center mt-4" color="transparent"> | ||
<v-row justify="center" no-gutters> | ||
<v-col sm="8" md="8" lg="8"> | ||
<login-form | ||
ref="loginForm" | ||
v-model="passphrase" | ||
@login="onLogin" | ||
@error="onLoginError" | ||
/> | ||
</v-col> | ||
</v-row> | ||
|
||
<v-row justify="center" class="mt-4" no-gutters> | ||
<v-col cols="auto"> | ||
<v-btn | ||
class="ma-2" | ||
:title="t('login.scan_qr_code_button_tooltip')" | ||
icon | ||
variant="text" | ||
size="x-small" | ||
:class="`${className}__icon`" | ||
@click="showQrcodeScanner = true" | ||
> | ||
<icon><qr-code-scan-icon /></icon> | ||
</v-btn> | ||
</v-col> | ||
|
||
<v-col cols="auto"> | ||
<qrcode-capture @detect="onDetectQrcode" @error="onDetectQrcodeError"> | ||
<v-row justify="center" class="mt-4" no-gutters> | ||
<v-col cols="auto"> | ||
<v-btn | ||
class="ma-2" | ||
:title="t('login.login_by_qr_code_tooltip')" | ||
:title="t('login.scan_qr_code_button_tooltip')" | ||
icon | ||
variant="text" | ||
size="x-small" | ||
:class="`${className}__icon`" | ||
@click="showQrcodeScanner = true" | ||
> | ||
<icon><file-icon /></icon> | ||
<icon><qr-code-scan-icon /></icon> | ||
</v-btn> | ||
</qrcode-capture> | ||
</v-col> | ||
</v-row> | ||
</v-sheet> | ||
</v-col> | ||
|
||
<v-row v-if="!isLoginViaPassword" justify="center" class="mt-8"> | ||
<v-col sm="8" md="8" lg="8"> | ||
<passphrase-generator @copy="onCopyPassphrase" /> | ||
</v-col> | ||
</v-row> | ||
<v-col cols="auto"> | ||
<qrcode-capture @detect="onDetectQrcode" @error="onDetectQrcodeError"> | ||
<v-btn | ||
class="ma-2" | ||
:title="t('login.login_by_qr_code_tooltip')" | ||
icon | ||
variant="text" | ||
size="x-small" | ||
:class="`${className}__icon`" | ||
> | ||
<icon><file-icon /></icon> | ||
</v-btn> | ||
</qrcode-capture> | ||
</v-col> | ||
</v-row> | ||
</v-sheet> | ||
|
||
<v-sheet v-if="isLoginViaPassword" class="text-center mt-6" color="transparent"> | ||
<v-row no-gutters justify="center"> | ||
<v-row v-if="!isLoginViaPassword" justify="center" class="mt-8"> | ||
<v-col sm="8" md="8" lg="8"> | ||
<login-password-form v-model="password" @login="onLogin" @error="onLoginError" /> | ||
<passphrase-generator @copy="onCopyPassphrase" /> | ||
</v-col> | ||
</v-row> | ||
</v-sheet> | ||
|
||
<qrcode-scanner-dialog | ||
v-if="showQrcodeScanner" | ||
v-model="showQrcodeScanner" | ||
@scan="onScanQrcode" | ||
/> | ||
</container> | ||
</v-row> | ||
|
||
<v-sheet v-if="isLoginViaPassword" class="text-center mt-6" color="transparent"> | ||
<v-row no-gutters justify="center"> | ||
<v-col sm="8" md="8" lg="8"> | ||
<login-password-form v-model="password" @login="onLogin" @error="onLoginError" /> | ||
</v-col> | ||
</v-row> | ||
</v-sheet> | ||
|
||
<qrcode-scanner-dialog | ||
v-if="showQrcodeScanner" | ||
v-model="showQrcodeScanner" | ||
@scan="onScanQrcode" | ||
/> | ||
</container> | ||
</v-row> | ||
</component> | ||
</template> | ||
|
||
<script> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one too, doesn't seem hard to convert to composition |
||
import { nextTick, defineComponent, computed, ref } from 'vue' | ||
import { useStore } from 'vuex' | ||
import { useI18n } from 'vue-i18n' | ||
import { mdiCog, mdiChevronRight } from '@mdi/js' | ||
import { useRoute } from 'vue-router' | ||
|
||
import QrcodeCapture from '@/components/QrcodeCapture.vue' | ||
import LanguageSwitcher from '@/components/LanguageSwitcher.vue' | ||
|
@@ -105,8 +110,6 @@ import FileIcon from '@/components/icons/common/File.vue' | |
import LoginPasswordForm from '@/components/LoginPasswordForm.vue' | ||
import Logo from '@/components/icons/common/Logo.vue' | ||
import { navigateByURI } from '@/router/navigationGuard' | ||
import { useI18n } from 'vue-i18n' | ||
import { mdiCog, mdiChevronRight } from '@mdi/js' | ||
|
||
export default defineComponent({ | ||
components: { | ||
|
@@ -127,12 +130,15 @@ export default defineComponent({ | |
const showQrcodeScanner = ref(false) | ||
const logo = '/img/adamant-logo-transparent-512x512.png' | ||
const store = useStore() | ||
const route = useRoute() | ||
const { t } = useI18n() | ||
const className = 'login-page' | ||
const loginForm = ref(null) | ||
|
||
const isLoginViaPassword = computed(() => store.getters['options/isLoginViaPassword']) | ||
|
||
const layout = computed(() => route.meta.layout || 'default') | ||
|
||
const onDetectQrcode = (passphrase) => { | ||
onScanQrcode(passphrase) | ||
} | ||
|
@@ -181,6 +187,7 @@ export default defineComponent({ | |
loginForm, | ||
mdiCog, | ||
mdiChevronRight, | ||
layout, | ||
onDetectQrcode, | ||
onDetectQrcodeError, | ||
onLogin, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -189,15 +189,16 @@ | |
</template> | ||
|
||
<script> | ||
import { mdiChevronRight, mdiChevronDown, mdiLogoutVariant } from '@mdi/js' | ||
|
||
import LanguageSwitcher from '@/components/LanguageSwitcher.vue' | ||
import CurrencySwitcher from '@/components/CurrencySwitcher.vue' | ||
import PasswordSetDialog from '@/components/PasswordSetDialog.vue' | ||
import { clearDb, db as isIDBSupported } from '@/lib/idb' | ||
import scrollPosition from '@/mixins/scrollPosition' | ||
import { resetPinia } from '@/plugins/pinia' | ||
import { mdiChevronRight, mdiChevronDown, mdiLogoutVariant } from '@mdi/js' | ||
import NavigationWrapper from '@/components/NavigationWrapper.vue' | ||
import { useSavedScroll } from '@/hooks/useSavedScroll' | ||
import { nextTick } from 'vue' | ||
|
||
export default { | ||
components: { | ||
|
@@ -206,7 +207,13 @@ export default { | |
CurrencySwitcher, | ||
PasswordSetDialog | ||
}, | ||
mixins: [scrollPosition], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You transported the scrollbar position logic to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. scrollPosition mixin didn't work at all, so I created new scroll position logic |
||
props: { | ||
sidebarLayoutRef: { | ||
type: Object, | ||
required: false, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need in |
||
default: null | ||
} | ||
}, | ||
setup() { | ||
const { hasView } = useSavedScroll() | ||
|
||
|
@@ -220,6 +227,19 @@ export default { | |
data: () => ({ | ||
passwordDialog: false | ||
}), | ||
mounted() { | ||
nextTick(() => { | ||
if (this.sidebarLayoutRef) { | ||
const scrollTopValue = Number(localStorage.getItem('optionsScrollTop')) || 0 | ||
this.sidebarLayoutRef.scrollTo({ | ||
top: scrollTopValue | ||
}) | ||
} | ||
}) | ||
}, | ||
beforeUnmount() { | ||
localStorage.setItem('optionsScrollTop', this.sidebarLayoutRef?.scrollTop || 0) | ||
}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why you store the scroll position in the LocalStorage? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. moved to vuex store already |
||
computed: { | ||
className: () => 'settings-view', | ||
stayLoggedIn() { | ||
|
@@ -315,11 +335,23 @@ export default { | |
value: true | ||
}) | ||
}, | ||
onKeydownHandler(e) { | ||
if (e.key === 'Escape') { | ||
if (this.passwordDialog) { | ||
e.stopPropagation() | ||
this.passwordDialog = false | ||
|
||
window.removeEventListener('keydown', this.onKeydownHandler, true) | ||
} | ||
} | ||
}, | ||
onCheckStayLoggedIn() { | ||
if (!this.stayLoggedIn) { | ||
isIDBSupported | ||
.then(() => { | ||
this.passwordDialog = true | ||
|
||
window.addEventListener('keydown', this.onKeydownHandler, true) | ||
}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like workaround. Can you explain why you put the listener here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you are right, it's better to move it inside dialog component |
||
.catch(() => { | ||
this.$store.dispatch('snackbar/show', { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May be convert this file to composition? It seems like it's going to be fast