Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/betaflight/betaflight-configurator.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml2
-rw-r--r--src/images/icons/star_orange.svg6
-rw-r--r--src/images/icons/star_orange_stroke.svg6
-rw-r--r--src/images/icons/star_transparent.svg6
-rw-r--r--src/js/port_handler.js20
-rw-r--r--src/js/tabs/options.js11
-rw-r--r--src/js/tabs/setup.js4
-rw-r--r--src/tabs/presets/DetailedDialog/PresetsDetailedDialog.js6
-rw-r--r--src/tabs/presets/FavoritePresets.js15
-rw-r--r--src/tabs/presets/TitlePanel/PresetTitlePanel.css18
-rw-r--r--src/tabs/presets/TitlePanel/PresetTitlePanel.js88
-rw-r--r--src/tabs/presets/TitlePanel/PresetTitlePanelBody.html1
-rw-r--r--src/tabs/presets/presets.js4
13 files changed, 155 insertions, 32 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b479041a..55b4de27 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -81,7 +81,7 @@ jobs:
cache: yarn
- name: Install Java JDK 8
- uses: actions/setup-java@v2
+ uses: actions/setup-java@v3
if: ${{ matrix.name == 'Android' }}
with:
distribution: temurin
diff --git a/src/images/icons/star_orange.svg b/src/images/icons/star_orange.svg
new file mode 100644
index 00000000..7be1447a
--- /dev/null
+++ b/src/images/icons/star_orange.svg
@@ -0,0 +1,6 @@
+<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
+ <g id="Layer_1">
+ <title>Layer 1</title>
+ <path stroke="#ffbb00" stroke-width="2" id="svg_1" d="m3.08281,39.47823l35.8418,0l11.07539,-34.04956l11.0754,34.04956l35.84179,0l-28.99657,21.04355l11.07596,34.04956l-28.99658,-21.04412l-28.99658,21.04412l11.07597,-34.04956l-28.99658,-21.04355z" fill="#ffbb00"/>
+ </g>
+</svg> \ No newline at end of file
diff --git a/src/images/icons/star_orange_stroke.svg b/src/images/icons/star_orange_stroke.svg
new file mode 100644
index 00000000..71fe5fe7
--- /dev/null
+++ b/src/images/icons/star_orange_stroke.svg
@@ -0,0 +1,6 @@
+<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
+ <g id="Layer_1">
+ <title>Layer 1</title>
+ <path stroke="#ffbb00" stroke-width="2" id="svg_1" d="m3.08281,39.47823l35.8418,0l11.07539,-34.04956l11.0754,34.04956l35.84179,0l-28.99657,21.04355l11.07596,34.04956l-28.99658,-21.04412l-28.99658,21.04412l11.07597,-34.04956l-28.99658,-21.04355z" fill="none"/>
+ </g>
+</svg> \ No newline at end of file
diff --git a/src/images/icons/star_transparent.svg b/src/images/icons/star_transparent.svg
new file mode 100644
index 00000000..a1b233d5
--- /dev/null
+++ b/src/images/icons/star_transparent.svg
@@ -0,0 +1,6 @@
+<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
+ <g id="Layer_1">
+ <title>Layer 1</title>
+ <path stroke="#9c9c9c" stroke-width="2" id="svg_1" d="m3.08281,39.47823l35.8418,0l11.07539,-34.04956l11.0754,34.04956l35.84179,0l-28.99657,21.04355l11.07596,34.04956l-28.99658,-21.04412l-28.99658,21.04412l11.07597,-34.04956l-28.99658,-21.04355z" fill="none"/>
+ </g>
+</svg> \ No newline at end of file
diff --git a/src/js/port_handler.js b/src/js/port_handler.js
index aed0da48..8d10afe6 100644
--- a/src/js/port_handler.js
+++ b/src/js/port_handler.js
@@ -26,9 +26,6 @@ PortHandler.initialize = function () {
this.selectList = document.querySelector(portPickerElementSelector);
this.initialWidth = this.selectList.offsetWidth + 12;
- this.showVirtualMode = ConfigStorage.get('showVirtualMode').showVirtualMode;
- this.showAllSerialDevices = ConfigStorage.get('showAllSerialDevices').showAllSerialDevices;
-
// fill dropdown with version numbers
generateVirtualApiVersions();
@@ -120,8 +117,17 @@ PortHandler.initialize = function () {
}
}, MDNS_INTERVAL);
- // start listening, check after TIMEOUT_CHECK ms
- this.check();
+ this.reinitialize(); // just to prevent code redundancy
+};
+
+PortHandler.reinitialize = function () {
+ this.initialPorts = false;
+ if (this.usbCheckLoop) {
+ clearTimeout(this.usbCheckLoop);
+ }
+ this.showVirtualMode = ConfigStorage.get('showVirtualMode').showVirtualMode;
+ this.showAllSerialDevices = ConfigStorage.get('showAllSerialDevices').showAllSerialDevices;
+ this.check(); // start listening, check after TIMEOUT_CHECK ms
};
PortHandler.check = function () {
@@ -135,7 +141,7 @@ PortHandler.check = function () {
self.check_serial_devices();
}
- setTimeout(function () {
+ self.usbCheckLoop = setTimeout(function () {
self.check();
}, TIMEOUT_CHECK);
};
@@ -197,7 +203,7 @@ PortHandler.check_usb_devices = function (callback) {
data: {isManual: true},
}));
- self.portPickerElement.val('DFU').change();
+ self.portPickerElement.val('DFU').trigger('change');
self.setPortsInputWidth();
}
self.dfu_available = true;
diff --git a/src/js/tabs/options.js b/src/js/tabs/options.js
index 5f6b7535..b75d4c38 100644
--- a/src/js/tabs/options.js
+++ b/src/js/tabs/options.js
@@ -133,8 +133,10 @@ options.initShowAllSerialDevices = function() {
const result = ConfigStorage.get('showAllSerialDevices');
showAllSerialDevicesElement
.prop('checked', !!result.showAllSerialDevices)
- .on('change', () => ConfigStorage.set({ showAllSerialDevices: showAllSerialDevicesElement.is(':checked') }))
- .trigger('change');
+ .on('change', () => {
+ ConfigStorage.set({ showAllSerialDevices: showAllSerialDevicesElement.is(':checked') });
+ PortHandler.reinitialize();
+ });
};
options.initShowVirtualMode = function() {
@@ -144,9 +146,8 @@ options.initShowVirtualMode = function() {
.prop('checked', !!result.showVirtualMode)
.on('change', () => {
ConfigStorage.set({ showVirtualMode: showVirtualModeElement.is(':checked') });
- PortHandler.initialPorts = false;
- })
- .trigger('change');
+ PortHandler.reinitialize();
+ });
};
options.initCordovaForceComputerUI = function () {
diff --git a/src/js/tabs/setup.js b/src/js/tabs/setup.js
index 7bdd6421..7a119b86 100644
--- a/src/js/tabs/setup.js
+++ b/src/js/tabs/setup.js
@@ -54,9 +54,7 @@ setup.initialize = function (callback) {
} else if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_41)) {
restoreButton.addClass('disabled');
- if (!PortHandler.showVirtualMode) {
- $('.backupRestore').hide();
- }
+ $('.backupRestore').hide();
}
// initialize 3D Model
diff --git a/src/tabs/presets/DetailedDialog/PresetsDetailedDialog.js b/src/tabs/presets/DetailedDialog/PresetsDetailedDialog.js
index 9f110bf1..cbf4e075 100644
--- a/src/tabs/presets/DetailedDialog/PresetsDetailedDialog.js
+++ b/src/tabs/presets/DetailedDialog/PresetsDetailedDialog.js
@@ -1,13 +1,14 @@
'use strict';
class PresetsDetailedDialog {
- constructor(domDialog, pickedPresetList, onPresetPickedCallback) {
+ constructor(domDialog, pickedPresetList, onPresetPickedCallback, favoritePresets) {
this._domDialog = domDialog;
this._pickedPresetList = pickedPresetList;
this._finalDialogYesNoSettings = {};
this._onPresetPickedCallback = onPresetPickedCallback;
this._openPromiseResolve = undefined;
this._isDescriptionHtml = false;
+ this._favoritePresets = favoritePresets;
}
load() {
@@ -71,7 +72,8 @@ class PresetsDetailedDialog {
}
this._titlePanel.empty();
- const titlePanel = new PresetTitlePanel(this._titlePanel, this._preset, false, () => this._setLoadingState(false));
+ const titlePanel = new PresetTitlePanel(this._titlePanel, this._preset, false,
+ () => this._setLoadingState(false), this._favoritePresets);
titlePanel.load();
this._loadOptionsSelect();
this._updateFinalCliText();
diff --git a/src/tabs/presets/FavoritePresets.js b/src/tabs/presets/FavoritePresets.js
index f5799ba5..9693d7d5 100644
--- a/src/tabs/presets/FavoritePresets.js
+++ b/src/tabs/presets/FavoritePresets.js
@@ -53,6 +53,16 @@ class FavoritePresetsData {
return preset;
}
+ delete(presetPath) {
+ const index = this._favoritePresetsList.findIndex((preset) => preset.presetPath === presetPath);
+
+ if (index >= 0) {
+ this._favoritePresetsList.splice(index, 1);
+ this._sort();
+ this._purgeOldPresets();
+ }
+ }
+
findPreset(presetPath) {
return this._favoritePresetsList.find((preset) => preset.presetPath === presetPath);
}
@@ -69,6 +79,11 @@ class FavoritePresetsClass {
preset.lastPickDate = favoritePreset.lastPickDate;
}
+ delete(preset) {
+ this._favoritePresetsData.delete(preset.fullPath);
+ preset.lastPickDate = undefined;
+ }
+
addLastPickDate(presets) {
for (let preset of presets) {
let favoritePreset = this._favoritePresetsData.findPreset(preset.fullPath);
diff --git a/src/tabs/presets/TitlePanel/PresetTitlePanel.css b/src/tabs/presets/TitlePanel/PresetTitlePanel.css
index bdd086d6..e9481d12 100644
--- a/src/tabs/presets/TitlePanel/PresetTitlePanel.css
+++ b/src/tabs/presets/TitlePanel/PresetTitlePanel.css
@@ -1,5 +1,6 @@
.preset_title_panel {
color: var(--defaultText);
+ position: relative;
}
.preset_title_panel_border {
@@ -14,11 +15,26 @@
.preset_title_panel_title {
font-size: 1.5em;
font-weight: bold;
- display: block;
+ display: inline-block;
margin-bottom: 1ex;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
+ width: calc(100% - 30px);
+}
+
+.preset_title_panel_star {
+ background-image: url(../../../images/icons/star_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: -6px;
+ top: -5px;
}
.preset_title_panel_category {
diff --git a/src/tabs/presets/TitlePanel/PresetTitlePanel.js b/src/tabs/presets/TitlePanel/PresetTitlePanel.js
index ec2b66f5..8c49760d 100644
--- a/src/tabs/presets/TitlePanel/PresetTitlePanel.js
+++ b/src/tabs/presets/TitlePanel/PresetTitlePanel.js
@@ -2,7 +2,7 @@
class PresetTitlePanel
{
- constructor(parentDiv, preset, clickable, onLoadedCallback)
+ constructor(parentDiv, preset, clickable, onLoadedCallback, favoritePresets)
{
PresetTitlePanel.s_panelCounter ++;
this._parentDiv = parentDiv;
@@ -10,16 +10,45 @@ class PresetTitlePanel
this._domId = `preset_title_panel_${PresetTitlePanel.s_panelCounter}`;
this._preset = preset;
this._clickable = clickable;
+ this._favoritePresets = favoritePresets;
this._parentDiv.append(`<div class="${this._domId}"></div>`);
this._domWrapperDiv = $(`.${this._domId}`);
this._domWrapperDiv.toggle(false);
+ this._starJustClicked = false;
+ this._mouseOnStar = false;
+ this._mouseOnPanel = false;
+ this._clickable = clickable;
if (clickable) {
this._domWrapperDiv.addClass("preset_title_panel_border");
// setting up hover effect here, because if setup in SCC it stops working after background animation like - this._domWrapperDiv.animate({ backgroundColor....
- this._domWrapperDiv.on("mouseenter", () => this._domWrapperDiv.css({"background-color": "var(--subtleAccent)"}));
- this._domWrapperDiv.on("mouseleave", () => this._domWrapperDiv.css({"background-color": "var(--boxBackground)"}));
+ }
+ }
+
+ _updateHoverEffects() {
+ let starMouseHover = false;
+
+ if (this._clickable && this._mouseOnPanel && !this._mouseOnStar) {
+ this._domWrapperDiv.css({"background-color": "var(--subtleAccent)"});
+ } else {
+ this._domWrapperDiv.css({"background-color": "var(--boxBackground)"});
+ }
+
+ if (this._mouseOnStar || (this._mouseOnPanel && this._clickable)) {
+ this._domStar.css({"background-color": "var(--subtleAccent)"});
+ starMouseHover = true;
+ } else {
+ this._domWrapperDiv.css({"background-color": "var(--boxBackground)"});
+ this._domStar.css({"background-color": "var(--boxBackground)"});
+ }
+
+ if (this._preset.lastPickDate) {
+ this._domStar.css("background-image", "url('../../../images/icons/star_orange.svg')");
+ } else if (starMouseHover) {
+ this._domStar.css("background-image", "url('../../../images/icons/star_orange_stroke.svg')");
+ } else {
+ this._domStar.css("background-image", "url('../../../images/icons/star_transparent.svg')");
}
}
@@ -30,14 +59,24 @@ class PresetTitlePanel
subscribeClick(presetsDetailedDialog, presetsRepo)
{
this._domWrapperDiv.on("click", () => {
- presetsDetailedDialog.open(this._preset, presetsRepo).then(isPresetPicked => {
- if (isPresetPicked) {
- const color = this._domWrapperDiv.css( "background-color" );
- this._domWrapperDiv.css('background-color', 'green');
- this._domWrapperDiv.animate({ backgroundColor: color }, 2000);
- this.setPicked(true);
- }
- });
+ if (!this._starJustClicked) {
+ this._showPresetsDetailedDialog(presetsDetailedDialog, presetsRepo);
+ }
+
+ this._starJustClicked = false;
+ });
+ }
+
+ _showPresetsDetailedDialog(presetsDetailedDialog, presetsRepo) {
+ presetsDetailedDialog.open(this._preset, presetsRepo).then(isPresetPicked => {
+ if (isPresetPicked) {
+ const color = this._domWrapperDiv.css( "background-color" );
+ this._domWrapperDiv.css('background-color', 'green');
+ this._domWrapperDiv.animate({ backgroundColor: color }, 2000);
+ this.setPicked(true);
+ }
+
+ this._updateHoverEffects();
});
}
@@ -70,6 +109,12 @@ class PresetTitlePanel
this._domStatusCommunity.toggle(this._preset.status === "COMMUNITY");
this._domStatusExperimental.toggle(this._preset.status === "EXPERIMENTAL");
this.setPicked(this._preset.isPicked);
+ this._setupStar();
+
+ this._domWrapperDiv.on("mouseenter", () => { this._mouseOnPanel = true; this._updateHoverEffects(); });
+ this._domWrapperDiv.on("mouseleave", () => { this._mouseOnPanel = false; this._updateHoverEffects(); } );
+ this._domStar.on("mouseenter", () => { this._mouseOnStar = true; this._updateHoverEffects(); });
+ this._domStar.on("mouseleave", () => { this._mouseOnStar = false; this._updateHoverEffects(); });
i18n.localizePage();
this._domWrapperDiv.toggle(true);
@@ -79,6 +124,7 @@ class PresetTitlePanel
_readDom()
{
this._domTitle = this._domWrapperDiv.find('.preset_title_panel_title');
+ this._domStar = this._domWrapperDiv.find('.preset_title_panel_star');
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');
@@ -88,6 +134,26 @@ class PresetTitlePanel
this._domStatusExperimental = this._domWrapperDiv.find('.preset_title_panel_status_experimental');
}
+ _setupStar() {
+ this._updateHoverEffects();
+
+ this._domStar.on("click", () => {
+ this._starJustClicked = true;
+ this._processStarClick();
+ });
+ }
+
+ _processStarClick() {
+ if (this._preset.lastPickDate) {
+ this._favoritePresets.delete(this._preset);
+ } else {
+ this._favoritePresets.add(this._preset);
+ }
+
+ this._favoritePresets.saveToStorage();
+ this._updateHoverEffects();
+ }
+
remove()
{
this._domWrapperDiv.remove();
diff --git a/src/tabs/presets/TitlePanel/PresetTitlePanelBody.html b/src/tabs/presets/TitlePanel/PresetTitlePanelBody.html
index 081c53eb..7dd031ba 100644
--- a/src/tabs/presets/TitlePanel/PresetTitlePanelBody.html
+++ b/src/tabs/presets/TitlePanel/PresetTitlePanelBody.html
@@ -1,4 +1,5 @@
<div class="preset_title_panel">
+ <span class="preset_title_panel_star"></span>
<div>
<span class="preset_title_panel_title"></span>
</div>
diff --git a/src/tabs/presets/presets.js b/src/tabs/presets/presets.js
index f5e89656..fd7936e7 100644
--- a/src/tabs/presets/presets.js
+++ b/src/tabs/presets/presets.js
@@ -269,7 +269,7 @@ presets.onHtmlLoad = function(callback) {
this.setupBackupWarning();
this._inputTextFilter.attr("placeholder", "example: \"karate race\", or \"5'' freestyle\"");
- this.presetsDetailedDialog = new PresetsDetailedDialog($("#presets_detailed_dialog"), this.pickedPresetList, () => this.onPresetPickedCallback());
+ this.presetsDetailedDialog = new PresetsDetailedDialog($("#presets_detailed_dialog"), this.pickedPresetList, () => this.onPresetPickedCallback(), favoritePresets);
this.presetsSourcesDialog = new PresetsSourcesDialog($("#presets_sources_dialog"));
this.presetsDetailedDialog.load()
@@ -460,7 +460,7 @@ presets.displayPresets = function(fitPresets) {
this._domListNoFound.toggle(fitPresets.length === 0);
fitPresets.forEach(preset => {
- const presetPanel = new PresetTitlePanel(this._divPresetList, preset, true);
+ const presetPanel = new PresetTitlePanel(this._divPresetList, preset, true, undefined, favoritePresets);
presetPanel.load();
this._presetPanels.push(presetPanel);
presetPanel.subscribeClick(this.presetsDetailedDialog, this.presetsRepo);