2022-06-01 17:51:17 -04:00
import { FC , ReactNode } from 'react' ;
2022-10-24 20:33:40 -04:00
2022-10-23 20:22:00 -04:00
import { findSP } from '../utils' ;
2022-11-04 21:46:22 -04:00
import { findModule , findModuleChild } from '../webpack' ;
2022-05-10 23:38:10 +02:00
2022-09-24 20:49:23 +03:00
// All of the popout options + strTitle are related. Proper usage is not yet known...
export interface ShowModalProps {
browserContext? : unknown ; // This is another Deck Object that is yet to be found
bForcePopOut? : boolean ;
bHideActionIcons? : boolean ;
bHideMainWindowForPopouts? : boolean ;
bNeverPopOut? : boolean ;
fnOnClose ? : ( ) = > void ; // Seems to be the same as "closeModal" callback, but only when the modal is a popout. Will no longer work after "Update" invocation!
popupHeight? : number ;
popupWidth? : number ;
promiseRenderComplete? : Promise < void > ; // Invoked once the render is complete. Currently, it seems to be used as image loading success/error callback...
strTitle? : string ;
}
export interface ShowModalResult {
// This method will not invoke any of the variations of "closeModal" callbacks!
Close : ( ) = > void ;
// This method will replace the modal element completely and will not update the callback chains,
2022-10-24 20:33:40 -04:00
// meaning that "closeModal" and etc. will not automatically close the modal anymore (also "fnOnClose"
// will not be even called upon close anymore)! You have to manually call the "Close" method when, for example,
// the "closeModal" is invoked in the newly updated modal:
2022-09-24 20:49:23 +03:00
// <ModalRoot closeModal={() => { console.log("ABOUT TO CLOSE"); showModalRes.Close(); }} />
Update : ( modal : ReactNode ) = > void ;
}
2022-11-04 21:46:22 -04:00
const showModalRaw :
| ( (
modal : ReactNode ,
parent? : EventTarget ,
title? : string ,
props? : ShowModalProps ,
unknown1? : unknown ,
hideActions ? : { bHideActions? : boolean } ,
modalManager? : unknown ,
) = > Promise < ShowModalResult > )
| void = findModuleChild ( ( m ) = > {
if ( typeof m !== 'object' ) return undefined ;
for ( let prop in m ) {
if (
typeof m [ prop ] === 'function' &&
m [ prop ] . toString ( ) . includes ( 'props.bDisableBackgroundDismiss' ) &&
! m [ prop ] ? . prototype ? . Cancel
) {
return m [ prop ] ;
2022-05-10 23:38:10 +02:00
}
2022-11-04 21:46:22 -04:00
}
} ) ;
const oldShowModalRaw :
| ( ( modal : ReactNode , parent? : EventTarget , props? : ShowModalProps ) = > Promise < ShowModalResult > )
| void = findModuleChild ( ( m ) = > {
if ( typeof m !== 'object' ) return undefined ;
for ( let prop in m ) {
if ( typeof m [ prop ] === 'function' && m [ prop ] . toString ( ) . includes ( 'bHideMainWindowForPopouts:!0' ) ) {
return m [ prop ] ;
}
}
} ) ;
2022-06-01 17:51:17 -04:00
2022-11-04 21:46:22 -04:00
export const showModal = (
modal : ReactNode ,
parent? : EventTarget ,
props : ShowModalProps = {
strTitle : 'Decky Dialog' ,
bHideMainWindowForPopouts : false ,
} ,
) : Promise < ShowModalResult > = > {
if ( showModalRaw ) {
return showModalRaw ( modal , parent || findSP ( ) , props . strTitle , props , undefined , {
bHideActions : props.bHideActionIcons ,
} ) ;
} else if ( oldShowModalRaw ) {
return oldShowModalRaw ( modal , parent || findSP ( ) , props ) ;
} else {
throw new Error ( '[DFL:Modals]: Cannot find showModal function' ) ;
}
2022-10-24 20:33:40 -04:00
} ;
2022-10-23 20:22:00 -04:00
2022-06-05 15:07:47 +02:00
export interface ModalRootProps {
2022-10-02 15:36:00 +03:00
children? : ReactNode ;
2022-06-01 17:51:17 -04:00
onCancel ? ( ) : void ;
2022-09-09 16:17:44 -04:00
closeModal ? ( ) : void ;
2022-06-01 17:51:17 -04:00
onOK ? ( ) : void ;
2022-07-25 15:29:38 -04:00
onEscKeypress ? ( ) : void ;
className? : string ;
modalClassName? : string ;
2022-06-01 17:51:17 -04:00
bAllowFullSize? : boolean ;
2022-07-25 15:29:38 -04:00
bDestructiveWarning? : boolean ;
bDisableBackgroundDismiss? : boolean ;
bHideCloseIcon? : boolean ;
2022-07-25 15:33:35 -04:00
bOKDisabled? : boolean ;
2022-09-29 19:34:00 +03:00
bCancelDisabled? : boolean ;
2022-06-01 17:51:17 -04:00
}
2022-09-09 16:17:44 -04:00
export interface ConfirmModalProps extends ModalRootProps {
2022-09-29 19:34:00 +03:00
onMiddleButton ? ( ) : void ; // setting this prop will enable the middle button
strTitle? : ReactNode ;
strDescription? : ReactNode ;
strOKButtonText? : ReactNode ;
strCancelButtonText? : ReactNode ;
strMiddleButtonText? : ReactNode ;
bAlertDialog? : boolean ; // This will open a modal with only OK button enabled
bMiddleDisabled? : boolean ;
2022-09-09 16:17:44 -04:00
}
export const ConfirmModal = findModuleChild ( ( m ) = > {
2022-06-05 15:07:47 +02:00
if ( typeof m !== 'object' ) return undefined ;
2022-06-01 17:51:17 -04:00
for ( let prop in m ) {
if ( ! m [ prop ] ? . prototype ? . OK && m [ prop ] ? . prototype ? . Cancel && m [ prop ] ? . prototype ? . render ) {
return m [ prop ] ;
}
}
2022-09-09 16:17:44 -04:00
} ) as FC < ConfirmModalProps > ;
2022-11-04 21:46:22 -04:00
// new
export const ModalRoot = ( Object . values (
findModule ( ( m : any ) = > {
if ( typeof m !== 'object' ) return false ;
for ( let prop in m ) {
if ( m [ prop ] ? . toString ( ) ? . includes ( '"ModalManager","DialogWrapper"' ) ) {
return true ;
}
2022-09-09 16:17:44 -04:00
}
2022-11-04 21:46:22 -04:00
return false ;
} ) || { } ,
) ? . find ( ( x : any ) = > x ? . type ? . toString ( ) ? . includes ( '((function(){' ) ) ||
// old
findModuleChild ( ( m ) = > {
if ( typeof m !== 'object' ) return undefined ;
for ( let prop in m ) {
if ( m [ prop ] ? . prototype ? . OK && m [ prop ] ? . prototype ? . Cancel && m [ prop ] ? . prototype ? . render ) {
return m [ prop ] ;
}
}
} ) ) as FC < ModalRootProps > ;