1
0
Fork 0
mirror of https://github.com/betaflight/betaflight-configurator.git synced 2025-07-23 16:25:22 +03:00

Add support for multiple presets repositories to be active at once (#3476)

* Add support for multiple presets repositories to be active at once

* Code-style changes to src/tabs/presets/presets.js

Co-authored-by: Mark Haslinghuis <mark@numloq.nl>

* Code-review changes

* Show presets repo name only when non-official repos are enabled

* Code-review changes

* Trim preset title not to overlap icons

---------

Co-authored-by: Mark Haslinghuis <mark@numloq.nl>
This commit is contained in:
Richard Benkovsky 2023-06-21 11:49:18 -07:00 committed by GitHub
parent b328324b61
commit ad9b29e6b6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 186 additions and 78 deletions

View file

@ -6857,6 +6857,10 @@
"message": "Keywords:",
"description": "Hint text in the presets detailed dialog"
},
"presetsSourceRepository": {
"message": "Source:",
"description": "Text prefixing user defined name of the preset repository containing a preset"
},
"presetsVersions": {
"message": "Firmware:",
"description": "Hint text in the presets detailed dialog"
@ -7005,6 +7009,10 @@
"message": "Make Active",
"description": "Presets tab, sources dialog, button to make selected source active"
},
"presetsSourcesDialogMakeSourceDisable": {
"message": "Make disabled",
"description": "Presets tab, sources dialog, button to make selected source disabled"
},
"presetsSourcesDialogDeleteSource": {
"message": "Delete",
"description": "Presets tab, sources dialog, button to delete selected source"
@ -7013,6 +7021,10 @@
"message": "<span class=\"message-negative\">WARNING!</span> A third party preset source is selected.",
"description": "Warning message that shows up when a third party preset source is selected"
},
"presetsFailedToLoadRepositories": {
"message": "<span class=\"message-negative\">WARNING!</span> Failed to load following repositories: <b>{{repos}}</b>",
"description": "Warning message that shows up when we fail to load some repositories"
},
"presetsWarningBackup": {
"message": "Please make sure you backup your current configuration ('$t(presetsBackupSave.message)' button or via CLI if the button is disabled) <strong>before</strong> picking and applying presets. Otherwise there is no way to return to previous configuration after applying presets.",
"description": "Warning message that shows up at the top of the presets tab"

View file

@ -26,9 +26,10 @@ export default class PresetsDetailedDialog {
});
}
open(preset, presetsRepo) {
open(preset, presetsRepo, showPresetRepoName) {
this._presetsRepo = presetsRepo;
this._preset = preset;
this._showPresetRepoName = showPresetRepoName;
this._setLoadingState(true);
this._domDialog[0].showModal();
this._optionsShowedAtLeastOnce = false;
@ -78,8 +79,8 @@ export default class PresetsDetailedDialog {
}
this._titlePanel.empty();
const titlePanel = new PresetTitlePanel(this._titlePanel, this._preset, false,
() => this._setLoadingState(false), this._favoritePresets);
const titlePanel = new PresetTitlePanel(this._titlePanel, this._preset, this._presetsRepo, false,
this._showPresetRepoName, () => this._setLoadingState(false), this._favoritePresets);
titlePanel.load();
this._loadOptionsSelect();
this._updateFinalCliText();
@ -263,7 +264,7 @@ export default class PresetsDetailedDialog {
_pickPreset() {
const cliStrings = this._getFinalCliText();
const pickedPreset = new PickedPreset(this._preset, cliStrings);
const pickedPreset = new PickedPreset(this._preset, cliStrings, this._presetsRepo);
this._pickedPresetList.push(pickedPreset);
this._onPresetPickedCallback?.();
this._isPresetPickedOnClose = true;

View file

@ -75,19 +75,19 @@ class FavoritePresetsClass {
this._favoritePresetsData = new FavoritePresetsData();
}
add(preset) {
const favoritePreset = this._favoritePresetsData.add(preset.fullPath);
add(preset, repo) {
const favoritePreset = this._favoritePresetsData.add(repo.getPresetOnlineLink(preset));
preset.lastPickDate = favoritePreset.lastPickDate;
}
delete(preset) {
this._favoritePresetsData.delete(preset.fullPath);
delete(preset, repo) {
this._favoritePresetsData.delete(repo.getPresetOnlineLink(preset));
preset.lastPickDate = undefined;
}
addLastPickDate(presets) {
addLastPickDate(presets, repo) {
for (let preset of presets) {
let favoritePreset = this._favoritePresetsData.findPreset(preset.fullPath);
let favoritePreset = this._favoritePresetsData.findPreset(repo.getPresetOnlineLink(preset));
if (favoritePreset) {
preset.lastPickDate = favoritePreset.lastPickDate;

View file

@ -1,8 +1,9 @@
export default class PickedPreset
{
constructor(preset, presetCli)
constructor(preset, presetCli, presetRepo)
{
this.preset = preset;
this.presetCli = presetCli;
this.presetRepo = presetRepo;
}
}

View file

@ -1,7 +1,7 @@
import PresetsRepoIndexed from "./PresetsRepoIndexed";
export default class PresetsGithubRepo extends PresetsRepoIndexed {
constructor(urlRepo, branch) {
constructor(urlRepo, branch, official, name) {
let correctUrlRepo = urlRepo.trim();
if (!correctUrlRepo.endsWith("/")) {
@ -21,6 +21,6 @@ export default class PresetsGithubRepo extends PresetsRepoIndexed {
const urlRaw = `https://raw.githubusercontent.com${correctUrlRepo.slice("https://github.com".length)}${correctBranch}/`;
const urlViewOnline = `${correctUrlRepo}blob/${correctBranch}/`;
super(urlRaw, urlViewOnline);
super(urlRaw, urlViewOnline, official, name);
}
}

View file

@ -1,16 +1,26 @@
import PresetParser from "./PresetParser";
export default class PresetsRepoIndexed {
constructor(urlRaw, urlViewOnline) {
constructor(urlRaw, urlViewOnline, official, name) {
this._urlRaw = urlRaw;
this._urlViewOnline = urlViewOnline;
this._index = null;
this._name = name;
this._official = official;
}
get index() {
return this._index;
}
get official() {
return this._official;
}
get name() {
return this._name;
}
loadIndex() {
return fetch(`${this._urlRaw}index.json`, {cache: "no-cache"})
.then(res => res.json())

View file

@ -1,7 +1,7 @@
import PresetsRepoIndexed from "./PresetsRepoIndexed";
export default class PresetsWebsiteRepo extends PresetsRepoIndexed {
constructor(url) {
constructor(url, official, name) {
let correctUrl = url.trim();
if (!correctUrl.endsWith("/")) {
@ -11,6 +11,6 @@ export default class PresetsWebsiteRepo extends PresetsRepoIndexed {
const urlRaw = correctUrl;
const urlViewOnline = correctUrl;
super(urlRaw, urlViewOnline);
super(urlRaw, urlViewOnline, official, name);
}
}

View file

@ -21,6 +21,7 @@
<div class="btn">
<div class="presets_source_panel_no_editing_selected"></div>
<a href="#" class="tool regular-button presets_source_panel_activate" i18n="presetsSourcesDialogMakeSourceActive"></a>
<a href="#" class="tool regular-button presets_source_panel_deactivate" i18n="presetsSourcesDialogMakeSourceDisable"></a>
<a href="#" class="tool regular-button presets_source_panel_save" i18n="presetsSourcesDialogSaveSource"></a>
<a href="#" class="tool regular-button presets_source_panel_reset" i18n="presetsSourcesDialogResetSource"></a>
<a href="#" class="tool regular-button presets_source_panel_delete" i18n="presetsSourcesDialogDeleteSource"></a>

View file

@ -47,6 +47,12 @@ export default class SourcePanel {
this._onActivateCallback = onActivateCallback;
}
setOnDeactivateCallback(onDeactivateCallback) {
// callback with this (SourcePanel) argument
// so that consumer knew which panel was clicked on
this._onDeactivateCallback = onDeactivateCallback;
}
setOnSaveCallback(onSaveCallback) {
// callback with this (SourcePanel) argument
// so that consumer knew which panel was clicked on
@ -65,6 +71,7 @@ export default class SourcePanel {
this._active = isActive;
this._domDivSelectedIndicator.toggle(this._active);
this._domButtonActivate.toggle(!isActive);
this._domButtonDeactivate.toggle(isActive);
}
_setUiOfficial() {
@ -120,6 +127,7 @@ export default class SourcePanel {
this._domButtonReset.on("click", () => this._onResetButtonClick());
this._domButtonDelete.on("click", () => this._onDeleteButtonClick());
this._domButtonActivate.on("click", () => this._onActivateButtonClick());
this._domButtonDeactivate.on("click", () => this._onDeactivateButtonClick());
this._domEditName.on("input", () => this._onInputChange());
this._domEditUrl.on("input", () => this._onInputChange());
@ -168,6 +176,12 @@ export default class SourcePanel {
this._onActivateCallback?.(this);
}
_onDeactivateButtonClick() {
this._onSaveButtonClick();
this.setActive(false);
this._onDeactivateCallback?.(this);
}
_setIsSaved(isSaved) {
if (isSaved) {
this._domButtonSave.addClass(GUI.buttonDisabledClass);
@ -190,6 +204,7 @@ export default class SourcePanel {
this._domButtonSave = this._domWrapperDiv.find(".presets_source_panel_save");
this._domButtonReset = this._domWrapperDiv.find(".presets_source_panel_reset");
this._domButtonActivate = this._domWrapperDiv.find(".presets_source_panel_activate");
this._domButtonDeactivate = this._domWrapperDiv.find(".presets_source_panel_deactivate");
this._domButtonDelete = this._domWrapperDiv.find(".presets_source_panel_delete");
this._domDivGithubBranch = this._domWrapperDiv.find(".presets_source_panel_editing_github_branch");
this._domDivNoEditingName = this._domWrapperDiv.find(".presets_source_panel_no_editing_name");

View file

@ -9,7 +9,7 @@ export default class PresetsSourcesDialog {
this._sourceSelectedPromiseResolve = null;
this._sourcesPanels = [];
this._sources = [];
this._activeSourceIndex = 0;
this._activeSourceIndexes = [0];
}
load() {
@ -28,20 +28,20 @@ export default class PresetsSourcesDialog {
return new Promise(resolve => this._sourceSelectedPromiseResolve = resolve);
}
getActivePresetSource() {
return this._sources[this._activeSourceIndex];
getActivePresetSources() {
return this._activeSourceIndexes.map(index => this._sources[index]);
}
get isOfficialActive() {
return this._activeSourceIndex === 0;
get isThirdPartyActive() {
return this.getActivePresetSources().filter(source => !source.official).length > 0;
}
_initializeSources() {
this._sources = this._readSourcesFromStorage();
this._activeSourceIndex = this._readActiveSourceIndexFromStorage(this._sources.length);
this._activeSourceIndexes = this._readActiveSourceIndexFromStorage(this._sources.length);
for (let i = 0; i < this._sources.length; i++) {
const isActive = this._activeSourceIndex === i;
const isActive = this._activeSourceIndexes.includes(i);
this._addNewSourcePanel(this._sources[i], isActive, false);
}
}
@ -67,15 +67,8 @@ export default class PresetsSourcesDialog {
}
_readActiveSourceIndexFromStorage(sourcesCount) {
const obj = getConfig('PresetSourcesActiveIndex');
const index = Number(obj.PresetSourcesActiveIndex);
let result = 0;
if (index && Number.isInteger(index) && index < sourcesCount) {
result = index;
}
return result;
const obj = getConfig('PresetSourcesActiveIndexes');
return obj.PresetSourcesActiveIndexes || [0];
}
_createOfficialSource() {
@ -117,6 +110,7 @@ export default class PresetsSourcesDialog {
sourcePanel.setOnSelectedCallback(selectedPanel => this._onSourcePanelSelected(selectedPanel));
sourcePanel.setOnDeleteCallback(selectedPanel => this._onSourcePanelDeleted(selectedPanel));
sourcePanel.setOnActivateCallback(selectedPanel => this._onSourcePanelActivated(selectedPanel));
sourcePanel.setOnDeactivateCallback(selectedPanel => this._onSourcePanelDeactivated(selectedPanel));
sourcePanel.setOnSaveCallback(() => this._onSourcePanelSaved());
sourcePanel.setActive(isActive);
if (isSelected) {
@ -140,18 +134,18 @@ export default class PresetsSourcesDialog {
_readPanels() {
this._sources = [];
this._activeSourceIndex = 0;
for(let i = 0; i < this._sourcesPanels.length; i++) {
this._activeSourceIndexes = [];
for (let i = 0; i < this._sourcesPanels.length; i++) {
this._sources.push(this._sourcesPanels[i].presetSource);
if (this._sourcesPanels[i].active) {
this._activeSourceIndex = i;
this._activeSourceIndexes.push(i);
}
}
}
_saveSources() {
setConfig({'PresetSources': this._sources});
setConfig({'PresetSourcesActiveIndex': this._activeSourceIndex});
setConfig({'PresetSourcesActiveIndexes': this._activeSourceIndexes});
}
_updateSourcesFromPanels() {
@ -183,15 +177,22 @@ export default class PresetsSourcesDialog {
_onSourcePanelActivated(selectedPanel) {
for (const panel of this._sourcesPanels) {
if (panel !== selectedPanel) {
panel.setActive(false);
} else {
if (panel === selectedPanel) {
panel.setActive(true);
}
}
this._updateSourcesFromPanels();
}
_onSourcePanelDeactivated(selectedPanel) {
for (const panel of this._sourcesPanels) {
if (panel === selectedPanel) {
panel.setActive(false);
}
}
this._updateSourcesFromPanels();
}
_readDom() {
this._domButtonAddNew = $("#presets_sources_dialog_add_new");
this._domButtonClose = $("#presets_sources_dialog_close");

View file

@ -20,7 +20,7 @@
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
width: calc(100% - 30px);
width: calc(100% - 60px);
}
.preset_title_panel_star {
@ -37,6 +37,20 @@
top: -5px;
}
.preset_title_panel_betaflight_official {
background-image: url(../../../images/icons/cf_icon_welcome_orange.svg);
width: 25px;
height: 25px;
background-size: cover;
border-radius: 5px;
padding: 5px;
background-origin: content-box;
background-repeat: no-repeat;
position: absolute;
right: 26px;
top: -5px;
}
.preset_title_panel_category {
color: var(--mutedText);
font-weight: bold;
@ -75,6 +89,12 @@
text-overflow: ellipsis;
}
.preset_title_panel_repository_text {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.presets_title_panel_table {
table-layout: fixed;
width: 100%;

View file

@ -2,13 +2,15 @@ import { i18n } from "../../../js/localization";
export default class PresetTitlePanel
{
constructor(parentDiv, preset, clickable, onLoadedCallback, favoritePresets)
constructor(parentDiv, preset, presetRepo, clickable, showPresetRepoName, onLoadedCallback, favoritePresets)
{
PresetTitlePanel.s_panelCounter ++;
this._parentDiv = parentDiv;
this._onLoadedCallback = onLoadedCallback;
this._domId = `preset_title_panel_${PresetTitlePanel.s_panelCounter}`;
this._preset = preset;
this._presetRepo = presetRepo;
this._showPresetRepoName = showPresetRepoName;
this._clickable = clickable;
this._favoritePresets = favoritePresets;
@ -68,7 +70,7 @@ export default class PresetTitlePanel
}
_showPresetsDetailedDialog(presetsDetailedDialog, presetsRepo) {
presetsDetailedDialog.open(this._preset, presetsRepo).then(isPresetPicked => {
presetsDetailedDialog.open(this._preset, presetsRepo, this._showPresetRepoName).then(isPresetPicked => {
if (isPresetPicked) {
const color = this._domWrapperDiv.css( "background-color" );
this._domWrapperDiv.css('background-color', 'green');
@ -103,11 +105,16 @@ export default class PresetTitlePanel
this._domTitle.prop("title", this._preset.title);
this._domAuthor.text(this._preset.author);
this._domVersions.text(this._preset.firmware_version?.join("; "));
this._domSourceRepository.text(this._presetRepo.name);
this._domSourceRepositoryRow.toggle(this._showPresetRepoName);
this._domKeywords.text(this._preset.keywords?.join("; "));
this._domKeywords.prop("title", this._preset.keywords?.join("; "));
this._domStatusOfficial.toggle(this._preset.status === "OFFICIAL");
this._domStatusCommunity.toggle(this._preset.status === "COMMUNITY");
this._domStatusExperimental.toggle(this._preset.status === "EXPERIMENTAL");
this._domOfficialSourceIcon.toggle(this._presetRepo.official);
this.setPicked(this._preset.isPicked);
this._setupStar();
@ -128,10 +135,13 @@ export default class PresetTitlePanel
this._domCategory = this._domWrapperDiv.find('.preset_title_panel_category');
this._domAuthor = this._domWrapperDiv.find('.preset_title_panel_author_text');
this._domKeywords = this._domWrapperDiv.find('.preset_title_panel_keywords_text');
this._domSourceRepository = this._domWrapperDiv.find('.preset_title_panel_repository_text');
this._domSourceRepositoryRow = this._domWrapperDiv.find('.preset_title_panel_repository_row');
this._domVersions = this._domWrapperDiv.find('.preset_title_panel_versions_text');
this._domStatusOfficial = this._domWrapperDiv.find('.preset_title_panel_status_official');
this._domStatusCommunity = this._domWrapperDiv.find('.preset_title_panel_status_community');
this._domStatusExperimental = this._domWrapperDiv.find('.preset_title_panel_status_experimental');
this._domOfficialSourceIcon = this._domWrapperDiv.find('.preset_title_panel_betaflight_official');
}
_setupStar() {
@ -145,9 +155,9 @@ export default class PresetTitlePanel
_processStarClick() {
if (this._preset.lastPickDate) {
this._favoritePresets.delete(this._preset);
this._favoritePresets.delete(this._preset, this._presetRepo);
} else {
this._favoritePresets.add(this._preset);
this._favoritePresets.add(this._preset, this._presetRepo);
}
this._favoritePresets.saveToStorage();

View file

@ -1,4 +1,5 @@
<div class="preset_title_panel">
<span class="preset_title_panel_betaflight_official hidden"></span>
<span class="preset_title_panel_star"></span>
<div>
<span class="preset_title_panel_title"></span>
@ -40,6 +41,14 @@
<span class="preset_title_panel_keywords_text"></span>
</td>
</tr>
<tr class="preset_title_panel_repository_row">
<td>
<span class="preset_title_panel_label preset_title_panel_repository_label" i18n="presetsSourceRepository"></span>
</td>
<td>
<span class="preset_title_panel_repository_text"></span>
</td>
</tr>
</tbody>
</table>
</div>

View file

@ -17,6 +17,7 @@
</div>
<div class="presets_warnings">
<div class="note presets_warning_not_official_source" i18n="presetsWarningNotOfficialSource"></div>
<div class="note presets_failed_to_load_repositories"></div>
<div class="note presets_warning_backup">
<div class="presets_warning_backup_text" i18n="presetsWarningBackup"></div>
<a href="#" id="" class="tool regular-button presets_warning_backup_button_hide" i18n="dontShowAgain">Don't show again</a>

View file

@ -17,7 +17,7 @@ import PresetsSourcesDialog from './SourcesDialog/SourcesDialog';
import PresetSource from './SourcesDialog/PresetSource';
const presets = {
presetsRepo: null,
presetsRepo: [],
cliEngine: null,
pickedPresetList: [],
majorVersion: 1,
@ -65,6 +65,7 @@ presets.readDom = function() {
this._domButtonPresetSources = $(".presets_sources_show");
this._domWarningNotOfficialSource = $(".presets_warning_not_official_source");
this._domWarningFailedToLoadRepositories = $(".presets_failed_to_load_repositories");
this._domWarningBackup = $(".presets_warning_backup");
this._domButtonHideBackupWarning = $(".presets_warning_backup_button_hide");
@ -116,8 +117,10 @@ presets.onSaveClick = function() {
};
presets.markPickedPresetsAsFavorites = function() {
for(const pickedPreset of this.pickedPresetList) {
favoritePresets.add(pickedPreset.preset);
for (const pickedPreset of this.pickedPresetList) {
if (pickedPreset.presetRepo !== undefined){
favoritePresets.add(pickedPreset.preset, pickedPreset.presetRepo);
}
}
favoritePresets.saveToStorage();
@ -134,7 +137,7 @@ presets.setupMenuButtons = function() {
this._domButtonCancel.on("click", () => {
for(const pickedPreset of this.pickedPresetList) {
for (const pickedPreset of this.pickedPresetList) {
pickedPreset.preset.isPicked = false;
}
@ -268,7 +271,7 @@ presets.onLoadConfigClick = function() {
.then(text => {
if (text) {
const cliStrings = text.split("\n");
const pickedPreset = new PickedPreset({title: "user configuration"}, cliStrings);
const pickedPreset = new PickedPreset({title: "user configuration"}, cliStrings, undefined);
this.pickedPresetList.push(pickedPreset);
this.onSaveClick();
}
@ -316,23 +319,32 @@ presets.reload = function() {
};
presets.tryLoadPresets = function() {
const presetSource = this.presetsSourcesDialog.getActivePresetSource();
const presetSources = this.presetsSourcesDialog.getActivePresetSources();
if (PresetSource.isUrlGithubRepo(presetSource.url)) {
this.presetsRepo = new PresetsGithubRepo(presetSource.url, presetSource.gitHubBranch);
} else {
this.presetsRepo = new PresetsWebsiteRepo(presetSource.url);
}
this.presetsRepo = presetSources.map(source => {
if (PresetSource.isUrlGithubRepo(source.url)) {
return new PresetsGithubRepo(source.url, source.gitHubBranch, source.official, source.name);
} else {
return new PresetsWebsiteRepo(source.url, source.official, source.name);
}
});
this._divMainContent.toggle(false);
this._divGlobalLoadingError.toggle(false);
this._divGlobalLoading.toggle(true);
this._domWarningNotOfficialSource.toggle(!this.presetsSourcesDialog.isOfficialActive);
this._domWarningNotOfficialSource.toggle(this.presetsSourcesDialog.isThirdPartyActive);
this.presetsRepo.loadIndex()
.then(() => this.checkPresetSourceVersion())
const failedToLoad = [];
Promise.all(this.presetsRepo.map(p => p.loadIndex().catch((reason => failedToLoad.push(p)))))
.then(() => {
favoritePresets.addLastPickDate(this.presetsRepo.index.presets);
this._domWarningFailedToLoadRepositories.toggle(failedToLoad.length > 0);
this._domWarningFailedToLoadRepositories.html(i18n.getMessage("presetsFailedToLoadRepositories", {"repos": failedToLoad.map(repo => repo.name).join("; ")}));
this.presetsRepo = this.presetsRepo.filter(repo => !failedToLoad.includes(repo));
return this.checkPresetSourceVersion();
})
.then(() => {
this.presetsRepo.forEach(p => favoritePresets.addLastPickDate(p.index.presets, p));
this.prepareFilterFields();
this._divGlobalLoading.toggle(false);
this._divMainContent.toggle(true);
@ -365,11 +377,12 @@ presets.checkPresetSourceVersion = function() {
const self = this;
return new Promise((resolve, reject) => {
if (self.majorVersion === self.presetsRepo.index.majorVersion) {
const differentMajorVersionsRepos = self.presetsRepo.filter(pr => self.majorVersion !== pr.index.majorVersion);
if (differentMajorVersionsRepos.length === 0) {
resolve();
} else {
const versionRequired = `${self.majorVersion}.X`;
const versionSource = `${self.presetsRepo.index.majorVersion}.${self.presetsRepo.index.minorVersion}`;
const versionSource = `${differentMajorVersionsRepos[0].index.majorVersion}.${differentMajorVersionsRepos[0].index.minorVersion}`;
const dialogSettings = {
title: i18n.getMessage("presetsWarningDialogTitle"),
@ -377,7 +390,7 @@ presets.checkPresetSourceVersion = function() {
buttonYesText: i18n.getMessage("yes"),
buttonNoText: i18n.getMessage("no"),
buttonYesCallback: () => resolve(),
buttonNoCallback: () => reject("Prset source version mismatch"),
buttonNoCallback: () => reject("Preset source version mismatch"),
};
GUI.showYesNoDialog(dialogSettings);
@ -385,13 +398,21 @@ presets.checkPresetSourceVersion = function() {
});
};
function getUniqueValues(objects, extractor) {
let values = objects.map(extractor);
let uniqueValues = [...values.reduce((a, b) => new Set([...a, ...b]), new Set())];
return uniqueValues.sort((a, b) => a.localeCompare(b, undefined, {sensitivity: 'base'}));
}
presets.prepareFilterFields = function() {
this._freezeSearch = true;
this.prepareFilterSelectField(this._selectCategory, this.presetsRepo.index.uniqueValues.category, 3);
this.prepareFilterSelectField(this._selectKeyword, this.presetsRepo.index.uniqueValues.keywords, 3);
this.prepareFilterSelectField(this._selectAuthor, this.presetsRepo.index.uniqueValues.author, 1);
this.prepareFilterSelectField(this._selectFirmwareVersion, this.presetsRepo.index.uniqueValues.firmware_version, 2);
this.prepareFilterSelectField(this._selectStatus, this.presetsRepo.index.settings.PresetStatusEnum, 2);
this.prepareFilterSelectField(this._selectCategory, getUniqueValues(this.presetsRepo, x => x.index.uniqueValues.category), 3);
this.prepareFilterSelectField(this._selectKeyword, getUniqueValues(this.presetsRepo, x => x.index.uniqueValues.keywords), 3);
this.prepareFilterSelectField(this._selectAuthor, getUniqueValues(this.presetsRepo, x => x.index.uniqueValues.author), 1);
this.prepareFilterSelectField(this._selectFirmwareVersion, getUniqueValues(this.presetsRepo, x => x.index.uniqueValues.firmware_version), 2);
this.prepareFilterSelectField(this._selectStatus, getUniqueValues(this.presetsRepo, x => x.index.settings.PresetStatusEnum), 2);
this.multipleSelectComponentScrollFix().then(() => {
this.preselectFilterFields();
this._inputTextFilter.on('input', () => this.updateSearchResults());
@ -404,9 +425,11 @@ presets.preselectFilterFields = function() {
const currentVersion = FC.CONFIG.flightControllerVersion;
const selectedVersions = [];
for(const bfVersion of this.presetsRepo.index.uniqueValues.firmware_version) {
if (currentVersion.startsWith(bfVersion)) {
selectedVersions.push(bfVersion);
for (const repo of this.presetsRepo) {
for (const bfVersion of repo.index.uniqueValues.firmware_version) {
if (currentVersion.startsWith(bfVersion)) {
selectedVersions.push(bfVersion);
}
}
}
@ -474,25 +497,29 @@ presets.displayPresets = function(fitPresets) {
this._domListNoFound.toggle(fitPresets.length === 0);
fitPresets.forEach(preset => {
const presetPanel = new PresetTitlePanel(this._divPresetList, preset, true, undefined, favoritePresets);
const presetPanel = new PresetTitlePanel(this._divPresetList, preset[0], preset[1], true, this.presetsSourcesDialog.isThirdPartyActive, favoritePresets);
presetPanel.load();
this._presetPanels.push(presetPanel);
presetPanel.subscribeClick(this.presetsDetailedDialog, this.presetsRepo);
presetPanel.subscribeClick(this.presetsDetailedDialog, preset[1]);
});
this._domListTooManyFound.appendTo(this._divPresetList);
};
presets.getFitPresets = function(searchParams) {
const result = [];
for(const preset of this.presetsRepo.index.presets) {
if(this.isPresetFitSearch(preset, searchParams)) {
result.push(preset);
const seenHashes = new Set();
for (const repo of this.presetsRepo){
for (const preset of repo.index.presets) {
if (this.isPresetFitSearch(preset, searchParams) && !seenHashes.has(preset.hash)) {
result.push([preset, repo]);
seenHashes.add(preset.hash);
}
}
}
result.sort((a, b) => this.presetSearchPriorityComparer(a,b));
result.sort((a, b) => this.presetSearchPriorityComparer(a[0], b[0]));
return result;
};
@ -653,7 +680,7 @@ presets.cleanup = function(callback) {
presets.resetInitialValues = function() {
CONFIGURATOR.cliEngineActive = false;
CONFIGURATOR.cliEngineValid = false;
TABS.presets.presetsRepo = null;
TABS.presets.presetsRepo = [];
TABS.presets.pickedPresetList.length = 0;
this._domProgressDialog.close();
};