diff options
author | Miguel Ángel Moreno <mail@migalmoreno.com> | 2023-10-22 20:35:54 +0200 |
---|---|---|
committer | Miguel Ángel Moreno <mail@migalmoreno.com> | 2023-10-22 20:35:54 +0200 |
commit | 821f50f900d855fbbf6fb3625ed66555a9f7ae98 (patch) | |
tree | 9d20382ed20ccadf9536ebc6eed43e157ef3b456 /src | |
parent | 24d2ad960199ba276eb973da6795aa87d07d4a2a (diff) |
feat(frontend): add initial local settings persistence support
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/tubo/routes.clj | 1 | ||||
-rw-r--r-- | src/frontend/tubo/events.cljs | 109 | ||||
-rw-r--r-- | src/frontend/tubo/routes.cljs | 6 | ||||
-rw-r--r-- | src/frontend/tubo/subs.cljs | 11 | ||||
-rw-r--r-- | src/frontend/tubo/views/settings.cljs | 35 |
5 files changed, 124 insertions, 38 deletions
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]]]])) |