Skip to content

Commit

Permalink
Fix as many Vue3 issues as possible
Browse files Browse the repository at this point in the history
The biggest problem is with arrays. Vue3 is not detecting well
reactivity in some arrays because we have the view and the logic in
different files, so we can't access the reactivity proxy in a clean way.

I've added reactivity in the definition of the modules affected as a
workaround, but I'm sure there must be a better way.
  • Loading branch information
McGiverGim authored and haslinghuis committed Feb 20, 2025
1 parent 4c110b1 commit 1d59a55
Show file tree
Hide file tree
Showing 13 changed files with 284 additions and 344 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
"three": "~0.97.0",
"tiny-emitter": "^2.1.0",
"vite-plugin-pwa": "^0.17.5",
"vue": "^3.5.12"
"vue": "^3.5.13"
},
"devDependencies": {
"@babel/core": "^7.24.4",
Expand Down
49 changes: 28 additions & 21 deletions src/components/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
// `i18n` helper to window and setting up `i18next`
// in the future it should be pure. This means it should
// explicitly export things used by other parts of the app.
import '../js/localization.js';
import '../js/injected_methods';
import i18next from 'i18next';
import { createApp } from "vue";
import "../js/localization.js";
import "../js/injected_methods";
import i18next from "i18next";
import { createApp, reactive } from "vue";
import I18NextVue from "i18next-vue";
import BatteryLegend from "./quad-status/BatteryLegend.vue";
import BetaflightLogo from "./betaflight-logo/BetaflightLogo.vue";
Expand All @@ -18,35 +18,42 @@ import PortUsage from "../js/port_usage.js";
import PortPicker from "./port-picker/PortPicker.vue";
import CONFIGURATOR from "../js/data_storage.js";

// Most of the global objects can go here at first.
// It's a bit of overkill for simple components,
// but these instance would eventually have more children
// which would find the use for those extra properties.
const betaflightModel = {
/*
Most of the global objects can go here at first.
It's a bit of overkill for simple components,
but these instance would eventually have more children
which would find the use for those extra properties.
FIXME For some reason, some of them (like PortHandler and FC)
need to be marked as reactive in it's own module, to detect
changes in arrays so I added the `reactive` wrapper there too.
*/
const betaflightModel = reactive({
CONFIGURATOR,
FC,
MSP,
PortUsage,
PortHandler,
};
});

i18next.on('initialized', function() {
i18next.on("initialized", function () {
console.log("i18n initialized, starting Vue framework");

const app = createApp({
data() { return betaflightModel; },
setup() {
return betaflightModel;
},
});

app
.use(I18NextVue, { i18next })
.component('BetaflightLogo', BetaflightLogo)
.component('BatteryLegend', BatteryLegend)
.component('StatusBar', StatusBar)
.component('BatteryIcon', BatteryIcon)
.component('PortPicker', PortPicker)
.mount('#main-wrapper');
app.use(I18NextVue, { i18next })
.component("BetaflightLogo", BetaflightLogo)
.component("BatteryLegend", BatteryLegend)
.component("StatusBar", StatusBar)
.component("BatteryIcon", BatteryIcon)
.component("PortPicker", PortPicker)
.mount("#main-wrapper");

if (process.env.NODE_ENV === 'development') {
if (process.env.NODE_ENV === "development") {
console.log("Development mode enabled, installing Vue tools");
// TODO Vue.config.devtools = true;
app.config.performance = true;
Expand Down
50 changes: 34 additions & 16 deletions src/components/port-picker/FirmwareVirtualOption.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
<template>
<div id="firmware-virtual-option" :style="{ display: isVirtual ? 'block' : 'none' }">
<div class="dropdown dropdown-dark">
<select id="firmware-version-dropdown" class="dropdown-select" :title="$t('virtualMSPVersion')">
<select
id="firmware-version-dropdown"
:value="modelValue"
class="dropdown-select"
:title="$t('virtualMSPVersion')"
@input="updateValue($event.target.value)"
>
<option v-for="(version, index) in firmwareVersions" :key="index" :value="version.value">
{{ version.label }}
</option>
Expand All @@ -11,24 +17,36 @@
</template>

<script>
import { defineComponent } from 'vue';
import { defineComponent, ref } from "vue";
export default defineComponent({
props: {
isVirtual: {
type: Boolean,
default: true,
props: {
modelValue: {
type: String,
default: "1.47.0",
},
isVirtual: {
type: Boolean,
default: true,
},
},
data() {
return {
firmwareVersions: [
{ value: "1.47.0", label: "MSP: 1.47 | Firmware: 4.6.*" },
{ value: "1.46.0", label: "MSP: 1.46 | Firmware: 4.5.*" },
{ value: "1.45.0", label: "MSP: 1.45 | Firmware: 4.4.*" },
{ value: "1.44.0", label: "MSP: 1.44 | Firmware: 4.3.*" },
],
};
emits: ["update:modelValue"],
setup(props, { emit }) {
const updateValue = (value) => {
emit("update:modelValue", value);
};
const firmwareVersions = ref([
{ value: "1.47.0", label: "MSP: 1.47 | Firmware: 4.6.*" },
{ value: "1.46.0", label: "MSP: 1.46 | Firmware: 4.5.*" },
{ value: "1.45.0", label: "MSP: 1.45 | Firmware: 4.4.*" },
{ value: "1.44.0", label: "MSP: 1.44 | Firmware: 4.3.*" },
]);
return {
firmwareVersions,
updateValue,
};
},
},
});
</script>
56 changes: 25 additions & 31 deletions src/components/port-picker/PortOverrideOption.vue
Original file line number Diff line number Diff line change
@@ -1,44 +1,38 @@
<template>
<div
v-if="isManual"
id="port-override-option"
>
<label
for="port-override"
><span>{{ $t("portOverrideText") }}</span>
<input
id="port-override"
type="text"
:value="value"
@change="inputValueChanged($event)"
>
</label>
</div>
<div v-if="isManual" id="port-override-option">
<label for="port-override">
<span>{{ $t("portOverrideText") }}</span>
<input id="port-override" type="text" :value="modelValue" @input="inputValueChanged($event.target.value)" />
</label>
</div>
</template>

<script>
import { defineComponent } from "vue";
import { set as setConfig } from "../../js/ConfigStorage";
import { defineComponent } from 'vue';
export default defineComponent({
props: {
value: {
type: String,
default: '/dev/rfcomm0',
},
methods: {
inputValueChanged(event) {
setConfig({ portOverride: event.target.value });
this.$emit("input", event.target.value);
props: {
modelValue: {
type: String,
default: "/dev/rfcomm0",
},
isManual: {
type: Boolean,
default: true,
},
},
},
methods: {
inputValueChanged(event) {
setConfig({'portOverride': event.target.value});
this.$emit('input', event.target.value);
emits: ["update:modelValue"],
setup(props, { emit }) {
const inputValueChanged = (newValue) => {
setConfig({ portOverride: newValue });
emit("update:modelValue", newValue);
};
return {
inputValueChanged,
};
},
},
});
</script>

Expand Down
43 changes: 19 additions & 24 deletions src/components/port-picker/PortPicker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,28 @@
<PortOverrideOption
v-if="modelValue.selectedPort === 'manual'"
:model-value="modelValue.portOverride"
@update:modelValue="updateValue('portOverride', $event)"
@update:modelValue="updateModelValue('portOverride', $event)"
/>
<FirmwareVirtualOption
v-if="modelValue.selectedPort === 'virtual' && !isConnected"
:model-value="modelValue.virtualMspVersion"
@update:modelValue="updateValue('virtualMspVersion', $event)"
@update:modelValue="updateModelValue('virtualMspVersion', $event)"
/>
<PortsInput
:model-value="modelValue.selectedPort"
:model-value="modelValue"
:connected-bluetooth-devices="connectedBluetoothDevices"
:connected-serial-devices="connectedSerialDevices"
:connected-usb-devices="connectedUsbDevices"
:disabled="disabled"
:show-virtual-option="showVirtualOption"
:show-manual-option="showManualOption"
@update:modelValue="updateValue(null, $event)"
@update:modelValue="updateModelValue(null, $event)"
/>
</div>
</template>

<script>
import { defineComponent } from "vue";
import { defineComponent, computed } from "vue";
import PortOverrideOption from "./PortOverrideOption.vue";
import FirmwareVirtualOption from "./FirmwareVirtualOption.vue";
import PortsInput from "./PortsInput.vue";
Expand All @@ -40,21 +40,15 @@ export default defineComponent({
props: {
modelValue: {
type: Object,
default: () => ({
selectedPort: "noselection",
selectedBaud: 115200,
portOverride: "/dev/rfcomm0",
virtualMspVersion: "1.46.0",
autoConnect: true,
}),
required: true,
},
connectedBluetoothDevices: {
type: Array,
default: () => [],
},
connectedSerialDevices: {
type: Array,
default: () => [],
required: true,
},
connectedUsbDevices: {
type: Array,
Expand All @@ -76,20 +70,21 @@ export default defineComponent({
emits: ["update:modelValue"],
computed: {
isConnected() {
return CONFIGURATOR.connectionValid;
},
},
setup(props, { emit }) {
const isConnected = computed(() => CONFIGURATOR.connectionValid);
methods: {
updateValue(key, value) {
if (key != null) {
this.$emit("update:modelValue", { ...this.modelValue, [key]: value });
const updateModelValue = (key, value) => {
if (key) {
emit("update:modelValue", { ...props.modelValue, [key]: value });
} else {
this.$emit("update:modelValue", { ...this.modelValue, ...value });
emit("update:modelValue", value); // Para el caso de PortsInput
}
},
};
return {
isConnected,
updateModelValue,
};
},
});
</script>
Expand Down
Loading

0 comments on commit 1d59a55

Please sign in to comment.