diff options
author | Miguel Ángel Moreno <mail@migalmoreno.com> | 2022-12-26 22:02:33 +0100 |
---|---|---|
committer | Miguel Ángel Moreno <mail@migalmoreno.com> | 2022-12-26 22:02:33 +0100 |
commit | b5404ac06a3a09d83bef66552083254fdff12196 (patch) | |
tree | 02785ab11a3dcf328e8d1375a7b76abb2edbf382 /src/frontend/tau/views | |
parent | dce9e36b352509665887ea1ca2e6f81904038a11 (diff) |
feat(frontend): Modularize components and add pagination
Diffstat (limited to 'src/frontend/tau/views')
-rw-r--r-- | src/frontend/tau/views/channel.cljs | 41 | ||||
-rw-r--r-- | src/frontend/tau/views/home.cljs | 2 | ||||
-rw-r--r-- | src/frontend/tau/views/kiosk.cljs | 9 | ||||
-rw-r--r-- | src/frontend/tau/views/playlist.cljs | 5 | ||||
-rw-r--r-- | src/frontend/tau/views/search.cljs | 64 | ||||
-rw-r--r-- | src/frontend/tau/views/stream.cljs | 98 |
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]))]]]])])) |