2025-08-12 17:05:52 +03:00
import { useEffect , useMemo , useState } from "preact/hooks" ;
2025-08-12 15:57:29 +03:00
import Button from "../react/Button" ;
import Modal from "../react/Modal" ;
import ReactBasicWidget from "../react/ReactBasicWidget" ;
2025-08-12 17:05:52 +03:00
import options from "../../services/options" ;
2025-08-12 17:48:44 +03:00
import { OptionNames } from "@triliumnext/commons" ;
import utils from "../../services/utils" ;
2025-08-12 15:57:29 +03:00
interface CallToAction {
title : string ;
message : string ;
2025-08-12 17:05:52 +03:00
enabled : ( ) = > boolean ;
2025-08-12 15:57:29 +03:00
buttons : {
text : string ;
2025-08-12 17:48:44 +03:00
onClick : ( ) = > ( void | Promise < void > ) ;
2025-08-12 15:57:29 +03:00
} [ ] ;
}
2025-08-12 17:05:52 +03:00
function isNextTheme() {
return [ "next" , "next-light" , "next-dark" ] . includes ( options . get ( "theme" ) ) ;
}
2025-08-12 16:35:27 +03:00
const CALL_TO_ACTIONS : CallToAction [ ] = [
{
2025-08-12 17:05:52 +03:00
title : "TriliumNext theme is now stable" ,
message : "For a while now, we've been working on a new theme to give the application a more modern look." ,
2025-08-12 17:42:18 +03:00
enabled : ( ) = > ! isNextTheme ( ) ,
2025-08-12 15:57:29 +03:00
buttons : [
2025-08-12 17:48:44 +03:00
{
text : "Switch to the TriliumNext theme" ,
async onClick() {
await options . save ( "theme" , "next" ) ;
await options . save ( "backgroundEffects" , "true" ) ;
utils . reloadFrontendApp ( "call-to-action" ) ;
}
}
2025-08-12 15:57:29 +03:00
]
2025-08-12 16:35:27 +03:00
} ,
{
2025-08-12 17:05:52 +03:00
title : "Background effects are now stable" ,
message : "On Windows devices, background effects are now fully stable. The background effects adds a touch of color to the user interface by blurring the background behind it. This technique is also used in other applications such as Windows Explorer." ,
2025-08-12 17:48:44 +03:00
enabled : ( ) = > isNextTheme ( ) && ! options . is ( "backgroundEffects" ) ,
2025-08-12 16:35:27 +03:00
buttons : [
2025-08-12 17:48:44 +03:00
{
text : "Enable background effects" ,
async onClick() {
await options . save ( "backgroundEffects" , "true" ) ;
utils . restartDesktopApp ( ) ;
}
}
2025-08-12 16:35:27 +03:00
]
}
] ;
2025-08-12 17:05:52 +03:00
function CallToActionDialogComponent ( { activeCallToActions } : { activeCallToActions : CallToAction [ ] } ) {
2025-08-12 16:35:27 +03:00
const [ activeIndex , setActiveIndex ] = useState ( 0 ) ;
const [ shown , setShown ] = useState ( true ) ;
2025-08-12 17:05:52 +03:00
const activeItem = activeCallToActions [ activeIndex ] ;
2025-08-12 16:35:27 +03:00
2025-08-12 17:42:18 +03:00
if ( ! activeCallToActions . length ) {
return < > < / > ;
}
2025-08-12 16:35:27 +03:00
function goToNext() {
2025-08-12 17:05:52 +03:00
if ( activeIndex + 1 < activeCallToActions . length ) {
2025-08-12 16:35:27 +03:00
setActiveIndex ( activeIndex + 1 ) ;
} else {
setShown ( false ) ;
}
}
2025-08-12 15:57:29 +03:00
return (
< Modal
2025-08-12 17:48:44 +03:00
className = "call-to-action"
size = "md"
2025-08-12 15:57:29 +03:00
title = "New features"
2025-08-12 16:35:27 +03:00
show = { shown }
2025-08-12 17:48:44 +03:00
onHidden = { ( ) = > setShown ( false ) }
2025-08-12 16:35:27 +03:00
footerAlignment = "between"
footer = { < >
< Button text = "Dismiss" onClick = { goToNext } / >
{ activeItem . buttons . map ( ( button ) = >
2025-08-12 17:48:44 +03:00
< Button text = { button . text } onClick = { async ( ) = > {
await button . onClick ( ) ;
2025-08-12 16:35:27 +03:00
goToNext ( ) ;
} } / >
) }
< / > }
2025-08-12 15:57:29 +03:00
>
2025-08-12 16:35:27 +03:00
< h4 > { activeItem . title } < / h4 >
< p > { activeItem . message } < / p >
2025-08-12 15:57:29 +03:00
< / Modal >
)
}
export class CallToActionDialog extends ReactBasicWidget {
get component() {
2025-08-12 17:05:52 +03:00
const filteredCallToActions = CALL_TO_ACTIONS . filter ( ( callToAction ) = > callToAction . enabled ( ) ) ;
return < CallToActionDialogComponent activeCallToActions = { filteredCallToActions } / >
2025-08-12 15:57:29 +03:00
}
}