mirror of https://github.com/keeweb/keeweb.git
advanced settings
This commit is contained in:
parent
f9a79bf2c4
commit
8df3899920
|
@ -3,68 +3,12 @@ import { View } from 'framework/views/view';
|
|||
import { Storage } from 'storage';
|
||||
import { Updater } from 'comp/app/updater';
|
||||
import { Launcher } from 'comp/launcher';
|
||||
import { Alerts } from 'comp/ui/alerts';
|
||||
import { Links } from 'const/links';
|
||||
import { AppSettingsModel } from 'models/app-settings-model';
|
||||
import { Locale } from 'util/locale';
|
||||
import { SettingsLogsView } from 'views/settings/settings-logs-view';
|
||||
import { minmax } from 'util/fn';
|
||||
import { NativeModules } from 'comp/launcher/native-modules';
|
||||
import template from 'templates/settings/settings-general.hbs';
|
||||
|
||||
class SettingsGeneralView extends View {
|
||||
template = template;
|
||||
|
||||
events = {
|
||||
'click .settings__general-theme': 'changeTheme',
|
||||
'click .settings__general-auto-switch-theme': 'changeAuthSwitchTheme',
|
||||
'change .settings__general-locale': 'changeLocale',
|
||||
'change .settings__general-font-size': 'changeFontSize',
|
||||
'change .settings__general-expand': 'changeExpandGroups',
|
||||
'change .settings__general-auto-update': 'changeAutoUpdate',
|
||||
'change .settings__general-idle-minutes': 'changeIdleMinutes',
|
||||
'change .settings__general-clipboard': 'changeClipboard',
|
||||
'change .settings__general-auto-save': 'changeAutoSave',
|
||||
'change .settings__general-auto-save-interval': 'changeAutoSaveInterval',
|
||||
'change .settings__general-remember-key-files': 'changeRememberKeyFiles',
|
||||
'change .settings__general-minimize': 'changeMinimize',
|
||||
'change .settings__general-minimize-on-field-copy': 'changeMinimizeOnFieldCopy',
|
||||
'change .settings__general-audit-passwords': 'changeAuditPasswords',
|
||||
'change .settings__general-audit-password-entropy': 'changeAuditPasswordEntropy',
|
||||
'change .settings__general-exclude-pins-from-audit': 'changeExcludePinsFromAudit',
|
||||
'change .settings__general-check-passwords-on-hibp': 'changeCheckPasswordsOnHIBP',
|
||||
'click .settings__general-toggle-help-hibp': 'clickToggleHelpHIBP',
|
||||
'change .settings__general-audit-password-age': 'changeAuditPasswordAge',
|
||||
'change .settings__general-lock-on-minimize': 'changeLockOnMinimize',
|
||||
'change .settings__general-lock-on-copy': 'changeLockOnCopy',
|
||||
'change .settings__general-lock-on-auto-type': 'changeLockOnAutoType',
|
||||
'change .settings__general-lock-on-os-lock': 'changeLockOnOsLock',
|
||||
'change .settings__general-table-view': 'changeTableView',
|
||||
'change .settings__general-colorful-icons': 'changeColorfulIcons',
|
||||
'change .settings__general-use-markdown': 'changeUseMarkdown',
|
||||
'change .settings__general-use-group-icon-for-entries': 'changeUseGroupIconForEntries',
|
||||
'change .settings__general-direct-autotype': 'changeDirectAutotype',
|
||||
'change .settings__general-autotype-title-filter': 'changeAutoTypeTitleFilter',
|
||||
'change .settings__general-field-label-dblclick-autotype':
|
||||
'changeFieldLabelDblClickAutoType',
|
||||
'change .settings__general-device-owner-auth': 'changeDeviceOwnerAuth',
|
||||
'change .settings__general-device-owner-auth-timeout': 'changeDeviceOwnerAuthTimeout',
|
||||
'change .settings__general-titlebar-style': 'changeTitlebarStyle',
|
||||
'click .settings__general-update-btn': 'checkUpdate',
|
||||
'click .settings__general-restart-btn': 'installUpdateAndRestart',
|
||||
'click .settings__general-download-update-btn': 'downloadUpdate',
|
||||
'click .settings__general-update-found-btn': 'installFoundUpdate',
|
||||
'change .settings__general-disable-offline-storage': 'changeDisableOfflineStorage',
|
||||
'change .settings__general-short-lived-storage-token': 'changeShortLivedStorageToken',
|
||||
'change .settings__general-prv-check': 'changeStorageEnabled',
|
||||
'click .settings__general-prv-logout': 'logoutFromStorage',
|
||||
'click .settings__general-show-advanced': 'showAdvancedSettings',
|
||||
'click .settings__general-dev-tools-link': 'openDevTools',
|
||||
'click .settings__general-try-beta-link': 'tryBeta',
|
||||
'click .settings__general-show-logs-link': 'showLogs',
|
||||
'click .settings__general-reload-app-link': 'reloadApp'
|
||||
};
|
||||
|
||||
changeClipboard(e) {
|
||||
const clipboardSeconds = +e.target.value;
|
||||
AppSettingsModel.clipboardSeconds = clipboardSeconds;
|
||||
|
@ -270,47 +214,6 @@ class SettingsGeneralView extends View {
|
|||
$(e.target).remove();
|
||||
}
|
||||
}
|
||||
|
||||
showAdvancedSettings() {
|
||||
this.$el
|
||||
.find('.settings__general-show-advanced, .settings__general-advanced')
|
||||
.toggleClass('hide');
|
||||
this.scrollToBottom();
|
||||
}
|
||||
|
||||
openDevTools() {
|
||||
if (Launcher) {
|
||||
Launcher.openDevTools();
|
||||
}
|
||||
}
|
||||
|
||||
tryBeta() {
|
||||
if (this.appModel.files.hasUnsavedFiles()) {
|
||||
Alerts.info({
|
||||
header: Locale.setGenTryBetaWarning,
|
||||
body: Locale.setGenTryBetaWarningBody
|
||||
});
|
||||
} else {
|
||||
location.href = Links.BetaWebApp;
|
||||
}
|
||||
}
|
||||
|
||||
showLogs() {
|
||||
if (this.views.logView) {
|
||||
this.views.logView.remove();
|
||||
}
|
||||
this.views.logView = new SettingsLogsView();
|
||||
this.views.logView.render();
|
||||
this.scrollToBottom();
|
||||
}
|
||||
|
||||
reloadApp() {
|
||||
location.reload();
|
||||
}
|
||||
|
||||
scrollToBottom() {
|
||||
this.$el.closest('.scroller').scrollTop(this.$el.height());
|
||||
}
|
||||
}
|
||||
|
||||
export { SettingsGeneralView };
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
import { View } from 'framework/views/view';
|
||||
import { StringFormat } from 'util/formatting/string-format';
|
||||
import { Logger } from 'util/logger';
|
||||
import template from 'templates/settings/settings-logs-view.hbs';
|
||||
|
||||
class SettingsLogsView extends View {
|
||||
parent = '.settings__general-advanced';
|
||||
template = template;
|
||||
levelToColor = { debug: 'muted', warn: 'yellow', error: 'red' };
|
||||
|
||||
render() {
|
||||
const logs = Logger.getLast().map((item) => ({
|
||||
level: item.level,
|
||||
color: this.levelToColor[item.level],
|
||||
msg:
|
||||
'[' +
|
||||
StringFormat.padStr(item.level.toUpperCase(), 5) +
|
||||
'] ' +
|
||||
item.args.map((arg) => this.mapArg(arg)).join(' ')
|
||||
}));
|
||||
super.render({ logs });
|
||||
}
|
||||
|
||||
mapArg(arg) {
|
||||
if (arg === null) {
|
||||
return 'null';
|
||||
}
|
||||
if (arg === undefined) {
|
||||
return 'undefined';
|
||||
}
|
||||
if (arg === '') {
|
||||
return '""';
|
||||
}
|
||||
if (!arg || !arg.toString() || typeof arg !== 'object') {
|
||||
return arg ? arg.toString() : arg;
|
||||
}
|
||||
if (arg instanceof Array) {
|
||||
return '[' + arg.map((item) => this.mapArg(item)).join(', ') + ']';
|
||||
}
|
||||
let str = arg.toString();
|
||||
if (str === '[object Object]') {
|
||||
const cache = [];
|
||||
str = JSON.stringify(arg, (key, value) => {
|
||||
if (typeof value === 'object' && value !== null) {
|
||||
if (cache.indexOf(value) !== -1) {
|
||||
return;
|
||||
}
|
||||
cache.push(value);
|
||||
}
|
||||
return value;
|
||||
});
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
export { SettingsLogsView };
|
|
@ -2,10 +2,53 @@ import { FunctionComponent, h } from 'preact';
|
|||
import { SettingsGeneralAdvancedView } from 'views/settings/general/settings-general-advanced-view';
|
||||
import { Launcher } from 'comp/launcher';
|
||||
import { Features } from 'util/features';
|
||||
import { useState } from 'preact/hooks';
|
||||
import { Alerts } from 'comp/ui/alerts';
|
||||
import { Locale } from 'util/locale';
|
||||
import { Links } from 'const/links';
|
||||
import { FileManager } from 'models/file-manager';
|
||||
|
||||
export const SettingsGeneralAdvanced: FunctionComponent = () => {
|
||||
const [showAdvanced, setShowAdvanced] = useState(false);
|
||||
const [showAppLogs, setShowAppLogs] = useState(false);
|
||||
|
||||
const showAdvancedChanged = () => {
|
||||
setShowAdvanced(!showAdvanced);
|
||||
};
|
||||
|
||||
const reloadAppClicked = () => {
|
||||
location.reload();
|
||||
};
|
||||
|
||||
const showDevToolsClicked = () => {
|
||||
Launcher?.ipcRenderer.invoke('show-devtools');
|
||||
};
|
||||
|
||||
const tryBetaClicked = () => {
|
||||
if (FileManager.hasUnsavedFiles) {
|
||||
Alerts.info({
|
||||
header: Locale.setGenTryBetaWarning,
|
||||
body: Locale.setGenTryBetaWarningBody
|
||||
});
|
||||
} else {
|
||||
location.href = Links.BetaWebApp;
|
||||
}
|
||||
};
|
||||
|
||||
const showAppLogsClicked = () => {
|
||||
setShowAppLogs(!showAppLogs);
|
||||
};
|
||||
|
||||
return h(SettingsGeneralAdvancedView, {
|
||||
showAdvanced,
|
||||
showAppLogs,
|
||||
devTools: !!Launcher,
|
||||
showReloadApp: Features.isStandalone
|
||||
showReloadApp: Features.isStandalone,
|
||||
|
||||
showAdvancedChanged,
|
||||
reloadAppClicked,
|
||||
showDevToolsClicked,
|
||||
tryBetaClicked,
|
||||
showAppLogsClicked
|
||||
});
|
||||
};
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
import { FunctionComponent, h } from 'preact';
|
||||
import { SettingsGeneralAppLogsView } from 'views/settings/general/settings-general-app-logs-view';
|
||||
import { Logger, LoggerLevel } from 'util/logger';
|
||||
import { StringFormat } from 'util/formatting/string-format';
|
||||
|
||||
const LevelToColor: Partial<Record<LoggerLevel, string>> = {
|
||||
[LoggerLevel.Debug]: 'muted',
|
||||
[LoggerLevel.Warn]: 'yellow',
|
||||
[LoggerLevel.Error]: 'red'
|
||||
};
|
||||
|
||||
const LevelToString: Record<LoggerLevel, string> = {
|
||||
[LoggerLevel.Off]: 'OFF',
|
||||
[LoggerLevel.All]: 'ALL',
|
||||
[LoggerLevel.Debug]: 'DEBUG',
|
||||
[LoggerLevel.Warn]: 'WARN',
|
||||
[LoggerLevel.Info]: 'INFO',
|
||||
[LoggerLevel.Error]: 'ERROR'
|
||||
};
|
||||
|
||||
function mapArg(arg: unknown): string {
|
||||
if (arg === null) {
|
||||
return 'null';
|
||||
}
|
||||
if (arg === undefined) {
|
||||
return 'undefined';
|
||||
}
|
||||
if (arg === '') {
|
||||
return '""';
|
||||
}
|
||||
if (!arg || !String(arg) || typeof arg !== 'object') {
|
||||
return arg ? String(arg) : '';
|
||||
}
|
||||
if (arg instanceof Array) {
|
||||
return '[' + arg.map((item) => mapArg(item)).join(', ') + ']';
|
||||
}
|
||||
let str = String(arg);
|
||||
if (str === '[object Object]') {
|
||||
const cache = new Set<unknown>();
|
||||
str = JSON.stringify(arg, (key, value) => {
|
||||
if (typeof value === 'object' && value !== null) {
|
||||
if (cache.has(value)) {
|
||||
return;
|
||||
}
|
||||
cache.add(value);
|
||||
}
|
||||
return value as unknown;
|
||||
});
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
export const SettingsGeneralAppLogs: FunctionComponent = () => {
|
||||
const logs = Logger.getLast().map((item) => ({
|
||||
level: LevelToString[item.level],
|
||||
color: LevelToColor[item.level],
|
||||
msg:
|
||||
'[' +
|
||||
StringFormat.padStr(LevelToString[item.level], 5) +
|
||||
'] ' +
|
||||
item.args.map((arg) => mapArg(arg)).join(' ')
|
||||
}));
|
||||
|
||||
return h(SettingsGeneralAppLogsView, {
|
||||
logs
|
||||
});
|
||||
};
|
|
@ -12,7 +12,7 @@ enum Level {
|
|||
const MaxLogsToSave = 100;
|
||||
|
||||
interface LogItem {
|
||||
level: string;
|
||||
level: Level;
|
||||
args: unknown[];
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ class Logger {
|
|||
debug(...args: unknown[]): void {
|
||||
args[0] = `${this.getPrefix()}${String(args[0])}`;
|
||||
if (this.level >= Level.Debug) {
|
||||
Logger.saveLast('debug', args);
|
||||
Logger.saveLast(Level.Debug, args);
|
||||
console.log(...args);
|
||||
}
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ class Logger {
|
|||
info(...args: unknown[]): void {
|
||||
args[0] = `${this.getPrefix()}${String(args[0])}`;
|
||||
if (this.level >= Level.Info) {
|
||||
Logger.saveLast('info', args);
|
||||
Logger.saveLast(Level.Info, args);
|
||||
console.info(...args);
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ class Logger {
|
|||
warn(...args: unknown[]): void {
|
||||
args[0] = `${this.getPrefix()}${String(args[0])}`;
|
||||
if (this.level >= Level.Warn) {
|
||||
Logger.saveLast('warn', args);
|
||||
Logger.saveLast(Level.Warn, args);
|
||||
console.warn(...args);
|
||||
}
|
||||
}
|
||||
|
@ -74,12 +74,12 @@ class Logger {
|
|||
error(...args: unknown[]): void {
|
||||
args[0] = `${this.getPrefix()}${String(args[0])}`;
|
||||
if (this.level >= Level.Error) {
|
||||
Logger.saveLast('error', args);
|
||||
Logger.saveLast(Level.Error, args);
|
||||
console.error(...args);
|
||||
}
|
||||
}
|
||||
|
||||
static saveLast(level: string, args: unknown[]): void {
|
||||
static saveLast(level: Level, args: unknown[]): void {
|
||||
lastLogs.push({ level, args: Array.prototype.slice.call(args) });
|
||||
if (lastLogs.length > MaxLogsToSave) {
|
||||
lastLogs.shift();
|
||||
|
@ -91,4 +91,4 @@ class Logger {
|
|||
}
|
||||
}
|
||||
|
||||
export { Logger };
|
||||
export { Logger, Level as LoggerLevel };
|
||||
|
|
|
@ -1,34 +1,73 @@
|
|||
import { FunctionComponent } from 'preact';
|
||||
import { Locale } from 'util/locale';
|
||||
import { SettingsGeneralAppLogs } from 'ui/settings/general/settings-general-app-logs';
|
||||
|
||||
export const SettingsGeneralAdvancedView: FunctionComponent<{
|
||||
showAdvanced: boolean;
|
||||
devTools: boolean;
|
||||
showReloadApp: boolean;
|
||||
}> = ({ devTools, showReloadApp }) => {
|
||||
showAppLogs: boolean;
|
||||
|
||||
showAdvancedChanged: () => void;
|
||||
reloadAppClicked: () => void;
|
||||
showDevToolsClicked: () => void;
|
||||
tryBetaClicked: () => void;
|
||||
showAppLogsClicked: () => void;
|
||||
}> = ({
|
||||
showAdvanced,
|
||||
devTools,
|
||||
showReloadApp,
|
||||
showAppLogs,
|
||||
|
||||
showAdvancedChanged,
|
||||
reloadAppClicked,
|
||||
showDevToolsClicked,
|
||||
tryBetaClicked,
|
||||
showAppLogsClicked
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<h2 id="advanced">{Locale.advanced}</h2>
|
||||
<a class="settings__general-show-advanced">{Locale.setGenShowAdvanced}</a>
|
||||
<div class="settings__general-advanced hide">
|
||||
{devTools ? (
|
||||
<>
|
||||
<button class="btn-silent settings__general-dev-tools-link">
|
||||
{Locale.setGenDevTools}
|
||||
<p>
|
||||
<a class="settings__general-show-advanced" onClick={showAdvancedChanged}>
|
||||
{Locale.setGenShowAdvanced}
|
||||
</a>
|
||||
</p>
|
||||
{showAdvanced ? (
|
||||
<div class="settings__general-advanced">
|
||||
{devTools ? (
|
||||
<>
|
||||
<button
|
||||
class="btn-silent settings__general-dev-tools-link"
|
||||
onClick={showDevToolsClicked}
|
||||
>
|
||||
{Locale.setGenDevTools}
|
||||
</button>
|
||||
<button
|
||||
class="btn-silent settings__general-try-beta-link"
|
||||
onClick={tryBetaClicked}
|
||||
>
|
||||
{Locale.setGenTryBeta}
|
||||
</button>
|
||||
</>
|
||||
) : null}
|
||||
{showReloadApp ? (
|
||||
<button
|
||||
class="btn-silent settings__general-reload-app-link"
|
||||
onClick={reloadAppClicked}
|
||||
>
|
||||
{Locale.setGenReloadApp}
|
||||
</button>
|
||||
<button class="btn-silent settings__general-try-beta-link">
|
||||
{Locale.setGenTryBeta}
|
||||
</button>
|
||||
</>
|
||||
) : null}
|
||||
{showReloadApp ? (
|
||||
<button class="btn-silent settings__general-reload-app-link">
|
||||
{Locale.setGenReloadApp}
|
||||
) : null}
|
||||
<button
|
||||
class="btn-silent settings__general-show-logs-link"
|
||||
onClick={showAppLogsClicked}
|
||||
>
|
||||
{Locale.setGenShowAppLogs}
|
||||
</button>
|
||||
) : null}
|
||||
<button class="btn-silent settings__general-show-logs-link">
|
||||
{Locale.setGenShowAppLogs}
|
||||
</button>
|
||||
</div>
|
||||
{showAppLogs ? <SettingsGeneralAppLogs /> : null}
|
||||
</div>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
import { FunctionComponent } from 'preact';
|
||||
import { classes } from 'util/ui/classes';
|
||||
import { useLayoutEffect, useRef } from 'preact/hooks';
|
||||
|
||||
interface LogItem {
|
||||
level: string;
|
||||
msg: string;
|
||||
color?: string;
|
||||
}
|
||||
|
||||
export const SettingsGeneralAppLogsView: FunctionComponent<{
|
||||
logs: LogItem[];
|
||||
}> = ({ logs }) => {
|
||||
const lastLine = useRef<HTMLDivElement>();
|
||||
|
||||
useLayoutEffect(() => {
|
||||
lastLine.current.scrollIntoView();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div class="settings__logs">
|
||||
{logs.map((log, ix) => (
|
||||
<pre
|
||||
key={ix}
|
||||
class={classes({
|
||||
'settings__logs-log': true,
|
||||
[`settings__logs-log--${log.level}`]: true,
|
||||
[`${log.color || ''}-color`]: !!log.color
|
||||
})}
|
||||
>
|
||||
{log.msg}
|
||||
</pre>
|
||||
))}
|
||||
<div class="settings__logs-last" ref={lastLine} />
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -1,5 +0,0 @@
|
|||
<div class="settings__logs">
|
||||
{{#each logs as |log|}}
|
||||
<pre class="settings__logs-log settings__logs-log--{{level}} {{#if color}}{{color}}-color{{/if}}">{{msg}}</pre>
|
||||
{{/each}}
|
||||
</div>
|
|
@ -119,4 +119,5 @@ export interface DesktopIpcMainCalls {
|
|||
'minimize-main-window': () => void;
|
||||
'maximize-main-window': () => void;
|
||||
'restore-main-window': () => void;
|
||||
'show-devtools': () => void;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue