Gauge logic

This commit is contained in:
2025-02-03 00:13:44 +01:00
parent 3af799d18e
commit 5599c3d1bd
13 changed files with 317 additions and 141 deletions
@@ -0,0 +1,67 @@
import {
ComponentProps,
ComputedSubject,
DisplayComponent,
FSComponent,
NodeReference,
Subscribable,
VNode,
} from '@microsoft/msfs-sdk';
interface ControlsProps extends ComponentProps {
containerRef: NodeReference<HTMLDivElement>;
reload: () => void;
position: Subscribable<number>;
page: number;
}
export class Controls extends DisplayComponent<ControlsProps> {
private cycleRef = FSComponent.createRef<HTMLButtonElement>();
private toTopRef = FSComponent.createRef<HTMLButtonElement>();
private reloadRef = FSComponent.createRef<HTMLButtonElement>();
private switchPosRef = FSComponent.createRef<HTMLButtonElement>();
private buttonName = ComputedSubject.create<number, string>(0, (val) => {
if (val === 1) return 'Move to INS';
else if (val === 2) return 'Move to FE';
return 'ERROR';
});
constructor(props: ControlsProps) {
super(props);
props.position.sub((p) => this.buttonName.set(p));
}
private cycle = (): void => {
if (this.props.page === 0) SimVar.SetSimVarValue('L:KH_FE_FPLAN_P1', 'bool', true);
else if (this.props.page === 1) SimVar.SetSimVarValue('L:KH_FE_FPLAN_P1', 'bool', false);
};
private toTop = (): void => {
if (!this.props.containerRef.instance) return;
this.props.containerRef.instance.scrollTop = 0;
};
private switchPosition = (): void => {
if (this.props.position.get() === 1) SimVar.SetSimVarValue('L:KH_FE_FPLAN_BOARD', 'number', 2);
else if (this.props.position.get() === 2) SimVar.SetSimVarValue('L:KH_FE_FPLAN_BOARD', 'number', 1);
};
public render = (): VNode => (
<div id="KH_CTRL">
{this.props.page === 1 && <button ref={this.cycleRef}>Prev Page</button>}
<button ref={this.toTopRef}>To top</button>
<button ref={this.reloadRef}>Reload</button>
<button ref={this.switchPosRef}>{this.buttonName}</button>
{this.props.page === 0 && <button ref={this.cycleRef}>Next Page</button>}
</div>
);
public onAfterRender = (): void => {
this.cycleRef.instance.onclick = this.cycle;
this.toTopRef.instance.onclick = this.toTop;
this.reloadRef.instance.onclick = this.props.reload;
this.switchPosRef.instance.onclick = this.switchPosition;
};
}
+72
View File
@@ -0,0 +1,72 @@
import { ComponentProps, DisplayComponent, FSComponent, Subscribable, VNode } from '@microsoft/msfs-sdk';
import { Controls } from '../controls/controls';
interface OFPProps extends ComponentProps {
content: Subscribable<string>;
reload: () => void;
position: Subscribable<number>;
}
export class OFP extends DisplayComponent<OFPProps> {
private containerRef = FSComponent.createRef<HTMLDivElement>();
private ofpRef = FSComponent.createRef<HTMLDivElement>();
constructor(props: OFPProps) {
super(props);
}
private defineDragScroll = (horizontalScroll = true, verticalScroll = true): void => {
if (!this.containerRef.instance) return;
let pos = { top: 0, left: 0, x: 0, y: 0 };
const mouseDownHandler = (e: MouseEvent) => {
pos = {
left: this.containerRef.instance.scrollLeft,
top: this.containerRef.instance.scrollTop,
x: e.clientX,
y: e.clientY,
};
document.addEventListener('mousemove', mouseMoveHandler);
document.addEventListener('mouseup', mouseUpHandler);
document.removeEventListener('mouseleave', mouseUpHandler);
};
const mouseMoveHandler = (e: MouseEvent) => {
const dx = e.clientX - pos.x;
const dy = e.clientY - pos.y;
if (verticalScroll) {
this.containerRef.instance.scrollTop = pos.top - dy;
}
if (horizontalScroll) {
this.containerRef.instance.scrollLeft = pos.left - dx;
}
};
const mouseUpHandler = (e: MouseEvent) => {
document.removeEventListener('mousemove', mouseMoveHandler);
document.removeEventListener('mouseup', mouseUpHandler);
document.removeEventListener('mouseleave', mouseUpHandler);
};
this.containerRef.instance.addEventListener('mousedown', mouseDownHandler);
};
public render = (): VNode => (
<>
<div ref={this.containerRef} id="KH_FE_FPLAN">
<div ref={this.ofpRef} id="OFP" />
</div>
<Controls containerRef={this.containerRef} position={this.props.position} reload={this.props.reload} page={0} />
</>
);
public onAfterRender = (): void => {
this.defineDragScroll();
this.props.content.sub((content) => {
this.ofpRef.instance.innerHTML = content;
});
};
}
+54 -65
View File
@@ -1,82 +1,71 @@
import { ComponentProps, DisplayComponent, FSComponent, Subscribable, VNode } from '@microsoft/msfs-sdk';
function defineDragScroll(ele: HTMLElement, horizontalScroll = true, verticalScroll = true) {
let pos = { top: 0, left: 0, x: 0, y: 0 };
const mouseDownHandler = function (e: MouseEvent) {
pos = {
// The current scroll
left: ele.scrollLeft,
top: ele.scrollTop,
// Get the current mouse position
x: e.clientX,
y: e.clientY,
};
document.addEventListener('mousemove', mouseMoveHandler);
document.addEventListener('mouseup', mouseUpHandler);
document.removeEventListener('mouseleave', mouseUpHandler);
};
const mouseMoveHandler = function (e: MouseEvent) {
// How far the mouse has been moved
const dx = e.clientX - pos.x;
const dy = e.clientY - pos.y;
// Scroll the element
if (verticalScroll) {
ele.scrollTop = pos.top - dy;
}
if (horizontalScroll) {
ele.scrollLeft = pos.left - dx;
}
};
const mouseUpHandler = function (e: MouseEvent) {
document.removeEventListener('mousemove', mouseMoveHandler);
document.removeEventListener('mouseup', mouseUpHandler);
document.removeEventListener('mouseleave', mouseUpHandler);
};
ele.addEventListener('mousedown', mouseDownHandler);
}
import { Controls } from '../controls/controls';
interface TLRProps extends ComponentProps {
content: Subscribable<string>;
reload: () => void;
position: Subscribable<number>;
}
export class TLR extends DisplayComponent<TLRProps> {
private containerRef = FSComponent.createRef<HTMLDivElement>();
constructor(props: TLRProps) {
super(props);
}
onAfterRender() {
const ele = document.getElementById('KH_FE_FPLAN');
if (ele) defineDragScroll(ele);
const toIns = document.getElementById('KH_FE_FPLAN_INS');
if (toIns) toIns.onclick = this.toIns;
const toTop = document.getElementById('KH_FE_FPLAN_TOP');
if (toTop) toTop.onclick = this.toTop;
}
private defineDragScroll = (horizontalScroll = true, verticalScroll = true): void => {
if (!this.containerRef.instance) return;
toIns() {
SimVar.SetSimVarValue('L:KH_FE_FPLAN_BOARD', 'number', 2);
}
let pos = { top: 0, left: 0, x: 0, y: 0 };
toTop() {
const ele = document.getElementById('KH_FE_FPLAN');
if (ele) ele.scrollTop = 0;
}
const mouseDownHandler = (e: MouseEvent) => {
pos = {
left: this.containerRef.instance.scrollLeft,
top: this.containerRef.instance.scrollTop,
x: e.clientX,
y: e.clientY,
};
document.addEventListener('mousemove', mouseMoveHandler);
document.addEventListener('mouseup', mouseUpHandler);
document.addEventListener('mouseleave', mouseUpHandler);
};
public render(): VNode {
return (
<>
<div id="KH_FE_FPLAN">
<div id="TLR">
<div>
<pre>{this.props.content}</pre>
</div>
const mouseMoveHandler = (e: MouseEvent) => {
const dx = e.clientX - pos.x;
const dy = e.clientY - pos.y;
if (verticalScroll) {
this.containerRef.instance.scrollTop = pos.top - dy;
}
if (horizontalScroll) {
this.containerRef.instance.scrollLeft = pos.left - dx;
}
};
const mouseUpHandler = (e: MouseEvent) => {
document.removeEventListener('mousemove', mouseMoveHandler);
document.removeEventListener('mouseup', mouseUpHandler);
document.removeEventListener('mouseleave', mouseUpHandler);
};
this.containerRef.instance.addEventListener('mousedown', mouseDownHandler);
};
public render = (): VNode => (
<>
<div ref={this.containerRef} id="KH_FE_FPLAN" class="p2">
<div id="TLR">
<div>
<pre>{this.props.content}</pre>
</div>
</div>
<div id="KH_CTRL">
<button id="KH_FE_FPLAN_TOP">To top</button>
<button id="KH_FE_FPLAN_INS">Switch to INS</button>
</div>
</>
);
}
</div>
<Controls containerRef={this.containerRef} position={this.props.position} reload={this.props.reload} page={1} />
</>
);
public onAfterRender = (): void => {
this.defineDragScroll();
};
}
+4 -3
View File
@@ -1,6 +1,7 @@
<link rel="stylesheet" href="index.css" />
<script type="text/html" import-script="/Pages/VCockpit/Instruments/FSS_B727/KH_FE_FPLAN/index.js"></script>
<script type="text/html" import-script="/JS/dataStorage.js"></script>
<script type="text/html" id="kh-fe-fplan">
<div id="root"></div>
</script>
<link rel="stylesheet" href="index.css" />
<script type="text/html" import-script="/Pages/VCockpit/Instruments/FSS_B727/KH_FE_FPLAN/index.js"></script>
+17 -10
View File
@@ -45,27 +45,34 @@
}
#KH_FE_FPLAN {
#TLR div {
height: calc(100vh - 6vw - 180px);
width: 100%;
margin-top: 100px;
margin-bottom: 3vw;
overflow-y: scroll;
overflow-x: hidden;
#TLR div,
#OFP div {
line-height: unset !important;
font-size: unset !important;
}
#TLR pre {
#TLR pre,
#OFP pre {
white-space: pre;
line-height: 14px;
font-size: 13px;
font-family: 'Consolas' !important;
}
#TLR img {
width: calc(100vw - 6vw);
#OFP img {
width: 100%;
}
height: calc(100vh - 6vw - 170px);
width: 100%;
margin-top: 90px;
margin-bottom: 3vw;
overflow-y: scroll;
overflow-x: hidden;
&.p2 {
height: calc(100vh - 6vw - 240px);
margin-top: 160px;
}
}
}
+72 -21
View File
@@ -1,23 +1,30 @@
/// <reference types="@microsoft/msfs-types/Pages/VCockpit/Core/VCockpit" />
/// <reference types="@microsoft/msfs-types/JS/dataStorage" />
import './index.scss';
import { EventBus, FSComponent, SimVarPublisher, SimVarValueType, Subject } from '@microsoft/msfs-sdk';
import { OFP } from './components/ofp/ofp';
import { TLR } from './components/tlr/tlr';
export interface NewDataEvents {
newData: boolean;
position: number;
}
class KH_FE_FPLAN extends BaseInstrument {
private readonly bus = new EventBus();
private readonly newDataPublisher = new SimVarPublisher<NewDataEvents>(
new Map([['newData', { name: 'L:KH_FE_FPLAN_NEW_DATA', type: SimVarValueType.Bool }]]),
new Map([
['newData', { name: 'L:KH_FE_FPLAN_NEW_DATA', type: SimVarValueType.Bool }],
['position', { name: 'L:KH_FE_FPLAN_BOARD', type: SimVarValueType.Number }],
]),
this.bus
);
private contentPLAN = Subject.create<string>('');
private contentOFP = Subject.create<string>('');
private contentTLR = Subject.create<string>('');
private position = Subject.create<number>(0);
private sbID = '';
get templateID(): string {
return 'kh-fe-fplan';
@@ -27,31 +34,75 @@ class KH_FE_FPLAN extends BaseInstrument {
return true;
}
public connectedCallback(): void {
super.connectedCallback();
constructor() {
super();
this.newDataPublisher.startPublish();
this.bus
.getSubscriber<NewDataEvents>()
.on('newData')
.handle((flag) => {
if (!flag) return;
SimVar.SetSimVarValue('L:KH_FE_FPLAN_NEW_DATA', 'bool', 0);
this.contentPLAN.set(JSON.parse(window.localStorage.getItem('KH_FE_FPLAN_PLAN') ?? ''));
this.contentTLR.set(JSON.parse(window.localStorage.getItem('KH_FE_FPLAN_TLR') ?? ''));
});
window.localStorage.removeItem('KH_FE_FPLAN_PLAN');
window.localStorage.removeItem('KH_FE_FPLAN_TLR');
FSComponent.render(<TLR content={this.contentTLR} />, document.getElementById('root'));
const config = GetStoredData('FSS_B727_EFB_CONFIG_PREFLIGHT');
try {
this.sbID = JSON.parse(config).simBriefId;
} catch (e) {
console.error('Failed loading config.', e);
}
}
private getSB = async (): Promise<void> => {
try {
const res = await fetch(`https://www.simbrief.com/api/xml.fetcher.php?username=${this.sbID}&json=1`);
if (res.ok) {
try {
const data = await res.json();
let ofp: string = data.text.plan_html;
ofp = ofp.replace(/href=".*?"/g, '');
this.contentOFP.set(ofp);
this.contentTLR.set(data.text.tlr_section);
} catch (e) {
console.error('JSON DECODE ERR', e);
}
}
} catch (e) {
console.error('FETCH ERR', e);
}
};
private reloadSB = (): void => {
SimVar.SetSimVarValue('L:KH_FE_FPLAN_NEW_DATA', 'bool', 1);
};
protected Update(): void {
super.Update();
this.newDataPublisher.onUpdate();
}
public connectedCallback(): void {
super.connectedCallback();
this.newDataPublisher.startPublish();
const sub = this.bus.getSubscriber<NewDataEvents>();
sub.on('newData').handle((flag) => {
if (!flag) return;
SimVar.SetSimVarValue('L:KH_FE_FPLAN_NEW_DATA', 'bool', 0);
this.getSB();
});
sub.on('position').handle((position) => {
this.position.set(position);
});
window.localStorage.removeItem('KH_FE_FPLAN_SB_ID');
const url = new URL(this.getAttribute('Url') ?? '');
const type = url.searchParams.get('type');
FSComponent.render(
<>
{type === 'ofp' && <OFP content={this.contentOFP} position={this.position} reload={this.reloadSB} />}
{type === 'tlr' && <TLR content={this.contentTLR} position={this.position} reload={this.reloadSB} />}
</>,
document.getElementById('root')
);
}
}
registerInstrument('kh-fe-fplan', KH_FE_FPLAN);