mirror of
https://github.com/keepassxreboot/keepassxc-browser.git
synced 2026-03-11 08:54:43 +00:00
Add credential sorting
This commit is contained in:
parent
07d59efebc
commit
a4355c95c2
8 changed files with 110 additions and 21 deletions
|
|
@ -683,6 +683,10 @@
|
|||
"message": "Color theme",
|
||||
"description": "Theme selection header text."
|
||||
},
|
||||
"optionsCredentialSortSelectionHeader": {
|
||||
"message": "Sort matching credentials by",
|
||||
"description": "Credential sort option header text."
|
||||
},
|
||||
"optionsThemeSelection": {
|
||||
"message": "Select color theme",
|
||||
"description": "Theme selection title text."
|
||||
|
|
@ -903,6 +907,22 @@
|
|||
"message": "Disable all features",
|
||||
"description": "Site preferences option selection."
|
||||
},
|
||||
"optionsSortByTitle": {
|
||||
"message": "Title",
|
||||
"desription": "Sort matching credentials by title option selection."
|
||||
},
|
||||
"optionsSortByUsername": {
|
||||
"message": "Username",
|
||||
"desription": "Sort matching credentials by username option selection."
|
||||
},
|
||||
"optionsSortByGroupAndTitle": {
|
||||
"message": "Group and title",
|
||||
"desription": "Sort matching credentials by group and title option selection."
|
||||
},
|
||||
"optionsSortByGroupAndUsername": {
|
||||
"message": "Group and username",
|
||||
"desription": "Sort matching credentials by group and username option selection."
|
||||
},
|
||||
"optionsCustomFieldsNotFound": {
|
||||
"message": "No saved custom login fields found.",
|
||||
"description": "Shown when no saved custom credentials are saved."
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ const defaultSettings = {
|
|||
autoSubmit: false,
|
||||
checkUpdateKeePassXC: 3,
|
||||
colorTheme: 'system',
|
||||
credentialSorting: SORT_BY_GROUP_AND_TITLE,
|
||||
defaultGroup: '',
|
||||
defaultGroupAlwaysAsk: false,
|
||||
redirectAllowance: 1,
|
||||
|
|
@ -82,6 +83,10 @@ page.initSettings = async function() {
|
|||
page.settings.colorTheme = defaultSettings.colorTheme;
|
||||
}
|
||||
|
||||
if (!('credentialSorting' in page.settings)) {
|
||||
page.settings.credentialSorting = defaultSettings.credentialSorting;
|
||||
}
|
||||
|
||||
if (!('defaultGroup' in page.settings)) {
|
||||
page.settings.defaultGroup = defaultSettings.defaultGroup;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,17 @@
|
|||
'use strict';
|
||||
|
||||
// Site Preferences ignore options
|
||||
const IGNORE_NOTHING = 'ignoreNothing';
|
||||
const IGNORE_NORMAL = 'ignoreNormal';
|
||||
const IGNORE_AUTOSUBMIT = 'ignoreAutoSubmit';
|
||||
const IGNORE_FULL = 'ignoreFull';
|
||||
|
||||
// Credential sorting options
|
||||
const SORT_BY_TITLE = 'sortByTitle';
|
||||
const SORT_BY_USERNAME = 'sortByUsername';
|
||||
const SORT_BY_GROUP_AND_TITLE = 'sortByGroupAndTitle';
|
||||
const SORT_BY_GROUP_AND_USERNAME = 'sortByGroupAndUsername';
|
||||
|
||||
const schemeSegment = '(\\*|http|https|ws|wss|file|ftp)';
|
||||
const hostSegment = '(\\*|(?:\\*\\.)?(?:[^/*]+))?';
|
||||
const pathSegment = '(.*)';
|
||||
|
|
|
|||
|
|
@ -1329,25 +1329,46 @@ kpxc.initCredentialFields = async function() {
|
|||
}
|
||||
};
|
||||
|
||||
// Intializes the login popup list for choosing credentials
|
||||
// Intializes the login lists for popup and Autocomplete Menu
|
||||
kpxc.initLoginPopup = function() {
|
||||
if (kpxc.credentials.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const getLoginText = function(credential, withGroup) {
|
||||
const name = credential.name.length < MAX_AUTOCOMPLETE_NAME_LEN
|
||||
// Returns a login item with additional information for sorting
|
||||
const getLoginItem = function(credential, withGroup, loginId) {
|
||||
const title = credential.name.length < MAX_AUTOCOMPLETE_NAME_LEN
|
||||
? credential.name
|
||||
: credential.name.substr(0, MAX_AUTOCOMPLETE_NAME_LEN) + '…';
|
||||
const group = (withGroup && credential.group) ? `[${credential.group}] ` : '';
|
||||
const visibleLogin = (credential.login.length > 0) ? credential.login : tr('credentialsNoUsername');
|
||||
const text = `${group}${name} (${visibleLogin})`;
|
||||
let text = `${group}${title} (${visibleLogin})`;
|
||||
|
||||
if (credential.expired && credential.expired === 'true') {
|
||||
return `${text} [${tr('credentialExpired')}]`;
|
||||
text = `${text} [${tr('credentialExpired')}]`;
|
||||
}
|
||||
|
||||
return text;
|
||||
return {
|
||||
title: title,
|
||||
group: group,
|
||||
visibleLogin: visibleLogin,
|
||||
login: credential.login,
|
||||
loginId: loginId,
|
||||
uuid: credential.uuid,
|
||||
text: text
|
||||
};
|
||||
};
|
||||
|
||||
// Sorting with or without group name included
|
||||
const sortLoginItemBy = function(a, b, name, withGroup = false) {
|
||||
const firstGroup = a.group.toLowerCase();
|
||||
const secondGroup = b.group.toLowerCase();
|
||||
const first = a[name].toLowerCase();
|
||||
const second = b[name].toLowerCase();
|
||||
|
||||
return withGroup
|
||||
? firstGroup.localeCompare(secondGroup) || first.localeCompare(second)
|
||||
: first.localeCompare(second);
|
||||
};
|
||||
|
||||
const getUniqueGroupCount = function(creds) {
|
||||
|
|
@ -1356,25 +1377,43 @@ kpxc.initLoginPopup = function() {
|
|||
return uniqueGroups.size;
|
||||
};
|
||||
|
||||
// Add usernames + descriptions to autocomplete-list and popup-list
|
||||
const usernames = [];
|
||||
kpxcUserAutocomplete.clear();
|
||||
const showGroupNameInAutocomplete = kpxc.settings.showGroupNameInAutocomplete && (getUniqueGroupCount(kpxc.credentials) > 1);
|
||||
|
||||
// Initialize login items
|
||||
const loginItems = [];
|
||||
for (let i = 0; i < kpxc.credentials.length; i++) {
|
||||
const loginText = getLoginText(kpxc.credentials[i], showGroupNameInAutocomplete);
|
||||
usernames.push({ text: loginText, uuid: kpxc.credentials[i].uuid });
|
||||
const loginItem = getLoginItem(kpxc.credentials[i], showGroupNameInAutocomplete, i);
|
||||
loginItems.push(loginItem);
|
||||
}
|
||||
|
||||
// Sort login items
|
||||
if (kpxc.settings.credentialSorting === SORT_BY_TITLE) {
|
||||
loginItems.sort((a, b) => sortLoginItemBy(a, b, 'title'));
|
||||
} else if (kpxc.settings.credentialSorting === SORT_BY_USERNAME) {
|
||||
loginItems.sort((a, b) => sortLoginItemBy(a, b, 'visibleLogin'));
|
||||
} else if (kpxc.settings.credentialSorting === SORT_BY_GROUP_AND_TITLE) {
|
||||
loginItems.sort((a, b) => sortLoginItemBy(a, b, 'title', true));
|
||||
} else if (kpxc.settings.credentialSorting === SORT_BY_GROUP_AND_USERNAME) {
|
||||
loginItems.sort((a, b) => sortLoginItemBy(a, b, 'visibleLogin', true));
|
||||
}
|
||||
|
||||
const popupLoginItems = [];
|
||||
kpxcUserAutocomplete.clear();
|
||||
|
||||
// Initialize Popup Login and Autocomplete Menu items
|
||||
for (const l of loginItems) {
|
||||
popupLoginItems.push({ text: l.text, uuid: l.uuid });
|
||||
|
||||
kpxcUserAutocomplete.elements.push({
|
||||
label: loginText,
|
||||
value: kpxc.credentials[i].login,
|
||||
uuid: kpxc.credentials[i].uuid,
|
||||
loginId: i
|
||||
label: l.text,
|
||||
value: l.login,
|
||||
uuid: l.uuid,
|
||||
loginId: l.loginId
|
||||
});
|
||||
}
|
||||
|
||||
// Generate popup-list of usernames + descriptions
|
||||
sendMessage('popup_login', usernames);
|
||||
// Activate Popup Login list of usernames + descriptions
|
||||
sendMessage('popup_login', popupLoginItems);
|
||||
};
|
||||
|
||||
kpxc.passwordFilled = async function() {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"name": "KeePassXC-Browser",
|
||||
"version": "1.7.6",
|
||||
"version_name": "1.7.6",
|
||||
"version": "1.7.7",
|
||||
"version_name": "1.7.7",
|
||||
"description": "__MSG_extensionDescription__",
|
||||
"author": "KeePassXC Team",
|
||||
"icons": {
|
||||
|
|
|
|||
|
|
@ -140,6 +140,18 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<label for="credentialSorting" data-i18n="optionsCredentialSortSelectionHeader"></label>
|
||||
<select class="form-control form-control-sm col-md-2" id="credentialSorting" data-i18n="[title]optionsCredentialSortSelection">
|
||||
<option value="sortByTitle" data-i18n="optionsSortByTitle"></option>
|
||||
<option value="sortByUsername" data-i18n="optionsSortByUsername"></option>
|
||||
<option value="sortByGroupAndTitle" data-i18n="optionsSortByGroupAndTitle"></option>
|
||||
<option value="sortByGroupAndUsername" data-i18n="optionsSortByGroupAndUsername"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" name="autoSubmit" id="autoSubmit" value="true" />
|
||||
|
|
|
|||
|
|
@ -73,12 +73,17 @@ options.initGeneralSettings = function() {
|
|||
$('#tab-general-settings select#colorTheme').val(options.settings['colorTheme']);
|
||||
}
|
||||
|
||||
$('#tab-general-settings select:first').change(async function() {
|
||||
$('#tab-general-settings select#colorTheme').change(async function() {
|
||||
options.settings['colorTheme'] = $(this).val();
|
||||
await options.saveSettings();
|
||||
location.reload();
|
||||
});
|
||||
|
||||
$('#tab-general-settings select#credentialSorting').change(async function() {
|
||||
options.settings['credentialSorting'] = $(this).val();
|
||||
await options.saveSettings();
|
||||
});
|
||||
|
||||
$('#tab-general-settings input[type=checkbox]').each(function() {
|
||||
$(this).attr('checked', options.settings[$(this).attr('name')]);
|
||||
if ($(this).attr('name') === 'defaultGroupAlwaysAsk' && $(this).attr('checked')) {
|
||||
|
|
@ -115,6 +120,7 @@ options.initGeneralSettings = function() {
|
|||
}
|
||||
});
|
||||
|
||||
$('#tab-general-settings select#credentialSorting').val(options.settings['credentialSorting']);
|
||||
$('#tab-general-settings input#defaultGroup').val(options.settings['defaultGroup']);
|
||||
|
||||
$('#tab-general-settings input[type=radio]').each(function() {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "KeePassXC-Browser",
|
||||
"version": "1.7.6",
|
||||
"version": "1.7.7",
|
||||
"description": "KeePassXC-Browser",
|
||||
"main": "build.js",
|
||||
"devDependencies": {
|
||||
|
|
|
|||
Loading…
Reference in a new issue