summaryrefslogtreecommitdiffstats
path: root/js
diff options
context:
space:
mode:
authorAlec Kojaev <alec@kojaev.name>2021-07-16 15:40:04 +0300
committerSean Molenaar <SMillerDev@users.noreply.github.com>2021-07-24 14:52:34 +0200
commit65c15dac38358d5c3a619379b57bd498c070ea6f (patch)
tree8052e83899b96b7e761f779a43d15feb7921e353 /js
parent691c42bdbce50eaa7857f8386c706a4e8c763d60 (diff)
Reimplement relative time formatting as a filter, dropping dependency on deprecated moment.js
Signed-off-by: Alec Kojaev <alec@kojaev.name>
Diffstat (limited to 'js')
-rw-r--r--js/.jshintrc1
-rw-r--r--js/controller/ContentController.js9
-rw-r--r--js/filter/RelativeTimestamp.js58
-rw-r--r--js/gulpfile.js1
-rw-r--r--js/karma.conf.js1
-rw-r--r--js/package-lock.json5
-rw-r--r--js/package.json1
-rw-r--r--js/tests/unit/controller/ContentControllerSpec.js21
8 files changed, 58 insertions, 39 deletions
diff --git a/js/.jshintrc b/js/.jshintrc
index 92f22ce7c..1f0c276f4 100644
--- a/js/.jshintrc
+++ b/js/.jshintrc
@@ -25,7 +25,6 @@
"jquery": true,
"globals": {
"angular": true,
- "moment": true,
"app": true,
"OC": true,
"csrfToken": true,
diff --git a/js/controller/ContentController.js b/js/controller/ContentController.js
index 942618a9c..ed8d0be55 100644
--- a/js/controller/ContentController.js
+++ b/js/controller/ContentController.js
@@ -198,15 +198,6 @@ app.controller('ContentController', function (Publisher, FeedResource, ItemResou
});
};
- this.getRelativeDate = function (timestamp) {
- if (timestamp !== undefined && timestamp !== '') {
- var languageCode = SettingsResource.get('language');
- return moment.unix(timestamp).locale(languageCode).fromNow() + '';
- } else {
- return '';
- }
- };
-
this.refresh = function () {
$route.reload();
};
diff --git a/js/filter/RelativeTimestamp.js b/js/filter/RelativeTimestamp.js
new file mode 100644
index 000000000..1a70db4a7
--- /dev/null
+++ b/js/filter/RelativeTimestamp.js
@@ -0,0 +1,58 @@
+/**
+ * Nextcloud - News
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ *
+ * @author Alec Kojaev <alec@kojaev.name>
+ * @copyright Alec Kojaev 2021
+ */
+app.filter('relativeTimestamp', ['SettingsResource', function (SettingsResource) {
+ 'use strict';
+
+ const languageCode = SettingsResource.get('language');
+ const relFormat = Intl.RelativeTimeFormat ?
+ new Intl.RelativeTimeFormat(languageCode, { numeric: 'auto' }) : null;
+ const maxRelDistance = 90*86400*1000;
+ const relLimits = [
+ [ 7*86400*1000, 'week' ],
+ [ 86400*1000, 'day' ],
+ [ 3600*1000, 'hour' ],
+ [ 60*1000, 'minute' ],
+ [ 1*1000, 'second' ]
+ ];
+ const absLimits = [
+ [ 7*86400*1000, { hour: '2-digit', minute: '2-digit', dayPeriod: 'narrow',
+ year: 'numeric', month: 'short', day: 'numeric' } ],
+ [ 43200*1000, { hour: '2-digit', minute: '2-digit', dayPeriod: 'narrow',
+ weekday: 'long' } ],
+ [ 0, { hour: '2-digit', minute: '2-digit', dayPeriod: 'narrow' } ]
+ ];
+
+ return function (timestamp) {
+ if (!Number.isFinite(timestamp)) {
+ return timestamp;
+ }
+ const ts = new Date(timestamp);
+ const dist = ts.getTime() - Date.now();
+ const absDist = Math.abs(dist);
+ if (relFormat && absDist < maxRelDistance) {
+ for (const [ scale, unit ] of relLimits) {
+ const value = Math.trunc(dist / scale);
+ if (value !== 0) {
+ return relFormat.format(value, unit);
+ }
+ }
+ // We arrive here only if distance from now is less than 1 second
+ return relFormat.format(0, 'second');
+ } else {
+ for (const [ limit, options ] of absLimits) {
+ if (absDist >= limit) {
+ return ts.toLocaleString(languageCode, options);
+ }
+ }
+ // We shouldn't be here
+ return ts.toLocaleString(languageCode, absLimits[absLimits.length - 1][1]);
+ }
+ };
+}]);
diff --git a/js/gulpfile.js b/js/gulpfile.js
index 299918986..7f9d288b5 100644
--- a/js/gulpfile.js
+++ b/js/gulpfile.js
@@ -30,7 +30,6 @@ const sources = [
'node_modules/angular-animate/angular-animate.min.js',
'node_modules/angular-route/angular-route.min.js',
'node_modules/angular-sanitize/angular-sanitize.min.js',
- 'node_modules/moment/min/moment-with-locales.min.js',
'node_modules/masonry-layout/dist/masonry.pkgd.min.js',
'node_modules/vue/dist/vue.js',
'node_modules/ngVue/build/index.js',
diff --git a/js/karma.conf.js b/js/karma.conf.js
index 6cf0f4a29..5a6e0af4e 100644
--- a/js/karma.conf.js
+++ b/js/karma.conf.js
@@ -17,7 +17,6 @@ module.exports = function (config) {
// list of files / patterns to load in the browser
files: [
'node_modules/jquery/dist/jquery.js',
- 'node_modules/moment/min/moment-with-locales.js',
'node_modules/angular/angular.js',
'node_modules/angular-mocks/angular-mocks.js',
'node_modules/angular-route/angular-route.js',
diff --git a/js/package-lock.json b/js/package-lock.json
index f866cf39a..3ae44a030 100644
--- a/js/package-lock.json
+++ b/js/package-lock.json
@@ -5601,11 +5601,6 @@
"minimist": "1.2.5"
}
},
- "moment": {
- "version": "2.29.1",
- "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
- "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
- },
"move-concurrently": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
diff --git a/js/package.json b/js/package.json
index 5cb91eb5c..4cff38d31 100644
--- a/js/package.json
+++ b/js/package.json
@@ -63,7 +63,6 @@
"angular-sanitize": "^1.8.2",
"debug": "^4.3.2",
"masonry-layout": "^4.2.2",
- "moment": "^2.29.1",
"ngVue": "^1.7.8",
"vue": "^2.6.14"
}
diff --git a/js/tests/unit/controller/ContentControllerSpec.js b/js/tests/unit/controller/ContentControllerSpec.js
index e8992ca8c..b410b7f95 100644
--- a/js/tests/unit/controller/ContentControllerSpec.js
+++ b/js/tests/unit/controller/ContentControllerSpec.js
@@ -513,27 +513,6 @@ describe('ContentController', function () {
expect(ctrl.autoPagingEnabled()).toBe(true);
}));
-
- it('should return relative date', inject(function ($controller,
- SettingsResource) {
-
- SettingsResource.receive({language: 'en'});
- var ctrl = $controller('ContentController', {
- data: {},
- });
-
- expect(ctrl.getRelativeDate(12)).not.toBe('');
- }));
-
-
- it('should return relative date empty', inject(function ($controller) {
- var ctrl = $controller('ContentController', {
- data: {}
- });
-
- expect(ctrl.getRelativeDate('')).toBe('');
- }));
-
it('should refresh the page', inject(function ($controller) {
var route = {
current: {