@@ -19,20 +19,22 @@ import toast from 'components/toast/toast';
1919import dialogHelper from 'components/dialogHelper/dialogHelper' ;
2020import baseAlert from 'components/alert' ;
2121import { getDefaultBackgroundClass } from 'components/cardbuilder/utils/builder' ;
22+ import type { ApiClient } from 'jellyfin-apiclient' ;
23+ import type { BrandingOptionsDto , UserDto } from '@jellyfin/sdk/lib/generated-client' ;
2224
2325import './login.scss' ;
2426
2527const enableFocusTransform = ! browser . slow && ! browser . edge ;
2628
27- function authenticateUserByName ( page , apiClient , url , username , password ) {
29+ function authenticateUserByName ( page : HTMLElement , apiClient : ApiClient , url : string , username : string , password : string ) {
2830 loading . show ( ) ;
2931 apiClient . authenticateUserByName ( username , password ) . then ( function ( result ) {
30- const user = result . User ;
32+ const user = result . User as UserDto ;
3133 loading . hide ( ) ;
3234
3335 onLoginSuccessful ( user . Id , result . AccessToken , apiClient , url ) ;
3436 } , function ( response ) {
35- page . querySelector ( '#txtManualPassword' ) . value = '' ;
37+ ( page . querySelector ( '#txtManualPassword' ) as HTMLInputElement ) . value = '' ;
3638 loading . hide ( ) ;
3739
3840 const UnauthorizedOrForbidden = [ 401 , 403 ] ;
@@ -48,15 +50,17 @@ function authenticateUserByName(page, apiClient, url, username, password) {
4850 } ) ;
4951}
5052
51- function authenticateQuickConnect ( apiClient , targetUrl ) {
53+ function authenticateQuickConnect ( apiClient : ApiClient , targetUrl : string ) {
5254 const url = apiClient . getUrl ( '/QuickConnect/Initiate' ) ;
55+ // @ts -expect-error: The signature of ajax has just one argument. TODO: This should be investigated
5356 apiClient . ajax ( { type : 'POST' , url } , true ) . then ( res => res . json ( ) ) . then ( function ( json ) {
5457 if ( ! json . Secret || ! json . Code ) {
5558 console . error ( 'Malformed quick connect response' , json ) ;
5659 return false ;
5760 }
5861
59- baseAlert ( {
62+ // Should we be awaiting this promise?
63+ void baseAlert ( {
6064 dialogOptions : {
6165 id : 'quickConnectAlert'
6266 } ,
@@ -81,7 +85,7 @@ function authenticateQuickConnect(apiClient, targetUrl) {
8185 }
8286
8387 const result = await apiClient . quickConnect ( data . Secret ) ;
84- onLoginSuccessful ( result . User . Id , result . AccessToken , apiClient , targetUrl ) ;
88+ onLoginSuccessful ( ( result . User as UserDto ) . Id , result . AccessToken , apiClient , targetUrl ) ;
8589 } , function ( e ) {
8690 clearInterval ( interval ) ;
8791
@@ -112,31 +116,32 @@ function authenticateQuickConnect(apiClient, targetUrl) {
112116 } ) ;
113117}
114118
115- function onLoginSuccessful ( id , accessToken , apiClient , url ) {
119+ function onLoginSuccessful ( id : string | null | undefined , accessToken : string | null | undefined , apiClient : ApiClient , url : string ) {
116120 Dashboard . onServerChanged ( id , accessToken , apiClient ) ;
117- Dashboard . navigate ( url || 'home' ) ;
121+ // Should we be handling the promise from navigate?
122+ void Dashboard . navigate ( url || 'home' ) ;
118123}
119124
120- function showManualForm ( context , showCancel , focusPassword ) {
121- context . querySelector ( '.chkRememberLogin' ) . checked = appSettings . enableAutoLogin ( ) ;
122- context . querySelector ( '.manualLoginForm' ) . classList . remove ( 'hide' ) ;
123- context . querySelector ( '.visualLoginForm' ) . classList . add ( 'hide' ) ;
124- context . querySelector ( '.btnManual' ) . classList . add ( 'hide' ) ;
125+ function showManualForm ( context : HTMLElement , showCancel : boolean , focusPassword ?: boolean ) {
126+ ( context . querySelector ( '.chkRememberLogin' ) as HTMLInputElement ) . checked = appSettings . enableAutoLogin ( ) ;
127+ ( context . querySelector ( '.manualLoginForm' ) as Element ) . classList . remove ( 'hide' ) ;
128+ ( context . querySelector ( '.visualLoginForm' ) as Element ) . classList . add ( 'hide' ) ;
129+ ( context . querySelector ( '.btnManual' ) as Element ) . classList . add ( 'hide' ) ;
125130
126131 if ( focusPassword ) {
127- context . querySelector ( '#txtManualPassword' ) . focus ( ) ;
132+ ( context . querySelector ( '#txtManualPassword' ) as HTMLInputElement ) . focus ( ) ;
128133 } else {
129- context . querySelector ( '#txtManualName' ) . focus ( ) ;
134+ ( context . querySelector ( '#txtManualName' ) as HTMLElement ) . focus ( ) ;
130135 }
131136
132137 if ( showCancel ) {
133- context . querySelector ( '.btnCancel' ) . classList . remove ( 'hide' ) ;
138+ ( context . querySelector ( '.btnCancel' ) as Element ) . classList . remove ( 'hide' ) ;
134139 } else {
135- context . querySelector ( '.btnCancel' ) . classList . add ( 'hide' ) ;
140+ ( context . querySelector ( '.btnCancel' ) as Element ) . classList . add ( 'hide' ) ;
136141 }
137142}
138143
139- function loadUserList ( context , apiClient , users ) {
144+ function loadUserList ( context : HTMLElement , apiClient : ApiClient , users : UserDto [ ] ) {
140145 let html = '' ;
141146
142147 for ( const user of users ) {
@@ -160,7 +165,7 @@ function loadUserList(context, apiClient, users) {
160165 let imgUrl ;
161166
162167 if ( user . PrimaryImageTag ) {
163- imgUrl = apiClient . getUserImageUrl ( user . Id , {
168+ imgUrl = apiClient . getUserImageUrl ( user . Id as string , {
164169 width : 300 ,
165170 tag : user . PrimaryImageTag ,
166171 type : 'Primary'
@@ -182,17 +187,19 @@ function loadUserList(context, apiClient, users) {
182187 html += '</button>' ;
183188 }
184189
185- context . querySelector ( '#divUsers' ) . innerHTML = html ;
190+ ( context . querySelector ( '#divUsers' ) as Element ) . innerHTML = html ;
186191}
187192
188- export default function ( view , params ) {
189- function getApiClient ( ) {
193+ export default function ( view : HTMLElement , params : Record < string , string > ) {
194+ function getApiClient ( ) : ApiClient {
190195 const serverId = params . serverid ;
191196
192197 if ( serverId ) {
193198 return ServerConnections . getOrCreateApiClient ( serverId ) ;
194199 }
195200
201+ // TODO: This should be investigated
202+ // @ts -expect-error: It appears we're returning a type definition here instead of an instance of the object, but this code works, so it's not as it seems
196203 return ApiClient ;
197204 }
198205
@@ -209,56 +216,57 @@ export default function (view, params) {
209216 }
210217
211218 function showVisualForm ( ) {
212- view . querySelector ( '.visualLoginForm' ) . classList . remove ( 'hide' ) ;
213- view . querySelector ( '.manualLoginForm' ) . classList . add ( 'hide' ) ;
214- view . querySelector ( '.btnManual' ) . classList . remove ( 'hide' ) ;
219+ ( view . querySelector ( '.visualLoginForm' ) as Element ) . classList . remove ( 'hide' ) ;
220+ ( view . querySelector ( '.manualLoginForm' ) as Element ) . classList . add ( 'hide' ) ;
221+ ( view . querySelector ( '.btnManual' ) as Element ) . classList . remove ( 'hide' ) ;
215222
216- import ( 'components/autoFocuser' ) . then ( ( { default : autoFocuser } ) => {
223+ // Should we be handling this promise?
224+ void import ( 'components/autoFocuser' ) . then ( ( { default : autoFocuser } ) => {
217225 autoFocuser . autoFocus ( view ) ;
218226 } ) ;
219227 }
220228
221- view . querySelector ( '#divUsers' ) . addEventListener ( 'click' , function ( e ) {
222- const card = dom . parentWithClass ( e . target , 'card' ) ;
229+ ( view . querySelector ( '#divUsers' ) as Element ) . addEventListener ( 'click' , function ( e ) {
230+ const card = dom . parentWithClass ( e . target as HTMLElement , 'card' ) ;
223231 const cardContent = card ? card . querySelector ( '.cardContent' ) : null ;
224232
225233 if ( cardContent ) {
226234 const context = view ;
227235 const id = cardContent . getAttribute ( 'data-userid' ) ;
228- const name = cardContent . getAttribute ( 'data-username' ) ;
236+ const name = cardContent . getAttribute ( 'data-username' ) as string ;
229237 const haspw = cardContent . getAttribute ( 'data-haspw' ) ;
230238
231239 if ( id === 'manual' ) {
232- context . querySelector ( '#txtManualName' ) . value = '' ;
240+ ( context . querySelector ( '#txtManualName' ) as HTMLInputElement ) . value = '' ;
233241 showManualForm ( context , true ) ;
234242 } else if ( haspw == 'false' ) {
235243 authenticateUserByName ( context , getApiClient ( ) , getTargetUrl ( ) , name , '' ) ;
236244 } else {
237- context . querySelector ( '#txtManualName' ) . value = name ;
238- context . querySelector ( '#txtManualPassword' ) . value = '' ;
245+ ( context . querySelector ( '#txtManualName' ) as HTMLInputElement ) . value = name ;
246+ ( context . querySelector ( '#txtManualPassword' ) as HTMLInputElement ) . value = '' ;
239247 showManualForm ( context , true , true ) ;
240248 }
241249 }
242250 } ) ;
243- view . querySelector ( '.manualLoginForm' ) . addEventListener ( 'submit' , function ( e ) {
244- appSettings . enableAutoLogin ( view . querySelector ( '.chkRememberLogin' ) . checked ) ;
245- authenticateUserByName ( view , getApiClient ( ) , getTargetUrl ( ) , view . querySelector ( '#txtManualName' ) . value , view . querySelector ( '#txtManualPassword' ) . value ) ;
251+ ( view . querySelector ( '.manualLoginForm' ) as Element ) . addEventListener ( 'submit' , function ( e ) {
252+ appSettings . enableAutoLogin ( ( view . querySelector ( '.chkRememberLogin' ) as HTMLInputElement ) . checked ) ;
253+ authenticateUserByName ( view , getApiClient ( ) , getTargetUrl ( ) , ( view . querySelector ( '#txtManualName' ) as HTMLInputElement ) . value , ( view . querySelector ( '#txtManualPassword' ) as HTMLInputElement ) . value ) ;
246254 e . preventDefault ( ) ;
247255 return false ;
248256 } ) ;
249- view . querySelector ( '.btnForgotPassword' ) . addEventListener ( 'click' , function ( ) {
250- Dashboard . navigate ( 'forgotpassword' ) ;
257+ ( view . querySelector ( '.btnForgotPassword' ) as Element ) . addEventListener ( 'click' , function ( ) {
258+ void Dashboard . navigate ( 'forgotpassword' ) ;
251259 } ) ;
252- view . querySelector ( '.btnCancel' ) . addEventListener ( 'click' , showVisualForm ) ;
253- view . querySelector ( '.btnQuick' ) . addEventListener ( 'click' , function ( ) {
260+ ( view . querySelector ( '.btnCancel' ) as Element ) . addEventListener ( 'click' , showVisualForm ) ;
261+ ( view . querySelector ( '.btnQuick' ) as Element ) . addEventListener ( 'click' , function ( ) {
254262 authenticateQuickConnect ( getApiClient ( ) , getTargetUrl ( ) ) ;
255263 return false ;
256264 } ) ;
257- view . querySelector ( '.btnManual' ) . addEventListener ( 'click' , function ( ) {
258- view . querySelector ( '#txtManualName' ) . value = '' ;
265+ ( view . querySelector ( '.btnManual' ) as Element ) . addEventListener ( 'click' , function ( ) {
266+ ( view . querySelector ( '#txtManualName' ) as HTMLInputElement ) . value = '' ;
259267 showManualForm ( view , true ) ;
260268 } ) ;
261- view . querySelector ( '.btnSelectServer' ) . addEventListener ( 'click' , function ( ) {
269+ ( view . querySelector ( '.btnSelectServer' ) as Element ) . addEventListener ( 'click' , function ( ) {
262270 Dashboard . selectServer ( ) ;
263271 } ) ;
264272
@@ -267,34 +275,36 @@ export default function (view, params) {
267275 libraryMenu . setTransparentMenu ( true ) ;
268276
269277 if ( ! appHost . supports ( AppFeature . MultiServer ) ) {
270- view . querySelector ( '.btnSelectServer' ) . classList . add ( 'hide' ) ;
278+ ( view . querySelector ( '.btnSelectServer' ) as Element ) . classList . add ( 'hide' ) ;
271279 }
272280
273281 const apiClient = getApiClient ( ) ;
274282
275283 apiClient . getQuickConnect ( 'Enabled' )
276284 . then ( enabled => {
277285 if ( enabled === true ) {
278- view . querySelector ( '.btnQuick' ) . classList . remove ( 'hide' ) ;
286+ ( view . querySelector ( '.btnQuick' ) as Element ) . classList . remove ( 'hide' ) ;
279287 }
280288 } )
281289 . catch ( ( ) => {
282290 console . debug ( 'Failed to get QuickConnect status' ) ;
283291 } ) ;
284292
285- apiClient . getPublicUsers ( ) . then ( function ( users ) {
293+ // Should we be awaiting this promise?
294+ void apiClient . getPublicUsers ( ) . then ( function ( users ) {
286295 if ( users . length ) {
287296 showVisualForm ( ) ;
288297 loadUserList ( view , apiClient , users ) ;
289298 } else {
290- view . querySelector ( '#txtManualName' ) . value = '' ;
299+ ( view . querySelector ( '#txtManualName' ) as HTMLInputElement ) . value = '' ;
291300 showManualForm ( view , false , false ) ;
292301 }
293302 } ) . catch ( ) . then ( function ( ) {
294303 loading . hide ( ) ;
295304 } ) ;
296- apiClient . getJSON ( apiClient . getUrl ( 'Branding/Configuration' ) ) . then ( function ( options ) {
297- const loginDisclaimer = view . querySelector ( '.loginDisclaimer' ) ;
305+ // Should this promise be awaited?
306+ void apiClient . getJSON ( apiClient . getUrl ( 'Branding/Configuration' ) ) . then ( function ( options : BrandingOptionsDto ) {
307+ const loginDisclaimer = ( view . querySelector ( '.loginDisclaimer' ) as Element ) ;
298308
299309 // eslint-disable-next-line sonarjs/disabled-auto-escaping
300310 loginDisclaimer . innerHTML = DOMPurify . sanitize ( markdownIt ( { html : true } ) . render ( options . LoginDisclaimer || '' ) ) ;
0 commit comments