Add a Light theme and a theme detection/selection feature

This commit is contained in:
Bubka
2023-02-01 17:21:55 +01:00
parent 4b0f2186da
commit eadebb41ac
32 changed files with 439 additions and 168 deletions

27
resources/js/app.js vendored
View File

@ -18,7 +18,32 @@ const app = new Vue({
appSettings: window.appSettings,
appConfig: window.appConfig,
isDemoApp: window.isDemoApp,
isTestingApp: window.isTestingApp
isTestingApp: window.isTestingApp,
prefersDarkScheme: window.matchMedia('(prefers-color-scheme: dark)').matches
},
computed: {
showDarkMode: function() {
return this.appSettings.theme == 'dark' ||
(this.appSettings.theme == 'system' && this.prefersDarkScheme)
}
},
mounted () {
this.mediaQueryList = window.matchMedia('(prefers-color-scheme: dark)')
this.$nextTick(() => {
this.mediaQueryList.addEventListener('change', this.setDarkScheme)
})
},
beforeDestroy () {
this.mediaQueryList.removeEventListener('change', this.setDarkScheme)
},
methods: {
setDarkScheme ({ matches }) {
this.prefersDarkScheme = matches
}
},
i18n,
router,

View File

@ -1,5 +1,5 @@
<template>
<footer class="has-background-black-ter">
<footer>
<div class="columns is-gapless" v-if="showButtons">
<div class="column has-text-centered">
<div class="field is-grouped">

View File

@ -26,14 +26,14 @@
<div v-if="showRules" class="columns is-mobile is-size-7 mt-0">
<div class="column is-one-third">
<span class="has-text-weight-semibold">{{ $t("auth.forms.mandatory_rules") }}</span><br />
<span class="is-underscored" :class="{'has-background-success-dark is-dot' : IsLongEnough}"></span>{{ $t('auth.forms.is_long_enough') }}<br/>
<span class="is-underscored" :class="{'is-dot' : IsLongEnough}"></span>{{ $t('auth.forms.is_long_enough') }}<br/>
</div>
<div class="column">
<span class="has-text-weight-semibold">{{ $t("auth.forms.optional_rules_you_should_follow") }}</span><br />
<span class="is-underscored" :class="{'has-background-success-dark is-dot' : hasLowerCase}"></span>{{ $t('auth.forms.has_lower_case') }}<br/>
<span class="is-underscored" :class="{'has-background-success-dark is-dot' : hasUpperCase}"></span>{{ $t('auth.forms.has_upper_case') }}<br/>
<span class="is-underscored" :class="{'has-background-success-dark is-dot' : hasSpecialChar}"></span>{{ $t('auth.forms.has_special_char') }}<br/>
<span class="is-underscored" :class="{'has-background-success-dark is-dot' : hasNumber}"></span>{{ $t('auth.forms.has_number') }}
<span class="is-underscored" :class="{'is-dot' : hasLowerCase}"></span>{{ $t('auth.forms.has_lower_case') }}<br/>
<span class="is-underscored" :class="{'is-dot' : hasUpperCase}"></span>{{ $t('auth.forms.has_upper_case') }}<br/>
<span class="is-underscored" :class="{'is-dot' : hasSpecialChar}"></span>{{ $t('auth.forms.has_special_char') }}<br/>
<span class="is-underscored" :class="{'is-dot' : hasNumber}"></span>{{ $t('auth.forms.has_number') }}
</div>
</div>
</div>

View File

@ -5,12 +5,15 @@
<button
role="radio"
type="button"
class="button is-dark"
class="button"
:aria-checked="form[fieldName] === choice.value"
:disabled="isDisabled"
v-for="(choice, index) in choices"
:key="index"
:class="{ 'is-link' : form[fieldName] === choice.value }"
:class="{
'is-link' : form[fieldName] === choice.value,
'is-dark' : $root.showDarkMode
}"
v-on:click.stop="setRadio(choice.value)"
>
<input

View File

@ -5,7 +5,7 @@
<section class="section">
<div class="columns is-centered">
<div class="column is-three-quarters">
<div class="box has-text-centered has-background-black-ter is-shadowless">
<div class="modal-slot box has-text-centered is-shadowless">
<slot></slot>
</div>
</div>
@ -14,7 +14,7 @@
</div>
<div v-if="this.showcloseButton" class="fullscreen-footer">
<!-- Close button -->
<button ref="closeModalButton" class="button is-dark is-rounded" @click.stop="closeModal">
<button ref="closeModalButton" class="button is-rounded" :class="{'is-dark' : $root.showDarkMode}" @click.stop="closeModal">
{{ $t('commons.close') }}
</button>
</div>

View File

@ -3,10 +3,10 @@
<figure class="image is-64x64" :class="{ 'no-icon': !internal_icon }" style="display: inline-block">
<img :src="$root.appConfig.subdirectory + '/storage/icons/' + internal_icon" v-if="internal_icon" :alt="$t('twofaccounts.icon_to_illustrate_the_account')">
</figure>
<p class="is-size-4 has-text-grey-light has-ellipsis">{{ internal_service }}</p>
<p class="is-size-6 has-text-grey has-ellipsis">{{ internal_account }}</p>
<p class="is-size-4 has-ellipsis" :class="$root.showDarkMode ? 'has-text-grey-light' : 'has-text-grey'">{{ internal_service }}</p>
<p class="is-size-6 has-ellipsis" :class="$root.showDarkMode ? 'has-text-grey' : 'has-text-grey-light'">{{ internal_account }}</p>
<p>
<span role="log" ref="otp" tabindex="0" class="otp is-size-1 has-text-white is-clickable px-3" @click="copyOTP(internal_password)" @keyup.enter="copyOTP(internal_password)" :title="$t('commons.copy_to_clipboard')">
<span role="log" ref="otp" tabindex="0" class="otp is-size-1 is-clickable px-3" :class="$root.showDarkMode ? 'has-text-white' : 'has-text-grey-dark'" @click="copyOTP(internal_password)" @keyup.enter="copyOTP(internal_password)" :title="$t('commons.copy_to_clipboard')">
{{ displayedOtp }}
</span>
</p>

View File

@ -1,5 +1,5 @@
<template>
<div class="options-header has-background-black-ter">
<div class="options-header">
<responsive-width-wrapper>
<div class="tabs is-centered is-fullwidth">
<ul>

View File

@ -97,6 +97,10 @@ Vue.mixin({
// url
// week
},
setTheme(theme) {
document.documentElement.dataset.theme = theme;
}
}
})

View File

@ -38,7 +38,10 @@ import {
faEyeSlash,
faExternalLinkAlt,
faCamera,
faFileDownload
faFileDownload,
faSun,
faMoon,
faDesktop
} from '@fortawesome/free-solid-svg-icons'
import {
@ -81,7 +84,10 @@ library.add(
faEyeSlash,
faExternalLinkAlt,
faCamera,
faFileDownload
faFileDownload,
faSun,
faMoon,
faDesktop
);
Vue.component('font-awesome-icon', FontAwesomeIcon)

View File

@ -2,10 +2,10 @@
<responsive-width-wrapper>
<h1 class="title has-text-grey-dark">{{ pagetitle }}</h1>
<p class="block">
<span class="has-text-white"><span class="is-size-5">2FAuth</span> v{{ appVersion }}</span><br />
<span :class="$root.showDarkMode ? 'has-text-white':'has-text-black'"><span class="is-size-5">2FAuth</span> v{{ appVersion }}</span><br />
{{ $t('commons.2fauth_teaser')}}
</p>
<img src="logo.svg" style="height: 32px" alt="2FAuth logo" />
<img class="about-logo" src="logo.svg" alt="2FAuth logo" />
<p class="block" :class="showUserOptions ? 'mb-5' : '' ">
©Bubka <a class="is-size-7" href="https://github.com/Bubka/2FAuth/blob/master/LICENSE">AGPL-3.0 license</a>
</p>
@ -13,25 +13,25 @@
{{ $t('commons.resources') }}
</h2>
<div class="buttons">
<a class="button is-dark" href="https://github.com/Bubka/2FAuth" target="_blank">
<a class="button" :class="{'is-dark' : $root.showDarkMode}" href="https://github.com/Bubka/2FAuth" target="_blank">
<span class="icon is-small">
<font-awesome-icon :icon="['fab', 'github-alt']" />
</span>
<span>Github</span>
</a>
<a class="button is-dark" href="https://docs.2fauth.app/" target="_blank">
<a class="button" :class="{'is-dark' : $root.showDarkMode}" href="https://docs.2fauth.app/" target="_blank">
<span class="icon is-small">
<font-awesome-icon :icon="['fas', 'book']" />
</span>
<span>Docs</span>
</a>
<a class="button is-dark" href="https://demo.2fauth.app/" target="_blank">
<a class="button" :class="{'is-dark' : $root.showDarkMode}" href="https://demo.2fauth.app/" target="_blank">
<span class="icon is-small">
<font-awesome-icon :icon="['fas', 'flask']" />
</span>
<span>Demo</span>
</a>
<a class="button is-dark" href="https://docs.2fauth.app/resources/rapidoc.html" target="_blank">
<a class="button" :class="{'is-dark' : $root.showDarkMode}" href="https://docs.2fauth.app/resources/rapidoc.html" target="_blank">
<span class="icon is-small">
<font-awesome-icon :icon="['fas', 'code']" />
</span>
@ -51,7 +51,7 @@
<h2 class="title is-5 has-text-grey-light">
{{ $t('commons.environment') }}
</h2>
<div class="box has-background-black-bis is-family-monospace is-size-7">
<div class="about-debug box is-family-monospace is-size-7">
<button :aria-label="$t('commons.copy_to_clipboard')" class="button is-like-text is-pulled-right is-small is-text" v-clipboard="() => this.$refs.listInfos.innerText" v-clipboard:success="clipboardSuccessHandler">
<font-awesome-icon :icon="['fas', 'copy']" />
</button>
@ -63,7 +63,7 @@
<h2 class="title is-5 has-text-grey-light">
{{ $t('settings.user_options') }}
</h2>
<div class="box has-background-black-bis is-family-monospace is-size-7">
<div class="about-debug box is-family-monospace is-size-7">
<button :aria-label="$t('commons.copy_to_clipboard')" class="button is-like-text is-pulled-right is-small is-text" v-clipboard="() => this.$refs.listUserOptions.innerText" v-clipboard:success="clipboardSuccessHandler">
<font-awesome-icon :icon="['fas', 'copy']" />
</button>
@ -76,7 +76,7 @@
<vue-footer :showButtons="true">
<!-- close button -->
<p class="control">
<router-link :to="{ name: 'accounts', params: { toRefresh: true } }" role="button" :aria-label="$t('commons.close_the_x_page', {pagetitle: pagetitle})" class="button is-dark is-rounded">{{ $t('commons.close') }}</router-link>
<router-link :to="{ name: 'accounts', params: { toRefresh: true } }" role="button" :aria-label="$t('commons.close_the_x_page', {pagetitle: pagetitle})" class="button is-rounded" :class="{'is-dark' : $root.showDarkMode}">{{ $t('commons.close') }}</router-link>
</p>
</vue-footer>
</responsive-width-wrapper>

View File

@ -6,7 +6,7 @@
<div class="column is-one-third-tablet is-one-quarter-desktop is-one-quarter-widescreen is-one-quarter-fullhd">
<div class="columns is-multiline">
<div class="column is-full" v-for="group in groups" v-if="group.twofaccounts_count > 0" :key="group.id">
<button class="button is-fullwidth is-dark has-text-light is-outlined" @click="setActiveGroup(group.id)">{{ group.name }}</button>
<button class="button is-fullwidth" :class="{'is-dark has-text-light is-outlined':$root.showDarkMode}" @click="setActiveGroup(group.id)">{{ group.name }}</button>
</div>
</div>
<div class="columns is-centered">
@ -19,7 +19,7 @@
<vue-footer :showButtons="true">
<!-- Close Group switch button -->
<p class="control">
<button class="button is-dark is-rounded" @click="closeGroupSwitch()">{{ $t('commons.close') }}</button>
<button class="button is-rounded" :class="{'is-dark' : $root.showDarkMode}" @click="closeGroupSwitch()">{{ $t('commons.close') }}</button>
</p>
</vue-footer>
</div>
@ -32,7 +32,7 @@
<div class="column is-one-third-tablet is-one-quarter-desktop is-one-quarter-widescreen is-one-quarter-fullhd">
<div class="columns is-multiline">
<div class="column is-full" v-for="group in groups" :key="group.id">
<button class="button is-fullwidth is-dark has-text-light is-outlined" :class="{ 'is-link' : moveAccountsTo === group.id}" @click="moveAccountsTo = group.id">
<button class="button is-fullwidth" :class="{'is-link' : moveAccountsTo === group.id, 'is-dark has-text-light is-outlined':$root.showDarkMode}" @click="moveAccountsTo = group.id">
<span v-if="group.id === 0" class="is-italic">
{{ $t('groups.no_group') }}
</span>
@ -56,12 +56,12 @@
</p>
<!-- Cancel button -->
<p class="control">
<button class="button is-dark is-rounded" @click="showGroupSelector = false">{{ $t('commons.cancel') }}</button>
<button class="button is-rounded" :class="{'is-dark' : $root.showDarkMode}" @click="showGroupSelector = false">{{ $t('commons.cancel') }}</button>
</p>
</vue-footer>
</div>
<!-- header -->
<div class="header has-background-black-ter" v-if="this.showAccounts || this.showGroupSwitch">
<div class="header" v-if="this.showAccounts || this.showGroupSwitch">
<div class="columns is-gapless is-mobile is-centered">
<div class="column is-three-quarters-mobile is-one-third-tablet is-one-quarter-desktop is-one-quarter-widescreen is-one-quarter-fullhd">
<!-- search -->
@ -79,19 +79,19 @@
<div class="columns">
<div class="column">
<!-- selected label -->
<span class="mr-1">{{ selectedAccounts.length }}&nbsp;{{ $t('commons.selected') }}</span>
<span class="has-text-grey mr-1">{{ selectedAccounts.length }}&nbsp;{{ $t('commons.selected') }}</span>
<!-- deselect all -->
<button @click="clearSelected" class="clear-selection delete mr-4" :style="{visibility: selectedAccounts.length > 0 ? 'visible' : 'hidden'}" :title="$t('commons.clear_selection')"></button>
<!-- select all button -->
<button @click="selectAll" class="button mr-5 has-line-height p-1 is-ghost has-background-black-ter has-text-grey" :title="$t('commons.select_all')">
<button @click="selectAll" class="button mr-5 has-line-height p-1 is-ghost has-text-grey" :title="$t('commons.select_all')">
<span>{{ $t('commons.all') }}</span>
<font-awesome-icon class="ml-1" :icon="['fas', 'check-square']" />
</button>
<!-- sort asc/desc buttons -->
<button @click="sortAsc" class="button has-line-height p-1 is-ghost has-background-black-ter has-text-grey" :title="$t('commons.sort_ascending')">
<button @click="sortAsc" class="button has-line-height p-1 is-ghost has-text-grey" :title="$t('commons.sort_ascending')">
<font-awesome-icon :icon="['fas', 'sort-alpha-down']" />
</button>
<button @click="sortDesc" class="button has-line-height p-1 is-ghost has-background-black-ter has-text-grey" :title="$t('commons.sort_descending')">
<button @click="sortDesc" class="button has-line-height p-1 is-ghost has-text-grey" :title="$t('commons.sort_descending')">
<font-awesome-icon :icon="['fas', 'sort-alpha-up']" />
</button>
</div>
@ -101,13 +101,13 @@
<div v-else class="has-text-centered">
<div class="columns">
<div class="column" v-if="!showGroupSwitch">
<button :title="$t('groups.show_group_selector')" tabindex="1" class="button is-text is-like-text" @click.stop="toggleGroupSwitch">
<button :title="$t('groups.show_group_selector')" tabindex="1" class="button is-text is-like-text" :class="{'has-text-grey' : !$root.showDarkMode}" @click.stop="toggleGroupSwitch">
{{ activeGroupName }} ({{ filteredAccounts.length }})&nbsp;
<font-awesome-icon :icon="['fas', 'caret-down']" />
</button>
</div>
<div class="column" v-else>
<button :title="$t('groups.hide_group_selector')" tabindex="1" class="button is-text is-like-text" @click.stop="toggleGroupSwitch">
<button :title="$t('groups.hide_group_selector')" tabindex="1" class="button is-text is-like-text" :class="{'has-text-grey' : !$root.showDarkMode}" @click.stop="toggleGroupSwitch">
{{ $t('groups.select_accounts_to_show') }}
</button>
</div>
@ -131,12 +131,12 @@
}" > -->
<draggable v-model="filteredAccounts" @start="drag = true" @end="saveOrder" ghost-class="ghost" handle=".tfa-dots" animation="200" class="accounts">
<transition-group class="columns is-multiline" :class="{ 'is-centered': $root.appSettings.displayMode === 'grid' }" type="transition" :name="!drag ? 'flip-list' : null">
<div :class="[$root.appSettings.displayMode === 'grid' ? 'tfa-grid' : 'tfa-list']" class="column is-narrow has-text-white" v-for="account in filteredAccounts" :key="account.id">
<div :class="[$root.appSettings.displayMode === 'grid' ? 'tfa-grid' : 'tfa-list']" class="column is-narrow" v-for="account in filteredAccounts" :key="account.id">
<div class="tfa-container">
<transition name="slideCheckbox">
<div class="tfa-cell tfa-checkbox" v-if="editMode">
<div class="field">
<input class="is-checkradio is-small is-white" :id="'ckb_' + account.id" :value="account.id" type="checkbox" :name="'ckb_' + account.id" v-model="selectedAccounts">
<input class="is-checkradio is-small" :class="$root.showDarkMode ? 'is-white':'is-info'" :id="'ckb_' + account.id" :value="account.id" type="checkbox" :name="'ckb_' + account.id" v-model="selectedAccounts">
<label tabindex="0" :for="'ckb_' + account.id" v-on:keypress.space.prevent="selectAccount(account.id)"></label>
</div>
</div>
@ -151,10 +151,10 @@
<transition name="fadeInOut">
<div class="tfa-cell tfa-edit has-text-grey" v-if="editMode">
<!-- <div class="tags has-addons"> -->
<router-link :to="{ name: 'editAccount', params: { twofaccountId: account.id }}" class="tag is-dark is-rounded mr-1">
<router-link :to="{ name: 'editAccount', params: { twofaccountId: account.id }}" class="tag is-rounded mr-1" :class="$root.showDarkMode ? 'is-dark' : 'is-white'">
{{ $t('commons.edit') }}
</router-link>
<router-link :to="{ name: 'showQRcode', params: { twofaccountId: account.id }}" class="tag is-dark is-rounded" :title="$t('twofaccounts.show_qrcode')">
<router-link :to="{ name: 'showQRcode', params: { twofaccountId: account.id }}" class="tag is-rounded" :class="$root.showDarkMode ? 'is-dark' : 'is-white'" :title="$t('twofaccounts.show_qrcode')">
<font-awesome-icon :icon="['fas', 'qrcode']" />
</router-link>
<!-- </div> -->
@ -182,13 +182,13 @@
</p>
<!-- Manage button -->
<p class="control" v-if="!editMode">
<button class="button is-dark is-rounded" @click="setEditModeTo(true)">{{ $t('commons.manage') }}</button>
<button class="button is-rounded" :class="{'is-dark' : $root.showDarkMode}" @click="setEditModeTo(true)">{{ $t('commons.manage') }}</button>
</p>
<!-- move button -->
<p class="control" v-if="editMode">
<button
:disabled='selectedAccounts.length == 0' class="button is-outlined is-rounded"
:class="selectedAccounts.length > 0 ? 'is-link' : 'is-dark'"
:disabled='selectedAccounts.length == 0' class="button is-rounded"
:class="[{'is-outlined': $root.showDarkMode||selectedAccounts.length == 0}, selectedAccounts.length == 0 ? 'is-dark': 'is-link']"
@click="showGroupSelector = true"
:title="$t('groups.move_selected_to_group')" >
{{ $t('commons.move') }}
@ -197,8 +197,8 @@
<!-- delete button -->
<p class="control" v-if="editMode">
<button
:disabled='selectedAccounts.length == 0' class="button is-outlined is-rounded"
:class="selectedAccounts.length > 0 ? 'is-link' : 'is-dark'"
:disabled='selectedAccounts.length == 0' class="button is-rounded"
:class="[{'is-outlined': $root.showDarkMode||selectedAccounts.length == 0}, selectedAccounts.length == 0 ? 'is-dark': 'is-link']"
@click="destroyAccounts" >
{{ $t('commons.delete') }}
</button>
@ -206,8 +206,8 @@
<!-- export button -->
<p class="control" v-if="editMode">
<button
:disabled='selectedAccounts.length == 0' class="button is-outlined is-rounded"
:class="selectedAccounts.length > 0 ? 'is-link' : 'is-dark'"
:disabled='selectedAccounts.length == 0' class="button is-rounded"
:class="[{'is-outlined': $root.showDarkMode||selectedAccounts.length == 0}, selectedAccounts.length == 0 ? 'is-dark': 'is-link']"
@click="exportAccounts"
:title="$t('twofaccounts.export_selected_to_json')" >
{{ $t('commons.export') }}

View File

@ -5,13 +5,13 @@
<section class="section">
<div class="columns is-centered">
<div class="column is-three-quarters">
<div class="box has-text-centered has-background-black-ter is-shadowless">
<div class="modal-slot box has-text-centered is-shadowless">
<div v-if="errorText">
<p class="block is-size-5">{{ $t('twofaccounts.stream.live_scan_cant_start') }}</p>
<p class="has-text-light block">{{ $t('twofaccounts.stream.' + errorText + '.reason') }}</p>
<p class="block" :class="{'has-text-light': $root.showDarkMode}">{{ $t('twofaccounts.stream.' + errorText + '.reason') }}</p>
<p class="is-size-7">{{ $t('twofaccounts.stream.' + errorText + '.solution') }}</p>
</div>
<span v-else class="is-size-4 has-text-light">
<span v-else class="is-size-4" :class="$root.showDarkMode ? 'has-text-light':'has-text-grey-dark'">
<font-awesome-icon :icon="['fas', 'spinner']" size="2x" spin />
</span>
</div>

View File

@ -12,10 +12,10 @@
</router-link>
</div>
<div v-if="groups.length > 0">
<div v-for="group in groups" :key="group.id" class="group-item has-text-light is-size-5 is-size-6-mobile">
<div v-for="group in groups" :key="group.id" class="group-item is-size-5 is-size-6-mobile">
{{ group.name }}
<!-- delete icon -->
<button class="button tag is-dark is-pulled-right" @click="deleteGroup(group.id)" :title="$t('commons.delete')">
<button class="button tag is-pulled-right" :class="$root.showDarkMode ? 'is-dark' : 'is-white'" @click="deleteGroup(group.id)" :title="$t('commons.delete')">
{{ $t('commons.delete') }}
</button>
<!-- edit link -->
@ -37,7 +37,7 @@
<vue-footer :showButtons="true">
<!-- close button -->
<p class="control">
<router-link :to="{ name: 'accounts', params: { toRefresh: true } }" class="button is-dark is-rounded">{{ $t('commons.close') }}</router-link>
<router-link :to="{ name: 'accounts', params: { toRefresh: true } }" class="button is-rounded" :class="{'is-dark' : $root.showDarkMode}">{{ $t('commons.close') }}</router-link>
</p>
</vue-footer>
</responsive-width-wrapper>

View File

@ -23,7 +23,7 @@
</div>
<!-- alternative methods -->
<div class="column is-full">
<div class="block has-text-light">{{ $t('twofaccounts.forms.alternative_methods') }}</div>
<div class="block" :class="$root.showDarkMode ? 'has-text-light':'has-text-grey-dark'">{{ $t('twofaccounts.forms.alternative_methods') }}</div>
<!-- upload a qr code -->
<div class="block has-text-link" v-if="!$root.appSettings.useBasicQrcodeReader">
<label role="button" tabindex="0" class="button is-link is-outlined is-rounded" ref="qrcodeInputLabel" @keyup.enter="$refs.qrcodeInputLabel.click()">
@ -49,7 +49,7 @@
<vue-footer :showButtons="true" >
<!-- back button -->
<p class="control" v-if="accountCount > 0">
<router-link class="button is-dark is-rounded" :to="{ name: returnToView }" >
<router-link class="button is-rounded" :class="{'is-dark' : $root.showDarkMode}" :to="{ name: returnToView }" >
{{ $t('commons.back') }}
</router-link>
</p>

View File

@ -37,7 +37,7 @@
<vue-footer :showButtons="true">
<!-- Cancel button -->
<p class="control">
<button class="button is-dark is-rounded" @click.stop="exitSettings">
<button class="button is-rounded" :class="{'is-dark' : $root.showDarkMode}" @click.stop="exitSettings">
{{ $t('commons.close') }}
</button>
</p>

View File

@ -14,12 +14,12 @@
</a>
</div>
<div v-if="tokens.length > 0">
<div v-for="token in tokens" :key="token.id" class="group-item has-text-light is-size-5 is-size-6-mobile">
<div v-for="token in tokens" :key="token.id" class="group-item is-size-5 is-size-6-mobile">
<font-awesome-icon v-if="token.value" class="has-text-success" :icon="['fas', 'check']" /> {{ token.name }}
<!-- revoke link -->
<div class="tags is-pulled-right">
<button v-if="token.value" class="button tag" v-clipboard="() => token.value" v-clipboard:success="clipboardSuccessHandler">{{ $t('commons.copy') }}</button>
<button class="button tag is-dark " @click="revokeToken(token.id)" :title="$t('settings.revoke')">{{ $t('settings.revoke') }}</button>
<button v-if="token.value" class="button tag" :class="{'is-link': !$root.showDarkMode}" v-clipboard="() => token.value" v-clipboard:success="clipboardSuccessHandler">{{ $t('commons.copy') }}</button>
<button class="button tag" :class="$root.showDarkMode ? 'is-dark':'is-white'" @click="revokeToken(token.id)" :title="$t('settings.revoke')">{{ $t('settings.revoke') }}</button>
</div>
<!-- edit link -->
<!-- <router-link :to="{ name: 'settings.oauth.editPAT' }" class="has-text-grey pl-1" :title="$t('commons.edit')">
@ -47,7 +47,7 @@
<vue-footer :showButtons="true">
<!-- close button -->
<p class="control">
<router-link :to="{ name: 'accounts', params: { toRefresh: false } }" class="button is-dark is-rounded" tabindex="0">{{ $t('commons.close') }}</router-link>
<router-link :to="{ name: 'accounts', params: { toRefresh: false } }" class="button is-rounded" :class="{'is-dark' : $root.showDarkMode}" tabindex="0">{{ $t('commons.close') }}</router-link>
</p>
</vue-footer>
</form-wrapper>

View File

@ -20,6 +20,8 @@
</div>
<!-- display mode -->
<form-toggle v-on:displayMode="saveSetting('displayMode', $event)" :choices="layouts" :form="form" fieldName="displayMode" :label="$t('settings.forms.display_mode.label')" :help="$t('settings.forms.display_mode.help')" />
<!-- theme -->
<form-toggle v-on:theme="saveSetting('theme', $event)" :choices="themes" :form="form" fieldName="theme" :label="$t('settings.forms.theme.label')" :help="$t('settings.forms.theme.help')" />
<!-- show icon -->
<form-checkbox v-on:showAccountsIcons="saveSetting('showAccountsIcons', $event)" :form="form" fieldName="showAccountsIcons" :label="$t('settings.forms.show_accounts_icons.label')" :help="$t('settings.forms.show_accounts_icons.help')" />
<!-- Official icons -->
@ -56,7 +58,7 @@
<vue-footer :showButtons="true">
<!-- Cancel button -->
<p class="control">
<button class="button is-dark is-rounded" @click.stop="exitSettings">
<button class="button is-rounded" :class="{'is-dark' : $root.showDarkMode}" @click.stop="exitSettings">
{{ $t('commons.close') }}
</button>
</p>
@ -104,11 +106,17 @@
rememberActiveGroup: true,
getOfficialIcons: null,
checkForUpdate: null,
theme: 'dark',
}),
layouts: [
{ text: this.$t('settings.forms.grid'), value: 'grid', icon: 'th' },
{ text: this.$t('settings.forms.list'), value: 'list', icon: 'list' },
],
themes: [
{ text: this.$t('settings.forms.light'), value: 'light', icon: 'sun' },
{ text: this.$t('settings.forms.dark'), value: 'dark', icon: 'moon' },
{ text: this.$t('settings.forms.automatic'), value: 'system', icon: 'desktop' },
],
kickUserAfters: [
{ text: this.$t('settings.forms.never'), value: '0' },
{ text: this.$t('settings.forms.on_otp_copy'), value: '-1' },
@ -199,6 +207,10 @@
}
else {
this.$root.appSettings[response.data.key] = response.data.value
if(settingName === 'theme') {
this.setTheme(response.data.value)
}
}
})
},

View File

@ -15,10 +15,10 @@
</div>
<!-- credentials list -->
<div v-if="credentials.length > 0" class="field">
<div v-for="credential in credentials" :key="credential.id" class="group-item has-text-light is-size-5 is-size-6-mobile">
<div v-for="credential in credentials" :key="credential.id" class="group-item is-size-5 is-size-6-mobile">
{{ displayName(credential) }}
<!-- revoke link -->
<button class="button tag is-dark is-pulled-right" @click="revokeCredential(credential.id)" :title="$t('settings.revoke')">
<button class="button tag is-pulled-right" :class="$root.showDarkMode ? 'is-dark':'is-white'" @click="revokeCredential(credential.id)" :title="$t('settings.revoke')">
{{ $t('settings.revoke') }}
</button>
<!-- edit link -->
@ -49,7 +49,7 @@
<vue-footer :showButtons="true">
<!-- close button -->
<p class="control">
<router-link :to="{ name: 'accounts', params: { toRefresh: false } }" class="button is-dark is-rounded">{{ $t('commons.close') }}</router-link>
<router-link :to="{ name: 'accounts', params: { toRefresh: false } }" class="button is-rounded" :class="{'is-dark' : $root.showDarkMode}">{{ $t('commons.close') }}</router-link>
</p>
</vue-footer>
</form-wrapper>

View File

@ -66,7 +66,7 @@
<div class="field is-grouped">
<!-- i'm lucky button -->
<div class="control" v-if="$root.appSettings.getOfficialIcons">
<v-button @click="fetchLogo" :color="'is-dark'" :nativeType="'button'" :isDisabled="form.service.length < 1">
<v-button @click="fetchLogo" :color="$root.showDarkMode ? 'is-dark' : ''" :nativeType="'button'" :isDisabled="form.service.length < 1">
<span class="icon is-small">
<font-awesome-icon :icon="['fas', 'globe']" />
</span>
@ -75,7 +75,7 @@
</div>
<!-- upload button -->
<div class="control">
<div role="button" tabindex="0" class="file is-dark" @keyup.enter="$refs.iconInputLabel.click()">
<div role="button" tabindex="0" class="file" :class="$root.showDarkMode ? 'is-dark' : 'is-white'" @keyup.enter="$refs.iconInputLabel.click()">
<label class="file-label" ref="iconInputLabel">
<input aria-hidden="true" tabindex="-1" class="file-input" type="file" accept="image/*" v-on:change="uploadIcon" ref="iconInput">
<span class="file-cta">
@ -85,7 +85,7 @@
<span class="file-label">{{ $t('twofaccounts.forms.choose_image') }}</span>
</span>
</label>
<span class="tag is-black is-large" v-if="tempIcon">
<span class="tag is-large" :class="$root.showDarkMode ? 'is-dark' : 'is-white'" v-if="tempIcon">
<img class="icon-preview" :src="$root.appConfig.subdirectory + '/storage/icons/' + tempIcon" :alt="$t('twofaccounts.icon_to_illustrate_the_account')">
<button class="clear-selection delete is-small" @click.prevent="deleteIcon" :aria-label="$t('twofaccounts.remove_icon')"></button>
</span>
@ -149,7 +149,7 @@
<div class="block">
{{ $t('errors.data_of_qrcode_is_not_valid_URI') }}
</div>
<div class="block has-text-light mb-6" v-html="uri"></div>
<div class="block mb-6" :class="$root.showDarkMode ? 'has-text-light':'has-text-grey-dark'" v-html="uri"></div>
<!-- Copy to clipboard -->
<div class="block has-text-link">
<button class="button is-link is-outlined is-rounded" v-clipboard="() => uri" v-clipboard:success="clipboardSuccessHandler">

View File

@ -10,7 +10,7 @@
<div class="field is-grouped">
<!-- i'm lucky button -->
<div class="control" v-if="$root.appSettings.getOfficialIcons">
<v-button @click="fetchLogo" :color="'is-dark'" :nativeType="'button'" :isDisabled="form.service.length < 3">
<v-button @click="fetchLogo" :color="$root.showDarkMode ? 'is-dark' : ''" :nativeType="'button'" :isDisabled="form.service.length < 3">
<span class="icon is-small">
<font-awesome-icon :icon="['fas', 'globe']" />
</span>
@ -19,7 +19,7 @@
</div>
<!-- upload button -->
<div class="control">
<div role="button" tabindex="0" class="file is-dark" @keyup.enter="$refs.iconInputLabel.click()">
<div role="button" tabindex="0" class="file" :class="$root.showDarkMode ? 'is-dark' : 'is-white'" @keyup.enter="$refs.iconInputLabel.click()">
<label class="file-label" ref="iconInputLabel">
<input aria-hidden="true" tabindex="-1" class="file-input" type="file" accept="image/*" v-on:change="uploadIcon" ref="iconInput">
<span class="file-cta">
@ -29,7 +29,7 @@
<span class="file-label">{{ $t('twofaccounts.forms.choose_image') }}</span>
</span>
</label>
<span class="tag is-black is-large" v-if="tempIcon">
<span class="tag is-large" :class="$root.showDarkMode ? 'is-dark' : 'is-white'" v-if="tempIcon">
<img class="icon-preview" :src="$root.appConfig.subdirectory + '/storage/icons/' + tempIcon" :alt="$t('twofaccounts.icon_to_illustrate_the_account')">
<button class="clear-selection delete is-small" @click.prevent="deleteIcon" :aria-label="$t('twofaccounts.remove_icon')"></button>
</span>
@ -50,14 +50,14 @@
<input :id="this.inputId('text','secret')" class="input" type="text" v-model="form.secret" :disabled="secretIsLocked">
</p>
<p class="control" v-if="secretIsLocked">
<button type="button" class="button is-dark field-lock" @click.stop="secretIsLocked = false" :title="$t('twofaccounts.forms.unlock.title')">
<button type="button" class="button field-lock" :class="{'is-dark' : $root.showDarkMode}" @click.stop="secretIsLocked = false" :title="$t('twofaccounts.forms.unlock.title')">
<span class="icon">
<font-awesome-icon :icon="['fas', 'lock']" />
</span>
</button>
</p>
<p class="control" v-else>
<button type="button" class="button is-dark field-unlock" @click.stop="secretIsLocked = true" :title="$t('twofaccounts.forms.lock.title')">
<button type="button" class="button field-unlock" :class="{'is-dark' : $root.showDarkMode}" @click.stop="secretIsLocked = true" :title="$t('twofaccounts.forms.lock.title')">
<span class="icon has-text-danger">
<font-awesome-icon :icon="['fas', 'lock-open']" />
</span>
@ -89,14 +89,14 @@
<input class="input" type="text" placeholder="" v-model="form.counter" :disabled="counterIsLocked" />
</div>
<div class="control" v-if="counterIsLocked">
<button type="button" class="button is-dark field-lock" @click="counterIsLocked = false" :title="$t('twofaccounts.forms.unlock.title')">
<button type="button" class="button field-lock" :class="{'is-dark' : $root.showDarkMode}" @click="counterIsLocked = false" :title="$t('twofaccounts.forms.unlock.title')">
<span class="icon">
<font-awesome-icon :icon="['fas', 'lock']" />
</span>
</button>
</div>
<div class="control" v-else>
<button type="button" class="button is-dark field-unlock" @click="counterIsLocked = true" :title="$t('twofaccounts.forms.lock.title')">
<button type="button" class="button field-unlock" :class="{'is-dark' : $root.showDarkMode}" @click="counterIsLocked = true" :title="$t('twofaccounts.forms.lock.title')">
<span class="icon has-text-danger">
<font-awesome-icon :icon="['fas', 'lock-open']" />
</span>

View File

@ -39,43 +39,19 @@
<p class="help">{{ $t('twofaccounts.import.supported_formats_for_file_upload') }}</p>
</div>
<!-- Supported migration resources -->
<h5 class="title is-5 mb-3 has-text-grey-dark">{{ $t('twofaccounts.import.supported_migration_formats') }}</h5>
<h5 class="title is-6 mb-3 has-text-grey-dark">{{ $t('twofaccounts.import.supported_migration_formats') }}</h5>
<div class="field is-grouped is-grouped-multiline pt-0">
<div class="control">
<div v-for="(source, index) in supportedSources" :key="index" class="control">
<div class="tags has-addons">
<span class="tag is-dark">2FAuth</span>
<span class="tag is-black">JSON</span>
</div>
</div>
<div class="control">
<div class="tags has-addons">
<span class="tag is-dark">Google Auth</span>
<span class="tag is-black">{{ $t('twofaccounts.import.qr_code') }}</span>
</div>
</div>
<div class="control">
<div class="tags has-addons">
<span class="tag is-dark">Aegis Auth</span>
<span class="tag is-black">JSON</span>
</div>
</div>
<div class="control">
<div class="tags has-addons">
<span class="tag is-dark">Aegis Auth</span>
<span class="tag is-black">{{ $t('twofaccounts.import.plain_text') }}</span>
</div>
</div>
<div class="control">
<div class="tags has-addons">
<span class="tag is-dark">2FAS Auth</span>
<span class="tag is-black">JSON</span>
<span class="tag" :class="$root.showDarkMode ? 'is-dark' : 'is-white'">{{ source.app }}</span>
<span class="tag" :class="$root.showDarkMode ? 'is-black' : 'has-background-grey-lighter has-text-black'">{{ source.format }}</span>
</div>
</div>
</div>
<span class="is-size-7" v-html="$t('twofaccounts.import.do_not_set_password_or_encryption')"></span>
</div>
<div v-else>
<div v-for="(account, index) in exportedAccounts" :key="account.name" class="group-item has-text-light is-size-5 is-size-6-mobile">
<div v-for="(account, index) in exportedAccounts" :key="account.name" class="group-item is-size-5 is-size-6-mobile">
<div class="is-flex is-justify-content-space-between">
<!-- Account name -->
<div v-if="account.id > -2 && account.imported !== 0" class="is-flex-grow-1 has-ellipsis is-clickable" @click="previewAccount(index)" :title="$t('twofaccounts.import.generate_a_test_password')">
@ -86,7 +62,7 @@
<!-- buttons -->
<div v-if="account.imported === -1" class="tags is-flex-wrap-nowrap">
<!-- discard button -->
<button class="button tag is-dark has-text-grey-light" @click="discardAccount(index)" :title="$t('twofaccounts.import.discard_this_account')">
<button class="button tag" :class="{'is-dark has-text-grey-light' : $root.showDarkMode}" @click="discardAccount(index)" :title="$t('twofaccounts.import.discard_this_account')">
<font-awesome-icon :icon="['fas', 'trash']" />
</button>
<!-- import button -->
@ -148,7 +124,7 @@
</p>
<!-- close button -->
<p class="control">
<router-link :to="{ name: 'accounts', params: { toRefresh: true } }" class="button is-dark is-rounded" v-html="importableCount > 0 ? $t('commons.cancel') : $t('commons.close')"></router-link>
<router-link :to="{ name: 'accounts', params: { toRefresh: true } }" class="button is-rounded" :class="{'is-dark' : $root.showDarkMode}" v-html="importableCount > 0 ? $t('commons.cancel') : $t('commons.close')"></router-link>
</p>
</vue-footer>
</responsive-width-wrapper>
@ -184,6 +160,13 @@
}),
uploadForm: new Form(),
ShowTwofaccountInModal : false,
supportedSources: [
{app: '2FAuth', format: 'JSON'},
{app: 'Google Auth', format: this.$t('twofaccounts.import.qr_code')},
{app: 'Aegis Auth', format: 'JSON'},
{app: 'Aegis Auth', format: this.$t('twofaccounts.import.plain_text')},
{app: '2FAS auth', format: 'JSON'},
]
}
},

View File

@ -8,7 +8,7 @@
</div>
<div class="fullscreen-footer">
<!-- Close button -->
<button class="button is-dark is-rounded" @click.stop="$router.push({name: 'accounts', params: {initialEditMode: true}});">
<button class="button is-rounded" :class="{'is-dark' : $root.showDarkMode}" @click.stop="$router.push({name: 'accounts', params: {initialEditMode: true}});">
{{ $t('commons.close') }}
</button>
</div>