mirror of
				https://github.com/mickael-kerjean/filestash.git
				synced 2025-10-31 10:07:15 +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 | ||||||
| @ -157,20 +157,20 @@ function componentRight(render) { | |||||||
|                 <img class="component_icon" draggable="false" src="data:image/svg+xml;base64,${ICONS.SORT}" alt="sort" /> |                 <img class="component_icon" draggable="false" src="data:image/svg+xml;base64,${ICONS.SORT}" alt="sort" /> | ||||||
|             </button> |             </button> | ||||||
|             <div class="component_dropdown view sort" data-target="sort"> |             <div class="component_dropdown view sort" data-target="sort"> | ||||||
|               <div class="dropdown_container"> |                 <div class="dropdown_container"> | ||||||
|                 <ul> |                     <ul> | ||||||
|                   <li data-target="type"> |                         <li data-target="type"> | ||||||
|                        Sort By Type |                             Sort By Type | ||||||
|                        <img class="component_icon" draggable="false" src="data:image/svg+xml;base64,${ICONS.CHECK}" alt="check" /> |                             <img class="component_icon" draggable="false" src="data:image/svg+xml;base64,${ICONS.CHECK}" alt="check" /> | ||||||
|                   </li> |                         </li> | ||||||
|                   <li data-target="date"> |                         <li data-target="date"> | ||||||
|                       Sort By Date |                             Sort By Date | ||||||
|                   </li> |                         </li> | ||||||
|                   <li data-target="name"> |                         <li data-target="name"> | ||||||
|                     Sort By Name |                             Sort By Name | ||||||
|                   </li> |                         </li> | ||||||
|                 </ul> |                     </ul> | ||||||
|               </div> |                 </div> | ||||||
|             </div> |             </div> | ||||||
|         `))), |         `))), | ||||||
|         rxjs.mergeMap(($page) => rxjs.merge( |         rxjs.mergeMap(($page) => rxjs.merge( | ||||||
| @ -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
	 MickaelK
					MickaelK