diff --git a/.eslintrc b/.eslintrc index 229d494..9ace490 100644 --- a/.eslintrc +++ b/.eslintrc @@ -115,6 +115,7 @@ "IGNORE_FULL": true, "IGNORE_NORMAL": true, "IGNORE_NOTHING": true, + "importScripts": true, "initColorTheme": true, "isEdge": true, "isFirefox": true, diff --git a/build.js b/build.js index a5c6a40..f44c6a8 100755 --- a/build.js +++ b/build.js @@ -13,25 +13,11 @@ const BROWSERS = { 'Chromium': 'manifest_chromium.json', }; -async function adjustManifest(manifest) { +async function getDestinationFilename(manifest) { const manifestFile = await fs.readFile(DEFAULT, { encoding: 'utf8' }); const data = JSON.parse(manifestFile); const browser = manifest.substring(manifest.indexOf('_') + 1, manifest.indexOf('.')); - if (manifest.includes('firefox')) { - for (const elem in data['icons']) { - data['icons'][elem] = 'icons/keepassxc.svg'; - } - for (const elem in data['browser_action']['default_icon']) { - data['browser_action']['default_icon'][elem] = 'icons/keepassxc.svg'; - } - delete data['version_name']; - delete data['minimum_chrome_version']; - } else if (manifest.includes('chromium')) { - delete data['applications']; - } - - await fs.writeFile(manifest, JSON.stringify(data, null, 4)); return `keepassxc-browser_${data['version']}_${browser}.zip`; } @@ -52,15 +38,14 @@ async function updateTranslations() { for (const browser in BROWSERS) { console.log(`KeePassXC-Browser: Creating extension package for ${browser}`); - const fileName = await adjustManifest(BROWSERS[browser]); - await fs.copyFile(BROWSERS[browser], `${DEST}/manifest.json`); + const fileName = await getDestinationFilename(BROWSERS[browser]); + await fs.copyFile(`./dist/${BROWSERS[browser]}`, `${DEST}/manifest.json`); if (await fs.exists(fileName)) { await fs.rm(fileName); } await zaf.zip(DEST, fileName); - await fs.rm(BROWSERS[browser], { recursive: true }); console.log('Done'); } diff --git a/dist/manifest_chromium.json b/dist/manifest_chromium.json new file mode 100755 index 0000000..9e1b05c --- /dev/null +++ b/dist/manifest_chromium.json @@ -0,0 +1,160 @@ +{ + "manifest_version": 3, + "name": "KeePassXC-Browser", + "version": "1.8.11", + "version_name": "1.8.11", + "minimum_chrome_version": "93", + "description": "__MSG_extensionDescription__", + "author": "KeePassXC Team", + "icons": { + "16": "icons/keepassxc_16x16.png", + "48": "icons/keepassxc_48x48.png", + "64": "icons/keepassxc_64x64.png", + "96": "icons/keepassxc_96x96.png", + "128": "icons/keepassxc_128x128.png" + }, + "action": { + "default_icon": { + "16": "icons/keepassxc_16x16.png", + "18": "icons/keepassxc_18x18.png", + "19": "icons/keepassxc_19x19.png", + "32": "icons/keepassxc_32x32.png", + "36": "icons/keepassxc_36x36.png", + "38": "icons/keepassxc_38x38.png", + "64": "icons/keepassxc_64x64.png" + }, + "default_title": "KeePassXC-Browser", + "default_popup": "popups/popup.html" + }, + "options_ui": { + "page": "options/options.html", + "open_in_tab": true + }, + "background": { + "service_worker": "background/background_service.js" + }, + "content_scripts": [ + { + "matches": [ + "" + ], + "js": [ + "common/browser-polyfill.min.js", + "common/global.js", + "common/global_ui.js", + "common/sites.js", + "content/ui.js", + "content/banner.js", + "content/autocomplete.js", + "content/credential-autocomplete.js", + "content/custom-fields-banner.js", + "content/fields.js", + "content/fill.js", + "content/form.js", + "content/icons.js", + "content/keepassxc-browser.js", + "content/observer-helper.js", + "content/pwgen.js", + "content/totp-autocomplete.js", + "content/totp-field.js", + "content/username-field.js", + "content/passkeys-utils.js" + ], + "run_at": "document_idle", + "all_frames": true + } + ], + "commands": { + "fill_username_password": { + "description": "__MSG_contextMenuFillUsernameAndPassword__", + "suggested_key": { + "default": "Alt+Shift+U", + "mac": "MacCtrl+Shift+U" + } + }, + "fill_password": { + "description": "__MSG_contextMenuFillPassword__", + "suggested_key": { + "default": "Alt+Shift+I", + "mac": "MacCtrl+Shift+I" + } + }, + "fill_totp": { + "description": "__MSG_contextMenuFillTOTP__", + "suggested_key": { + "default": "Alt+Shift+O", + "mac": "MacCtrl+Shift+O" + } + }, + "show_password_generator": { + "description": "__MSG_contextMenuShowPasswordGenerator__", + "suggested_key": { + "default": "Alt+Shift+G", + "mac": "MacCtrl+Shift+G" + } + }, + "save_credentials": { + "description": "__MSG_contextMenuSaveCredentials__" + }, + "redetect_fields": { + "description": "__MSG_popupRedetectButton__" + }, + "choose_credential_fields": { + "description": "__MSG_popupChooseCredentialsText__" + }, + "retrive_credentials_forced": { + "description": "__MSG_popupReopenButton__" + }, + "request_autotype": { + "description": "__MSG_contextMenuRequestGlobalAutoType__" + }, + "reload_extension": { + "description": "__MSG_popupReloadButton__" + } + }, + "web_accessible_resources": [{ + "resources": [ + "icons/disconnected.svg", + "icons/help.svg", + "icons/keepassxc.svg", + "icons/key.svg", + "icons/locked.svg", + "icons/otp.svg", + "css/autocomplete.css", + "css/banner.css", + "css/button.css", + "css/colors.css", + "css/define.css", + "css/notification.css", + "css/pwgen.css", + "css/username.css", + "css/totp.css", + "content/passkeys.js" + ], + "matches": [ + "https://*/*", + "http://*/*" + ] + }], + "permissions": [ + "activeTab", + "contextMenus", + "clipboardWrite", + "nativeMessaging", + "notifications", + "storage", + "tabs", + "webNavigation", + "webRequest", + "webRequestAuthProvider", + "webRequestBlocking" + ], + "content_security_policy": { + "extension_pages": "script-src 'self'" + }, + "host_permissions": [ + "https://*/*", + "http://*/*" + ], + "default_locale": "en" +} diff --git a/dist/manifest_firefox.json b/dist/manifest_firefox.json new file mode 100644 index 0000000..1ee0947 --- /dev/null +++ b/dist/manifest_firefox.json @@ -0,0 +1,166 @@ +{ + "manifest_version": 2, + "name": "KeePassXC-Browser", + "version": "1.8.11", + "description": "__MSG_extensionDescription__", + "author": "KeePassXC Team", + "icons": { + "16": "icons/keepassxc.svg", + "48": "icons/keepassxc.svg", + "64": "icons/keepassxc.svg", + "96": "icons/keepassxc.svg", + "128": "icons/keepassxc.svg" + }, + "browser_action": { + "default_icon": { + "16": "icons/keepassxc.svg", + "18": "icons/keepassxc.svg", + "19": "icons/keepassxc.svg", + "32": "icons/keepassxc.svg", + "36": "icons/keepassxc.svg", + "38": "icons/keepassxc.svg", + "64": "icons/keepassxc.svg" + }, + "default_title": "KeePassXC-Browser", + "default_popup": "popups/popup.html" + }, + "options_ui": { + "page": "options/options.html", + "open_in_tab": true + }, + "background": { + "scripts": [ + "common/browser-polyfill.min.js", + "common/global.js", + "common/sites.js", + "background/nacl.min.js", + "background/nacl-util.min.js", + "background/client.js", + "background/keepass.js", + "background/httpauth.js", + "background/browserAction.js", + "background/page.js", + "background/event.js", + "background/init.js" + ] + }, + "content_scripts": [ + { + "matches": [ + "" + ], + "js": [ + "common/browser-polyfill.min.js", + "common/global.js", + "common/sites.js", + "content/ui.js", + "content/banner.js", + "content/autocomplete.js", + "content/credential-autocomplete.js", + "content/custom-fields-banner.js", + "content/fields.js", + "content/fill.js", + "content/form.js", + "content/icons.js", + "content/keepassxc-browser.js", + "content/observer-helper.js", + "content/pwgen.js", + "content/totp-autocomplete.js", + "content/totp-field.js", + "content/username-field.js", + "content/passkeys-utils.js" + ], + "run_at": "document_idle", + "all_frames": true + } + ], + "commands": { + "fill_username_password": { + "description": "__MSG_contextMenuFillUsernameAndPassword__", + "suggested_key": { + "default": "Alt+Shift+U", + "mac": "MacCtrl+Shift+U" + } + }, + "fill_password": { + "description": "__MSG_contextMenuFillPassword__", + "suggested_key": { + "default": "Alt+Shift+I", + "mac": "MacCtrl+Shift+I" + } + }, + "fill_totp": { + "description": "__MSG_contextMenuFillTOTP__", + "suggested_key": { + "default": "Alt+Shift+O", + "mac": "MacCtrl+Shift+O" + } + }, + "show_password_generator": { + "description": "__MSG_contextMenuShowPasswordGenerator__", + "suggested_key": { + "default": "Alt+Shift+G", + "mac": "MacCtrl+Shift+G" + } + }, + "save_credentials": { + "description": "__MSG_contextMenuSaveCredentials__" + }, + "redetect_fields": { + "description": "__MSG_popupRedetectButton__" + }, + "choose_credential_fields": { + "description": "__MSG_popupChooseCredentialsText__" + }, + "retrive_credentials_forced": { + "description": "__MSG_popupReopenButton__" + }, + "request_autotype": { + "description": "__MSG_contextMenuRequestGlobalAutoType__" + }, + "reload_extension": { + "description": "__MSG_popupReloadButton__" + } + }, + "web_accessible_resources": [ + "icons/disconnected.svg", + "icons/help.svg", + "icons/keepassxc.svg", + "icons/key.svg", + "icons/locked.svg", + "icons/otp.svg", + "css/autocomplete.css", + "css/banner.css", + "css/button.css", + "css/colors.css", + "css/define.css", + "css/notification.css", + "css/pwgen.css", + "css/username.css", + "css/totp.css", + "content/passkeys.js" + ], + "permissions": [ + "activeTab", + "contextMenus", + "clipboardWrite", + "nativeMessaging", + "notifications", + "storage", + "tabs", + "webNavigation", + "webRequest", + "webRequestBlocking", + "https://*/*", + "http://*/*", + "https://api.github.com/" + ], + "content_security_policy": "script-src 'self' 'sha256-4nJ8uLezzRE3SiBFdkVN/uNwV9YTOGCqRXg6AvB5rCY='; object-src 'none'", + "applications": { + "gecko": { + "id": "keepassxc-browser@keepassxc.org", + "strict_min_version": "67.0" + } + }, + "default_locale": "en" +} diff --git a/keepassxc-browser/background/background_service.js b/keepassxc-browser/background/background_service.js new file mode 100644 index 0000000..06c21b8 --- /dev/null +++ b/keepassxc-browser/background/background_service.js @@ -0,0 +1,20 @@ +'use strict'; + +try { + importScripts( + '../common/browser-polyfill.min.js', + '../common/global.js', + '../common/sites.js', + 'nacl.min.js', + 'nacl-util.min.js', + 'client.js', + 'keepass.js', + 'httpauth.js', + 'browserAction.js', + 'page.js', + 'event.js', + 'init.js' + ); +} catch (e) { + console.log('Cannot import background scripts: ', e); +} diff --git a/keepassxc-browser/background/browserAction.js b/keepassxc-browser/background/browserAction.js index 7b6a7af..e497f35 100755 --- a/keepassxc-browser/background/browserAction.js +++ b/keepassxc-browser/background/browserAction.js @@ -1,17 +1,18 @@ 'use strict'; +const browserActionWrapper = browser.action || browser.browserAction; const browserAction = {}; -browserAction.show = function(tab, popupData) { +browserAction.show = async function(tab, popupData) { popupData ??= page.popupData; page.popupData = popupData; - browser.browserAction.setIcon({ - path: browserAction.generateIconName(popupData.iconType) + browserActionWrapper.setIcon({ + path: await browserAction.generateIconName(popupData.iconType) }); if (popupData.popup) { - browser.browserAction.setPopup({ + browserActionWrapper.setPopup({ tabId: tab.id, popup: `popups/${popupData.popup}.html` }); @@ -47,12 +48,27 @@ browserAction.showDefault = async function(tab) { popupData.popup = 'popup_login'; } - browserAction.show(tab, popupData); + await browserAction.show(tab, popupData); }; -browserAction.generateIconName = function(iconType) { +browserAction.updateIcon = async function(tab, iconType) { + if (!tab) { + const tabs = await browser.tabs.query({ 'active': true, 'currentWindow': true }); + if (tabs.length === 0) { + return; + } + + tab = tabs[0]; + } + + browserActionWrapper.setIcon({ + path: browserAction.generateIconName(iconType) + }); +}; + +browserAction.generateIconName = async function(iconType) { let name = 'icon_'; - name += (keepass.keePassXCUpdateAvailable()) ? 'new_' : ''; + name += (await keepass.keePassXCUpdateAvailable()) ? 'new_' : ''; name += (!iconType || iconType === 'normal') ? 'normal' : iconType; let style = 'colored'; @@ -72,7 +88,6 @@ browserAction.ignoreSite = async function(url) { const tab = await getCurrentTab(); // Send the message to the current tab's content script - await browser.runtime.getBackgroundPage(); browser.tabs.sendMessage(tab.id, { action: 'ignore_site', args: [ url ] diff --git a/keepassxc-browser/background/event.js b/keepassxc-browser/background/event.js index 06e4625..cafb943 100755 --- a/keepassxc-browser/background/event.js +++ b/keepassxc-browser/background/event.js @@ -135,12 +135,12 @@ kpxcEvent.onGetKeePassXCVersions = async function(tab) { }; kpxcEvent.onCheckUpdateKeePassXC = async function() { - keepass.checkForNewKeePassXCVersion(); + await keepass.checkForNewKeePassXCVersion(); return { current: keepass.currentKeePassXC, latest: keepass.latestKeePassXC.version }; }; kpxcEvent.onUpdateAvailableKeePassXC = async function() { - return (Number(page.settings.checkUpdateKeePassXC) !== CHECK_UPDATE_NEVER) ? keepass.keePassXCUpdateAvailable() : false; + return (Number(page.settings.checkUpdateKeePassXC) !== CHECK_UPDATE_NEVER) ? await keepass.keePassXCUpdateAvailable() : false; }; kpxcEvent.onRemoveCredentialsFromTabInformation = async function(tab) { @@ -156,7 +156,7 @@ kpxcEvent.onLoginPopup = async function(tab, logins) { }; page.tabs[tab.id].loginList = logins; - browserAction.show(tab, popupData); + await browserAction.show(tab, popupData); }; kpxcEvent.initHttpAuth = async function() { @@ -170,7 +170,7 @@ kpxcEvent.onHTTPAuthPopup = async function(tab, data) { }; page.tabs[tab.id].loginList = data; - browserAction.show(tab, popupData); + await browserAction.show(tab, popupData); }; kpxcEvent.onUsernameFieldDetected = async function(tab, detected) { diff --git a/keepassxc-browser/background/init.js b/keepassxc-browser/background/init.js index 80cfc8f..add144c 100644 --- a/keepassxc-browser/background/init.js +++ b/keepassxc-browser/background/init.js @@ -130,14 +130,7 @@ for (const item of contextMenuItems) { title: item.title, contexts: menuContexts, visible: item.visible, - id: item.id, - onclick: (info, tab) => { - browser.tabs.sendMessage(tab.id, { - action: item.action - }).catch((err) => { - logError(err); - }); - } + id: item.id || item.action }); } @@ -154,3 +147,25 @@ browser.commands.onCommand.addListener(async (command) => { } } }); + +browser.contextMenus.onClicked.addListener(async (item, tab) => { + if (item?.menuItemId?.startsWith('fill_attribute')) { + const menuItem = page.attributeMenuItems.find(i => i?.action === item?.menuItemId); + if (menuItem) { + browser.tabs.sendMessage(tab.id, { + action: 'fill_attribute', + args: menuItem?.args + }).catch((err) => { + logError(err); + }); + } + + return; + } + + browser.tabs.sendMessage(tab.id, { + action: item.menuItemId + }).catch((err) => { + logError(err); + }); +}); diff --git a/keepassxc-browser/background/keepass.js b/keepassxc-browser/background/keepass.js index cc50daa..3462545 100755 --- a/keepassxc-browser/background/keepass.js +++ b/keepassxc-browser/background/keepass.js @@ -715,6 +715,7 @@ keepass.saveKey = function(hash, id, key) { keepass.keyRing[hash].created = new Date().valueOf(); keepass.keyRing[hash].lastUsed = new Date().valueOf(); } + browser.storage.local.set({ 'keyRing': keepass.keyRing }); }; @@ -861,13 +862,13 @@ keepass.setcurrentKeePassXCVersion = function(version) { } }; -keepass.keePassXCUpdateAvailable = function() { +keepass.keePassXCUpdateAvailable = async function() { const checkUpdate = Number(page.settings.checkUpdateKeePassXC); if (checkUpdate !== CHECK_UPDATE_NEVER) { const lastChecked = (keepass.latestKeePassXC.lastChecked) ? new Date(keepass.latestKeePassXC.lastChecked) : new Date(1986, 11, 21); const daysSinceLastCheck = Math.floor(((new Date()).getTime() - lastChecked.getTime()) / 86400000); if (daysSinceLastCheck >= checkUpdate) { - keepass.checkForNewKeePassXCVersion(); + await keepass.checkForNewKeePassXCVersion(); } return keepass.compareVersion(keepass.currentKeePassXC, keepass.latestKeePassXC.version, false); @@ -876,33 +877,18 @@ keepass.keePassXCUpdateAvailable = function() { return false; }; -keepass.checkForNewKeePassXCVersion = function() { - const xhr = new XMLHttpRequest(); +keepass.checkForNewKeePassXCVersion = async function() { let version = -1; - xhr.onload = function(e) { - if (xhr.readyState === 4 && xhr.status === 200) { - const json = JSON.parse(xhr.responseText); - if (json.tag_name && json.prerelease === false) { - version = json.tag_name; - keepass.latestKeePassXC.version = version; - } - } - - if (version !== -1) { - browser.storage.local.set({ 'latestKeePassXC': keepass.latestKeePassXC }); - } - }; - - xhr.onerror = function(err) { - logError(`checkForNewKeePassXCVersion error: ${err}`); - }; - try { - xhr.open('GET', keepass.latestVersionUrl, true); - xhr.send(); + const response = await fetch(keepass.latestVersionUrl); + const jsonData = await response.json(); + if (jsonData?.tag_name && jsonData?.prerelease === false) { + version = jsonData.tag_name; + keepass.latestKeePassXC.version = version; + } } catch (ex) { - logError(ex); + logError(`checkForNewKeePassXCVersion error: ${ex}`); } keepass.latestKeePassXC.lastChecked = new Date().valueOf(); }; diff --git a/keepassxc-browser/background/page.js b/keepassxc-browser/background/page.js index 0774047..aebb730 100755 --- a/keepassxc-browser/background/page.js +++ b/keepassxc-browser/background/page.js @@ -38,7 +38,7 @@ const AUTO_SUBMIT_TIMEOUT = 5000; const page = {}; page.autoSubmitPerformed = false; -page.attributeMenuItemIds = []; +page.attributeMenuItems = []; page.blockedTabs = []; page.clearCredentialsTimeout = null; page.currentRequest = {}; @@ -295,9 +295,10 @@ page.fillHttpAuth = async function(tab, credentials) { // Update context menu for attribute filling page.updateContextMenu = async function(tab, credentials) { // Remove any old attribute items - while (page.attributeMenuItemIds.length) { - browser.contextMenus.remove(page.attributeMenuItemIds.pop()); - } + page.attributeMenuItems.forEach(item => { + browser.contextMenus.remove(item?.action); + }); + page.attributeMenuItems = []; // Set parent item visibility browser.contextMenus.update('fill_attribute', { visible: true }); @@ -315,12 +316,15 @@ page.updateContextMenu = async function(tab, credentials) { ? `[${cred.login}] ${attributeName}` : attributeName; - page.attributeMenuItemIds.push(createContextMenuItem({ - action: 'fill_attribute', + const menuItem = { + action: `fill_attribute_${finalName}`, args: attribute, parentId: 'fill_attribute', title: finalName - })); + }; + + createContextMenuItem(menuItem); + page.attributeMenuItems.push(menuItem); } } }; @@ -332,14 +336,7 @@ page.updatePopup = function(tab) { const createContextMenuItem = function({ action, args, ...options }) { return browser.contextMenus.create({ contexts: menuContexts, - onclick: (info, tab) => { - browser.tabs.sendMessage(tab.id, { - action: action, - args: args - }).catch((err) => { - logError(err); - }); - }, + id: action, ...options }); }; diff --git a/keepassxc-browser/common/global.js b/keepassxc-browser/common/global.js index fe84b65..d16b57d 100755 --- a/keepassxc-browser/common/global.js +++ b/keepassxc-browser/common/global.js @@ -37,7 +37,7 @@ const isEdge = function() { const showNotification = function(message) { browser.notifications.create({ 'type': 'basic', - 'iconUrl': browser.extension.getURL('icons/keepassxc_64x64.png'), + 'iconUrl': browser.runtime.getURL('icons/keepassxc_64x64.png'), 'title': 'KeePassXC-Browser', 'message': message }); @@ -158,11 +158,3 @@ const getCurrentTab = async function() { const tabs = await browser.tabs.query({ active: true, currentWindow: true }); return tabs.length > 0 ? tabs[0] : undefined; }; - -HTMLElement.prototype.show = function() { - this.style.display = 'block'; -}; - -HTMLElement.prototype.hide = function() { - this.style.display = 'none'; -}; diff --git a/keepassxc-browser/common/global_ui.js b/keepassxc-browser/common/global_ui.js new file mode 100644 index 0000000..582a441 --- /dev/null +++ b/keepassxc-browser/common/global_ui.js @@ -0,0 +1,9 @@ +'use strict'; + +HTMLElement.prototype.show = function() { + this.style.display = 'block'; +}; + +HTMLElement.prototype.hide = function() { + this.style.display = 'none'; +}; diff --git a/keepassxc-browser/content/keepassxc-browser.js b/keepassxc-browser/content/keepassxc-browser.js index efde0a3..9004316 100755 --- a/keepassxc-browser/content/keepassxc-browser.js +++ b/keepassxc-browser/content/keepassxc-browser.js @@ -10,7 +10,6 @@ const sendMessage = async function(action, args) { return await browser.runtime.sendMessage({ action: action, args: args }); }; - /** * @Object kpxc * The main content script object. diff --git a/keepassxc-browser/options/options.html b/keepassxc-browser/options/options.html index 10f4ede..c71dc97 100644 --- a/keepassxc-browser/options/options.html +++ b/keepassxc-browser/options/options.html @@ -13,18 +13,11 @@ + -
diff --git a/keepassxc-browser/options/options.js b/keepassxc-browser/options/options.js index 4cbe9a4..cdc20fb 100644 --- a/keepassxc-browser/options/options.js +++ b/keepassxc-browser/options/options.js @@ -58,7 +58,7 @@ options.saveKeyRing = async function() { }); }; -options.initGeneralSettings = function() { +options.initGeneralSettings = async function() { const changeCheckboxValue = async function(e) { const name = e.currentTarget.name; const isChecked = e.currentTarget.checked; @@ -173,7 +173,7 @@ options.initGeneralSettings = function() { await options.saveSettings(); }); - browser.runtime.sendMessage({ + await browser.runtime.sendMessage({ action: 'get_keepassxc_versions' }).then(options.showKeePassXCVersions); @@ -681,13 +681,20 @@ const getBrowserId = function() { (async() => { try { + // We eagerly load the theme here to avoid a white flash + let theme = localStorage.getItem('colorTheme') || 'system'; + if (theme === 'system') { + theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; + } + document.documentElement.setAttribute('data-bs-theme', theme); + const settings = await browser.runtime.sendMessage({ action: 'load_settings' }); options.settings = settings; const keyRing = await browser.runtime.sendMessage({ action: 'load_keyring' }); options.keyRing = keyRing; options.initMenu(); - options.initGeneralSettings(); + await options.initGeneralSettings(); options.initConnectedDatabases(); options.initCustomLoginFields(); options.initSitePreferences(); diff --git a/keepassxc-browser/popups/popup.css b/keepassxc-browser/popups/popup.css index f2245e8..3f0929f 100644 --- a/keepassxc-browser/popups/popup.css +++ b/keepassxc-browser/popups/popup.css @@ -116,6 +116,14 @@ code { text-align: start; } +#filter-block, +#not-configured, +#need-reconfigure, +#configured-not-associated, +#configured-and-associated, +#error-encountered, +#database-not-opened, +#username-field-detected, #update-available, #getting-started-guide, #troubleshooting-guide { @@ -163,6 +171,10 @@ code { text-align: right; } +#left-margin { + margin-left: 1em; +} + @media (prefers-color-scheme: dark), (prefers-color-scheme: light) { body { background: var(--kpxc-background-color) !important; diff --git a/keepassxc-browser/popups/popup.html b/keepassxc-browser/popups/popup.html index 45a01da..d6f44d0 100644 --- a/keepassxc-browser/popups/popup.html +++ b/keepassxc-browser/popups/popup.html @@ -9,6 +9,7 @@ + @@ -56,7 +57,7 @@

-