web: convert more code to typescript

This commit is contained in:
Abdullah Atta
2023-07-04 22:44:55 +05:00
parent 56f6d34995
commit fb32aedd69
11 changed files with 81 additions and 109 deletions

View File

@@ -23,7 +23,16 @@ import useSlider from "./hooks/use-slider";
import useMobile from "./hooks/use-mobile";
import useTablet from "./hooks/use-tablet";
export default function MobileAppEffects({ sliderId, overlayId, setShow }) {
type MobileAppEffectsProps = {
sliderId: string;
overlayId: string;
setShow: (show: boolean) => void;
};
export default function MobileAppEffects({
sliderId,
overlayId,
setShow
}: MobileAppEffectsProps) {
const isMobile = useMobile();
const isTablet = useTablet();
const toggleSideMenu = useStore((store) => store.toggleSideMenu);
@@ -40,6 +49,7 @@ export default function MobileAppEffects({ sliderId, overlayId, setShow }) {
const percent = offset - (position / width) * offset;
const overlay = document.getElementById("overlay");
if (!overlay) return;
if (percent > 0) {
overlay.style.opacity = `${percent}%`;
overlay.style.pointerEvents = "all";
@@ -74,6 +84,7 @@ export default function MobileAppEffects({ sliderId, overlayId, setShow }) {
useEffect(() => {
if (!overlayId) return;
const overlay = document.getElementById(overlayId);
if (!overlay) return;
overlay.onclick = () => toggleSideMenu(false);
return () => {
overlay.onclick = null;

View File

@@ -20,7 +20,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import React, { useEffect } from "react";
import { useStore } from "./stores/app-store";
import { useStore as useUserStore } from "./stores/user-store";
import { useStore as useNotesStore } from "./stores/note-store";
import { useStore as useThemeStore } from "./stores/theme-store";
import { useStore as useAttachmentStore } from "./stores/attachment-store";
import { useStore as useEditorStore } from "./stores/editor-store";
@@ -47,11 +46,13 @@ import { interruptedOnboarding } from "./dialogs/onboarding-dialog";
import { hashNavigate } from "./navigation";
import { desktop } from "./common/desktop-bridge";
export default function AppEffects({ setShow }) {
type AppEffectsProps = {
setShow: (show: boolean) => void;
};
export default function AppEffects({ setShow }: AppEffectsProps) {
const refreshNavItems = useStore((store) => store.refreshNavItems);
const updateLastSynced = useStore((store) => store.updateLastSynced);
const isFocusMode = useStore((store) => store.isFocusMode);
const addReminder = useStore((store) => store.addReminder);
const initUser = useUserStore((store) => store.init);
const initStore = useStore((store) => store.init);
const initAttachments = useAttachmentStore((store) => store.init);
@@ -68,7 +69,7 @@ export default function AppEffects({ setShow }) {
function initializeApp() {
const userCheckStatusEvent = EV.subscribe(
EVENTS.userCheckStatus,
async (type) => {
async (type: string) => {
if (isUserPremium()) {
return { type, result: true };
} else {
@@ -93,7 +94,7 @@ export default function AppEffects({ setShow }) {
showUpgradeReminderDialogs();
}
await resetReminders();
setIsVaultCreated(await db.vault.exists());
setIsVaultCreated(await db.vault?.exists());
await showOnboardingDialog(interruptedOnboarding());
await showFeatureDialog("highlights");
@@ -111,23 +112,29 @@ export default function AppEffects({ setShow }) {
updateLastSynced,
refreshNavItems,
initUser,
initNotes,
addReminder,
setIsVaultCreated
]
);
useEffect(() => {
const systemTimeInvalidEvent = EV.subscribe(
EVENTS.systemTimeInvalid,
async ({ serverTime, localTime }) => {
await showInvalidSystemTimeDialog({ serverTime, localTime });
}
);
// const systemTimeInvalidEvent = EV.subscribe(
// EVENTS.systemTimeInvalid,
// async ({ serverTime, localTime }) => {
// await showInvalidSystemTimeDialog({ serverTime, localTime });
// }
// );
const attachmentsLoadingEvent = EV.subscribe(
EVENTS.attachmentsLoading,
({ type, total, current }) => {
({
type,
total,
current
}: {
type: ProcessingType;
total: number;
current: number;
}) => {
const [key, status] = getProcessingStatusFromType(type);
if (current === total) {
@@ -144,7 +151,15 @@ export default function AppEffects({ setShow }) {
const progressEvent = AppEventManager.subscribe(
AppEvents.UPDATE_ATTACHMENT_PROGRESS,
({ type, total, loaded }) => {
({
type,
total,
loaded
}: {
type: ProcessingType;
total: number;
loaded: number;
}) => {
const [key, status] = getProcessingStatusFromType(type);
if (!key) return;
@@ -167,7 +182,7 @@ export default function AppEffects({ setShow }) {
return () => {
attachmentsLoadingEvent.unsubscribe();
progressEvent.unsubscribe();
systemTimeInvalidEvent.unsubscribe();
// systemTimeInvalidEvent.unsubscribe();
};
}, []);
@@ -221,7 +236,8 @@ export default function AppEffects({ setShow }) {
return <React.Fragment />;
}
function getProcessingStatusFromType(type) {
type ProcessingType = "download" | "upload" | "encrypt";
function getProcessingStatusFromType(type: ProcessingType) {
switch (type) {
case "download":
return ["downloadingAttachments", "Downloading"];
@@ -230,6 +246,6 @@ function getProcessingStatusFromType(type) {
case "encrypt":
return ["encryptingAttachments", "Encrypting"];
default:
return undefined;
return [];
}
}

View File

@@ -24,7 +24,7 @@ import useMobile from "./hooks/use-mobile";
import useTablet from "./hooks/use-tablet";
import { LazyMotion, domAnimation } from "framer-motion";
import useDatabase from "./hooks/use-database";
import { Allotment, LayoutPriority } from "allotment";
import { Allotment, AllotmentHandle, LayoutPriority } from "allotment";
import { useStore } from "./stores/app-store";
import { Toaster } from "react-hot-toast";
import { ViewLoader } from "./components/loaders/view-loader";
@@ -38,8 +38,8 @@ import { usePersistentState } from "./hooks/use-persistent-state";
new WebExtensionRelay();
const GlobalMenuWrapper = React.lazy(() =>
import("./components/global-menu-wrapper")
const GlobalMenuWrapper = React.lazy(
() => import("./components/global-menu-wrapper")
);
const AppEffects = React.lazy(() => import("./app-effects"));
const MobileAppEffects = React.lazy(() => import("./app-effects.mobile"));
@@ -91,9 +91,25 @@ function App() {
export default App;
function SuspenseLoader({ condition, props, component: Component, fallback }) {
type SuspenseLoaderProps<TComponent extends React.JSXElementConstructor<any>> =
{
condition: boolean;
props?: React.ComponentProps<TComponent>;
component: TComponent;
fallback: JSX.Element;
};
function SuspenseLoader<TComponent extends React.JSXElementConstructor<any>>({
condition,
props,
component,
fallback
}: SuspenseLoaderProps<TComponent>) {
if (!condition) return fallback;
const Component = component as (
props: any
) => React.ReactComponentElement<any, any>;
return (
<Suspense
fallback={
@@ -105,14 +121,23 @@ function SuspenseLoader({ condition, props, component: Component, fallback }) {
);
}
function DesktopAppContents({ isAppLoaded, show, setShow }) {
type DesktopAppContentsProps = {
isAppLoaded: boolean;
show: boolean;
setShow: (show: boolean) => void;
};
function DesktopAppContents({
isAppLoaded,
show,
setShow
}: DesktopAppContentsProps) {
const isFocusMode = useStore((store) => store.isFocusMode);
const isTablet = useTablet();
const [paneSizes, setPaneSizes] = usePersistentState("paneSizes", [
isTablet ? 60 : 180,
isTablet ? 240 : 380
]);
const panesRef = useRef();
const panesRef = useRef<AllotmentHandle>(null);
const [isNarrow, setIsNarrow] = useState(paneSizes[0] <= 55);
return (
@@ -184,7 +209,7 @@ function DesktopAppContents({ isAppLoaded, show, setShow }) {
);
}
function MobileAppContents({ isAppLoaded }) {
function MobileAppContents({ isAppLoaded }: { isAppLoaded: boolean }) {
return (
<FlexScrollContainer
id="slider"

View File

@@ -648,7 +648,7 @@ export function showSettings() {
));
}
export function showOnboardingDialog(type: string) {
export function showOnboardingDialog(type?: string) {
if (!type) return;
return showDialog("OnboardingDialog", (Dialog, perform) => (
<Dialog type={type} onClose={(res: boolean) => perform(res)} />

View File

@@ -1,72 +0,0 @@
/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2023 Streetwriters (Private) Limited
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
const SINGLE_LINE_HEIGHT = 1.4;
const DEFAULT_FONT_SIZE = document.getElementById("p").clientHeight - 1;
const MAX_HEIGHTS = {
note: SINGLE_LINE_HEIGHT * 7 * DEFAULT_FONT_SIZE,
notebook: SINGLE_LINE_HEIGHT * 7 * DEFAULT_FONT_SIZE,
generic: SINGLE_LINE_HEIGHT * 4 * DEFAULT_FONT_SIZE
};
function getNoteHeight(item) {
const { notebooks, headline } = item;
let height = SINGLE_LINE_HEIGHT * 3;
//if (title.length > 35) height += SINGLE_LINE_HEIGHT;
if (headline?.length > 0) height += SINGLE_LINE_HEIGHT * 2;
else height += SINGLE_LINE_HEIGHT;
if (notebooks?.length) height += SINGLE_LINE_HEIGHT;
return height * DEFAULT_FONT_SIZE;
}
function getNotebookHeight(item) {
const { topics, description, title } = item;
// at the minimum we will have a title and the info text
let height = SINGLE_LINE_HEIGHT * 3; // 2.8 = 2 lines
if (title.length > 35) {
height += SINGLE_LINE_HEIGHT; // title has become multiline
}
if (topics.length > 0) {
height += SINGLE_LINE_HEIGHT;
}
if (description?.length > 0) {
height += SINGLE_LINE_HEIGHT * 2;
}
return height * DEFAULT_FONT_SIZE;
}
function getItemHeight(item) {
const { title } = item;
// at the minimum we will have a title and the info text
let height = SINGLE_LINE_HEIGHT * 3; // 2.8 = 2 lines
if (title.length > 30) {
height += SINGLE_LINE_HEIGHT; // title has become multiline
}
return height * DEFAULT_FONT_SIZE;
}
export { getNoteHeight, getNotebookHeight, getItemHeight, MAX_HEIGHTS };

View File

@@ -33,11 +33,6 @@ const SINGLE_LINE_HEIGHT = 1.4;
const DEFAULT_LINE_HEIGHT =
(document.getElementById("p")?.clientHeight || 16) - 1;
export const DEFAULT_ITEM_HEIGHT = SINGLE_LINE_HEIGHT * 2 * DEFAULT_LINE_HEIGHT;
// const MAX_HEIGHTS = {
// note: SINGLE_LINE_HEIGHT * 7 * DEFAULT_LINE_HEIGHT,
// notebook: SINGLE_LINE_HEIGHT * 7 * DEFAULT_LINE_HEIGHT,
// generic: SINGLE_LINE_HEIGHT * 4 * DEFAULT_LINE_HEIGHT
// };
export type Item = { id: string; type: string; title: string } & Record<
string,

View File

@@ -20,14 +20,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import { useEffect } from "react";
import { NavigationEvents } from "../navigation";
function useNavigate(routeKey, onNavigation) {
function useNavigate(routeKey: string, onNavigation: () => void) {
useEffect(() => {
onNavigation();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
function onNavigate(route) {
function onNavigate(route: { key: string }) {
if (route?.key === routeKey) {
onNavigation();
}

View File

@@ -72,9 +72,6 @@ class AnnouncementStore extends BaseStore {
};
}
/**
* @type {[import("zustand").UseStore<AnnouncementStore>, AnnouncementStore]}
*/
const [useStore, store] = createStore(AnnouncementStore);
export { useStore, store };