Skip to content

Commit e0209c6

Browse files
authored
Convert battery icon to vue component (#2726)
* feat: use vue battery icon * Add battery icon stories * feat: use battery state if available
1 parent 1301f97 commit e0209c6

File tree

9 files changed

+213
-87
lines changed

9 files changed

+213
-87
lines changed

.storybook/preview.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ export const decorators = [
5050
template: `
5151
<div style="margin: 1rem;">
5252
<link rel="stylesheet" href="/css/opensans_webfontkit/fonts.css" />
53-
<link rel="stylesheet" href="/css/main.css" />
53+
<link rel="stylesheet" href="/css/theme.css" />
5454
<story />
5555
</div>
5656
`,

src/components/init.js

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import vueI18n from "./vueI18n.js";
1010
import BatteryLegend from "./quad-status/BatteryLegend.vue";
1111
import BetaflightLogo from "./betaflight-logo/BetaflightLogo.vue";
1212
import StatusBar from "./status-bar/StatusBar.vue";
13+
import BatteryIcon from "./quad-status/BatteryIcon.vue";
1314

1415
// Most of the global objects can go here at first.
1516
// It's a bit of overkill for simple components,
@@ -38,6 +39,7 @@ i18next.on('initialized', function() {
3839
BatteryLegend,
3940
BetaflightLogo,
4041
StatusBar,
42+
BatteryIcon,
4143
},
4244
data: betaflightModel,
4345
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import BatteryIcon from "./BatteryIcon.vue";
2+
3+
// More on default export: https://storybook.js.org/docs/vue/writing-stories/introduction#default-export
4+
export default {
5+
title: "Battery Icon",
6+
component: BatteryIcon,
7+
};
8+
9+
// More on component templates: https://storybook.js.org/docs/vue/writing-stories/introduction#using-args
10+
const Template = (_args, { argTypes }) => ({
11+
props: Object.keys(argTypes),
12+
components: { BatteryIcon },
13+
template: '<battery-icon v-bind="$props" />',
14+
});
15+
16+
export const OK = Template.bind({});
17+
OK.args = {
18+
voltage: 16,
19+
vbatmincellvoltage: 3.7,
20+
vbatmaxcellvoltage: 4.2,
21+
vbatwarningcellvoltage: 3.8,
22+
};
23+
export const Warning = Template.bind({});
24+
Warning.args = {
25+
...OK.args,
26+
voltage: 15.1,
27+
};
28+
export const Empty = Template.bind({});
29+
Empty.args = {
30+
...OK.args,
31+
voltage: 14,
32+
};
+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
<template>
2+
<div class="battery-icon">
3+
<div class="quad-status-contents">
4+
<div
5+
class="battery-status"
6+
:class="classes"
7+
:style="{ width: batteryWidth + '%' }"
8+
/>
9+
</div>
10+
</div>
11+
</template>
12+
<script>
13+
const NO_BATTERY_VOLTAGE_MAXIMUM = 1.8; // Maybe is better to add a call to MSP_BATTERY_STATE but is not available for all versions
14+
15+
export default {
16+
props: {
17+
voltage: {
18+
type: Number,
19+
default: 0,
20+
},
21+
vbatmincellvoltage: {
22+
type: Number,
23+
default: 1,
24+
},
25+
vbatmaxcellvoltage: {
26+
type: Number,
27+
default: 1,
28+
},
29+
vbatwarningcellvoltage: {
30+
type: Number,
31+
default: 1,
32+
},
33+
},
34+
computed: {
35+
nbCells() {
36+
let nbCells = Math.floor(this.voltage / this.vbatmaxcellvoltage) + 1;
37+
if (this.voltage === 0) {
38+
nbCells = 1;
39+
}
40+
return nbCells;
41+
},
42+
min() {
43+
return this.vbatmincellvoltage * this.nbCells;
44+
},
45+
max() {
46+
return this.vbatmaxcellvoltage * this.nbCells;
47+
},
48+
warn() {
49+
return this.vbatwarningcellvoltage * this.nbCells;
50+
},
51+
isEmpty() {
52+
return (
53+
this.voltage < this.min && this.voltage > NO_BATTERY_VOLTAGE_MAXIMUM
54+
);
55+
},
56+
classes() {
57+
if (this.batteryState) {
58+
return {
59+
"state-ok": this.batteryState === 0,
60+
"state-warning": this.batteryState === 1,
61+
"state-empty": this.batteryState === 2,
62+
// TODO: BATTERY_NOT_PRESENT
63+
// TODO: BATTERY_INIT
64+
};
65+
}
66+
const isWarning = this.voltage < this.warn;
67+
return {
68+
"state-empty": this.isEmpty,
69+
"state-warning": isWarning,
70+
"state-ok": !this.isEmpty && !isWarning,
71+
};
72+
},
73+
batteryWidth() {
74+
return this.isEmpty
75+
? 100
76+
: ((this.voltage - this.min) / (this.max - this.min)) * 100;
77+
},
78+
},
79+
};
80+
</script>
81+
82+
<style>
83+
.quad-status-contents {
84+
display: inline-block;
85+
margin-top: 10px;
86+
margin-left: 14px;
87+
height: 10px;
88+
width: 31px;
89+
}
90+
91+
.quad-status-contents progress::-webkit-progress-bar {
92+
height: 12px;
93+
background-color: #eee;
94+
}
95+
96+
.quad-status-contents progress::-webkit-progress-value {
97+
background-color: #bcf;
98+
}
99+
100+
.battery-icon {
101+
background-image: url(../../images/icons/cf_icon_bat_grey.svg);
102+
background-size: contain;
103+
background-position: center;
104+
display: inline-block;
105+
height: 30px;
106+
width: 60px;
107+
transition: none;
108+
margin-top: 4px;
109+
margin-left: -4px;
110+
background-repeat: no-repeat;
111+
}
112+
113+
.battery-status {
114+
height: 11px;
115+
}
116+
117+
@keyframes error-blinker {
118+
0% {
119+
background-color: transparent;
120+
}
121+
50% {
122+
background-color: var(--error);
123+
}
124+
}
125+
126+
.battery-status.state-ok {
127+
background-color: #59aa29;
128+
}
129+
.battery-status.state-warning {
130+
background-color: var(--error);
131+
}
132+
133+
.battery-status.state-empty {
134+
animation: error-blinker 1s linear infinite;
135+
}
136+
</style>

src/components/quad-status/BatteryLegend.stories.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import BatteryLegend from './BatteryLegend.vue';
1+
import BatteryLegend from "./BatteryLegend.vue";
22

33
// More on default export: https://storybook.js.org/docs/vue/writing-stories/introduction#default-export
44
export default {
5-
title: 'Battery Legend',
5+
title: "Battery Legend",
66
component: BatteryLegend,
77
};
88

src/css/main.less

+1-74
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,3 @@
1-
2-
@keyframes error-blinker {
3-
0% {
4-
background-color: transparent;
5-
}
6-
50% {
7-
background-color: var(--error);
8-
}
9-
}
10-
11-
&:root {
12-
--accent: #ffbb00;
13-
--error: red;
14-
--subtleAccent: silver;
15-
--quietText: #ffffff;
16-
--quietHeader: #828885;
17-
--defaultText: #000000;
18-
--subtleText: #c0c0c0;
19-
--mutedText: #616161;
20-
--linkText: #2e2ebb;
21-
--boxBackground: #ffffff;
22-
--alternativeBackground: #f9f9f9;
23-
--sideBackground: #ffffff;
24-
--ledAccent: #adadad;
25-
--ledBackground: #e9e9e9;
26-
--gimbalBackground: #eee;
27-
--gimbalCrosshair: var(--subtleAccent);
28-
--switcherysecond: #c4c4c4;
29-
--pushedButton-background: #c4c4c4;
30-
--pushedButton-fontColor: #000000;
31-
--hoverButton-background: #ffcc3e;
32-
--superSubtleAccent: #CCCCCC;
33-
--accentBorder: #ffbb00;
34-
}
351
* {
362
margin: 0;
373
padding: 0;
@@ -621,46 +587,7 @@ input[type="number"] {
621587
text-shadow: 0 1px rgba(0, 0, 0, 1.0);
622588
white-space: nowrap;
623589
}
624-
.quad-status-contents {
625-
display: none;
626-
margin-top: 10px;
627-
margin-left: 14px;
628-
height: 10px;
629-
width: 31px;
630-
progress {
631-
&::-webkit-progress-bar {
632-
height: 12px;
633-
background-color: #eee;
634-
}
635-
&::-webkit-progress-value {
636-
background-color: #bcf;
637-
}
638-
}
639-
}
640-
.battery-status {
641-
height: 11px;
642-
}
643-
.battery-status.state-ok {
644-
background-color: #59AA29;
645-
}
646-
.battery-status.state-warning {
647-
background-color: var(--error);
648-
}
649-
.battery-status.state-empty {
650-
animation: error-blinker 1s linear infinite;
651-
}
652-
.battery-icon {
653-
background-image: url(../images/icons/cf_icon_bat_grey.svg);
654-
background-size: contain;
655-
background-position: center;
656-
display: inline-block;
657-
height: 30px;
658-
width: 60px;
659-
transition: none;
660-
margin-top: 4px;
661-
margin-left: -4px;
662-
background-repeat: no-repeat;
663-
}
590+
664591
.armedicon {
665592
margin-left: 8px;
666593
margin-right: 8px;

src/css/theme.css

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Main theme colors
3+
* This file is left as css on purpose to make it easier to work without
4+
* the need to compile the less files and still can be use in storybook
5+
*/
6+
:root {
7+
--accent: #ffbb00;
8+
--error: red;
9+
--subtleAccent: silver;
10+
--quietText: #ffffff;
11+
--quietHeader: #828885;
12+
--defaultText: #000000;
13+
--subtleText: #c0c0c0;
14+
--mutedText: #616161;
15+
--linkText: #2e2ebb;
16+
--boxBackground: #ffffff;
17+
--alternativeBackground: #f9f9f9;
18+
--sideBackground: #ffffff;
19+
--ledAccent: #adadad;
20+
--ledBackground: #e9e9e9;
21+
--gimbalBackground: #eee;
22+
--gimbalCrosshair: var(--subtleAccent);
23+
--switcherysecond: #c4c4c4;
24+
--pushedButton-background: #c4c4c4;
25+
--pushedButton-fontColor: #000000;
26+
--hoverButton-background: #ffcc3e;
27+
--superSubtleAccent: #cccccc;
28+
--accentBorder: #ffbb00;
29+
}

src/js/serial_backend.js

-4
Original file line numberDiff line numberDiff line change
@@ -659,10 +659,6 @@ async function getStatus() {
659659
async function update_live_status() {
660660
const statuswrapper = $('#quad-status_wrapper');
661661

662-
$(".quad-status-contents").css({
663-
display: 'inline-block',
664-
});
665-
666662
if (GUI.active_tab !== 'cli' && GUI.active_tab !== 'presets') {
667663
await MSP.promise(MSPCodes.MSP_BOXNAMES);
668664
await getStatus();

src/main.html

+10-6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<link type="text/css" rel="stylesheet" href="./js/libraries/jquery.nouislider.min.css"/>
88
<link type="text/css" rel="stylesheet" href="./js/libraries/jquery.nouislider.pips.min.css"/>
99
<link type="text/css" rel="stylesheet" href="./js/libraries/flightindicators.css"/>
10+
<link type="text/css" rel="stylesheet" href="./css/theme.css" media="all"/>
1011
<link type="text/css" rel="stylesheet" href="./css/main.css" media="all"/>
1112
<link type="text/css" rel="stylesheet" href="./css/tabs/static_tab.css" media="all"/>
1213
<link type="text/css" rel="stylesheet" href="./css/tabs/landing.css" media="all"/>
@@ -184,12 +185,15 @@
184185
</div>
185186
<div class="header-wrapper">
186187
<div id="quad-status_wrapper">
187-
<div class="battery-icon">
188-
<div class="quad-status-contents">
189-
<div class="battery-status"></div>
190-
</div>
191-
</div>
192-
<battery-legend
188+
<battery-icon
189+
:voltage="FC.ANALOG.voltage"
190+
:vbatmincellvoltage="FC.BATTERY_CONFIG.vbatmincellvoltage"
191+
:vbatmaxcellvoltage="FC.BATTERY_CONFIG.vbatmaxcellvoltage"
192+
:vbatwarningcellvoltage="FC.BATTERY_CONFIG.vbatwarningcellvoltage"
193+
:batteryState="FC.BATTERY_STATE?.batteryState"
194+
>
195+
</battery-icon>
196+
<battery-legend
193197
:voltage="FC.ANALOG.voltage"
194198
:vbatmaxcellvoltage="FC.BATTERY_CONFIG.vbatmaxcellvoltage"
195199
></battery-legend>

0 commit comments

Comments
 (0)