diff --git a/src/cljs/nr/account.cljs b/src/cljs/nr/account.cljs index e51b82e4be..d86d1a7016 100644 --- a/src/cljs/nr/account.cljs +++ b/src/cljs/nr/account.cljs @@ -51,6 +51,7 @@ (swap! app-state assoc-in [:options :ghost-trojans] (:ghost-trojans @s)) (swap! app-state assoc-in [:options :display-encounter-info] (:display-encounter-info @s)) (swap! app-state assoc-in [:options :sides-overlap] (:sides-overlap @s)) + (swap! app-state assoc-in [:options :log-timestamps] (:log-timestamps @s)) (swap! app-state assoc-in [:options :runner-board-order] (:runner-board-order @s)) (swap! app-state assoc-in [:options :log-width] (:log-width @s)) (swap! app-state assoc-in [:options :log-top] (:log-top @s)) @@ -72,6 +73,7 @@ (.setItem js/localStorage "ghost-trojans" (:ghost-trojans @s)) (.setItem js/localStorage "display-encounter-info" (:display-encounter-info @s)) (.setItem js/localStorage "sides-overlap" (:sides-overlap @s)) + (.setItem js/localStorage "log-timestamps" (:log-timestamps @s)) (.setItem js/localStorage "runner-board-order" (:runner-board-order @s)) (.setItem js/localStorage "card-back" (:card-back @s)) (.setItem js/localStorage "card-zoom" (:card-zoom @s)) @@ -392,6 +394,12 @@ :checked (:sides-overlap @s) :on-change #(swap! s assoc-in [:sides-overlap] (.. % -target -checked))}] (tr [:settings.sides-overlap "Runner and Corp board may overlap"])]] + [:div + [:label [:input {:type "checkbox" + :value true + :checked (:log-timestamps @s) + :on-change #(swap! s assoc-in [:log-timestamps] (.. % -target -checked))}] + (tr [:settings.log-timestamps "Show log timestamps"])]] [:br] [:h4 (tr [:settings.runner-layout "Runner layout from Corp perspective"])] @@ -615,6 +623,7 @@ :ghost-trojans (get-in @app-state [:options :ghost-trojans]) :display-encounter-info (get-in @app-state [:options :display-encounter-info]) :sides-overlap (get-in @app-state [:options :sides-overlap]) + :log-timestamps (get-in @app-state [:options :log-timestamps]) :player-stats-icons (get-in @app-state [:options :player-stats-icons]) :runner-board-order (get-in @app-state [:options :runner-board-order]) :log-width (get-in @app-state [:options :log-width]) diff --git a/src/cljs/nr/appstate.cljs b/src/cljs/nr/appstate.cljs index be28371693..b9aa85d297 100644 --- a/src/cljs/nr/appstate.cljs +++ b/src/cljs/nr/appstate.cljs @@ -40,6 +40,7 @@ :player-stats-icons (= (get-local-value "player-stats-icons" "true") "true") :stacked-servers (= (get-local-value "stacked-servers" "true") "true") :sides-overlap (= (get-local-value "sides-overlap" "true") "true") + :log-timestamps (= (get-local-value "log-timestamps" "true") "true") :runner-board-order (let [value (get-local-value "runner-board-order" "irl")] (case value "true" "jnet" diff --git a/src/cljs/nr/gameboard/log.cljs b/src/cljs/nr/gameboard/log.cljs index e6a1ce4691..a7c1276520 100644 --- a/src/cljs/nr/gameboard/log.cljs +++ b/src/cljs/nr/gameboard/log.cljs @@ -186,6 +186,23 @@ [show-decklists] [command-menu !input-ref state]])))) +(defn format-system-timestamp [timestamp text corp runner] + (if (get-in @app-state [:options :log-timestamps]) + (render-message (render-player-highlight text corp runner (str "[" (string/replace (.toLocaleTimeString (js/Date. timestamp)) #"\s\w*" "") "]"))) + (render-message (render-player-highlight text corp runner)) + ) + ) + +(defn format-user-timestamp [timestamp user] + (if (get-in @app-state [:options :log-timestamps]) + [:div.timestamp-wrapper + [:div.username (:username user)] + [:div.timestamp "[" (string/replace (.toLocaleTimeString (js/Date. timestamp)) #"\s\w*" "") "]"] + ] + [:div.username (:username user)] + ) + ) + (defn log-messages [] (let [log (r/cursor game-state [:log]) corp (r/cursor game-state [:corp :user :username]) @@ -224,12 +241,13 @@ (fn [{:keys [user text timestamp]}] ^{:key timestamp} (if (= user "__system__") - [:div.system (render-message (render-player-highlight text @corp @runner))] - [:div.message - [avatar user {:opts {:size 38}}] - [:div.content - [:div.username (:username user)] - [:div (render-message text)]]])) + [:div.system + [format-system-timestamp timestamp text @corp @runner]] + [:div.message + [avatar user {:opts {:size 38}}] + [:div.content + [format-user-timestamp timestamp user] + [:div (render-message text)]]])) @log)))}))) (defn log-pane [] diff --git a/src/cljs/nr/gameboard/settings.cljs b/src/cljs/nr/gameboard/settings.cljs index ce68ca5e76..8204d13206 100644 --- a/src/cljs/nr/gameboard/settings.cljs +++ b/src/cljs/nr/gameboard/settings.cljs @@ -66,6 +66,14 @@ :on-change #(swap! app-state assoc-in [:options :runner-board-order] (.. % -target -value)) :checked (= (get-in @app-state [:options :runner-board-order]) (:ref option))}] (:name option)]]))] + [:section + [:h4 (tr [:ingame-settings.log-timestamps "Log timestamps"])] + [:div + [:label [:input {:type "checkbox" + :value true + :checked (get-in @app-state [:options :log-timestamps]) + :on-change #(swap! app-state assoc-in [:options :log-timestamps] (.. % -target -checked))}] + (tr [:ingame-settings.log-timestamps "Show log timestamps"])]]] [:section [:h4 (tr [:ingame-settings.board-overlap "Board overlap"])] diff --git a/src/cljs/nr/utils.cljs b/src/cljs/nr/utils.cljs index 26ed05c9c9..5980f2bc19 100644 --- a/src/cljs/nr/utils.cljs +++ b/src/cljs/nr/utils.cljs @@ -308,18 +308,27 @@ [input] (render-specials (render-icons (render-cards input)))) -(defn- player-highlight-patterns-impl [corp runner] +(defn wrap-timestamp + [element timestamp] + (if (some? timestamp) + [:div.timestamp-wrapper-system element [:span.timestamp.timestamp-system timestamp]] + element)) + +(defn- player-highlight-patterns-impl [corp runner timestamp] (letfn [(regex-of [player-name] (re-pattern (str "^" (regex-escape player-name))))] - (->> {corp [:span.corp-username corp] - runner [:span.runner-username runner]} + (->> {corp (wrap-timestamp [:span.corp-username corp] timestamp) + runner (wrap-timestamp [:span.runner-username runner] timestamp)} (filter (fn [[k _]] (not-empty k))) (mapcat (fn [[k v]] [[(regex-of k) v] [(regex-of (str "[!]" k)) [:<> [:div.smallwarning "!"] v]]])) (sort-by (comp count str first) >)))) (def player-highlight-patterns (memoize player-highlight-patterns-impl)) -(defn render-player-highlight [message corp runner] - (render-input message (player-highlight-patterns corp runner))) +(defn render-player-highlight + ([message corp runner] (render-player-highlight message corp runner nil)) + ([message corp runner timestamp] + (render-input message (player-highlight-patterns corp runner timestamp))) + ) (defn player-highlight-option-class [] (case (get-in @app-state [:options :log-player-highlight]) diff --git a/src/css/base.styl b/src/css/base.styl index f0631347d8..adc0308a2b 100644 --- a/src/css/base.styl +++ b/src/css/base.styl @@ -253,7 +253,7 @@ button.off margin-left: 2px margin-right: 2px width: 12px - display: inline-block + display: inline-block !important text-align: center .warning diff --git a/src/css/chat.styl b/src/css/chat.styl index 6b24df6467..a44c540c81 100644 --- a/src/css/chat.styl +++ b/src/css/chat.styl @@ -31,6 +31,30 @@ left: -70px transition(all 0.2s ease-in-out) +.timestamp-wrapper + display: flex + + .username + margin-right: 0 + + .timestamp + color: #999999 + font-size .5rem + display inline-flex + margin-left: .12rem + line-height: .5rem + margin-top: .15rem + +.timestamp-wrapper-system + display: inline-flex + line-height .75rem !important + + .timestamp + color: #999999 + font-size .5rem + display inline-flex + margin-left: .12rem + .message display-flex() margin-bottom: 5px diff --git a/src/css/gameboard.styl b/src/css/gameboard.styl index b563fcf23c..473c212d49 100644 --- a/src/css/gameboard.styl +++ b/src/css/gameboard.styl @@ -1077,7 +1077,8 @@ .username font-size: .875rem - margin-top: -2px + margin-top: -.0875rem + line-height: .91rem .avatar width: 28px