aboutsummaryrefslogtreecommitdiff
path: root/src/frontend/tau/views
diff options
context:
space:
mode:
authorMiguel Ángel Moreno <mail@migalmoreno.com>2022-12-26 22:02:33 +0100
committerMiguel Ángel Moreno <mail@migalmoreno.com>2022-12-26 22:02:33 +0100
commitb5404ac06a3a09d83bef66552083254fdff12196 (patch)
tree02785ab11a3dcf328e8d1375a7b76abb2edbf382 /src/frontend/tau/views
parentdce9e36b352509665887ea1ca2e6f81904038a11 (diff)
feat(frontend): Modularize components and add pagination
Diffstat (limited to 'src/frontend/tau/views')
-rw-r--r--src/frontend/tau/views/channel.cljs41
-rw-r--r--src/frontend/tau/views/home.cljs2
-rw-r--r--src/frontend/tau/views/kiosk.cljs9
-rw-r--r--src/frontend/tau/views/playlist.cljs5
-rw-r--r--src/frontend/tau/views/search.cljs64
-rw-r--r--src/frontend/tau/views/stream.cljs98
6 files changed, 163 insertions, 56 deletions
diff --git a/src/frontend/tau/views/channel.cljs b/src/frontend/tau/views/channel.cljs
new file mode 100644
index 0000000..abdbb54
--- /dev/null
+++ b/src/frontend/tau/views/channel.cljs
@@ -0,0 +1,41 @@
+(ns tau.views.channel
+ (:require
+ [re-frame.core :as rf]
+ [tau.components.items :as items]
+ [tau.components.loading :as loading]
+ [tau.components.navigation :as navigation]
+ [tau.events :as events]))
+
+(defn channel
+ [{{:keys [url]} :query-params}]
+ (let [{:keys [banner avatar name description subscriber-count
+ related-streams next-page]} @(rf/subscribe [:channel])
+ next-page-url (:url next-page)
+ service-color @(rf/subscribe [:service-color])
+ page-scroll @(rf/subscribe [:page-scroll])
+ page-loading? @(rf/subscribe [:show-page-loading])
+ pagination-loading? @(rf/subscribe [:show-pagination-loading])
+ scrolled-to-bottom? (= page-scroll (.-scrollHeight js/document.body))]
+ (when scrolled-to-bottom?
+ (rf/dispatch [::events/scroll-channel-pagination url next-page-url]))
+ [:div.flex.flex-col.items-center.px-5.py-2.text-white.flex-auto
+ (if page-loading?
+ [loading/page-loading-icon service-color]
+ [:div {:class "w-4/5"}
+ [navigation/back-button]
+ [:div [:img {:src banner}]]
+ [:div.flex.items-center.my-4.mx-2
+ [:div
+ [:img.rounded-full {:src avatar}]]
+ [:div.m-4
+ [:h1.text-xl name]
+ [:div.flex.my-2.items-center
+ [:i.fa-solid.fa-users]
+ [:span.mx-2 subscriber-count]]]]
+ [:div.my-2
+ [:p description]]
+ [:div.flex.justify-center.align-center.flex-wrap.my-2
+ (for [[i result] (map-indexed vector related-streams)]
+ [items/stream-item i result])]
+ (when-not (empty? next-page-url)
+ [loading/pagination-loading-icon service-color pagination-loading?])])]))
diff --git a/src/frontend/tau/views/home.cljs b/src/frontend/tau/views/home.cljs
index 0d42d7d..00d2e1e 100644
--- a/src/frontend/tau/views/home.cljs
+++ b/src/frontend/tau/views/home.cljs
@@ -1,7 +1,7 @@
(ns tau.views.home)
(defn home-page
- []
+ [match]
[:div.flex.justify-center.content-center.flex-col.text-center.text-white.text-lg.flex-auto
[:p.text-5xl.p-5 "Welcome to Tau"]
[:p.text-2xl "A web front-end for Newpipe"]])
diff --git a/src/frontend/tau/views/kiosk.cljs b/src/frontend/tau/views/kiosk.cljs
new file mode 100644
index 0000000..70caacf
--- /dev/null
+++ b/src/frontend/tau/views/kiosk.cljs
@@ -0,0 +1,9 @@
+(ns tau.views.kiosk
+ (:require
+ [re-frame.core :as rf]))
+
+(defn kiosk
+ [match]
+ (let [{:keys [id url related-streams]} @(rf/subscribe [:kiosk])]
+ [:div
+ [:h1 id]]))
diff --git a/src/frontend/tau/views/playlist.cljs b/src/frontend/tau/views/playlist.cljs
new file mode 100644
index 0000000..b82cc24
--- /dev/null
+++ b/src/frontend/tau/views/playlist.cljs
@@ -0,0 +1,5 @@
+(ns tau.views.playlist)
+
+(defn playlist
+ [match]
+ [:div])
diff --git a/src/frontend/tau/views/search.cljs b/src/frontend/tau/views/search.cljs
index 64bddf3..69f1353 100644
--- a/src/frontend/tau/views/search.cljs
+++ b/src/frontend/tau/views/search.cljs
@@ -1,38 +1,36 @@
(ns tau.views.search
(:require
[re-frame.core :as rf]
- [reitit.frontend.easy :as rfe]))
-
-(defn search-result
- [title author url thumbnail id]
- [:div.w-56.h-64.my-2 {:key id}
- [:div.p-5.border.rounded.border-slate-900.m-2.bg-slate-600.flex.flex-col.max-w-full.min-h-full.max-h-full
- [:a.overflow-hidden {:href (rfe/href :tau.routes/stream {} {:url url}) :title title}
- [:div.flex.justify-center.min-w-full.py-3.box-border
- [:div.h-28.min-w-full.flex.justify-center
- [:img.rounded.object-cover.max-h-full {:src thumbnail}]]]
- [:div.overflow-hidden
- [:h1.text-gray-300.font-bold author]
- [:h1 title]]]]])
+ [reitit.frontend.easy :as rfe]
+ [tau.components.items :as items]
+ [tau.components.loading :as loading]
+ [tau.events :as events]))
(defn search
- [m]
- (let [search-results (rf/subscribe [:search-results])
- services (rf/subscribe [:services])
- service-id (rf/subscribe [:service-id])]
- [:div.text-gray-300.text-center.py-5.relative
- [:h2 (str "Showing search results for: \"" (-> m :query-params :q) "\"")]
- [:h1 (str "Number of search results: " (count (:items @search-results)))]
- ;; TODO: Create loadable component that wraps other components that need to fetch from API
- ;; or use a :loading key to show a spinner component instead
- (if (empty? @search-results)
- [:p "Loading"]
- [:div.flex.justify-center.align-center.flex-wrap
- (for [[i result] (map-indexed vector (:items @search-results))]
- ;; TODO: Add a component per result type
- [search-result
- (:name result)
- (:upload-author result)
- (:url result)
- (:thumbnail-url result)
- i])])]))
+ [{{:keys [q serviceId]} :query-params}]
+ (let [{:keys [items next-page] :as search-results} @(rf/subscribe [:search-results])
+ next-page-url (:url next-page)
+ services @(rf/subscribe [:services])
+ service-id @(rf/subscribe [:service-id])
+ service-color @(rf/subscribe [:service-color])
+ page-scroll @(rf/subscribe [:page-scroll])
+ page-loading? @(rf/subscribe [:show-page-loading])
+ pagination-loading? @(rf/subscribe [:show-pagination-loading])
+ scrolled-to-bottom? (= page-scroll (.-scrollHeight js/document.body))]
+ (when scrolled-to-bottom?
+ (rf/dispatch [::events/scroll-search-pagination q serviceId next-page-url]))
+ [:div.flex.flex-col.text-gray-300.h-box-border.flex-auto
+ [:div.flex.flex-col.items-center.w-full.pt-4.flex-initial
+ [:h2 (str "Showing search results for: \"" q "\"")]
+ [:h1 (str "Number of search results: " (count items))]]
+ (if page-loading?
+ [loading/page-loading-icon service-color]
+ [:div.flex.flex-col
+ [:div.flex.justify-center.align-center.flex-wrap.flex-auto
+ (for [[i item] (map-indexed vector items)]
+ (cond
+ (:duration item) [items/stream-item i item]
+ (:subscriber-count item) [items/channel-item i item]
+ (:stream-count item) [items/playlist-item i item]))
+ (when-not (empty? next-page-url)
+ [loading/pagination-loading-icon service-color pagination-loading?])]])]))
diff --git a/src/frontend/tau/views/stream.cljs b/src/frontend/tau/views/stream.cljs
index ccc53eb..47039e6 100644
--- a/src/frontend/tau/views/stream.cljs
+++ b/src/frontend/tau/views/stream.cljs
@@ -1,27 +1,81 @@
(ns tau.views.stream
(:require
- [re-frame.core :as rf]))
+ [re-frame.core :as rf]
+ [reitit.frontend.easy :as rfe]
+ [tau.events :as events]
+ [tau.components.items :as items]
+ [tau.components.loading :as loading]
+ [tau.components.navigation :as navigation]))
(defn stream
- [m]
- (let [current-stream @(rf/subscribe [:stream])
- stream-type (-> (if (empty? (:video-streams current-stream))
- (:audio-streams current-stream)
- (:video-streams current-stream))
+ [match]
+ (let [{:keys [name url video-streams audio-streams view-count
+ subscriber-count like-count dislike-count
+ description upload-avatar upload-author
+ upload-url upload-date related-streams
+ thumbnail-url] :as stream} @(rf/subscribe [:stream])
+ stream-type (-> (if (empty? video-streams) audio-streams video-streams)
last
- :content)]
- [:div.flex.flex-col.justify-center.p-5.items-center
- [:div.flex.justify-center.py-2
- [:div.flex.justify-center {:class "w-4/5"}
- [:video.min-w-full.h-auto {:src stream-type :controls true}]]]
- [:div.flex.text-white
- [:button.border.rounded.border-slate-900.p-2.bg-slate-800
- {:on-click #(rf/dispatch [:switch-to-global-player current-stream])}
- "Add to global stream"]
- [:a {:href (:url current-stream)}
- "Open original source"]]
- [:div.flex.flex-col.items-center.py-2 {:class "w-4/5"}
- [:div.min-w-full.py-2
- [:h1.text-xl.font-extrabold (:name current-stream)]]
- [:div.min-w-full.py-2
- [:p (:description current-stream)]]]]))
+ :content)
+ page-loading? @(rf/subscribe [:show-page-loading])
+ service-color @(rf/subscribe [:service-color])]
+ [:div.flex.flex-col.p-5.items-center.justify-center.text-white.flex-auto
+ (if page-loading?
+ [loading/page-loading-icon service-color]
+ [:div {:class "w-4/5"}
+ [navigation/back-button]
+ [:div.flex.justify-center.relative.my-2
+ {:style {:background (str "center / cover no-repeat url('" thumbnail-url"')")
+ :height "450px"}}
+ [:video.min-h-full.absolute.bottom-0.object-cover {:src stream-type :controls true :width "100%"}]]
+ [:div.flex.text-white.flex.w-full.my-1
+ [:button.border.rounded.border-black.p-2.bg-stone-800
+ {:on-click #(rf/dispatch [::events/switch-to-global-player stream])}
+ [:i.fa-solid.fa-headphones]]
+ [:a {:href (:url stream)}
+ [:button.border.rounded.border-black.p-2.bg-stone-800.mx-2
+ [:i.fa-solid.fa-external-link-alt]]]]
+ [:div.flex.flex-col.py-1
+ [:div.min-w-full.py-3
+ [:h1.text-xl.font-extrabold name]]
+ [:div.flex.justify-between.py-2
+ [:div.flex.items-center.flex-auto
+ (when upload-avatar
+ [:div
+ [:img.rounded-full {:src upload-avatar :alt upload-author}]])
+ [:div.mx-2
+ [:a {:href (rfe/href :tau.routes/channel nil {:url upload-url})} upload-author]
+ (when subscriber-count
+ [:div.flex.my-2
+ [:i.fa-solid.fa-users]
+ [:p.mx-2 (.toLocaleString subscriber-count)]])]]
+ [:div
+ (when view-count
+ [:p
+ [:i.fa-solid.fa-eye]
+ [:span.mx-2 (.toLocaleString view-count)]])
+ [:div
+ (when like-count
+ [:p
+ [:i.fa-solid.fa-thumbs-up]
+ [:span.mx-2 like-count]])
+ (when dislike-count
+ [:p
+ [:i.fa-solid.fa-thumbs-down]
+ [:span.mx-2 dislike-count]])]
+ (when upload-date
+ [:p (-> upload-date
+ js/Date.parse
+ js/Date.
+ .toDateString)])]]
+ [:div.min-w-full.py-3
+ [:h1 name]
+ [:p description]]
+ [:div.py-3
+ [:h1.text-lg.bold "Related Results"]
+ [:div.flex.justify-center.align-center.flex-wrap
+ (for [[i item] (map-indexed vector related-streams)]
+ (cond
+ (:duration item) [items/stream-item i item]
+ (:subscriber-count item) [items/channel-item i item]
+ (:stream-count item) [items/playlist-item i item]))]]]])]))