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:
parent
b328324b61
commit
ad9b29e6b6
15 changed files with 186 additions and 78 deletions
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
export default class PickedPreset
|
||||
{
|
||||
constructor(preset, presetCli)
|
||||
constructor(preset, presetCli, presetRepo)
|
||||
{
|
||||
this.preset = preset;
|
||||
this.presetCli = presetCli;
|
||||
this.presetRepo = presetRepo;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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%;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue