@@ -24,7 +24,9 @@ define(function (require, exports, module) {
2424 DefaultDialogs = require ( "widgets/DefaultDialogs" ) ,
2525 Strings = require ( "strings" ) ,
2626 NativeApp = require ( "utils/NativeApp" ) ,
27- ProfileMenu = require ( "./profile-menu" ) ;
27+ ProfileMenu = require ( "./profile-menu" ) ,
28+ Mustache = require ( "thirdparty/mustache/mustache" ) ,
29+ otpDialogTemplate = require ( "text!./html/otp-dialog.html" ) ;
2830
2931 const KernalModeTrust = window . KernalModeTrust ;
3032 if ( ! KernalModeTrust ) {
@@ -42,6 +44,14 @@ define(function (require, exports, module) {
4244 // just used as trigger to notify different windows about user profile changes
4345 const PREF_USER_PROFILE_VERSION = "userProfileVersion" ;
4446
47+ EventDispatcher . makeEventDispatcher ( exports ) ;
48+ EventDispatcher . makeEventDispatcher ( secureExports ) ;
49+
50+ const _EVT_PAGE_FOCUSED = "page_focused" ;
51+ $ ( window ) . focus ( function ( ) {
52+ exports . trigger ( _EVT_PAGE_FOCUSED ) ;
53+ } ) ;
54+
4555
4656 function isLoggedIn ( ) {
4757 return isLoggedInUser ;
@@ -112,6 +122,7 @@ define(function (require, exports, module) {
112122 }
113123 // some error happened.
114124 if ( resolveResponse . err === ERR_INVALID ) { // the api key is invalid, we need to logout and tell user
125+ isLoggedInUser = false ;
115126 ProfileMenu . setNotLoggedIn ( ) ;
116127 Dialogs . showModalDialog (
117128 DefaultDialogs . DIALOG_ID_ERROR ,
@@ -166,8 +177,79 @@ define(function (require, exports, module) {
166177 }
167178 const { appSessionID, validationCode} = appAuthSession ;
168179 const appSignInURL = `${ Phoenix . config . account_url } authorizeApp?appSessionID=${ appSessionID } ` ;
169- // show a dialog here with the 6 letter validation code and a button to copy the validation code and another
170- // button to open the sign in code
180+
181+ // Show dialog with validation code
182+ const dialogData = {
183+ validationCode : validationCode ,
184+ Strings : Strings
185+ } ;
186+
187+ const $template = $ ( Mustache . render ( otpDialogTemplate , dialogData ) ) ;
188+ const dialog = Dialogs . showModalDialogUsingTemplate ( $template ) ;
189+
190+ // Set timeout to close dialog after 5 minutes, as validity is only 5 mins
191+ const closeTimeout = setTimeout ( ( ) => {
192+ dialog . close ( ) ;
193+ } , 5 * 60 * 1000 ) ;
194+
195+ // Handle button clicks
196+ $template . on ( 'click' , '[data-button-id="copy"]' , function ( ) {
197+ Phoenix . app . copyToClipboard ( validationCode ) ;
198+
199+ // Show "Copied" feedback
200+ const $validationCodeSpan = $template . find ( '.validation-code span' ) ;
201+ const originalText = $validationCodeSpan . text ( ) ;
202+
203+ // Replace validation code with "Copied" text
204+ $validationCodeSpan . text ( Strings . VALIDATION_CODE_COPIED ) ;
205+
206+ // Restore original validation code after 1.5 seconds
207+ setTimeout ( ( ) => {
208+ $validationCodeSpan . text ( originalText ) ;
209+ } , 1500 ) ;
210+ } ) ;
211+
212+ $template . on ( 'click' , '[data-button-id="open"]' , function ( ) {
213+ NativeApp . openURLInDefaultBrowser ( appSignInURL ) ;
214+ } ) ;
215+ $template . on ( 'click' , '[data-button-id="cancel"]' , function ( ) {
216+ dialog . close ( ) ;
217+ } ) ;
218+
219+ let checking = false , checkAgain = false ;
220+ async function checkLoginStatus ( ) {
221+ if ( checking ) {
222+ checkAgain = true ;
223+ return ;
224+ }
225+ checking = true ;
226+ try {
227+ const resolveResponse = await _resolveAPIKey ( appSessionID , validationCode ) ;
228+ if ( resolveResponse . userDetails ) {
229+ // the user has validated the creds
230+ userProfile = resolveResponse . userDetails ;
231+ ProfileMenu . setLoggedIn ( userProfile . profileIcon . initials , userProfile . profileIcon . color ) ;
232+ await KernalModeTrust . setCredential ( KernalModeTrust . CRED_KEY_API , JSON . stringify ( userProfile ) ) ;
233+ checkAgain = false ;
234+ isLoggedInUser = true ;
235+ dialog . close ( ) ;
236+ }
237+ } catch ( e ) {
238+ console . error ( "Failed to check login status." , e ) ;
239+ }
240+ checking = false ;
241+ if ( checkAgain ) {
242+ checkAgain = false ;
243+ setTimeout ( checkLoginStatus , 100 ) ;
244+ }
245+ }
246+ exports . on ( _EVT_PAGE_FOCUSED , checkLoginStatus ) ;
247+
248+ // Clean up when dialog is closed
249+ dialog . done ( function ( ) {
250+ exports . off ( _EVT_PAGE_FOCUSED , checkLoginStatus ) ;
251+ clearTimeout ( closeTimeout ) ;
252+ } ) ;
171253 NativeApp . openURLInDefaultBrowser ( appSignInURL ) ;
172254 }
173255
@@ -187,8 +269,6 @@ define(function (require, exports, module) {
187269
188270 // no sensitive apis or events should be triggered from the public exports of this module as extensions
189271 // can read them. Always use KernalModeTrust.loginService for sensitive apis.
190- EventDispatcher . makeEventDispatcher ( exports ) ;
191- EventDispatcher . makeEventDispatcher ( secureExports ) ;
192272
193273 // kernal exports
194274 secureExports . isLoggedIn = isLoggedIn ;
0 commit comments