aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--deps.edn3
-rw-r--r--src/backend/tubo/routes.clj1
-rw-r--r--src/frontend/tubo/events.cljs109
-rw-r--r--src/frontend/tubo/routes.cljs6
-rw-r--r--src/frontend/tubo/subs.cljs11
-rw-r--r--src/frontend/tubo/views/settings.cljs35
6 files changed, 126 insertions, 39 deletions
diff --git a/deps.edn b/deps.edn
index 2fe8e0a..6ae47c4 100644
--- a/deps.edn
+++ b/deps.edn
@@ -23,6 +23,7 @@
reagent/reagent {:mvn/version "1.1.1"}
re-frame/re-frame {:mvn/version "1.3.0"}
day8.re-frame/http-fx {:mvn/version "0.2.4"}
- cljs-ajax/cljs-ajax {:mvn/version "0.8.4"}}
+ cljs-ajax/cljs-ajax {:mvn/version "0.8.4"}
+ akiroz.re-frame/storage {:mvn/version "0.1.4"}}
:main-opts ["-m" "shadow.cljs.devtools.cli"]}
:run {:main-opts ["-m" "tubo.core"]}}}
diff --git a/src/backend/tubo/routes.clj b/src/backend/tubo/routes.clj
index d42b432..e22f35f 100644
--- a/src/backend/tubo/routes.clj
+++ b/src/backend/tubo/routes.clj
@@ -19,6 +19,7 @@
["/channel" handler/index]
["/playlist" handler/index]
["/kiosk" handler/index]
+ ["/settings" handler/index]
["/api"
["/services"
["" {:get handler/services}]
diff --git a/src/frontend/tubo/events.cljs b/src/frontend/tubo/events.cljs
index 152674d..9c2ab48 100644
--- a/src/frontend/tubo/events.cljs
+++ b/src/frontend/tubo/events.cljs
@@ -1,24 +1,39 @@
(ns tubo.events
(:require
+ [akiroz.re-frame.storage :refer [reg-co-fx!]]
[day8.re-frame.http-fx]
[re-frame.core :as rf]
[reitit.frontend.easy :as rfe]
[reitit.frontend.controllers :as rfc]
[tubo.api :as api]))
-(rf/reg-event-db
- ::initialize-db
- (fn [_ _]
- {:global-search ""
- :service-id 0
- :service-color "#cc0000"
- :stream {}
- :search-results []
- :services []
- :media-queue []
- :media-queue-pos 0
- :current-match nil
- :page-scroll 0}))
+(reg-co-fx! :tubo {:fx :store :cofx :store})
+
+(rf/reg-event-fx
+ ::initialize-db
+ [(rf/inject-cofx :store)]
+ (fn [{:keys [store]} _]
+ (let [{:keys [current-theme show-comments show-related show-description
+ media-queue media-queue-pos show-audio-player
+ loop-file loop-playlist]} store]
+ {:db
+ {:search-query ""
+ :service-id 0
+ :stream {}
+ :search-results []
+ :services []
+ :loop-file (if (nil? loop-file) false loop-file)
+ :loop-playlist (if (nil? loop-playlist) true loop-playlist)
+ :media-queue (if (nil? media-queue) [] media-queue)
+ :media-queue-pos (if (nil? media-queue-pos) 0 media-queue-pos)
+ :current-match nil
+ :show-audio-player (if (nil? show-audio-player) false show-audio-player)
+ :settings
+ {:current-theme (if (nil? current-theme) :light current-theme)
+ :themes #{:light :dark}
+ :show-comments (if (nil? show-comments) true show-comments)
+ :show-related (if (nil? show-related) true show-related)
+ :show-description (if (nil? show-description) true show-description)}}})))
(rf/reg-fx
::scroll-to-top
@@ -170,35 +185,50 @@
(rf/reg-event-fx
::add-to-media-queue
- (fn [{:keys [db]} [_ stream]]
- (let [media-queue (update db :media-queue conj stream)]
- {:db media-queue
- :fx [[:dispatch [::fetch-global-player-stream (:url stream)]]]})))
+ [(rf/inject-cofx :store)]
+ (fn [{:keys [db store]} [_ stream]]
+ (let [updated-db (update db :media-queue conj stream)]
+ {:db updated-db
+ :store (assoc store :media-queue (:media-queue updated-db))
+ :fx [[:dispatch [::fetch-audio-player-stream (:url stream)]]]})))
(rf/reg-event-fx
::change-media-queue-pos
- (fn [{:keys [db]} [_ idx]]
- {:db (assoc db :media-queue-pos idx)}))
+ [(rf/inject-cofx :store)]
+ (fn [{:keys [db store]} [_ idx]]
+ {:db (assoc db :media-queue-pos idx)
+ :store (assoc store :media-queue-pos idx)}))
-(rf/reg-event-db
+(rf/reg-event-fx
::change-media-queue-stream
- (fn [db [_ src]]
- (let [idx (- (count (:media-queue db)) 1)]
+ [(rf/inject-cofx :store)]
+ (fn [{:keys [db store]} [_ src]]
+ (let [idx (- (count (:media-queue db)) 1)
+ update-entry
+ (fn [elem] (assoc-in elem [:media-queue idx :stream] src))]
(when-not (-> db :media-queue (nth idx) :stream)
- (assoc-in db [:media-queue idx :stream] src)))))
+ {:db (update-entry db)
+ :store (update-entry store)}))))
-(rf/reg-event-db
- ::toggle-global-player
- (fn [db _]
- (-> db
- (assoc :show-global-player (not (:show-global-player db)))
- (assoc :media-queue [])
- (assoc :media-queue-pos 0))))
+(rf/reg-event-fx
+ ::toggle-audio-player
+ [(rf/inject-cofx :store)]
+ (fn [{:keys [db store]} _]
+ (let [remove-entries
+ (fn [elem]
+ (-> elem
+ (assoc :show-audio-player (not (:show-audio-player elem)))
+ (assoc :media-queue [])
+ (assoc :media-queue-pos 0)))]
+ {:db (remove-entries db)
+ :store (remove-entries store)})))
(rf/reg-event-fx
- ::switch-to-global-player
- (fn [{:keys [db]} [_ stream]]
- {:db (assoc db :show-global-player true)
+ ::switch-to-audio-player
+ [(rf/inject-cofx :store)]
+ (fn [{:keys [db store]} [_ stream]]
+ {:db (assoc db :show-audio-player true)
+ :store (assoc store :show-audio-player true)
:fx [[:dispatch [::add-to-media-queue stream]]]}))
(rf/reg-event-db
@@ -236,9 +266,9 @@
(assoc-in [:stream :show-comments] true)))))
(rf/reg-event-db
- ::toggle-comments
- (fn [db _]
- (assoc-in db [:stream :show-comments] (not (-> db :stream :show-comments)))))
+ ::toggle-stream-layout
+ (fn [db [_ layout]]
+ (assoc-in db [:stream layout] (not (-> db :stream layout)))))
(rf/reg-event-db
::toggle-comment-replies
@@ -439,3 +469,10 @@
[::load-search-results] [::bad-response]
{:q query})
:db (assoc db :show-page-loading true))))
+
+(rf/reg-event-fx
+ ::change-setting
+ [(rf/inject-cofx :store)]
+ (fn [{:keys [db store]} [_ key val]]
+ {:db (assoc-in db [:settings key] val)
+ :store (assoc store key val)}))
diff --git a/src/frontend/tubo/routes.cljs b/src/frontend/tubo/routes.cljs
index 725c999..1049812 100644
--- a/src/frontend/tubo/routes.cljs
+++ b/src/frontend/tubo/routes.cljs
@@ -8,6 +8,7 @@
[tubo.views.kiosk :as kiosk]
[tubo.views.playlist :as playlist]
[tubo.views.search :as search]
+ [tubo.views.settings :as settings]
[tubo.views.stream :as stream]))
(def router
@@ -40,11 +41,12 @@
:name ::kiosk
:controllers [{:parameters {:query [:kioskId :serviceId]}
:start (fn [{{:keys [serviceId kioskId]} :query}]
- (rf/dispatch [::events/get-kiosk-page serviceId kioskId]))}]}]]))
+ (rf/dispatch [::events/get-kiosk-page serviceId kioskId]))}]}]
+ ["/settings" {:view settings/settings-page
+ :name ::settings}]]))
(defn on-navigate
[new-match]
- (rf/dispatch [::events/reset-page-scroll])
(when new-match
(rf/dispatch [::events/navigated new-match])))
diff --git a/src/frontend/tubo/subs.cljs b/src/frontend/tubo/subs.cljs
index 6e7efb2..1740651 100644
--- a/src/frontend/tubo/subs.cljs
+++ b/src/frontend/tubo/subs.cljs
@@ -106,3 +106,14 @@
:show-mobile-nav
(fn [db _]
(:show-mobile-nav db)))
+
+(rf/reg-sub
+ :theme
+ (fn [db _]
+ (:theme db)))
+
+(rf/reg-sub
+ :settings
+ (fn [db _]
+ (:settings db)))
+
diff --git a/src/frontend/tubo/views/settings.cljs b/src/frontend/tubo/views/settings.cljs
new file mode 100644
index 0000000..de1f7a7
--- /dev/null
+++ b/src/frontend/tubo/views/settings.cljs
@@ -0,0 +1,35 @@
+(ns tubo.views.settings
+ (:require
+ [re-frame.core :as rf]
+ [tubo.events :as events]
+ [tubo.components.navigation :as navigation]))
+
+(defn boolean-input
+ [label key value]
+ [:div.w-full.flex.justify-between.items-center.py-2
+ [:label label]
+ [:input
+ {:type "checkbox"
+ :checked value
+ :value value
+ :on-change #(rf/dispatch [::events/change-setting key (not value)])}]])
+
+(defn settings-page []
+ (let [{:keys [current-theme themes show-comments show-related
+ show-description]} @(rf/subscribe [:settings])
+ service-color @(rf/subscribe [:service-color])]
+ [:div.flex.flex-col.items-center.px-5.py-2.flex-auto
+ [:div.flex.flex-col.flex-auto {:class "ml:w-4/5 xl:w-3/5"}
+ [navigation/back-button service-color]
+ [:h1.text-2xl.font-bold.py-6 "Settings"]
+ [:form.flex.flex-wrap
+ [:div.w-full.flex.justify-between.items-center.py-2
+ [:label "Theme"]
+ [:select.focus:ring-transparent.bg-transparent.font-bold.font-nunito
+ {:value current-theme
+ :on-change #(rf/dispatch [::events/change-setting :current-theme (.. % -target -value)])}
+ (for [[i theme] (map-indexed vector themes)]
+ [:option.dark:bg-neutral-900.border-none {:value theme :key i} theme])]]
+ [boolean-input "Show description?" :show-description show-description]
+ [boolean-input "Show comments?" :show-comments show-comments]
+ [boolean-input "Show related videos?" :show-related show-related]]]]))