From 10103b58f0c7254844e54d36deb9615dd1fa41e3 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Wed, 1 Nov 2017 20:46:37 +0100 Subject: [PATCH] Synchronize cart countdown with server time --- .../presale/templates/pretixpresale/base.html | 2 +- src/pretix/presale/views/__init__.py | 5 +++-- src/pretix/static/pretixpresale/js/ui/cart.js | 22 +++++++++++++++++-- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/pretix/presale/templates/pretixpresale/base.html b/src/pretix/presale/templates/pretixpresale/base.html index 42bb2950a2..b5856fba10 100644 --- a/src/pretix/presale/templates/pretixpresale/base.html +++ b/src/pretix/presale/templates/pretixpresale/base.html @@ -36,7 +36,7 @@ {% block custom_header %}{% endblock %} - + {% block above %} {% endblock %}
diff --git a/src/pretix/presale/views/__init__.py b/src/pretix/presale/views/__init__.py index 2a4ecac6bf..b7c29bd9fa 100644 --- a/src/pretix/presale/views/__init__.py +++ b/src/pretix/presale/views/__init__.py @@ -133,8 +133,9 @@ class CartMixin: try: first_expiry = min(p.expires for p in positions) if positions else now() - minutes_left = max(first_expiry - now(), timedelta()).seconds // 60 - seconds_left = max(first_expiry - now(), timedelta()).seconds % 60 + total_seconds_left = max(first_expiry - now(), timedelta()).total_seconds() + minutes_left = total_seconds_left // 60 + seconds_left = total_seconds_left % 60 except AttributeError: first_expiry = None minutes_left = None diff --git a/src/pretix/static/pretixpresale/js/ui/cart.js b/src/pretix/static/pretixpresale/js/ui/cart.js index 014cbeed24..d5b9b98ad2 100644 --- a/src/pretix/static/pretixpresale/js/ui/cart.js +++ b/src/pretix/static/pretixpresale/js/ui/cart.js @@ -3,6 +3,22 @@ var cart = { _deadline: null, _deadline_interval: null, _deadline_call: 0, + _time_offset: 0, + + _get_now: function () { + return moment().add(cart._time_offset, 'ms'); + }, + + _calc_offset: function () { + if (typeof window.performance === "undefined") { + return; + } + var perf = window.performance.timing; + var server_time = Math.round(parseFloat($("body").attr("data-now")) * 1000); + // We use requestStart as we don't know how latency is distributed and we rather want to err on the safe side + var client_time = perf.requestStart; + cart._time_offset = server_time - client_time; + }, draw_deadline: function () { function pad(n, width, z) { @@ -16,8 +32,9 @@ var cart = { // Language files are not loaded yet, don't run during the first seconds return; } - var diff_minutes = Math.floor(cart._deadline.diff(moment()) / 1000 / 60); - var diff_seconds = Math.floor(cart._deadline.diff(moment()) / 1000 % 60); + var now = cart._get_now(); + var diff_minutes = Math.floor(cart._deadline.diff(now) / 1000 / 60); + var diff_seconds = Math.floor(cart._deadline.diff(now) / 1000 % 60); if (diff_minutes < 0) { $("#cart-deadline").text(gettext("The items in your cart are no longer reserved for you.")); $("#cart-deadline-short").text( @@ -40,6 +57,7 @@ var cart = { "use strict"; cart._deadline = moment($("#cart-deadline").attr("data-expires")); cart._deadline_interval = window.setInterval(cart.draw_deadline, 500); + cart._calc_offset(); cart.draw_deadline(); } };