chore (rewrite): filesystem elements

This commit is contained in:
MickaelK
2024-05-10 01:31:20 +10:00
parent 0fe75a8a18
commit 34cb374202
8 changed files with 127 additions and 106 deletions

View File

@ -21,7 +21,7 @@ export default function(ctrl) {
render($page);
// 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
const $main = qs($page, `[data-bind="filemanager-children"]`);

View File

@ -45,7 +45,7 @@ class Loader extends window.HTMLElement {
customElements.define("component-loader", Loader);
export function createLoader($parent, opts = {}) {
const { wait = 500 } = opts;
const { wait = 250 } = opts;
const cancel = effect(new rxjs.Observable((observer) => {
const $icon = createElement(`
<div class="component_loader">
@ -61,7 +61,7 @@ export function createLoader($parent, opts = {}) {
`);
const id = window.setTimeout(() => {
$parent.replaceChildren($icon);
animate($icon, { time: 1000, keyframes: opacityIn() });
animate($icon, { time: 750, keyframes: opacityIn() });
}, wait);
return () => {
clearTimeout(id);

View File

@ -1,5 +1,5 @@
[is="component_filesystem"] .component_filesystem {
padding-top: 5px;
padding-top: 3px;
}
[is="component_filesystem"] .empty {
text-align: center;

View File

@ -49,15 +49,15 @@ export default async function(render) {
if (!!state.search) {
const removeLoader = createLoader($header);
return search(state.search_q).pipe(rxjs.map((files) => ({
...rest, files, ...state,
...rest, files, ...state, read_only: true,
})), removeLoader);
}
return rxjs.of({ ...rest, files, ...state });
return rxjs.of({ ...rest, files, ...state, read_only: false });
}))),
rxjs.mergeMap(({ show_hidden, files, ...rest }) => {
if (show_hidden === false) files = files.filter(({ name }) => name[0] !== ".");
console.log(rest);
files = sort(files, rest.sort);
files = sort(files, rest.sort, rest.order);
return rxjs.of({ ...rest, files })
}),
removeLoader,
@ -69,7 +69,7 @@ export default async function(render) {
return rxjs.of({...rest, files });
}),
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;
let FILE_HEIGHT, COLUMN_PER_ROW;
switch(view) {
@ -99,7 +99,7 @@ export default async function(render) {
$fs.appendChild(createThing({
...file,
...createLink(file, path),
view,
view, read_only,
n: i,
}));
}
@ -129,9 +129,10 @@ export default async function(render) {
$listAfter.style.height = `${height - size}px`;
};
setHeight(0);
// const top = ($node) => $node.getBoundingClientRect().top;
const top = ($node) => $node.getBoundingClientRect().top;
return rxjs.of({
files,
read_only,
path,
view,
currentState: 0,
@ -140,11 +141,11 @@ export default async function(render) {
FILE_HEIGHT,
BLOCK_SIZE,
COLUMN_PER_ROW,
MARGIN: 35, // TODO: top($list) - top($list.closest(".scroll-y"));
MARGIN: top($list) - top($list.closest(".scroll-y")),
});
}),
rxjs.mergeMap(({
files, path, view,
files, path, view, read_only,
BLOCK_SIZE, COLUMN_PER_ROW, FILE_HEIGHT,
MARGIN,
currentState,
@ -207,7 +208,7 @@ export default async function(render) {
type: "hidden",
}));
else $fs.appendChild(createThing({
...file,
...file, read_only,
...createLink(file, path),
view,
n: i,

View File

@ -4,7 +4,7 @@
position: sticky;
top: 0;
z-index: 3;
padding: 5px 0;
padding: 4px 0;
backdrop-filter: blur(20px) saturate(2);
transition: 0.2s ease box-shadow;
}

View File

@ -16,7 +16,7 @@ import componentDelete from "./modal_delete.js";
import { getSelection$, clearSelection } from "./state_selection.js";
import { getAction$, setAction } from "./state_event.js";
import { setState } from "./state_filesystem.js";
import { setState, getState$ } from "./state_filesystem.js";
const modalOpt = {
withButtonsRight: "OK",
@ -38,7 +38,7 @@ export default async function(render) {
componentRight(createRender(qs($page, ".action.right")));
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.startWith(false),
rxjs.tap((scrolling) => scrolling
@ -157,20 +157,20 @@ function componentRight(render) {
<img class="component_icon" draggable="false" src="data:image/svg+xml;base64,${ICONS.SORT}" alt="sort" />
</button>
<div class="component_dropdown view sort" data-target="sort">
<div class="dropdown_container">
<ul>
<li data-target="type">
Sort By Type
<img class="component_icon" draggable="false" src="data:image/svg+xml;base64,${ICONS.CHECK}" alt="check" />
</li>
<li data-target="date">
Sort By Date
</li>
<li data-target="name">
Sort By Name
</li>
</ul>
</div>
<div class="dropdown_container">
<ul>
<li data-target="type">
Sort By Type
<img class="component_icon" draggable="false" src="data:image/svg+xml;base64,${ICONS.CHECK}" alt="check" />
</li>
<li data-target="date">
Sort By Date
</li>
<li data-target="name">
Sort By Name
</li>
</ul>
</div>
</div>
`))),
rxjs.mergeMap(($page) => rxjs.merge(
@ -208,18 +208,23 @@ function componentRight(render) {
}
const $lis = qsa($page, `.dropdown_container li`);
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(
"sort", $el.getAttribute("data-target"),
"order", !!$el.querySelector("img") ? "asc" : "des",
"order", order === "asc" ? "des" : "asc",
);
[...$lis].map(($li) => {
const $img = $li.querySelector("img");
if ($img) $img.remove();
});
$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")),
);
}),
),

View File

@ -1,85 +1,94 @@
import { extname } from "../../lib/path.js";
export function sort(files, type) {
if (type === "name") {
return sortByName(files);
} else if (type === "date") {
return sortByDate(files);
} else {
return sortByType(files);
export function sort(files, type, order) {
switch(type) {
case "name": return sortByName(files, order);
case "date": return sortByDate(files, order);
default: return sortByType(files, order);
}
};
}
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) {
if (fileA.icon === "loading" && fileB.icon !== "loading") {
return +1;
} else if (fileA.icon !== "loading" && fileB.icon === "loading") {
return -1;
}
const aIsLoading = fileA.icon === "loading";
const bIsLoading = fileB.icon === "loading";
if (aIsLoading && !bIsLoading) return +1;
else if (!aIsLoading && bIsLoading) return -1;
return 0;
}
function _moveFolderUpward(fileA, fileB) {
if (["directory", "link"].indexOf(fileA.type) === -1 &&
["directory", "link"].indexOf(fileB.type) !== -1) {
return +1;
} else if (["directory", "link"].indexOf(fileA.type) !== -1 &&
["directory", "link"].indexOf(fileB.type) === -1) {
return -1;
}
const aIsDirectory = ["directory", "link"].indexOf(fileA.type) !== -1;
const bIsDirectory = ["directory", "link"].indexOf(fileB.type) !== -1;
if (!aIsDirectory && bIsDirectory) return +1;
else if (aIsDirectory && !bIsDirectory) return -1;
return 0;
}
function _moveHiddenFilesDownward(fileA, fileB) {
if (fileA.name[0] === "." && fileB.name[0] !== ".") return +1;
else if (fileA.name[0] !== "." && fileB.name[0] === ".") return -1;
const aIsHidden = fileA.name[0] === ".";
const bIsHidden = fileB.name[0] === ".";
if (aIsHidden && !bIsHidden) return +1;
if (!aIsHidden && bIsHidden) return -1;
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;
});
}

View File

@ -46,6 +46,7 @@ export function createThing({
// permissions = {}
view = "",
n = 0,
read_only = false,
}) {
const $thing = $tmpl.cloneNode(true);
assert.type($thing, window.HTMLElement);
@ -60,7 +61,12 @@ export function createThing({
$thing.classList.add("view-" + view);
$time.textContent = formatTime(new Date(time));
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) {
e.preventDefault();