123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- /**
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- *
- * @author Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author John Molakvoæ <skjnldsv@protonmail.com>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- import moment from 'moment'
- import History from './util-history'
- import OC from './index'
- import { formatFileSize as humanFileSize } from '@nextcloud/files'
- /**
- * @param {any} t -
- */
- function chunkify(t) {
- // Adapted from http://my.opera.com/GreyWyvern/blog/show.dml/1671288
- const tz = []
- let x = 0
- let y = -1
- let n = 0
- let c
- while (x < t.length) {
- c = t.charAt(x)
- // only include the dot in strings
- const m = ((!n && c === '.') || (c >= '0' && c <= '9'))
- if (m !== n) {
- // next chunk
- y++
- tz[y] = ''
- n = m
- }
- tz[y] += c
- x++
- }
- return tz
- }
- /**
- * Utility functions
- *
- * @namespace OC.Util
- */
- export default {
- History,
- /**
- * @deprecated use https://nextcloud.github.io/nextcloud-files/modules/_humanfilesize_.html#formatfilesize
- */
- humanFileSize,
- /**
- * Returns a file size in bytes from a humanly readable string
- * Makes 2kB to 2048.
- * Inspired by computerFileSize in helper.php
- *
- * @param {string} string file size in human readable format
- * @return {number} or null if string could not be parsed
- *
- *
- */
- computerFileSize(string) {
- if (typeof string !== 'string') {
- return null
- }
- const s = string.toLowerCase().trim()
- let bytes = null
- const bytesArray = {
- b: 1,
- k: 1024,
- kb: 1024,
- mb: 1024 * 1024,
- m: 1024 * 1024,
- gb: 1024 * 1024 * 1024,
- g: 1024 * 1024 * 1024,
- tb: 1024 * 1024 * 1024 * 1024,
- t: 1024 * 1024 * 1024 * 1024,
- pb: 1024 * 1024 * 1024 * 1024 * 1024,
- p: 1024 * 1024 * 1024 * 1024 * 1024,
- }
- const matches = s.match(/^[\s+]?([0-9]*)(\.([0-9]+))?( +)?([kmgtp]?b?)$/i)
- if (matches !== null) {
- bytes = parseFloat(s)
- if (!isFinite(bytes)) {
- return null
- }
- } else {
- return null
- }
- if (matches[5]) {
- bytes = bytes * bytesArray[matches[5]]
- }
- bytes = Math.round(bytes)
- return bytes
- },
- /**
- * @param {string|number} timestamp timestamp
- * @param {string} format date format, see momentjs docs
- * @return {string} timestamp formatted as requested
- */
- formatDate(timestamp, format) {
- if (window.TESTING === undefined) {
- console.warn('OC.Util.formatDate is deprecated and will be removed in Nextcloud 21. See @nextcloud/moment')
- }
- format = format || 'LLL'
- return moment(timestamp).format(format)
- },
- /**
- * @param {string|number} timestamp timestamp
- * @return {string} human readable difference from now
- */
- relativeModifiedDate(timestamp) {
- if (window.TESTING === undefined) {
- console.warn('OC.Util.relativeModifiedDate is deprecated and will be removed in Nextcloud 21. See @nextcloud/moment')
- }
- const diff = moment().diff(moment(timestamp))
- if (diff >= 0 && diff < 45000) {
- return t('core', 'seconds ago')
- }
- return moment(timestamp).fromNow()
- },
- /**
- * Returns the width of a generic browser scrollbar
- *
- * @return {number} width of scrollbar
- */
- getScrollBarWidth() {
- if (this._scrollBarWidth) {
- return this._scrollBarWidth
- }
- const inner = document.createElement('p')
- inner.style.width = '100%'
- inner.style.height = '200px'
- const outer = document.createElement('div')
- outer.style.position = 'absolute'
- outer.style.top = '0px'
- outer.style.left = '0px'
- outer.style.visibility = 'hidden'
- outer.style.width = '200px'
- outer.style.height = '150px'
- outer.style.overflow = 'hidden'
- outer.appendChild(inner)
- document.body.appendChild(outer)
- const w1 = inner.offsetWidth
- outer.style.overflow = 'scroll'
- let w2 = inner.offsetWidth
- if (w1 === w2) {
- w2 = outer.clientWidth
- }
- document.body.removeChild(outer)
- this._scrollBarWidth = (w1 - w2)
- return this._scrollBarWidth
- },
- /**
- * Remove the time component from a given date
- *
- * @param {Date} date date
- * @return {Date} date with stripped time
- */
- stripTime(date) {
- // FIXME: likely to break when crossing DST
- // would be better to use a library like momentJS
- return new Date(date.getFullYear(), date.getMonth(), date.getDate())
- },
- /**
- * Compare two strings to provide a natural sort
- *
- * @param {string} a first string to compare
- * @param {string} b second string to compare
- * @return {number} -1 if b comes before a, 1 if a comes before b
- * or 0 if the strings are identical
- */
- naturalSortCompare(a, b) {
- let x
- const aa = chunkify(a)
- const bb = chunkify(b)
- for (x = 0; aa[x] && bb[x]; x++) {
- if (aa[x] !== bb[x]) {
- const aNum = Number(aa[x]); const bNum = Number(bb[x])
- // note: == is correct here
- /* eslint-disable-next-line */
- if (aNum == aa[x] && bNum == bb[x]) {
- return aNum - bNum
- } else {
- // Note: This locale setting isn't supported by all browsers but for the ones
- // that do there will be more consistency between client-server sorting
- return aa[x].localeCompare(bb[x], OC.getLanguage())
- }
- }
- }
- return aa.length - bb.length
- },
- /**
- * Calls the callback in a given interval until it returns true
- *
- * @param {Function} callback function to call on success
- * @param {number} interval in milliseconds
- */
- waitFor(callback, interval) {
- const internalCallback = function() {
- if (callback() !== true) {
- setTimeout(internalCallback, interval)
- }
- }
- internalCallback()
- },
- /**
- * Checks if a cookie with the given name is present and is set to the provided value.
- *
- * @param {string} name name of the cookie
- * @param {string} value value of the cookie
- * @return {boolean} true if the cookie with the given name has the given value
- */
- isCookieSetToValue(name, value) {
- const cookies = document.cookie.split(';')
- for (let i = 0; i < cookies.length; i++) {
- const cookie = cookies[i].split('=')
- if (cookie[0].trim() === name && cookie[1].trim() === value) {
- return true
- }
- }
- return false
- },
- }
|