diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md index 7e0dc386306..f48284a9268 100644 --- a/.github/CHANGELOG.md +++ b/.github/CHANGELOG.md @@ -18,6 +18,7 @@ 1. [A380X/TELEX] Added popup for telex consent - @saschl (saschl) @Maximilian-Reuter (\_chaoz) 1. [ND] Fix memory leak when using TERR ON ND - @Nufflee (nufflee) 1. [A380X/OVHD] Fix RCDR GND CTL button/logic - @flogross89 (floridude) +1. [A380X] Various fixes in FMS and ECL @flogross89 (floridude) ## 0.12.0 diff --git a/fbw-a380x/src/systems/instruments/src/MFD/pages/FMS/F-PLN/FplnRevisionsMenu.tsx b/fbw-a380x/src/systems/instruments/src/MFD/pages/FMS/F-PLN/FplnRevisionsMenu.tsx index ac4cd8e1ab7..66ea64694e8 100644 --- a/fbw-a380x/src/systems/instruments/src/MFD/pages/FMS/F-PLN/FplnRevisionsMenu.tsx +++ b/fbw-a380x/src/systems/instruments/src/MFD/pages/FMS/F-PLN/FplnRevisionsMenu.tsx @@ -1,4 +1,4 @@ -import { TurnDirection } from '@flybywiresim/fbw-sdk'; +import { TurnDirection, WaypointDescriptor } from '@flybywiresim/fbw-sdk'; import { HoldType } from '@fmgc/flightplanning/data/flightplan'; import { SegmentClass } from '@fmgc/flightplanning/segments/SegmentClass'; import { FlightPlanIndex } from '@fmgc/index'; @@ -24,6 +24,8 @@ export function getRevisionsMenu(fpln: MfdFmsFpln, type: FplnRevisionsMenuType): return []; } + const revisedLeg = fpln.loadedFlightPlan?.legElementAt(legIndex); + return [ { name: 'FROM P.POS DIR TO', @@ -32,7 +34,7 @@ export function getRevisionsMenu(fpln: MfdFmsFpln, type: FplnRevisionsMenuType): legIndex >= (fpln.loadedFlightPlan?.firstMissedApproachLegIndex ?? Infinity) || planIndex === FlightPlanIndex.Temporary || [FplnRevisionsMenuType.Discontinuity || FplnRevisionsMenuType.TooSteepPath].includes(type) || - !fpln.loadedFlightPlan?.legElementAt(legIndex).isXF(), + !revisedLeg?.isXF(), onPressed: () => { const ppos = fpln.props.fmcService.master?.navigation.getPpos(); if (ppos) { @@ -85,17 +87,16 @@ export function getRevisionsMenu(fpln: MfdFmsFpln, type: FplnRevisionsMenuType): name: 'HOLD', disabled: [FplnRevisionsMenuType.Discontinuity || FplnRevisionsMenuType.TooSteepPath].includes(type), onPressed: async () => { - const waypoint = fpln.props.fmcService.master?.flightPlanService.active.legElementAt(legIndex); - if (waypoint && !waypoint.isHX()) { - const alt = waypoint.definition.altitude1 - ? waypoint.definition.altitude1 + if (revisedLeg && !revisedLeg.isHX()) { + const alt = revisedLeg.definition.altitude1 + ? revisedLeg.definition.altitude1 : SimVar.GetSimVarValue('INDICATED ALTITUDE', 'feet'); const previousLeg = fpln.props.fmcService.master?.flightPlanService.active.maybeElementAt(legIndex - 1); let inboundMagneticCourse = 100; const prevTerm = previousLeg?.isDiscontinuity === false && previousLeg?.terminationWaypoint(); - const wptTerm = waypoint.terminationWaypoint(); + const wptTerm = revisedLeg.terminationWaypoint(); if (previousLeg && previousLeg.isDiscontinuity === false && previousLeg.isXF() && prevTerm && wptTerm) { inboundMagneticCourse = Avionics.Utils.computeGreatCircleHeading(prevTerm.location, wptTerm.location); } @@ -122,7 +123,12 @@ export function getRevisionsMenu(fpln: MfdFmsFpln, type: FplnRevisionsMenuType): }, { name: 'AIRWAYS', - disabled: [FplnRevisionsMenuType.Discontinuity || FplnRevisionsMenuType.TooSteepPath].includes(type), + disabled: + [ + FplnRevisionsMenuType.Runway || FplnRevisionsMenuType.Discontinuity || FplnRevisionsMenuType.TooSteepPath, + ].includes(type) || + revisedLeg?.waypointDescriptor === WaypointDescriptor.Airport || + revisedLeg?.waypointDescriptor === WaypointDescriptor.Runway, onPressed: () => { fpln.props.fmcService.master?.flightPlanService.startAirwayEntry(legIndex); fpln.props.mfd.uiService.navigateTo(`fms/${fpln.props.mfd.uiService.activeUri.get().category}/f-pln-airways`); @@ -132,7 +138,7 @@ export function getRevisionsMenu(fpln: MfdFmsFpln, type: FplnRevisionsMenuType): name: !altnFlightPlan && ![FplnRevisionsMenuType.Discontinuity || FplnRevisionsMenuType.TooSteepPath].includes(type) && - fpln.loadedFlightPlan?.legElementAt(legIndex).definition.overfly + revisedLeg?.definition.overfly ? 'DELETE OVERFLY *' : 'OVERFLY *', disabled: @@ -163,9 +169,11 @@ export function getRevisionsMenu(fpln: MfdFmsFpln, type: FplnRevisionsMenuType): ), }, { - name: 'CMS', + name: '(N/A) CMS', disabled: - altnFlightPlan || [FplnRevisionsMenuType.Discontinuity || FplnRevisionsMenuType.TooSteepPath].includes(type), + true || + altnFlightPlan || + [FplnRevisionsMenuType.Discontinuity || FplnRevisionsMenuType.TooSteepPath].includes(type), onPressed: () => fpln.props.mfd.uiService.navigateTo( `fms/${fpln.props.mfd.uiService.activeUri.get().category}/f-pln-vert-rev/cms`, @@ -185,9 +193,9 @@ export function getRevisionsMenu(fpln: MfdFmsFpln, type: FplnRevisionsMenuType): disabled: true, onPressed: () => { // Find out whether waypoint is CLB, CRZ or DES waypoint and direct to appropriate WIND sub-page - if (fpln.loadedFlightPlan?.legElementAt(legIndex)?.segment?.class === SegmentClass.Arrival) { + if (revisedLeg?.segment?.class === SegmentClass.Arrival) { fpln.props.mfd.uiService.navigateTo(`fms/${fpln.props.mfd.uiService.activeUri.get().category}/wind/des`); - } else if (fpln.loadedFlightPlan?.legElementAt(legIndex)?.segment?.class === SegmentClass.Enroute) { + } else if (revisedLeg?.segment?.class === SegmentClass.Enroute) { fpln.props.mfd.uiService.navigateTo(`fms/${fpln.props.mfd.uiService.activeUri.get().category}/wind/crz`); } else { fpln.props.mfd.uiService.navigateTo(`fms/${fpln.props.mfd.uiService.activeUri.get().category}/wind/clb`); diff --git a/fbw-a380x/src/systems/instruments/src/MFD/pages/common/InputField.tsx b/fbw-a380x/src/systems/instruments/src/MFD/pages/common/InputField.tsx index e9afa027bba..bdb567abc7d 100644 --- a/fbw-a380x/src/systems/instruments/src/MFD/pages/common/InputField.tsx +++ b/fbw-a380x/src/systems/instruments/src/MFD/pages/common/InputField.tsx @@ -167,6 +167,10 @@ export class InputField extends DisplayComponent> { } private onKeyDown(ev: KeyboardEvent) { + if (!this.isFocused.get()) { + return; + } + if (ev.keyCode === KeyCode.KEY_BACK_SPACE) { this.handleBackspace(); } @@ -185,6 +189,10 @@ export class InputField extends DisplayComponent> { } private onKeyPress(ev: KeyboardEvent) { + if (!this.isFocused.get()) { + return; + } + // Un-select the text this.textInputRef.instance.classList.remove('valueSelected'); @@ -238,12 +246,12 @@ export class InputField extends DisplayComponent> { } this.isFocused.set(true); - // After 30s, unfocus field, if some other weird focus error happens + // After 20s, unfocus field, if some other weird focus error happens setTimeout(() => { if (this.isFocused.get()) { Coherent.trigger('UNFOCUS_INPUT_FIELD', this.guid); } - }, 30_000); + }, 20_000); this.textInputRef.instance.classList.add('valueSelected'); this.textInputRef.instance.classList.add('editing'); if (this.props.mandatory?.get()) { @@ -277,7 +285,7 @@ export class InputField extends DisplayComponent> { } // Restore mandatory class for correct coloring of dot (e.g. non-placeholders) - if (!this.props.value.get() && this.props.mandatory?.get()) { + if (this.props.value.get() === null && this.props.mandatory?.get()) { this.textInputRef.instance.classList.add('mandatory'); } @@ -398,7 +406,7 @@ export class InputField extends DisplayComponent> { this.subs.push( this.props.mandatory.sub((val) => { - if (val && !this.props.value.get()) { + if (val && this.props.value.get() === null) { this.textInputRef.instance.classList.add('mandatory'); } else { this.textInputRef.instance.classList.remove('mandatory'); @@ -434,7 +442,7 @@ export class InputField extends DisplayComponent> { this.containerRef.instance.classList.add('disabled'); this.textInputRef.instance.classList.add('disabled'); - if (this.props.mandatory?.get() && !this.props.value.get()) { + if (this.props.mandatory?.get() && this.props.value.get() === null) { this.textInputRef.instance.classList.remove('mandatory'); } } else { @@ -442,7 +450,7 @@ export class InputField extends DisplayComponent> { this.containerRef.instance.classList.remove('disabled'); this.textInputRef.instance.classList.remove('disabled'); - if (this.props.mandatory?.get() && !this.props.value.get()) { + if (this.props.mandatory?.get() && this.props.value.get() === null) { this.textInputRef.instance.classList.add('mandatory'); } } diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures.tsx index 0e5bf20ddaa..b31abea2174 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/NormalProcedures.tsx @@ -164,6 +164,7 @@ export const EcamNormalProcedures: { [n: number]: NormalProcedure } = { }, 1000006: { title: '<>', + deferred: true, items: [ { name: 'RWY & SID', diff --git a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx index ee63cec8c67..75fff92c9e9 100644 --- a/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx +++ b/fbw-a380x/src/systems/instruments/src/MsfsAvionicsCommon/EcamMessages/index.tsx @@ -582,6 +582,8 @@ export interface NormalProcedure { title: string; /** An array of possible checklist items.. */ items: ChecklistAction[]; + /** Checklist is deferred, i.e. only activated by request */ + deferred?: boolean; } export function isChecklistAction(element: ChecklistAction | ChecklistCondition): element is ChecklistAction { diff --git a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts index 0fe57a0bdf1..d38c4274c12 100644 --- a/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts +++ b/fbw-a380x/src/systems/systems-host/systems/FlightWarningSystem/FwsNormalChecklists.ts @@ -64,7 +64,7 @@ export class FwsNormalChecklists { const proc = EcamNormalProcedures[k] as NormalProcedure; this.checklistState.setValue(k, { id: k, - checklistCompleted: false, + checklistCompleted: proc.deferred ? true : false, itemsCompleted: Array(proc.items.length).fill(false), }); }); @@ -176,7 +176,6 @@ export class FwsNormalChecklists { this.moveDown(); } else if (this.selectedLine.get() === clState.itemsCompleted.length) { // C/L complete - console.log('COMPLETE'); clState.checklistCompleted = true; const proc = EcamNormalProcedures[this.checklistId.get()]; clState.itemsCompleted = clState.itemsCompleted.map((val, index) => (proc.items[index].sensed ? val : true)); @@ -199,7 +198,7 @@ export class FwsNormalChecklists { const procFollowing = EcamNormalProcedures[idFollowing]; const clStateFollowing: ChecklistState = { id: idFollowing, - checklistCompleted: false, + checklistCompleted: procFollowing.deferred ? true : false, itemsCompleted: [...clFollowing.itemsCompleted].map((val, index) => procFollowing.items[index].sensed ? val : false, ),