Link preview generation
Signed-off-by: Volodymyr Kozieiev <vkjr.sp@gmail.com>
This commit is contained in:
parent
27ad8f07c3
commit
f99b2aa401
|
@ -1349,7 +1349,6 @@ class StatusModule extends ReactContextBaseJavaModule implements LifecycleEventL
|
|||
StatusThreadPoolExecutor.getInstance().execute(r);
|
||||
}
|
||||
|
||||
|
||||
@ReactMethod
|
||||
public void getNodesFromContract(final String rpcEndpoint, final String contractAddress, final Callback callback) {
|
||||
Log.d(TAG, "getNodesFromContract");
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
|
@ -0,0 +1,58 @@
|
|||
(ns status-im.chat.models.link-preview
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.multiaccounts.update.core :as multiaccounts.update]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(fx/defn enable
|
||||
{:events [::enable]}
|
||||
[{{:keys [multiaccount]} :db :as cofx} site enabled?]
|
||||
(fx/merge cofx
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:link-previews-enabled-sites
|
||||
(if enabled?
|
||||
(conj (get multiaccount :link-previews-enabled-sites #{}) site)
|
||||
(disj (get multiaccount :link-previews-enabled-sites #{}) site))
|
||||
{})))
|
||||
|
||||
(fx/defn load-link-preview-data
|
||||
{:events [::load-link-preview-data]}
|
||||
[cofx link]
|
||||
(fx/merge cofx
|
||||
{::json-rpc/call [{:method (json-rpc/call-ext-method "getLinkPreviewData")
|
||||
:params [link]
|
||||
:on-success #(re-frame/dispatch [::cache-link-preview-data link %])
|
||||
:on-error #(log/error "Can't get preview data for " link)}]}))
|
||||
|
||||
(fx/defn cache-link-preview-data
|
||||
{:events [::cache-link-preview-data]}
|
||||
[{{:keys [multiaccount]} :db :as cofx} site {:keys [error] :as data}]
|
||||
(when-not error
|
||||
(multiaccounts.update/optimistic
|
||||
cofx
|
||||
:link-previews-cache
|
||||
(assoc (get multiaccount :link-previews-cache {}) site data))))
|
||||
|
||||
(fx/defn should-suggest-link-preview
|
||||
{:events [::should-suggest-link-preview]}
|
||||
[{:keys [db] :as cofx} enabled?]
|
||||
(multiaccounts.update/multiaccount-update
|
||||
cofx
|
||||
:link-preview-request-enabled (boolean enabled?)
|
||||
{}))
|
||||
|
||||
(fx/defn request-link-preview-whitelist
|
||||
[_]
|
||||
{::json-rpc/call [{:method (json-rpc/call-ext-method "getLinkPreviewWhitelist")
|
||||
:params []
|
||||
:on-success #(re-frame/dispatch [::link-preview-whitelist-received %])
|
||||
:on-error #(log/error "Failed to get link preview whitelist")}]})
|
||||
|
||||
(fx/defn save-link-preview-whitelist
|
||||
{:events [::link-preview-whitelist-received]}
|
||||
[cofx whitelist]
|
||||
(fx/merge cofx
|
||||
(multiaccounts.update/multiaccount-update
|
||||
:link-previews-whitelist whitelist {})))
|
||||
|
|
@ -124,7 +124,9 @@
|
|||
:currency :usd
|
||||
:appearance 0
|
||||
:log-level config/log-level
|
||||
:webview-allow-permission-requests? false})
|
||||
:webview-allow-permission-requests? false
|
||||
:link-previews-enabled-sites #{}
|
||||
:link-preview-request-enabled true})
|
||||
|
||||
(defn default-visible-tokens [chain]
|
||||
(get-in default-multiaccount [:wallet/visible-tokens chain]))
|
||||
|
|
|
@ -37,10 +37,11 @@
|
|||
:ens-name (:ensName message)
|
||||
:line-count (:lineCount message)
|
||||
:parsed-text (:parsedText message)
|
||||
:links (:links message)
|
||||
:rtl? (:rtl message)
|
||||
:response-to (:responseTo message)}
|
||||
:outgoing (boolean (:outgoingStatus message)))
|
||||
(dissoc :ensName :chatId :text :rtl :responseTo :image :sticker :lineCount :parsedText)))
|
||||
(dissoc :ensName :chatId :text :rtl :responseTo :image :sticker :lineCount :parsedText :links)))
|
||||
|
||||
(defn update-outgoing-status-rpc [message-id status]
|
||||
{::json-rpc/call [{:method (json-rpc/call-ext-method "updateMessageOutgoingStatus")
|
||||
|
|
|
@ -17,7 +17,8 @@
|
|||
:parsed-text "parsed-text"
|
||||
:rtl? false
|
||||
:image nil
|
||||
:response-to "a"}
|
||||
:response-to "a"
|
||||
:links nil}
|
||||
:whisper-timestamp 1
|
||||
:outgoing-status :sending
|
||||
:command-parameters nil
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
(update :pinned-mailservers rpc->pinned-mailservers)
|
||||
(update :stickers/packs-installed rpc->stickers-packs)
|
||||
(update :stickers/packs-pending set)
|
||||
(update :link-previews-enabled-sites set)
|
||||
(update :custom-bootnodes rpc->custom-bootnodes)
|
||||
(update :custom-bootnodes-enabled? rpc->custom-bootnodes)
|
||||
(update :currency keyword)))
|
||||
|
|
|
@ -81,6 +81,8 @@
|
|||
"wakuext_sendEmojiReaction" {}
|
||||
"wakuext_sendEmojiReactionRetraction" {}
|
||||
"wakuext_emojiReactionsByChatID" {}
|
||||
"wakuext_getLinkPreviewWhitelist" {}
|
||||
"wakuext_getLinkPreviewData" {}
|
||||
;;TODO not used anywhere?
|
||||
"wakuext_deleteChat" {}
|
||||
"wakuext_saveContact" {}
|
||||
|
|
|
@ -29,7 +29,8 @@
|
|||
[status-im.wallet.prices :as prices]
|
||||
[status-im.acquisition.core :as acquisition]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.data-store.invitations :as data-store.invitations]))
|
||||
[status-im.data-store.invitations :as data-store.invitations]
|
||||
[status-im.chat.models.link-preview :as link-preview]))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::login
|
||||
|
@ -217,7 +218,8 @@
|
|||
(mobile-network/on-network-status-change)
|
||||
(get-group-chat-invitations)
|
||||
(logging/set-log-level (:log-level multiaccount))
|
||||
(multiaccounts/switch-preview-privacy-mode-flag))))
|
||||
(multiaccounts/switch-preview-privacy-mode-flag)
|
||||
(link-preview/request-link-preview-whitelist))))
|
||||
|
||||
(defn get-new-auth-method [auth-method save-password?]
|
||||
(when save-password?
|
||||
|
@ -282,6 +284,7 @@
|
|||
:mailserver-topics {}
|
||||
:default-mailserver true})
|
||||
(multiaccounts/switch-preview-privacy-mode-flag)
|
||||
(link-preview/request-link-preview-whitelist)
|
||||
(logging/set-log-level (:log-level multiaccount)))))
|
||||
|
||||
(defn- keycard-setup? [cofx]
|
||||
|
|
|
@ -34,6 +34,8 @@
|
|||
:dapp-store (js/require "../resources/images/ui/dapp-store.png")
|
||||
:ens-header (js/require "../resources/images/ui/ens-header.png")
|
||||
:ens-header-dark (js/require "../resources/images/ui/ens-header-dark.png")
|
||||
:unfurl (js/require "../resources/images/ui/unfurl.png")
|
||||
:unfurl-dark (js/require "../resources/images/ui/unfurl-dark.png")
|
||||
:new-chat-header (js/require "../resources/images/ui/new-chat-header.png")
|
||||
:onboarding-phone (js/require "../resources/images/ui/onboarding-phone.png")
|
||||
:theme-dark (js/require "../resources/images/ui/theme-dark.png")
|
||||
|
|
|
@ -2345,6 +2345,32 @@
|
|||
(fn [manage]
|
||||
(not-any? :error (vals manage))))
|
||||
|
||||
;; LINK PREVIEW ========================================================================================================
|
||||
|
||||
(re-frame/reg-sub
|
||||
:link-preview/whitelist
|
||||
:<- [:multiaccount]
|
||||
(fn [multiaccount]
|
||||
(get multiaccount :link-previews-whitelist)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:link-preview/cache
|
||||
:<- [:multiaccount]
|
||||
(fn [multiaccount]
|
||||
(get multiaccount :link-previews-cache)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:link-preview/enabled-sites
|
||||
:<- [:multiaccount]
|
||||
(fn [multiaccount]
|
||||
(get multiaccount :link-previews-enabled-sites)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:link-preview/link-preview-request-enabled
|
||||
:<- [:multiaccount]
|
||||
(fn [multiaccount]
|
||||
(get multiaccount :link-preview-request-enabled)))
|
||||
|
||||
;; NOTIFICATIONS
|
||||
|
||||
(re-frame/reg-sub
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
(ns status-im.ui.screens.chat.message.link-preview
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[clojure.string :as string]
|
||||
[status-im.ui.components.react :as react]
|
||||
[quo.core :as quo]
|
||||
[status-im.utils.security :as security]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.screens.chat.message.styles :as styles]
|
||||
[status-im.react-native.resources :as resources]
|
||||
[status-im.chat.models.link-preview :as link-preview])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
(defn link-belongs-to-domain [link domain]
|
||||
(cond
|
||||
(string/starts-with? link (str "https://" domain)) true
|
||||
(string/starts-with? link (str "https://www." domain)) true
|
||||
:else false))
|
||||
|
||||
(defn domain-info-if-whitelisted [link whitelist]
|
||||
(first (filter
|
||||
#(link-belongs-to-domain link (:address %))
|
||||
whitelist)))
|
||||
|
||||
(defn link-extended-info [link whitelist enabled-list]
|
||||
(let [domain-info (domain-info-if-whitelisted link whitelist)]
|
||||
{:whitelisted (not (nil? domain-info))
|
||||
:enabled (contains? enabled-list (:title domain-info))
|
||||
:link link}))
|
||||
|
||||
(defn previewable-link [links whitelist enabled-list]
|
||||
(->> links
|
||||
(map #(link-extended-info % whitelist enabled-list))
|
||||
(filter #(:whitelisted %))
|
||||
(first)))
|
||||
|
||||
(defview link-preview-enable-request []
|
||||
[react/view (styles/link-preview-request-wrapper)
|
||||
[react/view {:margin 12}
|
||||
[react/image {:source (resources/get-theme-image :unfurl)
|
||||
:style styles/link-preview-request-image}]
|
||||
[quo/text {:size :small
|
||||
:align :center
|
||||
:style {:margin-top 6}}
|
||||
(i18n/label :t/enable-link-previews)]
|
||||
[quo/text {:size :small
|
||||
:color :secondary
|
||||
:align :center
|
||||
:style {:margin-top 2}}
|
||||
(i18n/label :t/once-enabled-share-metadata)]]
|
||||
[quo/separator]
|
||||
[quo/button {:on-press #(re-frame/dispatch [:navigate-to :link-preview-settings])
|
||||
:type :secondary}
|
||||
(i18n/label :enable)]
|
||||
[quo/separator]
|
||||
[quo/button {:on-press #(re-frame/dispatch
|
||||
[::link-preview/should-suggest-link-preview false])
|
||||
:type :secondary}
|
||||
(i18n/label :t/dont-ask)]])
|
||||
|
||||
(defview link-preview-loader [link outgoing]
|
||||
(letsubs [cache [:link-preview/cache]]
|
||||
(let [{:keys [site title thumbnailUrl] :as preview-data} (get cache link)]
|
||||
(if (not preview-data)
|
||||
(do
|
||||
(re-frame/dispatch
|
||||
[::link-preview/load-link-preview-data link])
|
||||
nil)
|
||||
|
||||
[react/touchable-highlight
|
||||
{:on-press #(when (and (security/safe-link? link))
|
||||
(re-frame/dispatch
|
||||
[:browser.ui/message-link-pressed link]))}
|
||||
|
||||
[react/view (styles/link-preview-wrapper outgoing)
|
||||
[react/image {:source {:uri thumbnailUrl}
|
||||
:style (styles/link-preview-image outgoing)
|
||||
:accessibility-label :member-photo}]
|
||||
[quo/text {:size :small
|
||||
:style styles/link-preview-title}
|
||||
title]
|
||||
[quo/text {:size :small
|
||||
:color :secondary
|
||||
:style styles/link-preview-site}
|
||||
site]]]))))
|
||||
|
||||
(defview link-preview-wrapper [links outgoing]
|
||||
(letsubs
|
||||
[ask-user? [:link-preview/link-preview-request-enabled]
|
||||
whitelist [:link-preview/whitelist]
|
||||
enabled-sites [:link-preview/enabled-sites]]
|
||||
(let [link-info (previewable-link links whitelist enabled-sites)
|
||||
{:keys [link whitelisted enabled]} link-info]
|
||||
(when (and link whitelisted)
|
||||
(if enabled
|
||||
[link-preview-loader link outgoing]
|
||||
(when ask-user?
|
||||
[link-preview-enable-request]))))))
|
|
@ -17,7 +17,8 @@
|
|||
[status-im.ui.screens.chat.message.reactions :as reactions]
|
||||
[quo.core :as quo]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.ui.screens.chat.components.reply :as components.reply])
|
||||
[status-im.ui.screens.chat.components.reply :as components.reply]
|
||||
[status-im.ui.screens.chat.message.link-preview :as link-preview])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
(defview mention-element [from]
|
||||
|
@ -213,7 +214,8 @@
|
|||
[message-author-name from modal]])
|
||||
;;MESSAGE CONTENT
|
||||
[react/view
|
||||
content]]]
|
||||
content]
|
||||
[link-preview/link-preview-wrapper (:links (:content message)) outgoing]]]
|
||||
; delivery status
|
||||
[react/view (style/delivery-status outgoing)
|
||||
[message-delivery-status message]]])
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
(ns status-im.ui.screens.chat.message.styles
|
||||
(:require [quo.design-system.colors :as colors]
|
||||
[status-im.ui.screens.chat.styles.photos :as photos]))
|
||||
[status-im.ui.screens.chat.styles.photos :as photos]
|
||||
[status-im.ui.components.colors :as components.colors]))
|
||||
|
||||
(defn picker-wrapper-style [{:keys [display-photo? outgoing]}]
|
||||
(merge {:flex-direction :row
|
||||
|
@ -84,3 +85,43 @@
|
|||
{:background-color (:interactive-02 @colors/theme)
|
||||
;; FIXME: Use broder color here
|
||||
:border-color "rgba(67, 96, 223, 0.2)"})))
|
||||
|
||||
(defn link-preview-request-wrapper []
|
||||
{:border-radius 16
|
||||
:border-width 1
|
||||
:border-color components.colors/gray-lighter
|
||||
:margin-vertical 4
|
||||
:background-color (:ui-background @colors/theme)})
|
||||
|
||||
(def link-preview-request-image
|
||||
{:width 132
|
||||
:height 94
|
||||
:align-self :center})
|
||||
|
||||
(defn link-preview-wrapper [outgoing]
|
||||
{:overflow :hidden
|
||||
:border-top-left-radius 16
|
||||
:border-top-right-radius 16
|
||||
:border-bottom-left-radius (if outgoing 16 4)
|
||||
:border-bottom-right-radius (if outgoing 4 16)
|
||||
:border-width 1
|
||||
:border-color components.colors/gray-lighter
|
||||
:margin-vertical 4
|
||||
:background-color (:ui-background @colors/theme)})
|
||||
|
||||
(defn link-preview-image [outgoing]
|
||||
{:height 170
|
||||
:overflow :hidden
|
||||
:border-top-left-radius 16
|
||||
:border-top-right-radius 16
|
||||
:border-bottom-left-radius (if outgoing 16 4)
|
||||
:border-bottom-right-radius (if outgoing 4 16)})
|
||||
|
||||
(def link-preview-title
|
||||
{:margin-horizontal 12
|
||||
:margin-top 10})
|
||||
|
||||
(def link-preview-site
|
||||
{:margin-horizontal 12
|
||||
:margin-top 2
|
||||
:margin-bottom 10})
|
|
@ -0,0 +1,13 @@
|
|||
(ns status-im.ui.screens.link-previews-settings.styles)
|
||||
|
||||
(def link-preview-settings-image
|
||||
{:height 100
|
||||
:align-self :center
|
||||
:margin-top 16})
|
||||
|
||||
(def whitelist-container
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between})
|
||||
|
||||
(def enable-all
|
||||
{:align-self :flex-end})
|
|
@ -0,0 +1,50 @@
|
|||
(ns status-im.ui.screens.link-previews-settings.views
|
||||
(:require-macros [status-im.utils.views :as views])
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
[quo.core :as quo]
|
||||
[status-im.react-native.resources :as resources]
|
||||
[status-im.ui.components.topbar :as topbar]
|
||||
[status-im.ui.screens.link-previews-settings.styles :as styles]
|
||||
[status-im.chat.models.link-preview :as link-preview]))
|
||||
|
||||
(defn prepare-urls-items-data [link-previews-enabled-sites]
|
||||
(fn [{:keys [title address]}]
|
||||
(let [enabled? (contains? link-previews-enabled-sites title)]
|
||||
{:title title
|
||||
:subtitle address
|
||||
:size :small
|
||||
:accessory :switch
|
||||
:active (contains? link-previews-enabled-sites title)
|
||||
:on-press #(re-frame/dispatch
|
||||
[::link-preview/enable title ((complement boolean) enabled?)])})))
|
||||
|
||||
(views/defview link-previews-settings []
|
||||
(views/letsubs [{:keys [link-previews-whitelist link-previews-enabled-sites]} [:multiaccount]]
|
||||
[react/view {:flex 1}
|
||||
[topbar/topbar {:title (i18n/label :t/chat-link-previews)}]
|
||||
[react/image {:source (resources/get-theme-image :unfurl)
|
||||
:style styles/link-preview-settings-image}]
|
||||
[quo/text {:style {:margin 16}}
|
||||
(i18n/label :t/you-can-choose-preview-websites)]
|
||||
[quo/separator {:style {:margin-vertical 8}}]
|
||||
|
||||
[react/view styles/whitelist-container
|
||||
[quo/list-header (i18n/label :t/websites)]
|
||||
|
||||
(when (> (count link-previews-whitelist) 1)
|
||||
[quo/button {:on-press #(doseq [site (map :title link-previews-whitelist)]
|
||||
(re-frame/dispatch
|
||||
[::link-preview/enable site true]))
|
||||
:type :secondary
|
||||
:style styles/enable-all}
|
||||
(i18n/label :t/enable-all)])]
|
||||
|
||||
[list/flat-list
|
||||
{:data (vec (map (prepare-urls-items-data link-previews-enabled-sites) link-previews-whitelist))
|
||||
:key-fn (fn [_ i] (str i))
|
||||
:render-fn quo/list-item
|
||||
:footer [quo/text {:color :secondary
|
||||
:style {:margin 16}} (i18n/label :t/previewing-may-share-metadata)]}]]))
|
|
@ -63,6 +63,11 @@
|
|||
:on-press #(re-frame/dispatch
|
||||
[:multiaccounts.ui/preview-privacy-mode-switched
|
||||
((complement boolean) preview-privacy?)])}]
|
||||
[quo/list-item {:size :small
|
||||
:title (i18n/label :t/chat-link-previews)
|
||||
:chevron true
|
||||
:on-press #(re-frame/dispatch [:navigate-to :link-previews-settings])
|
||||
:accessibility-label :chat-link-previews}]
|
||||
(when platform/android?
|
||||
[quo/list-item {:size :small
|
||||
:title (i18n/label :t/webview-camera-permission-requests)
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
[status-im.ui.screens.profile.contact.views :as contact]
|
||||
[status-im.ui.screens.notifications-settings.views :as notifications-settings]
|
||||
[status-im.ui.screens.wallet.send.views :as wallet]
|
||||
[status-im.ui.screens.link-previews-settings.views :as link-previews]
|
||||
[status-im.ui.screens.profile.my-status.views :as my-status]))
|
||||
|
||||
(defonce main-stack (navigation/create-stack))
|
||||
|
@ -79,6 +80,9 @@
|
|||
:on-focus [::new-chat.events/new-chat-focus]
|
||||
:transition :presentation-ios
|
||||
:component new-chat/new-contact}
|
||||
{:name :link-preview-settings
|
||||
:transition :presentation-ios
|
||||
:component link-previews/link-previews-settings}
|
||||
{:name :new-public-chat
|
||||
:transition :presentation-ios
|
||||
:insets {:bottom true}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
:as
|
||||
offline-messaging-settings]
|
||||
[status-im.ui.screens.dapps-permissions.views :as dapps-permissions]
|
||||
[status-im.ui.screens.link-previews-settings.views :as link-previews-settings]
|
||||
[status-im.ui.screens.privacy-and-security-settings.views :as privacy-and-security]
|
||||
[status-im.ui.screens.sync-settings.views :as sync-settings]
|
||||
[status-im.ui.screens.advanced-settings.views :as advanced-settings]
|
||||
|
@ -76,6 +77,8 @@
|
|||
:component edit-mailserver/edit-mailserver}
|
||||
{:name :dapps-permissions
|
||||
:component dapps-permissions/dapps-permissions}
|
||||
{:name :link-previews-settings
|
||||
:component link-previews-settings/link-previews-settings}
|
||||
{:name :privacy-and-security
|
||||
:component privacy-and-security/privacy-and-security}
|
||||
{:name :appearance
|
||||
|
|
|
@ -1315,5 +1315,14 @@
|
|||
"invalid-public-chat-topic": "Invalid public chat topic",
|
||||
"now": "Now",
|
||||
"statuses-my-profile-descr": "Status updates are messages you publish to your profile. They can be viewed by anyone visiting your profile inside Status",
|
||||
"new-status": "New status"
|
||||
"new-status": "New status",
|
||||
"chat-link-previews": "Chat link previews",
|
||||
"you-can-choose-preview-websites" : "You can choose which of the following websites can preview link of descriptions and pictures in chats",
|
||||
"previewing-may-share-metadata" : "Previewing links from these websites may share your metadata with their owners",
|
||||
"websites" : "Websites",
|
||||
"enable-all" : "Enable all",
|
||||
"warning-sending-to-contract-descr": "The address you entered is a smart contract, sending funds to this address may result in loss of funds. To interact with a DApp, open the DApp in the Status DApp Browser.",
|
||||
"dont-ask": "Don't ask me again",
|
||||
"enable-link-previews": "Enable link previews in chat?",
|
||||
"once-enabled-share-metadata": "Once enabled, links posted in the chat may share your metadata with the site"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue