2022-12-21 13:55:24 +00:00
|
|
|
import {
|
|
|
|
CompletionContext,
|
|
|
|
CompletionResult,
|
|
|
|
useEffect,
|
|
|
|
useRef,
|
|
|
|
} from "../deps.ts";
|
|
|
|
import type { ComponentChildren, FunctionalComponent } from "../deps.ts";
|
2022-10-10 12:50:21 +00:00
|
|
|
import { Notification } from "../types.ts";
|
2022-12-08 16:04:07 +00:00
|
|
|
import { FeatherProps } from "https://esm.sh/v99/preact-feather@4.2.1/dist/types";
|
2022-12-21 13:55:24 +00:00
|
|
|
import { MiniEditor } from "./mini_editor.tsx";
|
2023-06-14 18:58:08 +00:00
|
|
|
import process from "https://deno.land/std@0.177.1/node/process.ts";
|
2022-03-20 08:56:28 +00:00
|
|
|
|
2022-11-18 15:04:37 +00:00
|
|
|
export type ActionButton = {
|
2022-12-08 16:04:07 +00:00
|
|
|
icon: FunctionalComponent<FeatherProps>;
|
2022-11-18 15:04:37 +00:00
|
|
|
description: string;
|
|
|
|
callback: () => void;
|
2023-06-10 14:15:16 +00:00
|
|
|
href?: string;
|
2022-11-18 15:04:37 +00:00
|
|
|
};
|
|
|
|
|
2022-03-20 08:56:28 +00:00
|
|
|
export function TopBar({
|
|
|
|
pageName,
|
2022-03-31 12:28:07 +00:00
|
|
|
unsavedChanges,
|
2023-05-23 18:53:53 +00:00
|
|
|
synced,
|
2022-09-06 14:21:33 +00:00
|
|
|
isLoading,
|
2022-03-20 08:56:28 +00:00
|
|
|
notifications,
|
2022-11-18 15:04:37 +00:00
|
|
|
onRename,
|
|
|
|
actionButtons,
|
2022-12-21 13:55:24 +00:00
|
|
|
darkMode,
|
|
|
|
vimMode,
|
2023-06-14 18:58:08 +00:00
|
|
|
progressPerc,
|
2022-12-21 13:55:24 +00:00
|
|
|
completer,
|
2022-04-04 16:33:13 +00:00
|
|
|
lhs,
|
|
|
|
rhs,
|
2022-03-20 08:56:28 +00:00
|
|
|
}: {
|
|
|
|
pageName?: string;
|
2022-03-31 12:28:07 +00:00
|
|
|
unsavedChanges: boolean;
|
2023-05-23 18:53:53 +00:00
|
|
|
synced: boolean;
|
2022-09-06 14:21:33 +00:00
|
|
|
isLoading: boolean;
|
2022-03-20 08:56:28 +00:00
|
|
|
notifications: Notification[];
|
2022-12-21 13:55:24 +00:00
|
|
|
darkMode: boolean;
|
|
|
|
vimMode: boolean;
|
2023-06-14 18:58:08 +00:00
|
|
|
progressPerc?: number;
|
2022-12-21 13:55:24 +00:00
|
|
|
onRename: (newName?: string) => Promise<void>;
|
|
|
|
completer: (context: CompletionContext) => Promise<CompletionResult | null>;
|
2022-11-18 15:04:37 +00:00
|
|
|
actionButtons: ActionButton[];
|
2022-10-10 12:50:21 +00:00
|
|
|
lhs?: ComponentChildren;
|
|
|
|
rhs?: ComponentChildren;
|
2022-03-20 08:56:28 +00:00
|
|
|
}) {
|
2022-11-18 15:04:37 +00:00
|
|
|
const inputRef = useRef<HTMLInputElement>(null);
|
2022-09-24 17:01:16 +00:00
|
|
|
|
2022-12-21 13:55:24 +00:00
|
|
|
// Another one of my less proud moments:
|
|
|
|
// Somehow I cannot seem to proerply limit the width of the page name, so I'm doing
|
|
|
|
// it this way. If you have a better way to do this, please let me know!
|
|
|
|
useEffect(() => {
|
|
|
|
function resizeHandler() {
|
2023-02-28 09:07:20 +00:00
|
|
|
const editorWidth = parseInt(
|
|
|
|
getComputedStyle(document.getElementById("sb-root")!).getPropertyValue(
|
|
|
|
"--editor-width",
|
|
|
|
),
|
|
|
|
);
|
2022-12-21 13:55:24 +00:00
|
|
|
const currentPageElement = document.getElementById("sb-current-page");
|
|
|
|
if (currentPageElement) {
|
|
|
|
// Temporarily make it very narrow to give the parent space
|
|
|
|
currentPageElement.style.width = "10px";
|
|
|
|
const innerDiv = currentPageElement.parentElement!.parentElement!;
|
|
|
|
|
|
|
|
// Then calculate a new width
|
|
|
|
currentPageElement.style.width = `${
|
2023-02-28 09:07:20 +00:00
|
|
|
Math.min(editorWidth - 150, innerDiv.clientWidth - 150)
|
2022-12-21 13:55:24 +00:00
|
|
|
}px`;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
globalThis.addEventListener("resize", resizeHandler);
|
|
|
|
|
|
|
|
// Stop listening on unmount
|
|
|
|
return () => {
|
|
|
|
globalThis.removeEventListener("resize", resizeHandler);
|
|
|
|
};
|
|
|
|
}, []);
|
|
|
|
|
2022-03-20 08:56:28 +00:00
|
|
|
return (
|
2023-05-23 18:53:53 +00:00
|
|
|
<div id="sb-top" className={synced ? undefined : "sb-sync-error"}>
|
2022-04-04 16:33:13 +00:00
|
|
|
{lhs}
|
|
|
|
<div className="main">
|
|
|
|
<div className="inner">
|
2022-12-16 10:39:46 +00:00
|
|
|
<div className="wrapper">
|
|
|
|
<span
|
2022-12-21 13:55:24 +00:00
|
|
|
id="sb-current-page"
|
|
|
|
className={isLoading
|
|
|
|
? "sb-loading"
|
|
|
|
: unsavedChanges
|
|
|
|
? "sb-unsaved"
|
|
|
|
: "sb-saved"}
|
2022-12-16 10:39:46 +00:00
|
|
|
>
|
2022-12-21 13:55:24 +00:00
|
|
|
<MiniEditor
|
|
|
|
text={pageName ?? ""}
|
|
|
|
vimMode={vimMode}
|
|
|
|
darkMode={darkMode}
|
|
|
|
onBlur={(newName) => {
|
|
|
|
if (newName !== pageName) {
|
|
|
|
return onRename(newName);
|
|
|
|
} else {
|
|
|
|
return onRename();
|
2022-12-16 10:39:46 +00:00
|
|
|
}
|
2022-12-21 13:55:24 +00:00
|
|
|
}}
|
|
|
|
completer={completer}
|
|
|
|
onEnter={(newName) => {
|
|
|
|
onRename(newName);
|
2022-12-16 10:39:46 +00:00
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</span>
|
|
|
|
{notifications.length > 0 && (
|
|
|
|
<div className="sb-notifications">
|
|
|
|
{notifications.map((notification) => (
|
|
|
|
<div
|
|
|
|
key={notification.id}
|
|
|
|
className={`sb-notification-${notification.type}`}
|
|
|
|
>
|
|
|
|
{notification.message}
|
|
|
|
</div>
|
|
|
|
))}
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
<div className="sb-actions">
|
2023-06-14 18:58:08 +00:00
|
|
|
{progressPerc !== undefined &&
|
|
|
|
(
|
|
|
|
<div className="progress-wrapper" title={`${progressPerc}%`}>
|
|
|
|
<div
|
|
|
|
className="progress-bar"
|
|
|
|
style={`background: radial-gradient(closest-side, white 79%, transparent 80% 100%), conic-gradient(#282828 ${progressPerc}%, #adadad 0);`}
|
2023-06-10 14:15:16 +00:00
|
|
|
>
|
2023-06-14 18:58:08 +00:00
|
|
|
{progressPerc}%
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
{actionButtons.map((actionButton) => {
|
|
|
|
const button = (
|
|
|
|
<button
|
|
|
|
onClick={(e) => {
|
|
|
|
e.preventDefault();
|
|
|
|
actionButton.callback();
|
|
|
|
e.stopPropagation();
|
|
|
|
}}
|
|
|
|
title={actionButton.description}
|
|
|
|
>
|
|
|
|
<actionButton.icon size={18} />
|
|
|
|
</button>
|
|
|
|
);
|
2023-06-10 14:15:16 +00:00
|
|
|
|
2023-06-14 18:58:08 +00:00
|
|
|
return actionButton.href !== undefined
|
|
|
|
? <a href={actionButton.href}>{button}</a>
|
|
|
|
: button;
|
2023-06-10 14:15:16 +00:00
|
|
|
})}
|
2022-04-04 16:33:13 +00:00
|
|
|
</div>
|
2022-05-06 16:55:04 +00:00
|
|
|
</div>
|
2022-04-04 16:33:13 +00:00
|
|
|
</div>
|
2022-03-20 08:56:28 +00:00
|
|
|
</div>
|
2022-04-04 16:33:13 +00:00
|
|
|
{rhs}
|
2022-03-20 08:56:28 +00:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|