{-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE FlexibleContexts #-} module Simplex.Chat.Files where import Simplex.Chat.Controller import Simplex.Messaging.Util (ifM) import System.FilePath (combine, splitExtensions) import UnliftIO.Directory (doesDirectoryExist, doesFileExist, getHomeDirectory, getTemporaryDirectory) uniqueCombine :: FilePath -> String -> IO FilePath uniqueCombine :: FilePath -> FilePath -> IO FilePath uniqueCombine FilePath fPath FilePath fName = Int -> IO FilePath forall {m :: * -> *} {a}. (MonadIO m, Eq a, Num a, Show a) => a -> m FilePath tryCombine (Int 0 :: Int) where tryCombine :: a -> m FilePath tryCombine a n = let (FilePath name, FilePath ext) = FilePath -> (FilePath, FilePath) splitExtensions FilePath fName suffix :: FilePath suffix = if a n a -> a -> Bool forall a. Eq a => a -> a -> Bool == a 0 then FilePath "" else FilePath "_" FilePath -> FilePath -> FilePath forall a. Semigroup a => a -> a -> a <> a -> FilePath forall a. Show a => a -> FilePath show a n f :: FilePath f = FilePath fPath FilePath -> FilePath -> FilePath `combine` (FilePath name FilePath -> FilePath -> FilePath forall a. Semigroup a => a -> a -> a <> FilePath suffix FilePath -> FilePath -> FilePath forall a. Semigroup a => a -> a -> a <> FilePath ext) in m Bool -> m FilePath -> m FilePath -> m FilePath forall (m :: * -> *) a. Monad m => m Bool -> m a -> m a -> m a ifM (FilePath -> m Bool forall (m :: * -> *). MonadIO m => FilePath -> m Bool doesFileExist FilePath f) (a -> m FilePath tryCombine (a -> m FilePath) -> a -> m FilePath forall a b. (a -> b) -> a -> b $ a n a -> a -> a forall a. Num a => a -> a -> a + a 1) (FilePath -> m FilePath forall a. a -> m a forall (f :: * -> *) a. Applicative f => a -> f a pure FilePath f) getChatTempDirectory :: CM' FilePath getChatTempDirectory :: CM' FilePath getChatTempDirectory = (ChatController -> TVar (Maybe FilePath)) -> CM' (Maybe FilePath) forall a. (ChatController -> TVar a) -> CM' a chatReadVar' ChatController -> TVar (Maybe FilePath) tempDirectory CM' (Maybe FilePath) -> (Maybe FilePath -> CM' FilePath) -> CM' FilePath forall a b. ReaderT ChatController IO a -> (a -> ReaderT ChatController IO b) -> ReaderT ChatController IO b forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b >>= CM' FilePath -> (FilePath -> CM' FilePath) -> Maybe FilePath -> CM' FilePath forall b a. b -> (a -> b) -> Maybe a -> b maybe CM' FilePath forall (m :: * -> *). MonadIO m => m FilePath getTemporaryDirectory FilePath -> CM' FilePath forall a. a -> ReaderT ChatController IO a forall (f :: * -> *) a. Applicative f => a -> f a pure getDefaultFilesFolder :: CM' FilePath getDefaultFilesFolder :: CM' FilePath getDefaultFilesFolder = do FilePath dir <- (FilePath -> FilePath -> FilePath `combine` FilePath "Downloads") (FilePath -> FilePath) -> CM' FilePath -> CM' FilePath forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> CM' FilePath forall (m :: * -> *). MonadIO m => m FilePath getHomeDirectory ReaderT ChatController IO Bool -> CM' FilePath -> CM' FilePath -> CM' FilePath forall (m :: * -> *) a. Monad m => m Bool -> m a -> m a -> m a ifM (FilePath -> ReaderT ChatController IO Bool forall (m :: * -> *). MonadIO m => FilePath -> m Bool doesDirectoryExist FilePath dir) (FilePath -> CM' FilePath forall a. a -> ReaderT ChatController IO a forall (f :: * -> *) a. Applicative f => a -> f a pure FilePath dir) CM' FilePath getChatTempDirectory