mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-19 11:15:21 +01:00
Merge branch 'master' of https://github.com/bitwarden/browser into add-login-with-locked-vault
This commit is contained in:
commit
2613a8cfea
2
jslib
2
jslib
@ -1 +1 @@
|
||||
Subproject commit 91b73fa77727a12c788c00eef4f32065c23b6314
|
||||
Subproject commit 64bc115109f40ac92b42af980024e36f90df6285
|
@ -1807,5 +1807,11 @@
|
||||
},
|
||||
"personalVaultExportPolicyInEffect": {
|
||||
"message": "One or more organization policies prevents you from exporting your personal vault."
|
||||
},
|
||||
"copyCustomFieldNameInvalidElement": {
|
||||
"message": "Unable to identify a valid form element. Try inspecting the HTML instead."
|
||||
},
|
||||
"copyCustomFieldNameNotUnique": {
|
||||
"message": "No unique identifier found."
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ export default class ContextMenusBackground {
|
||||
if (info.menuItemId === 'generate-password') {
|
||||
await this.generatePasswordToClipboard();
|
||||
} else if (info.menuItemId === 'copy-identifier') {
|
||||
await this.getClickedElement();
|
||||
await this.getClickedElement(info.frameId);
|
||||
} else if (info.parentMenuItemId === 'autofill' ||
|
||||
info.parentMenuItemId === 'copy-username' ||
|
||||
info.parentMenuItemId === 'copy-password' ||
|
||||
@ -47,13 +47,13 @@ export default class ContextMenusBackground {
|
||||
this.passwordGenerationService.addHistory(password);
|
||||
}
|
||||
|
||||
private async getClickedElement() {
|
||||
private async getClickedElement(frameId: number) {
|
||||
const tab = await BrowserApi.getTabFromCurrentWindow();
|
||||
if (tab == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
BrowserApi.tabSendMessageData(tab, 'getClickedElement');
|
||||
BrowserApi.tabSendMessage(tab, { command: 'getClickedElement' }, { frameId: frameId });
|
||||
}
|
||||
|
||||
private async cipherAction(info: any) {
|
||||
|
@ -147,7 +147,8 @@ export default class MainBackground {
|
||||
constructor() {
|
||||
// Services
|
||||
this.messagingService = new BrowserMessagingService();
|
||||
this.platformUtilsService = new BrowserPlatformUtilsService(this.messagingService,
|
||||
this.storageService = new BrowserStorageService();
|
||||
this.platformUtilsService = new BrowserPlatformUtilsService(this.messagingService, this.storageService,
|
||||
(clipboardValue, clearMs) => {
|
||||
if (this.systemService != null) {
|
||||
this.systemService.clearClipboard(clipboardValue, clearMs);
|
||||
@ -166,7 +167,6 @@ export default class MainBackground {
|
||||
return promise.then(result => result.response === 'unlocked');
|
||||
}
|
||||
});
|
||||
this.storageService = new BrowserStorageService();
|
||||
this.secureStorageService = new BrowserStorageService();
|
||||
this.i18nService = new I18nService(BrowserApi.getUILanguage(window));
|
||||
this.cryptoFunctionService = new WebCryptoFunctionService(window, this.platformUtilsService);
|
||||
|
@ -26,6 +26,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
span[data-bwautofill].com-bitwarden-browser-animated-fill {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.com-bitwarden-browser-animated-fill {
|
||||
animation: bitwardenfill 200ms ease-in-out 0ms 1;
|
||||
-webkit-animation: bitwardenfill 200ms ease-in-out 0ms 1;
|
||||
|
@ -38,6 +38,7 @@
|
||||
5. Remove fakeTested prop.
|
||||
6. Rename com.agilebits.* stuff to com.bitwarden.*
|
||||
7. Remove "some useful globals" on window
|
||||
8. Add ability to autofill span[data-bwautofill] elements
|
||||
*/
|
||||
|
||||
function collect(document, undefined) {
|
||||
@ -103,6 +104,11 @@
|
||||
return el;
|
||||
|
||||
default:
|
||||
// START MODIFICATION
|
||||
if (!el.type && el.tagName.toLowerCase() === 'span') {
|
||||
return el.innerText;
|
||||
}
|
||||
// END MODIFICATION
|
||||
return el.value;
|
||||
}
|
||||
}
|
||||
@ -268,8 +274,16 @@
|
||||
addProp(field, 'htmlClass', getElementAttrValue(el, 'class'));
|
||||
addProp(field, 'tabindex', getElementAttrValue(el, 'tabindex'));
|
||||
addProp(field, 'title', getElementAttrValue(el, 'title'));
|
||||
|
||||
// START MODIFICATION
|
||||
addProp(field, 'userEdited', !!el.dataset['com.browser.browser.userEdited']);
|
||||
|
||||
var elTagName = el.tagName.toLowerCase();
|
||||
addProp(field, 'tagName', elTagName);
|
||||
|
||||
if (elTagName === 'span') {
|
||||
return field;
|
||||
}
|
||||
// END MODIFICATION
|
||||
|
||||
if ('hidden' != toLowerString(el.type)) {
|
||||
@ -555,7 +569,8 @@
|
||||
var els = [];
|
||||
try {
|
||||
var elsList = theDoc.querySelectorAll('input:not([type="hidden"]):not([type="submit"]):not([type="reset"])' +
|
||||
':not([type="button"]):not([type="image"]):not([type="file"]):not([data-bwignore]), select');
|
||||
':not([type="button"]):not([type="image"]):not([type="file"]):not([data-bwignore]), select, ' +
|
||||
'span[data-bwautofill]');
|
||||
els = Array.prototype.slice.call(elsList);
|
||||
} catch (e) { }
|
||||
|
||||
@ -809,6 +824,12 @@
|
||||
break;
|
||||
default:
|
||||
el.value == op || doAllFillOperations(el, function (theEl) {
|
||||
// START MODIFICATION
|
||||
if (!theEl.type && theEl.tagName.toLowerCase() === 'span') {
|
||||
theEl.innerText = op;
|
||||
return;
|
||||
}
|
||||
// END MODIFICATION
|
||||
theEl.value = op;
|
||||
});
|
||||
}
|
||||
@ -932,6 +953,11 @@
|
||||
currentEl = currentEl === document;
|
||||
}
|
||||
}
|
||||
// START MODIFICATION
|
||||
if (el && !el.type && el.tagName.toLowerCase() === 'span') {
|
||||
return true;
|
||||
}
|
||||
// END MODIFICATION
|
||||
return currentEl ? -1 !== 'email text password number tel url'.split(' ').indexOf(el.type || '') : false;
|
||||
}
|
||||
|
||||
@ -942,7 +968,10 @@
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
var elements = Array.prototype.slice.call(selectAllFromDoc('input, select, button'));
|
||||
// START MODIFICATION
|
||||
var elements = Array.prototype.slice.call(selectAllFromDoc('input, select, button, ' +
|
||||
'span[data-bwautofill]'));
|
||||
// END MODIFICATION
|
||||
var filteredElements = elements.filter(function (o) {
|
||||
return o.opid == theOpId;
|
||||
});
|
||||
|
@ -1,25 +1,46 @@
|
||||
const inputTags = ['input', 'textarea', 'select'];
|
||||
const labelTags = ['label', 'span'];
|
||||
const attributes = ['id', 'name', 'label-aria', 'placeholder'];
|
||||
const invalidElement = chrome.i18n.getMessage('copyCustomFieldNameInvalidElement');
|
||||
const noUniqueIdentifier = chrome.i18n.getMessage('copyCustomFieldNameNotUnique');
|
||||
|
||||
let clickedEl: HTMLElement = null;
|
||||
|
||||
// Find the best attribute to be used as the Name for an element in a custom field.
|
||||
function getClickedElementIdentifier() {
|
||||
if (clickedEl == null) {
|
||||
return 'Unable to identify clicked element.';
|
||||
return invalidElement;
|
||||
}
|
||||
|
||||
if (!inputTags.includes(clickedEl.nodeName.toLowerCase())) {
|
||||
return 'Invalid element type.';
|
||||
const clickedTag = clickedEl.nodeName.toLowerCase();
|
||||
let inputEl = null;
|
||||
|
||||
// Try to identify the input element (which may not be the clicked element)
|
||||
if (labelTags.includes(clickedTag)) {
|
||||
let inputId = null;
|
||||
if (clickedTag === 'label') {
|
||||
inputId = clickedEl.getAttribute('for');
|
||||
} else {
|
||||
inputId = clickedEl.closest('label')?.getAttribute('for');
|
||||
}
|
||||
|
||||
inputEl = document.getElementById(inputId);
|
||||
} else {
|
||||
inputEl = clickedEl;
|
||||
}
|
||||
|
||||
if (inputEl == null || !inputTags.includes(inputEl.nodeName.toLowerCase())) {
|
||||
return invalidElement;
|
||||
}
|
||||
|
||||
for (const attr of attributes) {
|
||||
const attributeValue = clickedEl.getAttribute(attr);
|
||||
const attributeValue = inputEl.getAttribute(attr);
|
||||
const selector = '[' + attr + '="' + attributeValue + '"]';
|
||||
if (!isNullOrEmpty(attributeValue) && document.querySelectorAll(selector)?.length === 1) {
|
||||
return attributeValue;
|
||||
}
|
||||
}
|
||||
return 'No unique identifier found.';
|
||||
return noUniqueIdentifier;
|
||||
}
|
||||
|
||||
function isNullOrEmpty(s: string) {
|
||||
|
@ -21,4 +21,5 @@ export default class AutofillField {
|
||||
autoCompleteType: string;
|
||||
selectInfo: any;
|
||||
maxLength: number;
|
||||
tagName: string;
|
||||
}
|
||||
|
@ -16,10 +16,16 @@
|
||||
</div>
|
||||
<div id="content"></div>
|
||||
<div>
|
||||
<<<<<<< HEAD
|
||||
<a href="#" id="close-button">
|
||||
<img id="close" alt="X"
|
||||
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeBAMAAADJHrORAAAAAXNSR0IB2cksfwAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAABJQTFRFAAAAMzMzMzMzMzMzMzMzMzMzbxxq5QAAAAZ0Uk5TAECg/2CfwOuXQgAAAJVJREFUeJxVkdEJwzAMRNXgAQpZINAu0Fz7b3AHyP7T1MrppNQfMuI9sE42s7vp3Lws7+zHMcsDPdqGz8SAhAEctgIhNDhiDYyNVw+8p5ZYgrCExBS+iSmgMIXCEhJTKMy+Yobf//BF0Hv9gp8lcPKRAifPPSiYBAULoXJTWHNyJy/f917vbv4fCtZOslSwcZLKMf/zB2MLKtNp5GuwAAAAAElFTkSuQmCC" />
|
||||
</a>
|
||||
=======
|
||||
<button type="button" class="neutral" id="close-button">
|
||||
<img id="close" alt="X" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeBAMAAADJHrORAAAAAXNSR0IB2cksfwAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAABJQTFRFAAAAMzMzMzMzMzMzMzMzMzMzbxxq5QAAAAZ0Uk5TAECg/2CfwOuXQgAAAJVJREFUeJxVkdEJwzAMRNXgAQpZINAu0Fz7b3AHyP7T1MrppNQfMuI9sE42s7vp3Lws7+zHMcsDPdqGz8SAhAEctgIhNDhiDYyNVw+8p5ZYgrCExBS+iSmgMIXCEhJTKMy+Yobf//BF0Hv9gp8lcPKRAifPPSiYBAULoXJTWHNyJy/f917vbv4fCtZOslSwcZLKMf/zB2MLKtNp5GuwAAAAAElFTkSuQmCC" />
|
||||
</button>
|
||||
>>>>>>> a3876db30bdfb5ac42bda44ec02a728a52ae149c
|
||||
</div>
|
||||
</div>
|
||||
<div id="templates" style="display: none;">
|
||||
|
@ -135,12 +135,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
});
|
||||
|
||||
sendPlatformMessage({
|
||||
command: 'bgAdjustNotificationBar',
|
||||
data: {
|
||||
height: body.scrollHeight
|
||||
}
|
||||
});
|
||||
window.addEventListener("resize", adjustHeight);
|
||||
adjustHeight();
|
||||
}
|
||||
|
||||
function getQueryVariable(variable) {
|
||||
@ -180,4 +176,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
select.appendChild(new Option(folder.name, folder.id || '', false));
|
||||
});
|
||||
}
|
||||
|
||||
function adjustHeight() {
|
||||
sendPlatformMessage({
|
||||
command: 'bgAdjustNotificationBar',
|
||||
data: {
|
||||
height: document.querySelector('body').scrollHeight
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -13,29 +13,19 @@
|
||||
padding: 0 10px;
|
||||
border-bottom: 2px solid #175ddc;
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto 1fr;
|
||||
column-gap: 10px;
|
||||
grid-template-columns: 24px auto 55px;
|
||||
grid-column-gap: 10px;
|
||||
box-sizing: border-box;
|
||||
height: 42px;
|
||||
}
|
||||
|
||||
.outer-wrapper > * {
|
||||
align-self: center;
|
||||
min-height: 42px;
|
||||
}
|
||||
|
||||
.inner-wrapper {
|
||||
display: grid;
|
||||
grid-template-columns: 2fr 1fr;
|
||||
column-gap: 10px;
|
||||
grid-column-gap: 10px;
|
||||
grid-template-columns: auto max-content;
|
||||
}
|
||||
|
||||
#content .change-buttons {
|
||||
justify-self: end;
|
||||
}
|
||||
|
||||
.wrapper > *, .inner-wrapper > * {
|
||||
.outer-wrapper > *, .inner-wrapper > * {
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
@ -59,41 +49,32 @@ img {
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
button:not(.link) {
|
||||
button:not(.link),
|
||||
button:not(.neutral) {
|
||||
background-color: #175DDC;
|
||||
padding: 5px 15px;
|
||||
border-radius: 3px;
|
||||
color: #ffffff;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
button:not(.link):hover {
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background-color: #1751bd;
|
||||
}
|
||||
}
|
||||
|
||||
button.link {
|
||||
button.link,
|
||||
button.neutral {
|
||||
background: none;
|
||||
padding: 5px 15px;
|
||||
color: #175DDC;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
button.link:hover {
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
background: none;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
body[class*='lang-en'] .add-buttons {
|
||||
width: 175px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
body[class*='lang-en'] .add-buttons {
|
||||
width: 420px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (print) {
|
||||
|
@ -3,9 +3,9 @@
|
||||
<div class="logo-image"></div>
|
||||
<p class="lead text-center">{{'loginOrCreateNewAccount' | i18n}}</p>
|
||||
<a class="btn primary block" routerLink="/login"><b>{{'login' | i18n}}</b></a>
|
||||
<a (click)="launchSsoBrowser()" class="btn block">
|
||||
<button type="button" (click)="launchSsoBrowser()" class="btn block">
|
||||
<i class="fa fa-bank" aria-hidden="true"></i> {{'enterpriseSingleSignOn' | i18n}}
|
||||
</a>
|
||||
</button>
|
||||
<a class="btn block" routerLink="/register">{{'createAccount' | i18n}}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -23,11 +23,11 @@
|
||||
class="monospaced" [(ngModel)]="masterPassword" required appInputVerbatim>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword()">
|
||||
<i class="fa fa-lg" [ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"
|
||||
aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -38,11 +38,11 @@
|
||||
</div>
|
||||
<div class="box" *ngIf="biometricLock">
|
||||
<div class="box-footer">
|
||||
<button class="btn primary block" (click)="unlockBiometric()" appStopClick>{{'unlockWithBiometrics' | i18n}}</button>
|
||||
<button type="button" class="btn primary block" (click)="unlockBiometric()" appStopClick>{{'unlockWithBiometrics' | i18n}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-center">
|
||||
<a href="#" appStopClick (click)="logOut()">{{'logOut' | i18n}}</a>
|
||||
<button type="button" appStopClick (click)="logOut()">{{'logOut' | i18n}}</button>
|
||||
</p>
|
||||
</content>
|
||||
</form>
|
||||
|
@ -28,11 +28,11 @@
|
||||
class="monospaced" [(ngModel)]="masterPassword" required appInputVerbatim>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword()">
|
||||
<i class="fa fa-lg" [ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"
|
||||
aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-row" [hidden]="!showCaptcha()">
|
||||
|
@ -36,11 +36,11 @@
|
||||
[appAutofocus]="email !== ''" appInputVerbatim (input)="updatePasswordStrength()">
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(false)">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
@ -64,11 +64,11 @@
|
||||
appInputVerbatim>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(true)">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
|
@ -43,11 +43,11 @@
|
||||
(input)="updatePasswordStrength()" appInputVerbatim>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick role="button"
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick role="button"
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(false)">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
@ -74,11 +74,11 @@
|
||||
autocomplete="new-password">
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick role="button"
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick role="button"
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(true)">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -10,14 +10,14 @@
|
||||
<content>
|
||||
<div class="box">
|
||||
<div class="box-content">
|
||||
<a href="#" appStopClick *ngFor="let p of providers" class="box-content-row" (click)="choose(p)">
|
||||
<button type="button" appStopClick *ngFor="let p of providers" class="box-content-row" (click)="choose(p)">
|
||||
<span class="text">{{p.name}}</span>
|
||||
<span class="detail">{{p.description}}</span>
|
||||
</a>
|
||||
<a href="#" appStopClick class="box-content-row" (click)="recover()">
|
||||
</button>
|
||||
<button type="button" appStopClick class="box-content-row" (click)="recover()">
|
||||
<span class="text">{{'recoveryCodeTitle' | i18n}}</span>
|
||||
<span class="detail">{{'recoveryCodeDesc' | i18n}}</span>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
|
@ -73,7 +73,7 @@
|
||||
<ng-container *ngIf="selectedProviderType === providerType.WebAuthn && webAuthnNewTab">
|
||||
<div class="content text-center" *ngIf="webAuthnNewTab">
|
||||
<p class="text-center">{{'webAuthnNewTab' | i18n}}</p>
|
||||
<button class="btn primary block" (click)="authWebAuthn()" appStopClick>{{'webAuthnNewTabOpen' | i18n}}</button>
|
||||
<button type="button" class="btn primary block" (click)="authWebAuthn()" appStopClick>{{'webAuthnNewTabOpen' | i18n}}</button>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="selectedProviderType === providerType.Duo ||
|
||||
@ -94,12 +94,12 @@
|
||||
</div>
|
||||
<div class="content no-vpad" *ngIf="selectedProviderType != null">
|
||||
<p class="text-center">
|
||||
<a href="#" appStopClick (click)="anotherMethod()">{{'useAnotherTwoStepMethod' | i18n}}</a>
|
||||
<button type="button" appStopClick (click)="anotherMethod()">{{'useAnotherTwoStepMethod' | i18n}}</button>
|
||||
</p>
|
||||
<p *ngIf="selectedProviderType === providerType.Email" class="text-center">
|
||||
<a href="#" appStopClick (click)="sendEmail(true)" [appApiAction]="emailPromise">
|
||||
<button type="button" appStopClick (click)="sendEmail(true)" [appApiAction]="emailPromise">
|
||||
{{'sendVerificationCodeEmailAgain' | i18n}}
|
||||
</a>
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
</content>
|
||||
|
@ -36,11 +36,11 @@
|
||||
appInputVerbatim (input)="updatePasswordStrength()">
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick
|
||||
<button class="row-btn" appStopClick appBlurClick
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(false)">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
@ -62,11 +62,11 @@
|
||||
appInputVerbatim>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick
|
||||
<button class="row-btn" appStopClick appBlurClick
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword(true)">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<a (click)="selectCipher(cipher)" (dblclick)="launchCipher(cipher)" href="#" appStopClick
|
||||
<button (click)="selectCipher(cipher)" (dblclick)="launchCipher(cipher)" appStopClick
|
||||
title="{{title}} - {{cipher.name}}" class="box-content-row box-content-row-flex virtual-scroll-item">
|
||||
<div class="row-main">
|
||||
<app-vault-icon [cipher]="cipher"></app-vault-icon>
|
||||
@ -20,4 +20,4 @@
|
||||
<app-action-buttons [cipher]="cipher" [showView]="showView" (onView)="viewCipher(cipher)" (launchEvent)="launchCipher(cipher)"
|
||||
class="action-buttons">
|
||||
</app-action-buttons>
|
||||
</a>
|
||||
</button>
|
||||
|
@ -12,11 +12,11 @@
|
||||
class="monospaced" [(ngModel)]="masterPassword" required appAutofocus>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick role="button"
|
||||
<button class="row-btn" appStopClick appBlurClick role="button"
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword()">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<ng-container>
|
||||
<button (click)="expand()" appA11yTitle="{{'popOutNewWindow' | i18n}}">
|
||||
<button type="button" (click)="expand()" appA11yTitle="{{'popOutNewWindow' | i18n}}">
|
||||
<i class="fa fa-external-link fa-rotate-270 fa-lg fa-fw" aria-hidden="true"></i>
|
||||
</button>
|
||||
</ng-container>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<a *ngFor="let s of sends" (click)="selectSend(s)" href="#" appStopClick title="{{title}} - {{s.name}}"
|
||||
<button type="button" *ngFor="let s of sends" (click)="selectSend(s)" appStopClick title="{{title}} - {{s.name}}"
|
||||
class="box-content-row box-content-row-flex">
|
||||
<div class="row-main">
|
||||
<div class="app-vault-icon">
|
||||
@ -47,4 +47,4 @@
|
||||
<i class="fa fa-lg fa-trash-o" aria-hidden="true"></i>
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
</button>
|
||||
|
@ -14,11 +14,11 @@
|
||||
class="monospaced" [(ngModel)]="pin" required appInputVerbatim cdkFocusInitial>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick appA11yTitle="{{'toggleVisibility' | i18n}}"
|
||||
<button class="row-btn" appStopClick appBlurClick appA11yTitle="{{'toggleVisibility' | i18n}}"
|
||||
(click)="toggleVisibility()">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPin, 'fa-eye-slash': showPin}"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<header>
|
||||
<div class="left">
|
||||
<button appBlurClick type="button" (click)="close()">
|
||||
<button type="button" appBlurClick type="button" (click)="close()">
|
||||
<span class="header-icon" aria-hidden="true"><i class="fa fa-chevron-left"></i></span>
|
||||
<span>{{'back' | i18n}}</span>
|
||||
</button>
|
||||
@ -9,7 +9,7 @@
|
||||
<span class="title">{{'passwordHistory' | i18n}}</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<button appBlurClick type="button" (click)="clear()">
|
||||
<button type="button" appBlurClick type="button" (click)="clear()">
|
||||
{{'clear' | i18n}}
|
||||
</button>
|
||||
</div>
|
||||
@ -26,10 +26,10 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appA11yTitle="{{'copyPassword' | i18n}}"
|
||||
<button type="button" class="row-btn" appStopClick appA11yTitle="{{'copyPassword' | i18n}}"
|
||||
(click)="copy(h.password)">
|
||||
<i class="fa fa-lg fa-clone" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -19,10 +19,10 @@
|
||||
</div>
|
||||
<div class="box list">
|
||||
<div class="box-content single-line">
|
||||
<a class="box-content-row text-primary" href="#" appStopClick appBlurClick
|
||||
(click)="regenerate()">{{'regeneratePassword' | i18n}}</a>
|
||||
<a class="box-content-row text-primary" href="#" appStopClick appBlurClick
|
||||
(click)="copy()">{{'copyPassword' | i18n}}</a>
|
||||
<button type="button" class="box-content-row text-primary" appStopClick appBlurClick
|
||||
(click)="regenerate()">{{'regeneratePassword' | i18n}}</button>
|
||||
<button type="button" class="box-content-row text-primary" appStopClick appBlurClick
|
||||
(click)="copy()">{{'copyPassword' | i18n}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box list">
|
||||
|
@ -307,7 +307,8 @@
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
> a {
|
||||
> a,
|
||||
> button {
|
||||
padding: 8px 8px 8px 4px;
|
||||
margin: 0;
|
||||
|
||||
@ -322,6 +323,12 @@
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
&.box-content-row-newmulti {
|
||||
@include themify($themes) {
|
||||
color: themed('primaryColor');
|
||||
}
|
||||
}
|
||||
|
||||
&.box-content-row-checkbox, &.box-content-row-input, &.box-content-row-slider {
|
||||
label, .row-label {
|
||||
font-size: $font-size-base;
|
||||
@ -518,7 +525,6 @@
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-width: 34px;
|
||||
height: 100%;
|
||||
margin-left: -5px;
|
||||
|
||||
@include themify($themes) {
|
||||
|
@ -69,7 +69,8 @@
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&.link {
|
||||
&.link,
|
||||
&.neutral {
|
||||
border: none !important;
|
||||
background: none !important;
|
||||
|
||||
@ -86,3 +87,15 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button.box-content-row {
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
button {
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
}
|
@ -50,20 +50,24 @@ app-home {
|
||||
color: themed('mutedColor');
|
||||
}
|
||||
|
||||
span {
|
||||
visibility: hidden;
|
||||
&:not(:hover):not(:focus) {
|
||||
span {
|
||||
clip: rect(0 0 0 0);
|
||||
clip-path: inset(50%);
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
width: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
&:hover, &:focus {
|
||||
text-decoration: none;
|
||||
|
||||
@include themify($themes) {
|
||||
color: themed('primaryColor');
|
||||
}
|
||||
|
||||
span {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,9 +46,9 @@
|
||||
<div class="box-content-row" *ngIf="editMode" appBoxRow>
|
||||
<div class="flex-label">
|
||||
<label>{{'expirationDate' | i18n}}</label>
|
||||
<a *ngIf="!disabled" href="#" appStopClick (click)="clearExpiration()">
|
||||
<button type="button" *ngIf="!disabled" appStopClick (click)="clearExpiration()">
|
||||
{{'clear' | i18n}}
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
<ng-container *ngTemplateOutlet="expirationDateCustom"></ng-container>
|
||||
</div>
|
||||
|
@ -155,11 +155,11 @@
|
||||
class="monospaced" [(ngModel)]="password" appInputVerbatim [readonly]="disableSend">
|
||||
</div>
|
||||
<div class="action-buttons" *ngIf="!disableSend">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePasswordVisible()">
|
||||
<i class="fa fa-lg" [ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"
|
||||
aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -204,7 +204,7 @@
|
||||
<!-- Delete -->
|
||||
<div class="box list" *ngIf="editMode">
|
||||
<div class="box-content single-line">
|
||||
<a class="box-content-row" href="#" appStopClick appBlurClick (click)="delete()"
|
||||
<button type="button" class="box-content-row" appStopClick appBlurClick (click)="delete()"
|
||||
[appApiAction]="deletePromise" #deleteBtn>
|
||||
<div class="row-main text-danger">
|
||||
<div class="icon text-danger" aria-hidden="true">
|
||||
@ -213,7 +213,7 @@
|
||||
</div>
|
||||
<span>{{'deleteSend' | i18n}}</span>
|
||||
</div>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
|
@ -8,7 +8,7 @@
|
||||
<i class="fa fa-search"></i>
|
||||
</div>
|
||||
<div class="right">
|
||||
<button appBlurClick (click)="addSend()" appA11yTitle="{{'addSend' | i18n}}" [disabled]="disableSend">
|
||||
<button type="button" appBlurClick (click)="addSend()" appA11yTitle="{{'addSend' | i18n}}" [disabled]="disableSend">
|
||||
<i class="fa fa-plus fa-lg fa-fw" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
@ -22,7 +22,7 @@
|
||||
<ng-container *ngIf="loaded">
|
||||
<i class="fa fa-frown-o fa-4x"></i>
|
||||
<p>{{'noItemsInList' | i18n}}</p>
|
||||
<button (click)="addSend()" class="btn block primary link"
|
||||
<button type="button" (click)="addSend()" class="btn block primary link"
|
||||
[disabled]="disableSend">{{'addSend' | i18n}}</button>
|
||||
</ng-container>
|
||||
</div>
|
||||
@ -32,22 +32,22 @@
|
||||
{{'types' | i18n}}
|
||||
</div>
|
||||
<div class="box-content single-line">
|
||||
<a href="#" class="box-content-row" appStopClick appBlurClick (click)="selectType(sendType.Text)">
|
||||
<button type="button" class="box-content-row" appStopClick appBlurClick (click)="selectType(sendType.Text)">
|
||||
<div class="row-main">
|
||||
<div class="icon"><i class="fa fa-fw fa-lg fa-file-text-o"></i></div>
|
||||
<span class="text">{{'sendTypeText' | i18n}}</span>
|
||||
</div>
|
||||
<span class="row-sub-label">{{typeCounts.get(sendType.Text) || 0}}</span>
|
||||
<span><i class="fa fa-chevron-right fa-lg row-sub-icon"></i></span>
|
||||
</a>
|
||||
<a href="#" class="box-content-row" appStopClick appBlurClick (click)="selectType(sendType.File)">
|
||||
</button>
|
||||
<button type="button" class="box-content-row" appStopClick appBlurClick (click)="selectType(sendType.File)">
|
||||
<div class="row-main">
|
||||
<div class="icon"><i class="fa fa-fw fa-lg fa-file-o"></i></div>
|
||||
<span class="text">{{'sendTypeFile' | i18n}}</span>
|
||||
</div>
|
||||
<span class="row-sub-label">{{typeCounts.get(sendType.File) || 0}}</span>
|
||||
<span><i class="fa fa-chevron-right fa-lg row-sub-icon"></i></span>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box list">
|
||||
|
@ -11,7 +11,7 @@
|
||||
<i class="fa fa-search"></i>
|
||||
</div>
|
||||
<div class="right">
|
||||
<button appBlurClick (click)="addSend()" appA11yTitle="{{'addSend' | i18n}}" [disabled]="disableSend">
|
||||
<button type="button" appBlurClick (click)="addSend()" appA11yTitle="{{'addSend' | i18n}}" [disabled]="disableSend">
|
||||
<i class="fa fa-plus fa-lg fa-fw" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
@ -24,7 +24,7 @@
|
||||
<i class="fa fa-spinner fa-spin fa-3x" *ngIf="!loaded" aria-hidden="true"></i>
|
||||
<ng-container *ngIf="loaded">
|
||||
<p>{{'noItemsInList' | i18n}}</p>
|
||||
<button (click)="addSend()" class="btn block primary link" [disabled]="disableSend">
|
||||
<button type="button" (click)="addSend()" class="btn block primary link" [disabled]="disableSend">
|
||||
{{'addSend' | i18n}}
|
||||
</button>
|
||||
</ng-container>
|
||||
|
@ -63,6 +63,8 @@ import { StateService } from 'jslib-common/services/state.service';
|
||||
import { PopupSearchService } from './popup-search.service';
|
||||
import { PopupUtilsService } from './popup-utils.service';
|
||||
|
||||
import { ThemeType } from 'jslib-common/enums/themeType';
|
||||
|
||||
function getBgService<T>(service: string) {
|
||||
return (): T => {
|
||||
const page = BrowserApi.getBackgroundPage();
|
||||
@ -96,17 +98,17 @@ export function initFactory(platformUtilsService: PlatformUtilsService, i18nServ
|
||||
await stateService.save(ConstantsService.disableBadgeCounterKey,
|
||||
await storageService.get<boolean>(ConstantsService.disableBadgeCounterKey));
|
||||
|
||||
let theme = await storageService.get<string>(ConstantsService.themeKey);
|
||||
if (theme == null) {
|
||||
theme = await platformUtilsService.getDefaultSystemTheme();
|
||||
|
||||
platformUtilsService.onDefaultSystemThemeChange(sysTheme => {
|
||||
window.document.documentElement.classList.remove('theme_light', 'theme_dark');
|
||||
window.document.documentElement.classList.add('theme_' + sysTheme);
|
||||
});
|
||||
}
|
||||
window.document.documentElement.classList.add('locale_' + i18nService.translationLocale);
|
||||
window.document.documentElement.classList.add('theme_' + theme);
|
||||
const htmlEl = window.document.documentElement;
|
||||
const theme = await platformUtilsService.getEffectiveTheme();
|
||||
htmlEl.classList.add('theme_' + theme);
|
||||
platformUtilsService.onDefaultSystemThemeChange(async sysTheme => {
|
||||
const bwTheme = await storageService.get<ThemeType>(ConstantsService.themeKey);
|
||||
if (bwTheme == null || bwTheme === ThemeType.System) {
|
||||
htmlEl.classList.remove('theme_' + ThemeType.Light, 'theme_' + ThemeType.Dark);
|
||||
htmlEl.classList.add('theme_' + sysTheme);
|
||||
}
|
||||
});
|
||||
htmlEl.classList.add('locale_' + i18nService.translationLocale);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -16,9 +16,9 @@
|
||||
<ng-container *ngIf="excludedDomains">
|
||||
<div class="box-content-row box-content-row-multi" appBoxRow
|
||||
*ngFor="let domain of excludedDomains; let i = index; trackBy:trackByFunction">
|
||||
<a href="#" appStopClick (click)="removeUri(i)" appA11yTitle="{{'remove' | i18n}}">
|
||||
<button type="button" appStopClick (click)="removeUri(i)" appA11yTitle="{{'remove' | i18n}}">
|
||||
<i class="fa fa-minus-circle fa-lg" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
<div class="row-main">
|
||||
<label for="excludedDomain{{i}}">{{'uriPosition' | i18n : (i + 1)}}</label>
|
||||
<input id="excludedDomain{{i}}" name="excludedDomain{{i}}" type="text" [(ngModel)]="domain.uri"
|
||||
@ -33,17 +33,17 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a *ngIf="currentUris && currentUris.length" class="row-btn" href="#" appStopClick
|
||||
<button type="button" *ngIf="currentUris && currentUris.length" class="row-btn" appStopClick
|
||||
appBlurClick appA11yTitle="{{'toggleCurrentUris' | i18n}}" (click)="toggleUriInput(domain)">
|
||||
<i aria-hidden="true" class="fa fa-lg fa-list"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<a href="#" appStopClick appBlurClick (click)="addUri()"
|
||||
<button type="button" appStopClick appBlurClick (click)="addUri()"
|
||||
class="box-content-row box-content-row-newmulti">
|
||||
<i class="fa fa-plus-circle fa-fw fa-lg" aria-hidden="true"></i> {{'newUri' | i18n}}
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{{'excludedDomainsDesc' | i18n}}
|
||||
|
@ -36,11 +36,11 @@
|
||||
[disabled]="disabledByPolicy">
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword()">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -24,7 +24,7 @@
|
||||
</div>
|
||||
<div class="box list" *ngIf="editMode">
|
||||
<div class="box-content single-line">
|
||||
<a class="box-content-row" href="#" appStopClick appBlurClick (click)="delete()"
|
||||
<button type="button" class="box-content-row" appStopClick appBlurClick (click)="delete()"
|
||||
[appApiAction]="deletePromise" #deleteBtn>
|
||||
<div class="row-main text-danger">
|
||||
<div class="icon text-danger" aria-hidden="true">
|
||||
@ -33,7 +33,7 @@
|
||||
</div>
|
||||
<span>{{'deleteFolder' | i18n}}</span>
|
||||
</div>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<span class="title">{{'folders' | i18n}}</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<button appBlurClick (click)="addFolder()" appA11yTitle="{{'addFolder' | i18n}}">
|
||||
<button type="button" appBlurClick (click)="addFolder()" appA11yTitle="{{'addFolder' | i18n}}">
|
||||
<i class="fa fa-plus fa-lg fa-fw" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
@ -17,8 +17,8 @@
|
||||
<content>
|
||||
<div class="box list full-list" *ngIf="folders && folders.length">
|
||||
<div class="box-content">
|
||||
<a href="#" appStopClick (click)="folderSelected(f)" class="box-content-row padded"
|
||||
*ngFor="let f of folders">{{f.name}}</a>
|
||||
<button type="button" appStopClick (click)="folderSelected(f)" class="box-content-row padded"
|
||||
*ngFor="let f of folders">{{f.name}}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="no-items" *ngIf="!folders || !folders.length">
|
||||
|
@ -3,6 +3,7 @@ import {
|
||||
OnInit,
|
||||
} from '@angular/core';
|
||||
|
||||
import { ThemeType } from 'jslib-common/enums/themeType';
|
||||
import { UriMatchType } from 'jslib-common/enums/uriMatchType';
|
||||
|
||||
import { I18nService } from 'jslib-common/abstractions/i18n.service';
|
||||
@ -44,10 +45,10 @@ export class OptionsComponent implements OnInit {
|
||||
private stateService: StateService, private totpService: TotpService, i18nService: I18nService) {
|
||||
this.themeOptions = [
|
||||
{ name: i18nService.t('default'), value: null },
|
||||
{ name: i18nService.t('light'), value: 'light' },
|
||||
{ name: i18nService.t('dark'), value: 'dark' },
|
||||
{ name: 'Nord', value: 'nord' },
|
||||
{ name: i18nService.t('solarizedDark'), value: 'solarizedDark' },
|
||||
{ name: i18nService.t('light'), value: ThemeType.Light },
|
||||
{ name: i18nService.t('dark'), value: ThemeType.Dark },
|
||||
{ name: 'Nord', value: ThemeType.Nord },
|
||||
{ name: i18nService.t('solarizedDark'), value: ThemeType.SolarizedDark },
|
||||
];
|
||||
this.uriMatchOptions = [
|
||||
{ name: i18nService.t('baseDomain'), value: UriMatchType.Domain },
|
||||
|
@ -48,16 +48,16 @@
|
||||
<label for="autoBiometricsPrompt">{{'disableAutoBiometricsPrompt' | i18n}}</label>
|
||||
<input id="autoBiometricsPrompt" type="checkbox" (change)="updateAutoBiometricsPrompt()" [disabled]="!biometric" [(ngModel)]="disableAutoBiometricsPrompt">
|
||||
</div>
|
||||
<a class="box-content-row box-content-row-flex text-default" href="#" appStopClick appBlurClick
|
||||
<button type="button" class="box-content-row box-content-row-flex text-default" appStopClick appBlurClick
|
||||
(click)="lock()">
|
||||
<div class="row-main">{{'lockNow' | i18n}}</div>
|
||||
<i class="fa fa-chevron-right fa-lg row-sub-icon" aria-hidden="true"></i>
|
||||
</a>
|
||||
<a class="box-content-row box-content-row-flex text-default" href="#" appStopClick appBlurClick
|
||||
</button>
|
||||
<button type="button" class="box-content-row box-content-row-flex text-default" appStopClick appBlurClick
|
||||
(click)="twoStep()">
|
||||
<div class="row-main">{{'twoStepLogin' | i18n}}</div>
|
||||
<i class="fa fa-chevron-right fa-lg row-sub-icon" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box list">
|
||||
@ -70,41 +70,41 @@
|
||||
</div>
|
||||
<span><i class="fa fa-chevron-right fa-lg row-sub-icon" aria-hidden="true"></i></span>
|
||||
</a>
|
||||
<a class="box-content-row box-content-row-flex text-default" href="#" appStopClick appBlurClick
|
||||
<button type="button" class="box-content-row box-content-row-flex text-default" appStopClick appBlurClick
|
||||
(click)="changePassword()">
|
||||
<div class="row-main">{{'changeMasterPassword' | i18n}}</div>
|
||||
<i class="fa fa-chevron-right fa-lg row-sub-icon" aria-hidden="true"></i>
|
||||
</a>
|
||||
<a class="box-content-row box-content-row-flex text-default" href="#" appStopClick appBlurClick
|
||||
</button>
|
||||
<button type="button" class="box-content-row box-content-row-flex text-default" appStopClick appBlurClick
|
||||
(click)="fingerprint()">
|
||||
<div class="row-main">{{'fingerprintPhrase' | i18n}}</div>
|
||||
<i class="fa fa-chevron-right fa-lg row-sub-icon" aria-hidden="true"></i>
|
||||
</a>
|
||||
<a class="box-content-row box-content-row-flex text-default" href="#" appStopClick appBlurClick
|
||||
</button>
|
||||
<button type="button" class="box-content-row box-content-row-flex text-default" appStopClick appBlurClick
|
||||
(click)="logOut()">
|
||||
<div class="row-main">{{'logOut' | i18n}}</div>
|
||||
<i class="fa fa-chevron-right fa-lg row-sub-icon" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box list">
|
||||
<div class="box-header">{{'tools' | i18n}}</div>
|
||||
<div class="box-content single-line">
|
||||
<a class="box-content-row box-content-row-flex text-default" href="#" appStopClick appBlurClick
|
||||
<button type="button" class="box-content-row box-content-row-flex text-default" appStopClick appBlurClick
|
||||
(click)="import()">
|
||||
<div class="row-main">{{'importItems' | i18n}}</div>
|
||||
<i class="fa fa-chevron-right fa-lg row-sub-icon" aria-hidden="true"></i>
|
||||
</a>
|
||||
<a class="box-content-row box-content-row-flex text-default" href="#" appStopClick appBlurClick
|
||||
</button>
|
||||
<button type="button" class="box-content-row box-content-row-flex text-default" appStopClick appBlurClick
|
||||
(click)="export()">
|
||||
<div class="row-main">{{'exportVault' | i18n}}</div>
|
||||
<i class="fa fa-chevron-right fa-lg row-sub-icon" aria-hidden="true"></i>
|
||||
</a>
|
||||
<a class="box-content-row box-content-row-flex text-default" href="#" appStopClick appBlurClick
|
||||
</button>
|
||||
<button type="button" class="box-content-row box-content-row-flex text-default" appStopClick appBlurClick
|
||||
(click)="webVault()">
|
||||
<div class="row-main">{{'bitWebVault' | i18n}}</div>
|
||||
<i class="fa fa-chevron-right fa-lg row-sub-icon" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box list">
|
||||
@ -114,26 +114,26 @@
|
||||
<div class="row-main">{{'options' | i18n}}</div>
|
||||
<i class="fa fa-chevron-right fa-lg row-sub-icon" aria-hidden="true"></i>
|
||||
</a>
|
||||
<a class="box-content-row box-content-row-flex text-default" href="#" appStopClick appBlurClick
|
||||
<button type="button" class="box-content-row box-content-row-flex text-default" appStopClick appBlurClick
|
||||
(click)="about()">
|
||||
<div class="row-main">{{'about' | i18n}}</div>
|
||||
<i class="fa fa-chevron-right fa-lg row-sub-icon" aria-hidden="true"></i>
|
||||
</a>
|
||||
<a class="box-content-row box-content-row-flex text-default" href="#" appStopClick appBlurClick
|
||||
</button>
|
||||
<button type="button" class="box-content-row box-content-row-flex text-default" appStopClick appBlurClick
|
||||
(click)="share()">
|
||||
<div class="row-main">{{'learnOrg' | i18n}}</div>
|
||||
<i class="fa fa-chevron-right fa-lg row-sub-icon" aria-hidden="true"></i>
|
||||
</a>
|
||||
<a class="box-content-row box-content-row-flex text-default" href="#" appStopClick appBlurClick
|
||||
</button>
|
||||
<button type="button" class="box-content-row box-content-row-flex text-default" appStopClick appBlurClick
|
||||
(click)="help()">
|
||||
<div class="row-main">{{'helpFeedback' | i18n}}</div>
|
||||
<i class="fa fa-chevron-right fa-lg row-sub-icon" aria-hidden="true"></i>
|
||||
</a>
|
||||
<a class="box-content-row box-content-row-flex text-default" href="#" appStopClick appBlurClick
|
||||
</button>
|
||||
<button type="button" class="box-content-row box-content-row-flex text-default" appStopClick appBlurClick
|
||||
(click)="rate()">
|
||||
<div class="row-main">{{'rateExtension' | i18n}}</div>
|
||||
<i class="fa fa-chevron-right fa-lg row-sub-icon" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
<div class="box-footer">{{'rateExtensionDesc' | i18n}}</div>
|
||||
</div>
|
||||
|
@ -8,9 +8,9 @@
|
||||
<div class="box-content-row box-content-row-multi box-draggable-row" appBoxRow cdkDrag
|
||||
*ngFor="let f of cipher.fields; let i = index; trackBy:trackByFunction"
|
||||
[ngClass]="{'box-content-row-checkbox': f.type === fieldType.Boolean}">
|
||||
<a href="#" appStopClick (click)="removeField(f)" appA11yTitle="{{'remove' | i18n}}">
|
||||
<button type="button" appStopClick (click)="removeField(f)" appA11yTitle="{{'remove' | i18n}}">
|
||||
<i class="fa fa-minus-circle fa-lg" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
<label for="fieldName{{i}}" class="sr-only">{{'name' | i18n}}</label>
|
||||
<label for="fieldValue{{i}}" class="sr-only">{{'value' | i18n}}</label>
|
||||
<div class="row-main">
|
||||
@ -28,11 +28,11 @@
|
||||
<input id="fieldValue{{i}}" name="Field.Value{{i}}" type="checkbox" [(ngModel)]="f.value"
|
||||
*ngIf="f.type === fieldType.Boolean" appTrueFalseValue trueValue="true" falseValue="false">
|
||||
<div class="action-buttons" *ngIf="f.type === fieldType.Hidden && (cipher.viewPassword || f.newField)">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick appA11yTitle="{{'toggleVisibility' | i18n}}"
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick appA11yTitle="{{'toggleVisibility' | i18n}}"
|
||||
(click)="toggleFieldValue(f)">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !f.showValue, 'fa-eye-slash': f.showValue}"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
<div class="drag-handle" appA11yTitle="{{'dragToSort' | i18n}}" cdkDragHandle>
|
||||
<i class="fa fa-bars" aria-hidden="true"></i>
|
||||
@ -41,9 +41,9 @@
|
||||
</div>
|
||||
<!-- Add new custom field -->
|
||||
<div class="box-content-row box-content-row-newmulti" appBoxRow>
|
||||
<a href="#" appStopClick (click)="addField()">
|
||||
<button type="button" appStopClick (click)="addField()">
|
||||
<i class="fa fa-plus-circle fa-fw fa-lg" aria-hidden="true"></i> {{'newCustomField' | i18n}}
|
||||
</a>
|
||||
</button>
|
||||
<label for="addFieldType" class="sr-only">{{'type' | i18n}}</label>
|
||||
<select id="addFieldType" name="AddFieldType" [(ngModel)]="addFieldType" class="field-type">
|
||||
<option *ngFor="let o of addFieldTypeOptions" [ngValue]="o.value">{{o.name}}</option>
|
||||
|
@ -56,17 +56,17 @@
|
||||
<i class="fa fa-lg fa-spinner fa-spin" [hidden]="!checkPasswordBtn.loading"
|
||||
aria-hidden="true"></i>
|
||||
</button>
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="togglePassword()"
|
||||
*ngIf="cipher.viewPassword">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</a>
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick
|
||||
</button>
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick
|
||||
appA11yTitle="{{'generatePassword' | i18n}}" (click)="generatePassword()"
|
||||
*ngIf="cipher.viewPassword">
|
||||
<i class="fa fa-lg fa-refresh" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
@ -90,11 +90,11 @@
|
||||
name="Card.Number" [(ngModel)]="cipher.card.number" appInputVerbatim>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="toggleCardNumber()">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showCardNumber, 'fa-eye-slash': showCardNumber}"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-row" appBoxRow>
|
||||
@ -121,11 +121,11 @@
|
||||
name="Card.Code" [(ngModel)]="cipher.card.code" appInputVerbatim>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick
|
||||
appA11yTitle="{{'toggleVisibility' | i18n}}" (click)="toggleCardCode()">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showCardCode, 'fa-eye-slash': showCardCode}"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -225,9 +225,9 @@
|
||||
<ng-container *ngIf="cipher.login.hasUris">
|
||||
<div class="box-content-row box-content-row-multi" appBoxRow
|
||||
*ngFor="let u of cipher.login.uris; let i = index; trackBy:trackByFunction">
|
||||
<a href="#" appStopClick (click)="removeUri(u)" appA11yTitle="{{'remove' | i18n}}">
|
||||
<button type="button" appStopClick (click)="removeUri(u)" appA11yTitle="{{'remove' | i18n}}">
|
||||
<i class="fa fa-minus-circle fa-lg" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
<div class="row-main">
|
||||
<label for="loginUri{{i}}">{{'uriPosition' | i18n : (i + 1)}}</label>
|
||||
<input id="loginUri{{i}}" type="text" name="Login.Uris[{{i}}].Uri" [(ngModel)]="u.uri"
|
||||
@ -251,21 +251,21 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a *ngIf="currentUris && currentUris.length" class="row-btn" href="#" appStopClick
|
||||
<button type="button" *ngIf="currentUris && currentUris.length" class="row-btn" appStopClick
|
||||
appBlurClick appA11yTitle="{{'toggleCurrentUris' | i18n}}" (click)="toggleUriInput(u)">
|
||||
<i aria-hidden="true" class="fa fa-lg fa-list"></i>
|
||||
</a>
|
||||
<a class="row-btn" href="#" appStopClick appBlurClick
|
||||
</button>
|
||||
<button type="button" class="row-btn" appStopClick appBlurClick
|
||||
appA11yTitle="{{'toggleOptions' | i18n}}" (click)="toggleUriOptions(u)">
|
||||
<i class="fa fa-lg fa-cog" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<a href="#" appStopClick appBlurClick (click)="addUri()"
|
||||
<button type="button" appStopClick appBlurClick (click)="addUri()"
|
||||
class="box-content-row box-content-row-newmulti">
|
||||
<i class="fa fa-plus-circle fa-fw fa-lg" aria-hidden="true"></i> {{'newUri' | i18n}}
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box" *ngIf="showAutoFillOnPageLoadOptions">
|
||||
@ -301,17 +301,17 @@
|
||||
<input id="passwordPrompt" type="checkbox" name="PasswordPrompt" [ngModel]="reprompt"
|
||||
(change)="repromptChanged()">
|
||||
</div>
|
||||
<a class="box-content-row box-content-row-flex text-default" href="#" appStopClick appBlurClick
|
||||
<button type="button" class="box-content-row box-content-row-flex text-default" appStopClick appBlurClick
|
||||
(click)="attachments()" *ngIf="editMode && showAttachments && !cloneMode">
|
||||
<div class="row-main">{{'attachments' | i18n}}</div>
|
||||
<i class="fa fa-external-link fa-lg fa-fw" aria-hidden="true" *ngIf="openAttachmentsInPopup"></i>
|
||||
<i class="fa fa-chevron-right row-sub-icon" aria-hidden="true" *ngIf="!openAttachmentsInPopup"></i>
|
||||
</a>
|
||||
<a class="box-content-row box-content-row-flex text-default" href="#" appStopClick appBlurClick
|
||||
</button>
|
||||
<button type="button" class="box-content-row box-content-row-flex text-default" appStopClick appBlurClick
|
||||
(click)="editCollections()" *ngIf="editMode && cipher.organizationId && !cloneMode">
|
||||
<div class="row-main">{{'collections' | i18n}}</div>
|
||||
<i class="fa fa-chevron-right row-sub-icon" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
@ -359,7 +359,7 @@
|
||||
</div>
|
||||
<div class="box list" *ngIf="editMode && !cloneMode">
|
||||
<div class="box-content single-line">
|
||||
<a class="box-content-row" href="#" appStopClick appBlurClick (click)="delete()"
|
||||
<button type="button" class="box-content-row" appStopClick appBlurClick (click)="delete()"
|
||||
[appApiAction]="deletePromise" #deleteBtn>
|
||||
<div class="row-main text-danger">
|
||||
<div class="icon text-danger" aria-hidden="true">
|
||||
@ -368,7 +368,7 @@
|
||||
</div>
|
||||
<span>{{'deleteItem' | i18n}}</span>
|
||||
</div>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</content>
|
||||
|
@ -28,7 +28,7 @@
|
||||
</div>
|
||||
<small class="row-sub-label">{{a.sizeName}}</small>
|
||||
<div class="action-buttons no-pad">
|
||||
<button class="row-btn btn" type="button" appStopClick appBlurClick
|
||||
<button type="button" class="row-btn btn" type="button" appStopClick appBlurClick
|
||||
appA11yTitle="{{'deleteAttachment' | i18n}}" (click)="delete(a)" #deleteBtn
|
||||
[appApiAction]="deletePromises[a.id]" [disabled]="deleteBtn.loading">
|
||||
<i class="fa fa-trash-o fa-lg fa-fw" [hidden]="deleteBtn.loading" aria-hidden="true"></i>
|
||||
|
@ -24,7 +24,7 @@
|
||||
{{'folders' | i18n}}
|
||||
</div>
|
||||
<div class="box-content single-line">
|
||||
<a *ngFor="let f of nestedFolders" href="#" class="box-content-row" appStopClick appBlurClick
|
||||
<button type="button" *ngFor="let f of nestedFolders" class="box-content-row" appStopClick appBlurClick
|
||||
(click)="selectFolder(f.node)">
|
||||
<div class="row-main">
|
||||
<div class="icon">
|
||||
@ -34,7 +34,7 @@
|
||||
<span class="text">{{f.node.name}}</span>
|
||||
</div>
|
||||
<span><i class="fa fa-chevron-right fa-lg row-sub-icon" aria-hidden="true"></i></span>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box list" *ngIf="nestedCollections && nestedCollections.length">
|
||||
@ -42,14 +42,14 @@
|
||||
{{'collections' | i18n}}
|
||||
</div>
|
||||
<div class="box-content single-line">
|
||||
<a *ngFor="let c of nestedCollections" href="#" class="box-content-row" appStopClick appBlurClick
|
||||
<button type="button" *ngFor="let c of nestedCollections" class="box-content-row" appStopClick appBlurClick
|
||||
(click)="selectCollection(c.node)">
|
||||
<div class="row-main">
|
||||
<div class="icon"><i class="fa fa-fw fa-lg fa-cube" aria-hidden="true"></i></div>
|
||||
<span class="text">{{c.node.name}}</span>
|
||||
</div>
|
||||
<span><i class="fa fa-chevron-right fa-lg row-sub-icon" aria-hidden="true"></i></span>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
@ -58,7 +58,7 @@
|
||||
<i class="fa fa-spinner fa-spin fa-3x" *ngIf="!loaded" aria-hidden="true"></i>
|
||||
<ng-container *ngIf="loaded">
|
||||
<p>{{'noItemsInList' | i18n}}</p>
|
||||
<button (click)="addCipher()" class="btn block primary link">
|
||||
<button type="button" (click)="addCipher()" class="btn block primary link">
|
||||
{{'addItem' | i18n}}
|
||||
</button>
|
||||
</ng-container>
|
||||
|
@ -8,7 +8,7 @@
|
||||
<i class="fa fa-search"></i>
|
||||
</div>
|
||||
<div class="right">
|
||||
<button appBlurClick (click)="addCipher()" appA11yTitle="{{'addItem' | i18n}}">
|
||||
<button type="button" appBlurClick (click)="addCipher()" appA11yTitle="{{'addItem' | i18n}}">
|
||||
<i class="fa fa-plus fa-lg fa-fw" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
@ -19,7 +19,7 @@
|
||||
<ng-container *ngIf="loaded">
|
||||
<i class="fa fa-frown-o fa-4x"></i>
|
||||
<p>{{'noItemsInList' | i18n}}</p>
|
||||
<button (click)="addCipher()" class="btn block primary link">{{'addItem' | i18n}}</button>
|
||||
<button type="button" (click)="addCipher()" class="btn block primary link">{{'addItem' | i18n}}</button>
|
||||
</ng-container>
|
||||
</div>
|
||||
<ng-container *ngIf="ciphers && ciphers.length && !showSearching()">
|
||||
@ -40,31 +40,31 @@
|
||||
<span class="flex-right">4</span>
|
||||
</div>
|
||||
<div class="box-content single-line">
|
||||
<a href="#" class="box-content-row" appStopClick appBlurClick (click)="selectType(cipherType.Login)">
|
||||
<button type="button" class="box-content-row" appStopClick appBlurClick (click)="selectType(cipherType.Login)">
|
||||
<div class="row-main">
|
||||
<div class="icon"><i class="fa fa-fw fa-lg fa-globe"></i></div>
|
||||
<span class="text">{{'typeLogin' | i18n}}</span>
|
||||
</div>
|
||||
<span class="row-sub-label">{{typeCounts.get(cipherType.Login) || 0}}</span>
|
||||
<span><i class="fa fa-chevron-right fa-lg row-sub-icon"></i></span>
|
||||
</a>
|
||||
<a href="#" class="box-content-row" appStopClick appBlurClick (click)="selectType(cipherType.Card)">
|
||||
</button>
|
||||
<button type="button" class="box-content-row" appStopClick appBlurClick (click)="selectType(cipherType.Card)">
|
||||
<div class="row-main">
|
||||
<div class="icon"><i class="fa fa-fw fa-lg fa-credit-card"></i></div>
|
||||
<span class="text">{{'typeCard' | i18n}}</span>
|
||||
</div>
|
||||
<span class="row-sub-label">{{typeCounts.get(cipherType.Card) || 0}}</span>
|
||||
<span><i class="fa fa-chevron-right fa-lg row-sub-icon"></i></span>
|
||||
</a>
|
||||
<a href="#" class="box-content-row" appStopClick appBlurClick (click)="selectType(cipherType.Identity)">
|
||||
</button>
|
||||
<button type="button" class="box-content-row" appStopClick appBlurClick (click)="selectType(cipherType.Identity)">
|
||||
<div class="row-main">
|
||||
<div class="icon"><i class="fa fa-fw fa-lg fa-id-card-o"></i></div>
|
||||
<span class="text">{{'typeIdentity' | i18n}}</span>
|
||||
</div>
|
||||
<span class="row-sub-label">{{typeCounts.get(cipherType.Identity) || 0}}</span>
|
||||
<span><i class="fa fa-chevron-right fa-lg row-sub-icon"></i></span>
|
||||
</a>
|
||||
<a href="#" class="box-content-row" appStopClick appBlurClick
|
||||
</button>
|
||||
<button type="button" class="box-content-row" appStopClick appBlurClick
|
||||
(click)="selectType(cipherType.SecureNote)">
|
||||
<div class="row-main">
|
||||
<div class="icon"><i class="fa fa-fw fa-lg fa-sticky-note-o"></i></div>
|
||||
@ -72,7 +72,7 @@
|
||||
</div>
|
||||
<span class="row-sub-label">{{typeCounts.get(cipherType.SecureNote) || 0}}</span>
|
||||
<span><i class="fa fa-chevron-right fa-lg row-sub-icon"></i></span>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box list" *ngIf="nestedFolders?.length">
|
||||
@ -81,7 +81,7 @@
|
||||
<span class="flex-right">{{folderCount}}</span>
|
||||
</div>
|
||||
<div class="box-content single-line">
|
||||
<a *ngFor="let f of nestedFolders" href="#" class="box-content-row" appStopClick appBlurClick
|
||||
<button type="button" *ngFor="let f of nestedFolders" class="box-content-row" appStopClick appBlurClick
|
||||
(click)="selectFolder(f.node)">
|
||||
<div class="row-main">
|
||||
<div class="icon">
|
||||
@ -92,7 +92,7 @@
|
||||
</div>
|
||||
<span class="row-sub-label">{{folderCounts.get(f.node.id) || 0}}</span>
|
||||
<span><i class="fa fa-chevron-right fa-lg row-sub-icon"></i></span>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box list" *ngIf="nestedCollections && nestedCollections.length">
|
||||
@ -101,7 +101,7 @@
|
||||
<span class="flex-right">{{nestedCollections.length}}</span>
|
||||
</div>
|
||||
<div class="box-content single-line">
|
||||
<a *ngFor="let nestedCollection of nestedCollections" href="#" class="box-content-row"
|
||||
<button type="button" *ngFor="let nestedCollection of nestedCollections" class="box-content-row"
|
||||
appStopClick appBlurClick (click)="selectCollection(nestedCollection.node)">
|
||||
<div class="row-main">
|
||||
<div class="icon"><i class="fa fa-fw fa-lg fa-cube"></i></div>
|
||||
@ -109,7 +109,7 @@
|
||||
</div>
|
||||
<span class="row-sub-label">{{collectionCounts.get(nestedCollection.node.id) || 0}}</span>
|
||||
<span><i class="fa fa-chevron-right fa-lg row-sub-icon"></i></span>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box list" *ngIf="showNoFolderCiphers">
|
||||
@ -129,7 +129,7 @@
|
||||
<span class="flex-right">{{deletedCount}}</span>
|
||||
</div>
|
||||
<div class="box-content single-line">
|
||||
<a href="#" class="box-content-row" appStopClick appBlurClick
|
||||
<button type="button" class="box-content-row" appStopClick appBlurClick
|
||||
(click)="selectTrash()">
|
||||
<div class="row-main">
|
||||
<div class="icon"><i class="fa fa-fw fa-lg fa-trash-o"></i></div>
|
||||
@ -137,7 +137,7 @@
|
||||
</div>
|
||||
<span class="row-sub-label">{{deletedCount}}</span>
|
||||
<span><i class="fa fa-chevron-right fa-lg row-sub-icon"></i></span>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
@ -20,10 +20,10 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appA11yTitle="{{'copyPassword' | i18n}}"
|
||||
<button type="button" class="row-btn" appStopClick appA11yTitle="{{'copyPassword' | i18n}}"
|
||||
(click)="copy(h.password)">
|
||||
<i class="fa fa-lg fa-clone" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -20,17 +20,17 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appA11yTitle="{{'toggleVisibility' | i18n}}"
|
||||
<button type="button" class="row-btn" appStopClick appA11yTitle="{{'toggleVisibility' | i18n}}"
|
||||
*ngIf="field.type === fieldType.Hidden && cipher.viewPassword"
|
||||
(click)="toggleFieldValue(field)">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !field.showValue, 'fa-eye-slash': field.showValue}"></i>
|
||||
</a>
|
||||
<a class="row-btn" href="#" appStopClick appA11yTitle="{{'copyValue' | i18n}}"
|
||||
</button>
|
||||
<button type="button" class="row-btn" appStopClick appA11yTitle="{{'copyValue' | i18n}}"
|
||||
*ngIf="field.value && field.type !== fieldType.Boolean && !(field.type === fieldType.Hidden && !cipher.viewPassword)"
|
||||
(click)="copy(field.value, 'value', field.type === fieldType.Hidden ? 'H_Field' : 'Field')">
|
||||
<i class="fa fa-lg fa-clone" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -29,10 +29,10 @@
|
||||
<input type="text" [value]="cipher.login.username" readonly aria-readonly="true" />
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appA11yTitle="{{'copyUsername' | i18n}}"
|
||||
<button type="button" class="row-btn" appStopClick appA11yTitle="{{'copyUsername' | i18n}}"
|
||||
(click)="copy(cipher.login.username, 'username', 'Username')">
|
||||
<i class="fa fa-lg fa-clone" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-flex" *ngIf="cipher.login.password">
|
||||
@ -54,15 +54,15 @@
|
||||
<i class="fa fa-lg fa-spinner fa-spin" [hidden]="!checkPasswordBtn.loading"
|
||||
aria-hidden="true"></i>
|
||||
</button>
|
||||
<a class="row-btn" href="#" appStopClick appA11yTitle="{{'toggleVisibility' | i18n}}"
|
||||
<button type="button" class="row-btn" appStopClick appA11yTitle="{{'toggleVisibility' | i18n}}"
|
||||
(click)="togglePassword()" *ngIf="cipher.viewPassword">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
|
||||
</a>
|
||||
<a class="row-btn" href="#" appStopClick appA11yTitle="{{'copyPassword' | i18n}}"
|
||||
</button>
|
||||
<button type="button" class="row-btn" appStopClick appA11yTitle="{{'copyPassword' | i18n}}"
|
||||
(click)="copy(cipher.login.password, 'password', 'Password')" *ngIf="cipher.viewPassword">
|
||||
<i class="fa fa-lg fa-clone" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-row box-content-row-flex totp" [ngClass]="{'low': totpLow}"
|
||||
@ -83,10 +83,10 @@
|
||||
</svg>
|
||||
</span>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appA11yTitle="{{'copyVerificationCode' | i18n}}"
|
||||
<button type="button" class="row-btn" appStopClick appA11yTitle="{{'copyVerificationCode' | i18n}}"
|
||||
(click)="copy(totpCode, 'verificationCodeTotp', 'TOTP')">
|
||||
<i class="fa fa-lg fa-clone" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -103,15 +103,15 @@
|
||||
<span [hidden]="!showCardNumber" class="monospaced">{{cipher.card.number}}</span>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appA11yTitle="{{'toggleVisibility' | i18n}}"
|
||||
<button type="button" class="row-btn" appStopClick appA11yTitle="{{'toggleVisibility' | i18n}}"
|
||||
(click)="toggleCardNumber()">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showCardNumber, 'fa-eye-slash': showCardNumber}"></i>
|
||||
</a>
|
||||
<a class="row-btn" href="#" appStopClick appA11yTitle="{{'copyNumber' | i18n}}"
|
||||
</button>
|
||||
<button type="button" class="row-btn" appStopClick appA11yTitle="{{'copyNumber' | i18n}}"
|
||||
(click)="copy(cipher.card.number, 'number', 'Card Number')">
|
||||
<i class="fa fa-lg fa-clone" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-content-row" *ngIf="cipher.card.brand">
|
||||
@ -129,15 +129,15 @@
|
||||
<span [hidden]="!showCardCode" class="monospaced">{{cipher.card.code}}</span>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appA11yTitle="{{'toggleVisibility' | i18n}}"
|
||||
<button type="button" class="row-btn" appStopClick appA11yTitle="{{'toggleVisibility' | i18n}}"
|
||||
(click)="toggleCardCode()">
|
||||
<i class="fa fa-lg" aria-hidden="true"
|
||||
[ngClass]="{'fa-eye': !showCardCode, 'fa-eye-slash': showCardCode}"></i>
|
||||
</a>
|
||||
<a class="row-btn" href="#" appStopClick appA11yTitle="{{'copySecurityCode' | i18n}}"
|
||||
</button>
|
||||
<button type="button" class="row-btn" appStopClick appA11yTitle="{{'copySecurityCode' | i18n}}"
|
||||
(click)="copy(cipher.card.code, 'securityCode', 'Security Code')">
|
||||
<i class="fa fa-lg fa-clone" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -198,14 +198,14 @@
|
||||
</span>
|
||||
</div>
|
||||
<div class="action-buttons">
|
||||
<a class="row-btn" href="#" appStopClick appA11yTitle="{{'launch' | i18n}}" *ngIf="u.canLaunch"
|
||||
<button type="button" class="row-btn" appStopClick appA11yTitle="{{'launch' | i18n}}" *ngIf="u.canLaunch"
|
||||
(click)="launch(u)">
|
||||
<i class="fa fa-lg fa-share-square-o" aria-hidden="true"></i>
|
||||
</a>
|
||||
<a class="row-btn" href="#" appStopClick appA11yTitle="{{'copyUri' | i18n}}"
|
||||
</button>
|
||||
<button type="button" class="row-btn"appStopClick appA11yTitle="{{'copyUri' | i18n}}"
|
||||
(click)="copy(u.uri, u.isWebsite ? 'website' : 'uri', 'URI')">
|
||||
<i class="fa fa-lg fa-clone" aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -229,19 +229,19 @@
|
||||
{{'attachments' | i18n}}
|
||||
</div>
|
||||
<div class="box-content">
|
||||
<a class="box-content-row box-content-row-flex text-default" *ngFor="let attachment of cipher.attachments"
|
||||
href="#" appStopClick appBlurCLick (click)="downloadAttachment(attachment)">
|
||||
<button type="button" class="box-content-row box-content-row-flex text-default" *ngFor="let attachment of cipher.attachments"
|
||||
appStopClick appBlurCLick (click)="downloadAttachment(attachment)">
|
||||
<span class="row-main">{{attachment.fileName}}</span>
|
||||
<small class="row-sub-label">{{attachment.sizeName}}</small>
|
||||
<i class="fa fa-download fa-fw row-sub-icon" *ngIf="!attachment.downloading" aria-hidden="true"></i>
|
||||
<i class="fa fa-spinner fa-fw fa-spin row-sub-icon" *ngIf="attachment.downloading"
|
||||
aria-hidden="true"></i>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box list">
|
||||
<div class="box-content single-line">
|
||||
<a class="box-content-row" href="#" appStopClick appBlurClick (click)="fillCipher()"
|
||||
<button type="button" class="box-content-row" appStopClick appBlurClick (click)="fillCipher()"
|
||||
*ngIf="cipher.type !== cipherType.SecureNote && !cipher.isDeleted && !inPopout">
|
||||
<div class="row-main text-primary">
|
||||
<div class="icon text-primary" aria-hidden="true">
|
||||
@ -249,8 +249,8 @@
|
||||
</div>
|
||||
<span>{{'autoFill' | i18n}}</span>
|
||||
</div>
|
||||
</a>
|
||||
<a class="box-content-row" href="#" appStopClick appBlurClick (click)="fillCipherAndSave()"
|
||||
</button>
|
||||
<button type="button" class="box-content-row" appStopClick appBlurClick (click)="fillCipherAndSave()"
|
||||
*ngIf="cipher.type === cipherType.Login && !cipher.isDeleted && !inPopout">
|
||||
<div class="row-main text-primary">
|
||||
<div class="icon text-primary" aria-hidden="true">
|
||||
@ -258,8 +258,8 @@
|
||||
</div>
|
||||
<span>{{'autoFillAndSave' | i18n}}</span>
|
||||
</div>
|
||||
</a>
|
||||
<a class="box-content-row" href="#" appStopClick appBlurClick (click)="clone()"
|
||||
</button>
|
||||
<button type="button" class="box-content-row" appStopClick appBlurClick (click)="clone()"
|
||||
*ngIf="!cipher.organizationId && !cipher.isDeleted">
|
||||
<div class="row-main text-primary">
|
||||
<div class="icon text-primary" aria-hidden="true">
|
||||
@ -267,31 +267,31 @@
|
||||
</div>
|
||||
<span>{{'cloneItem' | i18n}}</span>
|
||||
</div>
|
||||
</a>
|
||||
<a class="box-content-row" href="#" appStopClick appBlurClick (click)="share()" *ngIf="!cipher.organizationId">
|
||||
</button>
|
||||
<button type="button" class="box-content-row" appStopClick appBlurClick (click)="share()" *ngIf="!cipher.organizationId">
|
||||
<div class="row-main text-primary">
|
||||
<div class="icon text-primary" aria-hidden="true">
|
||||
<i class="fa fa-arrow-circle-o-right fa-lg fa-fw"></i>
|
||||
</div>
|
||||
<span>{{'moveToOrganization' | i18n}}</span>
|
||||
</div>
|
||||
</a>
|
||||
<a class="box-content-row" href="#" appStopClick appBlurClick (click)="restore()" *ngIf="cipher.isDeleted">
|
||||
</button>
|
||||
<button type="button" class="box-content-row" appStopClick appBlurClick (click)="restore()" *ngIf="cipher.isDeleted">
|
||||
<div class="row-main text-primary">
|
||||
<div class="icon text-primary" aria-hidden="true">
|
||||
<i class="fa fa-undo fa-lg fa-fw"></i>
|
||||
</div>
|
||||
<span>{{'restoreItem' | i18n}}</span>
|
||||
</div>
|
||||
</a>
|
||||
<a class="box-content-row" href="#" appStopClick appBlurClick (click)="delete()">
|
||||
</button>
|
||||
<button type="button" class="box-content-row" appStopClick appBlurClick (click)="delete()">
|
||||
<div class="row-main text-danger">
|
||||
<div class="icon text-danger" aria-hidden="true">
|
||||
<i class="fa fa-trash-o fa-lg fa-fw"></i>
|
||||
</div>
|
||||
<span>{{(cipher.isDeleted ? 'permanentlyDeleteItem' : 'deleteItem') | i18n}}</span>
|
||||
</div>
|
||||
</a>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
|
@ -306,7 +306,11 @@ export default class AutofillService implements AutofillServiceInterface {
|
||||
});
|
||||
|
||||
pageDetails.fields.forEach((field: any) => {
|
||||
if (filledFields.hasOwnProperty(field.opid) || !field.viewable) {
|
||||
if (filledFields.hasOwnProperty(field.opid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!field.viewable && field.tagName !== 'span') {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -459,6 +463,10 @@ export default class AutofillService implements AutofillServiceInterface {
|
||||
const fillFields: { [id: string]: AutofillField; } = {};
|
||||
|
||||
pageDetails.fields.forEach((f: any) => {
|
||||
if (this.forCustomFieldsOnly(f)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isExcludedType(f.type, ExcludedAutofillTypes)) {
|
||||
return;
|
||||
}
|
||||
@ -691,6 +699,10 @@ export default class AutofillService implements AutofillServiceInterface {
|
||||
const fillFields: { [id: string]: AutofillField; } = {};
|
||||
|
||||
pageDetails.fields.forEach((f: any) => {
|
||||
if (this.forCustomFieldsOnly(f)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isExcludedType(f.type, ExcludedAutofillTypes)) {
|
||||
return;
|
||||
}
|
||||
@ -928,6 +940,10 @@ export default class AutofillService implements AutofillServiceInterface {
|
||||
mustBeEmpty: boolean, fillNewPassword: boolean) {
|
||||
const arr: AutofillField[] = [];
|
||||
pageDetails.fields.forEach(f => {
|
||||
if (this.forCustomFieldsOnly(f)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isPassword = f.type === 'password';
|
||||
const valueIsLikePassword = (value: string) => {
|
||||
if (value == null) {
|
||||
@ -976,6 +992,10 @@ export default class AutofillService implements AutofillServiceInterface {
|
||||
let usernameField: AutofillField = null;
|
||||
for (let i = 0; i < pageDetails.fields.length; i++) {
|
||||
const f = pageDetails.fields[i];
|
||||
if (this.forCustomFieldsOnly(f)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (f.elementNumber >= passwordField.elementNumber) {
|
||||
break;
|
||||
}
|
||||
@ -1152,8 +1172,14 @@ export default class AutofillService implements AutofillServiceInterface {
|
||||
if (field.maxLength && value && value.length > field.maxLength) {
|
||||
value = value.substr(0, value.length);
|
||||
}
|
||||
fillScript.script.push(['click_on_opid', field.opid]);
|
||||
fillScript.script.push(['focus_by_opid', field.opid]);
|
||||
if (field.tagName !== 'span') {
|
||||
fillScript.script.push(['click_on_opid', field.opid]);
|
||||
fillScript.script.push(['focus_by_opid', field.opid]);
|
||||
}
|
||||
fillScript.script.push(['fill_by_opid', field.opid, value]);
|
||||
}
|
||||
|
||||
private forCustomFieldsOnly(field: AutofillField): boolean {
|
||||
return field.tagName === 'span';
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ import BrowserPlatformUtilsService from './browserPlatformUtils.service';
|
||||
|
||||
import { DeviceType } from 'jslib-common/enums/deviceType';
|
||||
|
||||
const platformUtilsFactory = () => new BrowserPlatformUtilsService(null, null, null, null);
|
||||
|
||||
describe('Browser Utils Service', () => {
|
||||
describe('getBrowser', () => {
|
||||
const originalUserAgent = navigator.userAgent;
|
||||
@ -27,7 +29,7 @@ describe('Browser Utils Service', () => {
|
||||
value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36',
|
||||
});
|
||||
|
||||
const browserPlatformUtilsService = new BrowserPlatformUtilsService(null, null, null);
|
||||
const browserPlatformUtilsService = platformUtilsFactory();
|
||||
expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.ChromeExtension);
|
||||
});
|
||||
|
||||
@ -37,7 +39,7 @@ describe('Browser Utils Service', () => {
|
||||
value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:58.0) Gecko/20100101 Firefox/58.0',
|
||||
});
|
||||
|
||||
const browserPlatformUtilsService = new BrowserPlatformUtilsService(null, null, null);
|
||||
const browserPlatformUtilsService = platformUtilsFactory();
|
||||
expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.FirefoxExtension);
|
||||
});
|
||||
|
||||
@ -52,7 +54,7 @@ describe('Browser Utils Service', () => {
|
||||
value: {},
|
||||
});
|
||||
|
||||
const browserPlatformUtilsService = new BrowserPlatformUtilsService(null, null, null);
|
||||
const browserPlatformUtilsService = platformUtilsFactory();
|
||||
expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.OperaExtension);
|
||||
});
|
||||
|
||||
@ -62,7 +64,7 @@ describe('Browser Utils Service', () => {
|
||||
value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.74 Safari/537.36 Edg/79.0.309.43',
|
||||
});
|
||||
|
||||
const browserPlatformUtilsService = new BrowserPlatformUtilsService(null, null, null);
|
||||
const browserPlatformUtilsService = platformUtilsFactory();
|
||||
expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.EdgeExtension);
|
||||
});
|
||||
|
||||
@ -77,7 +79,7 @@ describe('Browser Utils Service', () => {
|
||||
value: true,
|
||||
});
|
||||
|
||||
const browserPlatformUtilsService = new BrowserPlatformUtilsService(null, null, null);
|
||||
const browserPlatformUtilsService = platformUtilsFactory();
|
||||
expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.SafariExtension);
|
||||
|
||||
Object.defineProperty(window, 'safariAppExtension', {
|
||||
@ -92,7 +94,7 @@ describe('Browser Utils Service', () => {
|
||||
value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.97 Safari/537.36 Vivaldi/1.94.1008.40',
|
||||
});
|
||||
|
||||
const browserPlatformUtilsService = new BrowserPlatformUtilsService(null, null, null);
|
||||
const browserPlatformUtilsService = platformUtilsFactory();
|
||||
expect(browserPlatformUtilsService.getDevice()).toBe(DeviceType.VivaldiExtension);
|
||||
});
|
||||
});
|
||||
|
@ -2,9 +2,13 @@ import { BrowserApi } from '../browser/browserApi';
|
||||
import { SafariApp } from '../browser/safariApp';
|
||||
|
||||
import { DeviceType } from 'jslib-common/enums/deviceType';
|
||||
import { ThemeType } from 'jslib-common/enums/themeType';
|
||||
|
||||
import { MessagingService } from 'jslib-common/abstractions/messaging.service';
|
||||
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
|
||||
import { StorageService } from 'jslib-common/abstractions/storage.service';
|
||||
|
||||
import { ConstantsService } from 'jslib-common/services/constants.service';
|
||||
|
||||
const DialogPromiseExpiration = 600000; // 10 minutes
|
||||
|
||||
@ -16,7 +20,7 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
|
||||
private deviceCache: DeviceType = null;
|
||||
private prefersColorSchemeDark = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
|
||||
constructor(private messagingService: MessagingService,
|
||||
constructor(private messagingService: MessagingService, private storageService: StorageService,
|
||||
private clipboardWriteCallback: (clipboardValue: string, clearMs: number) => void,
|
||||
private biometricCallback: () => Promise<boolean>) { }
|
||||
|
||||
@ -317,13 +321,22 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
|
||||
return false;
|
||||
}
|
||||
|
||||
getDefaultSystemTheme(): Promise<'light' | 'dark'> {
|
||||
return Promise.resolve(this.prefersColorSchemeDark.matches ? 'dark' : 'light');
|
||||
getDefaultSystemTheme(): Promise<ThemeType.Light | ThemeType.Dark> {
|
||||
return Promise.resolve(this.prefersColorSchemeDark.matches ? ThemeType.Dark : ThemeType.Light);
|
||||
}
|
||||
|
||||
onDefaultSystemThemeChange(callback: ((theme: 'light' | 'dark') => unknown)) {
|
||||
onDefaultSystemThemeChange(callback: ((theme: ThemeType.Light | ThemeType.Dark) => unknown)) {
|
||||
this.prefersColorSchemeDark.addEventListener('change', ({ matches }) => {
|
||||
callback(matches ? 'dark' : 'light');
|
||||
callback(matches ? ThemeType.Dark : ThemeType.Light);
|
||||
});
|
||||
}
|
||||
|
||||
async getEffectiveTheme() {
|
||||
const theme = await this.storageService.get<ThemeType>(ConstantsService.themeKey);
|
||||
if (theme == null || theme === ThemeType.System) {
|
||||
return this.getDefaultSystemTheme();
|
||||
} else {
|
||||
return theme;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user