mobile: add support for changin sidebar + default home page

This commit is contained in:
Ammar Ahmed
2025-04-08 12:40:16 +05:00
committed by Abdullah Atta
parent b6d0d124fd
commit 552e8f50b7
16 changed files with 303 additions and 40 deletions

View File

@@ -38,7 +38,6 @@ import { fluidTabsRef } from "../../utils/global-refs";
import { Header } from "../list-items/headers/header";
import { Empty, PlaceholderData } from "./empty";
import { ListItemWrapper } from "./list-item.wrapper";
import { useSelectionStore } from "../../stores/use-selection-store";
type ListProps = {
data: VirtualizedGrouping<Item> | undefined;

View File

@@ -66,6 +66,7 @@ const COLUMN_BAR_ITEMS: ActionId[] = [
"move-notebook",
"pin",
"default-notebook",
"default-homepage",
"add-shortcut",
"reorder",
"rename-color",

View File

@@ -0,0 +1,98 @@
/*
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/>.
*/
import { strings } from "@notesnook/intl";
import { useThemeColors } from "@notesnook/theme";
import React from "react";
import { View } from "react-native";
import { eSendEvent, presentSheet } from "../../../services/event-manager";
import SettingsService from "../../../services/settings";
import { eCloseSheet } from "../../../utils/events";
import { SideMenuItem } from "../../../utils/menu-items";
import { AppFontSize } from "../../../utils/size";
import { DefaultAppStyles } from "../../../utils/styles";
import { useSideBarDraggingStore } from "../../side-menu/dragging-store";
import AppIcon from "../../ui/AppIcon";
import { Pressable } from "../../ui/pressable";
import Paragraph from "../../ui/typography/paragraph";
export const MenuItemProperties = ({ item }: { item: SideMenuItem }) => {
const { colors } = useThemeColors();
return (
<View
style={{
width: "100%",
justifyContent: "center",
alignItems: "center"
}}
>
{[
{
title: strings.setAsHomepage(),
onPress: () => {
SettingsService.setProperty("homepageV2", {
id: item.id,
type: "default"
});
eSendEvent(eCloseSheet);
},
icon: "home-outline"
},
{
title: strings.reorder(),
onPress: () => {
useSideBarDraggingStore.setState({
dragging: true
});
eSendEvent(eCloseSheet);
},
icon: "sort-ascending"
}
].map((item) => (
<Pressable
key={item.title}
style={{
paddingVertical: DefaultAppStyles.GAP_VERTICAL,
alignItems: "center",
flexDirection: "row",
justifyContent: "flex-start",
gap: DefaultAppStyles.GAP_SMALL,
borderRadius: 0,
paddingHorizontal: DefaultAppStyles.GAP
}}
onPress={() => {
item.onPress();
}}
>
<AppIcon
color={colors.secondary.icon}
name={item.icon}
size={AppFontSize.xl}
/>
<Paragraph>{item.title}</Paragraph>
</Pressable>
))}
</View>
);
};
MenuItemProperties.present = (item: SideMenuItem) => {
presentSheet({
component: <MenuItemProperties item={item} />
});
};

View File

@@ -55,6 +55,7 @@ import {
} from "./stores";
import { useSideBarDraggingStore } from "./dragging-store";
import { Button } from "../ui/button";
import SettingsService from "../../services/settings";
const renderScene = SceneMap({
home: SideMenuHome,
notebooks: SideMenuNotebooks,
@@ -65,7 +66,9 @@ const renderScene = SceneMap({
export const SideMenu = React.memo(
function SideMenu() {
const { colors } = useThemeColors();
const [index, setIndex] = React.useState(0);
const [index, setIndex] = React.useState(
SettingsService.getProperty("defaultSidebarTab")
);
const [routes] = React.useState<Route[]>([
{
key: "home",
@@ -113,7 +116,7 @@ const TabBar = (
const dragging = useSideBarDraggingStore((state) => state.dragging);
const { colors, isDark } = useThemeColors();
const groupOptions = useGroupOptions(
props.navigationState.index === 1 ? "notebook" : "tags"
props.navigationState.index === 1 ? "notebooks" : "tags"
);
const notebookSelectionEnabled = useSideMenuNotebookSelectionStore(
(state) => state.enabled
@@ -371,7 +374,7 @@ const TabBar = (
<IconButton
name={
groupOptions.sortDirection === "asc"
groupOptions?.sortDirection === "asc"
? "sort-ascending"
: "sort-descending"
}

View File

@@ -36,6 +36,7 @@ import { eSendEvent } from "../../services/event-manager";
import { eOpenPremiumDialog } from "../../utils/events";
import { useUserStore } from "../../stores/use-user-store";
import { Button } from "../ui/button";
import { MenuItemProperties } from "../sheets/menu-item-properties";
const pro = {
title: strings.getNotesnookPro(),
@@ -96,6 +97,7 @@ export function SideMenuHome() {
style={{
width: "100%"
}}
disableDefaultDrag
showsVerticalScrollIndicator={false}
renderDraggableItem={({ item, index }) => {
return (
@@ -106,7 +108,10 @@ export function SideMenuHome() {
title:
strings.routes[
item.title as keyof typeof strings.routes
]?.() || item.title
]?.() || item.title,
onLongPress: () => {
MenuItemProperties.present(item);
}
}}
testID={item.title}
index={index}

View File

@@ -64,6 +64,8 @@ import { eUpdateNoteInEditor } from "../utils/events";
import { deleteItems } from "../utils/functions";
import { convertNoteToText } from "../utils/note-to-text";
import { sleep } from "../utils/time";
import SettingsService from "../services/settings";
import { useSettingStore } from "../stores/use-setting-store";
export type ActionId =
| "select"
@@ -105,7 +107,8 @@ export type ActionId =
| "pin-to-notifications"
| "favorite"
| "remove-from-notebook"
| "trash";
| "trash"
| "default-homepage";
export type Action = {
id: ActionId;
@@ -155,6 +158,11 @@ export const useActions = ({
);
const [noteInCurrentNotebook, setNoteInCurrentNotebook] = useState(false);
const [locked, setLocked] = useState(false);
const isHomepage = useSettingStore(
(state) =>
state.settings.homepageV2?.type === item.type &&
state.settings.homepageV2?.id === item.id
);
const isPublished =
item.type === "note" && db.monographs.isPublished(item.id);
@@ -549,6 +557,31 @@ export const useActions = ({
});
}
if (
item.type === "notebook" ||
item.type === "tag" ||
item.type === "color"
) {
actions.push({
id: "default-homepage",
title: isHomepage ? strings.unsetAsHomepage() : strings.setAsHomepage(),
icon: "home-outline",
isToggle: true,
checked: isHomepage,
onPress: () => {
SettingsService.setProperty(
"homepageV2",
isHomepage
? undefined
: {
id: item.id,
type: item.type
}
);
}
});
}
if (item.type === "note") {
async function openHistory() {
presentSheet({

View File

@@ -21,12 +21,13 @@ import { db } from "../common/database";
import { eSubscribeEvent, eUnSubscribeEvent } from "../services/event-manager";
import Navigation from "../services/navigation";
import { eGroupOptionsUpdated } from "../utils/events";
import { useSettingStore } from "../stores/use-setting-store";
export function useGroupOptions(type: any) {
const appLoading = useSettingStore((state) => state.isAppLoading);
const [groupOptions, setGroupOptions] = useState(
db.settings?.getGroupOptions(type)
);
useEffect(() => {
const onUpdate = (groupType: string) => {
if (groupType !== type) return;
@@ -43,10 +44,15 @@ export function useGroupOptions(type: any) {
};
eSubscribeEvent(eGroupOptionsUpdated, onUpdate);
if (!appLoading) {
onUpdate(type);
}
return () => {
eUnSubscribeEvent(eGroupOptionsUpdated, onUpdate);
};
}, [type, groupOptions]);
}, [type, groupOptions, appLoading]);
return groupOptions;
}

View File

@@ -29,6 +29,7 @@ import useNavigationStore, {
import { useSelectionStore } from "../stores/use-selection-store";
import { useSettingStore } from "../stores/use-setting-store";
import { rootNavigatorRef } from "../utils/global-refs";
import { db } from "../common/database";
const RootStack = createNativeStackNavigator();
const AppStack = createNativeStackNavigator();
@@ -46,17 +47,97 @@ let ColoredNotes: any = null;
const AppNavigation = React.memo(
() => {
const { colors } = useThemeColors();
const homepage = SettingsService.get().homepage;
React.useEffect(() => {
setTimeout(() => {
useNavigationStore.getState().update(homepage as keyof RouteParams);
useNavigationStore.getState().setFocusedRouteId(homepage);
}, 300);
}, [homepage]);
const [home, setHome] = React.useState<{
name: string;
params: any;
}>();
const homepageV2 = SettingsService.get().homepageV2;
const loading = useSettingStore((state) => state.isAppLoading);
return (
React.useEffect(() => {
(async () => {
if (loading) return;
if (!homepageV2) {
setHome({
name: "Notes",
params: undefined
});
return;
}
switch (homepageV2.type) {
case "notebook": {
const notebook = await db.notebooks.notebook(homepageV2.id);
if (notebook) {
setHome({
name: "Notebook",
params: {
item: notebook,
id: notebook.id,
title: notebook.title
}
});
return;
}
}
case "color": {
const color = await db.colors.color(homepageV2.id);
if (color) {
setHome({
name: "ColoredNotes",
params: {
item: color,
id: color.id,
title: color.title
}
});
return;
}
break;
}
case "tag": {
const tag = await db.tags.tag(homepageV2.id);
if (tag) {
setHome({
name: "TaggedNotes",
params: {
item: tag,
id: tag.id,
title: tag.title
}
});
return;
}
break;
}
case "default":
{
setHome({
name: homepageV2.id,
params: undefined
});
}
return;
}
setHome({
name: "Notes",
params: undefined
});
})();
}, [homepageV2, loading]);
React.useEffect(() => {
useNavigationStore.getState().update(home?.name as keyof RouteParams);
useNavigationStore.getState().setFocusedRouteId(home?.params?.id || home);
}, [home]);
return !home ? null : (
<AppStack.Navigator
initialRouteName={homepage}
initialRouteName={home.name}
screenOptions={{
headerShown: false,
animation: "none",
@@ -96,6 +177,7 @@ const AppNavigation = React.memo(
TaggedNotes || require("../screens/notes/tagged").default;
return TaggedNotes;
}}
initialParams={home.name === "TaggedNotes" ? home.params : undefined}
/>
<AppStack.Screen
@@ -105,6 +187,7 @@ const AppNavigation = React.memo(
ColoredNotes || require("../screens/notes/colored").default;
return ColoredNotes;
}}
initialParams={home.name === "ColoredNotes" ? home.params : undefined}
/>
<AppStack.Screen
@@ -130,6 +213,7 @@ const AppNavigation = React.memo(
Notebook = Notebook || require("../screens/notebook").default;
return Notebook;
}}
initialParams={home.name === "Notebook" ? home.params : undefined}
/>
<AppStack.Screen

View File

@@ -31,6 +31,7 @@ import {
DateFormatPicker,
FontPicker,
HomePicker,
SidebarTabPicker,
TimeFormatPicker,
TrashIntervalPicker
} from "./picker/pickers";
@@ -67,5 +68,6 @@ export const components: { [name: string]: ReactElement } = {
<View style={{ paddingHorizontal: DefaultAppStyles.GAP }}>
<AttachmentGroupProgress groupId="offline-mode" />
</View>
)
),
"sidebar-tab-selector": <SidebarTabPicker />
};

View File

@@ -64,6 +64,25 @@ export const HomePicker = createSettingsPicker({
premium: true
});
export const SidebarTabPicker = createSettingsPicker({
getValue: () => useSettingStore.getState().settings.defaultSidebarTab,
updateValue: (item) => {
SettingsService.set({ defaultSidebarTab: item });
},
formatValue: (item) => {
const SidebarTabs = [
strings.routes.Home(),
strings.routes.Notebooks(),
strings.routes.Tags()
];
return SidebarTabs[item];
},
getItemKey: (item) => item,
options: [0, 1, 2],
compareValue: (current, item) => current === item,
premium: true
});
export const TrashIntervalPicker = createSettingsPicker({
getValue: () => db.settings.getTrashCleanupInterval(),
updateValue: (item) => {

View File

@@ -30,16 +30,12 @@ import * as RNIap from "react-native-iap";
//@ts-ignore
import { enabled } from "react-native-privacy-snapshot";
import ScreenGuardModule from "react-native-screenguard";
import { DatabaseLogger, db } from "../../common/database";
import { db } from "../../common/database";
import filesystem from "../../common/filesystem";
import { ChangePassword } from "../../components/auth/change-password";
import { presentDialog } from "../../components/dialog/functions";
import { AppLockPassword } from "../../components/dialogs/applock-password";
import {
endProgress,
startProgress,
updateProgress
} from "../../components/dialogs/progress";
import { endProgress, startProgress } from "../../components/dialogs/progress";
import { ChangeEmail } from "../../components/sheets/change-email";
import ExportNotesSheet from "../../components/sheets/export-notes";
import { Issue } from "../../components/sheets/github/issue";
@@ -64,19 +60,15 @@ import Sync from "../../services/sync";
import { useThemeStore } from "../../stores/use-theme-store";
import { useUserStore } from "../../stores/use-user-store";
import { SUBSCRIPTION_STATUS } from "../../utils/constants";
import {
eCloseSheet,
eCloseSimpleDialog,
eOpenRecoveryKeyDialog
} from "../../utils/events";
import { eCloseSheet, eOpenRecoveryKeyDialog } from "../../utils/events";
import { NotesnookModule } from "../../utils/notesnook-module";
import { sleep } from "../../utils/time";
import { MFARecoveryCodes, MFASheet } from "./2fa";
import { useDragState } from "./editor/state";
import { verifyUser, verifyUserWithApplock } from "./functions";
import { logoutUser } from "./logout";
import { SettingSection } from "./types";
import { getTimeLeft } from "./user-section";
import { logoutUser } from "./logout";
export const settingsGroups: SettingSection[] = [
{
@@ -639,11 +631,11 @@ export const settingsGroups: SettingSection[] = [
description: strings.behaviorDesc(),
sections: [
{
id: "default-home",
id: "default-sidebar-view",
type: "component",
name: strings.homepage(),
description: strings.homepageDesc(),
component: "homeselector"
name: strings.defaultSidebarTab(),
description: strings.defaultSidebarTabDesc(),
component: "sidebar-tab-selector"
},
{
id: "date-format",

View File

@@ -43,6 +43,10 @@ export type Settings = {
fullBackupReminder: "never" | "weekly" | "monthly";
encryptedBackup?: boolean;
homepage?: string;
homepageV2?: {
id: string;
type: "notebook" | "tag" | "color" | "default";
};
sort?: string;
sortOrder?: string;
screenshotMode?: boolean;
@@ -93,6 +97,7 @@ export type Settings = {
offlineMode?: boolean;
lastFullBackupDate?: number;
serverUrls?: Record<HostId, string>;
defaultSidebarTab: number;
};
type DimensionsType = {
@@ -149,6 +154,7 @@ export const defaultSettings: SettingStore["settings"] = {
forcePortraitOnTablet: false,
useSystemTheme: true,
reminder: "off",
defaultSidebarTab: 0,
encryptedBackup: false,
homepage: "Notes",
sort: "default",

View File

@@ -29,6 +29,7 @@ export type SideMenuItem = {
icon: string;
onPress?: (item: SideMenuItem) => void;
onLongPress?: (item: SideMenuItem) => void;
type: string;
};
export const MenuItemsList: SideMenuItem[] = [
@@ -36,7 +37,8 @@ export const MenuItemsList: SideMenuItem[] = [
dataType: "note",
id: "Notes",
title: "Notes",
icon: "note-outline"
icon: "note-outline",
type: "side-menu-item"
},
// {
// dataType: "notebook",
@@ -48,7 +50,8 @@ export const MenuItemsList: SideMenuItem[] = [
dataType: "note",
id: "Favorites",
title: "Favorites",
icon: "star-outline"
icon: "star-outline",
type: "side-menu-item"
},
// {
// dataType: "tag",
@@ -60,7 +63,8 @@ export const MenuItemsList: SideMenuItem[] = [
dataType: "reminder",
id: "Reminders",
title: "Reminders",
icon: "bell"
icon: "bell",
type: "side-menu-item"
},
{
dataType: "monograph",
@@ -70,7 +74,8 @@ export const MenuItemsList: SideMenuItem[] = [
onPress: () => {
Navigation.closeDrawer();
Monographs.navigate();
}
},
type: "side-menu-item"
},
// {
// dataType: "note",
@@ -82,6 +87,7 @@ export const MenuItemsList: SideMenuItem[] = [
dataType: "note",
id: "Trash",
title: "Trash",
icon: "delete-outline"
icon: "delete-outline",
type: "side-menu-item"
}
];

View File

@@ -4999,6 +4999,10 @@ msgstr "Reset"
msgid "Reset account password"
msgstr "Reset account password"
#: src/strings.ts:2467
msgid "Reset homepage"
msgstr "Reset homepage"
#: src/strings.ts:1806
msgid "Reset selection"
msgstr "Reset selection"

View File

@@ -4973,6 +4973,10 @@ msgstr ""
msgid "Reset account password"
msgstr ""
#: src/strings.ts:2467
msgid "Reset homepage"
msgstr ""
#: src/strings.ts:1806
msgid "Reset selection"
msgstr ""

View File

@@ -2463,5 +2463,6 @@ Use this if changes from other devices are not appearing on this device. This wi
addNotes: () => t`Add notes`,
setAsHomepage: () => t`Set as homepage`,
defaultSidebarTab: () => t`Default sidebar tab`,
defaultSidebarTabDesc: () => t`Select the default sidebar tab`
defaultSidebarTabDesc: () => t`Select the default sidebar tab`,
unsetAsHomepage: () => t`Reset homepage`
};