Files
simplex-chat/src/Simplex/Chat/Store/NoteFolders.hs
T
Alexander Bondarenko bc8a6f4833 core: add notes chat type (#3568)
* Add chat type "self"

* rename to Notes

* cover more things

* remove quote, tweak sql

* resolve comments

* constrain ACIQDirection to exclude CTLocal

* add CILocalRcv handling

* plug in migrations and tests

* cover more API, implement new folders

* working create/send/tail

* remove interaction with messages

* add note deletion (api-only)

* add folder deletion

* add getLocalChatItemIdByText

* add APICreateChatItem and files

* add protocol check for getFileTransfer protocol

* replace FTLocal with createLocalFile

* add chat previews

* add folder clear

* add reactions

* add read/unread

* add note updates

* resolve some comments

* remove local reactions

* remove folder names, deletion, add autocreate

* add file deletion check

* add preview pagination test

* add per-item file deletion check

* pull mkChatItem out of createLocal to prevent ci record updates

* use - as notes name

* bump migration ts

* update schema

* resolve comments

* add chat pagination test

* use chat queries from Direct instead

* evict note folders from createUserRecord

* switch to - for note folder chat type prefix and use empty name

* fix getLocalChatXxx

* add explicit createCCNoteFolder for tests

* use overloadedstrings for single-line queries

* add suggested chat list tests

* add notes chat to a user-creating test

* throw correct error for missing file

* remove unique check from schema

* add UndecidableInstances for ghc8.10

* switch to * for chat type sigil

* add file safety test

* add drop index

* remove indentation

* remove repeated folder

* remove redundant filter query, NoteFolderName

* don't attempt to cancel local files when deleting chat item

* rename function

* fix comment

* rename

* fix merge

* fix typo

* remove editable limit

* restore comment

* remove local file cancel

* Revert "remove editable limit"

This reverts commit 65df55caf8.

* refactor

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2024-01-11 17:01:44 +00:00

70 lines
2.9 KiB
Haskell

{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Simplex.Chat.Store.NoteFolders where
import Control.Monad.Except (ExceptT (..), throwError)
import Control.Monad.IO.Class (liftIO)
import Data.Time (getCurrentTime)
import Database.SQLite.Simple (Only (..))
import Database.SQLite.Simple.QQ (sql)
import Simplex.Chat.Store.Shared (StoreError (..))
import Simplex.Chat.Types (NoteFolder (..), NoteFolderId, User (..))
import Simplex.Messaging.Agent.Protocol (UserId)
import Simplex.Messaging.Agent.Store.SQLite (firstRow)
import qualified Simplex.Messaging.Agent.Store.SQLite.DB as DB
createNoteFolder :: DB.Connection -> User -> ExceptT StoreError IO ()
createNoteFolder db User {userId} = do
liftIO (DB.query db "SELECT note_folder_id FROM note_folders WHERE user_id = ? LIMIT 1" $ Only userId) >>= \case
[] -> liftIO $ DB.execute db "INSERT INTO note_folders (user_id) VALUES (?)" (Only userId)
Only noteFolderId : _ -> throwError $ SENoteFolderAlreadyExists noteFolderId
getUserNoteFolderId :: DB.Connection -> User -> ExceptT StoreError IO NoteFolderId
getUserNoteFolderId db User {userId} =
ExceptT . firstRow fromOnly SEUserNoteFolderNotFound $
DB.query db "SELECT note_folder_id FROM note_folders WHERE user_id = ?" (Only userId)
getNoteFolder :: DB.Connection -> User -> NoteFolderId -> ExceptT StoreError IO NoteFolder
getNoteFolder db User {userId} noteFolderId =
ExceptT . firstRow toNoteFolder (SENoteFolderNotFound noteFolderId) $
DB.query
db
[sql|
SELECT
created_at, updated_at, chat_ts, favorite, unread_chat
FROM note_folders
WHERE user_id = ?
AND note_folder_id = ?
|]
(userId, noteFolderId)
where
toNoteFolder (createdAt, updatedAt, chatTs, favorite, unread) =
NoteFolder {noteFolderId, userId, createdAt, updatedAt, chatTs, favorite, unread}
updateNoteFolderUnreadChat :: DB.Connection -> User -> NoteFolder -> Bool -> IO ()
updateNoteFolderUnreadChat db User {userId} NoteFolder {noteFolderId} unreadChat = do
updatedAt <- getCurrentTime
DB.execute db "UPDATE note_folders SET unread_chat = ?, updated_at = ? WHERE user_id = ? AND note_folder_id = ?" (unreadChat, updatedAt, userId, noteFolderId)
deleteNoteFolderFiles :: DB.Connection -> UserId -> NoteFolder -> IO ()
deleteNoteFolderFiles db userId NoteFolder {noteFolderId} = do
DB.execute
db
[sql|
DELETE FROM files
WHERE user_id = ?
AND chat_item_id IN (
SELECT chat_item_id FROM chat_items WHERE user_id = ? AND note_folder_id = ?
)
|]
(userId, userId, noteFolderId)
deleteNoteFolderCIs :: DB.Connection -> User -> NoteFolder -> IO ()
deleteNoteFolderCIs db User {userId} NoteFolder {noteFolderId} =
DB.execute db "DELETE FROM chat_items WHERE user_id = ? AND note_folder_id = ?" (userId, noteFolderId)