0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-15 17:21:17 -05:00

♻️ Refactor html5 history.

This commit is contained in:
Andrey Antukh 2020-04-30 17:16:10 +02:00
parent d856b9aae3
commit 7fe7c3da6c
9 changed files with 114 additions and 128 deletions

View file

@ -20,7 +20,6 @@
[uxbox.main.ui.modal :refer [modal]]
[uxbox.main.worker]
[uxbox.util.dom :as dom]
[uxbox.util.html.history :as html-history]
[uxbox.util.i18n :as i18n]
[uxbox.util.theme :as theme]
[uxbox.util.router :as rt]
@ -29,38 +28,33 @@
(declare reinit)
(defn- on-navigate
(defn on-navigate
[router path]
(let [match (rt/match router path)
profile (:profile storage)]
(cond
(and (= path "") (not profile))
(st/emit! (rt/nav :login))
(rt/nav :login)
(and (= path "") profile)
(st/emit! (rt/nav :dashboard-team {:team-id (:default-team-id profile)}))
(rt/nav :dashboard-team {:team-id (:default-team-id profile)})
(nil? match)
(st/emit! (rt/nav :not-found))
(rt/nav :not-found)
:else
(st/emit! #(assoc % :route match)))))
#(assoc % :route match))))
(defn init-ui
[]
(let [router (rt/init ui/routes)
cpath (deref html-history/path)]
(st/emit! (rt/initialize-router ui/routes)
(rt/initialize-history on-navigate))
(st/emit! #(assoc % :router router))
(add-watch html-history/path ::main #(on-navigate router %4))
(when (:profile storage)
(st/emit! udu/fetch-profile))
(when (:profile storage)
(st/emit! udu/fetch-profile))
(mf/mount (mf/element ui/app) (dom/get-element "app"))
(mf/mount (mf/element modal) (dom/get-element "modal"))
(on-navigate router cpath)))
(mf/mount (mf/element ui/app) (dom/get-element "app"))
(mf/mount (mf/element modal) (dom/get-element "modal")))
(defn ^:export init
[]
@ -73,7 +67,6 @@
(defn reinit
[]
(remove-watch html-history/path ::main)
(mf/unmount (dom/get-element "app"))
(mf/unmount (dom/get-element "modal"))
(init-ui))

View file

@ -83,7 +83,7 @@
(group-by :backend (vals db)))))
(add-watch fontsdb "main"
(fn [_ _ _ db]
(ts/schedule-on-idle #(materialize-fontsview db))))
(ts/schedule #(materialize-fontsview db))))
(defn register!
[backend fonts]

View file

@ -12,7 +12,7 @@
(:require
[beicon.core :as rx]
[rumext.alpha :as mf]
[uxbox.util.timers :refer [schedule-on-idle]]))
[uxbox.util.timers :refer [schedule]]))
(mf/defc chunked-list
[{:keys [items children initial-size chunk-size]
@ -34,7 +34,7 @@
:pending-num (- pending-num chunk-size)}))
(after-render [state]
(when (pos? (:pending-num @state))
(let [sem (schedule-on-idle (fn [] (swap! state update-state)))]
(let [sem (schedule (fn [] (swap! state update-state)))]
#(rx/cancel! sem))))]
(let [initial (mf/use-memo initial-state)

View file

@ -0,0 +1,49 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This Source Code Form is "Incompatible With Secondary Licenses", as
* defined by the Mozilla Public License, v. 2.0.
*
* Copyright (c) 2020 UXBOX Labs SL
*/
"use strict";
goog.provide("uxbox.util.browser_history");
goog.require("goog.history.Html5History");
goog.scope(function() {
const self = uxbox.util.browser_history;
const Html5History = goog.history.Html5History;
class TokenTransformer {
retrieveToken(pathPrefix, location) {
return location.pathname.substr(pathPrefix.length) + location.search;
}
createUrl(token, pathPrefix, location) {
return pathPrefix + token;
}
}
self.create = function() {
const instance = new Html5History(null, new TokenTransformer());
instance.setUseFragment(true);
return instance;
};
self.enable_BANG_ = function(instance) {
instance.setEnabled(true);
};
self.disable_BANG_ = function(instance) {
instance.setEnabled(false);
};
self.set_token_BANG_ = function(instance, token) {
instance.setToken(token);
}
});

View file

@ -9,7 +9,7 @@
(:require
[beicon.core :as rx]
[rumext.alpha :as mf]
[uxbox.util.timers :refer [schedule-on-idle]]))
[uxbox.util.timers :refer [schedule]]))
;; TODO: this file is DEPRECATED (pending deletion)
@ -33,7 +33,7 @@
:pending-num (- pending-num chunk-size)}))
(after-render [state]
(when (pos? (:pending-num @state))
(let [sem (schedule-on-idle (fn [] (swap! state update-state)))]
(let [sem (schedule (fn [] (swap! state update-state)))]
#(rx/cancel! sem))))]
(let [initial (mf/use-memo initial-state)

View file

@ -1,60 +0,0 @@
/**
* TokenTransformer
*
* @author Paul Anderson <paul@andersonpaul.com>, 2018
* @license BSD License <https://opensource.org/licenses/BSD-2-Clause>
*/
goog.provide('uxbox.util.html.TokenTransformer');
goog.require('goog.history.Html5History');
goog.scope(function() {
/**
* A goog.history.Html5History.TokenTransformer implementation that
* includes the query string in the token.
*
* The implementation of token<->url transforms in
* `goog.history.Html5History`, when useFragment is false and no custom
* transformer is supplied, assumes that a token is equivalent to
* `window.location.pathname` minus any configured path prefix. Since
* bide allows constructing urls that include a query string, we want
* to be able to store those as tokens.
*
* Addresses funcool/bide#15.
*
* @constructor
* @implements {goog.history.Html5History.TokenTransformer}
*/
uxbox.util.html.TokenTransformer = function () {};
/**
* Retrieves a history token given the path prefix and
* `window.location` object.
*
* @param {string} pathPrefix The path prefix to use when storing token
* in a path; always begin with a slash.
* @param {Location} location The `window.location` object.
* Treat this object as read-only.
* @return {string} token The history token.
*/
uxbox.util.html.TokenTransformer.prototype.retrieveToken = function(pathPrefix, location) {
return location.pathname.substr(pathPrefix.length) + location.search;
};
/**
* Creates a URL to be pushed into HTML5 history stack when storing
* token without using hash fragment.
*
* @param {string} token The history token.
* @param {string} pathPrefix The path prefix to use when storing token
* in a path; always begin with a slash.
* @param {Location} location The `window.location` object.
* Treat this object as read-only.
* @return {string} url The complete URL string from path onwards
* (without {@code protocol://host:port} part); must begin with a
* slash.
*/
uxbox.util.html.TokenTransformer.prototype.createUrl = function(token, pathPrefix, location) {
return pathPrefix + token;
};
});

View file

@ -1,31 +0,0 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) 2019 Andrey Antukh <niwi@niwi.nz>
(ns uxbox.util.html.history
"A singleton abstraction for the html5 fragment based history."
(:require [goog.events :as e])
(:import uxbox.util.html.TokenTransformer
goog.history.Html5History
goog.history.EventType))
(defonce ^:private +instance+
(doto (Html5History. nil (TokenTransformer.))
(.setUseFragment true)
(.setEnabled true)))
(defonce path (atom (.getToken +instance+)))
(defonce ^:private +instance-sem+
(e/listen +instance+ EventType.NAVIGATE
#(reset! path (.-token %))))
(defn set-path!
[path]
(.setToken +instance+ path))
(defn replace-path!
[path]
(.replaceToken +instance+ path))

View file

@ -7,16 +7,19 @@
(ns uxbox.util.router
(:refer-clojure :exclude [resolve])
(:require
[beicon.core :as rx]
[rumext.alpha :as mf]
[reitit.core :as r]
[goog.events :as e]
[cuerdas.core :as str]
[potok.core :as ptk]
[uxbox.common.data :as d]
[uxbox.util.html.history :as html-history])
[uxbox.util.browser-history :as bhistory]
[uxbox.common.data :as d])
(:import
goog.Uri
goog.Uri.QueryData))
;; --- API
;; --- Router API
(defn- parse-query-data
[^QueryData qdata]
@ -50,10 +53,17 @@
(.setQueryData uri qdt)
(.toString uri))))))
(defn init
(defn create
[routes]
(r/router routes))
(defn initialize-router
[routes]
(ptk/reify ::initialize-router
ptk/UpdateEvent
(update [_ state]
(assoc state :router (create routes)))))
(defn query-params
"Given goog.Uri, read query parameters into Clojure map."
[^goog.Uri uri]
@ -63,13 +73,6 @@
(map (juxt keyword #(.get q %)))
(into {}))))
(defn navigate!
([router id] (navigate! router id {} {}))
([router id params] (navigate! router id params {}))
([router id params qparams]
(-> (resolve router id params qparams)
(html-history/set-path!))))
(defn match
"Given routing tree and current path, return match with possibly
coerced parameters. Return nil if no match found."
@ -87,8 +90,10 @@
(deftype Navigate [id params qparams]
ptk/EffectEvent
(effect [_ state stream]
(let [router (:router state)]
(navigate! router id params qparams))))
(let [router (:router state)
history (:history state)
path (resolve router id params qparams)]
(bhistory/set-token! history path))))
(defn nav
([id] (nav id nil nil))
@ -99,3 +104,30 @@
(def navigate nav)
;; --- History API
(defn initialize-history
[on-change]
(ptk/reify ::initialize-history
ptk/UpdateEvent
(update [_ state]
(let [history (bhistory/create)]
(assoc state :history history)))
ptk/WatchEvent
(watch [_ state stream]
(let [stoper (rx/filter (ptk/type? ::initialize-history) stream)
history (:history state)
router (:router state)]
(->> (rx/create (fn [sink]
(let [key (e/listen history "navigate" #(sink (.-token %)))]
(bhistory/enable! history)
(fn []
(bhistory/disable! history)
(e/unlistenByKey key)))))
(rx/map #(on-change router %))
(rx/take-until stoper))))))

View file

@ -2,7 +2,10 @@
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) 2016-2019 Andrey Antukh <niwi@niwi.nz>
;; This Source Code Form is "Incompatible With Secondary Licenses", as
;; defined by the Mozilla Public License, v. 2.0.
;;
;; Copyright (c) 2020 UXBOX Labs SL
(ns uxbox.util.timers
(:require [beicon.core :as rx]))