mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-07-22 04:31:41 +00:00
96 lines
3.7 KiB
Haskell
96 lines
3.7 KiB
Haskell
{-# LANGUAGE DuplicateRecordFields #-}
|
|
{-# LANGUAGE LambdaCase #-}
|
|
{-# LANGUAGE NamedFieldPuns #-}
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
{-# LANGUAGE ScopedTypeVariables #-}
|
|
|
|
module Simplex.Chat.Terminal.Notification (Notification (..), initializeNotifications) where
|
|
|
|
import Data.List (isInfixOf)
|
|
import Data.Maybe (isJust)
|
|
import qualified Data.Text as T
|
|
import Simplex.Messaging.Util (catchAll_)
|
|
import System.Directory (createDirectoryIfMissing, doesFileExist, findExecutable, getAppUserDataDirectory)
|
|
import System.FilePath (combine)
|
|
import System.Info (os)
|
|
import System.Process (callProcess)
|
|
|
|
data Notification = Notification {title :: T.Text, text :: T.Text}
|
|
|
|
initializeNotifications :: IO (Notification -> IO ())
|
|
initializeNotifications =
|
|
hideException <$> case os of
|
|
"darwin" -> pure macNotify
|
|
"mingw32" -> initWinNotify
|
|
"linux" ->
|
|
doesFileExist "/proc/sys/kernel/osrelease" >>= \case
|
|
False -> initLinuxNotify
|
|
True -> do
|
|
v <- readFile "/proc/sys/kernel/osrelease"
|
|
if "Microsoft" `isInfixOf` v || "WSL" `isInfixOf` v
|
|
then initWslNotify
|
|
else initLinuxNotify
|
|
_ -> pure noNotifications
|
|
|
|
noNotifications :: Notification -> IO ()
|
|
noNotifications _ = pure ()
|
|
|
|
hideException :: (a -> IO ()) -> (a -> IO ())
|
|
hideException f a = f a `catchAll_` pure ()
|
|
|
|
initLinuxNotify :: IO (Notification -> IO ())
|
|
initLinuxNotify = do
|
|
found <- isJust <$> findExecutable "notify-send"
|
|
pure $ if found then linuxNotify else noNotifications
|
|
|
|
linuxNotify :: Notification -> IO ()
|
|
linuxNotify Notification {title, text} =
|
|
callProcess "notify-send" [T.unpack title, T.unpack text]
|
|
|
|
macNotify :: Notification -> IO ()
|
|
macNotify Notification {title, text} =
|
|
callProcess "osascript" ["-e", "display notification \"" <> macEscape text <> "\" with title \"" <> macEscape title <> "\""]
|
|
|
|
macEscape :: T.Text -> String
|
|
macEscape = concatMap esc . T.unpack
|
|
where
|
|
esc '\\' = "\\\\"
|
|
esc '"' = "\\\""
|
|
esc c = [c]
|
|
|
|
initWslNotify :: IO (Notification -> IO ())
|
|
initWslNotify = wslNotify <$> savePowershellScript
|
|
|
|
wslNotify :: FilePath -> Notification -> IO ()
|
|
wslNotify path Notification {title, text} =
|
|
callProcess "powershell.exe" ["-File", path, T.unpack title, T.unpack text]
|
|
|
|
initWinNotify :: IO (Notification -> IO ())
|
|
initWinNotify = winNotify <$> savePowershellScript
|
|
|
|
winNotify :: FilePath -> Notification -> IO ()
|
|
winNotify path Notification {title, text} =
|
|
callProcess "powershell.exe" ["-File", path, T.unpack title, T.unpack text]
|
|
|
|
savePowershellScript :: IO FilePath
|
|
savePowershellScript = do
|
|
appDir <- getAppUserDataDirectory "simplex"
|
|
createDirectoryIfMissing False appDir
|
|
let psScript = combine appDir "win-toast-notify.ps1"
|
|
writeFile
|
|
psScript
|
|
"[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] > $null\n\
|
|
\$Template = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent([Windows.UI.Notifications.ToastTemplateType]::ToastText02)\n\
|
|
\$RawXml = [xml] $Template.GetXml()\n\
|
|
\($RawXml.toast.visual.binding.text|where {$_.id -eq \"1\"}).AppendChild($RawXml.CreateTextNode($args[0])) > $null\n\
|
|
\($RawXml.toast.visual.binding.text|where {$_.id -eq \"2\"}).AppendChild($RawXml.CreateTextNode($args[1])) > $null\n\
|
|
\$SerializedXml = New-Object Windows.Data.Xml.Dom.XmlDocument\n\
|
|
\$SerializedXml.LoadXml($RawXml.OuterXml)\n\
|
|
\$Toast = [Windows.UI.Notifications.ToastNotification]::new($SerializedXml)\n\
|
|
\$Toast.Tag = \"simplex-chat\"\n\
|
|
\$Toast.Group = \"simplex-chat\"\n\
|
|
\$Toast.ExpirationTime = [DateTimeOffset]::Now.AddMinutes(1)\n\
|
|
\$Notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier(\"PowerShell\")\n\
|
|
\$Notifier.Show($Toast);\n"
|
|
return psScript
|