Warmcat homepage andy@warmcat.com
libwebsockets
{"schema":"libjg2-1", "vpath":"/git/", "avatar":"/git/avatar/", "alang":"", "gen_ut":1745907902, "reponame":"cgit", "desc":"CGI gitweb", "owner": { "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" },"url":"https://warmcat.com/repo/cgit", "f":3, "items": [ {"schema":"libjg2-1", "cid":"0f0b00b0890fc064adbad17eed468157", "commit": {"type":"commit", "time": 1530589970, "time_ofs": 480, "oid_tree": { "oid": "74b1dd86e08487d005e878b71aa4fd03dfe930bc", "alias": []}, "oid":{ "oid": "7def56a6bf82133385646222c74a5f3790803d45", "alias": []}, "msg": "cgit.css: add dynamic age update", "sig_commit": { "git_time": { "time": 1530589970, "offset": 480 }, "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" }, "sig_author": { "git_time": { "time": 1529823920, "offset": 480 }, "name": "Andy Green", "email": "andy@warmcat.com", "md5": "c50933ca2aa61e0fe2c43d46bb6b59cb" }}, "body": "cgit.css: add dynamic age update\n\nThis patch updates the emitted \u0022ages\u0022 dynamically on the client side.\n\nAfter updating on completion of the document load, it sets a timer\nto update according to the smallest age it found. If there are any\nages listed in minutes, then it will update again in 10s. When the\nmost recent age is in hours, it updates every 5m. If days, then\nevery 30m and so on.\n\nThis keeps the cost of the dynamic updates at worst once per 10s.\nThe updates are done entirely on the client side without contact\nwith the server.\n\nTo make this work reliably, since parsing datetimes is unreliable in\nbrowser js, the unix time is added as an attribute to all age spans.\n\nTo make that reliable cross-platform, the unix time is treated as a\nuint64_t when it is formatted for printing.\n\nThe rules for display conversion of the age is aligned with the\nexisting server-side rules in ui-shared.h.\n\nIf the client or server-side time are not synchronized by ntpd etc,\nages shown on the client will not relate to the original ages computed\nat the server. The client updates the ages immediately when the\nDOM has finished loading, so in the case the times at the server and\nclient are not aligned, this patch changes what the user sees on the\npage to reflect patch age compared to client time.\n\nIf the server and client clocks are aligned, this patch makes no\ndifference to what is seen on the page.\n\nSigned-off-by: Andy Green \u003candy@warmcat.com\u003e" , "diff": "diff --git a/cgit.h b/cgit.h\nindex 390df3b..2923e3a 100644\n--- a/cgit.h\n+++ b/cgit.h\n@@ -24,6 +24,7 @@\n #include \u003cutf8.h\u003e\n #include \u003cnotes.h\u003e\n #include \u003cgraph.h\u003e\n+#include \u003cinttypes.h\u003e\n \n /* Add isgraph(x) to Git's sane ctype support (see git-compat-util.h) */\n #undef isgraph\ndiff --git a/cgit.js b/cgit.js\nindex bc2ba65..d89fdf7 100644\n--- a/cgit.js\n+++ b/cgit.js\n@@ -347,6 +347,61 @@ function line_range_click(e) {\n \tline_range_highlight(0);\n }\n \n+/* this follows the logic and suffixes used in ui-shared.c */\n+\n+var age_classes \u003d [ \u0022age-mins\u0022, \u0022age-hours\u0022, \u0022age-days\u0022, \u0022age-weeks\u0022, \u0022age-months\u0022, \u0022age-years\u0022 ];\n+var age_suffix \u003d [ \u0022min.\u0022, \u0022hours\u0022, \u0022days\u0022, \u0022weeks\u0022, \u0022months\u0022, \u0022years\u0022, \u0022years\u0022 ];\n+var age_next \u003d [ 60, 3600, 24 * 3600, 7 * 24 * 3600, 30 * 24 * 3600, 365 * 24 * 3600, 365 * 24 * 3600 ];\n+var age_limit \u003d [ 7200, 24 * 7200, 7 * 24 * 7200, 30 * 24 * 7200, 365 * 25 * 7200, 365 * 25 * 7200 ];\n+var update_next \u003d [ 10, 5 * 60, 1800, 24 * 3600, 24 * 3600, 24 * 3600, 24 * 3600 ];\n+\n+function render_age(e, age)\n+{\n+\tvar t, n;\n+\n+\tfor (n \u003d 0; n \u003c age_classes.length; n++)\n+\t\tif (age \u003c age_limit[n])\n+\t\t\tbreak;\n+\n+\tt \u003d Math.round(age / age_next[n]) + \u0022 \u0022 + age_suffix[n];\n+\n+\tif (e.textContent !\u003d t) {\n+\t\te.textContent \u003d t;\n+\t\tif (n \u003d\u003d age_classes.length)\n+\t\t\tn--;\n+\t\tif (e.className !\u003d age_classes[n])\n+\t\t\te.className \u003d age_classes[n];\n+\t}\n+}\n+\n+function aging()\n+{\n+\tvar n, next \u003d 24 * 3600,\n+\t now_ut \u003d Math.round((new Date().getTime() / 1000));\n+\n+\tfor (n \u003d 0; n \u003c age_classes.length; n++) {\n+\t\tvar m, elems \u003d document.getElementsByClassName(age_classes[n]);\n+\n+\t\tif (elems.length \u0026\u0026 update_next[n] \u003c next)\n+\t\t\tnext \u003d update_next[n];\n+\n+\t\tfor (m \u003d 0; m \u003c elems.length; m++) {\n+\t\t\tvar age \u003d now_ut - elems[m].getAttribute(\u0022ut\u0022);\n+\n+\t\t\trender_age(elems[m], age);\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * We only need to come back when the age might have changed.\n+\t * Eg, if everything is counted in hours already, once per\n+\t * 5 minutes is accurate enough.\n+\t */\n+\n+\twindow.setTimeout(aging, next * 1000);\n+}\n+\n+\n /* we have to use load, because header images can push the layout vertically */\n window.addEventListener(\u0022load\u0022, function() {\n \tline_range_highlight(1);\n@@ -358,6 +413,9 @@ document.addEventListener(\u0022DOMContentLoaded\u0022, function() {\n \tvar e \u003d document.getElementById(\u0022linenumbers\u0022);\n \tif (e)\n \t\te.onclick \u003d line_range_click;\n+\n+\t/* we can do the aging on DOM content load since no layout dependency */\n+\taging();\n }, false);\n \n window.addEventListener(\u0022hashchange\u0022, function() {\ndiff --git a/ui-shared.c b/ui-shared.c\nindex 33a5d01..28c3d60 100644\n--- a/ui-shared.c\n+++ b/ui-shared.c\n@@ -671,7 +671,7 @@ const struct date_mode *cgit_date_mode(enum date_mode_type type)\n static void print_rel_date(time_t t, int tz, double value,\n \tconst char *class, const char *suffix)\n {\n-\thtmlf(\u0022\u003cspan class\u003d'%s' title\u003d'\u0022, class);\n+\thtmlf(\u0022\u003cspan class\u003d'%s' ut\u003d'%\u0022 PRIu64 \u0022' title\u003d'\u0022, class, (uint64_t)t);\n \thtml_attr(show_date(t, tz, cgit_date_mode(DATE_ISO8601)));\n \thtmlf(\u0022'\u003e%.0f %s\u003c/span\u003e\u0022, value, suffix);\n }\n","s":{"c":1745907902,"u": 2282}} ],"g": 4075,"chitpc": 0,"ehitpc": 0,"indexed":0 , "ab": 0, "si": 0, "db":0, "di":0, "sat":0, "lfc": "0000"}