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 <opensource@fthiessen.de>
This commit is contained in:
Ferdinand Thiessen 2026-01-12 21:34:37 +01:00
parent dac8fe4034
commit 8ac1602402
No known key found for this signature in database
GPG key ID: 7E849AE05218500F
5 changed files with 46 additions and 38 deletions

View file

@ -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(() => {

View file

@ -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<FileStat>, 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<FileStat>, 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,

View file

@ -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
}

22
package-lock.json generated
View file

@ -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",

View file

@ -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",