diff --git a/package-lock.json b/package-lock.json index 87ae8f839c..2118fad2a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8921,7 +8921,7 @@ } }, "web3": { - "version": "github:status-im/web3.js#aca66029d7ffac8ed2803b2fc7f0fec01e335ca3", + "version": "github:status-im/web3.js#aed8fa4baf4f8f9d5702bd82fac21c21f2ef6351", "requires": { "bignumber.js": "github:status-im/bignumber.js#cc066a0a3d6bfe0c436c9957f4ea8344bf963c89", "crypto-js": "3.1.8", diff --git a/resources/icons/warning.svg b/resources/icons/warning.svg new file mode 100644 index 0000000000..027f170834 --- /dev/null +++ b/resources/icons/warning.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/status_im/chat/events.cljs b/src/status_im/chat/events.cljs index deee7425b5..9061543564 100644 --- a/src/status_im/chat/events.cljs +++ b/src/status_im/chat/events.cljs @@ -5,6 +5,7 @@ [status-im.constants :as constants] [status-im.i18n :as i18n] [status-im.chat.models :as models] + [status-im.chat.models.message :as models.message] [status-im.chat.console :as console] [status-im.chat.constants :as chat.constants] [status-im.commands.events.loading :as events.loading] @@ -55,6 +56,13 @@ (models/set-chat-ui-props db {:show-bottom-info? true :bottom-info details}))) +(handlers/register-handler-db + :show-message-options + [re-frame/trim-v] + (fn [db [options]] + (models/set-chat-ui-props db {:show-message-options? true + :message-options options}))) + (def index-messages (partial into {} (map (juxt :message-id identity)))) (handlers/register-handler-fx @@ -85,6 +93,41 @@ {:db new-db :data-store/update-message (-> (get-in new-db msg-path) (select-keys [:message-id :user-statuses]))}))) +(handlers/register-handler-fx + :transport/set-message-envelope-hash + [re-frame/trim-v] + (fn [{:keys [db]} [chat-id message-id envelope-hash]] + {:db (assoc-in db [:transport/message-envelopes envelope-hash] {:chat-id chat-id + :message-id message-id})})) + +(handlers/register-handler-fx + :signals/envelope-status + [re-frame/trim-v] + (fn [{:keys [db] :as cofx} [envelope-hash status]] + (let [{:keys [chat-id message-id]} (get-in db [:transport/message-envelopes envelope-hash]) + message (get-in db [:chats chat-id :messages message-id])] + (models.message/update-message-status message status cofx)))) + +;; Change status of messages which are still in "sending" status to "not-sent" +;; (If signal from status-go has not been received) +(handlers/register-handler-fx + :process-pending-messages + [re-frame/trim-v] + (fn [{:keys [db]} []] + (let [pending-messages (->> db + :chats + vals + (mapcat (comp vals :messages)) + (filter (fn [{:keys [from user-statuses]}] (= :sending (get user-statuses from))))) + updated-messages (map (fn [{:keys [from] :as message}] + (assoc-in message [:user-statuses from] :not-sent)) + pending-messages)] + {:data-store/update-messages updated-messages + :db (reduce (fn [m {:keys [chat-id message-id from]}] + (assoc-in m [:chats chat-id :messages message-id :user-statuses from] :not-sent)) + db + pending-messages)}))) + (defn init-console-chat [{:keys [db] :as cofx}] (when-not (get-in db [:chats constants/console-chat-id]) @@ -349,3 +392,15 @@ (handlers-macro/merge-fx cofx {:db (assoc db :contacts/identity identity)} (navigation/navigate-forget :profile)))) + +(handlers/register-handler-fx + :resend-message + [re-frame/trim-v] + (fn [cofx [chat-id message-id]] + (models.message/resend-message chat-id message-id cofx))) + +(handlers/register-handler-fx + :delete-message + [re-frame/trim-v] + (fn [cofx [chat-id message-id]] + (models.message/delete-message chat-id message-id cofx))) diff --git a/src/status_im/chat/models/message.cljs b/src/status_im/chat/models/message.cljs index 9fceeb4179..ce2d0f0e18 100644 --- a/src/status_im/chat/models/message.cljs +++ b/src/status_im/chat/models/message.cljs @@ -170,17 +170,20 @@ :from current-account-id}}}))) (defn- send - [chat-id send-record {{:contacts/keys [contacts]} :db :as cofx}] + [chat-id message-id send-record {{:contacts/keys [contacts] :keys [network-status current-public-key]} :db :as cofx}] (let [{:keys [dapp? fcm-token]} (get contacts chat-id)] (if dapp? (send-dapp-message! cofx chat-id send-record) - (if fcm-token - (handlers-macro/merge-fx cofx - {:send-notification {:message "message" - :payload {:title "Status" :body "You have a new message"} - :tokens [fcm-token]}} - (transport/send send-record chat-id)) - (transport/send send-record chat-id cofx))))) + (if (= network-status :offline) + {:dispatch-later [{:ms 10000 + :dispatch [:update-message-status chat-id message-id current-public-key :not-sent]}]} + (if fcm-token + (handlers-macro/merge-fx cofx + {:send-notification {:message "message" + :payload {:title "Status" :body "You have a new message"} + :tokens [fcm-token]}} + (transport/send send-record chat-id)) + (transport/send send-record chat-id cofx)))))) (defn add-message-type [message {:keys [chat-id group-chat public?]}] (cond-> message @@ -200,19 +203,40 @@ :outgoing true :timestamp now :clock-value (utils.clocks/send last-clock-value) - :show? true} + :show? true + :user-statuses {identity :sending}} chat)) (def ^:private transport-keys [:content :content-type :message-type :clock-value :timestamp]) (defn- upsert-and-send [{:keys [chat-id] :as message} {:keys [now] :as cofx}] (let [send-record (protocol/map->Message (select-keys message transport-keys)) - message-with-id (assoc message :message-id (transport.utils/message-id send-record))] + message-id (transport.utils/message-id send-record) + message-with-id (assoc message :message-id message-id)] (handlers-macro/merge-fx cofx (chat-model/upsert-chat {:chat-id chat-id :timestamp now}) (add-message chat-id message-with-id true) - (send chat-id send-record)))) + (send chat-id message-id send-record)))) + +(defn update-message-status [{:keys [chat-id message-id from] :as message} status {:keys [db]}] + (let [updated-message (assoc-in message [:user-statuses from] status)] + {:db (assoc-in db [:chats chat-id :messages message-id] updated-message) + :data-store/update-message updated-message})) + +(defn resend-message [chat-id message-id cofx] + (let [message (get-in cofx [:db :chats chat-id :messages message-id]) + send-record (-> message + (select-keys transport-keys) + (update :message-type keyword) + protocol/map->Message)] + (handlers-macro/merge-fx cofx + (send chat-id message-id send-record) + (update-message-status message :sending)))) + +(defn delete-message [chat-id message-id {:keys [db]}] + {:db (update-in db [:chats chat-id :messages] dissoc message-id) + :data-store/delete-message message-id}) (defn send-message [{:keys [db now random-id] :as cofx} {:keys [chat-id] :as params}] (upsert-and-send (prepare-plain-message chat-id params (get-in db [:chats chat-id]) now) cofx)) diff --git a/src/status_im/chat/screen.cljs b/src/status_im/chat/screen.cljs index 30db4ecd87..21f7a2193d 100644 --- a/src/status_im/chat/screen.cljs +++ b/src/status_im/chat/screen.cljs @@ -12,6 +12,7 @@ [status-im.chat.views.input.input :as input] [status-im.chat.views.actions :as actions] [status-im.chat.views.bottom-info :as bottom-info] + [status-im.chat.views.message.options :as message-options] [status-im.chat.views.message.datemark :as message-datemark] [status-im.chat.views.message.message :as message] [status-im.chat.views.input.input :as input] @@ -123,6 +124,7 @@ (defview chat [] (letsubs [{:keys [group-chat public? input-text]} [:get-current-chat] show-bottom-info? [:get-current-chat-ui-prop :show-bottom-info?] + show-message-options? [:get-current-chat-ui-prop :show-message-options?] current-view [:get :view-id]] ;; this scroll-view is a hack that allows us to use on-blur and on-focus on Android ;; more details here: https://github.com/facebook/react-native/issues/11071 @@ -140,4 +142,6 @@ [input/container {:text-empty? (string/blank? input-text)}] (when show-bottom-info? [bottom-info/bottom-info-view]) + (when show-message-options? + [message-options/view]) [connectivity/error-view {:top (get platform/platform-specific :status-bar-default-height)}]]])) diff --git a/src/status_im/chat/styles/message/message.cljs b/src/status_im/chat/styles/message/message.cljs index dfd56de61e..e32ae99052 100644 --- a/src/status_im/chat/styles/message/message.cljs +++ b/src/status_im/chat/styles/message/message.cljs @@ -102,6 +102,25 @@ :android {:font-size 13} :ios {:font-size 14}}) +(def not-sent-view + (assoc delivery-view :opacity 1 + :margin-bottom 2 + :padding-top 2)) + +(def not-sent-text + (assoc delivery-text :color styles/color-red + :opacity 1 + :font-size 12 + :text-align :right + :padding-top 4)) + +(def not-sent-icon + {:padding-top 3 + :padding-left 3}) + +(def message-activity-indicator + {:padding-top 4}) + (defn text-message [{:keys [outgoing group-chat incoming-group]}] (merge style-message-text diff --git a/src/status_im/chat/styles/message/options.cljs b/src/status_im/chat/styles/message/options.cljs new file mode 100644 index 0000000000..35c79985e7 --- /dev/null +++ b/src/status_im/chat/styles/message/options.cljs @@ -0,0 +1,37 @@ +(ns status-im.chat.styles.message.options + (:require-macros [status-im.utils.styles :refer [defstyle defnstyle]]) + (:require [status-im.ui.components.styles :as styles] + [status-im.ui.components.colors :as colors] + [status-im.constants :as constants])) + +(defstyle row + {:flex-direction :row + :background-color :white + :align-items :center + :padding-horizontal 16 + :ios {:height 36} + :android {:height 36}}) + +(def title + {:padding-horizontal 16 + :padding-top 10 + :padding-bottom 10}) + +(def title-text + {:font-weight :bold + :font-size 14 + :letter-spacing -0.2 + :line-height 20}) + +(def label + {:padding-horizontal 16}) + +(def label-text + {:font-size 12}) + +(def icon + {:width 40 + :height 40 + :border-radius 20 + :align-items :center + :justify-content :center}) diff --git a/src/status_im/chat/views/bottom_info.cljs b/src/status_im/chat/views/bottom_info.cljs index c26efb110e..adb7adbc12 100644 --- a/src/status_im/chat/views/bottom_info.cljs +++ b/src/status_im/chat/views/bottom_info.cljs @@ -18,14 +18,14 @@ :friction 6 :tension 40})))) -(defn- overlay [{:keys [on-click-outside]} items] +(defn overlay [{:keys [on-click-outside]} items] [react/view styles/bottom-info-overlay [react/touchable-highlight {:on-press on-click-outside :style styles/overlay-highlight} [react/view nil]] items]) -(defn- container [height & _] +(defn container [height & _] (let [anim-value (anim/create-value 1) context {:to-value height :val anim-value} diff --git a/src/status_im/chat/views/message/message.cljs b/src/status_im/chat/views/message/message.cljs index 39108fefae..358bf26ae5 100644 --- a/src/status_im/chat/views/message/message.cljs +++ b/src/status_im/chat/views/message/message.cljs @@ -5,6 +5,8 @@ [status-im.ui.components.react :as react] [status-im.ui.components.animation :as animation] [status-im.ui.components.list-selection :as list-selection] + [status-im.ui.components.icons.vector-icons :as vector-icons] + [status-im.ui.components.action-sheet :as action-sheet] [status-im.commands.utils :as commands.utils] [status-im.chat.models.commands :as models.commands] [status-im.chat.models.message :as models.message] @@ -251,9 +253,30 @@ :font :default} (str "+ " (- delivery-statuses-count 3))])]])))) +(defn message-activity-indicator [] + [react/view style/message-activity-indicator + [react/activity-indicator {:animating true}]]) + +(defn message-not-sent-text [chat-id message-id] + [react/touchable-highlight {:on-press (fn [] (if platform/ios? + (action-sheet/show {:title (i18n/label :message-not-sent) + :options [{:label (i18n/label :resend-message) + :action #(re-frame/dispatch [:resend-message chat-id message-id])} + {:label (i18n/label :delete-message) + :destructive? true + :action #(re-frame/dispatch [:delete-message chat-id message-id])}]}) + (re-frame/dispatch + [:show-message-options {:chat-id chat-id + :message-id message-id}])))} + [react/view style/not-sent-view + [react/text {:style style/not-sent-text} + (i18n/message-status-label :not-sent)] + [react/view style/not-sent-icon + [vector-icons/icon :icons/warning {:color colors/red}]]]]) + (defn message-delivery-status - [{:keys [chat-id current-public-key user-statuses content]}] - (let [outgoing-status (or (get user-statuses current-public-key) :sending) + [{:keys [chat-id message-id current-public-key user-statuses content last-outgoing? outgoing message-type] :as message}] + (let [outgoing-status (or (get user-statuses current-public-key) :not-sent) delivery-status (get user-statuses chat-id) status (cond (and (= constants/console-chat-id chat-id) (not (console/commands-with-delivery-status (:command content)))) @@ -261,7 +284,14 @@ :else (or delivery-status outgoing-status))] - [text-status status])) + (case outgoing-status + :sending [message-activity-indicator] + :not-sent [message-not-sent-text chat-id message-id] + (when last-outgoing? + (if (= message-type :group-user-message) + [group-message-delivery-status message] + (when outgoing + [text-status status])))))) (defn- photo [from photo-path] [react/view @@ -293,7 +323,7 @@ (gfycat/generate-gfy from))])) ; TODO: We defensively generate the name for now, to be revisited when new protocol is defined (defn message-body - [{:keys [timestamp-str last-outgoing? last-in-group? message-type first-in-group? from outgoing group-chat username] :as message} content] + [{:keys [timestamp-str last-in-group? first-in-group? from outgoing username] :as message} content] [react/view (style/group-message-wrapper message) [react/view (style/message-body message) (when (not outgoing) @@ -308,11 +338,8 @@ [react/view {:style (style/timestamp-content-wrapper message)} content [message-timestamp timestamp-str]]]] - (when last-outgoing? - [react/view style/delivery-status - (if (= message-type :group-user-message) - [group-message-delivery-status message] - [message-delivery-status message])])]) + [react/view style/delivery-status + [message-delivery-status message]]]) (defn message-container-animation-logic [{:keys [to-value val callback]}] (fn [_] diff --git a/src/status_im/chat/views/message/options.cljs b/src/status_im/chat/views/message/options.cljs new file mode 100644 index 0000000000..6f164f97e6 --- /dev/null +++ b/src/status_im/chat/views/message/options.cljs @@ -0,0 +1,44 @@ +(ns status-im.chat.views.message.options + (:require-macros [status-im.utils.views :refer [defview]]) + (:require [re-frame.core :as re-frame] + [reagent.core :as reagent] + [clojure.string :as string] + [status-im.ui.components.react :as react] + [status-im.ui.components.colors :as colors] + [status-im.chat.views.bottom-info :as bottom-info] + [status-im.chat.styles.screen :as styles] + [status-im.chat.styles.message.options :as options.styles] + [status-im.i18n :as i18n] + [status-im.ui.components.animation :as anim] + [status-im.ui.components.list.views :as list] + [status-im.utils.core :as utils] + [status-im.utils.identicon :as identicon] + [status-im.ui.components.icons.vector-icons :as vector-icons])) + +(defn action-item [{:keys [label icon style on-press]}] + [react/touchable-highlight {:on-press on-press} + [react/view options.styles/row + [react/view + [vector-icons/icon icon style]] + [react/view (merge options.styles/label style) + [react/text {:style (merge options.styles/label-text style)} (i18n/label label)]]]]) + +(defn view [] + (let [{:keys [chat-id message-id]} @(re-frame/subscribe [:get-current-chat-ui-prop :message-options]) + close-message-options-fn #(re-frame/dispatch [:set-chat-ui-props {:show-message-options? false}])] + [bottom-info/overlay {:on-click-outside close-message-options-fn} + [bottom-info/container (* styles/item-height 2) + [react/view + [react/view options.styles/title + [react/text {:style options.styles/title-text} (i18n/label :message-not-sent)]] + [action-item {:label :resend-message + :icon :icons/refresh + :on-press #(do + (close-message-options-fn) + (re-frame/dispatch [:resend-message chat-id message-id]))}] + [action-item {:label :delete-message + :icon :icons/delete + :style {:color colors/red} + :on-press #(do + (close-message-options-fn) + (re-frame/dispatch [:delete-message chat-id message-id]))}]]]])) diff --git a/src/status_im/data_store/messages.cljs b/src/status_im/data_store/messages.cljs index 0e08e55ff9..55c816aa4a 100644 --- a/src/status_im/data_store/messages.cljs +++ b/src/status_im/data_store/messages.cljs @@ -91,12 +91,21 @@ message {:from (or from "anonymous") :received-timestamp (datetime/timestamp)}))))) +(defn delete + [message-id] + (when (data-store/exists? message-id) + (data-store/delete message-id))) (re-frame/reg-fx :data-store/save-message (fn [message] (async/go (async/>! core/realm-queue #(save message))))) +(re-frame/reg-fx + :data-store/delete-message + (fn [message-id] + (async/go (async/>! core/realm-queue #(delete message-id))))) + (defn update-message [{:keys [message-id] :as message}] (when-let [{:keys [chat-id]} (data-store/get-by-id message-id)] diff --git a/src/status_im/data_store/realm/messages.cljs b/src/status_im/data_store/realm/messages.cljs index 0e2ccf6051..c817abbffd 100644 --- a/src/status_im/data_store/realm/messages.cljs +++ b/src/status_im/data_store/realm/messages.cljs @@ -70,6 +70,12 @@ [message] (realm/save @realm/account-realm :message message true)) +(defn delete + [message-id] + (let [current-realm @realm/account-realm] + (when-let [message (realm/get-by-field current-realm :message :message-id message-id)] + (realm/delete current-realm message)))) + (defn delete-by-chat-id [chat-id] (let [current-realm @realm/account-realm] diff --git a/src/status_im/translations/en.cljs b/src/status_im/translations/en.cljs index 48d3ff4269..c929b953a7 100644 --- a/src/status_im/translations/en.cljs +++ b/src/status_im/translations/en.cljs @@ -99,6 +99,10 @@ :status-seen "Seen" :status-delivered "Delivered" :status-failed "Failed" + :status-not-sent "Not sent. Tap for options" + :message-not-sent "Message not sent" + :resend-message "Resend" + :delete-message "Delete message" ;;datetime :datetime-ago-format "{{number}} {{time-intervals}} {{ago}}" diff --git a/src/status_im/transport/message/v1/protocol.cljs b/src/status_im/transport/message/v1/protocol.cljs index 518dc83a25..641a4b459f 100644 --- a/src/status_im/transport/message/v1/protocol.cljs +++ b/src/status_im/transport/message/v1/protocol.cljs @@ -94,11 +94,9 @@ (send [this chat-id cofx] (send {:chat-id chat-id :payload this - :success-event [:update-message-status + :success-event [:transport/set-message-envelope-hash chat-id - (transport.utils/message-id this) - (get-in cofx [:db :current-public-key]) - :sent]} + (transport.utils/message-id this)]} cofx)) (receive [this chat-id signature cofx] {:dispatch [:chat-received-message/add (assoc (into {} this) diff --git a/src/status_im/transport/shh.cljs b/src/status_im/transport/shh.cljs index df648aff67..5f47b3328b 100644 --- a/src/status_im/transport/shh.cljs +++ b/src/status_im/transport/shh.cljs @@ -53,22 +53,22 @@ [{:keys [web3 whisper-message on-success on-error]}] (.. web3 -shh - (post (clj->js whisper-message) (fn [err resp] - (if-not err - (on-success resp) - (on-error err)))))) + (extPost (clj->js whisper-message) (fn [err resp] + (if-not err + (on-success resp) + (on-error err)))))) (re-frame/reg-fx :shh/post (fn [{:keys [web3 message success-event error-event] :or {error-event :protocol/send-status-message-error}}] - (post-message {:web3 web3 + (post-message {:web3 web3 :whisper-message (update message :payload (comp transport.utils/from-utf8 transit/serialize)) - :on-success (if success-event - #(re-frame/dispatch success-event) - #(log/debug :shh/post-success)) - :on-error #(re-frame/dispatch [error-event %])}))) + :on-success (if success-event + #(re-frame/dispatch (conj success-event %)) + #(log/debug :shh/post-success)) + :on-error #(re-frame/dispatch [error-event %])}))) ;; This event params contain a recipients key because it's a vector of map with public-key and topic keys. ;; the :shh/post event has public-key and topic keys at the top level of the args map. diff --git a/src/status_im/ui/components/icons/vector_icons.cljs b/src/status_im/ui/components/icons/vector_icons.cljs index b926c043ad..54322eabeb 100644 --- a/src/status_im/ui/components/icons/vector_icons.cljs +++ b/src/status_im/ui/components/icons/vector_icons.cljs @@ -82,7 +82,8 @@ :icons/refresh (components.svg/slurp-svg "./resources/icons/refresh.svg") :icons/newchat (components.svg/slurp-svg "./resources/icons/newchat.svg") :icons/logo (components.svg/slurp-svg "./resources/icons/logo.svg") - :icons/camera (components.svg/slurp-svg "./resources/icons/camera.svg")}) + :icons/camera (components.svg/slurp-svg "./resources/icons/camera.svg") + :icons/warning (components.svg/slurp-svg "./resources/icons/warning.svg")}) (defn normalize-property-name [n] (if (= n :icons/options) diff --git a/src/status_im/ui/screens/db.cljs b/src/status_im/ui/screens/db.cljs index 196f7a9952..dfe527308b 100644 --- a/src/status_im/ui/screens/db.cljs +++ b/src/status_im/ui/screens/db.cljs @@ -18,34 +18,35 @@ status-im.ui.screens.add-new.new-public-chat.db)) ;; initial state of app-db -(def app-db {:current-public-key nil - :status-module-initialized? (or platform/ios? js/goog.DEBUG) - :keyboard-height 0 - :accounts/accounts {} - :navigation-stack '() - :contacts/contacts {} - :qr-codes {} - :group/contact-groups {} - :group/selected-contacts #{} - :chats {} - :current-chat-id nil - :selected-participants #{} - :discoveries {} - :discover-search-tags #{} - :discover-current-dapp {} - :tags [] - :sync-state :done - :wallet.transactions constants/default-wallet-transactions - :wallet-selected-asset {} - :prices {} - :notifications {} - :network constants/default-network - :networks/networks constants/default-networks - :inbox/wnodes constants/default-wnodes - :inbox/password constants/inbox-password - :my-profile/editing? false - :transport/chats {} - :desktop/desktop {:tab-view-id :home}}) +(def app-db {:current-public-key nil + :status-module-initialized? (or platform/ios? js/goog.DEBUG) + :keyboard-height 0 + :accounts/accounts {} + :navigation-stack '() + :contacts/contacts {} + :qr-codes {} + :group/contact-groups {} + :group/selected-contacts #{} + :chats {} + :current-chat-id nil + :selected-participants #{} + :discoveries {} + :discover-search-tags #{} + :discover-current-dapp {} + :tags [] + :sync-state :done + :wallet.transactions constants/default-wallet-transactions + :wallet-selected-asset {} + :prices {} + :notifications {} + :network constants/default-network + :networks/networks constants/default-networks + :inbox/wnodes constants/default-wnodes + :inbox/password constants/inbox-password + :my-profile/editing? false + :transport/chats {} + :transport/message-envelopes {} + :desktop/desktop {:tab-view-id :home}}) ;;;;GLOBAL @@ -128,6 +129,8 @@ (spec/def :node/after-start (spec/nilable vector?)) (spec/def :node/after-stop (spec/nilable vector?)) +(spec/def ::message-envelopes (spec/nilable map?)) + (spec/def ::db (allowed-keys :opt [:contacts/contacts @@ -166,6 +169,7 @@ :browser/options :new/open-dapp :navigation/screen-params + :transport/message-envelopes :transport/chats :transport/discovery-filter :desktop/desktop] diff --git a/src/status_im/ui/screens/events.cljs b/src/status_im/ui/screens/events.cljs index 9298156877..73165c450b 100644 --- a/src/status_im/ui/screens/events.cljs +++ b/src/status_im/ui/screens/events.cljs @@ -277,6 +277,7 @@ [:initialize-browsers] [:initialize-debugging {:address address}] [:send-account-update-if-needed] + [:process-pending-messages] [:update-wallet] [:update-transactions] [:get-fcm-token] @@ -356,6 +357,8 @@ "node.stopped" [:status-node-stopped] "module.initialized" [:status-module-initialized] "jail.signal" (handle-jail-signal event) + "envelope.sent" [:signals/envelope-status (:hash event) :sent] + "envelope.expired" [:signals/envelope-status (:hash event) :not-sent] (log/debug "Event " type " not handled"))] (when to-dispatch {:dispatch to-dispatch}))))