From: john at keeping.me.uk (John Keeping)
Subject: [PATCH] cgit.css: add dynamic age update
Date: Sun, 24 Jun 2018 12:52:53 +0100 [thread overview]
Message-ID: <20180624115253.GM6584@john.keeping.me.uk> (raw)
In-Reply-To: <152982719141.10974.13155108541444051299.stgit@mail.warmcat.com>
Subject should be "cgit.js: " not cgit.css!
On Sun, Jun 24, 2018 at 03:59:51PM +0800, Andy Green wrote:
> This patch updates the emitted "ages" dynamically on the client side.
>
> After updating on completion of the document load, it sets a timer
> to update according to the smallest age it found. If there are any
> ages listed in minutes, then it will update again in 10s (this can
> never happen more than twelve times on a given page then). When the
> most recent age is in hours, it updates every 5m. If days, then
> every 30m and so on.
>
> This keeps the cost of the dynamic updates at worst once per 10s
> and trending towards being trivially cheap after a couple of minutes.
> The updates are done entirely on the client side without contact
> with the server.
>
> To make this work reliably, since parsing datetimes is unreliable in
> browser js, the unix time is added as an attribute to all age spans.
>
> To make that reliable cross-platform, the unix time is treated as a
> uint64_t when it is formatted for printing.
>
> The rules for display conversion of the age is aligned with the
> existing server-side rules in ui-shared.h.
>
> If the client or server-side time are not synchronized by ntpd etc,
> ages shown on the client will not relate to the original ages computed
> at the server. The client updates the ages immediately when the
> DOM has finished loading, so in the case the times at the server and
> client are not aligned, this patch changes what the user sees on the
> page to reflect patch age compared to client time.
>
> If the server and client clocks are aligned, this patch makes no
> difference to what is seen on the page.
>
> Signed-off-by: Andy Green <andy at warmcat.com>
If we're going to start depending on JS, should we take the robust
approach to this and never generate relative times on the server? Or do
so only for <noscript>?
I'd really like to here other people's opinions on this.
Personally, I'm slightly negative because while I do regularly use some
sites that take this approach (including having long-lived tabs open on
pages like this), I always end up refreshing the page anyway when I go
back to the tab, because new content doesn't load without doing so.
So I'm not sure what this tells me except "it's been at least N
{seconds,minutes,hours,days} since you last refreshed this page". And
the first thing I'm going to do is hit refresh anyway.
> ---
> cgit.h | 1 +
> cgit.js | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> ui-shared.c | 2 +-
> 3 files changed, 60 insertions(+), 1 deletion(-)
>
> diff --git a/cgit.h b/cgit.h
> index 2579ce4..9b21919 100644
> --- a/cgit.h
> +++ b/cgit.h
> @@ -24,6 +24,7 @@
> #include <utf8.h>
> #include <notes.h>
> #include <graph.h>
> +#include <inttypes.h>
>
> /* Add isgraph(x) to Git's sane ctype support (see git-compat-util.h) */
> #undef isgraph
> diff --git a/cgit.js b/cgit.js
> index e2c3799..e13faf2 100644
> --- a/cgit.js
> +++ b/cgit.js
> @@ -145,6 +145,61 @@ function cgit_line_range_click(e) {
> cgit_copy_clipboard(cp);
> }
>
> +/* this follows the logic and suffixes used in ui-shared.c */
> +
> +var cgit_age_classes = [ "age-mins", "age-hours", "age-days", "age-weeks", "age-months", "age-years" ];
> +var cgit_age_suffix = [ "min.", "hours", "days", "weeks", "months", "years", "years" ];
> +var cgit_age_next = [ 60, 3600, 24 * 3600, 7 * 24 * 3600, 30 * 24 * 3600, 365 * 24 * 3600, 365 * 24 * 3600 ];
> +var cgit_age_limit = [ 7200, 24 * 7200, 7 * 24 * 7200, 30 * 24 * 7200, 365 * 25 * 7200, 365 * 25 * 7200 ];
> +var cgit_update_next = [ 10, 5 * 60, 1800, 24 * 3600, 24 * 3600, 24 * 3600, 24 * 3600 ];
> +
> +function cgit_render_age(e, age)
> +{
> + var t, n;
> +
> + for (n = 0; n < cgit_age_classes.length; n++)
> + if (age < cgit_age_limit[n])
> + break;
> +
> + t = Math.round(age / cgit_age_next[n]) + " " + cgit_age_suffix[n];
> +
> + if (e.textContent != t) {
> + e.textContent = t;
> + if (n == cgit_age_classes.length)
> + n--;
> + if (e.className != cgit_age_classes[n])
> + e.className = cgit_age_classes[n];
> + }
> +}
> +
> +function cgit_aging()
> +{
> + var n, next = 24 * 3600,
> + now_ut = Math.round((new Date().getTime() / 1000));
> +
> + for (n = 0; n < cgit_age_classes.length; n++) {
> + var m, elems = document.getElementsByClassName(cgit_age_classes[n]);
> +
> + if (elems.length && cgit_update_next[n] < next)
> + next = cgit_update_next[n];
> +
> + for (m = 0; m < elems.length; m++) {
> + var age = now_ut - elems[m].getAttribute("ut");
> +
> + cgit_render_age(elems[m], age);
> + }
> + }
> +
> + /*
> + * We only need to come back when the age might have changed.
> + * Eg, if everything is counted in hours already, once per
> + * 5 minutes is accurate enough.
> + */
> +
> + window.setTimeout(cgit_aging, next * 1000);
> +}
> +
> +
> /* line range highlight */
>
> document.addEventListener("DOMContentLoaded", function() {
> @@ -152,6 +207,9 @@ document.addEventListener("DOMContentLoaded", function() {
> var e = document.getElementById("linenumber_td");
> if (e)
> e.addEventListener("click", cgit_line_range_click, true);
> +
> + cgit_aging();
> +
> }, false);
> window.addEventListener("hashchange", function() {
> cgit_line_range_highlight();
> diff --git a/ui-shared.c b/ui-shared.c
> index 836c590..8567c06 100644
> --- a/ui-shared.c
> +++ b/ui-shared.c
> @@ -670,7 +670,7 @@ const struct date_mode *cgit_date_mode(enum date_mode_type type)
> static void print_rel_date(time_t t, int tz, double value,
> const char *class, const char *suffix)
> {
> - htmlf("<span class='%s' title='", class);
> + htmlf("<span class='%s' ut='%" PRIu64 "' title='", class, (uint64_t)t);
> html_attr(show_date(t, tz, cgit_date_mode(DATE_ISO8601)));
> htmlf("'>%.0f %s</span>", value, suffix);
> }
>
> _______________________________________________
> CGit mailing list
> CGit at lists.zx2c4.com
> https://lists.zx2c4.com/mailman/listinfo/cgit
next prev parent reply other threads:[~2018-06-24 11:52 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-06-24 7:59 andy
2018-06-24 11:52 ` john [this message]
2018-06-24 12:11 ` andy
2018-06-24 22:58 ` list
2018-06-25 0:15 ` andy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180624115253.GM6584@john.keeping.me.uk \
--to=cgit@lists.zx2c4.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).