Merge branch 'master' into master-ghc8107

This commit is contained in:
Evgeny Poberezkin 2023-12-04 10:07:16 +00:00
commit 0b822e4a5c
16 changed files with 225 additions and 172 deletions

View File

@ -264,7 +264,7 @@ jobs:
# * And GitHub Actions does not support parameterizing shell in a matrix job - https://github.community/t/using-matrix-to-specify-shell-is-it-possible/17065 # * And GitHub Actions does not support parameterizing shell in a matrix job - https://github.community/t/using-matrix-to-specify-shell-is-it-possible/17065
- name: 'Setup MSYS2' - name: 'Setup MSYS2'
if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
uses: msys2/setup-msys2@v2 uses: msys2/setup-msys2@v2
with: with:
msystem: ucrt64 msystem: ucrt64

View File

@ -164,6 +164,12 @@ fun CIImageView(
} }
} }
} }
} else {
KeyChangeEffect(file) {
if (res.value == null) {
res.value = imageAndFilePath(file)
}
}
} }
val loaded = res.value val loaded = res.value
if (loaded != null) { if (loaded != null) {

View File

@ -83,5 +83,6 @@ mkChatOpts BroadcastBotOpts {coreOptions} =
allowInstantFiles = True, allowInstantFiles = True,
autoAcceptFileSize = 0, autoAcceptFileSize = 0,
muteNotifications = True, muteNotifications = True,
markRead = False,
maintenance = False maintenance = False
} }

View File

@ -5,10 +5,10 @@
{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ScopedTypeVariables #-}
module Directory.Options module Directory.Options
( DirectoryOpts (..), ( DirectoryOpts (..),
getDirectoryOpts, getDirectoryOpts,
mkChatOpts, mkChatOpts,
) )
where where
import Options.Applicative import Options.Applicative
@ -35,8 +35,8 @@ directoryOpts appDir defaultDbFileName = do
<> help "Comma-separated list of super-users in the format CONTACT_ID:DISPLAY_NAME who will be allowed to manage the directory" <> help "Comma-separated list of super-users in the format CONTACT_ID:DISPLAY_NAME who will be allowed to manage the directory"
) )
directoryLog <- directoryLog <-
Just <$> Just
strOption <$> strOption
( long "directory-file" ( long "directory-file"
<> metavar "DIRECTORY_FILE" <> metavar "DIRECTORY_FILE"
<> help "Append only log for directory state" <> help "Append only log for directory state"
@ -81,5 +81,6 @@ mkChatOpts DirectoryOpts {coreOptions} =
allowInstantFiles = True, allowInstantFiles = True,
autoAcceptFileSize = 0, autoAcceptFileSize = 0,
muteNotifications = True, muteNotifications = True,
markRead = False,
maintenance = False maintenance = False
} }

View File

@ -4,12 +4,14 @@ packages: .
with-compiler: ghc-8.10.7 with-compiler: ghc-8.10.7
index-state: 2023-10-20T00:00:00Z
constraints: zip +disable-bzip2 +disable-zstd constraints: zip +disable-bzip2 +disable-zstd
source-repository-package source-repository-package
type: git type: git
location: https://github.com/simplex-chat/simplexmq.git location: https://github.com/simplex-chat/simplexmq.git
tag: 117168ccce93ef5ac478c02e3f02a018fa8a2200 tag: eaf5317834b069144b5f4897f9c79831983e54dd
source-repository-package source-repository-package
type: git type: git
@ -45,3 +47,9 @@ source-repository-package
type: git type: git
location: https://github.com/simplex-chat/android-support.git location: https://github.com/simplex-chat/android-support.git
tag: 9aa09f148089d6752ce563b14c2df1895718d806 tag: 9aa09f148089d6752ce563b14c2df1895718d806
-- TODO this fork is only needed to compile with GHC 8.10.7 - it allows previous base version
source-repository-package
type: git
location: https://github.com/simplex-chat/zip.git
tag: bd421c6b19cc4c465cd7af1f6f26169fb8ee1ebc

View File

@ -45,6 +45,8 @@ When people connect to you via this address, you will receive a connection reque
If you start receiving too many requests via this address it is always safe to remove it all the connections you created via this address will remain active, as this address is not used to deliver the messages. If you start receiving too many requests via this address it is always safe to remove it all the connections you created via this address will remain active, as this address is not used to deliver the messages.
See the comparison with [1-time invitation links](./making-connections.md#comparison-of-1-time-invitation-links-and-simplex-contact-addresses).
Read more in [this post](../../blog/20221108-simplex-chat-v4.2-security-audit-new-website.md#auto-accept-contact-requests). Read more in [this post](../../blog/20221108-simplex-chat-v4.2-security-audit-new-website.md#auto-accept-contact-requests).
### Chat preferences ### Chat preferences

View File

@ -13,6 +13,71 @@ Private Connection — connect using an invitation link or QR code via video or
Group Chat — Users have the option to create a secret group, share their contact link [which can be deleted later on], or generate a one-time invitation link. Group Chat — Users have the option to create a secret group, share their contact link [which can be deleted later on], or generate a one-time invitation link.
## Your SimpleX contact address
You can [create an optional long term address](./app-settings.md#your-simplex-contact-address) for other people to connect with you. Unlike 1-time invitation links, these addresses can be used many times, that makes them good to share online, e.g. on social media platforms, or in email signatures. That helps more people discover SimpleX Chat, so please do it!
When people connect to you via this address, you will receive a connection request that you can accept or reject. You can configure an automatic acceptance of connection request and an automatic welcome message that will be sent to the new contacts. You can also share this address as part of your SimpleX profile, so group members can connect to you, and you contacts can share it with others - if this is something that you want.
If you start receiving too many requests via this address it is always safe to remove it all the connections you created via this address will remain active, as this address is not used to deliver the messages.
### Comparison of 1-time invitation links and SimpleX Contact addresses
<table>
<tr>
<th></th>
<th>1-time invitation link</th>
<th>SimpleX contact address</th>
</tr>
<tr>
<td>Can be used many times?</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>Can be included in user profile?</td>
<td>No, as it can only be used once.</td>
<td>Yes, to allow group members to connect directly, and your contacts to pass it on to their contacts.</td>
</tr>
<tr>
<td>When to use it?</td>
<td>With somebody you know, via another communication channel or QR code (in person or during a video call)</td>
<td>Where many people can see and connect via it, e.g. in email signature, website, social media or group chat.</td>
</tr>
<tr>
<td>Security</td>
<td>More secure, as can only be used once, and the initial connection request (including profile) is encrypted with double ratchet.</td>
<td>Initial connection request is also e2e encrypted, but without double ratchet (it is initialized when request is accepted).</td>
</tr>
<tr>
<td>Identification</td>
<td>Both sides know who they connect to, as they know with whom and by who the link was shared. You can attach alias to this invitation as soon as you share it or use it, to identify the other person when connection is established.</td>
<td>Only the person using the address knows who they connect to, via the channel where they found the address (email, social media, etc.). The address owner can only see the user profile of the request, and has no proof of identity from the person sending the request<sup>*</sup>.</td>
</tr>
<tr>
<td>Advantages over other platforms</td>
<td>There is no direct analogy, other platforms dont offer one-time invitations without any fixed part identifying the user.</td>
<td>Unlike addresses in other platforms, SimpleX addresses are not used to deliver the messages &mdash; only the initial connection requests.<br>It means that removing this address will not break the contacts made via it (like changing an email address would), it would only prevent new connections, which makes it a good solution against spam and abuse.</td>
</tr>
<tr>
<td>Vulnerability to attacks</td>
<td>Until the connection is established, anybody who intercepts this link can connect to it, so it has to be verified with the original contact that the connection succeeded.</td>
<td>These addresses are vulnerable to connection request spam. Unlike other platforms, you can delete or change the address, without losing any contacts (see above).</td>
</tr>
<tr>
<td>Passive attacks on connection links</td>
<td colspan="2">Both types of links are not vulnerable if simply observed &mdash; they only contain public keys. So they can be safely shared via insecure or public channels, as long as you can confirm that you connected to the intended person.</td>
</tr>
<tr>
<td>Active attacks on connection links</td>
<td colspan="2">If the link is substituted via the attack on the channel used to share it, the connection security can be compromised, and the original messages monitored (man-in-the-middle attack). If it is a real risk then security code should be verified to mitigate it - doing so proves<sup>**</sup> that the link and keys were not substituted, and that the end-to-end encryption is secure.</td>
</tr>
</table>
<sup>*</sup> Adding optional verified identities that we plan in the future will change it &mdash; the address owner will have an option to request identity verification before accepting the connection.
<sup>**</sup> Connection security code is the cryptographic hash (SHA256) of combined public keys of both sides &mdash; there are 2<sup>256</sup> possible security codes (1 with 77 zeros about [1000 times smaller](https://www.wolframalpha.com/input?i=2%5E256) than the estimated number of atoms in the visible universe).
## Conversation preferences ## Conversation preferences
Tap on one of your conversations to open conversation preferences. Tap on one of your conversations to open conversation preferences.

View File

@ -19,7 +19,6 @@ dependencies:
- attoparsec == 0.14.* - attoparsec == 0.14.*
- base >= 4.7 && < 5 - base >= 4.7 && < 5
- base64-bytestring >= 1.0 && < 1.3 - base64-bytestring >= 1.0 && < 1.3
- bytestring == 0.10.*
- composition == 1.0.* - composition == 1.0.*
- constraints >= 0.12 && < 0.14 - constraints >= 0.12 && < 0.14
- containers == 0.6.* - containers == 0.6.*
@ -32,10 +31,10 @@ dependencies:
- filepath == 1.4.* - filepath == 1.4.*
- http-types == 0.12.* - http-types == 0.12.*
- http2 >= 4.2.2 && < 4.3 - http2 >= 4.2.2 && < 4.3
- memory >= 0.15 && < 0.19 - memory == 0.18.*
- mtl >= 2.3.1 && < 3 - mtl >= 2.3.1 && < 3.0
- network >= 3.1.2.7 && < 3.2 - network >= 3.1.2.7 && < 3.2
- network-transport >= 0.5.6 && < 0.6 - network-transport == 0.5.6
- optparse-applicative >= 0.15 && < 0.17 - optparse-applicative >= 0.15 && < 0.17
- process == 1.6.* - process == 1.6.*
- random >= 1.1 && < 1.3 - random >= 1.1 && < 1.3
@ -45,14 +44,12 @@ dependencies:
- socks == 0.6.* - socks == 0.6.*
- sqlcipher-simple == 0.4.* - sqlcipher-simple == 0.4.*
- stm == 2.5.* - stm == 2.5.*
- template-haskell >= 2.16 && < 2.21
- terminal == 0.2.* - terminal == 0.2.*
- text >= 2.0 && < 3
- time == 1.9.* - time == 1.9.*
- tls >= 1.6.0 && < 1.7 - tls >= 1.6.0 && < 1.7
- unliftio == 0.2.* - unliftio == 0.2.*
- unliftio-core == 0.2.* - unliftio-core == 0.2.*
- zip >= 1.7 && < 2.1 - zip == 2.0.*
flags: flags:
swift: swift:
@ -64,6 +61,16 @@ when:
- condition: flag(swift) - condition: flag(swift)
cpp-options: cpp-options:
- -DswiftJSON - -DswiftJSON
- condition: impl(ghc >= 9.6.2)
dependencies:
- bytestring == 0.11.*
- template-haskell == 2.20.*
- text >= 2.0.1 && < 2.2
- condition: impl(ghc < 9.6.2)
dependencies:
- bytestring == 0.10.*
- template-haskell == 2.16.*
- text >= 1.2.3.0 && < 1.3
library: library:
source-dirs: src source-dirs: src

View File

@ -1,5 +1,5 @@
{ {
"https://github.com/simplex-chat/simplexmq.git"."117168ccce93ef5ac478c02e3f02a018fa8a2200" = "1091c4b8qjp9v29z862b7clda90w3kb4v2aqp5b2jh6yprlga98w"; "https://github.com/simplex-chat/simplexmq.git"."eaf5317834b069144b5f4897f9c79831983e54dd" = "0jlic1q08mq9p9sgvigmc59r6x1r5fa1zsfqvvrwd97pwain36mj";
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38";
"https://github.com/kazu-yamamoto/http2.git"."f5525b755ff2418e6e6ecc69e877363b0d0bcaeb" = "0fyx0047gvhm99ilp212mmz37j84cwrfnpmssib5dw363fyb88b6"; "https://github.com/kazu-yamamoto/http2.git"."f5525b755ff2418e6e6ecc69e877363b0d0bcaeb" = "0fyx0047gvhm99ilp212mmz37j84cwrfnpmssib5dw363fyb88b6";
"https://github.com/simplex-chat/direct-sqlcipher.git"."34309410eb2069b029b8fc1872deb1e0db123294" = "0kwkmhyfsn2lixdlgl15smgr1h5gjk7fky6abzh8rng2h5ymnffd"; "https://github.com/simplex-chat/direct-sqlcipher.git"."34309410eb2069b029b8fc1872deb1e0db123294" = "0kwkmhyfsn2lixdlgl15smgr1h5gjk7fky6abzh8rng2h5ymnffd";
@ -7,4 +7,5 @@
"https://github.com/simplex-chat/aeson.git"."aab7b5a14d6c5ea64c64dcaee418de1bb00dcc2b" = "0jz7kda8gai893vyvj96fy962ncv8dcsx71fbddyy8zrvc88jfrr"; "https://github.com/simplex-chat/aeson.git"."aab7b5a14d6c5ea64c64dcaee418de1bb00dcc2b" = "0jz7kda8gai893vyvj96fy962ncv8dcsx71fbddyy8zrvc88jfrr";
"https://github.com/simplex-chat/haskell-terminal.git"."f708b00009b54890172068f168bf98508ffcd495" = "0zmq7lmfsk8m340g47g5963yba7i88n4afa6z93sg9px5jv1mijj"; "https://github.com/simplex-chat/haskell-terminal.git"."f708b00009b54890172068f168bf98508ffcd495" = "0zmq7lmfsk8m340g47g5963yba7i88n4afa6z93sg9px5jv1mijj";
"https://github.com/simplex-chat/android-support.git"."9aa09f148089d6752ce563b14c2df1895718d806" = "0pbf2pf13v2kjzi397nr13f1h3jv0imvsq8rpiyy2qyx5vd50pqn"; "https://github.com/simplex-chat/android-support.git"."9aa09f148089d6752ce563b14c2df1895718d806" = "0pbf2pf13v2kjzi397nr13f1h3jv0imvsq8rpiyy2qyx5vd50pqn";
"https://github.com/simplex-chat/zip.git"."bd421c6b19cc4c465cd7af1f6f26169fb8ee1ebc" = "1csqfjhvc8wb5h4kxxndmb6iw7b4ib9ff2n81hrizsmnf45a6gg0";
} }

View File

@ -171,7 +171,6 @@ library
, attoparsec ==0.14.* , attoparsec ==0.14.*
, base >=4.7 && <5 , base >=4.7 && <5
, base64-bytestring >=1.0 && <1.3 , base64-bytestring >=1.0 && <1.3
, bytestring ==0.10.*
, composition ==1.0.* , composition ==1.0.*
, constraints >=0.12 && <0.14 , constraints >=0.12 && <0.14
, containers ==0.6.* , containers ==0.6.*
@ -184,10 +183,10 @@ library
, filepath ==1.4.* , filepath ==1.4.*
, http-types ==0.12.* , http-types ==0.12.*
, http2 >=4.2.2 && <4.3 , http2 >=4.2.2 && <4.3
, memory >=0.15 && <0.19 , memory ==0.18.*
, mtl >=2.3.1 && <3 , mtl >=2.3.1 && <3.0
, network >=3.1.2.7 && <3.2 , network >=3.1.2.7 && <3.2
, network-transport >=0.5.6 && <0.6 , network-transport ==0.5.6
, optparse-applicative >=0.15 && <0.17 , optparse-applicative >=0.15 && <0.17
, process ==1.6.* , process ==1.6.*
, random >=1.1 && <1.3 , random >=1.1 && <1.3
@ -197,17 +196,25 @@ library
, socks ==0.6.* , socks ==0.6.*
, sqlcipher-simple ==0.4.* , sqlcipher-simple ==0.4.*
, stm ==2.5.* , stm ==2.5.*
, template-haskell >=2.16 && <2.21
, terminal ==0.2.* , terminal ==0.2.*
, text >=2.0 && <3
, time ==1.9.* , time ==1.9.*
, tls >=1.6.0 && <1.7 , tls >=1.6.0 && <1.7
, unliftio ==0.2.* , unliftio ==0.2.*
, unliftio-core ==0.2.* , unliftio-core ==0.2.*
, zip >=1.7 && <2.1 , zip ==2.0.*
default-language: Haskell2010 default-language: Haskell2010
if flag(swift) if flag(swift)
cpp-options: -DswiftJSON cpp-options: -DswiftJSON
if impl(ghc >= 9.6.2)
build-depends:
bytestring ==0.11.*
, template-haskell ==2.20.*
, text >=2.0.1 && <2.2
if impl(ghc < 9.6.2)
build-depends:
bytestring ==0.10.*
, template-haskell ==2.16.*
, text >=1.2.3.0 && <1.3
executable simplex-bot executable simplex-bot
main-is: Main.hs main-is: Main.hs
@ -223,7 +230,6 @@ executable simplex-bot
, attoparsec ==0.14.* , attoparsec ==0.14.*
, base >=4.7 && <5 , base >=4.7 && <5
, base64-bytestring >=1.0 && <1.3 , base64-bytestring >=1.0 && <1.3
, bytestring ==0.10.*
, composition ==1.0.* , composition ==1.0.*
, constraints >=0.12 && <0.14 , constraints >=0.12 && <0.14
, containers ==0.6.* , containers ==0.6.*
@ -236,10 +242,10 @@ executable simplex-bot
, filepath ==1.4.* , filepath ==1.4.*
, http-types ==0.12.* , http-types ==0.12.*
, http2 >=4.2.2 && <4.3 , http2 >=4.2.2 && <4.3
, memory >=0.15 && <0.19 , memory ==0.18.*
, mtl >=2.3.1 && <3 , mtl >=2.3.1 && <3.0
, network >=3.1.2.7 && <3.2 , network >=3.1.2.7 && <3.2
, network-transport >=0.5.6 && <0.6 , network-transport ==0.5.6
, optparse-applicative >=0.15 && <0.17 , optparse-applicative >=0.15 && <0.17
, process ==1.6.* , process ==1.6.*
, random >=1.1 && <1.3 , random >=1.1 && <1.3
@ -250,17 +256,25 @@ executable simplex-bot
, socks ==0.6.* , socks ==0.6.*
, sqlcipher-simple ==0.4.* , sqlcipher-simple ==0.4.*
, stm ==2.5.* , stm ==2.5.*
, template-haskell >=2.16 && <2.21
, terminal ==0.2.* , terminal ==0.2.*
, text >=2.0 && <3
, time ==1.9.* , time ==1.9.*
, tls >=1.6.0 && <1.7 , tls >=1.6.0 && <1.7
, unliftio ==0.2.* , unliftio ==0.2.*
, unliftio-core ==0.2.* , unliftio-core ==0.2.*
, zip >=1.7 && <2.1 , zip ==2.0.*
default-language: Haskell2010 default-language: Haskell2010
if flag(swift) if flag(swift)
cpp-options: -DswiftJSON cpp-options: -DswiftJSON
if impl(ghc >= 9.6.2)
build-depends:
bytestring ==0.11.*
, template-haskell ==2.20.*
, text >=2.0.1 && <2.2
if impl(ghc < 9.6.2)
build-depends:
bytestring ==0.10.*
, template-haskell ==2.16.*
, text >=1.2.3.0 && <1.3
executable simplex-bot-advanced executable simplex-bot-advanced
main-is: Main.hs main-is: Main.hs
@ -276,7 +290,6 @@ executable simplex-bot-advanced
, attoparsec ==0.14.* , attoparsec ==0.14.*
, base >=4.7 && <5 , base >=4.7 && <5
, base64-bytestring >=1.0 && <1.3 , base64-bytestring >=1.0 && <1.3
, bytestring ==0.10.*
, composition ==1.0.* , composition ==1.0.*
, constraints >=0.12 && <0.14 , constraints >=0.12 && <0.14
, containers ==0.6.* , containers ==0.6.*
@ -289,10 +302,10 @@ executable simplex-bot-advanced
, filepath ==1.4.* , filepath ==1.4.*
, http-types ==0.12.* , http-types ==0.12.*
, http2 >=4.2.2 && <4.3 , http2 >=4.2.2 && <4.3
, memory >=0.15 && <0.19 , memory ==0.18.*
, mtl >=2.3.1 && <3 , mtl >=2.3.1 && <3.0
, network >=3.1.2.7 && <3.2 , network >=3.1.2.7 && <3.2
, network-transport >=0.5.6 && <0.6 , network-transport ==0.5.6
, optparse-applicative >=0.15 && <0.17 , optparse-applicative >=0.15 && <0.17
, process ==1.6.* , process ==1.6.*
, random >=1.1 && <1.3 , random >=1.1 && <1.3
@ -303,17 +316,25 @@ executable simplex-bot-advanced
, socks ==0.6.* , socks ==0.6.*
, sqlcipher-simple ==0.4.* , sqlcipher-simple ==0.4.*
, stm ==2.5.* , stm ==2.5.*
, template-haskell >=2.16 && <2.21
, terminal ==0.2.* , terminal ==0.2.*
, text >=2.0 && <3
, time ==1.9.* , time ==1.9.*
, tls >=1.6.0 && <1.7 , tls >=1.6.0 && <1.7
, unliftio ==0.2.* , unliftio ==0.2.*
, unliftio-core ==0.2.* , unliftio-core ==0.2.*
, zip >=1.7 && <2.1 , zip ==2.0.*
default-language: Haskell2010 default-language: Haskell2010
if flag(swift) if flag(swift)
cpp-options: -DswiftJSON cpp-options: -DswiftJSON
if impl(ghc >= 9.6.2)
build-depends:
bytestring ==0.11.*
, template-haskell ==2.20.*
, text >=2.0.1 && <2.2
if impl(ghc < 9.6.2)
build-depends:
bytestring ==0.10.*
, template-haskell ==2.16.*
, text >=1.2.3.0 && <1.3
executable simplex-broadcast-bot executable simplex-broadcast-bot
main-is: ../Main.hs main-is: ../Main.hs
@ -331,7 +352,6 @@ executable simplex-broadcast-bot
, attoparsec ==0.14.* , attoparsec ==0.14.*
, base >=4.7 && <5 , base >=4.7 && <5
, base64-bytestring >=1.0 && <1.3 , base64-bytestring >=1.0 && <1.3
, bytestring ==0.10.*
, composition ==1.0.* , composition ==1.0.*
, constraints >=0.12 && <0.14 , constraints >=0.12 && <0.14
, containers ==0.6.* , containers ==0.6.*
@ -344,10 +364,10 @@ executable simplex-broadcast-bot
, filepath ==1.4.* , filepath ==1.4.*
, http-types ==0.12.* , http-types ==0.12.*
, http2 >=4.2.2 && <4.3 , http2 >=4.2.2 && <4.3
, memory >=0.15 && <0.19 , memory ==0.18.*
, mtl >=2.3.1 && <3 , mtl >=2.3.1 && <3.0
, network >=3.1.2.7 && <3.2 , network >=3.1.2.7 && <3.2
, network-transport >=0.5.6 && <0.6 , network-transport ==0.5.6
, optparse-applicative >=0.15 && <0.17 , optparse-applicative >=0.15 && <0.17
, process ==1.6.* , process ==1.6.*
, random >=1.1 && <1.3 , random >=1.1 && <1.3
@ -358,17 +378,25 @@ executable simplex-broadcast-bot
, socks ==0.6.* , socks ==0.6.*
, sqlcipher-simple ==0.4.* , sqlcipher-simple ==0.4.*
, stm ==2.5.* , stm ==2.5.*
, template-haskell >=2.16 && <2.21
, terminal ==0.2.* , terminal ==0.2.*
, text >=2.0 && <3
, time ==1.9.* , time ==1.9.*
, tls >=1.6.0 && <1.7 , tls >=1.6.0 && <1.7
, unliftio ==0.2.* , unliftio ==0.2.*
, unliftio-core ==0.2.* , unliftio-core ==0.2.*
, zip >=1.7 && <2.1 , zip ==2.0.*
default-language: Haskell2010 default-language: Haskell2010
if flag(swift) if flag(swift)
cpp-options: -DswiftJSON cpp-options: -DswiftJSON
if impl(ghc >= 9.6.2)
build-depends:
bytestring ==0.11.*
, template-haskell ==2.20.*
, text >=2.0.1 && <2.2
if impl(ghc < 9.6.2)
build-depends:
bytestring ==0.10.*
, template-haskell ==2.16.*
, text >=1.2.3.0 && <1.3
executable simplex-chat executable simplex-chat
main-is: Main.hs main-is: Main.hs
@ -385,7 +413,6 @@ executable simplex-chat
, attoparsec ==0.14.* , attoparsec ==0.14.*
, base >=4.7 && <5 , base >=4.7 && <5
, base64-bytestring >=1.0 && <1.3 , base64-bytestring >=1.0 && <1.3
, bytestring ==0.10.*
, composition ==1.0.* , composition ==1.0.*
, constraints >=0.12 && <0.14 , constraints >=0.12 && <0.14
, containers ==0.6.* , containers ==0.6.*
@ -398,10 +425,10 @@ executable simplex-chat
, filepath ==1.4.* , filepath ==1.4.*
, http-types ==0.12.* , http-types ==0.12.*
, http2 >=4.2.2 && <4.3 , http2 >=4.2.2 && <4.3
, memory >=0.15 && <0.19 , memory ==0.18.*
, mtl >=2.3.1 && <3 , mtl >=2.3.1 && <3.0
, network ==3.1.* , network ==3.1.*
, network-transport >=0.5.6 && <0.6 , network-transport ==0.5.6
, optparse-applicative >=0.15 && <0.17 , optparse-applicative >=0.15 && <0.17
, process ==1.6.* , process ==1.6.*
, random >=1.1 && <1.3 , random >=1.1 && <1.3
@ -412,18 +439,26 @@ executable simplex-chat
, socks ==0.6.* , socks ==0.6.*
, sqlcipher-simple ==0.4.* , sqlcipher-simple ==0.4.*
, stm ==2.5.* , stm ==2.5.*
, template-haskell >=2.16 && <2.21
, terminal ==0.2.* , terminal ==0.2.*
, text >=2.0 && <3
, time ==1.9.* , time ==1.9.*
, tls >=1.6.0 && <1.7 , tls >=1.6.0 && <1.7
, unliftio ==0.2.* , unliftio ==0.2.*
, unliftio-core ==0.2.* , unliftio-core ==0.2.*
, websockets ==0.12.* , websockets ==0.12.*
, zip >=1.7 && <2.1 , zip ==2.0.*
default-language: Haskell2010 default-language: Haskell2010
if flag(swift) if flag(swift)
cpp-options: -DswiftJSON cpp-options: -DswiftJSON
if impl(ghc >= 9.6.2)
build-depends:
bytestring ==0.11.*
, template-haskell ==2.20.*
, text >=2.0.1 && <2.2
if impl(ghc < 9.6.2)
build-depends:
bytestring ==0.10.*
, template-haskell ==2.16.*
, text >=1.2.3.0 && <1.3
executable simplex-directory-service executable simplex-directory-service
main-is: ../Main.hs main-is: ../Main.hs
@ -443,7 +478,6 @@ executable simplex-directory-service
, attoparsec ==0.14.* , attoparsec ==0.14.*
, base >=4.7 && <5 , base >=4.7 && <5
, base64-bytestring >=1.0 && <1.3 , base64-bytestring >=1.0 && <1.3
, bytestring ==0.10.*
, composition ==1.0.* , composition ==1.0.*
, constraints >=0.12 && <0.14 , constraints >=0.12 && <0.14
, containers ==0.6.* , containers ==0.6.*
@ -456,10 +490,10 @@ executable simplex-directory-service
, filepath ==1.4.* , filepath ==1.4.*
, http-types ==0.12.* , http-types ==0.12.*
, http2 >=4.2.2 && <4.3 , http2 >=4.2.2 && <4.3
, memory >=0.15 && <0.19 , memory ==0.18.*
, mtl >=2.3.1 && <3 , mtl >=2.3.1 && <3.0
, network >=3.1.2.7 && <3.2 , network >=3.1.2.7 && <3.2
, network-transport >=0.5.6 && <0.6 , network-transport ==0.5.6
, optparse-applicative >=0.15 && <0.17 , optparse-applicative >=0.15 && <0.17
, process ==1.6.* , process ==1.6.*
, random >=1.1 && <1.3 , random >=1.1 && <1.3
@ -470,17 +504,25 @@ executable simplex-directory-service
, socks ==0.6.* , socks ==0.6.*
, sqlcipher-simple ==0.4.* , sqlcipher-simple ==0.4.*
, stm ==2.5.* , stm ==2.5.*
, template-haskell >=2.16 && <2.21
, terminal ==0.2.* , terminal ==0.2.*
, text >=2.0 && <3
, time ==1.9.* , time ==1.9.*
, tls >=1.6.0 && <1.7 , tls >=1.6.0 && <1.7
, unliftio ==0.2.* , unliftio ==0.2.*
, unliftio-core ==0.2.* , unliftio-core ==0.2.*
, zip >=1.7 && <2.1 , zip ==2.0.*
default-language: Haskell2010 default-language: Haskell2010
if flag(swift) if flag(swift)
cpp-options: -DswiftJSON cpp-options: -DswiftJSON
if impl(ghc >= 9.6.2)
build-depends:
bytestring ==0.11.*
, template-haskell ==2.20.*
, text >=2.0.1 && <2.2
if impl(ghc < 9.6.2)
build-depends:
bytestring ==0.10.*
, template-haskell ==2.16.*
, text >=1.2.3.0 && <1.3
test-suite simplex-chat-test test-suite simplex-chat-test
type: exitcode-stdio-1.0 type: exitcode-stdio-1.0
@ -524,7 +566,6 @@ test-suite simplex-chat-test
, attoparsec ==0.14.* , attoparsec ==0.14.*
, base >=4.7 && <5 , base >=4.7 && <5
, base64-bytestring >=1.0 && <1.3 , base64-bytestring >=1.0 && <1.3
, bytestring ==0.10.*
, composition ==1.0.* , composition ==1.0.*
, constraints >=0.12 && <0.14 , constraints >=0.12 && <0.14
, containers ==0.6.* , containers ==0.6.*
@ -540,10 +581,10 @@ test-suite simplex-chat-test
, hspec ==2.7.* , hspec ==2.7.*
, http-types ==0.12.* , http-types ==0.12.*
, http2 >=4.2.2 && <4.3 , http2 >=4.2.2 && <4.3
, memory >=0.15 && <0.19 , memory ==0.18.*
, mtl >=2.3.1 && <3 , mtl >=2.3.1 && <3.0
, network ==3.1.* , network ==3.1.*
, network-transport >=0.5.6 && <0.6 , network-transport ==0.5.6
, optparse-applicative >=0.15 && <0.17 , optparse-applicative >=0.15 && <0.17
, process ==1.6.* , process ==1.6.*
, random >=1.1 && <1.3 , random >=1.1 && <1.3
@ -555,14 +596,22 @@ test-suite simplex-chat-test
, socks ==0.6.* , socks ==0.6.*
, sqlcipher-simple ==0.4.* , sqlcipher-simple ==0.4.*
, stm ==2.5.* , stm ==2.5.*
, template-haskell >=2.16 && <2.21
, terminal ==0.2.* , terminal ==0.2.*
, text >=2.0 && <3
, time ==1.9.* , time ==1.9.*
, tls >=1.6.0 && <1.7 , tls >=1.6.0 && <1.7
, unliftio ==0.2.* , unliftio ==0.2.*
, unliftio-core ==0.2.* , unliftio-core ==0.2.*
, zip >=1.7 && <2.1 , zip ==2.0.*
default-language: Haskell2010 default-language: Haskell2010
if flag(swift) if flag(swift)
cpp-options: -DswiftJSON cpp-options: -DswiftJSON
if impl(ghc >= 9.6.2)
build-depends:
bytestring ==0.11.*
, template-haskell ==2.20.*
, text >=2.0.1 && <2.2
if impl(ghc < 9.6.2)
build-depends:
bytestring ==0.10.*
, template-haskell ==2.16.*
, text >=1.2.3.0 && <1.3

View File

@ -42,6 +42,7 @@ data ChatOpts = ChatOpts
allowInstantFiles :: Bool, allowInstantFiles :: Bool,
autoAcceptFileSize :: Integer, autoAcceptFileSize :: Integer,
muteNotifications :: Bool, muteNotifications :: Bool,
markRead :: Bool,
maintenance :: Bool maintenance :: Bool
} }
@ -268,6 +269,12 @@ chatOptsP appDir defaultDbFileName = do
( long "mute" ( long "mute"
<> help "Mute notifications" <> help "Mute notifications"
) )
markRead <-
switch
( long "mark-read"
<> short 'r'
<> help "Mark shown messages as read"
)
maintenance <- maintenance <-
switch switch
( long "maintenance" ( long "maintenance"
@ -286,6 +293,7 @@ chatOptsP appDir defaultDbFileName = do
allowInstantFiles, allowInstantFiles,
autoAcceptFileSize, autoAcceptFileSize,
muteNotifications, muteNotifications,
markRead,
maintenance maintenance
} }

View File

@ -44,7 +44,7 @@ simplexChatTerminal cfg opts t =
handle checkDBKeyError . simplexChatCore cfg opts $ \u cc -> do handle checkDBKeyError . simplexChatCore cfg opts $ \u cc -> do
ct <- newChatTerminal t opts ct <- newChatTerminal t opts
when (firstTime cc) . printToTerminal ct $ chatWelcome u when (firstTime cc) . printToTerminal ct $ chatWelcome u
runChatTerminal ct cc runChatTerminal ct cc opts
checkDBKeyError :: SQLError -> IO () checkDBKeyError :: SQLError -> IO ()
checkDBKeyError e = case sqlError e of checkDBKeyError e = case sqlError e of
@ -53,5 +53,5 @@ checkDBKeyError e = case sqlError e of
exitFailure exitFailure
_ -> throwIO e _ -> throwIO e
runChatTerminal :: ChatTerminal -> ChatController -> IO () runChatTerminal :: ChatTerminal -> ChatController -> ChatOpts -> IO ()
runChatTerminal ct cc = raceAny_ [runTerminalInput ct cc, runTerminalOutput ct cc, runInputLoop ct cc] runChatTerminal ct cc opts = raceAny_ [runTerminalInput ct cc, runTerminalOutput ct cc opts, runInputLoop ct cc]

View File

@ -142,13 +142,13 @@ withTermLock ChatTerminal {termLock} action = do
action action
atomically $ putTMVar termLock () atomically $ putTMVar termLock ()
runTerminalOutput :: ChatTerminal -> ChatController -> IO () runTerminalOutput :: ChatTerminal -> ChatController -> ChatOpts -> IO ()
runTerminalOutput ct cc@ChatController {outputQ, showLiveItems, logFilePath} = do runTerminalOutput ct cc@ChatController {outputQ, showLiveItems, logFilePath} ChatOpts {markRead} = do
forever $ do forever $ do
(_, outputRH, r) <- atomically $ readTBQueue outputQ (_, outputRH, r) <- atomically $ readTBQueue outputQ
case r of case r of
CRNewChatItem u ci -> markChatItemRead u ci CRNewChatItem u ci -> when markRead $ markChatItemRead u ci
CRChatItemUpdated u ci -> markChatItemRead u ci CRChatItemUpdated u ci -> when markRead $ markChatItemRead u ci
CRRemoteHostConnected {remoteHost = RemoteHostInfo {remoteHostId}} -> getRemoteUser remoteHostId CRRemoteHostConnected {remoteHost = RemoteHostInfo {remoteHostId}} -> getRemoteUser remoteHostId
CRRemoteHostStopped {remoteHostId_} -> mapM_ removeRemoteUser remoteHostId_ CRRemoteHostStopped {remoteHostId_} -> mapM_ removeRemoteUser remoteHostId_
_ -> pure () _ -> pure ()

View File

@ -1,96 +0,0 @@
# This file was automatically generated by 'stack init'
#
# Some commonly used options have been documented as comments in this file.
# For advanced use and comprehensive documentation of the format, please see:
# https://docs.haskellstack.org/en/stable/yaml_configuration/
# Resolver to choose a 'specific' stackage snapshot or a compiler version.
# A snapshot resolver dictates the compiler version and the set of packages
# to be used for project dependencies. For example:
#
# resolver: lts-3.5
# resolver: nightly-2015-09-21
# resolver: ghc-7.10.2
#
# The location of a snapshot can be provided as a file or url. Stack assumes
# a snapshot provided as a file might change, whereas a url resource does not.
#
# resolver: ./custom-snapshot.yaml
# resolver: https://example.com/snapshots/2018-01-01.yaml
resolver: lts-18.21
# User packages to be built.
# Various formats can be used as shown in the example below.
#
# packages:
# - some-directory
# - https://example.com/foo/bar/baz-0.0.2.tar.gz
# subdirs:
# - auto-update
# - wai
packages:
- .
# Dependency packages to be pulled from upstream that are not in the resolver.
# These entries can reference officially published versions as well as
# forks / in-progress versions pinned to a git hash. For example:
#
extra-deps:
- cryptostore-0.2.1.0@sha256:9896e2984f36a1c8790f057fd5ce3da4cbcaf8aa73eb2d9277916886978c5b19,3881
- network-3.1.2.7@sha256:e3d78b13db9512aeb106e44a334ab42b7aa48d26c097299084084cb8be5c5568,4888
- simple-logger-0.1.0@sha256:be8ede4bd251a9cac776533bae7fb643369ebd826eb948a9a18df1a8dd252ff8,1079
- tls-1.6.0@sha256:7ae39373fd2de27fb80e90f76d22aeeb9a074a0ddd120cbd02c9c52f516a9e55,6987
# below hackage dependencies are to update Aeson to 2.0.3
- OneTuple-0.3.1@sha256:a848c096c9d29e82ffdd30a9998aa2931cbccb3a1bc137539d80f6174d31603e,2262
- attoparsec-0.14.4@sha256:79584bdada8b730cb5138fca8c35c76fbef75fc1d1e01e6b1d815a5ee9843191,5810
- hashable-1.4.0.2@sha256:0cddd0229d1aac305ea0404409c0bbfab81f075817bd74b8b2929eff58333e55,5005
- semialign-1.2.0.1@sha256:0e179b4d3a8eff79001d374d6c91917c6221696b9620f0a4d86852fc6a9b9501,2836
- text-short-0.1.5@sha256:962c6228555debdc46f758d0317dea16e5240d01419b42966674b08a5c3d8fa6,3498
- time-compat-1.9.6.1@sha256:42d8f2e08e965e1718917d54ad69e1d06bd4b87d66c41dc7410f59313dba4ed1,5033
# - simplexmq-1.0.0@sha256:34b2004728ae396e3ae449cd090ba7410781e2b3cefc59259915f4ca5daa9ea8,8561
# - ../simplexmq
- github: simplex-chat/simplexmq
commit: 117168ccce93ef5ac478c02e3f02a018fa8a2200
- github: kazu-yamamoto/http2
commit: f5525b755ff2418e6e6ecc69e877363b0d0bcaeb
# - ../direct-sqlcipher
- github: simplex-chat/direct-sqlcipher
commit: 34309410eb2069b029b8fc1872deb1e0db123294
# - ../sqlcipher-simple
- github: simplex-chat/sqlcipher-simple
commit: 5e154a2aeccc33ead6c243ec07195ab673137221
# - terminal-0.2.0.0@sha256:de6770ecaae3197c66ac1f0db5a80cf5a5b1d3b64a66a05b50f442de5ad39570,2977
- github: simplex-chat/aeson
commit: aab7b5a14d6c5ea64c64dcaee418de1bb00dcc2b
- github: simplex-chat/haskell-terminal
commit: f708b00009b54890172068f168bf98508ffcd495
- github: simplex-chat/android-support
commit: 9aa09f148089d6752ce563b14c2df1895718d806
#
# extra-deps: []
# Override default flag values for local packages and extra-deps
flags:
zip:
disable-bzip2: true
disable-zstd: true
direct-sqlcipher:
openssl: true
# Extra package databases containing global packages
# extra-package-dbs: []
# Control whether we use the GHC we find on the path
# system-ghc: true
#
# Require a specific version of stack, using version ranges
# require-stack-version: -any # Default
# require-stack-version: ">=2.1"
#
# Override the architecture used by stack, especially useful on Windows
# arch: i386
# arch: x86_64
#
# Extra directories used by stack for building
# extra-lib-dirs: [/path/to/dir]
#
# Allow a newer minor version of GHC than the snapshot specifies
# compiler-check: newer-minor

View File

@ -81,6 +81,7 @@ testOpts =
allowInstantFiles = True, allowInstantFiles = True,
autoAcceptFileSize = 0, autoAcceptFileSize = 0,
muteNotifications = True, muteNotifications = True,
markRead = True,
maintenance = False maintenance = False
} }
@ -173,7 +174,7 @@ startTestChat_ db cfg opts user = do
t <- withVirtualTerminal termSettings pure t <- withVirtualTerminal termSettings pure
ct <- newChatTerminal t opts ct <- newChatTerminal t opts
cc <- newChatController db (Just user) cfg opts cc <- newChatController db (Just user) cfg opts
chatAsync <- async . runSimplexChat opts user cc . const $ runChatTerminal ct chatAsync <- async . runSimplexChat opts user cc $ \_u cc' -> runChatTerminal ct cc' opts
atomically . unless (maintenance opts) $ readTVar (agentAsync cc) >>= \a -> when (isNothing a) retry atomically . unless (maintenance opts) $ readTVar (agentAsync cc) >>= \a -> when (isNothing a) retry
termQ <- newTQueueIO termQ <- newTQueueIO
termAsync <- async $ readTerminalOutput t termQ termAsync <- async $ readTerminalOutput t termQ

View File

@ -162,13 +162,13 @@ storedBindingsTest = testChat2 aliceProfile aliceDesktopProfile $ \mobile deskto
desktop ##> "/list remote hosts" desktop ##> "/list remote hosts"
desktop <## "Remote hosts:" desktop <## "Remote hosts:"
desktop <## "1. Mobile (connected) [lo 127.0.0.1:52230]" desktop <##. "1. Mobile (connected) ["
stopDesktop mobile desktop stopDesktop mobile desktop
desktop ##> "/list remote hosts" desktop ##> "/list remote hosts"
desktop <## "Remote hosts:" desktop <## "Remote hosts:"
desktop <## "1. Mobile [lo 127.0.0.1:52230]" desktop <##. "1. Mobile ["
-- TODO: more parser tests -- TODO: more parser tests
remoteMessageTest :: HasCallStack => FilePath -> IO () remoteMessageTest :: HasCallStack => FilePath -> IO ()
remoteMessageTest = testChat3 aliceProfile aliceDesktopProfile bobProfile $ \mobile desktop bob -> do remoteMessageTest = testChat3 aliceProfile aliceDesktopProfile bobProfile $ \mobile desktop bob -> do