mirror of
https://github.com/logseq/logseq.git
synced 2026-04-27 23:54:55 +00:00
174 lines
5.1 KiB
JavaScript
174 lines
5.1 KiB
JavaScript
if (typeof window === 'undefined') {
|
|
global.window = {}
|
|
}
|
|
|
|
// Copy from https://github.com/primetwig/react-nestable/blob/dacea9dc191399a3520f5dc7623f5edebc83e7b7/dist/utils.js
|
|
export var closest = function closest (target, selector) {
|
|
// closest(e.target, '.field')
|
|
while (target) {
|
|
if (target.matches && target.matches(selector)) return target
|
|
target = target.parentNode
|
|
}
|
|
return null
|
|
}
|
|
|
|
export var getOffsetRect = function getOffsetRect (elem) {
|
|
// (1)
|
|
var box = elem.getBoundingClientRect()
|
|
|
|
var body = document.body
|
|
var docElem = document.documentElement
|
|
|
|
// (2)
|
|
var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop
|
|
var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft
|
|
|
|
// (3)
|
|
var clientTop = docElem.clientTop || body.clientTop || 0
|
|
var clientLeft = docElem.clientLeft || body.clientLeft || 0
|
|
|
|
// (4)
|
|
var top = box.top + scrollTop - clientTop
|
|
var left = box.left + scrollLeft - clientLeft
|
|
|
|
return { top: Math.round(top), left: Math.round(left) }
|
|
}
|
|
|
|
// jquery focus
|
|
export var focus = function (elem) {
|
|
return elem === document.activeElement &&
|
|
document.hasFocus() &&
|
|
!!(elem.type || elem.href || ~elem.tabIndex)
|
|
}
|
|
|
|
// copied from https://stackoverflow.com/a/32180863
|
|
export var timeConversion = function (millisec) {
|
|
var seconds = (millisec / 1000).toFixed(0)
|
|
var minutes = (millisec / (1000 * 60)).toFixed(0)
|
|
var hours = (millisec / (1000 * 60 * 60)).toFixed(1)
|
|
var days = (millisec / (1000 * 60 * 60 * 24)).toFixed(1)
|
|
|
|
if (seconds < 60) {
|
|
return seconds + 's'
|
|
} else if (minutes < 60) {
|
|
return minutes + 'm'
|
|
} else if (hours < 24) {
|
|
return hours + 'h'
|
|
} else {
|
|
return days + 'd'
|
|
}
|
|
}
|
|
|
|
export var getSelectionText = function () {
|
|
const selection = (window.getSelection() || '').toString().trim()
|
|
if (selection) {
|
|
return selection
|
|
}
|
|
|
|
// Firefox fix
|
|
const activeElement = window.document.activeElement
|
|
if (activeElement) {
|
|
if (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA') {
|
|
const el = activeElement
|
|
return el.value.slice(el.selectionStart || 0, el.selectionEnd || 0)
|
|
}
|
|
}
|
|
|
|
return '';
|
|
}
|
|
|
|
// Modified from https://github.com/GoogleChromeLabs/browser-nativefs
|
|
// because shadow-cljs doesn't handle this babel transform
|
|
export var getFiles = async function (dirHandle, recursive, cb, path = dirHandle.name) {
|
|
const dirs = [];
|
|
const files = [];
|
|
for await (const entry of dirHandle.values()) {
|
|
const nestedPath = `${path}/${entry.name}`;
|
|
if (entry.kind === 'file') {
|
|
cb(nestedPath, entry);
|
|
files.push(
|
|
entry.getFile().then((file) => {
|
|
Object.defineProperty(file, 'webkitRelativePath', {
|
|
configurable: true,
|
|
enumerable: true,
|
|
get: () => nestedPath,
|
|
});
|
|
Object.defineProperty(file, 'handle', {
|
|
configurable: true,
|
|
enumerable: true,
|
|
get: () => entry,
|
|
});
|
|
return file;
|
|
}
|
|
)
|
|
);
|
|
} else if (entry.kind === 'directory' && recursive) {
|
|
cb(nestedPath, entry);
|
|
dirs.push(getFiles(entry, recursive, cb, nestedPath));
|
|
}
|
|
}
|
|
|
|
return [(await Promise.all(dirs)), (await Promise.all(files))];
|
|
};
|
|
|
|
export var verifyPermission = async function (handle, readWrite) {
|
|
const options = {};
|
|
if (readWrite) {
|
|
options.mode = 'readwrite';
|
|
}
|
|
// Check if permission was already granted. If so, return true.
|
|
if ((await handle.queryPermission(options)) === 'granted') {
|
|
return true;
|
|
}
|
|
// Request permission. If the user grants permission, return true.
|
|
if ((await handle.requestPermission(options)) === 'granted') {
|
|
return true;
|
|
}
|
|
// The user didn't grant permission, so return false.
|
|
return false;
|
|
}
|
|
|
|
export var openDirectory = async function (options = {}, cb) {
|
|
options.recursive = options.recursive || false;
|
|
const handle = await window.showDirectoryPicker({ mode: 'readwrite' });
|
|
const _ask = await verifyPermission(handle, true);
|
|
return [handle, getFiles(handle, options.recursive, cb)];
|
|
};
|
|
|
|
export var writeFile = async function (fileHandle, contents) {
|
|
// Create a FileSystemWritableFileStream to write to.
|
|
const writable = await fileHandle.createWritable();
|
|
// Write the contents of the file to the stream.
|
|
await writable.write(contents);
|
|
// Close the file and write the contents to disk.
|
|
await writable.close();
|
|
};
|
|
|
|
export var nfsSupported = function () {
|
|
if ('chooseFileSystemEntries' in self) {
|
|
return 'chooseFileSystemEntries';
|
|
} else if ('showOpenFilePicker' in self) {
|
|
return 'showOpenFilePicker';
|
|
}
|
|
return false;
|
|
}
|
|
|
|
const inputTypes = [
|
|
window.HTMLInputElement,
|
|
window.HTMLSelectElement,
|
|
window.HTMLTextAreaElement,
|
|
]
|
|
|
|
export const triggerInputChange = (node, value = '', name = 'change') => {
|
|
|
|
// only process the change on elements we know have a value setter in their constructor
|
|
if (inputTypes.indexOf(node.__proto__.constructor) > -1) {
|
|
|
|
const setValue = Object.getOwnPropertyDescriptor(node.__proto__, 'value').set
|
|
const event = new Event('change', { bubbles: true })
|
|
|
|
setValue.call(node, value)
|
|
node.dispatchEvent(event)
|
|
}
|
|
}
|