From 587e0a18a96d299403a86cd890474928cf7a34e1 Mon Sep 17 00:00:00 2001 From: mervyn <6359152+reply2future@users.noreply.github.com> Date: Tue, 22 Oct 2024 22:10:01 +0800 Subject: [PATCH 1/2] feat(cli): add `display-name` option to cli --- src/Simplex/Chat/Core.hs | 30 ++++++++++++++++++------------ src/Simplex/Chat/Mobile.hs | 1 + src/Simplex/Chat/Options.hs | 10 ++++++++++ 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/Simplex/Chat/Core.hs b/src/Simplex/Chat/Core.hs index ad2f1367da..8e0d5ad33a 100644 --- a/src/Simplex/Chat/Core.hs +++ b/src/Simplex/Chat/Core.hs @@ -23,7 +23,7 @@ import Simplex.Chat import Simplex.Chat.Controller import Simplex.Chat.Options (ChatOpts (..), CoreChatOpts (..)) import Simplex.Chat.Store.Profiles -import Simplex.Chat.Types +import Simplex.Chat.Types (User (..), ContactName, Profile (..), NewUser (..), LocalProfile (..)) import Simplex.Chat.View (serializeChatResponse) import Simplex.Messaging.Agent.Store.SQLite (SQLiteStore, withTransaction) import System.Exit (exitFailure) @@ -32,7 +32,7 @@ import Text.Read (readMaybe) import UnliftIO.Async simplexChatCore :: ChatConfig -> ChatOpts -> (User -> ChatController -> IO ()) -> IO () -simplexChatCore cfg@ChatConfig {confirmMigrations, testView} opts@ChatOpts {coreOptions = CoreChatOpts {dbFilePrefix, dbKey, logAgent}} chat = +simplexChatCore cfg@ChatConfig {confirmMigrations, testView} opts@ChatOpts {coreOptions = CoreChatOpts {dbFilePrefix, dbKey, logAgent, displayName}} chat = case logAgent of Just level -> do setLogLevel level @@ -44,9 +44,9 @@ simplexChatCore cfg@ChatConfig {confirmMigrations, testView} opts@ChatOpts {core putStrLn $ "Error opening database: " <> show e exitFailure run db@ChatDatabase {chatStore} = do - u_ <- getSelectActiveUser chatStore + u_ <- getSelectActiveUser chatStore displayName cc <- newChatController db u_ cfg opts False - u <- maybe (createActiveUser cc) pure u_ + u <- maybe (createActiveUser cc displayName) pure u_ unless testView $ putStrLn $ "Current user: " <> userStr u runSimplexChat opts u cc chat @@ -64,12 +64,16 @@ sendChatCmdStr cc s = runReaderT (execChatCommand Nothing . encodeUtf8 $ T.pack sendChatCmd :: ChatController -> ChatCommand -> IO ChatResponse sendChatCmd cc cmd = runReaderT (execChatCommand' cmd) cc -getSelectActiveUser :: SQLiteStore -> IO (Maybe User) -getSelectActiveUser st = do +getSelectActiveUser :: SQLiteStore -> Maybe ContactName -> IO (Maybe User) +getSelectActiveUser st displayName = do users <- withTransaction st getUsers - case find activeUser users of - Just u -> pure $ Just u - Nothing -> selectUser users + case displayName of + Just name -> case find (\User {localDisplayName} -> localDisplayName == name) users of + Just u -> pure $ Just u + Nothing -> pure Nothing + Nothing -> case find activeUser users of + Just u -> pure $ Just u + Nothing -> selectUser users where selectUser :: [User] -> IO (Maybe User) selectUser = \case @@ -90,8 +94,8 @@ getSelectActiveUser st = do let user = users !! (n - 1) in Just <$> withTransaction st (`setActiveUser` user) -createActiveUser :: ChatController -> IO User -createActiveUser cc = do +createActiveUser :: ChatController -> Maybe ContactName -> IO User +createActiveUser cc name = do putStrLn "No user profiles found, it will be created now.\n\ \Please choose your display name.\n\ @@ -100,7 +104,9 @@ createActiveUser cc = do loop where loop = do - displayName <- T.pack <$> getWithPrompt "display name" + displayName <- case name of + Just n | not (T.null n) -> pure n + _ -> T.pack <$> getWithPrompt "display name" let profile = Just Profile {displayName, fullName = "", image = Nothing, contactLink = Nothing, preferences = Nothing} execChatCommand' (CreateActiveUser NewUser {profile, pastTimestamp = False}) `runReaderT` cc >>= \case CRActiveUser user -> pure user diff --git a/src/Simplex/Chat/Mobile.hs b/src/Simplex/Chat/Mobile.hs index 57b0ee6c17..9c01b8c2e6 100644 --- a/src/Simplex/Chat/Mobile.hs +++ b/src/Simplex/Chat/Mobile.hs @@ -189,6 +189,7 @@ mobileChatOpts dbFilePrefix = CoreChatOpts { dbFilePrefix, dbKey = "", -- for API database is already opened, and the key in options is not used + displayName = Nothing, smpServers = [], xftpServers = [], simpleNetCfg = defaultSimpleNetCfg, diff --git a/src/Simplex/Chat/Options.hs b/src/Simplex/Chat/Options.hs index 16ffe6e28f..d9e759a6e9 100644 --- a/src/Simplex/Chat/Options.hs +++ b/src/Simplex/Chat/Options.hs @@ -35,6 +35,7 @@ import Simplex.Messaging.Parsers (parseAll) import Simplex.Messaging.Protocol (ProtoServerWithAuth, ProtocolTypeI, SMPServerWithAuth, XFTPServerWithAuth) import Simplex.Messaging.Transport.Client (SocksProxyWithAuth (..), SocksAuth (..), defaultSocksProxyWithAuth) import System.FilePath (combine) +import Simplex.Chat.Types (ContactName) data ChatOpts = ChatOpts { coreOptions :: CoreChatOpts, @@ -56,6 +57,7 @@ data ChatOpts = ChatOpts data CoreChatOpts = CoreChatOpts { dbFilePrefix :: String, dbKey :: ScrubbedBytes, + displayName :: Maybe ContactName, smpServers :: [SMPServerWithAuth], xftpServers :: [XFTPServerWithAuth], simpleNetCfg :: SimpleNetCfg, @@ -99,6 +101,13 @@ coreChatOptsP appDir defaultDbFileName = do <> help "Database encryption key/pass-phrase" <> value "" ) + displayName <- + optional $ + strOption + ( long "display-name" + <> metavar "DISPLAY_NAME" + <> help "Display name will be sent to your contacts when you connect and only stored on your device and you can change it later." + ) smpServers <- option parseProtocolServers @@ -244,6 +253,7 @@ coreChatOptsP appDir defaultDbFileName = do CoreChatOpts { dbFilePrefix, dbKey, + displayName, smpServers, xftpServers, simpleNetCfg = From 2dc9c85cf222c16f6005c2f803c97967f07b3d80 Mon Sep 17 00:00:00 2001 From: mervyn <6359152+reply2future@users.noreply.github.com> Date: Fri, 1 Nov 2024 10:17:20 +0800 Subject: [PATCH 2/2] refactor(cli): move `display-name` option to `ChatOpts` in CLI --- .../src/Broadcast/Options.hs | 1 + .../src/Directory/Options.hs | 1 + src/Simplex/Chat/Core.hs | 2 +- src/Simplex/Chat/Mobile.hs | 2 +- src/Simplex/Chat/Options.hs | 18 +++++++++--------- tests/ChatClient.hs | 1 + tests/ChatTests/Profiles.hs | 6 +++--- 7 files changed, 17 insertions(+), 14 deletions(-) diff --git a/apps/simplex-broadcast-bot/src/Broadcast/Options.hs b/apps/simplex-broadcast-bot/src/Broadcast/Options.hs index 5bc4ffef25..932a6919d3 100644 --- a/apps/simplex-broadcast-bot/src/Broadcast/Options.hs +++ b/apps/simplex-broadcast-bot/src/Broadcast/Options.hs @@ -76,6 +76,7 @@ mkChatOpts BroadcastBotOpts {coreOptions} = ChatOpts { coreOptions, deviceName = Nothing, + displayName = Nothing, chatCmd = "", chatCmdDelay = 3, chatCmdLog = CCLNone, diff --git a/apps/simplex-directory-service/src/Directory/Options.hs b/apps/simplex-directory-service/src/Directory/Options.hs index 7f02a580e6..41e6402fcd 100644 --- a/apps/simplex-directory-service/src/Directory/Options.hs +++ b/apps/simplex-directory-service/src/Directory/Options.hs @@ -85,6 +85,7 @@ mkChatOpts DirectoryOpts {coreOptions} = ChatOpts { coreOptions, deviceName = Nothing, + displayName = Nothing, chatCmd = "", chatCmdDelay = 3, chatCmdLog = CCLNone, diff --git a/src/Simplex/Chat/Core.hs b/src/Simplex/Chat/Core.hs index 8e0d5ad33a..b3ee163c79 100644 --- a/src/Simplex/Chat/Core.hs +++ b/src/Simplex/Chat/Core.hs @@ -32,7 +32,7 @@ import Text.Read (readMaybe) import UnliftIO.Async simplexChatCore :: ChatConfig -> ChatOpts -> (User -> ChatController -> IO ()) -> IO () -simplexChatCore cfg@ChatConfig {confirmMigrations, testView} opts@ChatOpts {coreOptions = CoreChatOpts {dbFilePrefix, dbKey, logAgent, displayName}} chat = +simplexChatCore cfg@ChatConfig {confirmMigrations, testView} opts@ChatOpts {coreOptions = CoreChatOpts {dbFilePrefix, dbKey, logAgent}, displayName} chat = case logAgent of Just level -> do setLogLevel level diff --git a/src/Simplex/Chat/Mobile.hs b/src/Simplex/Chat/Mobile.hs index 9c01b8c2e6..68fffa0f7b 100644 --- a/src/Simplex/Chat/Mobile.hs +++ b/src/Simplex/Chat/Mobile.hs @@ -189,7 +189,6 @@ mobileChatOpts dbFilePrefix = CoreChatOpts { dbFilePrefix, dbKey = "", -- for API database is already opened, and the key in options is not used - displayName = Nothing, smpServers = [], xftpServers = [], simpleNetCfg = defaultSimpleNetCfg, @@ -203,6 +202,7 @@ mobileChatOpts dbFilePrefix = yesToUpMigrations = False }, deviceName = Nothing, + displayName = Nothing, chatCmd = "", chatCmdDelay = 3, chatCmdLog = CCLNone, diff --git a/src/Simplex/Chat/Options.hs b/src/Simplex/Chat/Options.hs index d9e759a6e9..c8e4c98ffb 100644 --- a/src/Simplex/Chat/Options.hs +++ b/src/Simplex/Chat/Options.hs @@ -40,6 +40,7 @@ import Simplex.Chat.Types (ContactName) data ChatOpts = ChatOpts { coreOptions :: CoreChatOpts, deviceName :: Maybe Text, + displayName :: Maybe ContactName, chatCmd :: String, chatCmdDelay :: Int, chatCmdLog :: ChatCmdLog, @@ -57,7 +58,6 @@ data ChatOpts = ChatOpts data CoreChatOpts = CoreChatOpts { dbFilePrefix :: String, dbKey :: ScrubbedBytes, - displayName :: Maybe ContactName, smpServers :: [SMPServerWithAuth], xftpServers :: [XFTPServerWithAuth], simpleNetCfg :: SimpleNetCfg, @@ -101,13 +101,6 @@ coreChatOptsP appDir defaultDbFileName = do <> help "Database encryption key/pass-phrase" <> value "" ) - displayName <- - optional $ - strOption - ( long "display-name" - <> metavar "DISPLAY_NAME" - <> help "Display name will be sent to your contacts when you connect and only stored on your device and you can change it later." - ) smpServers <- option parseProtocolServers @@ -253,7 +246,6 @@ coreChatOptsP appDir defaultDbFileName = do CoreChatOpts { dbFilePrefix, dbKey, - displayName, smpServers, xftpServers, simpleNetCfg = @@ -296,6 +288,13 @@ chatOptsP appDir defaultDbFileName = do <> metavar "DEVICE" <> help "Device name to use in connections with remote hosts and controller" ) + displayName <- + optional $ + strOption + ( long "display-name" + <> metavar "DISPLAY_NAME" + <> help "Display name will be sent to your contacts when you connect and only stored on your device and you can change it later." + ) chatCmd <- strOption ( long "execute" @@ -385,6 +384,7 @@ chatOptsP appDir defaultDbFileName = do pure ChatOpts { coreOptions, + displayName, deviceName, chatCmd, chatCmdDelay, diff --git a/tests/ChatClient.hs b/tests/ChatClient.hs index 73f3e350df..a462eff7b0 100644 --- a/tests/ChatClient.hs +++ b/tests/ChatClient.hs @@ -74,6 +74,7 @@ testOpts = ChatOpts { coreOptions = testCoreOpts, deviceName = Nothing, + displayName = Nothing, chatCmd = "", chatCmdDelay = 3, chatCmdLog = CCLNone, diff --git a/tests/ChatTests/Profiles.hs b/tests/ChatTests/Profiles.hs index 06ed9aa5bc..e14a2981f0 100644 --- a/tests/ChatTests/Profiles.hs +++ b/tests/ChatTests/Profiles.hs @@ -223,9 +223,9 @@ testMultiWordProfileNames = alice #> "@'Cath J' hi" cath <# "'Alice Jones'> hi" where - aliceProfile' = baseProfile {displayName = "Alice Jones"} - bobProfile' = baseProfile {displayName = "Bob James"} - cathProfile' = baseProfile {displayName = "Cath Johnson"} + aliceProfile' = (baseProfile :: Profile) {displayName = "Alice Jones"} + bobProfile' = (baseProfile :: Profile) {displayName = "Bob James"} + cathProfile' = (baseProfile :: Profile) {displayName = "Cath Johnson"} baseProfile = Profile {displayName = "", fullName = "", image = Nothing, contactLink = Nothing, preferences = defaultPrefs} testUserContactLink :: HasCallStack => FilePath -> IO ()