1
+ import { ComponentProps , DisplayComponent , EventBus , FSComponent , VNode } from "@microsoft/msfs-sdk"
2
+ import { CancelToken , navigraphRequest } from "navigraph/auth"
3
+ import { packages } from "../Lib/navigraph"
4
+ import { AuthService } from "../Services/AuthService"
5
+ import "./NavigraphLogin.css"
6
+ import { Dropdown } from "./Dropdown"
7
+
8
+ interface NavigraphLoginProps extends ComponentProps {
9
+ bus : EventBus
10
+ }
11
+
12
+ export class NavigraphLogin extends DisplayComponent < NavigraphLoginProps > {
13
+ private readonly textRef = FSComponent . createRef < HTMLDivElement > ( )
14
+ private readonly navdataTextRef = FSComponent . createRef < HTMLDivElement > ( )
15
+ private readonly loginButtonRef = FSComponent . createRef < HTMLButtonElement > ( )
16
+ private readonly qrCodeRef = FSComponent . createRef < HTMLImageElement > ( )
17
+ private readonly dropdownRef = FSComponent . createRef < Dropdown > ( )
18
+ private readonly downloadButtonRef = FSComponent . createRef < HTMLButtonElement > ( )
19
+
20
+ private cancelSource = CancelToken . source ( )
21
+
22
+ private commBusListener : ViewListener . ViewListener
23
+
24
+ constructor ( props : NavigraphLoginProps ) {
25
+ super ( props )
26
+
27
+ this . commBusListener = RegisterViewListener ( "JS_LISTENER_COMM_BUS" , ( ) => {
28
+ console . info ( "JS_LISTENER_COMM_BUS registered" )
29
+ } )
30
+
31
+ this . commBusListener . on ( "NAVIGRAPH_NavdataDownloaded" , ( ) => {
32
+ console . info ( "WASM downloaded navdata" )
33
+ this . navdataTextRef . instance . textContent = "Navdata downloaded!"
34
+ } )
35
+
36
+ this . commBusListener . on ( "NAVIGRAPH_UnzippedFilesRemaining" , ( jsonArgs : string ) => {
37
+ const args = JSON . parse ( jsonArgs )
38
+ console . info ( "WASM unzipping files" , args )
39
+ const percent = Math . round ( ( args . unzipped / args . total ) * 100 )
40
+ this . navdataTextRef . instance . textContent = `Unzipping files... ${ percent } % complete`
41
+ } )
42
+ }
43
+
44
+ public render ( ) : VNode {
45
+ return (
46
+ < div class = "auth-container" >
47
+ < div class = "horizontal" >
48
+ < div class = "vertical" >
49
+ < div ref = { this . textRef } />
50
+ < div ref = { this . loginButtonRef } class = "button" />
51
+ < div ref = { this . navdataTextRef } />
52
+ < img ref = { this . qrCodeRef } class = "qr-code" />
53
+ </ div >
54
+ < div class = "vertical" >
55
+ < Dropdown ref = { this . dropdownRef } />
56
+ < div ref = { this . downloadButtonRef } class = "button" >
57
+ Download
58
+ </ div >
59
+ </ div >
60
+ </ div >
61
+ </ div >
62
+ )
63
+ }
64
+
65
+ public onBeforeRender ( ) : void {
66
+ super . onBeforeRender ( )
67
+ }
68
+
69
+ public onAfterRender ( node : VNode ) : void {
70
+ super . onAfterRender ( node )
71
+
72
+ this . loginButtonRef . instance . addEventListener ( "click" , ( ) => this . handleClick ( ) . catch ( e => console . error ( e ) ) )
73
+ this . downloadButtonRef . instance . addEventListener ( "click" , ( ) => this . handleDownloadClick ( ) )
74
+
75
+ AuthService . user . sub ( user => {
76
+ if ( user ) {
77
+ this . qrCodeRef . instance . src = ""
78
+ this . qrCodeRef . instance . style . display = "none"
79
+ this . loginButtonRef . instance . textContent = "Log out"
80
+ this . textRef . instance . textContent = `Welcome, ${ user . preferred_username } `
81
+
82
+ this . handleLogin ( )
83
+ } else {
84
+ this . loginButtonRef . instance . textContent = "Sign in"
85
+ this . textRef . instance . textContent = "Not signed in"
86
+ }
87
+ } , true )
88
+ }
89
+
90
+ private async handleClick ( ) {
91
+ if ( AuthService . getUser ( ) ) {
92
+ await AuthService . signOut ( )
93
+ } else {
94
+ this . cancelSource = CancelToken . source ( ) // Reset any previous cancellations
95
+ AuthService . signIn ( p => {
96
+ if ( p ) {
97
+ this . qrCodeRef . instance . src = `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${ p . verification_uri_complete } `
98
+ this . qrCodeRef . instance . style . display = "block"
99
+ console . info ( p . verification_uri_complete )
100
+ }
101
+ } , this . cancelSource . token ) . catch ( e => console . error ( "Failed to sign in!" , e ) )
102
+ }
103
+ }
104
+
105
+ private handleLogin ( ) {
106
+ // Let's display all of our packages
107
+ packages
108
+ . listPackages ( )
109
+ . then ( pkgs => {
110
+ for ( const pkg of pkgs ) {
111
+ this . dropdownRef . instance . addDropdownItem ( pkg . format , pkg . format )
112
+ }
113
+ } )
114
+ . catch ( e => console . error ( e ) )
115
+ }
116
+
117
+ private handleDownloadClick ( ) {
118
+ packages
119
+ . getPackage ( this . dropdownRef . instance . getNavdataFormat ( ) as string )
120
+ . then ( pkg => {
121
+ const url = pkg . file . url
122
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
123
+ this . commBusListener . call (
124
+ "COMM_BUS_WASM_CALLBACK" ,
125
+ "NAVIGRAPH_DownloadNavdata" ,
126
+ JSON . stringify ( {
127
+ url,
128
+ folder : pkg . format ,
129
+ } ) ,
130
+ )
131
+ this . navdataTextRef . instance . textContent = "Downloading navdata..."
132
+ } )
133
+ . catch ( e => console . error ( e ) )
134
+ }
135
+ }
0 commit comments