From 8ac160240298543717607b259a0c4c2d5f59332d Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Mon, 12 Jan 2026 21:34:37 +0100 Subject: [PATCH] refactor: drop moment from new bundles On the Vue 3 side lets remove the dependency on Moment as this is a pretty huge dependency. Instead use plain Intl API for formatting. This reduces the bundle size by ~1.5MiB. Signed-off-by: Ferdinand Thiessen --- .../src/components/VersionEntry.vue | 11 ++++-- apps/files_versions/src/utils/versions.ts | 12 ++++-- .../src/services/clearAtService.js | 38 ++++++++++++------- package-lock.json | 22 ++--------- package.json | 1 - 5 files changed, 46 insertions(+), 38 deletions(-) diff --git a/apps/files_versions/src/components/VersionEntry.vue b/apps/files_versions/src/components/VersionEntry.vue index 2118b23a5cb..3101151afc2 100644 --- a/apps/files_versions/src/components/VersionEntry.vue +++ b/apps/files_versions/src/components/VersionEntry.vue @@ -139,8 +139,7 @@ import type { Version } from '../utils/versions.ts' import { getCurrentUser } from '@nextcloud/auth' import { formatFileSize, Permission } from '@nextcloud/files' import { loadState } from '@nextcloud/initial-state' -import { t } from '@nextcloud/l10n' -import moment from '@nextcloud/moment' +import { getCanonicalLocale, t } from '@nextcloud/l10n' import { getRootUrl } from '@nextcloud/router' import { computed, nextTick, ref } from 'vue' import NcActionButton from '@nextcloud/vue/components/NcActionButton' @@ -233,7 +232,13 @@ const versionAuthor = computed(() => { }) const versionHumanExplicitDate = computed(() => { - return moment(props.version.mtime).format('LLLL') + return new Date(props.version.mtime).toLocaleString( + [getCanonicalLocale(), getCanonicalLocale().split('-')[0]!], + { + timeStyle: 'long', + dateStyle: 'long', + }, + ) }) const downloadURL = computed(() => { diff --git a/apps/files_versions/src/utils/versions.ts b/apps/files_versions/src/utils/versions.ts index 1e14aa39059..f818779b0ec 100644 --- a/apps/files_versions/src/utils/versions.ts +++ b/apps/files_versions/src/utils/versions.ts @@ -9,7 +9,7 @@ import type { FileStat, ResponseDataDetailed } from 'webdav' import { getCurrentUser } from '@nextcloud/auth' import axios from '@nextcloud/axios' import { getClient } from '@nextcloud/files/dav' -import moment from '@nextcloud/moment' +import { getCanonicalLocale } from '@nextcloud/l10n' import { encodePath, join } from '@nextcloud/paths' import { generateRemoteUrl, generateUrl } from '@nextcloud/router' import davRequest from '../utils/davRequest.ts' @@ -97,7 +97,7 @@ export async function restoreVersion(version: Version) { * @param node - The original node */ function formatVersion(version: Required, node: INode): Version { - const mtime = moment(version.lastmod).unix() * 1000 + const mtime = Date.parse(version.lastmod) let previewUrl = '' if (mtime === node.mtime?.getTime()) { // Version is the current one @@ -119,7 +119,13 @@ function formatVersion(version: Required, node: INode): Version { author: version.props['version-author'] ? String(version.props['version-author']) : null, authorName: null, filename: version.filename, - basename: moment(mtime).format('LLL'), + basename: new Date(mtime).toLocaleString( + [getCanonicalLocale(), getCanonicalLocale().split('-')[0]!], + { + timeStyle: 'long', + dateStyle: 'medium', + }, + ), mime: version.mime, etag: `${version.props.getetag}`, size: version.size, diff --git a/apps/user_status/src/services/clearAtService.js b/apps/user_status/src/services/clearAtService.js index 83329993bfa..09766797afe 100644 --- a/apps/user_status/src/services/clearAtService.js +++ b/apps/user_status/src/services/clearAtService.js @@ -3,8 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -import { t } from '@nextcloud/l10n' -import moment from '@nextcloud/moment' +import { formatRelativeTime, t } from '@nextcloud/l10n' import { dateFactory } from './dateService.js' /** @@ -13,7 +12,7 @@ import { dateFactory } from './dateService.js' * @param {object | null} clearAt The clear-at config * @return {number | null} */ -function getTimestampForClearAt(clearAt) { +export function getTimestampForClearAt(clearAt) { if (clearAt === null) { return null } @@ -27,8 +26,9 @@ function getTimestampForClearAt(clearAt) { if (clearAt.type === 'end-of') { switch (clearAt.time) { case 'day': + return Math.floor(getEndOfDay(date).getTime() / 1000) case 'week': - return Number(moment(date).endOf(clearAt.time).format('X')) + return Math.floor(getEndOfWeek(date).getTime() / 1000) } } // This is not an officially supported type @@ -47,7 +47,7 @@ function getTimestampForClearAt(clearAt) { * @param {object} clearAt The clearAt object * @return {string|null} */ -function clearAtFormat(clearAt) { +export function clearAtFormat(clearAt) { if (clearAt === null) { return t('user_status', 'Don\'t clear') } @@ -65,23 +65,35 @@ function clearAtFormat(clearAt) { } if (clearAt.type === 'period') { - return moment.duration(clearAt.time * 1000).humanize() + return formatRelativeTime(Date.now() + clearAt.time * 1000) } // This is not an officially supported type // but only used internally to show the remaining time // in the Set Status Modal if (clearAt.type === '_time') { - const momentNow = moment(dateFactory()) - const momentClearAt = moment(clearAt.time, 'X') - - return moment.duration(momentNow.diff(momentClearAt)).humanize() + return formatRelativeTime(clearAt.time * 1000) } return null } -export { - clearAtFormat, - getTimestampForClearAt, +/** + * @param {Date} date - The date to calculate the end of the day for + */ +function getEndOfDay(date) { + const endOfDay = new Date(date) + endOfDay.setHours(23, 59, 59, 999) + return endOfDay +} + +/** + * Calculates the end of the week for a given date + * + * @param {Date} date - The date to calculate the end of the week for + */ +function getEndOfWeek(date) { + const endOfWeek = getEndOfDay(date) + endOfWeek.setDate(date.getDate() + ((endOfWeek.getFirstDay() - 1 - endOfWeek.getDay() + 7) % 7)) + return endOfWeek } diff --git a/package-lock.json b/package-lock.json index 46548d1ef07..900ad516d6c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,6 @@ "@nextcloud/initial-state": "^3.0.0", "@nextcloud/l10n": "^3.4.1", "@nextcloud/logger": "^3.0.3", - "@nextcloud/moment": "^1.3.5", "@nextcloud/password-confirmation": "^6.0.2", "@nextcloud/paths": "^3.0.0", "@nextcloud/router": "^3.1.0", @@ -2502,19 +2501,6 @@ "node": "^20.0.0 || ^22.0.0 || ^24.0.0" } }, - "node_modules/@nextcloud/moment": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@nextcloud/moment/-/moment-1.3.5.tgz", - "integrity": "sha512-sQjQ/D40sdedtq4ywuANSxqG0VhIB/i+QtZ6Voz3nyZWhkyyqGxdj9rQu9AyEvas3/Jlspdom5chc+a8jOmHxQ==", - "dependencies": { - "@nextcloud/l10n": "^3.4.0", - "moment": "^2.30.1" - }, - "engines": { - "node": "^20.0.0", - "npm": "^10.0.0" - } - }, "node_modules/@nextcloud/password-confirmation": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@nextcloud/password-confirmation/-/password-confirmation-6.0.2.tgz", @@ -6937,9 +6923,9 @@ } }, "node_modules/dayjs": { - "version": "1.11.18", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz", - "integrity": "sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==", + "version": "1.11.19", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", + "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", "dev": true, "license": "MIT" }, @@ -12216,6 +12202,7 @@ "version": "2.30.1", "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "dev": true, "license": "MIT", "engines": { "node": "*" @@ -12234,7 +12221,6 @@ "dev": true, "hasInstallScript": true, "license": "MIT", - "peer": true, "dependencies": { "@inquirer/confirm": "^5.0.0", "@mswjs/interceptors": "^0.40.0", diff --git a/package.json b/package.json index 8140cb2f379..79ef391b2ea 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,6 @@ "@nextcloud/initial-state": "^3.0.0", "@nextcloud/l10n": "^3.4.1", "@nextcloud/logger": "^3.0.3", - "@nextcloud/moment": "^1.3.5", "@nextcloud/password-confirmation": "^6.0.2", "@nextcloud/paths": "^3.0.0", "@nextcloud/router": "^3.1.0",