mirror of
https://github.com/mickael-kerjean/filestash.git
synced 2025-11-02 03:54:59 +08:00
chore (rewrite): get config at page init
This commit is contained in:
@ -3,27 +3,27 @@ import { toHref } from "../lib/skeleton/router.js";
|
||||
// import { setup_cache } from "../helpers/cache.js";
|
||||
import { init as setup_loader, loadJS } from "../helpers/loader.js";
|
||||
import { init as setup_translation } from "../locales/index.js";
|
||||
import { init as setup_config } from "../model/config.js";
|
||||
import { init as setup_chromecast } from "../model/chromecast.js";
|
||||
import { report } from "../helpers/log.js";
|
||||
|
||||
export default async function main() {
|
||||
try {
|
||||
let config = {};
|
||||
// await Config.refresh()
|
||||
|
||||
await Promise.all([ // procedure with no outside dependencies
|
||||
setup_config(),
|
||||
setup_translation(),
|
||||
setup_xdg_open(),
|
||||
// setup_cache(), // TODO: dependency on session
|
||||
setup_device(),
|
||||
// setup_sw(), // TODO
|
||||
setup_sw(),
|
||||
setup_blue_death_screen(),
|
||||
setup_loader(),
|
||||
setup_history(),
|
||||
]);
|
||||
|
||||
await Promise.all([ // procedure with dependency on config
|
||||
// setup_chromecast() // TODO
|
||||
setup_base(config),
|
||||
setup_chromecast(),
|
||||
setup_title(),
|
||||
]);
|
||||
|
||||
window.dispatchEvent(new window.Event("pagechange"));
|
||||
@ -72,30 +72,23 @@ async function setup_device() {
|
||||
});
|
||||
}
|
||||
|
||||
async function setup_base(config) {
|
||||
// TODO: base as config in admin
|
||||
const $meta = document.createElement("base");
|
||||
$meta.setAttribute("href", location.origin);
|
||||
document.head.appendChild($meta);
|
||||
async function setup_sw() {
|
||||
if (!("serviceWorker" in window.navigator)) return;
|
||||
|
||||
if (window.navigator.userAgent.indexOf("Mozilla/") !== -1 &&
|
||||
window.navigator.userAgent.indexOf("Firefox/") !== -1 &&
|
||||
window.navigator.userAgent.indexOf("Gecko/") !== -1) {
|
||||
// Firefox was acting weird with service worker so we disabled it
|
||||
// see: https://github.com/mickael-kerjean/filestash/issues/255
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// await window.navigator.serviceWorker.register("/sw_cache.js");
|
||||
} catch (err) {
|
||||
report("ServiceWorker registration failed", err);
|
||||
}
|
||||
}
|
||||
|
||||
// async function setup_sw() {
|
||||
// if (!("serviceWorker" in window.navigator)) return;
|
||||
|
||||
// if (window.navigator.userAgent.indexOf("Mozilla/") !== -1 &&
|
||||
// window.navigator.userAgent.indexOf("Firefox/") !== -1 &&
|
||||
// window.navigator.userAgent.indexOf("Gecko/") !== -1) {
|
||||
// // Firefox was acting weird with service worker so we disabled it
|
||||
// // see: https://github.com/mickael-kerjean/filestash/issues/255
|
||||
// return;
|
||||
// }
|
||||
// try {
|
||||
// await window.navigator.serviceWorker.register("/sw_cache.js");
|
||||
// } catch (err) {
|
||||
// report("ServiceWorker registration failed", err);
|
||||
// }
|
||||
// }
|
||||
|
||||
async function setup_blue_death_screen() {
|
||||
window.onerror = function(msg, url, lineNo, colNo, error) {
|
||||
report(msg, error, url, lineNo, colNo);
|
||||
@ -117,3 +110,7 @@ async function setup_blue_death_screen() {
|
||||
async function setup_history() {
|
||||
window.history.replaceState({}, "");
|
||||
}
|
||||
|
||||
async function setup_title() {
|
||||
document.title = CONFIG.name || "Filestash";
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ class ComponentBreadcrumb extends window.HTMLElement {
|
||||
|
||||
// STEP2: setup the actual content
|
||||
this.querySelector(`[data-bind="path"]`).innerHTML = pathChunks.map((chunk, idx) => {
|
||||
const label = idx === 0 ? "Filestash" : chunk;
|
||||
const label = idx === 0 ? (window.CONFIG.name || "Filestash") : chunk;
|
||||
const link = pathChunks.slice(0, idx + 1).join("/") + "/";
|
||||
const limitSize = (word, highlight = false) => {
|
||||
if (highlight === true && word.length > 30) {
|
||||
|
||||
81
public/assets/model/chromecast.js
Normal file
81
public/assets/model/chromecast.js
Normal file
@ -0,0 +1,81 @@
|
||||
export async function init() {
|
||||
if (!CONFIG.enable_chromecast) {
|
||||
return Promise.resolve();
|
||||
} else if (!("chrome" in window)) {
|
||||
return Promise.resolve();
|
||||
} else if (location.hostname === "localhost" || location.hostname === "127.0.0.1") {
|
||||
return Promise.resolve();
|
||||
}
|
||||
// return Chromecast.init();
|
||||
}
|
||||
|
||||
// import { Session } from "./session";
|
||||
// import { currentShare, objectGet } from "../helpers/";
|
||||
|
||||
// class ChromecastManager {
|
||||
// init() {
|
||||
// return new Promise((done) => {
|
||||
// const script = document.createElement("script");
|
||||
// script.src = "https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1";
|
||||
// script.onerror = () => done()
|
||||
// window["__onGCastApiAvailable"] = function(isAvailable) {
|
||||
// if (isAvailable) cast.framework.CastContext.getInstance().setOptions({
|
||||
// receiverApplicationId: chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID,
|
||||
// autoJoinPolicy: chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED,
|
||||
// });
|
||||
// done();
|
||||
// };
|
||||
// document.head.appendChild(script)
|
||||
// });
|
||||
// }
|
||||
|
||||
// origin() {
|
||||
// return location.origin;
|
||||
// };
|
||||
|
||||
// createLink(apiPath) {
|
||||
// const shareID = currentShare();
|
||||
// if (shareID) {
|
||||
// const target = new URL(this.origin() + apiPath);
|
||||
// target.searchParams.append("share", shareID);
|
||||
// return target.toString();
|
||||
// }
|
||||
// const target = new URL(this.origin() + apiPath)
|
||||
// return target.toString();
|
||||
// }
|
||||
|
||||
// createRequest(mediaInfo) {
|
||||
// let prior = Promise.resolve();
|
||||
// if (!Session.authorization) prior = Session.currentUser();
|
||||
// return prior.then(() => {
|
||||
// if (!Session.authorization) throw new Error("Invalid account");
|
||||
// // TODO: it would be much much nicer to set the authorization from an HTTP header
|
||||
// // but this would require to create a custom web receiver app, setup accounts on
|
||||
// // google, etc,... Until that happens, we're setting the authorization within the
|
||||
// // url. Once we have that app, the authorisation will come from a customData field
|
||||
// // of a chrome.cast.media.LoadRequest
|
||||
// const target = new URL(mediaInfo.contentId);
|
||||
// target.searchParams.append("authorization", Session.authorization);
|
||||
// mediaInfo.contentId = target.toString();
|
||||
// return new chrome.cast.media.LoadRequest(mediaInfo);
|
||||
// });
|
||||
// }
|
||||
|
||||
// context() {
|
||||
// if (!objectGet(window.chrome, ["cast", "isAvailable"])) {
|
||||
// return;
|
||||
// }
|
||||
// return cast.framework.CastContext.getInstance();
|
||||
// }
|
||||
// session() {
|
||||
// const context = this.context();
|
||||
// if (!context) return;
|
||||
// return context.getCurrentSession();
|
||||
// }
|
||||
// media() {
|
||||
// const session = this.session();
|
||||
// if (!session) return;
|
||||
// return session.getMediaSession();
|
||||
// }
|
||||
// }
|
||||
// export const Chromecast = new ChromecastManager();
|
||||
@ -9,6 +9,7 @@ const config$ = ajax({
|
||||
rxjs.map(({ responseJSON }) => responseJSON.result),
|
||||
);
|
||||
|
||||
export function get() {
|
||||
return config$;
|
||||
export async function init() {
|
||||
let config = await config$.toPromise();
|
||||
window.CONFIG = config;
|
||||
}
|
||||
|
||||
@ -9,7 +9,6 @@ import componentFilesystem, { init as initFilesystem } from "./filespage/ctrl_fi
|
||||
import componentSubmenu, { init as initSubmenu } from "./filespage/ctrl_submenu.js";
|
||||
import componentNewItem, { init as initNewItem } from "./filespage/ctrl_newitem.js";
|
||||
import componentUpload, { init as initUpload } from "./filespage/ctrl_upload.js";
|
||||
import { get as getConfig } from "./filespage/model_config.js";
|
||||
|
||||
import "../components/breadcrumb.js";
|
||||
|
||||
@ -44,7 +43,7 @@ export default WithShell(function(render) {
|
||||
export function init() {
|
||||
return Promise.all([
|
||||
loadCSS(import.meta.url, "ctrl_filespage.css"),
|
||||
initShell(), initFilesystem(), getConfig().toPromise(),
|
||||
initShell(), initFilesystem(),
|
||||
initSubmenu(), initNewItem(), initUpload(),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -5,11 +5,13 @@ import rxjs, { effect } from "../lib/rx.js";
|
||||
import { deleteSession } from "../model/session.js";
|
||||
import ctrlError from "./ctrl_error.js";
|
||||
import $loader from "../components/loader.js";
|
||||
import { init as setup_config } from "../model/config.js";
|
||||
|
||||
export default function(render) {
|
||||
render($loader);
|
||||
|
||||
effect(deleteSession().pipe(
|
||||
rxjs.mergeMap(setup_config),
|
||||
rxjs.tap(() => navigate(toHref("/"))),
|
||||
rxjs.catchError(ctrlError(render)),
|
||||
));
|
||||
|
||||
@ -4,7 +4,6 @@ import { ApplicationError } from "../lib/error.js";
|
||||
import { basename } from "../lib/path.js";
|
||||
import { loadCSS } from "../helpers/loader.js";
|
||||
import WithShell, { init as initShell } from "../components/decorator_shell_filemanager.js";
|
||||
import { get as getConfig } from "../model/config.js";
|
||||
|
||||
import ctrlError from "./ctrl_error.js";
|
||||
import { opener } from "./viewerpage/mimetype.js";
|
||||
@ -12,11 +11,6 @@ import { getCurrentPath } from "./viewerpage/common.js";
|
||||
|
||||
import "../components/breadcrumb.js";
|
||||
|
||||
const mime$ = getConfig().pipe(
|
||||
rxjs.map((config) => config.mime),
|
||||
rxjs.shareReplay(),
|
||||
);
|
||||
|
||||
function loadModule(appName) {
|
||||
switch (appName) {
|
||||
case "editor":
|
||||
@ -48,7 +42,7 @@ export default WithShell(async function(render) {
|
||||
const $page = createElement(`<div class="component_page_viewerpage"></div>`);
|
||||
render($page);
|
||||
|
||||
effect(mime$.pipe(
|
||||
effect(rxjs.of(CONFIG.mime || {}).pipe(
|
||||
rxjs.map((mimes) => opener(basename(getCurrentPath()), mimes)),
|
||||
rxjs.mergeMap(([opener, options]) => rxjs.from(loadModule(opener)).pipe(
|
||||
rxjs.map((module) => module.default(createRender($page), options)),
|
||||
@ -61,7 +55,7 @@ export async function init() {
|
||||
return Promise.all([
|
||||
loadCSS(import.meta.url, "./ctrl_viewerpage.css"),
|
||||
initShell(),
|
||||
mime$.pipe(
|
||||
rxjs.of(CONFIG.mime || {}).pipe(
|
||||
rxjs.map((mimes) => opener(basename(getCurrentPath()), mimes)),
|
||||
rxjs.mergeMap(([opener]) => loadModule(opener)),
|
||||
rxjs.mergeMap((module) => typeof module.init === "function"? module.init() : rxjs.EMPTY),
|
||||
|
||||
@ -13,6 +13,10 @@
|
||||
border-top-left-radius: 15px;
|
||||
border-top-right-radius: 15px;
|
||||
}
|
||||
.dark-mode .component_upload {
|
||||
color: var(--bg-color);
|
||||
}
|
||||
|
||||
.component_upload h2 {
|
||||
padding: 20px 20px 5px 20px;
|
||||
margin: 0 0 5px 0;
|
||||
@ -28,13 +32,13 @@
|
||||
}
|
||||
.component_upload h2 .count_block span.grandTotal {
|
||||
font-size: 0.8em;
|
||||
color: var(--emphasis-secondary);
|
||||
opacity: 0.8;
|
||||
}
|
||||
.component_upload h2 .count_block span.grandTotal:before {
|
||||
content: "/";
|
||||
}
|
||||
.component_upload h2 .count_block span.completed {
|
||||
color: var(--emphasis-secondary);
|
||||
opacity: 0.8;
|
||||
}
|
||||
.component_upload h2 .component_icon {
|
||||
cursor: pointer;
|
||||
@ -66,7 +70,7 @@
|
||||
color: var(--error);
|
||||
}
|
||||
.component_upload .stats_content .todo_color {
|
||||
color: var(--light);
|
||||
opacity: 0.7;
|
||||
}
|
||||
.component_upload .stats_content .file_row {
|
||||
display: flex;
|
||||
|
||||
@ -89,13 +89,15 @@ function componentFilezone(render, { workers$ }) {
|
||||
|
||||
const MAX_WORKERS = 4;
|
||||
|
||||
// TODO: calculate total
|
||||
|
||||
function componentUploadQueue(render, { workers$ }) {
|
||||
const $page = createElement(`
|
||||
<div class="component_upload hidden">
|
||||
<h2 class="no-select">${t("Current Upload")}
|
||||
<div class="count_block">
|
||||
<span class="completed">24</span>
|
||||
<span class="grandTotal">24</span>
|
||||
<span class="completed">0</span>
|
||||
<span class="grandTotal">0</span>
|
||||
</div>
|
||||
<img class="component_icon" draggable="false" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MS45NzYgNTEuOTc2Ij4KICA8cGF0aCBzdHlsZT0iZmlsbDojMDAwMDAwO2ZpbGwtb3BhY2l0eTowLjUzMzMzMjg1O3N0cm9rZS13aWR0aDoxLjQ1NjgxMTE5IiBkPSJtIDQxLjAwNTMxLDQwLjg0NDA2MiBjIC0xLjEzNzc2OCwxLjEzNzc2NSAtMi45ODIwODgsMS4xMzc3NjUgLTQuMTE5ODYxLDAgTCAyNi4wNjg2MjgsMzAuMDI3MjM0IDE0LjczNzU1MSw0MS4zNTgzMSBjIC0xLjEzNzc3MSwxLjEzNzc3MSAtMi45ODIwOTMsMS4xMzc3NzEgLTQuMTE5ODYxLDAgLTEuMTM3NzcyMiwtMS4xMzc3NjggLTEuMTM3NzcyMiwtMi45ODIwODggMCwtNC4xMTk4NjEgTCAyMS45NDg3NjYsMjUuOTA3MzcyIDExLjEzMTkzOCwxNS4wOTA1NTEgYyAtMS4xMzc3NjQ3LC0xLjEzNzc3MSAtMS4xMzc3NjQ3LC0yLjk4MzU1MyAwLC00LjExOTg2MSAxLjEzNzc3NCwtMS4xMzc3NzIxIDIuOTgyMDk4LC0xLjEzNzc3MjEgNC4xMTk4NjUsMCBMIDI2LjA2ODYyOCwyMS43ODc1MTIgMzYuMzY5NzM5LDExLjQ4NjM5OSBjIDEuMTM3NzY4LC0xLjEzNzc2OCAyLjk4MjA5MywtMS4xMzc3NjggNC4xMTk4NjIsMCAxLjEzNzc2NywxLjEzNzc2OSAxLjEzNzc2NywyLjk4MjA5NCAwLDQuMTE5ODYyIEwgMzAuMTg4NDg5LDI1LjkwNzM3MiA0MS4wMDUzMSwzNi43MjQxOTcgYyAxLjEzNzc3MSwxLjEzNzc2NyAxLjEzNzc3MSwyLjk4MjA5MSAwLDQuMTE5ODY1IHoiIC8+Cjwvc3ZnPgo=" alt="close">
|
||||
</h2>
|
||||
@ -112,13 +114,28 @@ function componentUploadQueue(render, { workers$ }) {
|
||||
<div class="file_control no-select"></div>
|
||||
</div>
|
||||
`);
|
||||
const updateTotal = {
|
||||
reset: () => {
|
||||
qs($page, ".grandTotal").innerText = 0;
|
||||
qs($page, ".completed").innerText = 0;
|
||||
},
|
||||
addToTotal: (n) => {
|
||||
const $total = qs($page, ".grandTotal");
|
||||
$total.innerText = parseInt($total.innerText) + n;
|
||||
},
|
||||
incrementCompleted: () => {
|
||||
const $completed = qs($page, ".completed");
|
||||
$completed.innerText = parseInt($completed.innerText) + 1;
|
||||
},
|
||||
};
|
||||
|
||||
// feature1: close the queue
|
||||
onClick(qs($page, `img[alt="close"]`)).pipe(
|
||||
rxjs.tap(async (cancel) => {
|
||||
const cleanup = await animate($page, { time: 200, keyframes: slideYOut(50) });
|
||||
qs($page, ".stats_content").innerHTML = "";
|
||||
$content.innerHTML = "";
|
||||
$page.classList.add("hidden");
|
||||
updateTotal.reset();
|
||||
cleanup();
|
||||
}),
|
||||
).subscribe();
|
||||
@ -126,6 +143,7 @@ function componentUploadQueue(render, { workers$ }) {
|
||||
// feature2: setup the task queue in the dom
|
||||
workers$.subscribe(({ tasks }) => {
|
||||
if (tasks.length === 0) return;
|
||||
updateTotal.addToTotal(tasks.length);
|
||||
const $fragment = document.createDocumentFragment();
|
||||
for (let i = 0; i<tasks.length; i++) {
|
||||
const $task = $file.cloneNode(true);
|
||||
@ -230,6 +248,7 @@ function componentUploadQueue(render, { workers$ }) {
|
||||
} catch(err) {
|
||||
updateDOMWithStatus($task, { exec, status: "error", nworker });
|
||||
}
|
||||
updateTotal.incrementCompleted(1);
|
||||
task.done = true;
|
||||
|
||||
if (tasks.length === 0 // no remaining tasks
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
import rxjs from "../../lib/rx.js";
|
||||
import { get as getConfig } from "../../model/config.js";
|
||||
|
||||
const config$ = getConfig().pipe(rxjs.shareReplay(1));
|
||||
|
||||
export function get() {
|
||||
return config$;
|
||||
}
|
||||
@ -1,23 +1,16 @@
|
||||
import { onDestroy } from "../../lib/skeleton/index.js";
|
||||
import rxjs, { effect, preventDefault } from "../../lib/rx.js";
|
||||
import { settingsGet, settingsSave } from "../../lib/store.js";
|
||||
import { get as getConfig } from "./model_config.js";
|
||||
|
||||
const state$ = new rxjs.BehaviorSubject(null);
|
||||
const state$ = new rxjs.BehaviorSubject(settingsGet({
|
||||
view: window.CONFIG.default_view || "grid",
|
||||
show_hidden: window.CONFIG.display_hidden || false,
|
||||
sort: window.CONFIG.default_sort || "type",
|
||||
order: null,
|
||||
search: "",
|
||||
}, "filespage"));
|
||||
|
||||
getConfig().subscribe((config) => {
|
||||
state$.next(settingsGet({
|
||||
view: config.default_view || "grid",
|
||||
show_hidden: config.display_hidden || false,
|
||||
sort: config.default_sort || "type",
|
||||
order: null,
|
||||
search: "",
|
||||
}, "filespage"));
|
||||
});
|
||||
|
||||
export const getState$ = () => state$.asObservable().pipe(
|
||||
rxjs.filter((state) => state !== null),
|
||||
);
|
||||
export const getState$ = () => state$.asObservable();
|
||||
|
||||
export const setState = (...args) => {
|
||||
const obj = { ...state$.value };
|
||||
|
||||
@ -5,7 +5,6 @@ import { animate, opacityIn } from "../../lib/animate.js";
|
||||
import assert from "../../lib/assert.js";
|
||||
|
||||
import { extractPath, isDir, isNativeFileUpload } from "./helper.js";
|
||||
import { get as getConfig } from "./model_config.js";
|
||||
import { files$ } from "./ctrl_filesystem.js";
|
||||
import { addSelection, isSelected, clearSelection } from "./state_selection.js";
|
||||
|
||||
@ -26,15 +25,15 @@ const IMAGE = {
|
||||
|
||||
|
||||
let TYPES = {
|
||||
MIME: {},
|
||||
THUMBNAILER: new Set(),
|
||||
MIME: window.CONFIG.mime,
|
||||
THUMBNAILER: (function() {
|
||||
const set = new Set();
|
||||
for (let i=0; i<window.CONFIG.thumbnailer.length; i++) {
|
||||
set.add(window.CONFIG.thumbnailer[i]);
|
||||
}
|
||||
return set;
|
||||
})(),
|
||||
};
|
||||
getConfig().subscribe((config) => {
|
||||
TYPES.MIME = config.mime;
|
||||
for (let i=0; i<config.thumbnailer.length; i++) {
|
||||
TYPES.THUMBNAILER.add(config.thumbnailer[i]);
|
||||
}
|
||||
});
|
||||
|
||||
const $tmpl = createElement(`
|
||||
<a href="__TEMPLATE__" class="component_thing no-select" draggable="false" data-link>
|
||||
|
||||
@ -7,7 +7,6 @@ import { createModal, MODAL_RIGHT_BUTTON } from "../../components/modal.js";
|
||||
import { loadCSS, loadJS } from "../../helpers/loader.js";
|
||||
import ajax from "../../lib/ajax.js";
|
||||
import { extname } from "../../lib/path.js";
|
||||
import { get as getConfig } from "../../model/config.js";
|
||||
import t from "../../locales/index.js";
|
||||
|
||||
import ctrlError from "../ctrl_error.js";
|
||||
@ -38,7 +37,6 @@ export default async function(render) {
|
||||
render($page);
|
||||
renderMenubar($dom.menubar(), buttonDownload(getFilename(), getDownloadUrl()));
|
||||
|
||||
const getConfig$ = getConfig().pipe(rxjs.shareReplay(1));
|
||||
const content$ = new rxjs.ReplaySubject(1);
|
||||
|
||||
// feature1: setup the dom
|
||||
@ -59,7 +57,7 @@ export default async function(render) {
|
||||
}
|
||||
return rxjs.of(content);
|
||||
}),
|
||||
rxjs.mergeMap((content) => getConfig$.pipe(
|
||||
rxjs.mergeMap((content) => rxjs.of(window.CONFIG).pipe(
|
||||
rxjs.mergeMap((config) => rxjs.from(loadKeybinding(config.editor)).pipe(rxjs.mapTo(config))),
|
||||
rxjs.map((config) => [content, config]),
|
||||
rxjs.mergeMap((arr) => rxjs.from(loadMode(extname(getFilename()))).pipe(
|
||||
|
||||
Reference in New Issue
Block a user