mirror of
https://github.com/mickael-kerjean/filestash.git
synced 2025-10-30 17:46:41 +08:00
chore (rewrite): filesystem elements
This commit is contained in:
@ -21,7 +21,7 @@ export default function(ctrl) {
|
|||||||
render($page);
|
render($page);
|
||||||
|
|
||||||
// feature1: setup the breadcrumb path
|
// feature1: setup the breadcrumb path
|
||||||
qs($page, `[is="component-breadcrumb"]`).setAttribute("path", urlToPath(location.pathname));
|
qs($page, `[is="component-breadcrumb"]`).setAttribute("path", urlToPath(location.pathname + location.hash));
|
||||||
|
|
||||||
// feature2: setup the childrens
|
// feature2: setup the childrens
|
||||||
const $main = qs($page, `[data-bind="filemanager-children"]`);
|
const $main = qs($page, `[data-bind="filemanager-children"]`);
|
||||||
|
|||||||
@ -45,7 +45,7 @@ class Loader extends window.HTMLElement {
|
|||||||
|
|
||||||
customElements.define("component-loader", Loader);
|
customElements.define("component-loader", Loader);
|
||||||
export function createLoader($parent, opts = {}) {
|
export function createLoader($parent, opts = {}) {
|
||||||
const { wait = 500 } = opts;
|
const { wait = 250 } = opts;
|
||||||
const cancel = effect(new rxjs.Observable((observer) => {
|
const cancel = effect(new rxjs.Observable((observer) => {
|
||||||
const $icon = createElement(`
|
const $icon = createElement(`
|
||||||
<div class="component_loader">
|
<div class="component_loader">
|
||||||
@ -61,7 +61,7 @@ export function createLoader($parent, opts = {}) {
|
|||||||
`);
|
`);
|
||||||
const id = window.setTimeout(() => {
|
const id = window.setTimeout(() => {
|
||||||
$parent.replaceChildren($icon);
|
$parent.replaceChildren($icon);
|
||||||
animate($icon, { time: 1000, keyframes: opacityIn() });
|
animate($icon, { time: 750, keyframes: opacityIn() });
|
||||||
}, wait);
|
}, wait);
|
||||||
return () => {
|
return () => {
|
||||||
clearTimeout(id);
|
clearTimeout(id);
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
[is="component_filesystem"] .component_filesystem {
|
[is="component_filesystem"] .component_filesystem {
|
||||||
padding-top: 5px;
|
padding-top: 3px;
|
||||||
}
|
}
|
||||||
[is="component_filesystem"] .empty {
|
[is="component_filesystem"] .empty {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|||||||
@ -49,15 +49,15 @@ export default async function(render) {
|
|||||||
if (!!state.search) {
|
if (!!state.search) {
|
||||||
const removeLoader = createLoader($header);
|
const removeLoader = createLoader($header);
|
||||||
return search(state.search_q).pipe(rxjs.map((files) => ({
|
return search(state.search_q).pipe(rxjs.map((files) => ({
|
||||||
...rest, files, ...state,
|
...rest, files, ...state, read_only: true,
|
||||||
})), removeLoader);
|
})), removeLoader);
|
||||||
}
|
}
|
||||||
return rxjs.of({ ...rest, files, ...state });
|
return rxjs.of({ ...rest, files, ...state, read_only: false });
|
||||||
}))),
|
}))),
|
||||||
rxjs.mergeMap(({ show_hidden, files, ...rest }) => {
|
rxjs.mergeMap(({ show_hidden, files, ...rest }) => {
|
||||||
if (show_hidden === false) files = files.filter(({ name }) => name[0] !== ".");
|
if (show_hidden === false) files = files.filter(({ name }) => name[0] !== ".");
|
||||||
console.log(rest);
|
console.log(rest);
|
||||||
files = sort(files, rest.sort);
|
files = sort(files, rest.sort, rest.order);
|
||||||
return rxjs.of({ ...rest, files })
|
return rxjs.of({ ...rest, files })
|
||||||
}),
|
}),
|
||||||
removeLoader,
|
removeLoader,
|
||||||
@ -69,7 +69,7 @@ export default async function(render) {
|
|||||||
return rxjs.of({...rest, files });
|
return rxjs.of({...rest, files });
|
||||||
}),
|
}),
|
||||||
rxjs.mergeMap((obj) => refreshOnResize$.pipe(rxjs.mapTo(obj))),
|
rxjs.mergeMap((obj) => refreshOnResize$.pipe(rxjs.mapTo(obj))),
|
||||||
rxjs.mergeMap(({ files, path, view }) => { // STEP1: setup the list of files
|
rxjs.mergeMap(({ files, path, view, read_only }) => { // STEP1: setup the list of files
|
||||||
$list.closest(".scroll-y").scrollTop = 0;
|
$list.closest(".scroll-y").scrollTop = 0;
|
||||||
let FILE_HEIGHT, COLUMN_PER_ROW;
|
let FILE_HEIGHT, COLUMN_PER_ROW;
|
||||||
switch(view) {
|
switch(view) {
|
||||||
@ -99,7 +99,7 @@ export default async function(render) {
|
|||||||
$fs.appendChild(createThing({
|
$fs.appendChild(createThing({
|
||||||
...file,
|
...file,
|
||||||
...createLink(file, path),
|
...createLink(file, path),
|
||||||
view,
|
view, read_only,
|
||||||
n: i,
|
n: i,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@ -129,9 +129,10 @@ export default async function(render) {
|
|||||||
$listAfter.style.height = `${height - size}px`;
|
$listAfter.style.height = `${height - size}px`;
|
||||||
};
|
};
|
||||||
setHeight(0);
|
setHeight(0);
|
||||||
// const top = ($node) => $node.getBoundingClientRect().top;
|
const top = ($node) => $node.getBoundingClientRect().top;
|
||||||
return rxjs.of({
|
return rxjs.of({
|
||||||
files,
|
files,
|
||||||
|
read_only,
|
||||||
path,
|
path,
|
||||||
view,
|
view,
|
||||||
currentState: 0,
|
currentState: 0,
|
||||||
@ -140,11 +141,11 @@ export default async function(render) {
|
|||||||
FILE_HEIGHT,
|
FILE_HEIGHT,
|
||||||
BLOCK_SIZE,
|
BLOCK_SIZE,
|
||||||
COLUMN_PER_ROW,
|
COLUMN_PER_ROW,
|
||||||
MARGIN: 35, // TODO: top($list) - top($list.closest(".scroll-y"));
|
MARGIN: top($list) - top($list.closest(".scroll-y")),
|
||||||
});
|
});
|
||||||
}),
|
}),
|
||||||
rxjs.mergeMap(({
|
rxjs.mergeMap(({
|
||||||
files, path, view,
|
files, path, view, read_only,
|
||||||
BLOCK_SIZE, COLUMN_PER_ROW, FILE_HEIGHT,
|
BLOCK_SIZE, COLUMN_PER_ROW, FILE_HEIGHT,
|
||||||
MARGIN,
|
MARGIN,
|
||||||
currentState,
|
currentState,
|
||||||
@ -207,7 +208,7 @@ export default async function(render) {
|
|||||||
type: "hidden",
|
type: "hidden",
|
||||||
}));
|
}));
|
||||||
else $fs.appendChild(createThing({
|
else $fs.appendChild(createThing({
|
||||||
...file,
|
...file, read_only,
|
||||||
...createLink(file, path),
|
...createLink(file, path),
|
||||||
view,
|
view,
|
||||||
n: i,
|
n: i,
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
padding: 5px 0;
|
padding: 4px 0;
|
||||||
backdrop-filter: blur(20px) saturate(2);
|
backdrop-filter: blur(20px) saturate(2);
|
||||||
transition: 0.2s ease box-shadow;
|
transition: 0.2s ease box-shadow;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@ import componentDelete from "./modal_delete.js";
|
|||||||
|
|
||||||
import { getSelection$, clearSelection } from "./state_selection.js";
|
import { getSelection$, clearSelection } from "./state_selection.js";
|
||||||
import { getAction$, setAction } from "./state_event.js";
|
import { getAction$, setAction } from "./state_event.js";
|
||||||
import { setState } from "./state_filesystem.js";
|
import { setState, getState$ } from "./state_filesystem.js";
|
||||||
|
|
||||||
const modalOpt = {
|
const modalOpt = {
|
||||||
withButtonsRight: "OK",
|
withButtonsRight: "OK",
|
||||||
@ -38,7 +38,7 @@ export default async function(render) {
|
|||||||
componentRight(createRender(qs($page, ".action.right")));
|
componentRight(createRender(qs($page, ".action.right")));
|
||||||
|
|
||||||
effect(rxjs.fromEvent($scroll, "scroll", { passive: true }).pipe(
|
effect(rxjs.fromEvent($scroll, "scroll", { passive: true }).pipe(
|
||||||
rxjs.map((e) => e.target.scrollTop > 30),
|
rxjs.map((e) => e.target.scrollTop > 12),
|
||||||
rxjs.distinctUntilChanged(),
|
rxjs.distinctUntilChanged(),
|
||||||
rxjs.startWith(false),
|
rxjs.startWith(false),
|
||||||
rxjs.tap((scrolling) => scrolling
|
rxjs.tap((scrolling) => scrolling
|
||||||
@ -208,18 +208,23 @@ function componentRight(render) {
|
|||||||
}
|
}
|
||||||
const $lis = qsa($page, `.dropdown_container li`);
|
const $lis = qsa($page, `.dropdown_container li`);
|
||||||
return onClick($lis).pipe(
|
return onClick($lis).pipe(
|
||||||
rxjs.tap(($el) => {
|
rxjs.first(),
|
||||||
|
rxjs.mergeMap(($el) => getState$().pipe(rxjs.first(), rxjs.map((state) => ({
|
||||||
|
order: state.order,
|
||||||
|
$el,
|
||||||
|
})))),
|
||||||
|
rxjs.tap(({ $el, order }) => {
|
||||||
setState(
|
setState(
|
||||||
"sort", $el.getAttribute("data-target"),
|
"sort", $el.getAttribute("data-target"),
|
||||||
"order", !!$el.querySelector("img") ? "asc" : "des",
|
"order", order === "asc" ? "des" : "asc",
|
||||||
);
|
);
|
||||||
[...$lis].map(($li) => {
|
[...$lis].map(($li) => {
|
||||||
const $img = $li.querySelector("img");
|
const $img = $li.querySelector("img");
|
||||||
if ($img) $img.remove();
|
if ($img) $img.remove();
|
||||||
});
|
});
|
||||||
$el.appendChild(createElement(`<img class="component_icon" src="data:image/svg+xml;base64,${ICONS.CHECK}" alt="check" />`));
|
$el.appendChild(createElement(`<img class="component_icon" src="data:image/svg+xml;base64,${ICONS.CHECK}" alt="check" />`));
|
||||||
|
$sort.classList.remove("active");
|
||||||
}),
|
}),
|
||||||
rxjs.tap(() => $sort.classList.remove("active")),
|
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -1,85 +1,94 @@
|
|||||||
import { extname } from "../../lib/path.js";
|
import { extname } from "../../lib/path.js";
|
||||||
|
|
||||||
export function sort(files, type) {
|
export function sort(files, type, order) {
|
||||||
if (type === "name") {
|
switch(type) {
|
||||||
return sortByName(files);
|
case "name": return sortByName(files, order);
|
||||||
} else if (type === "date") {
|
case "date": return sortByDate(files, order);
|
||||||
return sortByDate(files);
|
default: return sortByType(files, order);
|
||||||
} else {
|
}
|
||||||
return sortByType(files);
|
}
|
||||||
|
|
||||||
|
function sortByType(files, order) {
|
||||||
|
let tmp;
|
||||||
|
return files.sort(function(fileA, fileB) {
|
||||||
|
tmp = _moveLoadingDownward(fileA, fileB);
|
||||||
|
if (tmp !== 0) return tmp;
|
||||||
|
|
||||||
|
tmp = _moveFolderUpward(fileA, fileB);
|
||||||
|
if (tmp !== 0) return tmp;
|
||||||
|
|
||||||
|
tmp = _moveHiddenFilesDownward(fileA, fileB);
|
||||||
|
if (tmp !== 0) return tmp;
|
||||||
|
|
||||||
|
const faname = fileA.name.toLowerCase();
|
||||||
|
const fbname = fileB.name.toLowerCase();
|
||||||
|
|
||||||
|
const aExt = extname(faname);
|
||||||
|
const bExt = extname(fbname);
|
||||||
|
|
||||||
|
if (aExt === bExt) return sortString(faname, fbname, order);
|
||||||
|
return sortString(aExt, bExt, order);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function sortByName(files, order) {
|
||||||
|
let tmp;
|
||||||
|
return files.sort(function(fileA, fileB) {
|
||||||
|
tmp = _moveLoadingDownward(fileA, fileB);
|
||||||
|
if (tmp !== 0) return tmp;
|
||||||
|
|
||||||
|
tmp = _moveFolderUpward(fileA, fileB);
|
||||||
|
if (tmp !== 0) return tmp;
|
||||||
|
|
||||||
|
tmp = _moveHiddenFilesDownward(fileA, fileB);
|
||||||
|
if (tmp !== 0) return tmp;
|
||||||
|
|
||||||
|
return sortString(fileA.name.toLowerCase(), fileB.name.toLowerCase(), order);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function sortByDate(files, order) {
|
||||||
|
return files.sort(function(fileA, fileB) {
|
||||||
|
if (fileB.time === fileA.time) {
|
||||||
|
return sortString(fileA.name, fileB.name, order);
|
||||||
|
}
|
||||||
|
return sortNumber(fileA.time, fileB.time, order);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function sortString(a, b, order) {
|
||||||
|
if (order === "asc") return a > b ? +1 : -1;
|
||||||
|
return a < b ? +1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sortNumber(a, b, order) {
|
||||||
|
if (order === "asc") return b - a;
|
||||||
|
return a - b;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
function _moveLoadingDownward(fileA, fileB) {
|
function _moveLoadingDownward(fileA, fileB) {
|
||||||
if (fileA.icon === "loading" && fileB.icon !== "loading") {
|
const aIsLoading = fileA.icon === "loading";
|
||||||
return +1;
|
const bIsLoading = fileB.icon === "loading";
|
||||||
} else if (fileA.icon !== "loading" && fileB.icon === "loading") {
|
|
||||||
return -1;
|
if (aIsLoading && !bIsLoading) return +1;
|
||||||
}
|
else if (!aIsLoading && bIsLoading) return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _moveFolderUpward(fileA, fileB) {
|
function _moveFolderUpward(fileA, fileB) {
|
||||||
if (["directory", "link"].indexOf(fileA.type) === -1 &&
|
const aIsDirectory = ["directory", "link"].indexOf(fileA.type) !== -1;
|
||||||
["directory", "link"].indexOf(fileB.type) !== -1) {
|
const bIsDirectory = ["directory", "link"].indexOf(fileB.type) !== -1;
|
||||||
return +1;
|
|
||||||
} else if (["directory", "link"].indexOf(fileA.type) !== -1 &&
|
if (!aIsDirectory && bIsDirectory) return +1;
|
||||||
["directory", "link"].indexOf(fileB.type) === -1) {
|
else if (aIsDirectory && !bIsDirectory) return -1;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _moveHiddenFilesDownward(fileA, fileB) {
|
function _moveHiddenFilesDownward(fileA, fileB) {
|
||||||
if (fileA.name[0] === "." && fileB.name[0] !== ".") return +1;
|
const aIsHidden = fileA.name[0] === ".";
|
||||||
else if (fileA.name[0] !== "." && fileB.name[0] === ".") return -1;
|
const bIsHidden = fileB.name[0] === ".";
|
||||||
|
|
||||||
|
if (aIsHidden && !bIsHidden) return +1;
|
||||||
|
if (!aIsHidden && bIsHidden) return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
function sortByType(files) {
|
|
||||||
return files.sort((fileA, fileB) => {
|
|
||||||
let tmp = _moveLoadingDownward(fileA, fileB);
|
|
||||||
if (tmp !== 0) return tmp;
|
|
||||||
|
|
||||||
tmp = _moveFolderUpward(fileA, fileB);
|
|
||||||
if (tmp !== 0) return tmp;
|
|
||||||
|
|
||||||
tmp = _moveHiddenFilesDownward(fileA, fileB);
|
|
||||||
if (tmp !== 0) return tmp;
|
|
||||||
|
|
||||||
const aExt = extname(fileA.name.toLowerCase());
|
|
||||||
const bExt = extname(fileB.name.toLowerCase());
|
|
||||||
|
|
||||||
if (fileA.name.toLowerCase() === fileB.name.toLowerCase()) {
|
|
||||||
return fileA.name > fileB.name ? +1 : -1;
|
|
||||||
} else {
|
|
||||||
if (aExt !== bExt) return aExt > bExt ? +1 : -1;
|
|
||||||
else return fileA.name.toLowerCase() > fileB.name.toLowerCase() ? +1 : -1;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function sortByName(files) {
|
|
||||||
return files.sort((fileA, fileB) => {
|
|
||||||
let tmp = _moveLoadingDownward(fileA, fileB);
|
|
||||||
if (tmp !== 0) return tmp;
|
|
||||||
|
|
||||||
tmp = _moveFolderUpward(fileA, fileB);
|
|
||||||
if (tmp !== 0) return tmp;
|
|
||||||
|
|
||||||
tmp = _moveHiddenFilesDownward(fileA, fileB);
|
|
||||||
if (tmp !== 0) return tmp;
|
|
||||||
|
|
||||||
if (fileA.name.toLowerCase() === fileB.name.toLowerCase()) {
|
|
||||||
return fileA.name > fileB.name ? +1 : -1;
|
|
||||||
}
|
|
||||||
return fileA.name.toLowerCase() > fileB.name.toLowerCase() ? +1 : -1;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function sortByDate(files) {
|
|
||||||
return files.sort((fileA, fileB) => {
|
|
||||||
const tmp = _moveLoadingDownward(fileA, fileB);
|
|
||||||
if (tmp !== 0) return tmp;
|
|
||||||
|
|
||||||
if (fileB.time === fileA.time) {
|
|
||||||
return fileA.name > fileB.name ? +1 : -1;
|
|
||||||
}
|
|
||||||
return fileB.time - fileA.time;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|||||||
@ -46,6 +46,7 @@ export function createThing({
|
|||||||
// permissions = {}
|
// permissions = {}
|
||||||
view = "",
|
view = "",
|
||||||
n = 0,
|
n = 0,
|
||||||
|
read_only = false,
|
||||||
}) {
|
}) {
|
||||||
const $thing = $tmpl.cloneNode(true);
|
const $thing = $tmpl.cloneNode(true);
|
||||||
assert.type($thing, window.HTMLElement);
|
assert.type($thing, window.HTMLElement);
|
||||||
@ -60,7 +61,12 @@ export function createThing({
|
|||||||
$thing.classList.add("view-" + view);
|
$thing.classList.add("view-" + view);
|
||||||
$time.textContent = formatTime(new Date(time));
|
$time.textContent = formatTime(new Date(time));
|
||||||
sideEffectSelection($thing, isSelected(n));
|
sideEffectSelection($thing, isSelected(n));
|
||||||
if (type === "hidden") $thing.classList.add("hidden");
|
|
||||||
|
if (read_only === true) return $thing;
|
||||||
|
else if (type === "hidden") {
|
||||||
|
$thing.classList.add("hidden");
|
||||||
|
return $thing;
|
||||||
|
}
|
||||||
|
|
||||||
$thing.querySelector(".component_checkbox").onclick = function(e) {
|
$thing.querySelector(".component_checkbox").onclick = function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|||||||
Reference in New Issue
Block a user