diff --git a/images/ic_menu_black_24dp_1x.png b/images/ic_menu_black_24dp_1x.png new file mode 100644 index 0000000000..ef2a48c7ab Binary files /dev/null and b/images/ic_menu_black_24dp_1x.png differ diff --git a/images/ic_search_black_24dp_1x.png b/images/ic_search_black_24dp_1x.png new file mode 100644 index 0000000000..6b16343235 Binary files /dev/null and b/images/ic_search_black_24dp_1x.png differ diff --git a/src/syng_im/components/carousel.cljs b/src/syng_im/components/carousel.cljs new file mode 100644 index 0000000000..5a6eb07019 --- /dev/null +++ b/src/syng_im/components/carousel.cljs @@ -0,0 +1,15 @@ +(ns syng-im.components.carousel) + +(set! js/Carousel (.-default (js/require "react-native-carousel-control"))) + + +(defn carousel [opts & children] + (apply js/React.createElement js/Carousel (clj->js opts) children)) + + + +(comment + + + + ) \ No newline at end of file diff --git a/src/syng_im/components/discovery/discovery-popular-list-item.cljs b/src/syng_im/components/discovery/discovery-popular-list-item.cljs new file mode 100644 index 0000000000..da4fc87488 --- /dev/null +++ b/src/syng_im/components/discovery/discovery-popular-list-item.cljs @@ -0,0 +1,40 @@ +(ns syng-im.components.discovery.discovery-popular-list-item + (:require + [syng-im.components.react :refer [android? + view + scroll-view + list-view + text + image + navigator + toolbar-android]] + [syng-im.resources :as res] + [reagent.core :as r]) + ) + +(defn discovery-popular-list-item [discovery] + (r/as-element [view {:style {:flexDirection "row" + :paddingTop 10 + :paddingBottom 10}} + [view {:style {:flex 0.8 + :flexDirection "column"}} + [text {:style {:color "black" + :fontWeight "bold" + :fontSize 12}} (aget discovery "name")] + [text {:style {:color "black" + :fontWeight "normal" + :fontSize 12} + :numberOfLines 2} (aget discovery "status")] + ] + [view {:style {:flex 0.2 + :flexDirection "column" + :alignItems "center" + :paddingTop 5}} + [image {:style {:resizeMode "contain" + :borderRadius 150 + :width 30 + :height 30} + :source res/user-no-photo}] + ] + ]) + ) \ No newline at end of file diff --git a/src/syng_im/components/discovery/discovery-recent.cljs b/src/syng_im/components/discovery/discovery-recent.cljs new file mode 100644 index 0000000000..f1450fdc33 --- /dev/null +++ b/src/syng_im/components/discovery/discovery-recent.cljs @@ -0,0 +1,44 @@ +(ns syng-im.components.discovery.discovery-recent + (:require-macros + [natal-shell.data-source :refer [data-source clone-with-rows]] + + ) + (:require + [syng-im.components.react :refer [android? + view + scroll-view + list-view + text + image + navigator + toolbar-android]] + [syng-im.components.carousel :refer [carousel]] + [syng-im.components.discovery.discovery-popular-list-item :refer [discovery-popular-list-item]] + [syng-im.models.discoveries :refer [generate-discoveries]] + [reagent.core :as r] + [syng-im.resources :as res])) + + +(defn render-row [row section-id row-id] + (let [elem (discovery-popular-list-item row)] + elem) + ) + +(defn render-separator [sectionID, rowID, adjacentRowHighlighted] + (let [elem (r/as-element [view {:style {:borderBottomWidth 1 + :borderBottomColor "#eff2f3"} + :key rowID}])] + elem)) + +(defn get-data-source [elements] + (clone-with-rows (data-source {:rowHasChanged (fn [row1 row2] + (not= (:discovery-id row1) (:discovery-id row2)))}) + elements)) + +(defn discovery-recent [recent-discoveries] + [list-view {:dataSource (get-data-source recent-discoveries) + :renderRow render-row + :renderSeparator render-separator + :style {:backgroundColor "white" + :paddingLeft 15}}] + ) \ No newline at end of file diff --git a/src/syng_im/components/discovery/discovery.cljs b/src/syng_im/components/discovery/discovery.cljs new file mode 100644 index 0000000000..01d9944009 --- /dev/null +++ b/src/syng_im/components/discovery/discovery.cljs @@ -0,0 +1,106 @@ +(ns syng-im.components.discovery.discovery + + (:require + [re-frame.core :refer [subscribe dispatch dispatch-sync]] + [syng-im.components.react :refer [android? + view + scroll-view + text + image + navigator + toolbar-android]] + [reagent.core :as r] + [syng-im.components.discovery.discovery-popular :refer [discovery-popular]] + [syng-im.components.discovery.discovery-recent :refer [discovery-recent]] + [syng-im.models.discoveries :refer [generate-discoveries + get-discovery-popular + get-discovery-recent]] + [syng-im.resources :as res])) + +(defn discovery [{:keys [navigator]}] + (let [discoveries (subscribe [:get-discoveries]) + pop-discoveries (get-discovery-popular 3)] + (fn [] + [view {:style {:flex 1 + :backgroundColor "#edf2f5"}} + [toolbar-android {:title "Discover" + :titleColor "#4A5258" + :navIcon res/menu + :actions [{:title "Search" + :icon res/search + :show "always"}] + :style {:backgroundColor "white" + :justifyContent "center" + :height 56 + :elevation 2} + :onIconClicked (fn [] + (.log console "testttt")) + :onActionSelected (fn [index] + (index))}] + + [scroll-view {:style {}} + [view {:style {:paddingTop 5}} + [text {:style {:color "#b2bdc5" + :fontSize 14 + :textAlign "center"}} "Discover popular contacts \n around the world"]] + [view {:style {:paddingLeft 30 + :paddingTop 15 + :paddingBottom 15}} + [text {:style {:color "#b2bdc5" + :fontSize 14 + :fontWeight "bold"}} "Popular Tags"]] + [discovery-popular pop-discoveries] + [view {:style {:paddingLeft 30 + :paddingTop 15 + :paddingBottom 15}} + [text {:style {:color "#b2bdc5" + :fontSize 14 + :fontWeight "bold"}} "Recent"]] + [discovery-recent (get-discovery-recent 10)] + ] + ] + ) + ) + ) + (comment + (def page-width (aget (natal-shell.dimensions/get "window") "width")) + (def page-height (aget (natal-shell.dimensions/get "window") "height")) + [view {:style {:flex 1 + :backgroundColor "white"}} + [toolbar-android {:title "Discover" + :titleColor "#4A5258" + :navIcon res/menu + :actions [{:title "Search" + :icon res/search + :show "always"}] + :style {:backgroundColor "white" + :height 56 + :elevation 2} + :onIconClicked (fn [] + (.log console "testttt")) + :onActionSelected (fn [index] + (index))}] + [scroll-view {:style { }} + [view {:style {:paddingLeft 30 + :paddingTop 15 + :paddingBottom 15}} + [text {:style {:color "#232323" + :fontSize 18 + :fontWeight "bold"}} "Popular Tags"]] + [carousel {:pageStyle {:backgroundColor "white", :borderRadius 5} + :pageWidth (- page-width 60)} + [view {:style {:height (- page-height 100)}} [text {:style {:color "#232323" + :fontSize 18 + :fontWeight "bold"}} "Popular Tags"]] + [view [text "Welcome to Syng"]] + [view [text "Welcome to Syng"]] + [view [text "Welcome to Syng"]]] + [view {:style {:paddingLeft 30 + :paddingTop 15 + :paddingBottom 15}} + [text {:style {:color "#232323" + :fontSize 18 + :fontWeight "bold"}} "Recent"]] + [view {:style {:height 200}}] + ]] + ) diff --git a/src/syng_im/components/discovery/discovery_popular.cljs b/src/syng_im/components/discovery/discovery_popular.cljs new file mode 100644 index 0000000000..ef1863c4fa --- /dev/null +++ b/src/syng_im/components/discovery/discovery_popular.cljs @@ -0,0 +1,42 @@ +(ns syng-im.components.discovery.discovery-popular + + (:require + [syng-im.components.react :refer [android? + view + scroll-view + text + image + navigator + toolbar-android]] + [syng-im.components.carousel :refer [carousel]] + [syng-im.components.discovery.discovery-popular-list :refer [discovery-popular-list]] + [syng-im.models.discoveries :refer [generate-discoveries]] + [syng-im.resources :as res])) + +(defn page-width [] + (.-width (.get (.. js/React -Dimensions) "window"))) + + +(defn discovery-popular [popular-discoveries] + (let [popular-lists (mapv #(discovery-popular-list % (get popular-discoveries %)) (keys popular-discoveries))] + (if (> (count popular-lists) 0) + (apply carousel {:pageStyle {:borderRadius 1 + :shadowColor "black" + :shadowRadius 1 + :shadowOpacity 0.8 + :elevation 2 + :marginBottom 10} + :pageWidth (- (page-width) 60) + + } + popular-lists + ) + [text "None"] + ) + ) + ) + +(comment + (set! React (js/require "react-native")) + (.get (.Dimensions React) "window") + ) \ No newline at end of file diff --git a/src/syng_im/components/discovery/discovery_popular_list.cljs b/src/syng_im/components/discovery/discovery_popular_list.cljs new file mode 100644 index 0000000000..741bd3c12c --- /dev/null +++ b/src/syng_im/components/discovery/discovery_popular_list.cljs @@ -0,0 +1,64 @@ +(ns syng-im.components.discovery.discovery-popular-list + (:require-macros + [natal-shell.data-source :refer [data-source clone-with-rows]] + + ) + (:require + [syng-im.components.react :refer [android? + view + scroll-view + list-view + text + image + navigator + toolbar-android]] + [reagent.core :as r] + [syng-im.components.discovery.discovery-popular-list-item :refer [discovery-popular-list-item] ]) + ) + + +(defn render-row [row section-id row-id] + (let [elem (discovery-popular-list-item row)] + elem) +) + +(defn render-separator [sectionID, rowID, adjacentRowHighlighted] + (let [elem (r/as-element [view {:style {:borderBottomWidth 1 + :borderBottomColor "#eff2f3"} + :key rowID}])] + elem)) + +(defn get-data-source [elements] + (clone-with-rows (data-source {:rowHasChanged (fn [row1 row2] + (not= (:discovery-id row1) (:discovery-id row2)))}) + elements)) + +(defn discovery-popular-list [tag elements] + (r/as-element [view {:style {:flex 1 + :backgroundColor "white" + :paddingLeft 10 + :paddingTop 10}} + [view {:style {:flexDirection "row" + :backgroundColor "white" + :padding 0}} + [view {:style {:flexDirection "column" + :backgroundColor "#e9f7fe" + :borderRadius 5 + :padding 0}} + [text {:style {:color "#6092df" + :paddingRight 5 + :paddingBottom 2 + :alignItems "center" + :justifyContent "center"}} (str " #" (name tag))]]] + [list-view {:dataSource (get-data-source elements) + :renderRow render-row + :renderSeparator render-separator + :style {:backgroundColor "white"}}] + ]) + ) + +(comment + list-view {:dataSource elements + :renderRow (partial render-row list-element) + :style {:backgroundColor "white"}} + ) \ No newline at end of file diff --git a/src/syng_im/models/discoveries.cljs b/src/syng_im/models/discoveries.cljs new file mode 100644 index 0000000000..7d99315e73 --- /dev/null +++ b/src/syng_im/models/discoveries.cljs @@ -0,0 +1,183 @@ +(ns syng-im.models.discoveries + (:require [cljs.core.async :as async :refer [chan put! !]] + [re-frame.core :refer [subscribe dispatch dispatch-sync]] + [syng-im.utils.utils :refer [log toast]] + [syng-im.persistence.realm :as realm] + [syng-im.persistence.realm :as r] + [syng-im.resources :as res] + [syng-im.db :as db])) + +;; TODO see https://github.com/rt2zz/react-native-contacts/issues/45 +(def fake-discoveries? true) + + + +(defn signal-discovery-updated [db] + (update-in db db/updated-discovery-signal-path (fn [current] + (if current + (inc current) + 0)))) + +(defn discovery-updated? [db] + (get-in db db/updated-discovery-signal-path)) + +(defn- generate-discovery [n] + {:discovery-id n + :name (str "Contact " n) + :status (apply str (repeat (+ n 3) "Contact Status ")) + :whisper-id (str "id-" n) + :photo "" + :tags ["tag1" "tag2"] + :last-updated (js/Date. "10/01/2015") + }) + +(defn- generate-discoveries [n] + (map generate-discovery (range 1 (inc n)))) + +(def fake-discoveries (generate-discoveries 20)) + +(defn- get-discoveries [] + ( let [list (realm/get-list :discoveries)] + (if (> (.-length list) 0) (.slice list 0) []))) + +(defn load-syng-discoveries [db] + (let [discoveries (map (fn [discovery] + (merge discovery + {})) + (get-discoveries))] + (assoc db :discoveries discoveries))) + +(defn get-tag [tag] + (-> (r/get-by-field :tag :name tag) + (r/single-cljs))) + +(defn remove-tag [tag] + (let [tag-object (get-tag tag)] + (if tag-object + (realm/create :tag + {:name tag + :count (dec (:count tag-object)) + })))) + +(defn add-tag [tag] + (let [tag-object (get-tag tag) + counter (if tag-object (:count tag-object) 1)] + (realm/create :tag + {:name tag + :count (inc counter) + } + (if tag-object true false)))) + +(defn remove-tags [tags] + (doseq [tag tags] + (remove-tag tag))) + +(defn add-tags [tags] + (doseq [tag tags] + (add-tag tag))) + +(defn get-tags [whisper-id] + (:tags (-> (r/get-by-field :discoveries :whisper-id whisper-id) + (r/single-cljs)))) + +(defn- create-discovery [{:keys [name status whisper-id photo tags last-updated]}] + (do + ;(add-tags tags) + (realm/create :discoveries + {:name name + :status status + :whisper-id whisper-id + :photo photo + :tags (mapv (fn [tag] + {:name tag}) tags) + :last-updated last-updated} true) + ) + ) + + + +(defn- update-discovery [{:keys [name status whisper-id photo tags last-updated]}] + (let [old-tags (get-tags whisper-id)] + (do + ;;(remove-tags old-tags) + ;;(add-tags tags) + (realm/create :discoveries + {:name name + :status status + :whisper-id whisper-id + :photo photo + :tags (mapv (fn [tag] + {:name tag}) tags) + :last-updated last-updated} + true) + )) + ) + +(defn- discovery-exist? [discoveries discovery] + (some #(= (:whisper-id discovery) (:whisper-id %)) discoveries)) + +(defn- add-discoveries [discoveries] + (realm/write (fn [] + (let [db-discoveries (get-discoveries)] + (dorun (map (fn [discovery] + (if (not (discovery-exist? db-discoveries discovery)) + (create-discovery discovery) + (update-discovery discovery) + )) + discoveries)))))) + +(defn save-discoveries [discoveries] + (add-discoveries discoveries)) + +(defn discovery-list [] + (-> (r/get-all :discoveries) + (r/sorted :discovery-id :desc))) + +(defn get-discovery-recent [limit] + (if fake-discoveries? + (take limit fake-discoveries) + (-> (r/get-all :discoveries) + (r/sorted :last-updated :desc) + (r/page 0 limit))) + ) + +(defn get-tag-popular [limit] + (-> (r/get-all :tag) + (r/sorted :count :desc) + (r/page 0 limit))) + +(defn add-with-limit [data value limit] + (if (>= (count data) limit) + data + (conj data value)) + ) + +(defn group-by-tag [discoveries tag-limit] + (reduce (fn [result discovery] + (let [keys (:tags discovery)] + (reduce (fn [data key] + (assoc data (keyword key) (add-with-limit (get data (keyword key) []) discovery tag-limit))) + result + keys))) + {} + discoveries) + ) + +(defn get-discovery-popular [tag-limit] + (if fake-discoveries? + (group-by-tag fake-discoveries tag-limit) + (-> (r/get-all :discoveries) + (r/sorted :last-updated :desc) + (.slice 0) + (group-by-tag tag-limit)) + ) + ) + +(comment + (group-by-tag [{:tags ["a" "b" "c"] + :name "test1"} + {:tags ["a" "c"] + :name "test2"} + {:tags ["c"] + :name "test3"}]) + ) \ No newline at end of file