This commit is contained in:
parent
a90dba04f9
commit
0cf452207e
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "status-desktop",
|
||||
"name": "Status",
|
||||
"version": "0.0.1",
|
||||
"main": "js/main.js"
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -102,6 +102,9 @@
|
|||
"tweetnacl": "0.14.5"
|
||||
}
|
||||
},
|
||||
"bignumber.js": {
|
||||
"version": "github:status-im/bignumber.js#cc066a0a3d6bfe0c436c9957f4ea8344bf963c89"
|
||||
},
|
||||
"block-stream": {
|
||||
"version": "0.0.9",
|
||||
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
|
||||
|
@ -513,6 +516,14 @@
|
|||
"verror": "1.10.0"
|
||||
}
|
||||
},
|
||||
"linkify-it": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-1.2.4.tgz",
|
||||
"integrity": "sha1-B3NSbDF8j9E71TTuHRgP+Iq/iBo=",
|
||||
"requires": {
|
||||
"uc.micro": "1.0.3"
|
||||
}
|
||||
},
|
||||
"loose-envify": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz",
|
||||
|
@ -861,6 +872,13 @@
|
|||
"prop-types": "15.6.0"
|
||||
}
|
||||
},
|
||||
"react-native-hyperlink": {
|
||||
"version": "git+https://github.com/flexsurfer/react-native-hyperlink.git#3cd0b0f6bd2cc7dc4ccefe6fbc18699b72f68219",
|
||||
"requires": {
|
||||
"linkify-it": "1.2.4",
|
||||
"react-native-web": "0.1.12"
|
||||
}
|
||||
},
|
||||
"react-native-web": {
|
||||
"version": "0.1.12",
|
||||
"resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.1.12.tgz",
|
||||
|
@ -1046,6 +1064,11 @@
|
|||
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz",
|
||||
"integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g=="
|
||||
},
|
||||
"uc.micro": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.3.tgz",
|
||||
"integrity": "sha1-ftUNXg+an7ClczeSWfKndFjVAZI="
|
||||
},
|
||||
"uid-number": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/uid-number/-/uid-number-0.0.6.tgz",
|
||||
|
@ -1077,18 +1100,13 @@
|
|||
}
|
||||
},
|
||||
"web3": {
|
||||
"version": "github:status-im/web3.js#17b13f26044e60ac824d1b97052bfad1be5af9cc",
|
||||
"version": "github:status-im/web3.js#aca66029d7ffac8ed2803b2fc7f0fec01e335ca3",
|
||||
"requires": {
|
||||
"bignumber.js": "github:status-im/bignumber.js#cc066a0a3d6bfe0c436c9957f4ea8344bf963c89",
|
||||
"crypto-js": "3.1.8",
|
||||
"utf8": "2.1.2",
|
||||
"xhr2": "0.1.4",
|
||||
"xmlhttprequest": "1.8.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"bignumber.js": {
|
||||
"version": "github:status-im/bignumber.js#cc066a0a3d6bfe0c436c9957f4ea8344bf963c89"
|
||||
}
|
||||
}
|
||||
},
|
||||
"whatwg-fetch": {
|
||||
|
|
15
package.json
15
package.json
|
@ -3,17 +3,18 @@
|
|||
"version": "0.0.1",
|
||||
"description": "Status Desktop (React Native Web and Electron)",
|
||||
"dependencies": {
|
||||
"react": "16.0.0",
|
||||
"react-dom": "16.0.0",
|
||||
"react-native-web": "0.1.12",
|
||||
"awesome-phonenumber": "^1.0.13",
|
||||
"chance": "1.0.4",
|
||||
"eccjs": "0.3.1",
|
||||
"emojilib": "^2.2.1",
|
||||
"homoglyph-finder": "^1.1.1",
|
||||
"identicon.js": "github:status-im/identicon.js",
|
||||
"awesome-phonenumber": "^1.0.13",
|
||||
"emojilib": "^2.2.1",
|
||||
"web3": "github:status-im/web3.js#status-develop",
|
||||
"status-nodejs": "git+https://github.com/status-im/status-nodejs.git"
|
||||
"react": "16.0.0",
|
||||
"react-dom": "16.0.0",
|
||||
"react-native-hyperlink": "git+https://github.com/flexsurfer/react-native-hyperlink.git",
|
||||
"react-native-web": "0.1.12",
|
||||
"status-nodejs": "git+https://github.com/status-im/status-nodejs.git",
|
||||
"web3": "github:status-im/web3.js#status-develop"
|
||||
},
|
||||
"license": "MPL-2.0",
|
||||
"repository": "https://github.com/status-im/status-electron"
|
||||
|
|
10
project.clj
10
project.clj
|
@ -30,12 +30,12 @@
|
|||
["cljsbuild" "once" "prod-front"]]
|
||||
|
||||
;; electron packager for production
|
||||
"desktop-app-osx" ["shell" "electron-packager" "./app/prod" "status-desktop" "--platform=darwin" "--arch=x64" "--electron-version=1.8.2-beta.3" "--extraResource=./node_modules" "--icon=assets/icon1024.icns"]
|
||||
"desktop-app-linux" ["shell" "electron-packager" "./app/prod" "status-desktop" "--platform=linux" "--arch=x64" "--electron-version=1.8.2-beta.3" "--extraResource=./node_modules" "--icon=assets/icon1024.png"]
|
||||
"desktop-app-osx" ["shell" "electron-packager" "./app/prod" "Status" "--platform=darwin" "--arch=x64" "--electron-version=1.8.2-beta.3" "--extraResource=./node_modules" "--icon=assets/icon1024.icns"]
|
||||
"desktop-app-linux" ["shell" "electron-packager" "./app/prod" "Status" "--platform=linux" "--arch=x64" "--electron-version=1.8.2-beta.3" "--extraResource=./node_modules" "--icon=assets/icon1024.png"]
|
||||
|
||||
"desktop-app-store" ["shell" "electron-packager" "./app/prod" "status-desktop" "--platform=mas" "--arch=x64" "--electron-version=1.8.2-beta.3" "--extraResource=./node_modules"]
|
||||
"desktop-app-win64" ["shell" "cmd.exe" "/c" "electron-packager" "./app/prod" "status-desktop" "--platform=win32" "--arch=x64" "--electron-version=1.8.2-beta.3" "--extraResource=./node_modules"]
|
||||
"desktop-app-win32" ["shell" "cmd.exe" "/c" "electron-packager" "./app/prod" "status-desktop" "--platform=win32" "--arch=ia32" "--electron-version=1.8.2-beta.3" "--extraResource=./node_modules"]}
|
||||
"desktop-app-store" ["shell" "electron-packager" "./app/prod" "Status" "--platform=mas" "--arch=x64" "--electron-version=1.8.2-beta.3" "--extraResource=./node_modules"]
|
||||
"desktop-app-win64" ["shell" "cmd.exe" "/c" "electron-packager" "./app/prod" "Status" "--platform=win32" "--arch=x64" "--electron-version=1.8.2-beta.3" "--extraResource=./node_modules"]
|
||||
"desktop-app-win32" ["shell" "cmd.exe" "/c" "electron-packager" "./app/prod" "Status" "--platform=win32" "--arch=ia32" "--electron-version=1.8.2-beta.3" "--extraResource=./node_modules"]}
|
||||
|
||||
:hooks [leiningen.cljsbuild]
|
||||
:cljsbuild {:builds {:dev-main {:source-paths ["src"]
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
(.on app "ready"
|
||||
(fn []
|
||||
|
||||
(reset! *win* (BrowserWindow. (clj->js {:width 1200 :height 800 :icon (.resolve path (js* "__dirname") "../status.icns")})))
|
||||
(reset! *win* (BrowserWindow. (clj->js {:width 1200 :height 800})))
|
||||
|
||||
;; when no optimize comment out
|
||||
(.loadURL @*win* (str "file://" (.resolve path (js* "__dirname") "../index.html")))
|
||||
|
@ -50,14 +50,15 @@
|
|||
|
||||
(.on ipcMain "StartNode"
|
||||
(fn [event config]
|
||||
(let [config (.GenerateConfig status-go (.resolve path (js* "__dirname") "../ethereum") 3 0)
|
||||
(let [app-path (.getPath app "userData")
|
||||
config (.GenerateConfig status-go (str app-path "/ethereum") 3 0)
|
||||
config' (.parse js/JSON config)
|
||||
_ (set! (.-LogLevel config') "INFO")
|
||||
_ (set! (.-LogFile config') (.resolve path (js* "__dirname") "../node.log"))
|
||||
_ (set! (.-LogFile config') (str app-path "/node.log"))
|
||||
_ (set! (.-Enabled (.-UpstreamConfig config')) true)
|
||||
config'' (.stringify js/JSON config')
|
||||
res (.StartNode status-go config'')]
|
||||
(.log js/console (str "Node started at " (.resolve path (js* "__dirname") "../ethereum")))
|
||||
(.log js/console (str "Node started at " (str app-path "/ethereum")))
|
||||
(set! (.-returnValue event) (str "Config " config'' " Node result: " res)))))
|
||||
|
||||
(.on ipcMain "CreateAccount"
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
{ :role "quit"}]})))
|
||||
(.append menu
|
||||
(MenuItem.
|
||||
(clj->js {:label "Status" :submenu [{ :label "Logs" :click #(re-frame/dispatch [:logs]) :accelerator "CmdOrCtrl+L"}]})))
|
||||
(clj->js {:label "Dev" :submenu [{ :label "Logs" :click #(re-frame/dispatch [:logs]) :accelerator "CmdOrCtrl+L"}]})))
|
||||
(.setApplicationMenu Menu menu))
|
||||
(mount-root)
|
||||
(re-frame/dispatch-sync [:initialize-app]))
|
||||
|
|
|
@ -8,11 +8,21 @@
|
|||
|
||||
;;;; DESKTOP
|
||||
|
||||
(def audio {:notif01 (js/Audio. (str js/__dirname "/resources/notif01.mp3"))
|
||||
:notif02 (js/Audio. (str js/__dirname "/resources/notif02.mp3"))
|
||||
:notif03 (js/Audio. (str js/__dirname "/resources/notif03.mp3"))
|
||||
:notif04 (js/Audio. (str js/__dirname "/resources/notif04.mp3"))
|
||||
:notif05 (js/Audio. (str js/__dirname "/resources/notif05.mp3"))
|
||||
:notif06 (js/Audio. (str js/__dirname "/resources/notif06.mp3"))
|
||||
:notif07 (js/Audio. (str js/__dirname "/resources/notif07.mp3"))
|
||||
:notif08 (js/Audio. (str js/__dirname "/resources/notif08.mp3"))})
|
||||
|
||||
(re-frame/reg-fx
|
||||
:send-desktop-notification
|
||||
(fn [{:keys [content from]}]
|
||||
(fn [{:keys [content from sound]}]
|
||||
(when-not (.hasFocus js/document)
|
||||
(js/Notification. from (clj->js {:body content})))))
|
||||
(when sound (.play (get audio sound)))
|
||||
(js/Notification. from (clj->js {:body content :silent true})))))
|
||||
|
||||
;;;; old events
|
||||
|
||||
|
@ -100,8 +110,8 @@
|
|||
|
||||
(re-frame/reg-fx
|
||||
:update-message
|
||||
(fn [message]))
|
||||
;(msg-store/update-message message)))
|
||||
(fn [message]
|
||||
(storage/update-message message)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:save-message
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
[status-desktop-front.web3-provider :as web3-provider]
|
||||
[status-im.protocol.handlers :as protocol.handlers]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.utils.handlers :as handlers]))
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-desktop-front.storage :as storage]))
|
||||
|
||||
;;;; COFX
|
||||
|
||||
|
@ -15,7 +16,7 @@
|
|||
(re-frame/reg-cofx
|
||||
::protocol.handlers/get-chat-groups
|
||||
(fn [coeffects _]
|
||||
(assoc coeffects :groups [])))
|
||||
(assoc coeffects :groups (storage/get-active-group-chats))))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
::protocol.handlers/get-pending-messages
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
(ns status-desktop-front.storage
|
||||
(:require [alandipert.storage-atom :refer [local-storage]]
|
||||
[status-im.data-store.messages :as data-store.messages]
|
||||
[status-im.utils.random :as random]))
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.constants :as constants]))
|
||||
;;;; ACCOUNTS
|
||||
|
||||
;; I would love to have something similar in status-react instead realm
|
||||
|
@ -24,7 +25,7 @@
|
|||
;;;; CONTACTS
|
||||
|
||||
(defn save-contact [contact]
|
||||
(swap! (:contacts @account) assoc (:whisper-identity contact) contact))
|
||||
(swap! (:contacts @account) update-in (:whisper-identity contact) merge contact))
|
||||
|
||||
(defn save-contacts [contacts]
|
||||
(mapv save-contact contacts))
|
||||
|
@ -59,6 +60,19 @@
|
|||
(> timestamp removed-from-at)
|
||||
(> timestamp added-at))))
|
||||
|
||||
(defn- groups [active?]
|
||||
(filter #(and (:group-chat %) (= (:is-active %) active?)) (get-all-chats)))
|
||||
|
||||
(defn get-active-group-chats []
|
||||
(map (fn [{:keys [chat-id public-key private-key public?]}]
|
||||
(let [group {:group-id chat-id
|
||||
:public? public?}]
|
||||
(if (and public-key private-key)
|
||||
(assoc group :keypair {:private private-key
|
||||
:public public-key})
|
||||
group)))
|
||||
(groups true)))
|
||||
|
||||
;;;; MESSAGE
|
||||
|
||||
(defn save-message [{:keys [message-id content] :as message}]
|
||||
|
@ -69,11 +83,24 @@
|
|||
:timestamp (random/timestamp)})]
|
||||
(swap! (:messages @account) assoc message-id message')))
|
||||
|
||||
(defn update-message [{:keys [message-id content] :as message}]
|
||||
(swap! (:messages @account) update-in [message-id] merge message))
|
||||
|
||||
(defn get-message-by-id [message-id]
|
||||
(get @(:messages @account) message-id))
|
||||
|
||||
(defn get-messages-by-chat-id [chat-id]
|
||||
(filter #(= chat-id (:chat-id %)) (vals @(:messages @account))))
|
||||
(defn get-messages-by-chat-id
|
||||
([chat-id]
|
||||
(get-messages-by-chat-id chat-id 0))
|
||||
([chat-id from]
|
||||
(let [chats (sort-by :timestamp > (filter #(= chat-id (:chat-id %)) (vals @(:messages @account))))
|
||||
to (+ from constants/default-number-of-messages)]
|
||||
(if (< to (count chats))
|
||||
;;TODO yeah i know i know
|
||||
(subvec (into [] chats)
|
||||
from
|
||||
to)
|
||||
chats))))
|
||||
|
||||
(defn get-last-message [chat-id]
|
||||
(->> (vals @(:messages @account))
|
||||
|
|
|
@ -4,7 +4,14 @@
|
|||
[status-desktop-front.ui.components.icons :as icons]
|
||||
[status-im.ui.components.common.styles :as styles]
|
||||
[status-im.ui.components.action-button.styles :as st]
|
||||
[status-im.ui.components.styles :as common]))
|
||||
[status-im.ui.components.styles :as common]
|
||||
[status-im.ui.components.checkbox.styles :as checkbox.styles]))
|
||||
|
||||
(defn checkbox [{:keys [on-value-change checked?]}]
|
||||
[react/touchable-highlight {:style checkbox.styles/wrapper :on-press #(do (when on-value-change (on-value-change (not checked?))))}
|
||||
[react/view {:style (checkbox.styles/icon-check-container checked?)}
|
||||
(when checked?
|
||||
[icons/icon :icons/ok {:style checkbox.styles/check-icon}])]])
|
||||
|
||||
;; TODO copy-pate with minimum modifications of status-react components
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
(ns status-desktop-front.ui.screens.chat.profile.views
|
||||
(:require [status-desktop-front.react-native-web :as react]
|
||||
[status-im.ui.screens.profile.styles :as styles]
|
||||
[status-desktop-front.ui.components.views :as components]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.utils.utils :refer [hash-tag?]]
|
||||
[clojure.string :as string]
|
||||
[cljs.nodejs :as nodejs])
|
||||
|
@ -76,6 +78,36 @@
|
|||
[profile-info-address-item contact]
|
||||
[profile-info-public-key-item public-key contact]])
|
||||
|
||||
(views/defview sound-view [sound label sound-name]
|
||||
[react/view {:style (merge styles/profile-setting-item {:height 30})}
|
||||
[react/text {:style styles/profile-setting-text} label]
|
||||
[react/view {:style {:flex 1}}]
|
||||
[components/checkbox {:on-value-change
|
||||
#(re-frame/dispatch [:set-in [:desktop :notifications :sound] sound-name])
|
||||
:checked?
|
||||
(= sound sound-name)}]])
|
||||
|
||||
(views/defview notifications []
|
||||
(views/letsubs [notifications-enabled? [:get-in [:desktop :notifications :enabled?]]
|
||||
sound [:get-in [:desktop :notifications :sound]]]
|
||||
[react/view
|
||||
[react/view {:style styles/profile-setting-item}
|
||||
[react/text {:style styles/profile-setting-text} "Notifications"]
|
||||
[react/view {:style {:flex 1}}]
|
||||
[components/checkbox {:on-value-change
|
||||
#(re-frame/dispatch [:set-in [:desktop :notifications :enabled?] %])
|
||||
:checked?
|
||||
notifications-enabled?}]]
|
||||
[sound-view sound "Sound 1" :notif01]
|
||||
[sound-view sound "Sound 2" :notif02]
|
||||
[sound-view sound "Sound 3" :notif03]
|
||||
[sound-view sound "Sound 4" :notif04]
|
||||
[sound-view sound "Sound 5" :notif05]
|
||||
[sound-view sound "Sound 6" :notif06]
|
||||
[sound-view sound "Sound 7" :notif07]
|
||||
[sound-view sound "Sound 8" :notif08]]))
|
||||
|
||||
|
||||
(views/defview profile []
|
||||
(views/letsubs [{:keys [status public-key] :as current-account} [:get-current-account]]
|
||||
[react/view {:style (merge styles/profile {:background-color :white})}
|
||||
|
@ -84,4 +116,5 @@
|
|||
[profile-badge current-account]
|
||||
[profile-status status true]]
|
||||
[react/view {:style styles/profile-info-container}
|
||||
[my-profile-info current-account]]]]))
|
||||
[my-profile-info current-account]]
|
||||
[notifications]]]))
|
|
@ -6,20 +6,23 @@
|
|||
[status-desktop-front.ui.components.icons :as icons]
|
||||
[status-desktop-front.web3-provider :as protocol]
|
||||
[clojure.string :as string]
|
||||
[status-im.chat.views.message.message :as message.views]
|
||||
[status-im.chat.styles.message.message :as message.style]
|
||||
[status-im.utils.gfycat.core :as gfycat.core]
|
||||
[status-im.utils.gfycat.core :as gfycat]
|
||||
[status-im.ui.screens.chats-list.styles :as chats-list.styles]
|
||||
[status-im.constants :as constants])
|
||||
[status-im.constants :as constants]
|
||||
[status-desktop-front.react-native-hyperlink :as rn-hl])
|
||||
(:require-macros [status-im.utils.views :as views]))
|
||||
|
||||
(views/defview message-author-name [{:keys [outgoing from] :as message}]
|
||||
(views/letsubs [current-account [:get-current-account]
|
||||
incoming-name [:contact-name-by-identity from]]
|
||||
(when-let [name (if outgoing
|
||||
(:name current-account)
|
||||
(or incoming-name "Unknown contact"))]
|
||||
[react/text {:style message.style/author} name])))
|
||||
incoming-name [:contact-name-by-identity from]]
|
||||
(if outgoing
|
||||
[react/text {:style message.style/author} (:name current-account)]
|
||||
(let [name (or incoming-name (gfycat/generate-gfy from))]
|
||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:show-contact-dialog from name (boolean incoming-name)])}
|
||||
[react/text {:style message.style/author} name]]))))
|
||||
|
||||
(defn message [text me? {:keys [outgoing message-id chat-id message-status user-statuses
|
||||
from current-public-key content-type group-chat] :as message}]
|
||||
|
@ -36,90 +39,115 @@
|
|||
:message-id message-id}]))
|
||||
:reagent-render
|
||||
(fn []
|
||||
[react/view {:style (merge {:padding-bottom 8}
|
||||
(if me?
|
||||
{:align-items :flex-end
|
||||
:padding-left 90
|
||||
:padding-right 60}
|
||||
{:align-items :flex-start
|
||||
:padding-left 60
|
||||
:padding-right 90}))}
|
||||
[react/view {:style (merge
|
||||
{:padding-bottom 8}
|
||||
(if me?
|
||||
{:align-items :flex-end
|
||||
:padding-left 90
|
||||
:padding-right 60}
|
||||
{:align-items :flex-start
|
||||
:padding-left 60
|
||||
:padding-right 90}))}
|
||||
[react/view {:style {:padding 12 :background-color :white :border-radius 8}}
|
||||
(when group-chat [message-author-name message])
|
||||
[react/text
|
||||
text]]])})))
|
||||
[rn-hl/hyperlink {:linkStyle {:color "#2980b9"} :on-press #(re-frame/dispatch [:show-link-dialog %1])}
|
||||
[react/text
|
||||
text]]]])})))
|
||||
|
||||
(views/defview messages-view [{:keys [chat-id group-chat]}]
|
||||
(let [scroll-ref (atom nil)
|
||||
messages (re-frame/subscribe [:get-chat-messages chat-id])
|
||||
current-public-key (re-frame/subscribe [:get-current-public-key])]
|
||||
[react/view {:style {:flex 1 :background-color "#eef2f5"}}
|
||||
[react/scroll-view {:onContentSizeChange #(.scrollToEnd @scroll-ref) :ref #(reset! scroll-ref %)}
|
||||
[react/view {:style {:padding-vertical 60}}
|
||||
(for [[index {:keys [from content message-id] :as message-obj}] (map-indexed vector (reverse @messages))]
|
||||
^{:key message-id} [message content (= from @current-public-key) (assoc message-obj :group-chat group-chat)])]]]))
|
||||
(views/letsubs [chat-id* (atom nil)
|
||||
scroll-ref (atom nil)
|
||||
scroll-timer (atom nil)
|
||||
scroll-height (atom nil)]
|
||||
(let [_ (when (or (not @chat-id*) (not= @chat-id* chat-id))
|
||||
(reset! chat-id* chat-id)
|
||||
(println "dirty hack")
|
||||
(js/setTimeout #(when scroll-ref (.scrollToEnd @scroll-ref)) 400))
|
||||
messages (re-frame/subscribe [:get-chat-messages chat-id])
|
||||
current-public-key (re-frame/subscribe [:get-current-public-key])]
|
||||
[react/view {:style {:flex 1 :background-color "#eef2f5"}}
|
||||
[react/scroll-view {:scrollEventThrottle 16
|
||||
:on-scroll (fn [e]
|
||||
(let [ne (.-nativeEvent e)
|
||||
y (.-y (.-contentOffset ne))]
|
||||
(when (zero? y)
|
||||
(when @scroll-timer (js/clearTimeout @scroll-timer))
|
||||
(reset! scroll-timer (js/setTimeout #(re-frame/dispatch [:load-more-messages]) 300)))
|
||||
(reset! scroll-height (+ y (.-height (.-layoutMeasurement ne))))))
|
||||
:on-content-size-change #(when (or (not @scroll-height) (< (- %2 @scroll-height) 500))
|
||||
(.scrollToEnd @scroll-ref))
|
||||
:ref #(reset! scroll-ref %)}
|
||||
[react/view {:style {:padding-vertical 60}}
|
||||
(for [[index {:keys [from content message-id] :as message-obj}] (map-indexed vector (reverse @messages))]
|
||||
^{:key message-id} [message content (= from @current-public-key) (assoc message-obj :group-chat group-chat)])]]])))
|
||||
|
||||
(views/defview status-view []
|
||||
[react/view {:style {:flex 1 :background-color "#eef2f5" :align-items :center :justify-content :center}}
|
||||
[react/view {:style {:flex 1 :background-color "#eef2f5" :align-items :center :justify-content :center}}
|
||||
[react/text {:style {:font-size 18 :color "#939ba1"}}
|
||||
"Status.im"]])
|
||||
|
||||
(views/defview toolbar-chat-view []
|
||||
(views/letsubs [name [:chat :name]
|
||||
chat-id [:get-current-chat-id]
|
||||
(views/letsubs [name [:chat :name]
|
||||
chat-id [:get-current-chat-id]
|
||||
pending-contact? [:current-contact :pending?]
|
||||
public-key [:chat :public-key]]
|
||||
public-key [:chat :public-key]]
|
||||
(let [chat-name (if (string/blank? name)
|
||||
(gfycat.core/generate-gfy public-key)
|
||||
(or name;(get-contact-translated chat-id :name name)
|
||||
"Chat name"))];(label :t/chat-name)))]
|
||||
(or name ;(get-contact-translated chat-id :name name)
|
||||
"Chat name"))] ;(label :t/chat-name)))]
|
||||
[react/view {:style {:height 64 :align-items :center :padding-horizontal 11 :justify-content :center}}
|
||||
[react/text {:style {:font-size 16 :color :black :font-weight "600"}}
|
||||
chat-name]
|
||||
(when pending-contact?
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch [:add-pending-contact chat-id])}
|
||||
[react/view ;style/add-contact
|
||||
[react/view ;style/add-contact
|
||||
[react/text {:style {:font-size 14 :color "#939ba1" :margin-top 3}}
|
||||
"Add to contacts"]]])])))
|
||||
;[react/text {:style {:font-size 14 :color "#939ba1" :margin-top 3}}
|
||||
;"Contact status not implemented"]])))
|
||||
;[react/text {:style {:font-size 14 :color "#939ba1" :margin-top 3}}
|
||||
;"Contact status not implemented"]])))
|
||||
|
||||
(views/defview chat-text-input []
|
||||
(views/letsubs [input-text [:chat :input-text]
|
||||
inp-ref (atom nil)]
|
||||
[react/view {:style {:height 90 :margin-horizontal 16 :margin-bottom 16 :background-color :white :border-radius 12
|
||||
:box-shadow "0 0.5px 4.5px 0 rgba(0, 0, 0, 0.04)"}}
|
||||
[react/view {:style {:flex-direction :row :margin-horizontal 16 :margin-top 16 :flex 1 :margin-bottom 16}}
|
||||
[react/view {:style {:flex 1}}
|
||||
[react/text-input {:default-value (or input-text "")
|
||||
:placeholder "Type a message..."
|
||||
:auto-focus true
|
||||
:multiline true
|
||||
:blur-on-submit true
|
||||
:style {:flex 1}
|
||||
:ref #(reset! inp-ref %)
|
||||
:on-key-press (fn [e]
|
||||
(let [native-event (.-nativeEvent e)
|
||||
key (.-key native-event)]
|
||||
(when (= key "Enter")
|
||||
(js/setTimeout #(do
|
||||
(.clear @inp-ref)
|
||||
(.focus @inp-ref)) 200)
|
||||
(re-frame/dispatch [:send-current-message]))))
|
||||
:on-change (fn [e]
|
||||
(let [native-event (.-nativeEvent e)
|
||||
text (.-text native-event)]
|
||||
(re-frame/dispatch [:set-chat-input-text text])))}]]
|
||||
[react/touchable-highlight {:on-press (fn []
|
||||
(js/setTimeout #(do (.clear @inp-ref)(.focus @inp-ref)) 200)
|
||||
(re-frame/dispatch [:send-current-message]))}
|
||||
[react/view {:style {:margin-left 16 :width 30 :height 30 :border-radius 15 :background-color "#eef2f5" :align-items :center
|
||||
:justify-content :center}}
|
||||
[icons/icon :icons/dropdown-up]]]]]))
|
||||
|
||||
(views/defview chat-view []
|
||||
(views/letsubs [current-chat [:get-current-chat]
|
||||
input-text [:chat :input-text]
|
||||
inp-ref (atom nil)]
|
||||
(views/letsubs [current-chat [:get-current-chat]]
|
||||
[react/view {:style {:flex 1 :background-color "#eef2f5"}}
|
||||
[toolbar-chat-view]
|
||||
[react/view {:style {:height 1 :background-color "#e8ebec" :margin-horizontal 16}}]
|
||||
[messages-view current-chat]
|
||||
[react/view {:style {:height 90 :margin-horizontal 16 :margin-bottom 16 :background-color :white :border-radius 12
|
||||
:box-shadow "0 0.5px 4.5px 0 rgba(0, 0, 0, 0.04)"}}
|
||||
[react/view {:style {:flex-direction :row :margin-horizontal 16 :margin-top 16 :flex 1 :margin-bottom 16}}
|
||||
[react/view {:style {:flex 1}}
|
||||
[react/text-input {:value (or input-text "")
|
||||
:placeholder "Type a message..."
|
||||
:auto-focus true
|
||||
:multiline true
|
||||
:blur-on-submit true
|
||||
:style {:flex 1}
|
||||
:ref #(reset! inp-ref %)
|
||||
:on-key-press (fn [e]
|
||||
(let [native-event (.-nativeEvent e)
|
||||
key (.-key native-event)]
|
||||
(when (= key "Enter")
|
||||
(js/setTimeout #(.focus @inp-ref) 200)
|
||||
(re-frame/dispatch [:send-current-message]))))
|
||||
:on-change (fn [e]
|
||||
(let [native-event (.-nativeEvent e)
|
||||
text (.-text native-event)]
|
||||
(re-frame/dispatch [:set-chat-input-text text])))}]]
|
||||
[react/touchable-highlight {:on-press (fn []
|
||||
(js/setTimeout #(.focus @inp-ref) 200)
|
||||
(re-frame/dispatch [:send-current-message]))}
|
||||
[react/view {:style {:margin-left 16 :width 30 :height 30 :border-radius 15 :background-color "#eef2f5" :align-items :center
|
||||
:justify-content :center}}
|
||||
[icons/icon :icons/dropdown-up]]]]]]))
|
||||
[chat-text-input]]))
|
||||
|
||||
|
||||
(views/defview new-contact []
|
||||
(views/letsubs [new-contact-identity [:get :contacts/new-identity]
|
||||
|
@ -151,6 +179,7 @@
|
|||
[react/view {:style {:height 90 :margin-horizontal 16 :margin-bottom 16 :background-color :white :border-radius 12
|
||||
:box-shadow "0 0.5px 4.5px 0 rgba(0, 0, 0, 0.04)"}}
|
||||
[react/view {:style {:flex-direction :row :margin-horizontal 16 :margin-top 16}}
|
||||
[react/text "#"]
|
||||
[react/view {:style {:flex 1}}
|
||||
[react/text-input {:placeholder "topic"
|
||||
:on-change (fn [e]
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
status-desktop-front.override.login
|
||||
status-desktop-front.override.account
|
||||
status-desktop-front.override.contacts
|
||||
status-desktop-front.override.recieve-message))
|
||||
status-desktop-front.override.recieve-message
|
||||
status-desktop-front.ui.screens.chat.events))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:create-desktop-account
|
||||
|
|
Loading…
Reference in New Issue