mirror of
https://github.com/mickael-kerjean/filestash
synced 2025-12-29 03:33:24 +01:00
chore (rewrite): prepare initial release
This commit is contained in:
parent
0e8eb0d820
commit
e854211d7f
15 changed files with 137 additions and 48 deletions
|
|
@ -267,7 +267,7 @@ export class ShareComponent extends React.Component {
|
|||
type="inline"
|
||||
cond={!!this.state.show_advanced}><Icon name="arrow_top"/></NgIf>
|
||||
<NgIf
|
||||
type="inline"t("Password") }
|
||||
type="inline"
|
||||
placeholder={ t("protect access with a password") }
|
||||
onChange={this.updateState.bind(this, "password")}
|
||||
inputType="password"/>
|
||||
|
|
|
|||
|
|
@ -32,11 +32,14 @@
|
|||
border-top-right-radius: 30px;
|
||||
}
|
||||
.component_filemanager_shell [data-bind="sidebar"].hidden ~ div > component-breadcrumb > .component_breadcrumb,
|
||||
.component_filemanager_shell [data-bind="sidebar"].hidden ~ div > [data-bind="filemanager-children"] .container {
|
||||
width: 95%;
|
||||
.component_filemanager_shell [data-bind="sidebar"]:empty ~ div > component-breadcrumb > .component_breadcrumb,
|
||||
.component_filemanager_shell [data-bind="sidebar"].hidden ~ div > [data-bind="filemanager-children"] .container,
|
||||
.component_filemanager_shell [data-bind="sidebar"]:empty ~ div > [data-bind="filemanager-children"] .container {
|
||||
width: 98%;
|
||||
margin: 0 auto;
|
||||
max-width: 815px;
|
||||
}
|
||||
|
||||
.component_filemanager_shell [data-bind="sidebar"].hidden ~ div > [data-bind="filemanager-children"] {
|
||||
background: rgba(100,100,100,.05);
|
||||
}
|
||||
|
|
@ -50,10 +53,15 @@
|
|||
}
|
||||
|
||||
.component_filemanager_shell [data-bind="sidebar"].hidden ~ div [is="component_filesystem"],
|
||||
.component_filemanager_shell [data-bind="sidebar"]:empty ~ div [is="component_filesystem"],
|
||||
.component_filemanager_shell [data-bind="sidebar"].hidden ~ div [is="component_newitem"],
|
||||
.component_filemanager_shell [data-bind="sidebar"]:empty ~ div [is="component_newitem"],
|
||||
.component_filemanager_shell [data-bind="sidebar"].hidden ~ div component-menubar,
|
||||
.component_filemanager_shell [data-bind="sidebar"]:empty ~ div component-menubar,
|
||||
.component_filemanager_shell [data-bind="sidebar"].hidden ~ div component-breadcrumb,
|
||||
.component_filemanager_shell [data-bind="sidebar"].hidden ~ div [is="component_submenu"] .component_submenu {
|
||||
.component_filemanager_shell [data-bind="sidebar"]:empty ~ div component-breadcrumb,
|
||||
.component_filemanager_shell [data-bind="sidebar"].hidden ~ div [is="component_submenu"] .component_submenu,
|
||||
.component_filemanager_shell [data-bind="sidebar"]:empty ~ div [is="component_submenu"] .component_submenu {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
box-shadow: 1px 2px 20px rgba(0, 0, 0, 0.1);
|
||||
background: white;
|
||||
width: 80%;
|
||||
max-width: 310px;
|
||||
max-width: 320px;
|
||||
padding: 20px 20px 0 20px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,8 +113,10 @@ class ModalComponent extends window.HTMLElement {
|
|||
));
|
||||
|
||||
// feature: center horizontally
|
||||
effect(rxjs.fromEvent(window, "resize").pipe(
|
||||
rxjs.startWith(null),
|
||||
effect(rxjs.merge(
|
||||
rxjs.fromEvent(window, "resize"),
|
||||
rxjs.of(null),
|
||||
).pipe(
|
||||
rxjs.distinct(() => document.body.offsetHeight),
|
||||
rxjs.map(() => {
|
||||
let size = targetHeight;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,15 @@
|
|||
padding-right: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.component_filemanager_shell .component_sidebar h3 input::placeholder {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
.component_filemanager_shell .component_sidebar h3 input {
|
||||
border: none;
|
||||
color: var(--dark);
|
||||
font-weight: bold;
|
||||
font-size: inherit;
|
||||
}
|
||||
.component_filemanager_shell .component_sidebar [data-bind="your-files"] > ul { margin-left: 0px; }
|
||||
.component_filemanager_shell .component_sidebar ul {
|
||||
margin-top: 0px;
|
||||
|
|
@ -44,7 +53,12 @@
|
|||
padding-left: 5px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.component_filemanager_shell .search .component_sidebar ul {
|
||||
margin: 0;
|
||||
}
|
||||
.component_filemanager_shell .search .component_sidebar ul li {
|
||||
padding-left: 0;
|
||||
}
|
||||
.component_filemanager_shell .component_sidebar a {
|
||||
display: flex;
|
||||
padding: 5px 5px 5px 10px;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { createElement, onDestroy } from "../lib/skeleton/index.js";
|
||||
import rxjs, { effect, onClick } from "../lib/rx.js";
|
||||
import { fromHref, toHref } from "../lib/skeleton/router.js";
|
||||
import { qs } from "../lib/dom.js";
|
||||
import { animate, opacityIn } from "../lib/animate.js";
|
||||
import { qs, qsa } from "../lib/dom.js";
|
||||
import { settingsGet, settingsSave } from "../lib/store.js";
|
||||
import { loadCSS } from "../helpers/loader.js";
|
||||
import t from "../locales/index.js";
|
||||
|
|
@ -20,13 +19,13 @@ const mv = (from, to) => withVirtualLayer(
|
|||
|
||||
export default async function ctrlSidebar(render) {
|
||||
if (new URL(location).searchParams.get("nav") === "false") return;
|
||||
else if (document.body.clientWidth < 850) return; // do not waste CPU cycle on small devices
|
||||
else if (document.body.clientWidth < 850) return;
|
||||
|
||||
const $page = render(createElement(`
|
||||
<div class="component_sidebar"><div>
|
||||
<h3>
|
||||
<img src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgYXJpYS1oaWRkZW49InRydWUiCiAgIGZvY3VzYWJsZT0iZmFsc2UiCiAgIHJvbGU9ImltZyIKICAgY2xhc3M9Im9jdGljb24gb2N0aWNvbi1zaWRlYmFyLWV4cGFuZCIKICAgdmlld0JveD0iMCAwIDE2IDE2IgogICB3aWR0aD0iMTYiCiAgIGhlaWdodD0iMTYiCiAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgdXNlci1zZWxlY3Q6IG5vbmU7IHZlcnRpY2FsLWFsaWduOiB0ZXh0LWJvdHRvbTsgb3ZlcmZsb3c6IHZpc2libGU7IgogICB2ZXJzaW9uPSIxLjEiCiAgIGlkPSJzdmc3MjI3IgogICBzb2RpcG9kaTpkb2NuYW1lPSJnaXRodWJmb2xkLnN2ZyIKICAgaW5rc2NhcGU6dmVyc2lvbj0iMS4yLjIgKGIwYTg0ODY1NDEsIDIwMjItMTItMDEpIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgeG1sbnM6c29kaXBvZGk9Imh0dHA6Ly9zb2RpcG9kaS5zb3VyY2Vmb3JnZS5uZXQvRFREL3NvZGlwb2RpLTAuZHRkIgogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogIDxkZWZzCiAgICAgaWQ9ImRlZnM3MjMxIiAvPgogIDxzb2RpcG9kaTpuYW1lZHZpZXcKICAgICBpZD0ibmFtZWR2aWV3NzIyOSIKICAgICBwYWdlY29sb3I9IiNmZmZmZmYiCiAgICAgYm9yZGVyY29sb3I9IiMwMDAwMDAiCiAgICAgYm9yZGVyb3BhY2l0eT0iMC4yNSIKICAgICBpbmtzY2FwZTpzaG93cGFnZXNoYWRvdz0iMiIKICAgICBpbmtzY2FwZTpwYWdlb3BhY2l0eT0iMC4wIgogICAgIGlua3NjYXBlOnBhZ2VjaGVja2VyYm9hcmQ9IjAiCiAgICAgaW5rc2NhcGU6ZGVza2NvbG9yPSIjZDFkMWQxIgogICAgIHNob3dncmlkPSJmYWxzZSIKICAgICBpbmtzY2FwZTp6b29tPSIxNC43NSIKICAgICBpbmtzY2FwZTpjeD0iNC4yMDMzODk4IgogICAgIGlua3NjYXBlOmN5PSI4IgogICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTgxNyIKICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSIxMzk3IgogICAgIGlua3NjYXBlOndpbmRvdy14PSI3IgogICAgIGlua3NjYXBlOndpbmRvdy15PSIzNCIKICAgICBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIxIgogICAgIGlua3NjYXBlOmN1cnJlbnQtbGF5ZXI9InN2ZzcyMjciIC8+CiAgPHBhdGgKICAgICBkPSJtNC4xNzcgNy44MjMgMi4zOTYtMi4zOTZBLjI1LjI1IDAgMCAxIDcgNS42MDR2NC43OTJhLjI1LjI1IDAgMCAxLS40MjcuMTc3TDQuMTc3IDguMTc3YS4yNS4yNSAwIDAgMSAwLS4zNTRaIgogICAgIGlkPSJwYXRoNzIyMyIKICAgICBzdHlsZT0iZmlsbDojNTc1OTVhO2ZpbGwtb3BhY2l0eToxIiAvPgogIDxwYXRoCiAgICAgZD0iTTAgMS43NUMwIC43ODQuNzg0IDAgMS43NSAwaDEyLjVDMTUuMjE2IDAgMTYgLjc4NCAxNiAxLjc1djEyLjVBMS43NSAxLjc1IDAgMCAxIDE0LjI1IDE2SDEuNzVBMS43NSAxLjc1IDAgMCAxIDAgMTQuMjVabTEuNzUtLjI1YS4yNS4yNSAwIDAgMC0uMjUuMjV2MTIuNWMwIC4xMzguMTEyLjI1LjI1LjI1SDkuNXYtMTNabTEyLjUgMTNhLjI1LjI1IDAgMCAwIC4yNS0uMjVWMS43NWEuMjUuMjUgMCAwIDAtLjI1LS4yNUgxMXYxM1oiCiAgICAgaWQ9InBhdGg3MjI1IgogICAgIHN0eWxlPSJmaWxsOiM1NzU5NWE7ZmlsbC1vcGFjaXR5OjEiIC8+Cjwvc3ZnPgo=" alt="close">
|
||||
${t("Your Files")}
|
||||
<input type="text" placeholder="${t("Your Files")}" />
|
||||
</h3>
|
||||
<div data-bind="your-files"></div>
|
||||
|
||||
|
|
@ -73,16 +72,18 @@ export default async function ctrlSidebar(render) {
|
|||
$page.firstElementChild.scrollTop = state.scrollTop;
|
||||
}
|
||||
onDestroy(() => {
|
||||
$page.classList.remove("search");
|
||||
state.$cache = $files.firstElementChild.cloneNode(true);
|
||||
state.scrollTop = $page.firstElementChild.scrollTop
|
||||
});
|
||||
const chunk = new pathChunk();
|
||||
const arr = chunk.toArray();
|
||||
const fullpath = chunk.toString();
|
||||
const $tree = document.createDocumentFragment();
|
||||
for (let i = 0; i<arr.length-1; i++) {
|
||||
const path = chunk.toString(i);
|
||||
try {
|
||||
const $list = await createListOfFiles(path, arr[i+1]);
|
||||
const $list = await createListOfFiles(path, arr[i+1], fullpath);
|
||||
const $anchor = i === 0 ?
|
||||
$tree :
|
||||
qs($tree, `[data-path="${chunk.toString(i)}"]`);
|
||||
|
|
@ -117,9 +118,28 @@ export default async function ctrlSidebar(render) {
|
|||
if (checkVisible($active) === false) {
|
||||
$active.scrollIntoView({ behavior: "smooth" });
|
||||
}
|
||||
|
||||
// feature: quick search
|
||||
effect(rxjs.fromEvent(qs($page, "h3 input"), "keydown").pipe(
|
||||
rxjs.debounceTime(200),
|
||||
rxjs.tap((e) => {
|
||||
const inputValue = e.target.value.toLowerCase();
|
||||
qsa($page, "li a").forEach(($li) => {
|
||||
if (inputValue === "") {
|
||||
$li.classList.remove("hidden");
|
||||
$page.classList.remove("search");
|
||||
return;
|
||||
}
|
||||
$page.classList.add("search");
|
||||
qs($li, "div").textContent.toLowerCase().indexOf(inputValue) === -1 ?
|
||||
$li.classList.add("hidden") :
|
||||
$li.classList.remove("hidden");
|
||||
})
|
||||
}),
|
||||
));
|
||||
}
|
||||
|
||||
async function createListOfFiles(path, currentName) {
|
||||
async function createListOfFiles(path, currentName, fullpath) {
|
||||
const r = await cache().get(path);
|
||||
const whats = r === null ? (currentName ? [currentName] : []) : r.files
|
||||
.filter(({ type, name }) => type === "directory" && name[0] !== ".")
|
||||
|
|
@ -127,16 +147,22 @@ async function createListOfFiles(path, currentName) {
|
|||
.sort();
|
||||
const $ul = document.createElement("ul");
|
||||
for (let i=0; i<whats.length; i++) {
|
||||
const currpath = path + whats[i] + "/";
|
||||
const $li = createElement(`
|
||||
<li data-path="${path + whats[i] + "/"}" title="${path + whats[i] + "/"}">
|
||||
<a data-link href="${toHref("/files" + path) + whats[i] + "/"}">
|
||||
<img class="component_icon" draggable="false" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgYXJpYS1oaWRkZW49InRydWUiCiAgIGZvY3VzYWJsZT0iZmFsc2UiCiAgIGNsYXNzPSJvY3RpY29uIG9jdGljb24tZmlsZS1kaXJlY3RvcnktZmlsbCIKICAgdmlld0JveD0iMCAwIDE2IDE2IgogICB3aWR0aD0iMTYiCiAgIGhlaWdodD0iMTYiCiAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgdXNlci1zZWxlY3Q6IG5vbmU7IHZlcnRpY2FsLWFsaWduOiB0ZXh0LWJvdHRvbTsgb3ZlcmZsb3c6IHZpc2libGU7IgogICB2ZXJzaW9uPSIxLjEiCiAgIGlkPSJzdmcxNTgiCiAgIHNvZGlwb2RpOmRvY25hbWU9ImdpdGh1YmZvbGRlci5zdmciCiAgIGlua3NjYXBlOnZlcnNpb249IjEuMi4yIChiMGE4NDg2NTQxLCAyMDIyLTEyLTAxKSIKICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZGVmcwogICAgIGlkPSJkZWZzMTYyIiAvPgogIDxzb2RpcG9kaTpuYW1lZHZpZXcKICAgICBpZD0ibmFtZWR2aWV3MTYwIgogICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIKICAgICBib3JkZXJjb2xvcj0iIzAwMDAwMCIKICAgICBib3JkZXJvcGFjaXR5PSIwLjI1IgogICAgIGlua3NjYXBlOnNob3dwYWdlc2hhZG93PSIyIgogICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwLjAiCiAgICAgaW5rc2NhcGU6cGFnZWNoZWNrZXJib2FyZD0iMCIKICAgICBpbmtzY2FwZTpkZXNrY29sb3I9IiNkMWQxZDEiCiAgICAgc2hvd2dyaWQ9ImZhbHNlIgogICAgIGlua3NjYXBlOnpvb209IjcxLjYyNSIKICAgICBpbmtzY2FwZTpjeD0iNy44MTE1MTgzIgogICAgIGlua3NjYXBlOmN5PSI4IgogICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMjAzNiIKICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSIxMzk3IgogICAgIGlua3NjYXBlOndpbmRvdy14PSI3IgogICAgIGlua3NjYXBlOndpbmRvdy15PSIzNCIKICAgICBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIxIgogICAgIGlua3NjYXBlOmN1cnJlbnQtbGF5ZXI9InN2ZzE1OCIgLz4KICA8cGF0aAogICAgIGQ9Ik0xLjc1IDFBMS43NSAxLjc1IDAgMCAwIDAgMi43NXYxMC41QzAgMTQuMjE2Ljc4NCAxNSAxLjc1IDE1aDEyLjVBMS43NSAxLjc1IDAgMCAwIDE2IDEzLjI1di04LjVBMS43NSAxLjc1IDAgMCAwIDE0LjI1IDNINy41YS4yNS4yNSAwIDAgMS0uMi0uMWwtLjktMS4yQzYuMDcgMS4yNiA1LjU1IDEgNSAxSDEuNzVaIgogICAgIGlkPSJwYXRoMTU2IgogICAgIHN0eWxlPSJmaWxsOiM1NzU5NWE7ZmlsbC1vcGFjaXR5OjEiIC8+Cjwvc3ZnPgo=" alt="directory">
|
||||
<li data-path="${currpath}" title="${currpath}" class="no-select">
|
||||
<a data-link href="${toHref("/files" + currpath)}" draggable="false">
|
||||
<img class="component_icon" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgYXJpYS1oaWRkZW49InRydWUiCiAgIGZvY3VzYWJsZT0iZmFsc2UiCiAgIGNsYXNzPSJvY3RpY29uIG9jdGljb24tZmlsZS1kaXJlY3RvcnktZmlsbCIKICAgdmlld0JveD0iMCAwIDE2IDE2IgogICB3aWR0aD0iMTYiCiAgIGhlaWdodD0iMTYiCiAgIGZpbGw9ImN1cnJlbnRDb2xvciIKICAgc3R5bGU9ImRpc3BsYXk6IGlubGluZS1ibG9jazsgdXNlci1zZWxlY3Q6IG5vbmU7IHZlcnRpY2FsLWFsaWduOiB0ZXh0LWJvdHRvbTsgb3ZlcmZsb3c6IHZpc2libGU7IgogICB2ZXJzaW9uPSIxLjEiCiAgIGlkPSJzdmcxNTgiCiAgIHNvZGlwb2RpOmRvY25hbWU9ImdpdGh1YmZvbGRlci5zdmciCiAgIGlua3NjYXBlOnZlcnNpb249IjEuMi4yIChiMGE4NDg2NTQxLCAyMDIyLTEyLTAxKSIKICAgeG1sbnM6aW5rc2NhcGU9Imh0dHA6Ly93d3cuaW5rc2NhcGUub3JnL25hbWVzcGFjZXMvaW5rc2NhcGUiCiAgIHhtbG5zOnNvZGlwb2RpPSJodHRwOi8vc29kaXBvZGkuc291cmNlZm9yZ2UubmV0L0RURC9zb2RpcG9kaS0wLmR0ZCIKICAgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIgogICB4bWxuczpzdmc9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZGVmcwogICAgIGlkPSJkZWZzMTYyIiAvPgogIDxzb2RpcG9kaTpuYW1lZHZpZXcKICAgICBpZD0ibmFtZWR2aWV3MTYwIgogICAgIHBhZ2Vjb2xvcj0iI2ZmZmZmZiIKICAgICBib3JkZXJjb2xvcj0iIzAwMDAwMCIKICAgICBib3JkZXJvcGFjaXR5PSIwLjI1IgogICAgIGlua3NjYXBlOnNob3dwYWdlc2hhZG93PSIyIgogICAgIGlua3NjYXBlOnBhZ2VvcGFjaXR5PSIwLjAiCiAgICAgaW5rc2NhcGU6cGFnZWNoZWNrZXJib2FyZD0iMCIKICAgICBpbmtzY2FwZTpkZXNrY29sb3I9IiNkMWQxZDEiCiAgICAgc2hvd2dyaWQ9ImZhbHNlIgogICAgIGlua3NjYXBlOnpvb209IjcxLjYyNSIKICAgICBpbmtzY2FwZTpjeD0iNy44MTE1MTgzIgogICAgIGlua3NjYXBlOmN5PSI4IgogICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMjAzNiIKICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSIxMzk3IgogICAgIGlua3NjYXBlOndpbmRvdy14PSI3IgogICAgIGlua3NjYXBlOndpbmRvdy15PSIzNCIKICAgICBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIxIgogICAgIGlua3NjYXBlOmN1cnJlbnQtbGF5ZXI9InN2ZzE1OCIgLz4KICA8cGF0aAogICAgIGQ9Ik0xLjc1IDFBMS43NSAxLjc1IDAgMCAwIDAgMi43NXYxMC41QzAgMTQuMjE2Ljc4NCAxNSAxLjc1IDE1aDEyLjVBMS43NSAxLjc1IDAgMCAwIDE2IDEzLjI1di04LjVBMS43NSAxLjc1IDAgMCAwIDE0LjI1IDNINy41YS4yNS4yNSAwIDAgMS0uMi0uMWwtLjktMS4yQzYuMDcgMS4yNiA1LjU1IDEgNSAxSDEuNzVaIgogICAgIGlkPSJwYXRoMTU2IgogICAgIHN0eWxlPSJmaWxsOiM1NzU5NWE7ZmlsbC1vcGFjaXR5OjEiIC8+Cjwvc3ZnPgo=" alt="directory">
|
||||
<div>${whats[i]}</div>
|
||||
</a>
|
||||
</li>
|
||||
`);
|
||||
$ul.appendChild($li);
|
||||
const $link = qs($li, "a");
|
||||
if ($li.getAttribute("data-path") === fullpath) {
|
||||
$link.removeAttribute("href", "");
|
||||
$link.removeAttribute("data-link");
|
||||
continue;
|
||||
}
|
||||
$link.ondrop = async (e) => {
|
||||
$link.classList.remove("highlight");
|
||||
const from = e.dataTransfer.getData("path");
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { toHref } from "./skeleton/router.js";
|
||||
import rxjs, { ajax } from "./rx.js";
|
||||
import { AjaxError } from "./error.js";
|
||||
|
||||
|
|
@ -11,14 +12,20 @@ export default function(opts) {
|
|||
const result = res.xhr.responseText;
|
||||
if (opts.responseType === "json") {
|
||||
const json = JSON.parse(result);
|
||||
res.responseJSON = json;
|
||||
if (json.status !== "ok") {
|
||||
throw new AjaxError("Oups something went wrong", result);
|
||||
}
|
||||
res.responseJSON = json;
|
||||
}
|
||||
return res;
|
||||
}),
|
||||
rxjs.catchError((err) => rxjs.throwError(processError(err.xhr, err))),
|
||||
rxjs.catchError((err) => {
|
||||
if (err.status === 401) {
|
||||
location.href = toHref("/login?next=" + location.pathname + location.hash + location.search);
|
||||
return rxjs.EMPTY;
|
||||
}
|
||||
return rxjs.throwError(processError(err.xhr, err))
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -326,14 +326,13 @@ function createLink(file, currentPath) {
|
|||
}
|
||||
|
||||
function gridSize(size, windowSize) {
|
||||
const DESIRED_FILE_WIDTH_ON_LARGE_SCREEN = 225;
|
||||
console.log("GS", size, windowSize)
|
||||
const DESIRED_FILE_WIDTH_ON_LARGE_SCREEN = 210;
|
||||
if (windowSize > 1100) return Math.max(
|
||||
4,
|
||||
Math.floor(size / DESIRED_FILE_WIDTH_ON_LARGE_SCREEN),
|
||||
);
|
||||
else if (size > 750) return 4;
|
||||
else if (size > 550) return 3;
|
||||
else if (size > 520) return 3;
|
||||
else if (size > 300) return 2;
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -149,6 +149,9 @@
|
|||
.component_supercheckbox > label {
|
||||
font-size: 0.95em;
|
||||
font-style: italic;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.component_supercheckbox > label .label {
|
||||
margin-left: -5px;
|
||||
|
|
|
|||
|
|
@ -76,6 +76,9 @@
|
|||
padding: 2px;
|
||||
border-radius: 50px;
|
||||
}
|
||||
.touch-yes .component_thing .component_checkbox {
|
||||
opacity: 1;
|
||||
}
|
||||
.component_thing .component_checkbox .indicator {
|
||||
top: 7px;
|
||||
left: 6px;
|
||||
|
|
@ -237,6 +240,9 @@
|
|||
left: 3px;
|
||||
transform: translateX(-5px);
|
||||
}
|
||||
.touch-yes .list > .component_thing.view-grid .component_checkbox {
|
||||
transform: translateX(0px);
|
||||
}
|
||||
.list > .component_thing.view-grid:hover .component_checkbox,
|
||||
.list > .component_thing.view-grid.selected .component_checkbox {
|
||||
transform: translateX(0px);
|
||||
|
|
|
|||
|
|
@ -276,6 +276,9 @@ pre.CodeMirror-line {
|
|||
.cm-s-default .cm-quote {
|
||||
color: var(--dark);
|
||||
}
|
||||
.cm-s-default .cm-invalidchar {
|
||||
color: var(--error);
|
||||
}
|
||||
|
||||
.CodeMirror-gutters {
|
||||
box-shadow: 0px 0px 2px rgba(0, 0, 0, 0.1);
|
||||
|
|
|
|||
|
|
@ -49,15 +49,13 @@ export default async function(render, { acl$ }) {
|
|||
acl$,
|
||||
).pipe(
|
||||
rxjs.mergeMap(([content, acl]) => {
|
||||
if (content === null || has_binary(content)) {
|
||||
return rxjs.from(initDownloader()).pipe(
|
||||
removeLoader,
|
||||
rxjs.mergeMap(() => {
|
||||
ctrlDownloader(render);
|
||||
return rxjs.EMPTY;
|
||||
}),
|
||||
);
|
||||
}
|
||||
if (content === null || has_binary(content)) return rxjs.from(initDownloader()).pipe(
|
||||
removeLoader,
|
||||
rxjs.mergeMap(() => {
|
||||
ctrlDownloader(render);
|
||||
return rxjs.EMPTY;
|
||||
}),
|
||||
);
|
||||
return rxjs.of(content).pipe(
|
||||
rxjs.mergeMap((content) => rxjs.of(window.CONFIG).pipe(
|
||||
rxjs.mergeMap((config) => rxjs.from(loadKeybinding(config.editor)).pipe(rxjs.mapTo(config))),
|
||||
|
|
@ -233,8 +231,14 @@ function loadMode(ext) {
|
|||
else if (ext === "less" || ext === "scss" || ext === "sass") mode = "sass";
|
||||
else if (ext === "js" || ext === "json") mode = "javascript";
|
||||
else if (ext === "jsx") mode = "jsx";
|
||||
else if (ext === "php" || ext === "php5" || ext === "php4") mode = "php";
|
||||
else if (ext === "elm") mode = "elm";
|
||||
else if (ext === "php" || ext === "php5" || ext === "php4") {
|
||||
mode = "php";
|
||||
before = Promise.all([
|
||||
loadJS(import.meta.url, "../../lib/vendor/codemirror/mode/xml/xml.js"),
|
||||
loadJS(import.meta.url, "../../lib/vendor/codemirror/mode/javascript/javascript.js"),
|
||||
loadJS(import.meta.url, "../../lib/vendor/codemirror/mode/css/css.js"),
|
||||
]);
|
||||
} else if (ext === "elm") mode = "elm";
|
||||
else if (ext === "erl") mode = "erlang";
|
||||
else if (ext === "go") mode = "go";
|
||||
else if (ext === "markdown" || ext === "md") {
|
||||
|
|
|
|||
|
|
@ -2,9 +2,10 @@ import { createElement } from "../../lib/skeleton/index.js";
|
|||
import rxjs, { effect } from "../../lib/rx.js";
|
||||
import { animate, slideYIn } from "../../lib/animate.js";
|
||||
import { loadCSS, loadJS } from "../../helpers/loader.js";
|
||||
import { qs } from "../../lib/dom.js";
|
||||
import { qs, qsa } from "../../lib/dom.js";
|
||||
import { settings_get, settings_put } from "../../lib/settings.js";
|
||||
import assert from "../../lib/assert.js";
|
||||
import { ApplicationError } from "../../lib/error.js";
|
||||
|
||||
import Hls from "../../lib/vendor/hlsjs/hls.js";
|
||||
|
||||
|
|
@ -13,7 +14,7 @@ import ctrlError from "../ctrl_error.js";
|
|||
import { transition, getFilename, getDownloadUrl } from "./common.js";
|
||||
import { formatTimecode } from "./common_player.js";
|
||||
import { ICON } from "./common_icon.js";
|
||||
import { renderMenubar, buttonDownload } from "./component_menubar.js";
|
||||
import { renderMenubar, buttonDownload, buttonFullscreen } from "./component_menubar.js";
|
||||
|
||||
import "../../components/icon.js";
|
||||
|
||||
|
|
@ -22,10 +23,6 @@ const STATUS_PAUSED = "PAUSED";
|
|||
const STATUS_BUFFERING = "BUFFERING";
|
||||
|
||||
export default function(render, { mime }) {
|
||||
if (!Hls.isSupported()) {
|
||||
ctrlError()(new Error("browser not supporting hls"));
|
||||
return;
|
||||
}
|
||||
const $page = createElement(`
|
||||
<div class="component_videoplayer">
|
||||
<component-menubar></component-menubar>
|
||||
|
|
@ -65,7 +62,7 @@ export default function(render, { mime }) {
|
|||
</div>
|
||||
</span>
|
||||
|
||||
<div class="component_pager">
|
||||
<div class="component_pager hidden">
|
||||
<div class="wrapper no-select">
|
||||
<span>
|
||||
<a href="/view/Videos/Animation Movie.webm">
|
||||
|
|
@ -88,7 +85,11 @@ export default function(render, { mime }) {
|
|||
</div>
|
||||
`);
|
||||
render($page);
|
||||
renderMenubar(qs($page, "component-menubar"), buttonDownload(getFilename(), getDownloadUrl()));
|
||||
renderMenubar(
|
||||
qs($page, "component-menubar"),
|
||||
buttonDownload(getFilename(), getDownloadUrl()),
|
||||
buttonFullscreen(qs($page, "video")),
|
||||
);
|
||||
transition(qs($page, ".video_container"));
|
||||
|
||||
const $video = qs($page, "video");
|
||||
|
|
@ -155,21 +156,31 @@ export default function(render, { mime }) {
|
|||
|
||||
// feature1: setup the dom
|
||||
const setup$ = rxjs.of(null).pipe(
|
||||
rxjs.tap(() => {
|
||||
rxjs.map(() => {
|
||||
const hls = new Hls();
|
||||
const sources = window.overrides["video-map-sources"]([{
|
||||
src: getDownloadUrl(),
|
||||
type: mime,
|
||||
}]);
|
||||
for (let i=0; i<sources.length; i++) {
|
||||
if (sources[i].type !== "application/x-mpegURL") {
|
||||
const $source = document.createElement("source");
|
||||
$source.setAttribute("type", "video/mp4");
|
||||
$source.setAttribute("src", sources[i].src);
|
||||
$video.appendChild($source);
|
||||
return [{ ...sources[i], type: "video/mp4" }];
|
||||
}
|
||||
hls.loadSource(sources[i].src, sources[i].type);
|
||||
}
|
||||
hls.attachMedia($video);
|
||||
return sources;
|
||||
}),
|
||||
rxjs.mergeMap(() => rxjs.fromEvent($video, "loadeddata")),
|
||||
// rxjs.tap(() => renderMenubar(buildMenubar(
|
||||
// menubarDownload(),
|
||||
// ))),
|
||||
rxjs.mergeMap((sources) => rxjs.merge(
|
||||
rxjs.fromEvent($video, "loadeddata"),
|
||||
...[...qsa($page, "source")].map(($source) => rxjs.fromEvent($source, "error").pipe(rxjs.tap((err) => {
|
||||
throw new ApplicationError("NOT_SUPPORTED", JSON.stringify({ mime, sources }, null, 2));
|
||||
}))),
|
||||
)),
|
||||
rxjs.mergeMap(() => {
|
||||
const $loader = qs($page, ".loader");
|
||||
$loader.replaceChildren(createElement(`<img style="height:170px;cursor:pointer;filter:brightness(0.5) invert(1);" src="${ICON.PLAY}" />`));
|
||||
|
|
@ -181,7 +192,10 @@ export default function(render, { mime }) {
|
|||
],
|
||||
});
|
||||
setSeek(0);
|
||||
return rxjs.fromEvent($loader, "click").pipe(rxjs.mapTo($loader));
|
||||
return rxjs.race(
|
||||
rxjs.fromEvent($loader, "click").pipe(rxjs.mapTo($loader)),
|
||||
rxjs.fromEvent(document, "keydown").pipe(rxjs.filter((e) => e.code === "Space"), rxjs.first()),
|
||||
).pipe(rxjs.mapTo($loader));
|
||||
}),
|
||||
rxjs.tap(($loader) => {
|
||||
$loader.classList.add("hidden");
|
||||
|
|
@ -190,6 +204,7 @@ export default function(render, { mime }) {
|
|||
animate($control, { time: 300, keyframes: slideYIn(5) });
|
||||
setStatus(STATUS_PLAYING);
|
||||
}),
|
||||
rxjs.catchError(ctrlError()),
|
||||
rxjs.share(),
|
||||
);
|
||||
effect(setup$);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
<base href="{{ .base }}">
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">
|
||||
<link rel="stylesheet" href="assets/css/designsystem.css">
|
||||
<link rel="icon" href="favicon.ico">
|
||||
<title></title>
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ int png_to_webp(int inputDesc, int outputDesc, int targetSize) {
|
|||
}
|
||||
png_init_io(png_ptr, input);
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
png_set_strip_alpha(png_ptr);
|
||||
png_uint_32 width = png_get_image_width(png_ptr, info_ptr);
|
||||
png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
|
||||
png_byte color_type = png_get_color_type(png_ptr, info_ptr);
|
||||
|
|
@ -65,6 +66,7 @@ int png_to_webp(int inputDesc, int outputDesc, int targetSize) {
|
|||
int scale_factor = height > targetSize ? height / targetSize : 1;
|
||||
png_uint_32 thumb_width = width / scale_factor;
|
||||
png_uint_32 thumb_height = height / scale_factor;
|
||||
|
||||
if (thumb_width == 0 || thumb_height == 0) {
|
||||
ERROR("0 dimensions");
|
||||
status = 1;
|
||||
|
|
|
|||
Loading…
Reference in a new issue