diff --git a/public/assets/components/decorator_shell_filemanager.js b/public/assets/components/decorator_shell_filemanager.js
index bd65f972..2799ae39 100644
--- a/public/assets/components/decorator_shell_filemanager.js
+++ b/public/assets/components/decorator_shell_filemanager.js
@@ -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"]`);
diff --git a/public/assets/components/loader.js b/public/assets/components/loader.js
index ef595e0e..f4fe0a27 100644
--- a/public/assets/components/loader.js
+++ b/public/assets/components/loader.js
@@ -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(`
@@ -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);
diff --git a/public/assets/pages/filespage/ctrl_filesystem.css b/public/assets/pages/filespage/ctrl_filesystem.css
index e34bd92c..1a2cf9b5 100644
--- a/public/assets/pages/filespage/ctrl_filesystem.css
+++ b/public/assets/pages/filespage/ctrl_filesystem.css
@@ -1,5 +1,5 @@
[is="component_filesystem"] .component_filesystem {
- padding-top: 5px;
+ padding-top: 3px;
}
[is="component_filesystem"] .empty {
text-align: center;
diff --git a/public/assets/pages/filespage/ctrl_filesystem.js b/public/assets/pages/filespage/ctrl_filesystem.js
index 4a929ea0..4636d460 100644
--- a/public/assets/pages/filespage/ctrl_filesystem.js
+++ b/public/assets/pages/filespage/ctrl_filesystem.js
@@ -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,
diff --git a/public/assets/pages/filespage/ctrl_submenu.css b/public/assets/pages/filespage/ctrl_submenu.css
index 725fa716..65901562 100644
--- a/public/assets/pages/filespage/ctrl_submenu.css
+++ b/public/assets/pages/filespage/ctrl_submenu.css
@@ -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;
}
diff --git a/public/assets/pages/filespage/ctrl_submenu.js b/public/assets/pages/filespage/ctrl_submenu.js
index c5d916b5..09f33a24 100644
--- a/public/assets/pages/filespage/ctrl_submenu.js
+++ b/public/assets/pages/filespage/ctrl_submenu.js
@@ -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) {
-
-
- -
- Sort By Type
-
-
- -
- Sort By Date
-
- -
- Sort By Name
-
-
-
+
+
+ -
+ Sort By Type
+
+
+ -
+ Sort By Date
+
+ -
+ Sort By Name
+
+
+
`))),
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(`

`));
+ $sort.classList.remove("active");
}),
- rxjs.tap(() => $sort.classList.remove("active")),
);
}),
),
diff --git a/public/assets/pages/filespage/helper.js b/public/assets/pages/filespage/helper.js
index cc2af8b5..dba852f9 100644
--- a/public/assets/pages/filespage/helper.js
+++ b/public/assets/pages/filespage/helper.js
@@ -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;
- });
-}
diff --git a/public/assets/pages/filespage/thing.js b/public/assets/pages/filespage/thing.js
index 2d6b6e8d..f30779aa 100644
--- a/public/assets/pages/filespage/thing.js
+++ b/public/assets/pages/filespage/thing.js
@@ -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();