Skip to content

Commit

Permalink
feat: popup window
Browse files Browse the repository at this point in the history
  • Loading branch information
lideming committed Oct 31, 2023
1 parent 6c2f6fd commit efc67c2
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 63 deletions.
20 changes: 15 additions & 5 deletions src/Infra/Router.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// file: Router.ts

import { ui } from "./UI";
import { Callbacks } from "./utils";
import { Callbacks, MenuItem } from "./utils";
import { ContentView, SidebarItem } from "./ui-views";

export interface Route {
Expand Down Expand Up @@ -38,14 +38,16 @@ export const router = new (class {
}
addRoute(arg: Route) {
this.routes.push(arg);
if (arg.sidebarItem)
if (arg.sidebarItem) {
arg.sidebarItem().onActive.add(() => {
if (arg.contentView && arg.contentView().isVisible) {
arg.contentView().onSidebarItemReactived();
return;
}
this.nav([...arg.path]);
});
arg.sidebarItem().routerPath = arg.path;
}
}
nav(
path: string | string[],
Expand All @@ -54,7 +56,7 @@ export const router = new (class {
evenIsCurrent?: boolean;
idx?: number;
popup?: boolean;
}
},
) {
const popup = options?.popup ?? false;
if (typeof path === "string") path = parsePath(path);
Expand Down Expand Up @@ -84,8 +86,16 @@ export const router = new (class {
for (const r of this.routes) {
if (match(path, r)) {
if (!popup) {
if (r.contentView) ui.content.setCurrent(r.contentView());
if (r.sidebarItem) ui.sidebarList.setActive(r.sidebarItem());
let activeSidebarItem = true;
if (r.contentView) {
const setContentResult = ui.content.setCurrent(r.contentView());
if (setContentResult === "popup") {
activeSidebarItem = false;
}
}
if (activeSidebarItem && r.sidebarItem) {
ui.sidebarList.setActive(r.sidebarItem());
}
} else {
if (r.contentView) ui.content.popup(r.contentView());
}
Expand Down
89 changes: 70 additions & 19 deletions src/Infra/UI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { BottomBar } from "./BottomBar";
View.debugging = true;

views.SidebarItem.prototype.bindContentView = function (
viewFunc: Func<views.ContentView>
viewFunc: Func<views.ContentView>,
) {
this.onActive.add(() => {
if (!this.contentView) this.contentView = viewFunc();
Expand Down Expand Up @@ -59,6 +59,7 @@ import {
InputStateTracker,
Toast,
ToolTip,
Action,
} from "./utils";
import { I18n, i18n, I } from "../I18n/I18n";
import { Track } from "../Track/Track";
Expand All @@ -74,6 +75,7 @@ export const ui = new (class {
this.addErrorListener();
this.lang.init();
this.sidebar.init();
this.content.init();
this.contentBg.init();
bottomBar.bindPlayer(playerCore);
this.sidebarLogin.init();
Expand Down Expand Up @@ -102,7 +104,7 @@ export const ui = new (class {
.addText(
files.length === 1
? I`Did you mean to upload 1 file?`
: I`Did you mean to upload ${files.length} files?`
: I`Did you mean to upload ${files.length} files?`,
)
.addResultBtns(["no", "yes"])
.allowCloseWithResult("no")
Expand All @@ -124,7 +126,7 @@ export const ui = new (class {
this.usingKeyboardInput = true;
document.body.classList.add("keyboard-input");
},
true
true,
);
["mousedown", "touchstart"].forEach((evt) =>
document.addEventListener(
Expand All @@ -133,8 +135,8 @@ export const ui = new (class {
this.usingKeyboardInput = false;
document.body.classList.remove("keyboard-input");
},
{ passive: true, capture: true }
)
{ passive: true, capture: true },
),
);
}
addErrorListener() {
Expand All @@ -159,13 +161,13 @@ export const ui = new (class {
all = ["light", "dark", "dark-rounded", "light-rounded"] as const;
current: this["all"][number] = "light";
timer = new Timer(() =>
toggleClass(document.body, "changing-theme", false)
toggleClass(document.body, "changing-theme", false),
);
private rendered = false;
siTheme = new SettingItem<this["current"]>(
"mcloud-theme",
"str",
"light-rounded"
"light-rounded",
).render((theme) => {
if (this.current !== theme) {
this.current = theme;
Expand All @@ -174,7 +176,7 @@ export const ui = new (class {
toggleClass(document.body, "dark", color === "dark");
toggleClass(document.body, "rounded", rounded === "rounded");
var meta = document.getElementById(
"meta-theme-color"
"meta-theme-color",
) as HTMLMetaElement;
if (meta) {
meta.content = color === "dark" ? "black" : "";
Expand All @@ -200,7 +202,7 @@ export const ui = new (class {
i18n.curLang = lang;
document.body.lang = lang;
console.info(
`[UI] Current language: '${i18n.curLang}' - '${I`English`}'`
`[UI] Current language: '${i18n.curLang}' - '${I`English`}'`,
);
ui.updateAllViews();
});
Expand Down Expand Up @@ -327,7 +329,7 @@ export const ui = new (class {
this.toggleHide(
mobile
? this._hideMobile || this._hideLarge
: this._hideLarge && this._hideMobile
: this._hideLarge && this._hideMobile,
);
}
}
Expand Down Expand Up @@ -422,6 +424,18 @@ export const ui = new (class {
})();
content = new (class {
container = mainContainer.contentOuter;
popups: Array<{
window: Window;
container: View;
content: views.ContentView;
}> = [];

init() {
window.addEventListener("unload", (e) => {
this.popups.forEach((x) => x.window.close());
});
}

current: views.ContentView | null = null;
removeCurrent() {
const cur = this.current;
Expand All @@ -431,6 +445,7 @@ export const ui = new (class {
}
setCurrent(view: views.ContentView | null) {
if (view === this.current) return;
if (view && this.tryFocusExistingPopup(view)) return 'popup';
this.container.toggleClass("content-animation-reverse", router.wasBacked);
this.removeCurrent();
if (view) {
Expand All @@ -444,24 +459,60 @@ export const ui = new (class {
this.current = view;
}

tryFocusExistingPopup(view: views.ContentView) {
const existed = this.popups.find(
(x) => x.content === view && !x.window.closed,
);
if (existed) {
existed.window.focus();
return true;
}
return false;
}

async popup(view: views.ContentView) {
if (this.tryFocusExistingPopup(view)) return;
if (view === this.current) {
this.removeCurrent();
}
const win = await this.createPopupWindow();
view.onShow();
mountView(win.document.body, view);
win.container.appendView(view);
win.content = view;
win.window.document.title = `${view.contentViewTitle} - MusicCloud`;
view.onDomInserted();
view.fadeIn();
}

private _nextPopupId = 1;
private async createPopupWindow() {
console.info("create popup");
const win = window.open("about:blank", undefined, "width=600,height=400");
return new Promise<Window>((r) => {
win?.addEventListener("load", () => {
injectStyle({ parent: win!.document.head });
r(win);
// prevents cross-origin to "about:blank"
const popupid = this._nextPopupId++;
const url = URL.createObjectURL(
new Blob([`<!DOCTYPE html>`], { type: "text/html" }),
);
const win = window.open(
url,
"popup-" + popupid,
"popup,toolbar=no,location=no,status=no,menubar=no",
);
return new Promise<(typeof this.popups)[0]>((r) => {
if (!win) return console.warn("window.open() return null");
win.addEventListener("DOMContentLoaded", () => {
injectStyle({ parent: win.document.head });
const container = new View({ tag: "div.popup-container" });
mountView(win.document.body, container);
(win as any).mcloudDialogParent = new DialogParent(container);
const popup = { window: win, container, content: null! };
this.popups.push(popup);

win.addEventListener("unload", () => {
const content = popup.content as views.ContentView;
content.fadeOut();
});

r(popup);
});
});
}
Expand All @@ -484,11 +535,11 @@ export const ui = new (class {
playerCore.onStateChanged.add(() => {
this.bgView!.toggleClass(
"has-video",
playerCore.track?.infoObj?.type === "video"
playerCore.track?.infoObj?.type === "video",
);
});
api.onTrackInfoChanged.add(
(t) => t.id === playerCore.track?.id && this.update()
(t) => t.id === playerCore.track?.id && this.update(),
);
}

Expand Down Expand Up @@ -636,7 +687,7 @@ class TouchPanListener {
filter: (e: TouchEvent) => boolean;
constructor(
readonly element: HTMLElement,
public mode: "x" | "y" | "both" = "both"
public mode: "x" | "y" | "both" = "both",
) {}

private _enabled = false;
Expand Down
37 changes: 32 additions & 5 deletions src/Infra/ui-views.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ import { I } from "../I18n/I18n";
import svgSettings from "../../resources/settings-24px.svg";
import { settingsUI } from "../Settings/SettingsUI";
import { ui } from "./UI";
import { fadeout, FadeoutResult } from "@yuuza/webfx";
import { ContextMenu, fadeout, FadeoutResult } from "@yuuza/webfx";
import { router } from "./Router";

export class MainContainer extends View {
sidebar = new Sidebar();
Expand All @@ -50,7 +51,7 @@ export class Sidebar extends View {
{new View(<div style="flex: 1"></div>)}
<SettingsBtn />
</div>
)
),
);
features = new ListView(<div id="sidebar-features"></div>);
list = new View(<div id="sidebar-list"></div>);
Expand Down Expand Up @@ -85,6 +86,28 @@ export class SidebarItem extends ListViewItem {
text: () => getFuncVal(this.text),
};
}
routerPath: string[] | null = null;
getRouterMenuItems() {
return this.routerPath
? [
new MenuItem({
text: "Open popup",
onActive: () => {
router.nav([...this.routerPath!], { popup: true });
},
}),
]
: [];
}
getMenuItems(): MenuItem[] {
return [...this.getRouterMenuItems()];
}
onContextMenu = (item, ev) => {
ev.preventDefault();
ui.showContextMenuForItem([this], new ContextMenu(this.getMenuItems()), {
ev: ev,
});
};
bindContentView(viewFunc: Func<ContentView>) {
// implement in UI.ts
return this;
Expand Down Expand Up @@ -113,6 +136,10 @@ export class ContentView extends View {
return this._isVisible;
}

get contentViewTitle() {
return "";
}

_lastRenderedLanguage = "";

postCreateDom() {
Expand Down Expand Up @@ -198,7 +225,7 @@ export class ContentHeader extends View {
if (this.scrollbox) {
this.scrollbox.removeEventListener(
"scroll",
this.scrollboxScrollHandler!
this.scrollboxScrollHandler!,
);
this.scrollboxScrollHandler = null;
}
Expand All @@ -210,7 +237,7 @@ export class ContentHeader extends View {
this.onScrollboxScroll();
}
}),
{ passive: true }
{ passive: true },
);
}
onScrollboxScroll() {
Expand Down Expand Up @@ -270,7 +297,7 @@ export function setScrollableShadow(dom: HTMLElement, position: number) {
dom.style.boxShadow = `0 0 ${numLimit(
Math.log(position) * 2,
0,
10
10,
)}px var(--color-light-shadow)`;
}

Expand Down
Loading

0 comments on commit efc67c2

Please sign in to comment.