This commit is contained in:
2024-02-25 08:27:01 +08:00
commit 20c1fa08dc
279 changed files with 78489 additions and 0 deletions

37
src/utils/api.ts Normal file
View File

@@ -0,0 +1,37 @@
import { CloudreveFile } from "../types";
import { list } from "../services/navigate";
import { pathJoin } from "../component/Uploader/core/utils";
export function getPreviewPath(selected: any): string {
return encodeURIComponent(
selected.path === "/"
? selected.path + selected.name
: selected.path + "/" + selected.name
);
}
export async function walk(
file: CloudreveFile[],
share: any
): Promise<CloudreveFile[]> {
let res: CloudreveFile[] = [];
for (const f of file) {
if (f.type === "file") {
res.push(f);
continue;
}
if (f.type === "dir") {
const response = await list(
pathJoin([f.path, f.name]),
share,
"",
""
);
const subs = await walk(response.data.objects, share);
res = [...res, ...subs];
}
}
return res;
}

53
src/utils/datetime.js Normal file
View File

@@ -0,0 +1,53 @@
import dayjs from "dayjs";
import timezone from "dayjs/plugin/timezone";
import utc from "dayjs/plugin/utc";
import Auth from "../middleware/Auth";
import i18next from "../i18n";
dayjs.extend(utc);
dayjs.extend(timezone);
let userTimezone = "";
try {
userTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
} catch (e) {
console.log(e);
}
if (!userTimezone || userTimezone=="Etc/Unknown") {
userTimezone = "Asia/Shanghai";
}
const preferTimeZone = Auth.GetPreference("timeZone");
export let timeZone = preferTimeZone ? preferTimeZone : userTimezone;
export function refreshTimeZone() {
timeZone = Auth.GetPreference("timeZone");
timeZone = timeZone ? timeZone : userTimezone;
}
export function formatLocalTime(time) {
return i18next.t("intlDateTime", {
ns: "common",
val: dayjs(time).tz(timeZone).toDate(),
formatParams: {
val: {
year: "numeric",
month: "numeric",
day: "numeric",
hour: "numeric",
minute: "numeric",
second: "numeric",
},
},
});
}
export function validateTimeZone(name) {
try {
dayjs().tz(name).format();
} catch (e) {
return false;
}
return true;
}

81
src/utils/filesystem.ts Normal file
View File

@@ -0,0 +1,81 @@
// get the paths of files (no directories) in the directory
// parent: "" or "/"
export const getFileSystemDirectoryPaths = async (
handle: FileSystemDirectoryHandle,
parent = ""
): Promise<string[]> => {
const paths: Array<string> = [];
for await (const [path, fileSystemHandle] of handle.entries()) {
if (fileSystemHandle instanceof window.FileSystemFileHandle) {
paths.push(`${parent}${path}`);
} else {
paths.push(
...(await getFileSystemDirectoryPaths(
fileSystemHandle,
`${parent}${path}/`
))
);
}
}
return paths;
};
// create the dst directory if it doesn't exist
// return the dst directory handle
// paths: "/dir1/dir2" => ["dir1","dir2"]
export const createFileSystemDirectory = async (
handle: FileSystemDirectoryHandle,
paths: string[]
) => {
let cur = handle;
while (paths.length > 0) {
const path = paths.shift();
if (!path) {
break;
}
cur = await cur.getDirectoryHandle(path, { create: true });
}
return cur;
};
// save file into the dst directory
// create the dst file if it doesn't exist by default
// path: a/b/c.jpg
export const saveFileToFileSystemDirectory = async (
handle: FileSystemDirectoryHandle,
stream: FileSystemWriteChunkType,
path: string,
create = true
) => {
const paths = path.split("/");
const fileName = paths.pop();
if (!fileName) return;
const dir = await createFileSystemDirectory(handle, paths);
const file = await dir.getFileHandle(fileName, { create });
const writable = await file.createWritable();
await writable.write(stream);
await writable.close();
};
// verify or request the permission of the readwrite permission
export async function verifyFileSystemRWPermission(
fileHandle: FileSystemDirectoryHandle
) {
const opts = { mode: "readwrite" as FileSystemPermissionMode };
// Check if we already have permission, if so, return true.
if ((await fileHandle.queryPermission(opts)) === "granted") {
return true;
}
// Request permission to the file, if the user grants permission, return true.
if ((await fileHandle.requestPermission(opts)) === "granted") {
return true;
}
// The user did not grant permission, return false.
return false;
}

172
src/utils/index.js Normal file
View File

@@ -0,0 +1,172 @@
export const sizeToString = (bytes) => {
if (bytes === 0 || bytes === "0") return "0 B";
const k = 1024;
const sizes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return (bytes / Math.pow(k, i)).toFixed(1) + " " + sizes[i];
};
export const fixUrlHash = (path) => {
return path;
};
export const setCookie = (name, value, days) => {
if (days) {
const date = new Date();
date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
}
document.cookie = name + "=" + (value || "") + "; path=/";
};
export const setGetParameter = (paramName, paramValue) => {
let url = window.location.href;
if (url.indexOf(paramName + "=") >= 0) {
const prefix = url.substring(0, url.indexOf(paramName));
let suffix = url.substring(url.indexOf(paramName));
suffix = suffix.substring(suffix.indexOf("=") + 1);
suffix =
suffix.indexOf("&") >= 0
? suffix.substring(suffix.indexOf("&"))
: "";
url = prefix + paramName + "=" + paramValue + suffix;
} else {
if (url.indexOf("?") < 0) url += "?" + paramName + "=" + paramValue;
else url += "&" + paramName + "=" + paramValue;
}
if (url === window.location.href) {
return;
}
window.history.pushState(null, null, url);
};
export const checkGetParameters = (field) => {
const url = window.location.href;
if (url.indexOf("?" + field + "=") !== -1) return true;
else if (url.indexOf("&" + field + "=") !== -1) return true;
return false;
};
export const changeThemeColor = (color) => {
const metaThemeColor = window.document.querySelector(
"meta[name=theme-color]"
);
metaThemeColor.setAttribute("content", color);
};
export function bufferDecode(value) {
return Uint8Array.from(atob(value), (c) => c.charCodeAt(0));
}
// ArrayBuffer to URLBase64
export function bufferEncode(value) {
return btoa(String.fromCharCode.apply(null, new Uint8Array(value)))
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=/g, "");
}
export function pathBack(path) {
const folders =
path !== null
? path.substr(1).split("/")
: this.props.path.substr(1).split("/");
return "/" + folders.slice(0, folders.length - 1).join("/");
}
export function filePath(file) {
return file.path === "/"
? file.path + file.name
: file.path + "/" + file.name;
}
export function hex2bin(hex) {
return parseInt(hex, 16).toString(2).padStart(8, "0");
}
export function pathJoin(parts, sep) {
const separator = sep || "/";
parts = parts.map((part, index) => {
if (index) {
part = part.replace(new RegExp("^" + separator), "");
}
if (index !== parts.length - 1) {
part = part.replace(new RegExp(separator + "$"), "");
}
return part;
});
return parts.join(separator);
}
export function basename(path) {
if (!path) {
return "";
}
const pathList = path.split("/");
pathList.pop();
return pathList.join("/") === "" ? "/" : pathList.join("/");
}
export function filename(path) {
const pathList = path.split("/");
return pathList.pop();
}
export function fileNameNoExt(filename) {
return filename.substring(0, filename.lastIndexOf(".")) || filename;
}
export function randomStr(length) {
let result = "";
const characters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const charactersLength = characters.length;
for (let i = 0; i < length; i++) {
result += characters.charAt(
Math.floor(Math.random() * charactersLength)
);
}
return result;
}
export function getNumber(base, conditions) {
conditions.forEach((v) => {
if (v) {
base++;
}
});
return base;
}
export const isMac = () => {
return navigator.platform.toUpperCase().indexOf("MAC") >= 0;
};
export const isMobileSafari = () => {
const ua = window.navigator.userAgent;
const iOS = !!ua.match(/iPad/i) || !!ua.match(/iPhone/i);
const webkit = !!ua.match(/WebKit/i);
return iOS && webkit && !ua.match(/CriOS/i);
};
export function vhCheck() {
const vh = window.innerHeight;
document.documentElement.style.setProperty("--vh", `${vh}px`);
}
export const getSelectItemStyles = (name, personName, theme) => {
return {
fontWeight:
personName.indexOf(name) === -1
? theme.typography.fontWeightRegular
: theme.typography.fontWeightMedium,
};
};
export const removeI18nCache = () => {
Object.keys(localStorage).forEach(function (key) {
if (key && key.startsWith("i18next_res_")) {
localStorage.removeItem(key);
}
});
};

18
src/utils/page.ts Normal file
View File

@@ -0,0 +1,18 @@
const statusHelper = {
isHomePage(path: string) {
return path === "/home";
},
isSharePage(path: string) {
return path && path.startsWith("/s/");
},
isAdminPage(path: string) {
return path && path.startsWith("/admin");
},
isLoginPage(path: string) {
return path && path.startsWith("/login");
},
isMobile() {
return window.innerWidth < 600;
},
};
export default statusHelper;

257
src/utils/zip.js Normal file
View File

@@ -0,0 +1,257 @@
/* eslint-disable */
class Crc32 {
constructor() {
this.crc = -1;
}
append(data) {
let crc = this.crc | 0;
const table = this.table;
for (let offset = 0, len = data.length | 0; offset < len; offset++) {
crc = (crc >>> 8) ^ table[(crc ^ data[offset]) & 0xff];
}
this.crc = crc;
}
get() {
return ~this.crc;
}
}
Crc32.prototype.table = (() => {
let i;
let j;
let t;
const table = [];
for (i = 0; i < 256; i++) {
t = i;
for (j = 0; j < 8; j++) {
t = t & 1 ? (t >>> 1) ^ 0xedb88320 : t >>> 1;
}
table[i] = t;
}
return table;
})();
const getDataHelper = (byteLength) => {
const uint8 = new Uint8Array(byteLength);
return {
array: uint8,
view: new DataView(uint8.buffer),
};
};
const pump = (zipObj) =>
zipObj.reader.read().then((chunk) => {
if (chunk.done) return zipObj.writeFooter();
const outputData = chunk.value;
zipObj.crc.append(outputData);
zipObj.uncompressedLength += outputData.length;
zipObj.compressedLength += outputData.length;
zipObj.ctrl.enqueue(outputData);
});
/**
* [createWriter description]
* @param {Object} underlyingSource [description]
* @return {Boolean} [description]
*/
function createWriter(underlyingSource) {
const files = Object.create(null);
const filenames = [];
const encoder = new TextEncoder();
let offset = 0;
let activeZipIndex = 0;
let ctrl;
let activeZipObject, closed;
function next() {
activeZipIndex++;
activeZipObject = files[filenames[activeZipIndex]];
if (activeZipObject) processNextChunk();
else if (closed) closeZip();
}
const zipWriter = {
enqueue(fileLike) {
if (closed)
throw new TypeError(
"Cannot enqueue a chunk into a readable stream that is closed or has been requested to be closed"
);
let name = fileLike.name.trim();
const date = new Date(
typeof fileLike.lastModified === "undefined"
? Date.now()
: fileLike.lastModified
);
if (fileLike.directory && !name.endsWith("/")) name += "/";
if (files[name]) throw new Error("File already exists.");
const nameBuf = encoder.encode(name);
filenames.push(name);
const zipObject = (files[name] = {
level: 0,
ctrl,
directory: !!fileLike.directory,
nameBuf,
comment: encoder.encode(fileLike.comment || ""),
compressedLength: 0,
uncompressedLength: 0,
writeHeader() {
const header = getDataHelper(26);
const data = getDataHelper(30 + nameBuf.length);
zipObject.offset = offset;
zipObject.header = header;
if (zipObject.level !== 0 && !zipObject.directory) {
header.view.setUint16(4, 0x0800);
}
header.view.setUint32(0, 0x14000808);
header.view.setUint16(
6,
(((date.getHours() << 6) | date.getMinutes()) << 5) |
(date.getSeconds() / 2),
true
);
header.view.setUint16(
8,
((((date.getFullYear() - 1980) << 4) |
(date.getMonth() + 1)) <<
5) |
date.getDate(),
true
);
header.view.setUint16(22, nameBuf.length, true);
data.view.setUint32(0, 0x504b0304);
data.array.set(header.array, 4);
data.array.set(nameBuf, 30);
offset += data.array.length;
ctrl.enqueue(data.array);
},
writeFooter() {
const footer = getDataHelper(16);
footer.view.setUint32(0, 0x504b0708);
if (zipObject.crc) {
zipObject.header.view.setUint32(
10,
zipObject.crc.get(),
true
);
zipObject.header.view.setUint32(
14,
zipObject.compressedLength,
true
);
zipObject.header.view.setUint32(
18,
zipObject.uncompressedLength,
true
);
footer.view.setUint32(4, zipObject.crc.get(), true);
footer.view.setUint32(
8,
zipObject.compressedLength,
true
);
footer.view.setUint32(
12,
zipObject.uncompressedLength,
true
);
}
ctrl.enqueue(footer.array);
offset += zipObject.compressedLength + 16;
next();
},
fileLike,
});
if (!activeZipObject) {
activeZipObject = zipObject;
processNextChunk();
}
},
close() {
if (closed)
throw new TypeError(
"Cannot close a readable stream that has already been requested to be closed"
);
if (!activeZipObject) closeZip();
closed = true;
},
};
function closeZip() {
let length = 0;
let index = 0;
let indexFilename, file;
for (
indexFilename = 0;
indexFilename < filenames.length;
indexFilename++
) {
file = files[filenames[indexFilename]];
length += 46 + file.nameBuf.length + file.comment.length;
}
const data = getDataHelper(length + 22);
for (
indexFilename = 0;
indexFilename < filenames.length;
indexFilename++
) {
file = files[filenames[indexFilename]];
data.view.setUint32(index, 0x504b0102);
data.view.setUint16(index + 4, 0x1400);
data.array.set(file.header.array, index + 6);
data.view.setUint16(index + 32, file.comment.length, true);
if (file.directory) {
data.view.setUint8(index + 38, 0x10);
}
data.view.setUint32(index + 42, file.offset, true);
data.array.set(file.nameBuf, index + 46);
data.array.set(file.comment, index + 46 + file.nameBuf.length);
index += 46 + file.nameBuf.length + file.comment.length;
}
data.view.setUint32(index, 0x504b0506);
data.view.setUint16(index + 8, filenames.length, true);
data.view.setUint16(index + 10, filenames.length, true);
data.view.setUint32(index + 12, length, true);
data.view.setUint32(index + 16, offset, true);
ctrl.enqueue(data.array);
ctrl.close();
}
function processNextChunk() {
if (!activeZipObject) return;
if (activeZipObject.directory)
return activeZipObject.writeFooter(activeZipObject.writeHeader());
if (activeZipObject.reader) return pump(activeZipObject);
if (activeZipObject.fileLike.stream) {
activeZipObject.crc = new Crc32();
activeZipObject.reader = activeZipObject.fileLike
.stream()
.getReader();
activeZipObject.writeHeader();
} else next();
}
return new ReadableStream({
start: (c) => {
ctrl = c;
underlyingSource.start &&
Promise.resolve(underlyingSource.start(zipWriter));
},
pull() {
return (
processNextChunk() ||
(underlyingSource.pull &&
Promise.resolve(underlyingSource.pull(zipWriter)))
);
},
});
}
window.ZIP = createWriter;