diff --git a/go.mod b/go.mod index 8e720cec75e02ad4a107fb1da74c9f138a17031b..289a784729233f8987211fed186a12d84e63d64c 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( github.com/hack-pad/go-indexeddb v0.2.0 github.com/pkg/errors v0.9.1 github.com/spf13/jwalterweatherman v1.1.0 - gitlab.com/elixxir/client v1.5.1-0.20220907213656-d2cb1308c363 + gitlab.com/elixxir/client v1.5.1-0.20220908172911-8967d2e85c80 gitlab.com/elixxir/crypto v0.0.7-0.20220902165412-5c5e3e990e84 gitlab.com/xx_network/primitives v0.0.4-0.20220809193445-9fc0a5209548 ) diff --git a/go.sum b/go.sum index e471cb0897c27da30384732b5c5889c9029bc746..ef9a49f0f40964bc9009384f64cefb2811fec9d7 100644 --- a/go.sum +++ b/go.sum @@ -613,8 +613,8 @@ github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f h1:yXGvNBqzZwAhDYlSnxPRbgor6JWoOt1Z7s3z1O9JR40= gitlab.com/elixxir/bloomfilter v0.0.0-20211222005329-7d931ceead6f/go.mod h1:H6jztdm0k+wEV2QGK/KYA+MY9nj9Zzatux/qIvDDv3k= -gitlab.com/elixxir/client v1.5.1-0.20220907213656-d2cb1308c363 h1:pj80sFUq/0Kg/7sLo1/lldf94Ygbul1i7sBEqsqbYyA= -gitlab.com/elixxir/client v1.5.1-0.20220907213656-d2cb1308c363/go.mod h1:HvISFfNXL/XCJ6ynSrEwG9kPEp14i87G5y4wyL1H8R0= +gitlab.com/elixxir/client v1.5.1-0.20220908172911-8967d2e85c80 h1:P+l27l4/qRxwkQZktnSKGPm11v5ygogKXoKM9EfYlWc= +gitlab.com/elixxir/client v1.5.1-0.20220908172911-8967d2e85c80/go.mod h1:HvISFfNXL/XCJ6ynSrEwG9kPEp14i87G5y4wyL1H8R0= gitlab.com/elixxir/comms v0.0.4-0.20220907184530-d8eec143a1e8 h1:xbJBQdMdB+mMsKIVXqx7eAWzZmulA3KdRhlbyAk0NIc= gitlab.com/elixxir/comms v0.0.4-0.20220907184530-d8eec143a1e8/go.mod h1:xE9NKMAxzvTXmyJ5BMjBZFWMPfvQpw3rB7be2VYvU8E= gitlab.com/elixxir/crypto v0.0.0-20200804182833-984246dea2c4/go.mod h1:ucm9SFKJo+K0N2GwRRpaNr+tKXMIOVWzmyUD0SbOu2c= diff --git a/indexedDb/implementation.go b/indexedDb/implementation.go index 30099e9b205b510501eac0e18018142e75386423..8c16d352f7ba9d2d3bc0c5ba3f1f69c3f942d51a 100644 --- a/indexedDb/implementation.go +++ b/indexedDb/implementation.go @@ -38,14 +38,14 @@ type wasmModel struct { func (w *wasmModel) JoinChannel(channel *cryptoBroadcast.Channel) { parentErr := errors.New("failed to JoinChannel") - // Build Channel object + // Build object newChannel := Channel{ Id: channel.ReceptionID.Marshal(), Name: channel.Name, Description: channel.Description, } - // Convert Channel to jsObject + // Convert to jsObject newChannelJson, err := json.Marshal(&newChannel) if err != nil { jww.ERROR.Printf("%+v", errors.Wrapf(parentErr, @@ -62,13 +62,13 @@ func (w *wasmModel) JoinChannel(channel *cryptoBroadcast.Channel) { // Prepare the Transaction ctx := context.Background() - txn, err := w.db.Transaction(idb.TransactionReadWrite, messageStoreName) + txn, err := w.db.Transaction(idb.TransactionReadWrite, channelsStoreName) if err != nil { jww.ERROR.Printf("%+v", errors.Wrapf(parentErr, "Unable to create Transaction: %+v", err)) return } - store, err := txn.ObjectStore(messageStoreName) + store, err := txn.ObjectStore(channelsStoreName) if err != nil { jww.ERROR.Printf("%+v", errors.Wrapf(parentErr, "Unable to get ObjectStore: %+v", err)) @@ -98,13 +98,13 @@ func (w *wasmModel) LeaveChannel(channelID *id.ID) { // Prepare the Transaction ctx := context.Background() - txn, err := w.db.Transaction(idb.TransactionReadWrite, messageStoreName) + txn, err := w.db.Transaction(idb.TransactionReadWrite, channelsStoreName) if err != nil { jww.ERROR.Printf("%+v", errors.Wrapf(parentErr, "Unable to create Transaction: %+v", err)) return } - store, err := txn.ObjectStore(messageStoreName) + store, err := txn.ObjectStore(channelsStoreName) if err != nil { jww.ERROR.Printf("%+v", errors.Wrapf(parentErr, "Unable to get ObjectStore: %+v", err)) @@ -128,12 +128,73 @@ func (w *wasmModel) LeaveChannel(channelID *id.ID) { } } +// receiveHelper is a private helper for receiving any sort of message +func (w *wasmModel) receiveHelper(channelID []byte, messageID []byte, + parentId []byte, senderUsername string, + text string, timestamp time.Time, lease time.Duration) error { + // Build object + newMessage := Message{ + Id: messageID, + SenderUsername: senderUsername, + ChannelId: channelID, + ParentMessageId: parentId, + Timestamp: timestamp, + Lease: lease, + Status: uint8(channels.Delivered), + Hidden: false, + Pinned: false, + Text: text, + } + + // Convert to jsObject + newMessageJson, err := json.Marshal(&newMessage) + if err != nil { + return errors.Errorf("Unable to marshal Message: %+v", err) + } + var messageObj *jsObject + err = json.Unmarshal(newMessageJson, messageObj) + if err != nil { + return errors.Errorf("Unable to unmarshal Message: %+v", err) + } + + // Prepare the Transaction + ctx := context.Background() + txn, err := w.db.Transaction(idb.TransactionReadWrite, messageStoreName) + if err != nil { + return errors.Errorf("Unable to create Transaction: %+v", err) + } + store, err := txn.ObjectStore(messageStoreName) + if err != nil { + return errors.Errorf("Unable to get ObjectStore: %+v", err) + } + + // Perform the operation + _, err = store.Add(js.ValueOf(*messageObj)) + if err != nil { + return errors.Errorf("Unable to Add Message: %+v", err) + } + + // Wait for the operation to return + err = txn.Await(ctx) + if err != nil { + return errors.Errorf("Adding Message failed: %+v", err) + } + return nil +} + // ReceiveMessage is called whenever a message is received on a given channel // It may be called multiple times on the same message, it is incumbent on // the user of the API to filter such called by message ID. func (w *wasmModel) ReceiveMessage(channelID *id.ID, messageID cryptoChannel.MessageID, - senderUsername string, text string, - timestamp time.Time, lease time.Duration, round rounds.Round) { + senderUsername string, text string, timestamp time.Time, lease time.Duration, + round rounds.Round) { + parentErr := errors.New("failed to ReceiveMessage") + + err := w.receiveHelper(channelID.Marshal(), messageID.Bytes(), nil, + senderUsername, text, timestamp, lease) + if err != nil { + jww.ERROR.Printf("%+v", errors.Wrap(parentErr, err.Error())) + } } // ReceiveReply is called whenever a message is received which is a reply @@ -141,10 +202,17 @@ func (w *wasmModel) ReceiveMessage(channelID *id.ID, messageID cryptoChannel.Mes // it is incumbent on the user of the API to filter such called by message ID // Messages may arrive our of order, so a reply in theory can arrive before // the initial message, as a result it may be important to buffer replies. -func (w *wasmModel) ReceiveReply(ChannelID *id.ID, messageID cryptoChannel.MessageID, - SenderUsername string, text string, timestamp time.Time, - lease time.Duration, round rounds.Round) { +func (w *wasmModel) ReceiveReply(channelID *id.ID, messageID cryptoChannel.MessageID, + replyTo cryptoChannel.MessageID, senderUsername string, + text string, timestamp time.Time, lease time.Duration, + round rounds.Round) { + parentErr := errors.New("failed to ReceiveReply") + err := w.receiveHelper(channelID.Marshal(), messageID.Bytes(), + replyTo.Bytes(), senderUsername, text, timestamp, lease) + if err != nil { + jww.ERROR.Printf("%+v", errors.Wrap(parentErr, err.Error())) + } } // ReceiveReaction is called whenever a reaction to a message is received @@ -156,6 +224,13 @@ func (w *wasmModel) ReceiveReaction(channelID *id.ID, messageID cryptoChannel.Me reactionTo cryptoChannel.MessageID, senderUsername string, reaction string, timestamp time.Time, lease time.Duration, round rounds.Round) { + parentErr := errors.New("failed to ReceiveReaction") + + err := w.receiveHelper(channelID.Marshal(), messageID.Bytes(), + reactionTo.Bytes(), senderUsername, reaction, timestamp, lease) + if err != nil { + jww.ERROR.Printf("%+v", errors.Wrap(parentErr, err.Error())) + } } // MessageSent is called whenever the user sends a message. It should be diff --git a/indexedDb/model.go b/indexedDb/model.go index d8c52107c7053db72e60cd14520bc9b3466c6526..c9b58c0d93fb511f3d14b317e3b2dcca3f4c3f20 100644 --- a/indexedDb/model.go +++ b/indexedDb/model.go @@ -40,14 +40,16 @@ const ( // A Message belongs to one Channel. // A Message may belong to one Message (Parent). type Message struct { - Id []byte `json:"id"` // Matches pkeyName - SenderId []byte `json:"sender_id"` - ChannelId []byte `json:"channel_id"` // Index - ParentMessageId []byte `json:"parent_message_id"` // Index - Timestamp time.Time `json:"timestamp"` // Index - Status uint8 `json:"status"` - Hidden bool `json:"hidden"` - Pinned bool `json:"pinned"` // Index + Id []byte `json:"id"` // Matches pkeyName + SenderUsername string `json:"sender_username"` + ChannelId []byte `json:"channel_id"` // Index + ParentMessageId []byte `json:"parent_message_id"` // Index + Timestamp time.Time `json:"timestamp"` // Index + Lease time.Duration `json:"lease"` + Status uint8 `json:"status"` + Hidden bool `json:"hidden"` + Pinned bool `json:"pinned"` // Index + Text string `json:"text"` } // User defines the IndexedDb representation of a single User.