chore (rewrite): prepare initial release

This commit is contained in:
MickaelK 2024-07-15 21:41:23 +10:00
parent 0e8eb0d820
commit e854211d7f
15 changed files with 137 additions and 48 deletions

View file

@ -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"/>

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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");

View file

@ -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))
}),
);
}

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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") {

View file

@ -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$);

View file

@ -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>

View file

@ -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;