diff --git a/fbw-a380x/src/systems/instruments/src/AtcMailbox/AtcMailbox.tsx b/fbw-a380x/src/systems/instruments/src/AtcMailbox/AtcMailbox.tsx index 57c394aff8b..f1824432f36 100644 --- a/fbw-a380x/src/systems/instruments/src/AtcMailbox/AtcMailbox.tsx +++ b/fbw-a380x/src/systems/instruments/src/AtcMailbox/AtcMailbox.tsx @@ -31,6 +31,7 @@ export class AtcMailbox extends DisplayComponent { destroy(): void { this.topRef.getOrDefault()?.removeEventListener('mousemove', this.onMouseMoveHandler); + this.mouseCursorRef.getOrDefault()?.destroy(); super.destroy(); } diff --git a/fbw-a380x/src/systems/instruments/src/MFD/MFD.tsx b/fbw-a380x/src/systems/instruments/src/MFD/MFD.tsx index cd60b114481..226be5a8efd 100644 --- a/fbw-a380x/src/systems/instruments/src/MFD/MFD.tsx +++ b/fbw-a380x/src/systems/instruments/src/MFD/MFD.tsx @@ -328,6 +328,8 @@ export class MfdComponent extends DisplayComponent implements destroy(): void { this.topRef.getOrDefault()?.removeEventListener('mousemove', this.onMouseMoveHandler); + this.mouseCursorRef.getOrDefault()?.destroy(); + this.duplicateNamesRef.getOrDefault()?.destroy(); super.destroy(); } diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/UiWidgets/MouseCursor.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/UiWidgets/MouseCursor.tsx index f285a6fdf8b..8bc6ad6fa73 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/UiWidgets/MouseCursor.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/UiWidgets/MouseCursor.tsx @@ -25,7 +25,7 @@ interface MouseCursorProps extends ComponentProps { } export class MouseCursor extends DisplayComponent { - private subs: Subscription[] = []; + private readonly subs: Subscription[] = []; private readonly divRef = FSComponent.createRef(); @@ -36,6 +36,8 @@ export class MouseCursor extends DisplayComponent { private readonly fillColor = this.color.map((c) => (c === MouseCursorColor.Magenta ? '#ff94ff' : '#ffff00')); + private readonly rotation = this.props.side.map((side) => `rotate(${side === 'FO' ? 90 : 0} 40 40)`); + private hideTimer: ReturnType | undefined = undefined; updatePosition(x: number, y: number) { @@ -72,13 +74,21 @@ export class MouseCursor extends DisplayComponent { if (this.props.visible) { this.subs.push(this.props.visible.sub((vis) => (vis ? this.show() : this.hide()), true)); } + + this.subs.push(this.fillColor, this.rotation); + } + + destroy(): void { + for (const s of this.subs) { + s.destroy(); + } } render(): VNode { return (
- `rotate(${side === 'FO' ? 90 : 0} 40 40)`)}> + diff --git a/fbw-a380x/src/systems/instruments/src/ND/OansControlPanel.tsx b/fbw-a380x/src/systems/instruments/src/ND/OansControlPanel.tsx index e70d8e9116e..b215d3a3806 100644 --- a/fbw-a380x/src/systems/instruments/src/ND/OansControlPanel.tsx +++ b/fbw-a380x/src/systems/instruments/src/ND/OansControlPanel.tsx @@ -163,7 +163,7 @@ export class OansControlPanel extends DisplayComponent { private readonly pposLongWord = Arinc429LocalVarConsumerSubject.create(this.sub.on('longitude')); - private presentPos = MappedSubject.create( + private readonly presentPos = MappedSubject.create( ([lat, lon]) => { return { lat: lat.value, long: lon.value } as Coordinates; }, @@ -171,15 +171,14 @@ export class OansControlPanel extends DisplayComponent { this.pposLongWord, ); - private presentPosNotAvailable = MappedSubject.create( + private readonly presentPosNotAvailable = MappedSubject.create( ([lat, long]) => !lat.isNormalOperation() || !long.isNormalOperation(), this.pposLatWord, this.pposLongWord, ); - private readonly setPlanModeDisplay = ConsumerSubject.create(this.sub.on('oans_show_set_plan_mode'), false).map( - (it) => (it ? 'inherit' : 'none'), - ); + private readonly setPlanModeConsumer = ConsumerSubject.create(this.sub.on('oans_show_set_plan_mode'), false); + private readonly setPlanModeDisplay = this.setPlanModeConsumer.map((it) => (it ? 'inherit' : 'none')); private readonly fmsDataStore = new FmsDataStore(this.props.bus); @@ -304,16 +303,18 @@ export class OansControlPanel extends DisplayComponent { }, true), ); - this.fmsDataStore.landingRunway.sub(async (it) => { - // Set control panel display - if (it) { - // Load runway data - const destination = this.fmsDataStore.destination.get(); - if (destination && this.navigraphAvailable.get() === false) { - this.setBtvRunwayFromFmsRunway(); + this.subs.push( + this.fmsDataStore.landingRunway.sub(async (it) => { + // Set control panel display + if (it) { + // Load runway data + const destination = this.fmsDataStore.destination.get(); + if (destination && this.navigraphAvailable.get() === false) { + this.setBtvRunwayFromFmsRunway(); + } } - } - }); + }), + ); this.subs.push( this.sub @@ -336,47 +337,74 @@ export class OansControlPanel extends DisplayComponent { this.subs.push(this.sub.on('oans_display_airport').handle((arpt) => this.handleSelectAirport(arpt))); - this.selectedEntityIndex.sub((val) => { - const searchMode = this.selectedEntityType.get(); - if (searchMode !== null && this.mapDataFeatures && val !== null) { - const prop = ControlPanelUtils.getMapDataSearchModeProp(searchMode); - const idx = this.mapDataFeatures.findIndex((f) => f.properties[prop] === this.availableEntityList.get(val)); - this.selectedEntityString.set(idx !== -1 ? this.mapDataFeatures[idx]?.properties[prop]?.toString() ?? '' : ''); - - if ( - (idx !== -1 && searchMode === ControlPanelMapDataSearchMode.Runway) || - searchMode === ControlPanelMapDataSearchMode.Stand - ) { - const feature = this.mapDataFeatures[idx] as Feature; - this.selectedEntityPosition = feature.geometry.coordinates; - this.selectedFeatureId.set(feature.properties?.id); - this.selectedFeatureType.set(feature.properties?.feattype); - } else if ( - idx !== -1 && - (searchMode === ControlPanelMapDataSearchMode.Taxiway || searchMode === ControlPanelMapDataSearchMode.Other) - ) { - const taxiway = this.mapDataFeatures[idx] as Feature; - this.selectedEntityPosition = taxiway.properties.midpoint?.coordinates ?? [0, 0]; - this.selectedFeatureId.set(taxiway.properties?.id); - this.selectedFeatureType.set(taxiway.properties?.feattype); - } + this.subs.push( + this.selectedEntityIndex.sub((val) => { + const searchMode = this.selectedEntityType.get(); + if (searchMode !== null && this.mapDataFeatures && val !== null) { + const prop = ControlPanelUtils.getMapDataSearchModeProp(searchMode); + const idx = this.mapDataFeatures.findIndex((f) => f.properties[prop] === this.availableEntityList.get(val)); + this.selectedEntityString.set( + idx !== -1 ? this.mapDataFeatures[idx]?.properties[prop]?.toString() ?? '' : '', + ); - if (idx !== -1 && this.selectedEntityType.get() === ControlPanelMapDataSearchMode.Runway) { - this.runwayLda.set(this.mapDataFeatures[idx].properties.lda?.toFixed(0) ?? ''); - this.runwayTora.set(this.mapDataFeatures[idx].properties.tora?.toFixed(0) ?? ''); + if ( + (idx !== -1 && searchMode === ControlPanelMapDataSearchMode.Runway) || + searchMode === ControlPanelMapDataSearchMode.Stand + ) { + const feature = this.mapDataFeatures[idx] as Feature; + this.selectedEntityPosition = feature.geometry.coordinates; + this.selectedFeatureId.set(feature.properties?.id); + this.selectedFeatureType.set(feature.properties?.feattype); + } else if ( + idx !== -1 && + (searchMode === ControlPanelMapDataSearchMode.Taxiway || searchMode === ControlPanelMapDataSearchMode.Other) + ) { + const taxiway = this.mapDataFeatures[idx] as Feature; + this.selectedEntityPosition = taxiway.properties.midpoint?.coordinates ?? [0, 0]; + this.selectedFeatureId.set(taxiway.properties?.id); + this.selectedFeatureType.set(taxiway.properties?.feattype); + } + + if (idx !== -1 && this.selectedEntityType.get() === ControlPanelMapDataSearchMode.Runway) { + this.runwayLda.set(this.mapDataFeatures[idx].properties.lda?.toFixed(0) ?? ''); + this.runwayTora.set(this.mapDataFeatures[idx].properties.tora?.toFixed(0) ?? ''); + } + } else { + this.selectedEntityString.set(''); + this.runwayLda.set(''); + this.runwayTora.set(''); } - } else { - this.selectedEntityString.set(''); - this.runwayLda.set(''); - this.runwayTora.set(''); - } - }, true); - this.selectedEntityType.sub((v) => this.handleSelectMapDataSearchMode(v ?? ControlPanelMapDataSearchMode.Runway)); + }, true), + ); + this.subs.push( + this.selectedEntityType.sub((v) => this.handleSelectMapDataSearchMode(v ?? ControlPanelMapDataSearchMode.Runway)), + ); - this.sub - .on(this.props.side === 'L' ? 'kccuOnL' : 'kccuOnR') - .whenChanged() - .handle((it) => this.interactionMode.set(it ? InteractionMode.Kccu : InteractionMode.Touchscreen)); + this.subs.push( + this.sub + .on(this.props.side === 'L' ? 'kccuOnL' : 'kccuOnR') + .whenChanged() + .handle((it) => this.interactionMode.set(it ? InteractionMode.Kccu : InteractionMode.Touchscreen)), + ); + + this.subs.push( + this.setPlanModeConsumer, + this.setPlanModeDisplay, + this.oansResetPulled, + this.oansAvailable, + this.entityIsNotSelected, + this.symbolsForFeatureIds, + this.flagExistsForEntity, + this.crossExistsForEntity, + this.pposLatWord, + this.pposLongWord, + this.presentPos, + this.presentPosNotAvailable, + this.oansRequestedStoppingDistance, + this.reqStoppingDistance, + this.fmsLandingRunwayVisibility, + this.airportDatabase, + ); } public updateAirportSearchData() { diff --git a/fbw-common/src/systems/instruments/src/OANC/OancMovingModeOverlay.tsx b/fbw-common/src/systems/instruments/src/OANC/OancMovingModeOverlay.tsx index 450f0573ec8..75539b4500f 100644 --- a/fbw-common/src/systems/instruments/src/OANC/OancMovingModeOverlay.tsx +++ b/fbw-common/src/systems/instruments/src/OANC/OancMovingModeOverlay.tsx @@ -60,6 +60,8 @@ export class OancMovingModeOverlay extends DisplayComponent this.rotationArinc429Word.setValueSsm(r, Arinc429SignStatusMatrix.NormalOperation); }), ); + + this.subs.push(this.arcModeVisible, this.roseModeVisible); } destroy(): void {