mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-21 22:19:41 +01:00
mobile: ui redesign
This commit is contained in:
committed by
Abdullah Atta
parent
8f84c85c23
commit
b315a834c2
@@ -19,20 +19,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
import { i18n } from "@lingui/core";
|
import { i18n } from "@lingui/core";
|
||||||
import { I18nProvider } from "@lingui/react";
|
import { I18nProvider } from "@lingui/react";
|
||||||
import {
|
import {
|
||||||
|
ScopedThemeProvider,
|
||||||
THEME_COMPATIBILITY_VERSION,
|
THEME_COMPATIBILITY_VERSION,
|
||||||
useThemeEngineStore
|
useThemeEngineStore
|
||||||
} from "@notesnook/theme";
|
} from "@notesnook/theme";
|
||||||
import React, { useEffect } from "react";
|
import React, { useEffect } from "react";
|
||||||
import { I18nManager, View } from "react-native";
|
import { I18nManager, StatusBar } from "react-native";
|
||||||
import "react-native-gesture-handler";
|
import "react-native-gesture-handler";
|
||||||
import { GestureHandlerRootView } from "react-native-gesture-handler";
|
import { GestureHandlerRootView } from "react-native-gesture-handler";
|
||||||
import { SafeAreaProvider } from "react-native-safe-area-context";
|
import { SafeAreaProvider } from "react-native-safe-area-context";
|
||||||
import AppLockedOverlay from "./components/app-lock-overlay";
|
import DialogProvider from "./components/dialog-provider";
|
||||||
import { withErrorBoundry } from "./components/exception-handler";
|
import { withErrorBoundry } from "./components/exception-handler";
|
||||||
import GlobalSafeAreaProvider from "./components/globalsafearea";
|
import GlobalSafeAreaProvider from "./components/globalsafearea";
|
||||||
|
import { Toast } from "./components/toast";
|
||||||
import { useAppEvents } from "./hooks/use-app-events";
|
import { useAppEvents } from "./hooks/use-app-events";
|
||||||
import { ApplicationHolder } from "./navigation";
|
|
||||||
import { NotePreviewConfigure } from "./screens/note-preview-configure";
|
import { NotePreviewConfigure } from "./screens/note-preview-configure";
|
||||||
|
import { RootNavigation } from "./navigation/navigation-stack";
|
||||||
import { themeTrpcClient } from "./screens/settings/theme-selector";
|
import { themeTrpcClient } from "./screens/settings/theme-selector";
|
||||||
import Notifications from "./services/notifications";
|
import Notifications from "./services/notifications";
|
||||||
import SettingsService from "./services/settings";
|
import SettingsService from "./services/settings";
|
||||||
@@ -64,42 +66,26 @@ const App = (props: { configureMode: "note-preview" }) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
height: "100%",
|
|
||||||
width: "100%",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
position: "absolute",
|
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
zIndex: -1
|
|
||||||
}}
|
|
||||||
pointerEvents="none"
|
|
||||||
>
|
|
||||||
<SafeAreaProvider>
|
<SafeAreaProvider>
|
||||||
<GlobalSafeAreaProvider />
|
<StatusBar translucent={true} backgroundColor="transparent" />
|
||||||
</SafeAreaProvider>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<GestureHandlerRootView
|
<GestureHandlerRootView
|
||||||
style={{
|
style={{
|
||||||
height: "100%",
|
height: "100%",
|
||||||
width: "100%"
|
width: "100%"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
<GlobalSafeAreaProvider />
|
||||||
{props.configureMode === "note-preview" ? (
|
{props.configureMode === "note-preview" ? (
|
||||||
<NotePreviewConfigure />
|
<NotePreviewConfigure />
|
||||||
) : (
|
) : (
|
||||||
<ApplicationHolder />
|
<RootNavigation />
|
||||||
)}
|
)}
|
||||||
|
<ScopedThemeProvider value="dialog">
|
||||||
|
<Toast />
|
||||||
|
</ScopedThemeProvider>
|
||||||
|
<DialogProvider />
|
||||||
</GestureHandlerRootView>
|
</GestureHandlerRootView>
|
||||||
<AppLockedOverlay />
|
</SafeAreaProvider>
|
||||||
</View>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ const verifyUserPassword = async (password: string) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const AppLockedOverlay = () => {
|
const AppLockedScreen = () => {
|
||||||
const initialLaunchBiometricRequest = useRef(true);
|
const initialLaunchBiometricRequest = useRef(true);
|
||||||
const { colors } = useThemeColors();
|
const { colors } = useThemeColors();
|
||||||
const user = getUser();
|
const user = getUser();
|
||||||
@@ -203,14 +203,12 @@ const AppLockedOverlay = () => {
|
|||||||
}
|
}
|
||||||
}, [appState, onUnlockAppRequested, appLocked]);
|
}, [appState, onUnlockAppRequested, appLocked]);
|
||||||
|
|
||||||
return appLocked ? (
|
return (
|
||||||
<KeyboardAwareScrollView
|
<KeyboardAwareScrollView
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: colors.primary.background,
|
backgroundColor: colors.primary.background,
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: "100%",
|
height: "100%"
|
||||||
position: "absolute",
|
|
||||||
zIndex: 999
|
|
||||||
}}
|
}}
|
||||||
contentContainerStyle={{
|
contentContainerStyle={{
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
@@ -333,7 +331,7 @@ const AppLockedOverlay = () => {
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</KeyboardAwareScrollView>
|
</KeyboardAwareScrollView>
|
||||||
) : null;
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default AppLockedOverlay;
|
export default AppLockedScreen;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
import { useThemeColors } from "@notesnook/theme";
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
import { useRoute } from "@react-navigation/native";
|
import { useRoute } from "@react-navigation/native";
|
||||||
import React, { useCallback, useEffect } from "react";
|
import React, { useCallback, useEffect } from "react";
|
||||||
import { Keyboard, View } from "react-native";
|
import { Keyboard, TouchableOpacity, View } from "react-native";
|
||||||
import Animated, {
|
import Animated, {
|
||||||
Easing,
|
Easing,
|
||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
@@ -34,7 +34,7 @@ import { useSelectionStore } from "../../stores/use-selection-store";
|
|||||||
import { useSettingStore } from "../../stores/use-setting-store";
|
import { useSettingStore } from "../../stores/use-setting-store";
|
||||||
import { getElevationStyle } from "../../utils/elevation";
|
import { getElevationStyle } from "../../utils/elevation";
|
||||||
import { SIZE, normalize } from "../../utils/size";
|
import { SIZE, normalize } from "../../utils/size";
|
||||||
import { Pressable } from "../ui/pressable";
|
import { DefaultAppStyles } from "../../utils/styles";
|
||||||
|
|
||||||
interface FloatingButtonProps {
|
interface FloatingButtonProps {
|
||||||
onPress: () => void;
|
onPress: () => void;
|
||||||
@@ -108,20 +108,24 @@ const FloatingButton = ({
|
|||||||
style={[
|
style={[
|
||||||
{
|
{
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
right: 12,
|
right: DefaultAppStyles.GAP,
|
||||||
bottom: 20,
|
bottom: 20,
|
||||||
zIndex: 10
|
zIndex: 10
|
||||||
},
|
},
|
||||||
animatedStyle
|
animatedStyle
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<Pressable
|
<TouchableOpacity
|
||||||
testID={notesnook.buttons.add}
|
testID={notesnook.buttons.add}
|
||||||
type="accent"
|
activeOpacity={0.95}
|
||||||
accentColor={color}
|
|
||||||
style={{
|
style={{
|
||||||
...getElevationStyle(5),
|
...getElevationStyle(10),
|
||||||
borderRadius: 100
|
borderRadius: 20,
|
||||||
|
borderTopWidth: 0,
|
||||||
|
borderBottomWidth: 0,
|
||||||
|
borderLeftWidth: 0,
|
||||||
|
borderRightWidth: 0,
|
||||||
|
backgroundColor: colors.primary.background
|
||||||
}}
|
}}
|
||||||
onPress={onPress}
|
onPress={onPress}
|
||||||
>
|
>
|
||||||
@@ -130,7 +134,9 @@ const FloatingButton = ({
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
height: normalize(60),
|
height: normalize(60),
|
||||||
width: normalize(60)
|
width: normalize(60),
|
||||||
|
backgroundColor: colors.primary.shade,
|
||||||
|
borderRadius: 20
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
@@ -141,11 +147,11 @@ const FloatingButton = ({
|
|||||||
? "delete"
|
? "delete"
|
||||||
: "plus"
|
: "plus"
|
||||||
}
|
}
|
||||||
color={colors.primary.accentForeground}
|
color={colors.primary.accent}
|
||||||
size={SIZE.xxl}
|
size={SIZE.xxxl}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</Pressable>
|
</TouchableOpacity>
|
||||||
</Animated.View>
|
</Animated.View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -46,8 +46,6 @@ const DialogButtons = ({
|
|||||||
{
|
{
|
||||||
backgroundColor: colors.secondary.background,
|
backgroundColor: colors.secondary.background,
|
||||||
height: 60,
|
height: 60,
|
||||||
borderBottomRightRadius: 5,
|
|
||||||
borderBottomLeftRadius: 5,
|
|
||||||
paddingHorizontal: 12,
|
paddingHorizontal: 12,
|
||||||
borderTopWidth: 0.7,
|
borderTopWidth: 0.7,
|
||||||
borderTopColor: getColorLinearShade(
|
borderTopColor: getColorLinearShade(
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import { Button } from "../ui/button";
|
|||||||
import { getContainerBorder } from "../../utils/colors";
|
import { getContainerBorder } from "../../utils/colors";
|
||||||
import { Notice } from "../ui/notice";
|
import { Notice } from "../ui/notice";
|
||||||
import { strings } from "@notesnook/intl";
|
import { strings } from "@notesnook/intl";
|
||||||
|
import { br } from "../../utils/size";
|
||||||
|
|
||||||
export const Dialog = ({ context = "global" }) => {
|
export const Dialog = ({ context = "global" }) => {
|
||||||
const { colors } = useThemeColors();
|
const { colors } = useThemeColors();
|
||||||
@@ -125,10 +126,11 @@ export const Dialog = ({ context = "global" }) => {
|
|||||||
...getElevationStyle(5),
|
...getElevationStyle(5),
|
||||||
width: DDS.isTab ? 400 : "85%",
|
width: DDS.isTab ? 400 : "85%",
|
||||||
maxHeight: 450,
|
maxHeight: 450,
|
||||||
borderRadius: 5,
|
borderRadius: br,
|
||||||
backgroundColor: colors.primary.background,
|
backgroundColor: colors.primary.background,
|
||||||
paddingTop: 12,
|
paddingTop: 12,
|
||||||
...getContainerBorder(colors.primary.border, 0.5)
|
...getContainerBorder(colors.primary.border, 0.5),
|
||||||
|
overflow: "hidden"
|
||||||
};
|
};
|
||||||
|
|
||||||
return visible ? (
|
return visible ? (
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ import {
|
|||||||
eUpdateNoteInEditor
|
eUpdateNoteInEditor
|
||||||
} from "../../../utils/events";
|
} from "../../../utils/events";
|
||||||
import { deleteItems } from "../../../utils/functions";
|
import { deleteItems } from "../../../utils/functions";
|
||||||
import { tabBarRef } from "../../../utils/global-refs";
|
import { fluidTabsRef } from "../../../utils/global-refs";
|
||||||
import { convertNoteToText } from "../../../utils/note-to-text";
|
import { convertNoteToText } from "../../../utils/note-to-text";
|
||||||
import { sleep } from "../../../utils/time";
|
import { sleep } from "../../../utils/time";
|
||||||
import BaseDialog from "../../dialog/base-dialog";
|
import BaseDialog from "../../dialog/base-dialog";
|
||||||
@@ -553,7 +553,7 @@ export class VaultDialog extends Component {
|
|||||||
item: note
|
item: note
|
||||||
});
|
});
|
||||||
if (!DDS.isTab) {
|
if (!DDS.isTab) {
|
||||||
tabBarRef.current?.goToPage(1);
|
fluidTabsRef.current?.goToPage(1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,12 +37,12 @@ import Animated, {
|
|||||||
WithSpringConfig,
|
WithSpringConfig,
|
||||||
withTiming
|
withTiming
|
||||||
} from "react-native-reanimated";
|
} from "react-native-reanimated";
|
||||||
|
import { useTabStore } from "../../screens/editor/tiptap/use-tab-store";
|
||||||
import { getAppState } from "../../screens/editor/tiptap/utils";
|
import { getAppState } from "../../screens/editor/tiptap/utils";
|
||||||
import { eSendEvent } from "../../services/event-manager";
|
import { eSendEvent } from "../../services/event-manager";
|
||||||
import { useSettingStore } from "../../stores/use-setting-store";
|
import { useSettingStore } from "../../stores/use-setting-store";
|
||||||
import { eClearEditor } from "../../utils/events";
|
import { eClearEditor } from "../../utils/events";
|
||||||
import { useSideBarDraggingStore } from "../side-menu/dragging-store";
|
import { useSideBarDraggingStore } from "../side-menu/dragging-store";
|
||||||
import { useTabStore } from "../../screens/editor/tiptap/use-tab-store";
|
|
||||||
|
|
||||||
interface TabProps extends ViewProps {
|
interface TabProps extends ViewProps {
|
||||||
dimensions: { width: number; height: number };
|
dimensions: { width: number; height: number };
|
||||||
@@ -66,7 +66,7 @@ export interface TabsRef {
|
|||||||
node: RefObject<Animated.View>;
|
node: RefObject<Animated.View>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
|
export const FluidPanels = forwardRef<TabsRef, TabProps>(function FluidTabs(
|
||||||
{
|
{
|
||||||
children,
|
children,
|
||||||
dimensions,
|
dimensions,
|
||||||
@@ -81,9 +81,6 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
|
|||||||
const appState = useMemo(() => getAppState(), []);
|
const appState = useMemo(() => getAppState(), []);
|
||||||
const deviceMode = useSettingStore((state) => state.deviceMode);
|
const deviceMode = useSettingStore((state) => state.deviceMode);
|
||||||
const fullscreen = useSettingStore((state) => state.fullscreen);
|
const fullscreen = useSettingStore((state) => state.fullscreen);
|
||||||
const introCompleted = useSettingStore(
|
|
||||||
(state) => state.settings.introCompleted
|
|
||||||
);
|
|
||||||
const translateX = useSharedValue(
|
const translateX = useSharedValue(
|
||||||
widths
|
widths
|
||||||
? appState &&
|
? appState &&
|
||||||
@@ -118,7 +115,6 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
|
|||||||
const isIPhone = Platform.OS === "ios";
|
const isIPhone = Platform.OS === "ios";
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (introCompleted) {
|
|
||||||
if (deviceMode === "tablet" || fullscreen) {
|
if (deviceMode === "tablet" || fullscreen) {
|
||||||
translateX.value = 0;
|
translateX.value = 0;
|
||||||
} else {
|
} else {
|
||||||
@@ -134,10 +130,19 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
|
|||||||
}
|
}
|
||||||
isLoaded.current = true;
|
isLoaded.current = true;
|
||||||
prevWidths.current = widths;
|
prevWidths.current = widths;
|
||||||
}
|
}, [
|
||||||
|
deviceMode,
|
||||||
|
widths,
|
||||||
|
fullscreen,
|
||||||
|
translateX,
|
||||||
|
editorPosition,
|
||||||
|
appState,
|
||||||
|
onChangeTab
|
||||||
|
]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
const sub = BackHandler.addEventListener("hardwareBackPress", () => {
|
const sub = BackHandler.addEventListener("hardwareBackPress", () => {
|
||||||
if (isDrawerOpen.value) {
|
if (isDrawerOpen.value && !forcedLock.value) {
|
||||||
translateX.value = withTiming(homePosition);
|
translateX.value = withTiming(homePosition);
|
||||||
onDrawerStateChange(false);
|
onDrawerStateChange(false);
|
||||||
isDrawerOpen.value = false;
|
isDrawerOpen.value = false;
|
||||||
@@ -149,16 +154,11 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
|
|||||||
sub && sub.remove();
|
sub && sub.remove();
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
introCompleted,
|
forcedLock.value,
|
||||||
deviceMode,
|
|
||||||
widths,
|
|
||||||
fullscreen,
|
|
||||||
translateX,
|
|
||||||
isDrawerOpen,
|
|
||||||
homePosition,
|
homePosition,
|
||||||
|
isDrawerOpen,
|
||||||
onDrawerStateChange,
|
onDrawerStateChange,
|
||||||
editorPosition,
|
translateX
|
||||||
appState
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
useImperativeHandle(
|
useImperativeHandle(
|
||||||
@@ -294,8 +294,8 @@ export const FluidTabs = forwardRef<TabsRef, TabProps>(function FluidTabs(
|
|||||||
const gesture = Gesture.Pan()
|
const gesture = Gesture.Pan()
|
||||||
.maxPointers(1)
|
.maxPointers(1)
|
||||||
.enabled(enabled && !disabled)
|
.enabled(enabled && !disabled)
|
||||||
.activeOffsetX([-5, 5])
|
.activeOffsetX([-20, 20])
|
||||||
.failOffsetY([-15, 15])
|
.failOffsetY([-10, 10])
|
||||||
.onBegin((event) => {
|
.onBegin((event) => {
|
||||||
locked.value = false;
|
locked.value = false;
|
||||||
gestureStartValue.value = {
|
gestureStartValue.value = {
|
||||||
@@ -17,60 +17,52 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { strings } from "@notesnook/intl";
|
||||||
import { useThemeColors } from "@notesnook/theme";
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
import React, { useCallback, useEffect, useState } from "react";
|
import React, { useCallback, useEffect, useState } from "react";
|
||||||
import { Platform, StyleSheet, View } from "react-native";
|
import { View } from "react-native";
|
||||||
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
|
|
||||||
import {
|
import {
|
||||||
eSubscribeEvent,
|
eSubscribeEvent,
|
||||||
eUnSubscribeEvent
|
eUnSubscribeEvent
|
||||||
} from "../../services/event-manager";
|
} from "../../services/event-manager";
|
||||||
import useNavigationStore, {
|
import { RouteName } from "../../stores/use-navigation-store";
|
||||||
RouteName
|
|
||||||
} from "../../stores/use-navigation-store";
|
|
||||||
import { useSelectionStore } from "../../stores/use-selection-store";
|
import { useSelectionStore } from "../../stores/use-selection-store";
|
||||||
import { eScrollEvent } from "../../utils/events";
|
import { eScrollEvent } from "../../utils/events";
|
||||||
|
import { SIZE } from "../../utils/size";
|
||||||
|
import { DefaultAppStyles } from "../../utils/styles";
|
||||||
|
import { IconButtonProps } from "../ui/icon-button";
|
||||||
|
import { Pressable } from "../ui/pressable";
|
||||||
|
import Heading from "../ui/typography/heading";
|
||||||
|
import Paragraph from "../ui/typography/paragraph";
|
||||||
import { LeftMenus } from "./left-menus";
|
import { LeftMenus } from "./left-menus";
|
||||||
import { RightMenus } from "./right-menus";
|
import { RightMenus } from "./right-menus";
|
||||||
import { Title } from "./title";
|
|
||||||
|
|
||||||
type HeaderRightButton = {
|
|
||||||
title: string;
|
|
||||||
onPress: () => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Header = ({
|
export const Header = ({
|
||||||
renderedInRoute,
|
renderedInRoute,
|
||||||
onLeftMenuButtonPress,
|
onLeftMenuButtonPress,
|
||||||
title,
|
title,
|
||||||
titleHiddenOnRender,
|
|
||||||
headerRightButtons,
|
|
||||||
id,
|
id,
|
||||||
accentColor,
|
|
||||||
isBeta,
|
|
||||||
canGoBack,
|
canGoBack,
|
||||||
onPressDefaultRightButton,
|
|
||||||
hasSearch,
|
hasSearch,
|
||||||
onSearch
|
onSearch,
|
||||||
|
rightButton
|
||||||
}: {
|
}: {
|
||||||
onLeftMenuButtonPress?: () => void;
|
onLeftMenuButtonPress?: () => void;
|
||||||
renderedInRoute?: RouteName;
|
renderedInRoute?: RouteName;
|
||||||
id?: string;
|
id?: string;
|
||||||
title: string;
|
title: string;
|
||||||
headerRightButtons?: HeaderRightButton[];
|
|
||||||
titleHiddenOnRender?: boolean;
|
|
||||||
accentColor?: string;
|
|
||||||
isBeta?: boolean;
|
|
||||||
canGoBack?: boolean;
|
canGoBack?: boolean;
|
||||||
onPressDefaultRightButton?: () => void;
|
onPressDefaultRightButton?: () => void;
|
||||||
hasSearch?: boolean;
|
hasSearch?: boolean;
|
||||||
onSearch?: () => void;
|
onSearch?: () => void;
|
||||||
|
rightButton?: IconButtonProps;
|
||||||
}) => {
|
}) => {
|
||||||
const { colors } = useThemeColors();
|
const { colors } = useThemeColors();
|
||||||
const insets = useGlobalSafeAreaInsets();
|
|
||||||
const [borderHidden, setBorderHidden] = useState(true);
|
const [borderHidden, setBorderHidden] = useState(true);
|
||||||
const selectionMode = useSelectionStore((state) => state.selectionMode);
|
const [selectedItemsList, selectionMode] = useSelectionStore((state) => [
|
||||||
const isFocused = useNavigationStore((state) => state.focusedRouteId === id);
|
state.selectedItemsList,
|
||||||
|
state.selectionMode
|
||||||
|
]);
|
||||||
|
|
||||||
const onScroll = useCallback(
|
const onScroll = useCallback(
|
||||||
(data: { x: number; y: number; id?: string; route: string }) => {
|
(data: { x: number; y: number; id?: string; route: string }) => {
|
||||||
@@ -93,88 +85,47 @@ export const Header = ({
|
|||||||
};
|
};
|
||||||
}, [borderHidden, onScroll]);
|
}, [borderHidden, onScroll]);
|
||||||
|
|
||||||
return selectionMode && isFocused ? null : (
|
const HeaderWrapper = hasSearch ? Pressable : View;
|
||||||
<>
|
|
||||||
|
return (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={{
|
||||||
styles.container,
|
paddingHorizontal: DefaultAppStyles.GAP
|
||||||
{
|
}}
|
||||||
marginTop: Platform.OS === "android" ? insets.top : null,
|
>
|
||||||
backgroundColor: colors.primary.background,
|
<HeaderWrapper
|
||||||
overflow: "hidden",
|
style={{
|
||||||
borderBottomWidth: 1,
|
flexDirection: "row",
|
||||||
borderBottomColor: borderHidden
|
justifyContent: "space-between",
|
||||||
? "transparent"
|
marginTop: DefaultAppStyles.GAP_SMALL,
|
||||||
: colors.secondary.background,
|
borderRadius: 10,
|
||||||
justifyContent: "space-between"
|
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL,
|
||||||
}
|
borderWidth: hasSearch ? 1 : 0,
|
||||||
]}
|
borderColor: colors.secondary.border,
|
||||||
|
paddingHorizontal: !hasSearch ? 0 : DefaultAppStyles.GAP_SMALL,
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
onPress={() => {
|
||||||
|
onSearch?.();
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<>
|
|
||||||
<View style={styles.leftBtnContainer}>
|
|
||||||
<LeftMenus
|
<LeftMenus
|
||||||
canGoBack={canGoBack}
|
canGoBack={canGoBack}
|
||||||
onLeftButtonPress={onLeftMenuButtonPress}
|
onLeftButtonPress={onLeftMenuButtonPress}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Title
|
{hasSearch ? (
|
||||||
isHiddenOnRender={titleHiddenOnRender}
|
<Paragraph>
|
||||||
renderedInRoute={renderedInRoute}
|
{selectionMode
|
||||||
id={id}
|
? `${selectedItemsList.length} selected`
|
||||||
accentColor={accentColor}
|
: strings.searchInRoute(title)}
|
||||||
title={title}
|
</Paragraph>
|
||||||
isBeta={isBeta}
|
) : (
|
||||||
/>
|
<Heading size={SIZE.lg}>{title}</Heading>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<RightMenus rightButton={rightButton} />
|
||||||
|
</HeaderWrapper>
|
||||||
</View>
|
</View>
|
||||||
<RightMenus
|
|
||||||
renderedInRoute={renderedInRoute}
|
|
||||||
id={id}
|
|
||||||
headerRightButtons={headerRightButtons}
|
|
||||||
onPressDefaultRightButton={onPressDefaultRightButton}
|
|
||||||
search={hasSearch}
|
|
||||||
onSearch={onSearch}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
</View>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const styles = StyleSheet.create({
|
|
||||||
container: {
|
|
||||||
flexDirection: "row",
|
|
||||||
zIndex: 11,
|
|
||||||
height: 50,
|
|
||||||
maxHeight: 50,
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
paddingHorizontal: 12,
|
|
||||||
width: "100%"
|
|
||||||
},
|
|
||||||
leftBtnContainer: {
|
|
||||||
flexDirection: "row",
|
|
||||||
justifyContent: "flex-start",
|
|
||||||
alignItems: "center",
|
|
||||||
flexShrink: 1
|
|
||||||
},
|
|
||||||
leftBtn: {
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
height: 40,
|
|
||||||
width: 40,
|
|
||||||
borderRadius: 100,
|
|
||||||
marginLeft: -5,
|
|
||||||
marginRight: 25
|
|
||||||
},
|
|
||||||
rightBtnContainer: {
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center"
|
|
||||||
},
|
|
||||||
rightBtn: {
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "flex-end",
|
|
||||||
height: 40,
|
|
||||||
width: 40,
|
|
||||||
paddingRight: 0
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -20,10 +20,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
import { useThemeColors } from "@notesnook/theme";
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { notesnook } from "../../../e2e/test.ids";
|
import { notesnook } from "../../../e2e/test.ids";
|
||||||
import { DDS } from "../../services/device-detection";
|
|
||||||
import Navigation from "../../services/navigation";
|
import Navigation from "../../services/navigation";
|
||||||
import { useSettingStore } from "../../stores/use-setting-store";
|
import { useSettingStore } from "../../stores/use-setting-store";
|
||||||
import { tabBarRef } from "../../utils/global-refs";
|
import { fluidTabsRef } from "../../utils/global-refs";
|
||||||
import { IconButton } from "../ui/icon-button";
|
import { IconButton } from "../ui/icon-button";
|
||||||
|
|
||||||
export const LeftMenus = ({
|
export const LeftMenus = ({
|
||||||
@@ -41,7 +40,7 @@ export const LeftMenus = ({
|
|||||||
if (onLeftButtonPress) return onLeftButtonPress();
|
if (onLeftButtonPress) return onLeftButtonPress();
|
||||||
|
|
||||||
if (!canGoBack) {
|
if (!canGoBack) {
|
||||||
if (tabBarRef.current?.isDrawerOpen()) {
|
if (fluidTabsRef.current?.isDrawerOpen()) {
|
||||||
Navigation.closeDrawer();
|
Navigation.closeDrawer();
|
||||||
} else {
|
} else {
|
||||||
Navigation.openDrawer();
|
Navigation.openDrawer();
|
||||||
@@ -54,23 +53,14 @@ export const LeftMenus = ({
|
|||||||
return isTablet && !canGoBack ? null : (
|
return isTablet && !canGoBack ? null : (
|
||||||
<IconButton
|
<IconButton
|
||||||
testID={notesnook.ids.default.header.buttons.left}
|
testID={notesnook.ids.default.header.buttons.left}
|
||||||
style={{
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
height: 40,
|
|
||||||
width: 40,
|
|
||||||
borderRadius: 100,
|
|
||||||
marginRight: DDS.isLargeTablet() ? 10 : 7
|
|
||||||
}}
|
|
||||||
left={40}
|
left={40}
|
||||||
top={40}
|
top={40}
|
||||||
right={DDS.isLargeTablet() ? 10 : 10}
|
|
||||||
onPress={_onLeftButtonPress}
|
onPress={_onLeftButtonPress}
|
||||||
onLongPress={() => {
|
onLongPress={() => {
|
||||||
Navigation.popToTop();
|
Navigation.popToTop();
|
||||||
}}
|
}}
|
||||||
name={canGoBack ? "arrow-left" : "menu"}
|
name={canGoBack ? "arrow-left" : "menu"}
|
||||||
color={colors.primary.paragraph}
|
color={colors.primary.icon}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,127 +17,30 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useRef } from "react";
|
|
||||||
import { Platform, StyleSheet, View } from "react-native";
|
|
||||||
import { useThemeColors } from "@notesnook/theme";
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
import { Menu } from "react-native-material-menu";
|
import React from "react";
|
||||||
import { notesnook } from "../../../e2e/test.ids";
|
import { StyleSheet, View } from "react-native";
|
||||||
import {
|
import { IconButton, IconButtonProps } from "../ui/icon-button";
|
||||||
HeaderRightButton,
|
|
||||||
RouteName
|
|
||||||
} from "../../stores/use-navigation-store";
|
|
||||||
import { useSettingStore } from "../../stores/use-setting-store";
|
|
||||||
import { SIZE } from "../../utils/size";
|
|
||||||
import { sleep } from "../../utils/time";
|
|
||||||
import { Button } from "../ui/button";
|
|
||||||
import { IconButton } from "../ui/icon-button";
|
|
||||||
|
|
||||||
export const RightMenus = ({
|
export const RightMenus = ({
|
||||||
headerRightButtons,
|
rightButton
|
||||||
renderedInRoute,
|
|
||||||
id,
|
|
||||||
onPressDefaultRightButton,
|
|
||||||
search,
|
|
||||||
onSearch
|
|
||||||
}: {
|
}: {
|
||||||
headerRightButtons?: HeaderRightButton[];
|
rightButton?: IconButtonProps;
|
||||||
renderedInRoute?: RouteName;
|
|
||||||
id?: string;
|
|
||||||
onPressDefaultRightButton?: () => void;
|
|
||||||
search?: boolean;
|
|
||||||
onSearch?: () => void;
|
|
||||||
}) => {
|
}) => {
|
||||||
const { colors } = useThemeColors();
|
const { colors } = useThemeColors();
|
||||||
const { colors: contextMenuColors } = useThemeColors("contextMenu");
|
|
||||||
const deviceMode = useSettingStore((state) => state.deviceMode);
|
|
||||||
const menuRef = useRef<Menu>(null);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.rightBtnContainer}>
|
<View style={styles.rightBtnContainer}>
|
||||||
{search ? (
|
{rightButton ? (
|
||||||
<IconButton
|
<IconButton {...rightButton} color={colors.primary.icon} />
|
||||||
onPress={onSearch}
|
) : (
|
||||||
testID="icon-search"
|
<View
|
||||||
name="magnify"
|
|
||||||
color={colors.primary.paragraph}
|
|
||||||
style={styles.rightBtn}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
{deviceMode !== "mobile" ? (
|
|
||||||
<Button
|
|
||||||
onPress={onPressDefaultRightButton}
|
|
||||||
testID={notesnook.ids.default.addBtn}
|
|
||||||
icon={renderedInRoute === "Trash" ? "delete" : "plus"}
|
|
||||||
iconSize={SIZE.xl}
|
|
||||||
type="accent"
|
|
||||||
hitSlop={{
|
|
||||||
top: 10,
|
|
||||||
right: 10,
|
|
||||||
bottom: 10,
|
|
||||||
left: 0
|
|
||||||
}}
|
|
||||||
style={{
|
style={{
|
||||||
marginLeft: 10,
|
width: 40,
|
||||||
width: 32,
|
height: 40
|
||||||
height: 32,
|
|
||||||
borderRadius: 100,
|
|
||||||
paddingHorizontal: 0,
|
|
||||||
borderWidth: 1,
|
|
||||||
borderColor: colors.primary.accent
|
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
) : null}
|
)}
|
||||||
|
|
||||||
{headerRightButtons && headerRightButtons.length > 0 ? (
|
|
||||||
<Menu
|
|
||||||
ref={menuRef}
|
|
||||||
animationDuration={200}
|
|
||||||
style={{
|
|
||||||
borderRadius: 5,
|
|
||||||
backgroundColor: contextMenuColors.primary.background,
|
|
||||||
marginTop: 35
|
|
||||||
}}
|
|
||||||
onRequestClose={() => {
|
|
||||||
//@ts-ignore
|
|
||||||
menuRef.current?.hide();
|
|
||||||
}}
|
|
||||||
anchor={
|
|
||||||
<IconButton
|
|
||||||
onPress={() => {
|
|
||||||
//@ts-ignore
|
|
||||||
menuRef.current?.show();
|
|
||||||
}}
|
|
||||||
name="dots-vertical"
|
|
||||||
color={colors.primary.paragraph}
|
|
||||||
style={styles.rightBtn}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{headerRightButtons.map((item) => (
|
|
||||||
<Button
|
|
||||||
style={{
|
|
||||||
justifyContent: "flex-start",
|
|
||||||
borderRadius: 0,
|
|
||||||
alignSelf: "flex-start",
|
|
||||||
width: "100%"
|
|
||||||
}}
|
|
||||||
type="plain"
|
|
||||||
buttonType={{
|
|
||||||
text: contextMenuColors.primary.paragraph
|
|
||||||
}}
|
|
||||||
key={item.title}
|
|
||||||
title={item.title}
|
|
||||||
onPress={async () => {
|
|
||||||
//@ts-ignore
|
|
||||||
menuRef.current?.hide();
|
|
||||||
if (Platform.OS === "ios") await sleep(300);
|
|
||||||
item.onPress();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</Menu>
|
|
||||||
) : null}
|
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -149,10 +52,6 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
rightBtn: {
|
rightBtn: {
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
alignItems: "center",
|
alignItems: "center"
|
||||||
height: 40,
|
|
||||||
width: 40,
|
|
||||||
marginLeft: 10,
|
|
||||||
paddingRight: 0
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,122 +17,43 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { getFormattedDate } from "@notesnook/common";
|
||||||
import { Notebook } from "@notesnook/core";
|
import { Notebook } from "@notesnook/core";
|
||||||
|
import { strings } from "@notesnook/intl";
|
||||||
import { useThemeColors } from "@notesnook/theme";
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
import React, { useState } from "react";
|
import React from "react";
|
||||||
import { View } from "react-native";
|
import { View } from "react-native";
|
||||||
import { db } from "../../../common/database";
|
|
||||||
import { ToastManager } from "../../../services/event-manager";
|
|
||||||
import { useMenuStore } from "../../../stores/use-menu-store";
|
|
||||||
import { SIZE } from "../../../utils/size";
|
import { SIZE } from "../../../utils/size";
|
||||||
import { IconButton } from "../../ui/icon-button";
|
import { DefaultAppStyles } from "../../../utils/styles";
|
||||||
|
import AppIcon from "../../ui/AppIcon";
|
||||||
import Heading from "../../ui/typography/heading";
|
import Heading from "../../ui/typography/heading";
|
||||||
import Paragraph from "../../ui/typography/paragraph";
|
import Paragraph from "../../ui/typography/paragraph";
|
||||||
import { getFormattedDate } from "@notesnook/common";
|
|
||||||
import { strings } from "@notesnook/intl";
|
|
||||||
|
|
||||||
export const NotebookHeader = ({
|
export const NotebookHeader = ({
|
||||||
notebook,
|
notebook,
|
||||||
onEditNotebook,
|
|
||||||
totalNotes = 0
|
totalNotes = 0
|
||||||
}: {
|
}: {
|
||||||
notebook: Notebook;
|
notebook: Notebook;
|
||||||
onEditNotebook: () => void;
|
|
||||||
totalNotes: number;
|
totalNotes: number;
|
||||||
}) => {
|
}) => {
|
||||||
const { colors } = useThemeColors();
|
const { colors } = useThemeColors();
|
||||||
const [isPinnedToMenu, setIsPinnedToMenu] = useState(
|
|
||||||
db.shortcuts.exists(notebook.id)
|
|
||||||
);
|
|
||||||
const setMenuPins = useMenuStore((state) => state.setMenuPins);
|
|
||||||
|
|
||||||
const onPinNotebook = async () => {
|
|
||||||
try {
|
|
||||||
if (isPinnedToMenu) {
|
|
||||||
await db.shortcuts.remove(notebook.id);
|
|
||||||
} else {
|
|
||||||
await db.shortcuts.add({
|
|
||||||
item: {
|
|
||||||
id: notebook.id,
|
|
||||||
type: "notebook"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
ToastManager.show({
|
|
||||||
heading: strings.shortcutCreated(),
|
|
||||||
type: "success"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
setIsPinnedToMenu(db.shortcuts.exists(notebook.id));
|
|
||||||
setMenuPins();
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
marginBottom: 5,
|
paddingHorizontal: DefaultAppStyles.GAP,
|
||||||
padding: 0,
|
marginVertical: DefaultAppStyles.GAP,
|
||||||
|
backgroundColor: colors.secondary.background
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
paddingVertical: 15,
|
gap: DefaultAppStyles.GAP_VERTICAL,
|
||||||
paddingHorizontal: 12,
|
paddingVertical: 25
|
||||||
alignSelf: "center",
|
|
||||||
borderRadius: 10,
|
|
||||||
paddingTop: 25
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Paragraph color={colors.secondary.paragraph} size={SIZE.xs}>
|
<AppIcon name="notebook" size={SIZE.xxl} />
|
||||||
{getFormattedDate(notebook.dateModified, "date-time")}
|
<Heading size={SIZE.lg}>{notebook.title}</Heading>
|
||||||
</Paragraph>
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
flexDirection: "row",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
alignItems: "center"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Heading
|
|
||||||
style={{
|
|
||||||
flexShrink: 1
|
|
||||||
}}
|
|
||||||
size={SIZE.lg}
|
|
||||||
>
|
|
||||||
{notebook.title}
|
|
||||||
</Heading>
|
|
||||||
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
flexDirection: "row"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<IconButton
|
|
||||||
name={isPinnedToMenu ? "link-variant-off" : "link-variant"}
|
|
||||||
onPress={onPinNotebook}
|
|
||||||
tooltipText={"Create shortcut in side menu"}
|
|
||||||
style={{
|
|
||||||
marginRight: 15,
|
|
||||||
width: 40,
|
|
||||||
height: 40
|
|
||||||
}}
|
|
||||||
type="transparent"
|
|
||||||
color={isPinnedToMenu ? colors.primary.accent : colors.primary.icon}
|
|
||||||
size={SIZE.lg}
|
|
||||||
/>
|
|
||||||
<IconButton
|
|
||||||
size={SIZE.lg}
|
|
||||||
onPress={onEditNotebook}
|
|
||||||
tooltipText="Edit this notebook"
|
|
||||||
name="pencil"
|
|
||||||
type="transparent"
|
|
||||||
color={colors.primary.icon}
|
|
||||||
style={{
|
|
||||||
width: 40,
|
|
||||||
height: 40
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
{notebook.description ? (
|
{notebook.description ? (
|
||||||
<Paragraph size={SIZE.sm} color={colors.primary.paragraph}>
|
<Paragraph size={SIZE.sm} color={colors.primary.paragraph}>
|
||||||
@@ -140,17 +61,21 @@ export const NotebookHeader = ({
|
|||||||
</Paragraph>
|
</Paragraph>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<Paragraph
|
<View
|
||||||
style={{
|
style={{
|
||||||
marginTop: 10,
|
flexDirection: "row",
|
||||||
fontStyle: "italic",
|
gap: DefaultAppStyles.GAP_SMALL
|
||||||
fontFamily: undefined
|
|
||||||
}}
|
}}
|
||||||
size={SIZE.xs}
|
|
||||||
color={colors.secondary.paragraph}
|
|
||||||
>
|
>
|
||||||
|
<Paragraph size={SIZE.xxs} color={colors.secondary.paragraph}>
|
||||||
{strings.notes(totalNotes || 0)}
|
{strings.notes(totalNotes || 0)}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
|
||||||
|
<Paragraph color={colors.secondary.paragraph} size={SIZE.xxs}>
|
||||||
|
{getFormattedDate(notebook.dateModified, "date-time")}
|
||||||
|
</Paragraph>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,16 +21,16 @@ import { GroupHeader, GroupOptions, ItemType } from "@notesnook/core";
|
|||||||
import { strings } from "@notesnook/intl";
|
import { strings } from "@notesnook/intl";
|
||||||
import { useThemeColors } from "@notesnook/theme";
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { TouchableOpacity, View, useWindowDimensions } from "react-native";
|
import { useWindowDimensions, View } from "react-native";
|
||||||
import { useIsCompactModeEnabled } from "../../../hooks/use-is-compact-mode-enabled";
|
import { useIsCompactModeEnabled } from "../../../hooks/use-is-compact-mode-enabled";
|
||||||
import { presentSheet } from "../../../services/event-manager";
|
import { presentSheet } from "../../../services/event-manager";
|
||||||
import SettingsService from "../../../services/settings";
|
import SettingsService from "../../../services/settings";
|
||||||
import { RouteName } from "../../../stores/use-navigation-store";
|
import { RouteName } from "../../../stores/use-navigation-store";
|
||||||
import { getContainerBorder } from "../../../utils/colors";
|
|
||||||
import { SIZE } from "../../../utils/size";
|
import { SIZE } from "../../../utils/size";
|
||||||
|
import { DefaultAppStyles } from "../../../utils/styles";
|
||||||
import Sort from "../../sheets/sort";
|
import Sort from "../../sheets/sort";
|
||||||
import { Button } from "../../ui/button";
|
|
||||||
import { IconButton } from "../../ui/icon-button";
|
import { IconButton } from "../../ui/icon-button";
|
||||||
|
import { Pressable } from "../../ui/pressable";
|
||||||
import Heading from "../../ui/typography/heading";
|
import Heading from "../../ui/typography/heading";
|
||||||
|
|
||||||
type SectionHeaderProps = {
|
type SectionHeaderProps = {
|
||||||
@@ -65,91 +65,88 @@ export const SectionHeader = React.memo<
|
|||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
flexDirection: "row",
|
width: "100%",
|
||||||
alignItems: "center",
|
paddingHorizontal: DefaultAppStyles.GAP,
|
||||||
width: "95%",
|
marginVertical: DefaultAppStyles.GAP
|
||||||
justifyContent: "space-between",
|
|
||||||
paddingHorizontal: 12,
|
|
||||||
height: 35 * fontScale,
|
|
||||||
backgroundColor: colors.secondary.background,
|
|
||||||
alignSelf: "center",
|
|
||||||
borderRadius: 5,
|
|
||||||
marginVertical: 5,
|
|
||||||
...getContainerBorder(colors.secondary.background, 0.8)
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<TouchableOpacity
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
width: "100%",
|
||||||
|
alignSelf: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
borderColor: colors.primary.border,
|
||||||
|
paddingBottom: DefaultAppStyles.GAP_VERTICAL
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Pressable
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
onOpenJumpToDialog();
|
onOpenJumpToDialog();
|
||||||
}}
|
}}
|
||||||
activeOpacity={0.9}
|
|
||||||
hitSlop={{ top: 10, left: 10, right: 30, bottom: 15 }}
|
hitSlop={{ top: 10, left: 10, right: 30, bottom: 15 }}
|
||||||
style={{
|
style={{
|
||||||
height: "100%",
|
justifyContent: "flex-start",
|
||||||
justifyContent: "center"
|
flexDirection: "row",
|
||||||
|
width: "auto"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Heading
|
<Heading
|
||||||
color={color || colors.primary.accent}
|
|
||||||
size={SIZE.sm}
|
size={SIZE.sm}
|
||||||
style={{
|
style={{
|
||||||
alignSelf: "center",
|
alignSelf: "center",
|
||||||
textAlignVertical: "center"
|
textAlignVertical: "center"
|
||||||
}}
|
}}
|
||||||
|
color={colors.primary.accent}
|
||||||
>
|
>
|
||||||
{!item.title || item.title === "" ? strings.pinned() : item.title}
|
{!item.title || item.title === "" ? strings.pinned() : item.title}
|
||||||
</Heading>
|
</Heading>
|
||||||
</TouchableOpacity>
|
</Pressable>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center"
|
alignItems: "center",
|
||||||
|
gap: DefaultAppStyles.GAP_SMALL
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{index === 0 ? (
|
{index === 0 ? (
|
||||||
<>
|
<>
|
||||||
<Button
|
<IconButton
|
||||||
onPress={() => {
|
name={
|
||||||
presentSheet({
|
|
||||||
component: <Sort screen={screen} type={dataType} />
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
title={groupBy}
|
|
||||||
icon={
|
|
||||||
groupOptions.sortDirection === "asc"
|
groupOptions.sortDirection === "asc"
|
||||||
? "sort-ascending"
|
? "sort-ascending"
|
||||||
: "sort-descending"
|
: "sort-descending"
|
||||||
}
|
}
|
||||||
height={25}
|
onPress={() => {
|
||||||
style={{
|
if (!screen) return;
|
||||||
borderRadius: 100,
|
presentSheet({
|
||||||
paddingHorizontal: 0,
|
component: <Sort screen={screen} type={dataType} />
|
||||||
backgroundColor: "transparent",
|
});
|
||||||
marginRight:
|
|
||||||
dataType === "note" ||
|
|
||||||
screen === "Notes" ||
|
|
||||||
dataType === "notebook"
|
|
||||||
? 10
|
|
||||||
: 0
|
|
||||||
}}
|
}}
|
||||||
type="plain"
|
|
||||||
iconPosition="right"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<IconButton
|
|
||||||
style={{
|
style={{
|
||||||
width: 25,
|
width: 25,
|
||||||
height: 25
|
height: 25
|
||||||
}}
|
}}
|
||||||
|
size={SIZE.lg - 2}
|
||||||
|
/>
|
||||||
|
<IconButton
|
||||||
hidden={
|
hidden={
|
||||||
dataType !== "note" &&
|
dataType !== "note" &&
|
||||||
dataType !== "notebook" &&
|
dataType !== "notebook" &&
|
||||||
screen !== "Notes"
|
screen !== "Notes"
|
||||||
}
|
}
|
||||||
|
style={{
|
||||||
|
width: 25,
|
||||||
|
height: 25
|
||||||
|
}}
|
||||||
testID="icon-compact-mode"
|
testID="icon-compact-mode"
|
||||||
color={colors.secondary.icon}
|
color={colors.secondary.icon}
|
||||||
name={isCompactModeEnabled ? "view-list" : "view-list-outline"}
|
name={
|
||||||
|
isCompactModeEnabled ? "view-list" : "view-list-outline"
|
||||||
|
}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
SettingsService.set({
|
SettingsService.set({
|
||||||
[dataType !== "notebook"
|
[dataType !== "notebook"
|
||||||
@@ -163,6 +160,16 @@ export const SectionHeader = React.memo<
|
|||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
<IconButton
|
||||||
|
style={{
|
||||||
|
width: 25,
|
||||||
|
height: 25
|
||||||
|
}}
|
||||||
|
name={"chevron-down"}
|
||||||
|
size={SIZE.lg - 2}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -29,24 +29,25 @@ import { EntityLevel, decode } from "entities";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { View } from "react-native";
|
import { View } from "react-native";
|
||||||
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||||
import { notesnook } from "../../../../e2e/test.ids";
|
|
||||||
import { useIsCompactModeEnabled } from "../../../hooks/use-is-compact-mode-enabled";
|
import { useIsCompactModeEnabled } from "../../../hooks/use-is-compact-mode-enabled";
|
||||||
import NotebookScreen from "../../../screens/notebook";
|
|
||||||
import { TaggedNotes } from "../../../screens/notes/tagged";
|
|
||||||
import useNavigationStore from "../../../stores/use-navigation-store";
|
import useNavigationStore from "../../../stores/use-navigation-store";
|
||||||
import { useRelationStore } from "../../../stores/use-relation-store";
|
import { useRelationStore } from "../../../stores/use-relation-store";
|
||||||
import { SIZE } from "../../../utils/size";
|
import { SIZE } from "../../../utils/size";
|
||||||
|
|
||||||
import { useTabStore } from "../../../screens/editor/tiptap/use-tab-store";
|
|
||||||
import { NotebooksWithDateEdited, TagsWithDateEdited } from "@notesnook/common";
|
import { NotebooksWithDateEdited, TagsWithDateEdited } from "@notesnook/common";
|
||||||
|
import { strings } from "@notesnook/intl";
|
||||||
|
import { notesnook } from "../../../../e2e/test.ids";
|
||||||
|
import useIsSelected from "../../../hooks/use-selected";
|
||||||
|
import { useTabStore } from "../../../screens/editor/tiptap/use-tab-store";
|
||||||
|
import { useSelectionStore } from "../../../stores/use-selection-store";
|
||||||
|
import { DefaultAppStyles } from "../../../utils/styles";
|
||||||
import { Properties } from "../../properties";
|
import { Properties } from "../../properties";
|
||||||
import { Button } from "../../ui/button";
|
import AppIcon from "../../ui/AppIcon";
|
||||||
import { IconButton } from "../../ui/icon-button";
|
import { IconButton } from "../../ui/icon-button";
|
||||||
import { ReminderTime } from "../../ui/reminder-time";
|
import { ReminderTime } from "../../ui/reminder-time";
|
||||||
import { TimeSince } from "../../ui/time-since";
|
import { TimeSince } from "../../ui/time-since";
|
||||||
import Heading from "../../ui/typography/heading";
|
import Heading from "../../ui/typography/heading";
|
||||||
import Paragraph from "../../ui/typography/paragraph";
|
import Paragraph from "../../ui/typography/paragraph";
|
||||||
import { strings } from "@notesnook/intl";
|
|
||||||
|
|
||||||
type NoteItemProps = {
|
type NoteItemProps = {
|
||||||
item: Note | BaseTrashItem<Note>;
|
item: Note | BaseTrashItem<Note>;
|
||||||
@@ -85,6 +86,8 @@ const NoteItem = ({
|
|||||||
);
|
);
|
||||||
const _update = useRelationStore((state) => state.updater);
|
const _update = useRelationStore((state) => state.updater);
|
||||||
const primaryColors = isEditingNote ? colors.selected : colors.primary;
|
const primaryColors = isEditingNote ? colors.selected : colors.primary;
|
||||||
|
const selectionMode = useSelectionStore((state) => state.selectionMode);
|
||||||
|
const [selected] = useIsSelected(item);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -94,64 +97,6 @@ const NoteItem = ({
|
|||||||
flexShrink: 1
|
flexShrink: 1
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{!compactMode ? (
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center",
|
|
||||||
zIndex: 10,
|
|
||||||
elevation: 10,
|
|
||||||
marginBottom: 2.5,
|
|
||||||
flexWrap: "wrap"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{notebooks?.items
|
|
||||||
?.filter(
|
|
||||||
(item) =>
|
|
||||||
item.id !== useNavigationStore.getState().focusedRouteId
|
|
||||||
)
|
|
||||||
.map((item) => (
|
|
||||||
<Button
|
|
||||||
title={
|
|
||||||
item.title.length > 25
|
|
||||||
? item.title.slice(0, 25) + "..."
|
|
||||||
: item.title
|
|
||||||
}
|
|
||||||
tooltipText={item.title}
|
|
||||||
key={item.id}
|
|
||||||
height={25}
|
|
||||||
icon="book-outline"
|
|
||||||
type="secondary"
|
|
||||||
fontSize={SIZE.xs}
|
|
||||||
iconSize={SIZE.sm}
|
|
||||||
textStyle={{
|
|
||||||
marginRight: 0
|
|
||||||
}}
|
|
||||||
style={{
|
|
||||||
borderRadius: 5,
|
|
||||||
marginRight: 5,
|
|
||||||
paddingHorizontal: 6,
|
|
||||||
marginBottom: 5
|
|
||||||
}}
|
|
||||||
onPress={() => {
|
|
||||||
NotebookScreen.navigate(item, true);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
|
|
||||||
<ReminderTime
|
|
||||||
reminder={reminder}
|
|
||||||
color={color?.colorCode}
|
|
||||||
onPress={() => {
|
|
||||||
Properties.present(reminder);
|
|
||||||
}}
|
|
||||||
style={{
|
|
||||||
height: 25
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
{compactMode ? (
|
{compactMode ? (
|
||||||
<Paragraph
|
<Paragraph
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
@@ -167,7 +112,7 @@ const NoteItem = ({
|
|||||||
<Heading
|
<Heading
|
||||||
numberOfLines={1}
|
numberOfLines={1}
|
||||||
color={color?.colorCode || primaryColors.heading}
|
color={color?.colorCode || primaryColors.heading}
|
||||||
size={SIZE.md}
|
size={SIZE.sm}
|
||||||
style={{
|
style={{
|
||||||
paddingRight: 10
|
paddingRight: 10
|
||||||
}}
|
}}
|
||||||
@@ -198,7 +143,9 @@ const NoteItem = ({
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
marginTop: 5,
|
marginTop: 5,
|
||||||
height: SIZE.md + 2
|
columnGap: 8,
|
||||||
|
rowGap: 4,
|
||||||
|
flexWrap: "wrap"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{!isTrash ? (
|
{!isTrash ? (
|
||||||
@@ -206,9 +153,6 @@ const NoteItem = ({
|
|||||||
{item.conflicted ? (
|
{item.conflicted ? (
|
||||||
<Icon
|
<Icon
|
||||||
name="alert-circle"
|
name="alert-circle"
|
||||||
style={{
|
|
||||||
marginRight: 6
|
|
||||||
}}
|
|
||||||
size={SIZE.sm}
|
size={SIZE.sm}
|
||||||
color={colors.error.accent}
|
color={colors.error.accent}
|
||||||
/>
|
/>
|
||||||
@@ -219,9 +163,6 @@ const NoteItem = ({
|
|||||||
testID="sync-off"
|
testID="sync-off"
|
||||||
name="sync-off"
|
name="sync-off"
|
||||||
size={SIZE.sm}
|
size={SIZE.sm}
|
||||||
style={{
|
|
||||||
marginRight: 6
|
|
||||||
}}
|
|
||||||
color={primaryColors.icon}
|
color={primaryColors.icon}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
@@ -231,18 +172,14 @@ const NoteItem = ({
|
|||||||
testID="pencil-lock"
|
testID="pencil-lock"
|
||||||
name="pencil-lock"
|
name="pencil-lock"
|
||||||
size={SIZE.sm}
|
size={SIZE.sm}
|
||||||
style={{
|
|
||||||
marginRight: 6
|
|
||||||
}}
|
|
||||||
color={primaryColors.icon}
|
color={primaryColors.icon}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<TimeSince
|
<TimeSince
|
||||||
style={{
|
style={{
|
||||||
fontSize: SIZE.xs,
|
fontSize: SIZE.xxs,
|
||||||
color: colors.secondary.paragraph,
|
color: colors.secondary.paragraph
|
||||||
marginRight: 6
|
|
||||||
}}
|
}}
|
||||||
time={date}
|
time={date}
|
||||||
updateFrequency={Date.now() - date < 60000 ? 2000 : 60000}
|
updateFrequency={Date.now() - date < 60000 ? 2000 : 60000}
|
||||||
@@ -253,7 +190,6 @@ const NoteItem = ({
|
|||||||
style={{
|
style={{
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
marginRight: 6,
|
|
||||||
gap: 2
|
gap: 2
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -264,7 +200,7 @@ const NoteItem = ({
|
|||||||
/>
|
/>
|
||||||
<Paragraph
|
<Paragraph
|
||||||
color={colors.secondary.paragraph}
|
color={colors.secondary.paragraph}
|
||||||
size={SIZE.xs}
|
size={SIZE.xxs}
|
||||||
>
|
>
|
||||||
{attachmentsCount}
|
{attachmentsCount}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
@@ -275,10 +211,7 @@ const NoteItem = ({
|
|||||||
<Icon
|
<Icon
|
||||||
testID="icon-pinned"
|
testID="icon-pinned"
|
||||||
name="pin-outline"
|
name="pin-outline"
|
||||||
size={SIZE.sm}
|
size={SIZE.xs}
|
||||||
style={{
|
|
||||||
marginRight: 6
|
|
||||||
}}
|
|
||||||
color={color?.colorCode || primaryColors.accent}
|
color={color?.colorCode || primaryColors.accent}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
@@ -288,9 +221,6 @@ const NoteItem = ({
|
|||||||
name="lock"
|
name="lock"
|
||||||
testID="note-locked-icon"
|
testID="note-locked-icon"
|
||||||
size={SIZE.sm}
|
size={SIZE.sm}
|
||||||
style={{
|
|
||||||
marginRight: 6
|
|
||||||
}}
|
|
||||||
color={primaryColors.icon}
|
color={primaryColors.icon}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
@@ -300,36 +230,80 @@ const NoteItem = ({
|
|||||||
testID="icon-star"
|
testID="icon-star"
|
||||||
name="star-outline"
|
name="star-outline"
|
||||||
size={SIZE.sm}
|
size={SIZE.sm}
|
||||||
style={{
|
|
||||||
marginRight: 6
|
|
||||||
}}
|
|
||||||
color="orange"
|
color="orange"
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
{reminder ? (
|
||||||
|
<ReminderTime
|
||||||
|
reminder={reminder}
|
||||||
|
disabled
|
||||||
|
color={color?.colorCode}
|
||||||
|
textStyle={{
|
||||||
|
fontSize: SIZE.xxxs
|
||||||
|
}}
|
||||||
|
iconSize={SIZE.xxxs}
|
||||||
|
style={{
|
||||||
|
height: "auto"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
{notebooks?.items
|
||||||
|
?.filter(
|
||||||
|
(item) =>
|
||||||
|
item.id !== useNavigationStore.getState().focusedRouteId
|
||||||
|
)
|
||||||
|
.map((item) => (
|
||||||
|
<View
|
||||||
|
key={item.id}
|
||||||
|
style={{
|
||||||
|
borderRadius: 4,
|
||||||
|
backgroundColor: colors.secondary.background,
|
||||||
|
paddingHorizontal: 4,
|
||||||
|
borderWidth: 0.5,
|
||||||
|
borderColor: primaryColors.border,
|
||||||
|
paddingVertical: 1,
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: DefaultAppStyles.GAP_SMALL / 2
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AppIcon
|
||||||
|
name="book-outline"
|
||||||
|
size={SIZE.xxxs}
|
||||||
|
color={colors.secondary.icon}
|
||||||
|
/>
|
||||||
|
<Paragraph
|
||||||
|
size={SIZE.xxxs}
|
||||||
|
color={colors.secondary.paragraph}
|
||||||
|
>
|
||||||
|
{item.title}
|
||||||
|
</Paragraph>
|
||||||
|
</View>
|
||||||
|
))}
|
||||||
|
|
||||||
{!isTrash && !compactMode && tags
|
{!isTrash && !compactMode && tags
|
||||||
? tags.items?.map((item) =>
|
? tags.items?.map((item) =>
|
||||||
item.id ? (
|
item.id ? (
|
||||||
<Button
|
<View
|
||||||
title={"#" + item.title}
|
|
||||||
key={item.id}
|
key={item.id}
|
||||||
height={23}
|
|
||||||
type="plain"
|
|
||||||
textStyle={{
|
|
||||||
textDecorationLine: "underline",
|
|
||||||
color: colors.secondary.paragraph
|
|
||||||
}}
|
|
||||||
hitSlop={{ top: 8, bottom: 12, left: 0, right: 0 }}
|
|
||||||
fontSize={SIZE.xs}
|
|
||||||
style={{
|
style={{
|
||||||
borderRadius: 5,
|
borderRadius: 4,
|
||||||
paddingHorizontal: 6,
|
backgroundColor: colors.secondary.background,
|
||||||
marginRight: 4,
|
paddingHorizontal: 4,
|
||||||
zIndex: 10,
|
borderWidth: 0.5,
|
||||||
maxWidth: tags.items?.length > 1 ? 130 : null
|
borderColor: primaryColors.border,
|
||||||
|
paddingVertical: 1
|
||||||
}}
|
}}
|
||||||
onPress={() => TaggedNotes.navigate(item, true)}
|
>
|
||||||
/>
|
<Paragraph
|
||||||
|
size={SIZE.xxxs}
|
||||||
|
color={colors.secondary.paragraph}
|
||||||
|
>
|
||||||
|
#{item.title}
|
||||||
|
</Paragraph>
|
||||||
|
</View>
|
||||||
) : null
|
) : null
|
||||||
)
|
)
|
||||||
: null}
|
: null}
|
||||||
@@ -338,7 +312,7 @@ const NoteItem = ({
|
|||||||
<>
|
<>
|
||||||
<Paragraph
|
<Paragraph
|
||||||
color={colors.secondary.paragraph}
|
color={colors.secondary.paragraph}
|
||||||
size={SIZE.xs}
|
size={SIZE.xxs}
|
||||||
style={{
|
style={{
|
||||||
marginRight: 6
|
marginRight: 6
|
||||||
}}
|
}}
|
||||||
@@ -352,7 +326,7 @@ const NoteItem = ({
|
|||||||
|
|
||||||
<Paragraph
|
<Paragraph
|
||||||
color={primaryColors.accent}
|
color={primaryColors.accent}
|
||||||
size={SIZE.xs}
|
size={SIZE.xxs}
|
||||||
style={{
|
style={{
|
||||||
marginRight: 6
|
marginRight: 6
|
||||||
}}
|
}}
|
||||||
@@ -409,7 +383,7 @@ const NoteItem = ({
|
|||||||
|
|
||||||
<TimeSince
|
<TimeSince
|
||||||
style={{
|
style={{
|
||||||
fontSize: SIZE.xs,
|
fontSize: SIZE.xxs,
|
||||||
color: colors.secondary.paragraph,
|
color: colors.secondary.paragraph,
|
||||||
marginRight: 6
|
marginRight: 6
|
||||||
}}
|
}}
|
||||||
@@ -419,11 +393,20 @@ const NoteItem = ({
|
|||||||
</>
|
</>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
|
{selectionMode ? (
|
||||||
|
<>
|
||||||
|
<AppIcon
|
||||||
|
name={selected ? "checkbox-outline" : "checkbox-blank-outline"}
|
||||||
|
color={selected ? colors.selected.icon : colors.primary.icon}
|
||||||
|
size={SIZE.lg}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
<IconButton
|
<IconButton
|
||||||
testID={notesnook.listitem.menu}
|
testID={notesnook.listitem.menu}
|
||||||
color={primaryColors.paragraph}
|
color={colors.secondary.icon}
|
||||||
name="dots-horizontal"
|
name="dots-horizontal"
|
||||||
size={SIZE.xl}
|
size={SIZE.lg}
|
||||||
onPress={() => !noOpen && Properties.present(item)}
|
onPress={() => !noOpen && Properties.present(item)}
|
||||||
style={{
|
style={{
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
@@ -433,6 +416,7 @@ const NoteItem = ({
|
|||||||
alignItems: "center"
|
alignItems: "center"
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
</View>
|
</View>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import {
|
|||||||
presentSheet
|
presentSheet
|
||||||
} from "../../../services/event-manager";
|
} from "../../../services/event-manager";
|
||||||
import { eOnLoadNote, eShowMergeDialog } from "../../../utils/events";
|
import { eOnLoadNote, eShowMergeDialog } from "../../../utils/events";
|
||||||
import { tabBarRef } from "../../../utils/global-refs";
|
import { fluidTabsRef } from "../../../utils/global-refs";
|
||||||
|
|
||||||
import { NotebooksWithDateEdited, TagsWithDateEdited } from "@notesnook/common";
|
import { NotebooksWithDateEdited, TagsWithDateEdited } from "@notesnook/common";
|
||||||
import NotePreview from "../../note-history/preview";
|
import NotePreview from "../../note-history/preview";
|
||||||
@@ -66,7 +66,7 @@ export const openNote = async (
|
|||||||
item: note
|
item: note
|
||||||
});
|
});
|
||||||
if (!DDS.isTab) {
|
if (!DDS.isTab) {
|
||||||
tabBarRef.current?.goToPage(1);
|
fluidTabsRef.current?.goToPage(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -101,6 +101,7 @@ export const NoteWrapper = React.memo<
|
|||||||
onPress={() => openNote(item as Note, isTrash, isRenderedInActionSheet)}
|
onPress={() => openNote(item as Note, isTrash, isRenderedInActionSheet)}
|
||||||
isSheet={isRenderedInActionSheet}
|
isSheet={isRenderedInActionSheet}
|
||||||
item={item}
|
item={item}
|
||||||
|
index={index}
|
||||||
color={restProps.color?.colorCode}
|
color={restProps.color?.colorCode}
|
||||||
>
|
>
|
||||||
<NoteItem {...restProps} item={item} index={index} isTrash={isTrash} />
|
<NoteItem {...restProps} item={item} index={index} isTrash={isTrash} />
|
||||||
|
|||||||
@@ -39,16 +39,15 @@ export const Filler = ({ item, color }: { item: Item; color?: string }) => {
|
|||||||
style={{
|
style={{
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
width: "110%",
|
width: "110%",
|
||||||
height: "150%",
|
height: "100%",
|
||||||
backgroundColor: colors.selected.background,
|
backgroundColor: colors.selected.accent
|
||||||
borderLeftWidth: 5,
|
// borderLeftWidth: 5,
|
||||||
borderLeftColor: isEditingNote
|
// borderLeftColor: isEditingNote
|
||||||
? color
|
// ? color
|
||||||
? color
|
// ? color
|
||||||
: colors.selected.accent
|
// : colors.selected.accent
|
||||||
: "transparent"
|
// : "transparent"
|
||||||
}}
|
}}
|
||||||
collapsable={false}
|
|
||||||
/>
|
/>
|
||||||
) : null;
|
) : null;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,14 +17,14 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Item, TrashItem } from "@notesnook/core";
|
||||||
import { useThemeColors } from "@notesnook/theme";
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
import React, { PropsWithChildren, useRef } from "react";
|
import React, { PropsWithChildren, useRef } from "react";
|
||||||
import { useIsCompactModeEnabled } from "../../../hooks/use-is-compact-mode-enabled";
|
import { useIsCompactModeEnabled } from "../../../hooks/use-is-compact-mode-enabled";
|
||||||
|
import { useTabStore } from "../../../screens/editor/tiptap/use-tab-store";
|
||||||
import { useSelectionStore } from "../../../stores/use-selection-store";
|
import { useSelectionStore } from "../../../stores/use-selection-store";
|
||||||
|
import { DefaultAppStyles } from "../../../utils/styles";
|
||||||
import { Pressable } from "../../ui/pressable";
|
import { Pressable } from "../../ui/pressable";
|
||||||
import { Filler } from "./back-fill";
|
|
||||||
import { SelectionIcon } from "./selection";
|
|
||||||
import { Item, TrashItem } from "@notesnook/core";
|
|
||||||
|
|
||||||
export function selectItem(item: Item) {
|
export function selectItem(item: Item) {
|
||||||
if (useSelectionStore.getState().selectionMode === item.type) {
|
if (useSelectionStore.getState().selectionMode === item.type) {
|
||||||
@@ -49,6 +49,7 @@ type SelectionWrapperProps = PropsWithChildren<{
|
|||||||
testID?: string;
|
testID?: string;
|
||||||
isSheet?: boolean;
|
isSheet?: boolean;
|
||||||
color?: string;
|
color?: string;
|
||||||
|
index?: number;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
const SelectionWrapper = ({
|
const SelectionWrapper = ({
|
||||||
@@ -57,10 +58,16 @@ const SelectionWrapper = ({
|
|||||||
testID,
|
testID,
|
||||||
isSheet,
|
isSheet,
|
||||||
children,
|
children,
|
||||||
color
|
color,
|
||||||
|
index = 0
|
||||||
}: SelectionWrapperProps) => {
|
}: SelectionWrapperProps) => {
|
||||||
const itemId = useRef(item.id);
|
const itemId = useRef(item.id);
|
||||||
const { colors, isDark } = useThemeColors();
|
const { colors, isDark } = useThemeColors();
|
||||||
|
const isEditingNote = useTabStore(
|
||||||
|
(state) =>
|
||||||
|
state.tabs.find((t) => t.id === state.currentTab)?.session?.noteId ===
|
||||||
|
item.id
|
||||||
|
);
|
||||||
const compactMode = useIsCompactModeEnabled(
|
const compactMode = useIsCompactModeEnabled(
|
||||||
(item as TrashItem).itemType || item.type
|
(item as TrashItem).itemType || item.type
|
||||||
);
|
);
|
||||||
@@ -79,7 +86,13 @@ const SelectionWrapper = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Pressable
|
<Pressable
|
||||||
customColor={isSheet ? colors.secondary.background : "transparent"}
|
customColor={
|
||||||
|
isEditingNote
|
||||||
|
? colors.selected.background
|
||||||
|
: isSheet
|
||||||
|
? colors.primary.hover
|
||||||
|
: "transparent"
|
||||||
|
}
|
||||||
testID={testID}
|
testID={testID}
|
||||||
onLongPress={onLongPress}
|
onLongPress={onLongPress}
|
||||||
onPress={onPress}
|
onPress={onPress}
|
||||||
@@ -91,15 +104,14 @@ const SelectionWrapper = ({
|
|||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
width: "100%",
|
width: "100%",
|
||||||
|
alignSelf: "center",
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
paddingHorizontal: 12,
|
paddingHorizontal: DefaultAppStyles.GAP,
|
||||||
paddingVertical: compactMode ? 4 : 12,
|
paddingVertical: compactMode ? 4 : DefaultAppStyles.GAP_VERTICAL,
|
||||||
borderRadius: isSheet ? 10 : 0,
|
borderRadius: isSheet ? 10 : 0,
|
||||||
marginBottom: isSheet ? 12 : undefined
|
marginBottom: isSheet ? 12 : undefined
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{item.type === "note" ? <Filler item={item} color={color} /> : null}
|
|
||||||
<SelectionIcon item={item} />
|
|
||||||
{children}
|
{children}
|
||||||
</Pressable>
|
</Pressable>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -17,13 +17,13 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Dimensions, View } from "react-native";
|
import { Dimensions, View } from "react-native";
|
||||||
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||||
import { useMessageStore } from "../../stores/use-message-store";
|
import { useMessageStore } from "../../stores/use-message-store";
|
||||||
import { useThemeColors } from "@notesnook/theme";
|
|
||||||
import { getContainerBorder, hexToRGBA } from "../../utils/colors";
|
|
||||||
import { SIZE } from "../../utils/size";
|
import { SIZE } from "../../utils/size";
|
||||||
|
import { DefaultAppStyles } from "../../utils/styles";
|
||||||
import { Pressable } from "../ui/pressable";
|
import { Pressable } from "../ui/pressable";
|
||||||
import Paragraph from "../ui/typography/paragraph";
|
import Paragraph from "../ui/typography/paragraph";
|
||||||
|
|
||||||
@@ -38,19 +38,24 @@ export const Card = ({ color }: { color?: string }) => {
|
|||||||
(announcements && announcements.length) ? null : (
|
(announcements && announcements.length) ? null : (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
width: "95%"
|
width: "100%",
|
||||||
|
paddingHorizontal: DefaultAppStyles.GAP,
|
||||||
|
marginTop: DefaultAppStyles.GAP
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Pressable
|
<Pressable
|
||||||
onPress={messageBoardState.onPress}
|
onPress={messageBoardState.onPress}
|
||||||
type="plain"
|
type="plain"
|
||||||
style={{
|
style={{
|
||||||
paddingVertical: 12,
|
paddingVertical: DefaultAppStyles.GAP_VERTICAL,
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
paddingHorizontal: 0,
|
paddingHorizontal: DefaultAppStyles.GAP_SMALL,
|
||||||
width: "100%"
|
width: "100%",
|
||||||
|
backgroundColor: colors.secondary.background,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderColor: colors.primary.border
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View
|
<View
|
||||||
@@ -63,24 +68,14 @@ export const Card = ({ color }: { color?: string }) => {
|
|||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
width: 40 * fontScale,
|
width: 40 * fontScale,
|
||||||
backgroundColor:
|
|
||||||
messageBoardState.type === "error"
|
|
||||||
? hexToRGBA(colors.error.accent, 0.15)
|
|
||||||
: hexToRGBA(color, 0.15),
|
|
||||||
height: 40 * fontScale,
|
height: 40 * fontScale,
|
||||||
borderRadius: 100,
|
borderRadius: 100,
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
justifyContent: "center"
|
||||||
...getContainerBorder(
|
|
||||||
messageBoardState.type === "error"
|
|
||||||
? colors.error.accent
|
|
||||||
: color || colors.primary.accent,
|
|
||||||
0.4
|
|
||||||
)
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
size={SIZE.lg}
|
size={SIZE.xxxl}
|
||||||
color={
|
color={
|
||||||
messageBoardState.type === "error" ? colors.error.icon : color
|
messageBoardState.type === "error" ? colors.error.icon : color
|
||||||
}
|
}
|
||||||
@@ -95,9 +90,6 @@ export const Card = ({ color }: { color?: string }) => {
|
|||||||
marginRight: 10
|
marginRight: 10
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Paragraph color={colors.secondary.paragraph} size={SIZE.xs}>
|
|
||||||
{messageBoardState.message}
|
|
||||||
</Paragraph>
|
|
||||||
<Paragraph
|
<Paragraph
|
||||||
style={{
|
style={{
|
||||||
flexWrap: "nowrap",
|
flexWrap: "nowrap",
|
||||||
@@ -107,6 +99,9 @@ export const Card = ({ color }: { color?: string }) => {
|
|||||||
>
|
>
|
||||||
{messageBoardState.actionText}
|
{messageBoardState.actionText}
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
|
<Paragraph color={colors.secondary.paragraph} size={SIZE.xxs}>
|
||||||
|
{messageBoardState.message}
|
||||||
|
</Paragraph>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,7 @@ import Sync from "../../services/sync";
|
|||||||
import { RouteName } from "../../stores/use-navigation-store";
|
import { RouteName } from "../../stores/use-navigation-store";
|
||||||
import { useSettingStore } from "../../stores/use-setting-store";
|
import { useSettingStore } from "../../stores/use-setting-store";
|
||||||
import { eScrollEvent } from "../../utils/events";
|
import { eScrollEvent } from "../../utils/events";
|
||||||
import { tabBarRef } from "../../utils/global-refs";
|
import { fluidTabsRef } from "../../utils/global-refs";
|
||||||
import { Footer } from "../list-items/footer";
|
|
||||||
import { Header } from "../list-items/headers/header";
|
import { Header } from "../list-items/headers/header";
|
||||||
import { Empty, PlaceholderData } from "./empty";
|
import { Empty, PlaceholderData } from "./empty";
|
||||||
import { ListItemWrapper } from "./list-item.wrapper";
|
import { ListItemWrapper } from "./list-item.wrapper";
|
||||||
@@ -43,6 +42,7 @@ import { ListItemWrapper } from "./list-item.wrapper";
|
|||||||
type ListProps = {
|
type ListProps = {
|
||||||
data: VirtualizedGrouping<Item> | undefined;
|
data: VirtualizedGrouping<Item> | undefined;
|
||||||
dataType: Item["type"];
|
dataType: Item["type"];
|
||||||
|
mode?: "drawer" | "sheet";
|
||||||
onRefresh?: () => void;
|
onRefresh?: () => void;
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
headerTitle?: string;
|
headerTitle?: string;
|
||||||
@@ -160,7 +160,7 @@ export default function List(props: ListProps) {
|
|||||||
onScroll={onListScroll}
|
onScroll={onListScroll}
|
||||||
nestedScrollEnabled={true}
|
nestedScrollEnabled={true}
|
||||||
onMomentumScrollEnd={() => {
|
onMomentumScrollEnd={() => {
|
||||||
tabBarRef.current?.unlock();
|
fluidTabsRef.current?.unlock();
|
||||||
}}
|
}}
|
||||||
getItemType={(item: number, index: number) => {
|
getItemType={(item: number, index: number) => {
|
||||||
return props.data?.type(index);
|
return props.data?.type(index);
|
||||||
@@ -192,9 +192,6 @@ export default function List(props: ListProps) {
|
|||||||
/>
|
/>
|
||||||
) : null
|
) : null
|
||||||
}
|
}
|
||||||
ListFooterComponent={
|
|
||||||
<Footer height={props.renderedInRoute === "Notebook" ? 300 : 150} />
|
|
||||||
}
|
|
||||||
ListHeaderComponent={
|
ListHeaderComponent={
|
||||||
<>
|
<>
|
||||||
{props.CustomLisHeader ? (
|
{props.CustomLisHeader ? (
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import {
|
|||||||
DraxListRenderItemContent
|
DraxListRenderItemContent
|
||||||
} from "react-native-drax";
|
} from "react-native-drax";
|
||||||
|
|
||||||
import { tabBarRef } from "../../utils/global-refs";
|
import { fluidTabsRef } from "../../utils/global-refs";
|
||||||
import { SIZE } from "../../utils/size";
|
import { SIZE } from "../../utils/size";
|
||||||
import { useSideBarDraggingStore } from "../side-menu/dragging-store";
|
import { useSideBarDraggingStore } from "../side-menu/dragging-store";
|
||||||
import { IconButton } from "../ui/icon-button";
|
import { IconButton } from "../ui/icon-button";
|
||||||
@@ -61,9 +61,9 @@ function ReorderableList<T extends { id: string }>({
|
|||||||
const listRef = useRef<FlatList | null>(null);
|
const listRef = useRef<FlatList | null>(null);
|
||||||
|
|
||||||
if (dragging) {
|
if (dragging) {
|
||||||
tabBarRef.current?.lock();
|
fluidTabsRef.current?.lock();
|
||||||
} else {
|
} else {
|
||||||
tabBarRef.current?.unlock();
|
fluidTabsRef.current?.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -78,8 +78,7 @@ function ReorderableList<T extends { id: string }>({
|
|||||||
return isHidden && !dragging ? null : (
|
return isHidden && !dragging ? null : (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
flexDirection: "row",
|
flexDirection: "row"
|
||||||
paddingHorizontal: 12
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View
|
<View
|
||||||
|
|||||||
@@ -16,18 +16,19 @@ GNU General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
import { strings } from "@notesnook/intl";
|
||||||
import { useThemeColors } from "@notesnook/theme";
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Platform, View } from "react-native";
|
import { View } from "react-native";
|
||||||
import { FlatList } from "react-native-actions-sheet";
|
import { FlatList } from "react-native-actions-sheet";
|
||||||
import { db } from "../../common/database";
|
import { db } from "../../common/database";
|
||||||
import { DDS } from "../../services/device-detection";
|
import { DDS } from "../../services/device-detection";
|
||||||
import { eSendEvent, presentSheet } from "../../services/event-manager";
|
import { eSendEvent, presentSheet } from "../../services/event-manager";
|
||||||
import { ColorValues } from "../../utils/colors";
|
import { ColorValues } from "../../utils/colors";
|
||||||
import { eOnLoadNote } from "../../utils/events";
|
import { eOnLoadNote } from "../../utils/events";
|
||||||
|
import { fluidTabsRef } from "../../utils/global-refs";
|
||||||
import { SIZE } from "../../utils/size";
|
import { SIZE } from "../../utils/size";
|
||||||
import SheetProvider from "../sheet-provider";
|
import SheetProvider from "../sheet-provider";
|
||||||
import { useSideBarDraggingStore } from "../side-menu/dragging-store";
|
|
||||||
import { IconButton } from "../ui/icon-button";
|
import { IconButton } from "../ui/icon-button";
|
||||||
import { Pressable } from "../ui/pressable";
|
import { Pressable } from "../ui/pressable";
|
||||||
import { ReminderTime } from "../ui/reminder-time";
|
import { ReminderTime } from "../ui/reminder-time";
|
||||||
@@ -36,10 +37,8 @@ import Paragraph from "../ui/typography/paragraph";
|
|||||||
import { DateMeta } from "./date-meta";
|
import { DateMeta } from "./date-meta";
|
||||||
import { Items } from "./items";
|
import { Items } from "./items";
|
||||||
import Notebooks from "./notebooks";
|
import Notebooks from "./notebooks";
|
||||||
import { Synced } from "./synced";
|
|
||||||
import { TagStrip, Tags } from "./tags";
|
import { TagStrip, Tags } from "./tags";
|
||||||
import { tabBarRef } from "../../utils/global-refs";
|
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||||
import { strings } from "@notesnook/intl";
|
|
||||||
|
|
||||||
const Line = ({ top = 6, bottom = 6 }) => {
|
const Line = ({ top = 6, bottom = 6 }) => {
|
||||||
const { colors } = useThemeColors();
|
const { colors } = useThemeColors();
|
||||||
@@ -101,7 +100,8 @@ export const Properties = ({ close = () => {}, item, buttons = [] }) => {
|
|||||||
style={{
|
style={{
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
flexShrink: 1
|
flexShrink: 1,
|
||||||
|
gap: 5
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{item.type === "color" ? (
|
{item.type === "color" ? (
|
||||||
@@ -116,16 +116,15 @@ export const Properties = ({ close = () => {}, item, buttons = [] }) => {
|
|||||||
marginRight: 10
|
marginRight: 10
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
) : item.type === "tag" ? (
|
||||||
|
<Icon
|
||||||
|
name="pound"
|
||||||
|
size={SIZE.lg}
|
||||||
|
color={colors.primary.icon}
|
||||||
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<Heading size={SIZE.lg}>
|
<Heading size={SIZE.lg}>{item.title}</Heading>
|
||||||
{item.type === "tag" && !isColor ? (
|
|
||||||
<Heading size={SIZE.xl} color={colors.primary.accent}>
|
|
||||||
#
|
|
||||||
</Heading>
|
|
||||||
) : null}
|
|
||||||
{item.title}
|
|
||||||
</Heading>
|
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{item.type === "note" ? (
|
{item.type === "note" ? (
|
||||||
@@ -144,7 +143,7 @@ export const Properties = ({ close = () => {}, item, buttons = [] }) => {
|
|||||||
newTab: true
|
newTab: true
|
||||||
});
|
});
|
||||||
if (!DDS.isTab) {
|
if (!DDS.isTab) {
|
||||||
tabBarRef.current?.goToPage(1);
|
fluidTabsRef.current?.goToPage(1);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@@ -202,8 +201,6 @@ export const Properties = ({ close = () => {}, item, buttons = [] }) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Synced item={item} close={close} />
|
|
||||||
|
|
||||||
{DDS.isTab ? (
|
{DDS.isTab ? (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
@@ -218,87 +215,36 @@ export const Properties = ({ close = () => {}, item, buttons = [] }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
Properties.present = async (item, buttons = [], isSheet) => {
|
Properties.present = async (item, isSheet) => {
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
let type = item?.type;
|
let type = item?.type;
|
||||||
let props = [];
|
let dbItem;
|
||||||
let android = [];
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "trash":
|
case "trash":
|
||||||
props[0] = item;
|
dbItem = item;
|
||||||
props.push(["delete", "restore"]);
|
|
||||||
break;
|
break;
|
||||||
case "note":
|
case "note":
|
||||||
android = Platform.OS === "android" ? ["pin-to-notifications"] : [];
|
dbItem = await db.notes.note(item.id);
|
||||||
props[0] = await db.notes.note(item.id);
|
|
||||||
props.push([
|
|
||||||
"notebooks",
|
|
||||||
"add-reminder",
|
|
||||||
"share",
|
|
||||||
"export",
|
|
||||||
"copy",
|
|
||||||
"publish",
|
|
||||||
"pin",
|
|
||||||
"favorite",
|
|
||||||
"attachments",
|
|
||||||
"lock-unlock",
|
|
||||||
"trash",
|
|
||||||
"remove-from-notebook",
|
|
||||||
"history",
|
|
||||||
"read-only",
|
|
||||||
"reminders",
|
|
||||||
"local-only",
|
|
||||||
"duplicate",
|
|
||||||
"copy-link",
|
|
||||||
"references",
|
|
||||||
...android,
|
|
||||||
...buttons
|
|
||||||
]);
|
|
||||||
break;
|
break;
|
||||||
case "notebook":
|
case "notebook":
|
||||||
props[0] = await db.notebooks.notebook(item.id);
|
dbItem = await db.notebooks.notebook(item.id);
|
||||||
props.push([
|
|
||||||
"edit-notebook",
|
|
||||||
"pin",
|
|
||||||
"add-shortcut",
|
|
||||||
"trash",
|
|
||||||
"default-notebook",
|
|
||||||
"add-notebook",
|
|
||||||
"move-notes",
|
|
||||||
"move-notebook"
|
|
||||||
]);
|
|
||||||
break;
|
break;
|
||||||
case "tag":
|
case "tag":
|
||||||
props[0] = await db.tags.tag(item.id);
|
dbItem = await db.tags.tag(item.id);
|
||||||
props.push(["add-shortcut", "trash", "rename-tag"]);
|
|
||||||
break;
|
break;
|
||||||
case "color":
|
case "color":
|
||||||
props[0] = await db.colors.color(item.id);
|
dbItem = await db.colors.color(item.id);
|
||||||
|
|
||||||
props.push([
|
|
||||||
"trash",
|
|
||||||
"rename-color",
|
|
||||||
...(useSideBarDraggingStore.getState().dragging ? [] : ["reorder"])
|
|
||||||
]);
|
|
||||||
break;
|
break;
|
||||||
case "reminder": {
|
case "reminder": {
|
||||||
props[0] = await db.reminders.reminder(item.id);
|
dbItem = await db.reminders.reminder(item.id);
|
||||||
props.push(["edit-reminder", "trash", "disable-reminder"]);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!props[0]) return;
|
|
||||||
presentSheet({
|
presentSheet({
|
||||||
context: isSheet ? "local" : undefined,
|
context: isSheet ? "local" : undefined,
|
||||||
component: (ref, close) => (
|
component: (ref, close) => (
|
||||||
<Properties
|
<Properties close={close} actionSheetRef={ref} item={dbItem} />
|
||||||
close={() => {
|
|
||||||
close();
|
|
||||||
}}
|
|
||||||
actionSheetRef={ref}
|
|
||||||
item={props[0]}
|
|
||||||
buttons={props[1]}
|
|
||||||
/>
|
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,266 +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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { useThemeColors } from "@notesnook/theme";
|
|
||||||
import React from "react";
|
|
||||||
import { Dimensions, ScrollView, View } from "react-native";
|
|
||||||
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
|
||||||
import { useActions } from "../../hooks/use-actions";
|
|
||||||
import { useStoredRef } from "../../hooks/use-stored-ref";
|
|
||||||
import { DDS } from "../../services/device-detection";
|
|
||||||
import { useSettingStore } from "../../stores/use-setting-store";
|
|
||||||
import { SIZE } from "../../utils/size";
|
|
||||||
import { Button } from "../ui/button";
|
|
||||||
import { Pressable } from "../ui/pressable";
|
|
||||||
import Paragraph from "../ui/typography/paragraph";
|
|
||||||
|
|
||||||
export const Items = ({ item, buttons, close }) => {
|
|
||||||
const { colors } = useThemeColors();
|
|
||||||
const topBarSorting = useStoredRef("topbar-sorting-ref", {});
|
|
||||||
|
|
||||||
const dimensions = useSettingStore((state) => state.dimensions);
|
|
||||||
const actions = useActions({ item, close });
|
|
||||||
const data = actions.filter((i) => buttons.indexOf(i.id) > -1 && !i.hidden);
|
|
||||||
let width = dimensions.width > 600 ? 600 : dimensions.width;
|
|
||||||
const shouldShrink =
|
|
||||||
Dimensions.get("window").fontScale > 1 &&
|
|
||||||
Dimensions.get("window").width < 450;
|
|
||||||
let columnItemsCount = DDS.isLargeTablet() ? 7 : shouldShrink ? 4 : 5;
|
|
||||||
let columnItemWidth = DDS.isTab
|
|
||||||
? (width - 12) / columnItemsCount
|
|
||||||
: (width - 12) / columnItemsCount;
|
|
||||||
|
|
||||||
const _renderRowItem = ({ item }) => (
|
|
||||||
<View
|
|
||||||
key={item.id}
|
|
||||||
testID={"icon-" + item.id}
|
|
||||||
style={{
|
|
||||||
alignItems: "center",
|
|
||||||
width: columnItemWidth,
|
|
||||||
marginBottom: 10
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Pressable
|
|
||||||
onPress={item.func}
|
|
||||||
type={item.on ? "shade" : "secondary"}
|
|
||||||
style={{
|
|
||||||
height: columnItemWidth - 12,
|
|
||||||
width: columnItemWidth - 12,
|
|
||||||
borderRadius: 10,
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
textAlign: "center",
|
|
||||||
textAlignVertical: "center",
|
|
||||||
marginBottom: DDS.isTab ? 7 : 3.5
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
allowFontScaling
|
|
||||||
name={item.icon}
|
|
||||||
size={DDS.isTab ? SIZE.xxl : shouldShrink ? SIZE.xxl : SIZE.lg}
|
|
||||||
color={
|
|
||||||
item.on
|
|
||||||
? colors.primary.accent
|
|
||||||
: item.id.match(/(delete|trash)/g)
|
|
||||||
? colors.error.icon
|
|
||||||
: colors.secondary.icon
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Pressable>
|
|
||||||
|
|
||||||
<Paragraph
|
|
||||||
size={SIZE.xs}
|
|
||||||
textBreakStrategy="simple"
|
|
||||||
style={{ textAlign: "center" }}
|
|
||||||
>
|
|
||||||
{item.title}
|
|
||||||
</Paragraph>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
|
|
||||||
const renderColumnItem = (item) => (
|
|
||||||
<Button
|
|
||||||
key={item.name + item.title}
|
|
||||||
buttonType={{
|
|
||||||
text: item.on
|
|
||||||
? colors.primary.accent
|
|
||||||
: item.name === "Delete" || item.name === "PermDelete"
|
|
||||||
? colors.error.paragraph
|
|
||||||
: colors.primary.paragraph
|
|
||||||
}}
|
|
||||||
onPress={item.func}
|
|
||||||
title={item.title}
|
|
||||||
icon={item.icon}
|
|
||||||
type={item.on ? "shade" : "plain"}
|
|
||||||
fontSize={SIZE.sm}
|
|
||||||
style={{
|
|
||||||
borderRadius: 0,
|
|
||||||
justifyContent: "flex-start",
|
|
||||||
alignSelf: "flex-start",
|
|
||||||
width: "100%"
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
const renderTopBarItem = (item, index) => {
|
|
||||||
return (
|
|
||||||
<Pressable
|
|
||||||
onPress={() => {
|
|
||||||
item.func();
|
|
||||||
setImmediate(() => {
|
|
||||||
const currentValue = topBarSorting.current[item.id] || 0;
|
|
||||||
topBarSorting.current = {
|
|
||||||
...topBarSorting.current,
|
|
||||||
[item.id]: currentValue + 1
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
key={item.id}
|
|
||||||
testID={"icon-" + item.id}
|
|
||||||
activeOpacity={1}
|
|
||||||
style={{
|
|
||||||
alignSelf: "flex-start",
|
|
||||||
paddingHorizontal: 0,
|
|
||||||
flex: 1
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
onPress={item.func}
|
|
||||||
style={{
|
|
||||||
height: topBarItemWidth,
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
textAlign: "center",
|
|
||||||
textAlignVertical: "center",
|
|
||||||
marginBottom: DDS.isTab ? 7 : 3.5,
|
|
||||||
borderRadius: 100
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
name={item.icon}
|
|
||||||
allowFontScaling
|
|
||||||
size={DDS.isTab ? SIZE.xxl : SIZE.md + 4}
|
|
||||||
color={
|
|
||||||
item.on
|
|
||||||
? colors.primary.accent
|
|
||||||
: item.name === "Delete" || item.name === "PermDelete"
|
|
||||||
? colors.error.icon
|
|
||||||
: colors.secondary.icon
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<Paragraph
|
|
||||||
textBreakStrategy="simple"
|
|
||||||
size={SIZE.xxs}
|
|
||||||
style={{ textAlign: "center" }}
|
|
||||||
>
|
|
||||||
{item.title}
|
|
||||||
</Paragraph>
|
|
||||||
</Pressable>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const topBarItemsList = [
|
|
||||||
"pin",
|
|
||||||
"favorite",
|
|
||||||
"copy",
|
|
||||||
"share",
|
|
||||||
"lock-unlock",
|
|
||||||
"publish",
|
|
||||||
"export",
|
|
||||||
"copy-link",
|
|
||||||
"duplicate",
|
|
||||||
"local-only",
|
|
||||||
"read-only"
|
|
||||||
];
|
|
||||||
|
|
||||||
const bottomBarItemsList = [
|
|
||||||
"notebooks",
|
|
||||||
"add-reminder",
|
|
||||||
"pin-to-notifications",
|
|
||||||
"history",
|
|
||||||
"reminders",
|
|
||||||
"attachments",
|
|
||||||
"references",
|
|
||||||
"trash"
|
|
||||||
];
|
|
||||||
|
|
||||||
const topBarItems = data
|
|
||||||
.filter((item) => topBarItemsList.indexOf(item.id) > -1)
|
|
||||||
.sort((a, b) =>
|
|
||||||
topBarItemsList.indexOf(a.id) > topBarItemsList.indexOf(b.id) ? 1 : -1
|
|
||||||
)
|
|
||||||
.sort((a, b) => {
|
|
||||||
return (
|
|
||||||
(topBarSorting.current[b.id] || 0) - (topBarSorting.current[a.id] || 0)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const bottomGridItems = data
|
|
||||||
.filter((item) => bottomBarItemsList.indexOf(item.id) > -1)
|
|
||||||
.sort((a, b) =>
|
|
||||||
bottomBarItemsList.indexOf(a.id) > bottomBarItemsList.indexOf(b.id)
|
|
||||||
? 1
|
|
||||||
: -1
|
|
||||||
);
|
|
||||||
|
|
||||||
let topBarItemWidth =
|
|
||||||
(width - (topBarItems.length * 10 + 14)) / topBarItems.length;
|
|
||||||
topBarItemWidth;
|
|
||||||
|
|
||||||
if (topBarItemWidth < 60) {
|
|
||||||
topBarItemWidth = 60;
|
|
||||||
}
|
|
||||||
|
|
||||||
return item.type === "note" ? (
|
|
||||||
<>
|
|
||||||
<ScrollView
|
|
||||||
horizontal
|
|
||||||
style={{
|
|
||||||
paddingHorizontal: 12,
|
|
||||||
marginTop: 6,
|
|
||||||
marginBottom: 6
|
|
||||||
}}
|
|
||||||
showsHorizontalScrollIndicator={false}
|
|
||||||
contentContainerStyle={{
|
|
||||||
paddingRight: 25,
|
|
||||||
gap: 15
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{topBarItems.map(renderTopBarItem)}
|
|
||||||
</ScrollView>
|
|
||||||
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
flexDirection: "row",
|
|
||||||
flexWrap: "wrap",
|
|
||||||
alignContent: "flex-start",
|
|
||||||
marginTop: item.type !== "note" ? 10 : 0,
|
|
||||||
paddingTop: 10,
|
|
||||||
marginLeft: 6
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{bottomGridItems.map((item) => _renderRowItem({ item }))}
|
|
||||||
</View>
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<View data={data}>{data.map(renderColumnItem)}</View>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
301
apps/mobile/app/components/properties/items.tsx
Normal file
301
apps/mobile/app/components/properties/items.tsx
Normal file
@@ -0,0 +1,301 @@
|
|||||||
|
/*
|
||||||
|
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 { Item } from "@notesnook/core";
|
||||||
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
|
import React from "react";
|
||||||
|
import { Dimensions, ScrollView, View } from "react-native";
|
||||||
|
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||||
|
import { Action, ActionId, useActions } from "../../hooks/use-actions";
|
||||||
|
import { useStoredRef } from "../../hooks/use-stored-ref";
|
||||||
|
import { DDS } from "../../services/device-detection";
|
||||||
|
import { useSettingStore } from "../../stores/use-setting-store";
|
||||||
|
import { SIZE } from "../../utils/size";
|
||||||
|
import { DefaultAppStyles } from "../../utils/styles";
|
||||||
|
import { Button } from "../ui/button";
|
||||||
|
import { Pressable } from "../ui/pressable";
|
||||||
|
import Paragraph from "../ui/typography/paragraph";
|
||||||
|
|
||||||
|
const TOP_BAR_ITEMS: ActionId[] = [
|
||||||
|
"pin",
|
||||||
|
"favorite",
|
||||||
|
"copy",
|
||||||
|
"share",
|
||||||
|
"lock-unlock",
|
||||||
|
"publish",
|
||||||
|
"export",
|
||||||
|
"copy-link",
|
||||||
|
"duplicate",
|
||||||
|
"local-only",
|
||||||
|
"read-only"
|
||||||
|
];
|
||||||
|
|
||||||
|
const BOTTOM_BAR_ITEMS: ActionId[] = [
|
||||||
|
"notebooks",
|
||||||
|
"add-reminder",
|
||||||
|
"pin-to-notifications",
|
||||||
|
"history",
|
||||||
|
"reminders",
|
||||||
|
"attachments",
|
||||||
|
"references",
|
||||||
|
"trash"
|
||||||
|
];
|
||||||
|
|
||||||
|
const COLUMN_BAR_ITEMS: ActionId[] = [
|
||||||
|
"select",
|
||||||
|
"add-notebook",
|
||||||
|
"edit-notebook",
|
||||||
|
"move-notes",
|
||||||
|
"move-notebook",
|
||||||
|
"pin",
|
||||||
|
"default-notebook",
|
||||||
|
"add-shortcut",
|
||||||
|
"trash"
|
||||||
|
];
|
||||||
|
|
||||||
|
export const Items = ({ item, close }: { item: Item; close: () => void }) => {
|
||||||
|
const { colors } = useThemeColors();
|
||||||
|
const topBarSorting = useStoredRef<{ [name: string]: number }>(
|
||||||
|
"topbar-sorting-ref",
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
const dimensions = useSettingStore((state) => state.dimensions);
|
||||||
|
const actions = useActions({ item, close });
|
||||||
|
const selectedActions = actions.filter((i) => !i.hidden);
|
||||||
|
const deviceMode = useSettingStore((state) => state.deviceMode);
|
||||||
|
const width = Math.min(dimensions.width, 600);
|
||||||
|
|
||||||
|
const shouldShrink =
|
||||||
|
Dimensions.get("window").fontScale > 1 &&
|
||||||
|
Dimensions.get("window").width < 450;
|
||||||
|
|
||||||
|
const columnItemsCount = deviceMode === "tablet" ? 7 : shouldShrink ? 4 : 5;
|
||||||
|
|
||||||
|
const columnItemWidth =
|
||||||
|
deviceMode !== "mobile"
|
||||||
|
? (width - 16) / columnItemsCount
|
||||||
|
: (width - 16) / columnItemsCount;
|
||||||
|
|
||||||
|
const topBarItems = selectedActions
|
||||||
|
.filter((item) => TOP_BAR_ITEMS.indexOf(item.id) > -1)
|
||||||
|
.sort((a, b) =>
|
||||||
|
TOP_BAR_ITEMS.indexOf(a.id) > TOP_BAR_ITEMS.indexOf(b.id) ? 1 : -1
|
||||||
|
)
|
||||||
|
.sort((a, b) => {
|
||||||
|
return (
|
||||||
|
(topBarSorting.current[b.id] || 0) - (topBarSorting.current[a.id] || 0)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
const bottomGridItems = selectedActions
|
||||||
|
.filter((item) => BOTTOM_BAR_ITEMS.indexOf(item.id) > -1)
|
||||||
|
.sort((a, b) =>
|
||||||
|
BOTTOM_BAR_ITEMS.indexOf(a.id) > BOTTOM_BAR_ITEMS.indexOf(b.id) ? 1 : -1
|
||||||
|
);
|
||||||
|
|
||||||
|
const columnItems = selectedActions
|
||||||
|
.filter((item) => COLUMN_BAR_ITEMS.indexOf(item.id) > -1)
|
||||||
|
.sort((a, b) =>
|
||||||
|
COLUMN_BAR_ITEMS.indexOf(a.id) > COLUMN_BAR_ITEMS.indexOf(b.id) ? 1 : -1
|
||||||
|
);
|
||||||
|
|
||||||
|
const topBarItemHeight = Math.min(
|
||||||
|
(width - (topBarItems.length * 10 + 14)) / topBarItems.length,
|
||||||
|
60
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderRowItem = React.useCallback(
|
||||||
|
({ item }: { item: Action }) => (
|
||||||
|
<View
|
||||||
|
key={item.id}
|
||||||
|
testID={"icon-" + item.id}
|
||||||
|
style={{
|
||||||
|
alignItems: "center",
|
||||||
|
width: columnItemWidth - 8
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Pressable
|
||||||
|
onPress={item.onPress}
|
||||||
|
type={item.checked ? "shade" : "secondary"}
|
||||||
|
style={{
|
||||||
|
height: columnItemWidth - 8,
|
||||||
|
width: columnItemWidth - 8,
|
||||||
|
borderRadius: 10,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: DDS.isTab ? 7 : 3.5
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
allowFontScaling
|
||||||
|
name={item.icon}
|
||||||
|
size={DDS.isTab ? SIZE.xxl : shouldShrink ? SIZE.xxl : SIZE.lg}
|
||||||
|
color={
|
||||||
|
item.checked
|
||||||
|
? item.activeColor || colors.primary.accent
|
||||||
|
: item.id.match(/(delete|trash)/g)
|
||||||
|
? colors.error.icon
|
||||||
|
: colors.secondary.icon
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Pressable>
|
||||||
|
|
||||||
|
<Paragraph
|
||||||
|
size={SIZE.xxs}
|
||||||
|
textBreakStrategy="simple"
|
||||||
|
style={{ textAlign: "center" }}
|
||||||
|
>
|
||||||
|
{item.title}
|
||||||
|
</Paragraph>
|
||||||
|
</View>
|
||||||
|
),
|
||||||
|
[
|
||||||
|
colors.error.icon,
|
||||||
|
colors.primary.accent,
|
||||||
|
colors.secondary.icon,
|
||||||
|
columnItemWidth,
|
||||||
|
shouldShrink
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderColumnItem = React.useCallback(
|
||||||
|
(item: Action) => (
|
||||||
|
<Button
|
||||||
|
key={item.id}
|
||||||
|
buttonType={{
|
||||||
|
text: item.checked
|
||||||
|
? item.activeColor || colors.primary.accent
|
||||||
|
: item.id === "delete" || item.id === "trash"
|
||||||
|
? colors.error.paragraph
|
||||||
|
: colors.primary.paragraph
|
||||||
|
}}
|
||||||
|
onPress={item.onPress}
|
||||||
|
title={item.title}
|
||||||
|
icon={item.icon}
|
||||||
|
type={item.checked ? "inverted" : "plain"}
|
||||||
|
fontSize={SIZE.sm}
|
||||||
|
style={{
|
||||||
|
borderRadius: 0,
|
||||||
|
justifyContent: "flex-start",
|
||||||
|
alignSelf: "flex-start",
|
||||||
|
width: "100%"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
[colors.error.paragraph, colors.primary.accent, colors.primary.paragraph]
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderTopBarItem = React.useCallback(
|
||||||
|
(item: Action) => {
|
||||||
|
return (
|
||||||
|
<Pressable
|
||||||
|
onPress={() => {
|
||||||
|
item.onPress();
|
||||||
|
setImmediate(() => {
|
||||||
|
const currentValue = topBarSorting.current[item.id] || 0;
|
||||||
|
topBarSorting.current = {
|
||||||
|
...topBarSorting.current,
|
||||||
|
[item.id]: currentValue + 1
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
key={item.id}
|
||||||
|
testID={"icon-" + item.id}
|
||||||
|
style={{
|
||||||
|
alignSelf: "flex-start",
|
||||||
|
paddingHorizontal: 0,
|
||||||
|
flex: 1
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
height: topBarItemHeight,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: DDS.isTab ? 7 : 3.5,
|
||||||
|
borderRadius: 100
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
name={item.icon}
|
||||||
|
allowFontScaling
|
||||||
|
size={DDS.isTab ? SIZE.xxl : SIZE.md + 4}
|
||||||
|
color={
|
||||||
|
item.checked
|
||||||
|
? item.activeColor || colors.primary.accent
|
||||||
|
: item.id === "delete" || item.id === "trash"
|
||||||
|
? colors.error.icon
|
||||||
|
: colors.secondary.icon
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Paragraph
|
||||||
|
textBreakStrategy="simple"
|
||||||
|
size={SIZE.xxs}
|
||||||
|
style={{ textAlign: "center" }}
|
||||||
|
>
|
||||||
|
{item.title}
|
||||||
|
</Paragraph>
|
||||||
|
</Pressable>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[
|
||||||
|
colors.error.icon,
|
||||||
|
colors.primary.accent,
|
||||||
|
colors.secondary.icon,
|
||||||
|
topBarItemHeight,
|
||||||
|
topBarSorting
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
return item.type === "note" ? (
|
||||||
|
<>
|
||||||
|
<ScrollView
|
||||||
|
horizontal
|
||||||
|
style={{
|
||||||
|
paddingHorizontal: 16,
|
||||||
|
marginTop: 6,
|
||||||
|
marginBottom: 6
|
||||||
|
}}
|
||||||
|
showsHorizontalScrollIndicator={false}
|
||||||
|
contentContainerStyle={{
|
||||||
|
paddingRight: 25,
|
||||||
|
gap: 15
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{topBarItems.map(renderTopBarItem)}
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
marginTop: 10,
|
||||||
|
gap: 5,
|
||||||
|
paddingHorizontal: DefaultAppStyles.GAP
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{bottomGridItems.map((item) => renderRowItem({ item }))}
|
||||||
|
</View>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<View>{columnItems.map(renderColumnItem)}</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -19,75 +19,32 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
import { useThemeColors } from "@notesnook/theme";
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { View, useWindowDimensions } from "react-native";
|
|
||||||
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
|
||||||
import { useUserStore } from "../../stores/use-user-store";
|
import { useUserStore } from "../../stores/use-user-store";
|
||||||
import { openLinkInBrowser } from "../../utils/functions";
|
import { openLinkInBrowser } from "../../utils/functions";
|
||||||
import { SIZE } from "../../utils/size";
|
import { SIZE } from "../../utils/size";
|
||||||
|
import { DefaultAppStyles } from "../../utils/styles";
|
||||||
import { sleep } from "../../utils/time";
|
import { sleep } from "../../utils/time";
|
||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
import Heading from "../ui/typography/heading";
|
|
||||||
import Paragraph from "../ui/typography/paragraph";
|
|
||||||
import { strings } from "@notesnook/intl";
|
|
||||||
export const Synced = ({ item, close }) => {
|
export const Synced = ({ item, close }) => {
|
||||||
const { colors } = useThemeColors();
|
const { colors } = useThemeColors();
|
||||||
const user = useUserStore((state) => state.user);
|
const user = useUserStore((state) => state.user);
|
||||||
const lastSynced = useUserStore((state) => state.lastSynced);
|
const lastSynced = useUserStore((state) => state.lastSynced);
|
||||||
|
|
||||||
const dimensions = useWindowDimensions();
|
|
||||||
const shouldShrink = dimensions.fontScale > 1 && dimensions.width < 450;
|
|
||||||
return user && lastSynced >= item.dateModified ? (
|
return user && lastSynced >= item.dateModified ? (
|
||||||
<View
|
<Button
|
||||||
style={{
|
style={{
|
||||||
paddingVertical: 0,
|
|
||||||
width: "100%",
|
|
||||||
paddingHorizontal: 12,
|
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
justifyContent: "flex-start",
|
justifyContent: "flex-start",
|
||||||
alignSelf: "center",
|
alignSelf: "flex-start",
|
||||||
paddingTop: 10,
|
height: "auto",
|
||||||
marginTop: 10,
|
padding: DefaultAppStyles.GAP_VERTICAL_SMALL,
|
||||||
borderTopWidth: 1,
|
paddingHorizontal: DefaultAppStyles.GAP_SMALL
|
||||||
borderTopColor: colors.primary.border
|
|
||||||
}}
|
}}
|
||||||
>
|
fontSize={SIZE.xxxs}
|
||||||
<Icon
|
iconSize={SIZE.xs}
|
||||||
name="shield-key-outline"
|
icon="shield-key-outline"
|
||||||
color={colors.primary.accent}
|
type="shade"
|
||||||
size={shouldShrink ? SIZE.xxl : SIZE.xxxl}
|
title="Encrypted and synced"
|
||||||
/>
|
|
||||||
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
flex: 1,
|
|
||||||
marginLeft: 5,
|
|
||||||
flexShrink: 1
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Heading
|
|
||||||
color={colors.primary.heading}
|
|
||||||
size={SIZE.xs}
|
|
||||||
style={{
|
|
||||||
flexWrap: "wrap"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{strings.noteSyncedNoticeHeading()}
|
|
||||||
</Heading>
|
|
||||||
{shouldShrink ? null : (
|
|
||||||
<Paragraph
|
|
||||||
style={{
|
|
||||||
flexWrap: "wrap"
|
|
||||||
}}
|
|
||||||
size={SIZE.xs}
|
|
||||||
color={colors.primary.paragraph}
|
|
||||||
>
|
|
||||||
{strings.noteSyncedNoticeDesc(item.itemType || item.type)}
|
|
||||||
</Paragraph>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<Button
|
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
try {
|
try {
|
||||||
close();
|
close();
|
||||||
@@ -100,11 +57,6 @@ export const Synced = ({ item, close }) => {
|
|||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
title={strings.learnMore()}
|
|
||||||
fontSize={SIZE.xs}
|
|
||||||
height={30}
|
|
||||||
type="secondaryAccented"
|
|
||||||
/>
|
/>
|
||||||
</View>
|
|
||||||
) : null;
|
) : null;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,18 +35,17 @@ import Navigation from "../../services/navigation";
|
|||||||
import useNavigationStore from "../../stores/use-navigation-store";
|
import useNavigationStore from "../../stores/use-navigation-store";
|
||||||
import { useSelectionStore } from "../../stores/use-selection-store";
|
import { useSelectionStore } from "../../stores/use-selection-store";
|
||||||
import { deleteItems } from "../../utils/functions";
|
import { deleteItems } from "../../utils/functions";
|
||||||
import { tabBarRef } from "../../utils/global-refs";
|
import { fluidTabsRef } from "../../utils/global-refs";
|
||||||
import { updateNotebook } from "../../utils/notebooks";
|
import { updateNotebook } from "../../utils/notebooks";
|
||||||
import { SIZE } from "../../utils/size";
|
import { SIZE } from "../../utils/size";
|
||||||
|
import { DefaultAppStyles } from "../../utils/styles";
|
||||||
import { sleep } from "../../utils/time";
|
import { sleep } from "../../utils/time";
|
||||||
import { presentDialog } from "../dialog/functions";
|
import { presentDialog } from "../dialog/functions";
|
||||||
import MoveNoteSheet from "../sheets/add-to";
|
import MoveNoteSheet from "../sheets/add-to";
|
||||||
import ExportNotesSheet from "../sheets/export-notes";
|
import ExportNotesSheet from "../sheets/export-notes";
|
||||||
import ManageTagsSheet from "../sheets/manage-tags";
|
import ManageTagsSheet from "../sheets/manage-tags";
|
||||||
import { MoveNotebookSheet } from "../sheets/move-notebook";
|
import { MoveNotebookSheet } from "../sheets/move-notebook";
|
||||||
import { Button } from "../ui/button";
|
|
||||||
import { IconButton } from "../ui/icon-button";
|
import { IconButton } from "../ui/icon-button";
|
||||||
import Heading from "../ui/typography/heading";
|
|
||||||
|
|
||||||
export const SelectionHeader = React.memo(
|
export const SelectionHeader = React.memo(
|
||||||
({
|
({
|
||||||
@@ -75,9 +74,9 @@ export const SelectionHeader = React.memo(
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectionMode) {
|
if (selectionMode) {
|
||||||
tabBarRef.current?.lock();
|
fluidTabsRef.current?.lock();
|
||||||
} else {
|
} else {
|
||||||
tabBarRef.current?.unlock();
|
fluidTabsRef.current?.unlock();
|
||||||
}
|
}
|
||||||
}, [selectionMode]);
|
}, [selectionMode]);
|
||||||
|
|
||||||
@@ -139,61 +138,24 @@ export const SelectionHeader = React.memo(
|
|||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
height: Platform.OS === "android" ? 50 + insets.top : 50,
|
|
||||||
paddingTop: Platform.OS === "android" ? insets.top : null,
|
|
||||||
backgroundColor: colors.primary.background,
|
backgroundColor: colors.primary.background,
|
||||||
justifyContent: "space-between",
|
paddingVertical: DefaultAppStyles.GAP_VERTICAL,
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
zIndex: 999,
|
zIndex: 999,
|
||||||
paddingHorizontal: 12
|
paddingHorizontal: DefaultAppStyles.GAP,
|
||||||
|
position: "absolute",
|
||||||
|
bottom: 0,
|
||||||
|
borderTopWidth: 1,
|
||||||
|
borderColor: colors.primary.border,
|
||||||
|
justifyContent: "space-between"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
justifyContent: "flex-start",
|
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
borderRadius: 100
|
gap: DefaultAppStyles.GAP_SMALL
|
||||||
}}
|
|
||||||
>
|
|
||||||
<IconButton
|
|
||||||
style={{
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
height: 40,
|
|
||||||
width: 40,
|
|
||||||
borderRadius: 100,
|
|
||||||
marginRight: 10
|
|
||||||
}}
|
|
||||||
onPress={() => {
|
|
||||||
clearSelection();
|
|
||||||
}}
|
|
||||||
color={colors.primary.icon}
|
|
||||||
name="close"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
height: 40,
|
|
||||||
borderRadius: 100,
|
|
||||||
paddingHorizontal: 16,
|
|
||||||
justifyContent: "center",
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Heading size={SIZE.lg} color={colors.primary.paragraph}>
|
|
||||||
{selectedItemsList.length}
|
|
||||||
</Heading>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
flexDirection: "row",
|
|
||||||
justifyContent: "flex-start",
|
|
||||||
alignItems: "center"
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<IconButton
|
<IconButton
|
||||||
@@ -202,42 +164,14 @@ export const SelectionHeader = React.memo(
|
|||||||
.getState()
|
.getState()
|
||||||
.setAll(allSelected ? [] : [...((await items?.ids()) || [])]);
|
.setAll(allSelected ? [] : [...((await items?.ids()) || [])]);
|
||||||
}}
|
}}
|
||||||
tooltipText="Select all"
|
size={SIZE.lg}
|
||||||
tooltipPosition={4}
|
color={allSelected ? colors.primary.accent : colors.primary.icon}
|
||||||
style={{
|
|
||||||
marginLeft: 10
|
|
||||||
}}
|
|
||||||
color={
|
|
||||||
allSelected ? colors.primary.accent : colors.primary.paragraph
|
|
||||||
}
|
|
||||||
name="select-all"
|
name="select-all"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{selectedItemsList.length ? (
|
{!selectedItemsList.length
|
||||||
<Menu
|
? null
|
||||||
ref={menuRef}
|
: [
|
||||||
animationDuration={200}
|
|
||||||
style={{
|
|
||||||
borderRadius: 5,
|
|
||||||
backgroundColor: contextMenuColors.primary.background,
|
|
||||||
marginTop: 35
|
|
||||||
}}
|
|
||||||
onRequestClose={() => {
|
|
||||||
//@ts-ignore
|
|
||||||
menuRef.current?.hide();
|
|
||||||
}}
|
|
||||||
anchor={
|
|
||||||
<IconButton
|
|
||||||
onPress={() => {
|
|
||||||
//@ts-ignore
|
|
||||||
menuRef.current?.show();
|
|
||||||
}}
|
|
||||||
name="dots-vertical"
|
|
||||||
color={colors.primary.paragraph}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{[
|
|
||||||
{
|
{
|
||||||
title: strings.move(),
|
title: strings.move(),
|
||||||
onPress: async () => {
|
onPress: async () => {
|
||||||
@@ -341,20 +275,12 @@ export const SelectionHeader = React.memo(
|
|||||||
}
|
}
|
||||||
].map((item) =>
|
].map((item) =>
|
||||||
!item.visible ? null : (
|
!item.visible ? null : (
|
||||||
<Button
|
<IconButton
|
||||||
style={{
|
size={SIZE.lg}
|
||||||
justifyContent: "flex-start",
|
|
||||||
borderRadius: 0,
|
|
||||||
alignSelf: "flex-start",
|
|
||||||
width: "100%"
|
|
||||||
}}
|
|
||||||
type="plain"
|
type="plain"
|
||||||
buttonType={{
|
name={item.icon}
|
||||||
text: contextMenuColors.primary.paragraph
|
|
||||||
}}
|
|
||||||
icon={item.icon}
|
|
||||||
key={item.title}
|
key={item.title}
|
||||||
title={item.title}
|
color={colors.primary.icon}
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
menuRef.current?.hide();
|
menuRef.current?.hide();
|
||||||
@@ -364,9 +290,16 @@ export const SelectionHeader = React.memo(
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</Menu>
|
|
||||||
) : null}
|
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
<IconButton
|
||||||
|
size={SIZE.lg}
|
||||||
|
onPress={() => {
|
||||||
|
clearSelection();
|
||||||
|
}}
|
||||||
|
color={colors.primary.icon}
|
||||||
|
name="close"
|
||||||
|
/>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Notebook } from "@notesnook/core";
|
import { Notebook } from "@notesnook/core";
|
||||||
|
import { strings } from "@notesnook/intl";
|
||||||
import React, { useRef, useState } from "react";
|
import React, { useRef, useState } from "react";
|
||||||
import { TextInput, View } from "react-native";
|
import { TextInput, View } from "react-native";
|
||||||
import { notesnook } from "../../../../e2e/test.ids";
|
import { notesnook } from "../../../../e2e/test.ids";
|
||||||
@@ -30,17 +31,16 @@ import {
|
|||||||
} from "../../../services/event-manager";
|
} from "../../../services/event-manager";
|
||||||
import Navigation from "../../../services/navigation";
|
import Navigation from "../../../services/navigation";
|
||||||
import { useMenuStore } from "../../../stores/use-menu-store";
|
import { useMenuStore } from "../../../stores/use-menu-store";
|
||||||
|
import { useNotebookStore } from "../../../stores/use-notebook-store";
|
||||||
import { useRelationStore } from "../../../stores/use-relation-store";
|
import { useRelationStore } from "../../../stores/use-relation-store";
|
||||||
|
import { eOnNotebookUpdated } from "../../../utils/events";
|
||||||
|
import { getParentNotebookId } from "../../../utils/notebooks";
|
||||||
import { SIZE } from "../../../utils/size";
|
import { SIZE } from "../../../utils/size";
|
||||||
import { Button } from "../../ui/button";
|
import { Button } from "../../ui/button";
|
||||||
import Input from "../../ui/input";
|
import Input from "../../ui/input";
|
||||||
import Seperator from "../../ui/seperator";
|
import Seperator from "../../ui/seperator";
|
||||||
import Heading from "../../ui/typography/heading";
|
import Heading from "../../ui/typography/heading";
|
||||||
import { MoveNotes } from "../move-notes/movenote";
|
import { MoveNotes } from "../move-notes/movenote";
|
||||||
import { eOnNotebookUpdated } from "../../../utils/events";
|
|
||||||
import { getParentNotebookId } from "../../../utils/notebooks";
|
|
||||||
import { useNotebookStore } from "../../../stores/use-notebook-store";
|
|
||||||
import { strings } from "@notesnook/intl";
|
|
||||||
|
|
||||||
export const AddNotebookSheet = ({
|
export const AddNotebookSheet = ({
|
||||||
notebook,
|
notebook,
|
||||||
@@ -97,11 +97,10 @@ export const AddNotebookSheet = ({
|
|||||||
parentNotebook?.id ||
|
parentNotebook?.id ||
|
||||||
(await getParentNotebookId(notebook?.id || (id as string)));
|
(await getParentNotebookId(notebook?.id || (id as string)));
|
||||||
|
|
||||||
eSendEvent(eOnNotebookUpdated, parent);
|
eSendEvent(eOnNotebookUpdated, parent || notebook?.id);
|
||||||
if (notebook) {
|
|
||||||
setImmediate(() => {
|
if (!parent) {
|
||||||
eSendEvent(eOnNotebookUpdated, notebook.id);
|
useNotebookStore.getState().refresh();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!notebook && showMoveNotesOnComplete && id) {
|
if (!notebook && showMoveNotesOnComplete && id) {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import { Notebook, VirtualizedGrouping } from "@notesnook/core";
|
import { Notebook, VirtualizedGrouping } from "@notesnook/core";
|
||||||
|
import { strings } from "@notesnook/intl";
|
||||||
import { useThemeColors } from "@notesnook/theme";
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
import React, { useCallback, useEffect, useState } from "react";
|
import React, { useCallback, useEffect, useState } from "react";
|
||||||
import { Text, View } from "react-native";
|
import { Text, View } from "react-native";
|
||||||
@@ -45,7 +46,6 @@ import { Pressable } from "../../ui/pressable";
|
|||||||
import Seperator from "../../ui/seperator";
|
import Seperator from "../../ui/seperator";
|
||||||
import Paragraph from "../../ui/typography/paragraph";
|
import Paragraph from "../../ui/typography/paragraph";
|
||||||
import { AddNotebookSheet } from "../add-notebook";
|
import { AddNotebookSheet } from "../add-notebook";
|
||||||
import { strings } from "@notesnook/intl";
|
|
||||||
|
|
||||||
const useNotebookExpandedStore = create<{
|
const useNotebookExpandedStore = create<{
|
||||||
expanded: {
|
expanded: {
|
||||||
@@ -119,14 +119,19 @@ export const MoveNotebookSheet = ({
|
|||||||
},
|
},
|
||||||
notebook
|
notebook
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
await db.relations.add(selectedNotebook, notebook);
|
||||||
|
if (parent) {
|
||||||
eSendEvent(eOnNotebookUpdated, parent);
|
eSendEvent(eOnNotebookUpdated, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
await db.relations.add(selectedNotebook, notebook);
|
|
||||||
eSendEvent(eOnNotebookUpdated, selectedNotebook.id);
|
|
||||||
eSendEvent(eOnNotebookUpdated, notebook.id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!parent) {
|
||||||
useNotebookStore.getState().refresh();
|
useNotebookStore.getState().refresh();
|
||||||
|
} else {
|
||||||
|
eSendEvent(eOnNotebookUpdated, selectedNotebook.id);
|
||||||
|
}
|
||||||
|
|
||||||
close?.();
|
close?.();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import { useDBItem, useNoteLocked } from "../../../hooks/use-db-item";
|
|||||||
import { eSendEvent, presentSheet } from "../../../services/event-manager";
|
import { eSendEvent, presentSheet } from "../../../services/event-manager";
|
||||||
import { useRelationStore } from "../../../stores/use-relation-store";
|
import { useRelationStore } from "../../../stores/use-relation-store";
|
||||||
import { eOnLoadNote } from "../../../utils/events";
|
import { eOnLoadNote } from "../../../utils/events";
|
||||||
import { tabBarRef } from "../../../utils/global-refs";
|
import { fluidTabsRef } from "../../../utils/global-refs";
|
||||||
import { SIZE } from "../../../utils/size";
|
import { SIZE } from "../../../utils/size";
|
||||||
import SheetProvider from "../../sheet-provider";
|
import SheetProvider from "../../sheet-provider";
|
||||||
import { Button } from "../../ui/button";
|
import { Button } from "../../ui/button";
|
||||||
@@ -423,7 +423,7 @@ export const ReferencesList = ({ item, close }: ReferencesListProps) => {
|
|||||||
item: note,
|
item: note,
|
||||||
blockId: blockId
|
blockId: blockId
|
||||||
});
|
});
|
||||||
tabBarRef.current?.goToPage(1);
|
fluidTabsRef.current?.goToPage(1);
|
||||||
close?.();
|
close?.();
|
||||||
}}
|
}}
|
||||||
reference={item as Note}
|
reference={item as Note}
|
||||||
|
|||||||
@@ -17,45 +17,55 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
GroupingKey,
|
||||||
|
GroupOptions,
|
||||||
|
ItemType,
|
||||||
|
SortOptions
|
||||||
|
} from "@notesnook/core";
|
||||||
|
import { strings } from "@notesnook/intl";
|
||||||
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import { View } from "react-native";
|
import { View } from "react-native";
|
||||||
import { db } from "../../../common/database";
|
import { db } from "../../../common/database";
|
||||||
import { eSendEvent } from "../../../services/event-manager";
|
import { eSendEvent } from "../../../services/event-manager";
|
||||||
import Navigation from "../../../services/navigation";
|
import Navigation from "../../../services/navigation";
|
||||||
import { useThemeColors } from "@notesnook/theme";
|
import { RouteName } from "../../../stores/use-navigation-store";
|
||||||
import { GROUP, SORT } from "../../../utils/constants";
|
import { GROUP, SORT } from "../../../utils/constants";
|
||||||
import { eGroupOptionsUpdated, refreshNotesPage } from "../../../utils/events";
|
import { eGroupOptionsUpdated, refreshNotesPage } from "../../../utils/events";
|
||||||
import { SIZE } from "../../../utils/size";
|
import { SIZE } from "../../../utils/size";
|
||||||
|
import { DefaultAppStyles } from "../../../utils/styles";
|
||||||
|
import AppIcon from "../../ui/AppIcon";
|
||||||
import { Button } from "../../ui/button";
|
import { Button } from "../../ui/button";
|
||||||
import Seperator from "../../ui/seperator";
|
import { Pressable } from "../../ui/pressable";
|
||||||
import Heading from "../../ui/typography/heading";
|
import Heading from "../../ui/typography/heading";
|
||||||
import { strings } from "@notesnook/intl";
|
import Paragraph from "../../ui/typography/paragraph";
|
||||||
const Sort = ({ type, screen }) => {
|
const Sort = ({ type, screen }: { type: ItemType; screen: RouteName }) => {
|
||||||
const isTopicSheet = screen === "TopicSheet";
|
|
||||||
const { colors } = useThemeColors();
|
const { colors } = useThemeColors();
|
||||||
const [groupOptions, setGroupOptions] = useState(
|
const [groupOptions, setGroupOptions] = useState(
|
||||||
db.settings.getGroupOptions(screen === "Notes" ? "home" : type + "s")
|
db.settings.getGroupOptions(
|
||||||
|
screen === "Notes" ? "home" : ((type + "s") as GroupingKey)
|
||||||
|
)
|
||||||
);
|
);
|
||||||
const updateGroupOptions = async (_groupOptions) => {
|
const updateGroupOptions = async (_groupOptions: GroupOptions) => {
|
||||||
const groupType = screen === "Notes" ? "home" : type + "s";
|
const groupType =
|
||||||
|
screen === "Notes" ? "home" : ((type + "s") as GroupingKey);
|
||||||
|
console.log("updateGroupOptions for group", groupType, "in", screen);
|
||||||
await db.settings.setGroupOptions(groupType, _groupOptions);
|
await db.settings.setGroupOptions(groupType, _groupOptions);
|
||||||
setGroupOptions(_groupOptions);
|
setGroupOptions(_groupOptions);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (screen !== "TopicSheet") Navigation.queueRoutesForUpdate(screen);
|
Navigation.queueRoutesForUpdate(screen);
|
||||||
eSendEvent(eGroupOptionsUpdated, groupType);
|
eSendEvent(eGroupOptionsUpdated, groupType);
|
||||||
eSendEvent(refreshNotesPage);
|
eSendEvent(refreshNotesPage);
|
||||||
}, 1);
|
}, 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const setOrderBy = async () => {
|
const setOrderBy = async () => {
|
||||||
let _groupOptions = {
|
const _groupOptions: GroupOptions = {
|
||||||
...groupOptions,
|
...groupOptions,
|
||||||
sortDirection: groupOptions?.sortDirection === "asc" ? "desc" : "asc"
|
sortDirection: groupOptions?.sortDirection === "asc" ? "desc" : "asc"
|
||||||
};
|
};
|
||||||
if (type === "topics") {
|
|
||||||
_groupOptions.groupBy = "none";
|
|
||||||
}
|
|
||||||
await updateGroupOptions(_groupOptions);
|
await updateGroupOptions(_groupOptions);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -64,7 +74,8 @@ const Sort = ({ type, screen }) => {
|
|||||||
style={{
|
style={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
backgroundColor: colors.primary.background,
|
backgroundColor: colors.primary.background,
|
||||||
justifyContent: "space-between"
|
justifyContent: "space-between",
|
||||||
|
gap: DefaultAppStyles.GAP_SMALL
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View
|
<View
|
||||||
@@ -72,11 +83,12 @@ const Sort = ({ type, screen }) => {
|
|||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
paddingHorizontal: 12
|
paddingHorizontal: DefaultAppStyles.GAP,
|
||||||
|
paddingVertical: DefaultAppStyles.GAP_VERTICAL
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Heading
|
<Heading
|
||||||
size={SIZE.xl}
|
size={SIZE.md}
|
||||||
style={{
|
style={{
|
||||||
alignSelf: "center"
|
alignSelf: "center"
|
||||||
}}
|
}}
|
||||||
@@ -105,34 +117,22 @@ const Sort = ({ type, screen }) => {
|
|||||||
? "sort-ascending"
|
? "sort-ascending"
|
||||||
: "sort-descending"
|
: "sort-descending"
|
||||||
}
|
}
|
||||||
height={25}
|
height={30}
|
||||||
iconPosition="right"
|
iconPosition="right"
|
||||||
fontSize={SIZE.sm - 1}
|
fontSize={SIZE.sm}
|
||||||
type="transparent"
|
type="plain"
|
||||||
buttonType={{
|
|
||||||
text: colors.primary.accent
|
|
||||||
}}
|
|
||||||
style={{
|
style={{
|
||||||
borderRadius: 100,
|
paddingHorizontal: DefaultAppStyles.GAP_SMALL
|
||||||
paddingHorizontal: 6
|
|
||||||
}}
|
}}
|
||||||
onPress={setOrderBy}
|
onPress={setOrderBy}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<Seperator />
|
|
||||||
|
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
flexDirection: "row",
|
flexDirection: "column",
|
||||||
justifyContent: "flex-start",
|
justifyContent: "flex-start",
|
||||||
flexWrap: "wrap",
|
borderBottomColor: colors.primary.border
|
||||||
borderBottomWidth: isTopicSheet ? 0 : 1,
|
|
||||||
borderBottomColor: colors.primary.border,
|
|
||||||
marginBottom: 12,
|
|
||||||
paddingHorizontal: 12,
|
|
||||||
paddingBottom: 12,
|
|
||||||
alignItems: "center"
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{groupOptions?.groupBy === "abc" ? (
|
{groupOptions?.groupBy === "abc" ? (
|
||||||
@@ -149,105 +149,118 @@ const Sort = ({ type, screen }) => {
|
|||||||
) : (
|
) : (
|
||||||
Object.keys(SORT).map((item) =>
|
Object.keys(SORT).map((item) =>
|
||||||
(item === "dueDate" && screen !== "Reminders") ||
|
(item === "dueDate" && screen !== "Reminders") ||
|
||||||
((screen !== "Tags" || screen !== "Reminders") &&
|
(screen !== "Tags" &&
|
||||||
|
screen !== "Reminders" &&
|
||||||
item === "dateModified") ||
|
item === "dateModified") ||
|
||||||
((screen === "Tags" || screen === "Reminders") &&
|
((screen === "Tags" || screen === "Reminders") &&
|
||||||
item === "dateEdited") ? null : (
|
item === "dateEdited") ? null : (
|
||||||
<Button
|
<Pressable
|
||||||
key={item}
|
key={item}
|
||||||
type={groupOptions?.sortBy === item ? "selected" : "plain"}
|
type={groupOptions?.sortBy === item ? "selected" : "plain"}
|
||||||
title={strings.sortByStrings[item]()}
|
noborder
|
||||||
height={40}
|
|
||||||
iconPosition="left"
|
|
||||||
icon={groupOptions?.sortBy === item ? "check" : null}
|
|
||||||
style={{
|
style={{
|
||||||
marginRight: 10,
|
width: "100%",
|
||||||
paddingHorizontal: 8
|
justifyContent: "space-between",
|
||||||
|
height: 40,
|
||||||
|
flexDirection: "row",
|
||||||
|
borderRadius: 0,
|
||||||
|
paddingHorizontal: DefaultAppStyles.GAP
|
||||||
}}
|
}}
|
||||||
buttonType={{
|
|
||||||
text:
|
|
||||||
groupOptions?.sortBy === item
|
|
||||||
? colors.primary.accent
|
|
||||||
: colors.secondary.paragraph
|
|
||||||
}}
|
|
||||||
fontSize={SIZE.sm}
|
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
let _groupOptions = {
|
const _groupOptions: GroupOptions = {
|
||||||
...groupOptions,
|
...groupOptions,
|
||||||
sortBy: type === "trash" ? "dateDeleted" : item
|
sortBy:
|
||||||
|
type === "trash"
|
||||||
|
? "dateDeleted"
|
||||||
|
: (item as SortOptions["sortBy"])
|
||||||
};
|
};
|
||||||
if (screen === "TopicSheet") {
|
|
||||||
_groupOptions.groupBy = "none";
|
|
||||||
}
|
|
||||||
await updateGroupOptions(_groupOptions);
|
await updateGroupOptions(_groupOptions);
|
||||||
}}
|
}}
|
||||||
iconSize={SIZE.md}
|
>
|
||||||
|
<Paragraph>
|
||||||
|
{strings.sortByStrings[
|
||||||
|
item as keyof typeof strings.sortByStrings
|
||||||
|
]()}
|
||||||
|
</Paragraph>
|
||||||
|
|
||||||
|
{groupOptions.sortBy === item ? (
|
||||||
|
<AppIcon
|
||||||
|
size={SIZE.lg}
|
||||||
|
name="check"
|
||||||
|
color={colors.selected.accent}
|
||||||
/>
|
/>
|
||||||
|
) : null}
|
||||||
|
</Pressable>
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{isTopicSheet ? null : (
|
|
||||||
<>
|
<>
|
||||||
<Heading
|
<View
|
||||||
style={{
|
style={{
|
||||||
marginLeft: 12
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
paddingHorizontal: DefaultAppStyles.GAP,
|
||||||
|
paddingVertical: DefaultAppStyles.GAP_VERTICAL
|
||||||
}}
|
}}
|
||||||
size={SIZE.lg}
|
|
||||||
>
|
>
|
||||||
{strings.groupBy()}
|
<Heading size={SIZE.md}>{strings.groupBy()}</Heading>
|
||||||
</Heading>
|
</View>
|
||||||
|
|
||||||
<Seperator />
|
|
||||||
|
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
borderRadius: 0,
|
borderRadius: 0,
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
flexWrap: "wrap",
|
flexWrap: "wrap"
|
||||||
paddingHorizontal: 12
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{Object.keys(GROUP).map((item) => (
|
{Object.keys(GROUP).map((item) => (
|
||||||
<Button
|
<Pressable
|
||||||
key={item}
|
key={item}
|
||||||
testID={"btn-" + item}
|
|
||||||
type={
|
type={
|
||||||
groupOptions?.groupBy === GROUP[item] ? "selected" : "plain"
|
groupOptions?.groupBy === GROUP[item as keyof typeof GROUP]
|
||||||
|
? "selected"
|
||||||
|
: "plain"
|
||||||
}
|
}
|
||||||
buttonType={{
|
noborder
|
||||||
text:
|
style={{
|
||||||
groupOptions?.groupBy === GROUP[item]
|
width: "100%",
|
||||||
? colors.primary.accent
|
justifyContent: "space-between",
|
||||||
: colors.secondary.paragraph
|
height: 40,
|
||||||
|
flexDirection: "row",
|
||||||
|
borderRadius: 0,
|
||||||
|
paddingHorizontal: DefaultAppStyles.GAP
|
||||||
}}
|
}}
|
||||||
onPress={async () => {
|
onPress={async () => {
|
||||||
let _groupOptions = {
|
const _groupOptions: GroupOptions = {
|
||||||
...groupOptions,
|
...groupOptions,
|
||||||
groupBy: GROUP[item]
|
sortBy:
|
||||||
|
type === "trash"
|
||||||
|
? "dateDeleted"
|
||||||
|
: (item as SortOptions["sortBy"])
|
||||||
};
|
};
|
||||||
|
await updateGroupOptions(_groupOptions);
|
||||||
if (item === "abc") {
|
|
||||||
_groupOptions.sortBy = "title";
|
|
||||||
_groupOptions.sortDirection = "desc";
|
|
||||||
}
|
|
||||||
|
|
||||||
updateGroupOptions(_groupOptions);
|
|
||||||
}}
|
|
||||||
height={40}
|
|
||||||
icon={groupOptions?.groupBy === GROUP[item] ? "check" : null}
|
|
||||||
title={strings.groupByStrings[item]()}
|
|
||||||
style={{
|
|
||||||
paddingHorizontal: 8,
|
|
||||||
marginBottom: 10,
|
|
||||||
marginRight: 10
|
|
||||||
}}
|
}}
|
||||||
|
>
|
||||||
|
<Paragraph>
|
||||||
|
{strings.groupByStrings[
|
||||||
|
item as keyof typeof strings.groupByStrings
|
||||||
|
]()}
|
||||||
|
</Paragraph>
|
||||||
|
|
||||||
|
{groupOptions.groupBy === item ? (
|
||||||
|
<AppIcon
|
||||||
|
size={SIZE.lg}
|
||||||
|
name="check"
|
||||||
|
color={colors.selected.accent}
|
||||||
/>
|
/>
|
||||||
|
) : null}
|
||||||
|
</Pressable>
|
||||||
))}
|
))}
|
||||||
</View>
|
</View>
|
||||||
</>
|
</>
|
||||||
)}
|
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
304
apps/mobile/app/components/sheets/user/index.tsx
Normal file
304
apps/mobile/app/components/sheets/user/index.tsx
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
/*
|
||||||
|
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 { useNetInfo } from "@react-native-community/netinfo";
|
||||||
|
import React from "react";
|
||||||
|
import { ActivityIndicator, Image, View } from "react-native";
|
||||||
|
import { useSheetRef } from "react-native-actions-sheet";
|
||||||
|
import useSyncProgress from "../../../hooks/use-sync-progress";
|
||||||
|
import { presentSheet } from "../../../services/event-manager";
|
||||||
|
import Navigation from "../../../services/navigation";
|
||||||
|
import { SyncStatus, useUserStore } from "../../../stores/use-user-store";
|
||||||
|
import { SIZE } from "../../../utils/size";
|
||||||
|
import { DefaultAppStyles } from "../../../utils/styles";
|
||||||
|
import { Card } from "../../list/card";
|
||||||
|
import AppIcon from "../../ui/AppIcon";
|
||||||
|
import { Button } from "../../ui/button";
|
||||||
|
import { Pressable } from "../../ui/pressable";
|
||||||
|
import { TimeSince } from "../../ui/time-since";
|
||||||
|
import Paragraph from "../../ui/typography/paragraph";
|
||||||
|
|
||||||
|
export const UserSheet = () => {
|
||||||
|
const ref = useSheetRef();
|
||||||
|
const { colors } = useThemeColors();
|
||||||
|
const [userProfile, user, syncing, lastSyncStatus, lastSynced] = useUserStore(
|
||||||
|
(state) => [
|
||||||
|
state.profile,
|
||||||
|
state.user,
|
||||||
|
state.syncing,
|
||||||
|
state.lastSyncStatus,
|
||||||
|
state.lastSynced
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
const { isInternetReachable } = useNetInfo();
|
||||||
|
const isOffline = !isInternetReachable;
|
||||||
|
const { progress } = useSyncProgress();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
justifyContent: "center",
|
||||||
|
paddingHorizontal: DefaultAppStyles.GAP,
|
||||||
|
gap: DefaultAppStyles.GAP
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{user ? (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
source={{
|
||||||
|
uri: userProfile?.profilePicture
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
width: 40,
|
||||||
|
height: 40,
|
||||||
|
borderRadius: 10
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View style={{ marginLeft: 10 }}>
|
||||||
|
<Paragraph size={SIZE.xs}>{userProfile?.fullName}</Paragraph>
|
||||||
|
<Paragraph
|
||||||
|
style={{
|
||||||
|
flexWrap: "wrap"
|
||||||
|
}}
|
||||||
|
size={SIZE.xxs}
|
||||||
|
color={colors.secondary.heading}
|
||||||
|
>
|
||||||
|
<AppIcon
|
||||||
|
name="checkbox-blank-circle"
|
||||||
|
size={10}
|
||||||
|
allowFontScaling
|
||||||
|
color={
|
||||||
|
!user || lastSyncStatus === SyncStatus.Failed
|
||||||
|
? colors.error.icon
|
||||||
|
: isOffline
|
||||||
|
? colors.static.orange
|
||||||
|
: colors.success.icon
|
||||||
|
}
|
||||||
|
/>{" "}
|
||||||
|
{!user ? (
|
||||||
|
strings.notLoggedIn()
|
||||||
|
) : lastSynced && lastSynced !== "Never" ? (
|
||||||
|
<>
|
||||||
|
{syncing
|
||||||
|
? `${strings.syncing()} ${
|
||||||
|
progress ? `(${progress.current})` : ""
|
||||||
|
}`
|
||||||
|
: lastSyncStatus === SyncStatus.Failed
|
||||||
|
? strings.syncFailed()
|
||||||
|
: strings.synced()}{" "}
|
||||||
|
{!syncing ? (
|
||||||
|
<TimeSince
|
||||||
|
style={{
|
||||||
|
fontSize: SIZE.xxs,
|
||||||
|
color: colors.secondary.paragraph
|
||||||
|
}}
|
||||||
|
updateFrequency={30 * 1000}
|
||||||
|
time={lastSynced as number}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
{isOffline ? ` (${strings.offline()})` : ""}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
strings.never()
|
||||||
|
)}
|
||||||
|
</Paragraph>
|
||||||
|
</View>
|
||||||
|
{syncing ? (
|
||||||
|
<ActivityIndicator
|
||||||
|
color={colors.primary.accent}
|
||||||
|
size={SIZE.xxl}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
) : (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
width: "100%"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Card />
|
||||||
|
</View>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{user ? (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
paddingVertical: DefaultAppStyles.GAP_SMALL,
|
||||||
|
gap: DefaultAppStyles.GAP,
|
||||||
|
borderRadius: 10,
|
||||||
|
backgroundColor: colors.primary.background
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
gap: DefaultAppStyles.GAP_SMALL,
|
||||||
|
paddingHorizontal: DefaultAppStyles.GAP_SMALL
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
width: "100%",
|
||||||
|
justifyContent: "space-between"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Paragraph size={SIZE.xxs}>{strings.storage()}</Paragraph>
|
||||||
|
<Paragraph size={SIZE.xxs}>50/100MB {strings.used()}</Paragraph>
|
||||||
|
</View>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
backgroundColor: colors.secondary.background,
|
||||||
|
width: "100%",
|
||||||
|
height: 5,
|
||||||
|
borderRadius: 10
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
backgroundColor: colors.static.black,
|
||||||
|
height: 5,
|
||||||
|
width: "50%",
|
||||||
|
borderRadius: 10
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
width: "100%",
|
||||||
|
padding: DefaultAppStyles.GAP_SMALL,
|
||||||
|
borderRadius: 10
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View>
|
||||||
|
<Paragraph size={SIZE.sm}>{strings.freePlan()}</Paragraph>
|
||||||
|
<Paragraph color={colors.secondary.paragraph} size={SIZE.xxxs}>
|
||||||
|
{strings.viewAllLimits()}
|
||||||
|
<AppIcon name="information" size={SIZE.xxxs} />
|
||||||
|
</Paragraph>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
title={strings.upgradeNow()}
|
||||||
|
onPress={() => {}}
|
||||||
|
type="accent"
|
||||||
|
fontSize={SIZE.xs}
|
||||||
|
style={{
|
||||||
|
paddingHorizontal: DefaultAppStyles.GAP_SMALL,
|
||||||
|
height: "auto",
|
||||||
|
paddingVertical: DefaultAppStyles.GAP_SMALL
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
) : null}
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
borderBottomWidth: 1,
|
||||||
|
height: 1,
|
||||||
|
borderColor: colors.primary.border
|
||||||
|
}}
|
||||||
|
></View>
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
gap: DefaultAppStyles.GAP_VERTICAL
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{[
|
||||||
|
{
|
||||||
|
icon: "account-outline",
|
||||||
|
title: strings.editProfile(),
|
||||||
|
onPress: () => {},
|
||||||
|
hidden: !user
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: "cog-outline",
|
||||||
|
title: strings.settings(),
|
||||||
|
onPress: () => {
|
||||||
|
ref.current?.hide();
|
||||||
|
Navigation.closeDrawer();
|
||||||
|
Navigation.navigate("Settings");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: "logout",
|
||||||
|
title: strings.logout(),
|
||||||
|
onPress: () => {
|
||||||
|
ref.current?.hide();
|
||||||
|
},
|
||||||
|
hidden: !user
|
||||||
|
}
|
||||||
|
].map((item) =>
|
||||||
|
item.hidden ? null : (
|
||||||
|
<Pressable
|
||||||
|
key={item.title}
|
||||||
|
style={{
|
||||||
|
paddingVertical: DefaultAppStyles.GAP_SMALL,
|
||||||
|
alignItems: "center",
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "flex-start",
|
||||||
|
gap: DefaultAppStyles.GAP_SMALL,
|
||||||
|
paddingHorizontal: DefaultAppStyles.GAP_SMALL
|
||||||
|
}}
|
||||||
|
onPress={() => {
|
||||||
|
item.onPress();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AppIcon
|
||||||
|
color={colors.secondary.icon}
|
||||||
|
name={item.icon}
|
||||||
|
size={SIZE.xl}
|
||||||
|
/>
|
||||||
|
<Paragraph>{item.title}</Paragraph>
|
||||||
|
</Pressable>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
UserSheet.present = () => {
|
||||||
|
presentSheet({
|
||||||
|
component: <UserSheet />
|
||||||
|
});
|
||||||
|
};
|
||||||
@@ -18,22 +18,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Color } from "@notesnook/core";
|
import { Color } from "@notesnook/core";
|
||||||
import { useThemeColors } from "@notesnook/theme";
|
import React, { useEffect, useMemo } from "react";
|
||||||
import React, { useEffect } from "react";
|
|
||||||
import { View } from "react-native";
|
import { View } from "react-native";
|
||||||
import { db } from "../../common/database";
|
import { db } from "../../common/database";
|
||||||
import { ColoredNotes } from "../../screens/notes/colored";
|
import { ColoredNotes } from "../../screens/notes/colored";
|
||||||
import Navigation from "../../services/navigation";
|
import Navigation from "../../services/navigation";
|
||||||
import { useMenuStore } from "../../stores/use-menu-store";
|
import { useMenuStore } from "../../stores/use-menu-store";
|
||||||
import useNavigationStore from "../../stores/use-navigation-store";
|
|
||||||
import { useSettingStore } from "../../stores/use-setting-store";
|
import { useSettingStore } from "../../stores/use-setting-store";
|
||||||
import { SIZE, normalize } from "../../utils/size";
|
import { SideMenuItem } from "../../utils/menu-items";
|
||||||
import ReorderableList from "../list/reorderable-list";
|
import ReorderableList from "../list/reorderable-list";
|
||||||
import { Properties } from "../properties";
|
import { Properties } from "../properties";
|
||||||
import { Pressable } from "../ui/pressable";
|
|
||||||
import Heading from "../ui/typography/heading";
|
|
||||||
import Paragraph from "../ui/typography/paragraph";
|
|
||||||
import { useSideBarDraggingStore } from "./dragging-store";
|
import { useSideBarDraggingStore } from "./dragging-store";
|
||||||
|
import { MenuItem } from "./menu-item";
|
||||||
|
|
||||||
export const ColorSection = React.memo(
|
export const ColorSection = React.memo(
|
||||||
function ColorSection() {
|
function ColorSection() {
|
||||||
@@ -54,6 +50,54 @@ export const ColorSection = React.memo(
|
|||||||
}
|
}
|
||||||
}, [loading, setColorNotes]);
|
}, [loading, setColorNotes]);
|
||||||
|
|
||||||
|
const onPress = React.useCallback((item: SideMenuItem) => {
|
||||||
|
ColoredNotes.navigate(item.data as Color, false);
|
||||||
|
setImmediate(() => {
|
||||||
|
Navigation.closeDrawer();
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onLongPress = React.useCallback((item: SideMenuItem) => {
|
||||||
|
if (useSideBarDraggingStore.getState().dragging) return;
|
||||||
|
Properties.present(item.data as Color);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const renderIcon = React.useCallback((item: SideMenuItem, size: number) => {
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
width: size,
|
||||||
|
height: size,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
width: size - 5,
|
||||||
|
height: size - 5,
|
||||||
|
backgroundColor: (item.data as Color).colorCode,
|
||||||
|
borderRadius: 100
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const menuItems = useMemo(
|
||||||
|
() =>
|
||||||
|
colorNotes.map((item) => ({
|
||||||
|
id: item.id,
|
||||||
|
title: item.title,
|
||||||
|
icon: "circle",
|
||||||
|
dataType: "color",
|
||||||
|
data: item,
|
||||||
|
onPress: onPress,
|
||||||
|
onLongPress: onLongPress
|
||||||
|
})) as SideMenuItem[],
|
||||||
|
[colorNotes, onPress, onLongPress]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReorderableList
|
<ReorderableList
|
||||||
onListOrderChanged={(data) => {
|
onListOrderChanged={(data) => {
|
||||||
@@ -66,103 +110,16 @@ export const ColorSection = React.memo(
|
|||||||
itemOrder={order}
|
itemOrder={order}
|
||||||
hiddenItems={hiddensItems}
|
hiddenItems={hiddensItems}
|
||||||
alwaysBounceVertical={false}
|
alwaysBounceVertical={false}
|
||||||
data={colorNotes}
|
data={menuItems}
|
||||||
style={{
|
style={{
|
||||||
width: "100%"
|
width: "100%"
|
||||||
}}
|
}}
|
||||||
showsVerticalScrollIndicator={false}
|
showsVerticalScrollIndicator={false}
|
||||||
renderDraggableItem={({ item }) => {
|
renderDraggableItem={({ item }) => {
|
||||||
return <ColorItem key={item.id} item={item} />;
|
return <MenuItem item={item} renderIcon={renderIcon} />;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
() => true
|
() => true
|
||||||
);
|
);
|
||||||
|
|
||||||
const ColorItem = React.memo(
|
|
||||||
function ColorItem({ item }: { item: Color }) {
|
|
||||||
const { colors, isDark } = useThemeColors();
|
|
||||||
const isFocused = useNavigationStore(
|
|
||||||
(state) => state.focusedRouteId === item.id
|
|
||||||
);
|
|
||||||
|
|
||||||
const onPress = (item: Color) => {
|
|
||||||
ColoredNotes.navigate(item, false);
|
|
||||||
|
|
||||||
setImmediate(() => {
|
|
||||||
Navigation.closeDrawer();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const onLongPress = () => {
|
|
||||||
if (useSideBarDraggingStore.getState().dragging) return;
|
|
||||||
Properties.present(item);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Pressable
|
|
||||||
customColor={isFocused ? "rgba(0,0,0,0.04)" : "transparent"}
|
|
||||||
onLongPress={onLongPress}
|
|
||||||
customSelectedColor={item.colorCode}
|
|
||||||
customAlpha={!isDark ? -0.02 : 0.02}
|
|
||||||
customOpacity={0.12}
|
|
||||||
onPress={() => onPress(item)}
|
|
||||||
style={{
|
|
||||||
width: "100%",
|
|
||||||
alignSelf: "center",
|
|
||||||
borderRadius: 5,
|
|
||||||
flexDirection: "row",
|
|
||||||
paddingHorizontal: 8,
|
|
||||||
justifyContent: "space-between",
|
|
||||||
alignItems: "center",
|
|
||||||
height: normalize(50),
|
|
||||||
marginBottom: 5
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
width: 30,
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "flex-start"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
width: SIZE.lg - 2,
|
|
||||||
height: SIZE.lg - 2,
|
|
||||||
backgroundColor: item.colorCode,
|
|
||||||
borderRadius: 100,
|
|
||||||
justifyContent: "center",
|
|
||||||
marginRight: 10
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
{isFocused ? (
|
|
||||||
<Heading color={colors.selected.heading} size={SIZE.md}>
|
|
||||||
{item.title}
|
|
||||||
</Heading>
|
|
||||||
) : (
|
|
||||||
<Paragraph color={colors.primary.paragraph} size={SIZE.md}>
|
|
||||||
{item.title}
|
|
||||||
</Paragraph>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
</Pressable>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
(prev, next) => {
|
|
||||||
if (!next.item) return false;
|
|
||||||
if (prev.item?.title !== next.item.title) return false;
|
|
||||||
if (prev.item?.dateModified !== next.item?.dateModified) return false;
|
|
||||||
if (prev.item?.id !== next.item?.id) return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|||||||
@@ -18,162 +18,351 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { useThemeColors } from "@notesnook/theme";
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
import React, { useCallback } from "react";
|
import React from "react";
|
||||||
import { View } from "react-native";
|
import { Image, View } from "react-native";
|
||||||
import { DraxProvider, DraxScrollView } from "react-native-drax";
|
import {
|
||||||
|
NavigationState,
|
||||||
|
Route,
|
||||||
|
SceneMap,
|
||||||
|
SceneRendererProps,
|
||||||
|
TabDescriptor,
|
||||||
|
TabView
|
||||||
|
} from "react-native-tab-view";
|
||||||
|
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||||
import { db } from "../../common/database";
|
import { db } from "../../common/database";
|
||||||
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
|
import Navigation from "../../services/navigation";
|
||||||
import { eSendEvent } from "../../services/event-manager";
|
|
||||||
import { useMenuStore } from "../../stores/use-menu-store";
|
|
||||||
import { useSettingStore } from "../../stores/use-setting-store";
|
|
||||||
import { useUserStore } from "../../stores/use-user-store";
|
import { useUserStore } from "../../stores/use-user-store";
|
||||||
import { SUBSCRIPTION_STATUS } from "../../utils/constants";
|
import { deleteItems } from "../../utils/functions";
|
||||||
import { eOpenPremiumDialog } from "../../utils/events";
|
import { SIZE } from "../../utils/size";
|
||||||
import { MenuItemsList } from "../../utils/menu-items";
|
import { DefaultAppStyles } from "../../utils/styles";
|
||||||
import ReorderableList from "../list/reorderable-list";
|
import { MoveNotebookSheet } from "../sheets/move-notebook";
|
||||||
import { Button } from "../ui/button";
|
import { UserSheet } from "../sheets/user";
|
||||||
import { ColorSection } from "./color-section";
|
import { Pressable } from "../ui/pressable";
|
||||||
import { useSideBarDraggingStore } from "./dragging-store";
|
import Paragraph from "../ui/typography/paragraph";
|
||||||
import { MenuItem } from "./menu-item";
|
import { SideMenuHome } from "./side-menu-home";
|
||||||
import { PinnedSection } from "./pinned-section";
|
import { SideMenuNotebooks } from "./side-menu-notebooks";
|
||||||
import { UserStatus } from "./user-status";
|
import { SideMenuTags } from "./side-menu-tags";
|
||||||
import { strings } from "@notesnook/intl";
|
import {
|
||||||
|
useSideMenuNotebookSelectionStore,
|
||||||
|
useSideMenuTagsSelectionStore
|
||||||
|
} from "./stores";
|
||||||
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
import { rootNavigatorRef } from "../../utils/global-refs";
|
||||||
|
const renderScene = SceneMap({
|
||||||
|
home: SideMenuHome,
|
||||||
|
notebooks: SideMenuNotebooks,
|
||||||
|
tags: SideMenuTags,
|
||||||
|
settings: () => null
|
||||||
|
});
|
||||||
|
|
||||||
export const SideMenu = React.memo(
|
export const SideMenu = React.memo(
|
||||||
function SideMenu() {
|
function SideMenu() {
|
||||||
const { colors, isDark } = useThemeColors();
|
const { colors } = useThemeColors();
|
||||||
const insets = useGlobalSafeAreaInsets();
|
const [index, setIndex] = React.useState(0);
|
||||||
const subscriptionType = useUserStore(
|
const [routes] = React.useState<Route[]>([
|
||||||
(state) => state.user?.subscription?.type
|
{
|
||||||
);
|
key: "home",
|
||||||
const isAppLoading = useSettingStore((state) => state.isAppLoading);
|
title: "Home"
|
||||||
const dragging = useSideBarDraggingStore((state) => state.dragging);
|
},
|
||||||
const [order, hiddensItems] = useMenuStore((state) => [
|
{
|
||||||
state.order["routes"],
|
key: "notebooks",
|
||||||
state.hiddenItems["routes"]
|
title: "Notebooks"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "tags",
|
||||||
|
title: "Tags"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "settings",
|
||||||
|
title: "Settings"
|
||||||
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const introCompleted = useSettingStore(
|
|
||||||
(state) => state.settings.introCompleted
|
|
||||||
);
|
|
||||||
|
|
||||||
const pro = {
|
|
||||||
name: "Notesnook Pro",
|
|
||||||
icon: "crown",
|
|
||||||
func: () => {
|
|
||||||
eSendEvent(eOpenPremiumDialog);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const renderItem = useCallback(
|
|
||||||
() => (
|
|
||||||
<>
|
|
||||||
<ReorderableList
|
|
||||||
onListOrderChanged={(data) => {
|
|
||||||
db.settings.setSideBarOrder("routes", data);
|
|
||||||
}}
|
|
||||||
onHiddenItemsChanged={(data) => {
|
|
||||||
db.settings.setSideBarHiddenItems("routes", data);
|
|
||||||
}}
|
|
||||||
itemOrder={order}
|
|
||||||
hiddenItems={hiddensItems}
|
|
||||||
alwaysBounceVertical={false}
|
|
||||||
data={MenuItemsList}
|
|
||||||
style={{
|
|
||||||
width: "100%"
|
|
||||||
}}
|
|
||||||
showsVerticalScrollIndicator={false}
|
|
||||||
renderDraggableItem={({ item, index }) => {
|
|
||||||
return (
|
return (
|
||||||
<MenuItem
|
<SafeAreaView
|
||||||
key={item.name}
|
|
||||||
item={{
|
|
||||||
...item,
|
|
||||||
title:
|
|
||||||
strings.routes[
|
|
||||||
item.name as keyof typeof strings.routes
|
|
||||||
]?.() || item.name
|
|
||||||
}}
|
|
||||||
testID={item.name}
|
|
||||||
index={index}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<ColorSection />
|
|
||||||
<PinnedSection />
|
|
||||||
</>
|
|
||||||
),
|
|
||||||
[order, hiddensItems]
|
|
||||||
);
|
|
||||||
|
|
||||||
return !isAppLoading && introCompleted ? (
|
|
||||||
<View
|
|
||||||
style={{
|
style={{
|
||||||
height: "100%",
|
flex: 1,
|
||||||
width: "100%",
|
|
||||||
backgroundColor: colors.primary.background
|
backgroundColor: colors.primary.background
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View
|
<TabView
|
||||||
style={{
|
navigationState={{ index, routes }}
|
||||||
height: "100%",
|
renderTabBar={(props) => <TabBar {...props} />}
|
||||||
width: "100%",
|
tabBarPosition="bottom"
|
||||||
backgroundColor: colors.primary.background,
|
renderScene={renderScene}
|
||||||
paddingTop: insets.top
|
onIndexChange={setIndex}
|
||||||
}}
|
swipeEnabled={false}
|
||||||
>
|
animationEnabled={false}
|
||||||
<DraxProvider>
|
|
||||||
<DraxScrollView nestedScrollEnabled={false}>
|
|
||||||
{renderItem()}
|
|
||||||
</DraxScrollView>
|
|
||||||
</DraxProvider>
|
|
||||||
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
paddingHorizontal: 12
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{subscriptionType === SUBSCRIPTION_STATUS.TRIAL ||
|
|
||||||
subscriptionType === SUBSCRIPTION_STATUS.BASIC ? (
|
|
||||||
<MenuItem testID={pro.name} key={pro.name} item={pro} index={0} />
|
|
||||||
) : null}
|
|
||||||
</View>
|
|
||||||
|
|
||||||
{dragging ? (
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
paddingHorizontal: 12
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
type="secondaryAccented"
|
|
||||||
style={{
|
|
||||||
flexDirection: "row",
|
|
||||||
borderRadius: 5,
|
|
||||||
marginBottom: 12,
|
|
||||||
justifyContent: "flex-start",
|
|
||||||
alignItems: "center",
|
|
||||||
paddingHorizontal: 12,
|
|
||||||
marginTop: 5,
|
|
||||||
paddingVertical: 6,
|
|
||||||
width: "100%"
|
|
||||||
}}
|
|
||||||
icon="close"
|
|
||||||
title={strings.stopReordering()}
|
|
||||||
onPress={() => {
|
|
||||||
useSideBarDraggingStore.setState({
|
|
||||||
dragging: false
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</View>
|
</SafeAreaView>
|
||||||
) : (
|
);
|
||||||
<UserStatus />
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
) : null;
|
|
||||||
},
|
},
|
||||||
() => true
|
() => true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const SettingsIcon = (props: {
|
||||||
|
route: Route;
|
||||||
|
isFocused: boolean;
|
||||||
|
jumpTo: (routeName: string) => void;
|
||||||
|
}) => {
|
||||||
|
const { colors } = useThemeColors();
|
||||||
|
const userProfile = useUserStore((state) => state.profile);
|
||||||
|
const user = useUserStore((state) => state.user);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Pressable
|
||||||
|
key={props.route.key}
|
||||||
|
onPress={() => {
|
||||||
|
rootNavigatorRef.navigate("Settings");
|
||||||
|
// if (!user) {
|
||||||
|
// rootNavigatorRef.navigate("Settings");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// UserSheet.present();
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
borderRadius: 10,
|
||||||
|
paddingVertical: 2,
|
||||||
|
width: "25%"
|
||||||
|
}}
|
||||||
|
type={props.isFocused ? "selected" : "plain"}
|
||||||
|
>
|
||||||
|
{userProfile?.profilePicture ? (
|
||||||
|
<Image
|
||||||
|
source={{
|
||||||
|
uri: userProfile?.profilePicture
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
width: SIZE.lg,
|
||||||
|
height: SIZE.lg,
|
||||||
|
borderRadius: 100
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Icon
|
||||||
|
name="cog-outline"
|
||||||
|
color={props.isFocused ? colors.primary.accent : colors.primary.icon}
|
||||||
|
size={SIZE.lg}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<Paragraph
|
||||||
|
color={
|
||||||
|
props.isFocused
|
||||||
|
? colors.primary.paragraph
|
||||||
|
: colors.secondary.paragraph
|
||||||
|
}
|
||||||
|
style={{
|
||||||
|
opacity: props.isFocused ? 1 : 0.6
|
||||||
|
}}
|
||||||
|
size={SIZE.xxxs - 1}
|
||||||
|
>
|
||||||
|
{userProfile?.fullName
|
||||||
|
? userProfile.fullName.split(" ")[0]
|
||||||
|
: props.route.title}
|
||||||
|
</Paragraph>
|
||||||
|
</Pressable>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const TabBar = (
|
||||||
|
props: SceneRendererProps & {
|
||||||
|
navigationState: NavigationState<Route>;
|
||||||
|
options: Record<string, TabDescriptor<Route>> | undefined;
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
const { colors } = useThemeColors();
|
||||||
|
const notebookSelectionEnabled = useSideMenuNotebookSelectionStore(
|
||||||
|
(state) => state.enabled
|
||||||
|
);
|
||||||
|
const tagSelectionEnabled = useSideMenuTagsSelectionStore(
|
||||||
|
(state) => state.enabled
|
||||||
|
);
|
||||||
|
const isSelectionEnabled = notebookSelectionEnabled || tagSelectionEnabled;
|
||||||
|
|
||||||
|
const getIcon = (key: string) => {
|
||||||
|
switch (key) {
|
||||||
|
case "home":
|
||||||
|
return "home-outline";
|
||||||
|
case "settings":
|
||||||
|
return "cog-outline";
|
||||||
|
case "notebooks":
|
||||||
|
return "book-outline";
|
||||||
|
case "tags":
|
||||||
|
return "pound";
|
||||||
|
default:
|
||||||
|
return "home-outline";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
width: "100%",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
backgroundColor: colors.primary.background,
|
||||||
|
paddingHorizontal: DefaultAppStyles.GAP,
|
||||||
|
paddingVertical: DefaultAppStyles.GAP_SMALL
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{isSelectionEnabled ? (
|
||||||
|
<>
|
||||||
|
{[
|
||||||
|
{
|
||||||
|
title: "Select all",
|
||||||
|
icon: "check-all"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Delete",
|
||||||
|
icon: "delete"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Move",
|
||||||
|
icon: "arrow-right-bold-box-outline",
|
||||||
|
hidden: !notebookSelectionEnabled
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Close",
|
||||||
|
icon: "close"
|
||||||
|
}
|
||||||
|
].map((item) => (
|
||||||
|
<>
|
||||||
|
<Pressable
|
||||||
|
key={item.title}
|
||||||
|
onPress={async () => {
|
||||||
|
switch (item.title) {
|
||||||
|
case "Select all": {
|
||||||
|
if (notebookSelectionEnabled) {
|
||||||
|
useSideMenuNotebookSelectionStore
|
||||||
|
.getState()
|
||||||
|
.selectAll?.();
|
||||||
|
} else {
|
||||||
|
useSideMenuTagsSelectionStore.getState().selectAll?.();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "Delete": {
|
||||||
|
if (notebookSelectionEnabled) {
|
||||||
|
const ids = useSideMenuNotebookSelectionStore
|
||||||
|
.getState()
|
||||||
|
.getSelectedItemIds();
|
||||||
|
deleteItems(ids, "notebook");
|
||||||
|
} else {
|
||||||
|
const ids = useSideMenuTagsSelectionStore
|
||||||
|
.getState()
|
||||||
|
.getSelectedItemIds();
|
||||||
|
deleteItems(ids, "tag");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "Move": {
|
||||||
|
const ids = useSideMenuNotebookSelectionStore
|
||||||
|
.getState()
|
||||||
|
.getSelectedItemIds();
|
||||||
|
const notebooks = await db.notebooks.all.items(ids);
|
||||||
|
MoveNotebookSheet.present(notebooks);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "Close": {
|
||||||
|
useSideMenuNotebookSelectionStore.setState({
|
||||||
|
enabled: false,
|
||||||
|
selection: {}
|
||||||
|
});
|
||||||
|
useSideMenuTagsSelectionStore.setState({
|
||||||
|
enabled: false,
|
||||||
|
selection: {}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
borderRadius: 10,
|
||||||
|
paddingVertical: 2,
|
||||||
|
width: "25%"
|
||||||
|
}}
|
||||||
|
type="plain"
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
name={item.icon}
|
||||||
|
color={colors.primary.icon}
|
||||||
|
size={SIZE.lg}
|
||||||
|
/>
|
||||||
|
<Paragraph
|
||||||
|
color={colors.secondary.paragraph}
|
||||||
|
size={SIZE.xxxs - 1}
|
||||||
|
>
|
||||||
|
{item.title}
|
||||||
|
</Paragraph>
|
||||||
|
</Pressable>
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{props.navigationState.routes.map((route, index) => {
|
||||||
|
const isFocused = props.navigationState.index === index;
|
||||||
|
|
||||||
|
return route.key === "settings" ? (
|
||||||
|
<SettingsIcon
|
||||||
|
isFocused={isFocused}
|
||||||
|
jumpTo={props.jumpTo}
|
||||||
|
route={route}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<Pressable
|
||||||
|
key={route.key}
|
||||||
|
onPress={() => {
|
||||||
|
props.jumpTo(route.key);
|
||||||
|
switch (route.key) {
|
||||||
|
case "notebooks":
|
||||||
|
Navigation.routeNeedsUpdate(
|
||||||
|
"Notebooks",
|
||||||
|
Navigation.routeUpdateFunctions.Notebooks
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "tags":
|
||||||
|
Navigation.routeNeedsUpdate(
|
||||||
|
"Tags",
|
||||||
|
Navigation.routeUpdateFunctions.Tags
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
borderRadius: 10,
|
||||||
|
opacity: isFocused ? 1 : 0.6,
|
||||||
|
paddingVertical: 2,
|
||||||
|
width: "25%"
|
||||||
|
}}
|
||||||
|
type={isFocused ? "selected" : "plain"}
|
||||||
|
>
|
||||||
|
<Icon
|
||||||
|
name={getIcon(route.key)}
|
||||||
|
color={
|
||||||
|
isFocused ? colors.primary.accent : colors.primary.icon
|
||||||
|
}
|
||||||
|
size={SIZE.lg}
|
||||||
|
/>
|
||||||
|
<Paragraph
|
||||||
|
color={
|
||||||
|
isFocused
|
||||||
|
? colors.primary.paragraph
|
||||||
|
: colors.secondary.paragraph
|
||||||
|
}
|
||||||
|
size={SIZE.xxxs - 1}
|
||||||
|
>
|
||||||
|
{route.title}
|
||||||
|
</Paragraph>
|
||||||
|
</Pressable>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|||||||
@@ -18,85 +18,146 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { useThemeColors } from "@notesnook/theme";
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
import React from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import { View } from "react-native";
|
import { View } from "react-native";
|
||||||
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||||
import ToggleSwitch from "toggle-switch-react-native";
|
import { db } from "../../common/database";
|
||||||
|
import { useTotalNotes } from "../../hooks/use-db-item";
|
||||||
import Navigation from "../../services/navigation";
|
import Navigation from "../../services/navigation";
|
||||||
import useNavigationStore from "../../stores/use-navigation-store";
|
import { useFavoriteStore } from "../../stores/use-favorite-store";
|
||||||
import { SIZE, normalize } from "../../utils/size";
|
import useNavigationStore, {
|
||||||
import { Button } from "../ui/button";
|
RouteParams
|
||||||
|
} from "../../stores/use-navigation-store";
|
||||||
|
import { useNoteStore } from "../../stores/use-notes-store";
|
||||||
|
import { useTrashStore } from "../../stores/use-trash-store";
|
||||||
|
import { SideMenuItem } from "../../utils/menu-items";
|
||||||
|
import { SIZE } from "../../utils/size";
|
||||||
|
import { DefaultAppStyles } from "../../utils/styles";
|
||||||
import { Pressable } from "../ui/pressable";
|
import { Pressable } from "../ui/pressable";
|
||||||
import Heading from "../ui/typography/heading";
|
|
||||||
import Paragraph from "../ui/typography/paragraph";
|
import Paragraph from "../ui/typography/paragraph";
|
||||||
import { strings } from "@notesnook/intl";
|
|
||||||
|
|
||||||
function _MenuItem({
|
function _MenuItem({
|
||||||
item,
|
item,
|
||||||
index,
|
index,
|
||||||
testID,
|
testID,
|
||||||
rightBtn
|
renderIcon
|
||||||
}: {
|
}: {
|
||||||
item: any;
|
item: SideMenuItem;
|
||||||
index: number;
|
index?: number;
|
||||||
testID: string;
|
testID?: string;
|
||||||
rightBtn?: {
|
renderIcon?: (item: SideMenuItem, size: number) => React.ReactNode;
|
||||||
name: string;
|
|
||||||
icon: string;
|
|
||||||
func: () => void;
|
|
||||||
};
|
|
||||||
}) {
|
}) {
|
||||||
|
const [itemCount, setItemCount] = useState(0);
|
||||||
const { colors } = useThemeColors();
|
const { colors } = useThemeColors();
|
||||||
const isFocused = useNavigationStore(
|
const isFocused = useNavigationStore(
|
||||||
(state) => state.focusedRouteId === item.name
|
(state) => state.focusedRouteId === item.id
|
||||||
);
|
);
|
||||||
const primaryColors = isFocused ? colors.selected : colors.primary;
|
const totalNotes = useTotalNotes(
|
||||||
|
item.dataType as "notebook" | "tag" | "color"
|
||||||
|
);
|
||||||
|
const getTotalNotesRef = useRef(totalNotes.getTotalNotes);
|
||||||
|
getTotalNotesRef.current = totalNotes.getTotalNotes;
|
||||||
|
|
||||||
|
const menuItemCount = !item.data
|
||||||
|
? itemCount
|
||||||
|
: totalNotes.totalNotes(item.data.id);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
let unsub: () => void;
|
||||||
|
if (!item.data) {
|
||||||
|
switch (item.id) {
|
||||||
|
case "Notes":
|
||||||
|
unsub = useNoteStore.subscribe((state) => {
|
||||||
|
setItemCount(
|
||||||
|
useNoteStore.getState().items?.placeholders?.length || 0
|
||||||
|
);
|
||||||
|
});
|
||||||
|
setItemCount(
|
||||||
|
useNoteStore.getState().items?.placeholders?.length || 0
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "Favorites":
|
||||||
|
unsub = useFavoriteStore.subscribe((state) => {
|
||||||
|
setItemCount(state.items?.placeholders.length || 0);
|
||||||
|
});
|
||||||
|
setItemCount(
|
||||||
|
useFavoriteStore.getState().items?.placeholders?.length || 0
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "Reminders":
|
||||||
|
unsub = useFavoriteStore.subscribe((state) => {
|
||||||
|
setItemCount(state.items?.placeholders.length || 0);
|
||||||
|
});
|
||||||
|
setItemCount(
|
||||||
|
useFavoriteStore.getState().items?.placeholders?.length || 0
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case "Monographs":
|
||||||
|
db.monographs.all.count().then((count) => {
|
||||||
|
setItemCount(count);
|
||||||
|
});
|
||||||
|
// TODO make it reactive?
|
||||||
|
break;
|
||||||
|
case "Trash":
|
||||||
|
unsub = useTrashStore.subscribe((state) => {
|
||||||
|
setItemCount(state.items?.placeholders.length || 0);
|
||||||
|
});
|
||||||
|
setItemCount(
|
||||||
|
useTrashStore.getState().items?.placeholders?.length || 0
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
getTotalNotesRef.current?.([item.data.id]);
|
||||||
|
}
|
||||||
|
return () => {
|
||||||
|
unsub?.();
|
||||||
|
};
|
||||||
|
}, [item.data, item.id]);
|
||||||
|
|
||||||
const _onPress = () => {
|
const _onPress = () => {
|
||||||
if (item.func) {
|
if (item.onPress) return item.onPress(item);
|
||||||
item.func();
|
|
||||||
} else {
|
if (useNavigationStore.getState().currentRoute !== item.id) {
|
||||||
if (useNavigationStore.getState().currentRoute !== item.name) {
|
Navigation.navigate(item.id as keyof RouteParams, {
|
||||||
Navigation.navigate(item.name, {
|
canGoBack: false
|
||||||
canGoBack: false,
|
|
||||||
beta: item.isBeta
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (item.close) {
|
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
Navigation.closeDrawer();
|
Navigation.closeDrawer();
|
||||||
});
|
});
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Pressable
|
<Pressable
|
||||||
testID={testID}
|
testID={testID}
|
||||||
key={item.name + index}
|
key={item.id}
|
||||||
onPress={_onPress}
|
onPress={_onPress}
|
||||||
|
onLongPress={() => item.onLongPress?.(item)}
|
||||||
type={isFocused ? "selected" : "plain"}
|
type={isFocused ? "selected" : "plain"}
|
||||||
style={{
|
style={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
alignSelf: "center",
|
alignSelf: "center",
|
||||||
borderRadius: 5,
|
borderRadius: 5,
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
paddingHorizontal: 8,
|
paddingHorizontal: DefaultAppStyles.GAP_SMALL,
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
height: normalize(50),
|
paddingVertical: DefaultAppStyles.GAP_VERTICAL
|
||||||
marginBottom: 5
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center"
|
alignItems: "center",
|
||||||
|
gap: DefaultAppStyles.GAP_SMALL
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{renderIcon ? (
|
||||||
|
renderIcon(item, SIZE.md)
|
||||||
|
) : (
|
||||||
<Icon
|
<Icon
|
||||||
style={{
|
style={{
|
||||||
width: 30,
|
|
||||||
textAlignVertical: "center",
|
textAlignVertical: "center",
|
||||||
textAlign: "left"
|
textAlign: "left"
|
||||||
}}
|
}}
|
||||||
@@ -106,66 +167,42 @@ function _MenuItem({
|
|||||||
item.icon === "crown"
|
item.icon === "crown"
|
||||||
? colors.static.yellow
|
? colors.static.yellow
|
||||||
: isFocused
|
: isFocused
|
||||||
? colors.selected.icon
|
? colors.selected.paragraph
|
||||||
: colors.secondary.icon
|
: colors.secondary.icon
|
||||||
}
|
}
|
||||||
size={SIZE.lg - 2}
|
size={SIZE.md}
|
||||||
/>
|
/>
|
||||||
{isFocused ? (
|
|
||||||
<Heading color={colors.selected.heading} size={SIZE.md}>
|
|
||||||
{item.title || item.name}
|
|
||||||
</Heading>
|
|
||||||
) : (
|
|
||||||
<Paragraph size={SIZE.md}>{item.title || item.name}</Paragraph>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{item.isBeta ? (
|
<Paragraph
|
||||||
<View
|
color={
|
||||||
style={{
|
isFocused ? colors.primary.paragraph : colors.secondary.paragraph
|
||||||
borderRadius: 100,
|
}
|
||||||
backgroundColor: primaryColors.accent,
|
size={SIZE.sm}
|
||||||
paddingHorizontal: 4,
|
|
||||||
marginLeft: 5,
|
|
||||||
paddingVertical: 2
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<Paragraph color={primaryColors.accentForeground} size={SIZE.xxs}>
|
{item.title}
|
||||||
{strings.beta()}
|
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
</View>
|
</View>
|
||||||
) : null}
|
|
||||||
</View>
|
|
||||||
|
|
||||||
{item.switch ? (
|
{menuItemCount > 0 ? (
|
||||||
<ToggleSwitch
|
<Paragraph
|
||||||
isOn={item.on}
|
size={SIZE.xxs}
|
||||||
onColor={primaryColors.accent}
|
color={
|
||||||
offColor={primaryColors.icon}
|
isFocused ? colors.primary.paragraph : colors.secondary.paragraph
|
||||||
size="small"
|
}
|
||||||
animationSpeed={150}
|
>
|
||||||
onToggle={_onPress}
|
{menuItemCount}
|
||||||
/>
|
</Paragraph>
|
||||||
) : rightBtn ? (
|
|
||||||
<Button
|
|
||||||
title={rightBtn.name}
|
|
||||||
type="shade"
|
|
||||||
height={30}
|
|
||||||
fontSize={SIZE.xs}
|
|
||||||
iconSize={SIZE.xs}
|
|
||||||
icon={rightBtn.icon}
|
|
||||||
style={{
|
|
||||||
borderRadius: 100,
|
|
||||||
paddingHorizontal: 16
|
|
||||||
}}
|
|
||||||
onPress={rightBtn.func}
|
|
||||||
/>
|
|
||||||
) : null}
|
) : null}
|
||||||
</Pressable>
|
</Pressable>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MenuItem = React.memo(_MenuItem, (prev, next) => {
|
export const MenuItem = React.memo(_MenuItem, (prev, next) => {
|
||||||
if (prev.item.name !== next.item.name) return false;
|
if (
|
||||||
if (prev.rightBtn?.name !== next.rightBtn?.name) return false;
|
prev.item.id !== next.item.id &&
|
||||||
|
prev.item.data?.dateModified !== next.item.data?.dateModified
|
||||||
|
)
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -18,30 +18,23 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Notebook, Tag } from "@notesnook/core";
|
import { Notebook, Tag } from "@notesnook/core";
|
||||||
import { useThemeColors } from "@notesnook/theme";
|
import React, { useEffect, useMemo } from "react";
|
||||||
import React, { useEffect, useRef, useState } from "react";
|
|
||||||
import { View } from "react-native";
|
import { View } from "react-native";
|
||||||
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
|
||||||
import { db } from "../../common/database";
|
import { db } from "../../common/database";
|
||||||
import NotebookScreen from "../../screens/notebook";
|
import NotebookScreen from "../../screens/notebook";
|
||||||
import { TaggedNotes } from "../../screens/notes/tagged";
|
import { TaggedNotes } from "../../screens/notes/tagged";
|
||||||
import Navigation from "../../services/navigation";
|
import Navigation from "../../services/navigation";
|
||||||
import { useMenuStore } from "../../stores/use-menu-store";
|
import { useMenuStore } from "../../stores/use-menu-store";
|
||||||
import useNavigationStore from "../../stores/use-navigation-store";
|
|
||||||
import { useSettingStore } from "../../stores/use-setting-store";
|
import { useSettingStore } from "../../stores/use-setting-store";
|
||||||
import { SIZE, normalize } from "../../utils/size";
|
import { SideMenuItem } from "../../utils/menu-items";
|
||||||
import ReorderableList from "../list/reorderable-list";
|
import ReorderableList from "../list/reorderable-list";
|
||||||
import { Button } from "../ui/button";
|
import { MenuItem } from "./menu-item";
|
||||||
import { Notice } from "../ui/notice";
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
import { Pressable } from "../ui/pressable";
|
import { DefaultAppStyles } from "../../utils/styles";
|
||||||
import Seperator from "../ui/seperator";
|
|
||||||
import SheetWrapper from "../ui/sheet";
|
|
||||||
import Heading from "../ui/typography/heading";
|
|
||||||
import Paragraph from "../ui/typography/paragraph";
|
|
||||||
import { strings } from "@notesnook/intl";
|
|
||||||
|
|
||||||
export const PinnedSection = React.memo(
|
export const PinnedSection = React.memo(
|
||||||
function PinnedSection() {
|
function PinnedSection() {
|
||||||
|
const { colors } = useThemeColors();
|
||||||
const menuPins = useMenuStore((state) => state.menuPins);
|
const menuPins = useMenuStore((state) => state.menuPins);
|
||||||
const loading = useSettingStore((state) => state.isAppLoading);
|
const loading = useSettingStore((state) => state.isAppLoading);
|
||||||
const setMenuPins = useMenuStore((state) => state.setMenuPins);
|
const setMenuPins = useMenuStore((state) => state.setMenuPins);
|
||||||
@@ -52,42 +45,55 @@ export const PinnedSection = React.memo(
|
|||||||
}
|
}
|
||||||
}, [loading, setMenuPins]);
|
}, [loading, setMenuPins]);
|
||||||
|
|
||||||
const onPress = (item: Notebook | Tag) => {
|
const onPress = React.useCallback((item: SideMenuItem) => {
|
||||||
if (item.type === "notebook") {
|
const data = item.data as Notebook | Tag;
|
||||||
NotebookScreen.navigate(item);
|
if (data.type === "notebook") {
|
||||||
} else if (item.type === "tag") {
|
NotebookScreen.navigate(data);
|
||||||
TaggedNotes.navigate(item);
|
} else if (data.type === "tag") {
|
||||||
|
TaggedNotes.navigate(data);
|
||||||
}
|
}
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
Navigation.closeDrawer();
|
Navigation.closeDrawer();
|
||||||
});
|
});
|
||||||
};
|
}, []);
|
||||||
const renderItem = ({
|
|
||||||
item,
|
const menuItems = useMemo(
|
||||||
index
|
() =>
|
||||||
}: {
|
menuPins.map((item) => ({
|
||||||
item: Notebook | Tag;
|
id: item.id,
|
||||||
index: number;
|
title: item.title,
|
||||||
}) => {
|
icon: item.type === "notebook" ? "notebook-outline" : "pound",
|
||||||
return <PinItem item={item} onPress={onPress} />;
|
dataType: item.type,
|
||||||
};
|
data: item,
|
||||||
|
onPress: onPress
|
||||||
|
})) as SideMenuItem[],
|
||||||
|
[menuPins, onPress]
|
||||||
|
);
|
||||||
|
|
||||||
|
const renderItem = React.useCallback(({ item }: { item: SideMenuItem }) => {
|
||||||
|
return <MenuItem item={item} />;
|
||||||
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
flexGrow: 1
|
flexGrow: 1,
|
||||||
|
borderTopWidth: 1,
|
||||||
|
borderTopColor: colors.primary.border,
|
||||||
|
marginTop: DefaultAppStyles.GAP_SMALL,
|
||||||
|
paddingTop: DefaultAppStyles.GAP_SMALL
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ReorderableList
|
<ReorderableList
|
||||||
onListOrderChanged={(data) => {
|
onListOrderChanged={(data) => {
|
||||||
db.settings.setSideBarOrder("shortcuts", data);
|
db.settings.setSideBarOrder("shortcuts", data);
|
||||||
}}
|
}}
|
||||||
onHiddenItemsChanged={(data) => {}}
|
onHiddenItemsChanged={() => {}}
|
||||||
canHideItems={false}
|
canHideItems={false}
|
||||||
itemOrder={order}
|
itemOrder={order}
|
||||||
hiddenItems={[]}
|
hiddenItems={[]}
|
||||||
alwaysBounceVertical={false}
|
alwaysBounceVertical={false}
|
||||||
data={menuPins}
|
data={menuItems}
|
||||||
style={{
|
style={{
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
width: "100%"
|
width: "100%"
|
||||||
@@ -97,161 +103,9 @@ export const PinnedSection = React.memo(
|
|||||||
}}
|
}}
|
||||||
showsVerticalScrollIndicator={false}
|
showsVerticalScrollIndicator={false}
|
||||||
renderDraggableItem={renderItem}
|
renderDraggableItem={renderItem}
|
||||||
ListEmptyComponent={
|
|
||||||
<Notice
|
|
||||||
size="small"
|
|
||||||
type="information"
|
|
||||||
text={strings.sideMenuNotice()}
|
|
||||||
style={{
|
|
||||||
marginHorizontal: 12
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
() => true
|
() => true
|
||||||
);
|
);
|
||||||
|
|
||||||
export const PinItem = React.memo(
|
|
||||||
function PinItem({
|
|
||||||
item,
|
|
||||||
onPress,
|
|
||||||
isPlaceholder
|
|
||||||
}: {
|
|
||||||
item: Notebook | Tag;
|
|
||||||
onPress: (item: Notebook | Tag) => void;
|
|
||||||
isPlaceholder?: boolean;
|
|
||||||
}) {
|
|
||||||
const { colors } = useThemeColors();
|
|
||||||
const setMenuPins = useMenuStore((state) => state.setMenuPins);
|
|
||||||
|
|
||||||
const [visible, setVisible] = useState(false);
|
|
||||||
const isFocused = useNavigationStore(
|
|
||||||
(state) => state.focusedRouteId === item.id
|
|
||||||
);
|
|
||||||
const primaryColors = isFocused ? colors.selected : colors.primary;
|
|
||||||
const color = isFocused ? colors.selected.accent : colors.primary.icon;
|
|
||||||
const fwdRef = useRef();
|
|
||||||
|
|
||||||
const icons = {
|
|
||||||
topic: "bookmark",
|
|
||||||
notebook: "book-outline",
|
|
||||||
tag: "pound"
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{visible && (
|
|
||||||
<SheetWrapper
|
|
||||||
onClose={() => {
|
|
||||||
setVisible(false);
|
|
||||||
}}
|
|
||||||
gestureEnabled={false}
|
|
||||||
fwdRef={fwdRef}
|
|
||||||
>
|
|
||||||
<Seperator />
|
|
||||||
<Button
|
|
||||||
title={strings.removeShortcut()}
|
|
||||||
type="error"
|
|
||||||
onPress={async () => {
|
|
||||||
await db.shortcuts.remove(item.id);
|
|
||||||
setVisible(false);
|
|
||||||
setMenuPins();
|
|
||||||
}}
|
|
||||||
fontSize={SIZE.md}
|
|
||||||
width="95%"
|
|
||||||
style={{
|
|
||||||
marginBottom: 30
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</SheetWrapper>
|
|
||||||
)}
|
|
||||||
<Pressable
|
|
||||||
type={isFocused ? "selected" : "plain"}
|
|
||||||
onPress={() => onPress(item)}
|
|
||||||
style={{
|
|
||||||
width: "100%",
|
|
||||||
alignSelf: "center",
|
|
||||||
borderRadius: 5,
|
|
||||||
flexDirection: "row",
|
|
||||||
paddingHorizontal: 8,
|
|
||||||
justifyContent: "space-between",
|
|
||||||
alignItems: "center",
|
|
||||||
height: normalize(50),
|
|
||||||
marginBottom: 5
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
flexDirection: "row",
|
|
||||||
alignItems: "center",
|
|
||||||
flexGrow: 1,
|
|
||||||
flex: 1
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
width: 30,
|
|
||||||
justifyContent: "center"
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
allowFontScaling
|
|
||||||
color={color}
|
|
||||||
size={SIZE.lg - 2}
|
|
||||||
name={icons[item.type]}
|
|
||||||
/>
|
|
||||||
<Icon
|
|
||||||
style={{
|
|
||||||
position: "absolute",
|
|
||||||
bottom: -6,
|
|
||||||
left: -6
|
|
||||||
}}
|
|
||||||
allowFontScaling
|
|
||||||
color={color}
|
|
||||||
size={SIZE.xs}
|
|
||||||
name="arrow-top-right-thick"
|
|
||||||
/>
|
|
||||||
</View>
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
alignItems: "flex-start",
|
|
||||||
flexGrow: 1,
|
|
||||||
flex: 1
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{isFocused ? (
|
|
||||||
<Heading
|
|
||||||
style={{
|
|
||||||
flexWrap: "wrap"
|
|
||||||
}}
|
|
||||||
color={primaryColors.heading}
|
|
||||||
size={SIZE.md}
|
|
||||||
>
|
|
||||||
{item.title}
|
|
||||||
</Heading>
|
|
||||||
) : (
|
|
||||||
<Paragraph
|
|
||||||
numberOfLines={1}
|
|
||||||
color={primaryColors.paragraph}
|
|
||||||
size={SIZE.md}
|
|
||||||
>
|
|
||||||
{item.title}
|
|
||||||
</Paragraph>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</Pressable>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
(prev, next) => {
|
|
||||||
if (!next.item) return false;
|
|
||||||
if (prev.item.title !== next.item.title) return false;
|
|
||||||
if (prev.item?.dateModified !== next.item?.dateModified) return false;
|
|
||||||
if (prev.item?.id !== next.item?.id) return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|||||||
112
apps/mobile/app/components/side-menu/side-menu-header.tsx
Normal file
112
apps/mobile/app/components/side-menu/side-menu-header.tsx
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/*
|
||||||
|
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 { useThemeColors } from "@notesnook/theme";
|
||||||
|
import React from "react";
|
||||||
|
import { View } from "react-native";
|
||||||
|
import { useThemeStore } from "../../stores/use-theme-store";
|
||||||
|
import { SIZE } from "../../utils/size";
|
||||||
|
import { DefaultAppStyles } from "../../utils/styles";
|
||||||
|
import { IconButton, IconButtonProps } from "../ui/icon-button";
|
||||||
|
import { SvgView } from "../ui/svg";
|
||||||
|
import Heading from "../ui/typography/heading";
|
||||||
|
|
||||||
|
export const SideMenuHeader = (props: { rightButtons?: IconButtonProps[] }) => {
|
||||||
|
const { colors, isDark } = useThemeColors();
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: DefaultAppStyles.GAP
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
gap: DefaultAppStyles.GAP_SMALL,
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
backgroundColor: "black",
|
||||||
|
width: 28,
|
||||||
|
height: 28,
|
||||||
|
borderRadius: 10
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SvgView
|
||||||
|
width={28}
|
||||||
|
height={28}
|
||||||
|
src={`<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<g clip-path="url(#clip0_24_33)">
|
||||||
|
<path d="M1024 0H0V1024H1024V0Z" fill="black"/>
|
||||||
|
<path d="M724.985 682.919C707.73 733.33 673.15 775.984 627.397 803.291C581.645 830.598 527.687 840.787 475.128 832.044C422.568 823.301 374.814 796.194 340.365 755.546C305.916 714.898 287.006 663.347 287 610.064V499.814L366.121 532.867V610.019C366.114 630.798 370.555 651.337 379.145 670.256C387.735 689.176 400.276 706.037 415.925 719.707C418.895 722.294 421.978 724.814 425.161 727.166C448.518 744.554 476.563 754.518 505.655 755.763C506.645 755.763 507.601 755.842 508.58 755.864C509.559 755.887 510.83 755.864 511.955 755.864C513.08 755.864 514.205 755.864 515.33 755.864C516.455 755.864 517.265 755.864 518.255 755.763C547.336 754.515 575.371 744.56 598.726 727.188C601.899 724.837 604.981 722.328 607.963 719.741C628.519 701.761 643.619 678.375 651.545 652.241L724.985 682.919Z" fill="white"/>
|
||||||
|
<path d="M737 414V610.065C737 612.596 737 615.139 736.842 617.67L657.879 584.651V414C657.866 376.316 643.272 340.099 617.154 312.934C591.035 285.77 555.419 269.766 517.765 268.274C480.11 266.782 443.339 279.918 415.154 304.931C386.968 329.944 369.554 364.893 366.56 402.457C366.279 406.26 366.121 410.119 366.121 414V462.712L287 429.637V189H512C571.674 189 628.903 212.705 671.099 254.901C713.295 297.097 737 354.326 737 414Z" fill="white"/>
|
||||||
|
</g>
|
||||||
|
<defs>
|
||||||
|
<clipPath id="clip0_24_33">
|
||||||
|
<rect width="1024" height="1024" rx="200" fill="white"/>
|
||||||
|
</clipPath>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
`}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Heading size={SIZE.lg}>Notesnook</Heading>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: DefaultAppStyles.GAP_SMALL
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{props.rightButtons?.map((button, index) => (
|
||||||
|
<IconButton
|
||||||
|
key={index}
|
||||||
|
{...button}
|
||||||
|
style={{
|
||||||
|
width: 28,
|
||||||
|
height: 28
|
||||||
|
}}
|
||||||
|
color={colors.primary.icon}
|
||||||
|
size={SIZE.lg}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<IconButton
|
||||||
|
onPress={() => {
|
||||||
|
useThemeStore.getState().setColorScheme();
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
width: 28,
|
||||||
|
height: 28
|
||||||
|
}}
|
||||||
|
color={colors.primary.icon}
|
||||||
|
name={isDark ? "weather-night" : "weather-sunny"}
|
||||||
|
size={SIZE.lg}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
105
apps/mobile/app/components/side-menu/side-menu-home.tsx
Normal file
105
apps/mobile/app/components/side-menu/side-menu-home.tsx
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
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 { DraxProvider, DraxScrollView } from "react-native-drax";
|
||||||
|
import { db } from "../../common/database";
|
||||||
|
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
|
||||||
|
import { useMenuStore } from "../../stores/use-menu-store";
|
||||||
|
import { useSettingStore } from "../../stores/use-setting-store";
|
||||||
|
import { MenuItemsList } from "../../utils/menu-items";
|
||||||
|
import { DefaultAppStyles } from "../../utils/styles";
|
||||||
|
import ReorderableList from "../list/reorderable-list";
|
||||||
|
import { ColorSection } from "./color-section";
|
||||||
|
import { MenuItem } from "./menu-item";
|
||||||
|
import { PinnedSection } from "./pinned-section";
|
||||||
|
import { SideMenuHeader } from "./side-menu-header";
|
||||||
|
|
||||||
|
export function SideMenuHome() {
|
||||||
|
const { colors } = useThemeColors();
|
||||||
|
const [isAppLoading, introCompleted] = useSettingStore((state) => [
|
||||||
|
state.isAppLoading,
|
||||||
|
state.settings.introCompleted
|
||||||
|
]);
|
||||||
|
const [order, hiddensItems] = useMenuStore((state) => [
|
||||||
|
state.order["routes"],
|
||||||
|
state.hiddenItems["routes"]
|
||||||
|
]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
height: "100%",
|
||||||
|
width: "100%",
|
||||||
|
paddingTop: DefaultAppStyles.GAP_SMALL,
|
||||||
|
backgroundColor: colors.primary.background,
|
||||||
|
gap: DefaultAppStyles.GAP,
|
||||||
|
paddingHorizontal: DefaultAppStyles.GAP
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SideMenuHeader />
|
||||||
|
|
||||||
|
{!isAppLoading && introCompleted ? (
|
||||||
|
<DraxProvider>
|
||||||
|
<DraxScrollView nestedScrollEnabled={false}>
|
||||||
|
<ReorderableList
|
||||||
|
onListOrderChanged={(data) => {
|
||||||
|
db.settings.setSideBarOrder("routes", data);
|
||||||
|
}}
|
||||||
|
onHiddenItemsChanged={(data) => {
|
||||||
|
db.settings.setSideBarHiddenItems("routes", data);
|
||||||
|
}}
|
||||||
|
itemOrder={order}
|
||||||
|
hiddenItems={hiddensItems}
|
||||||
|
alwaysBounceVertical={false}
|
||||||
|
data={MenuItemsList}
|
||||||
|
style={{
|
||||||
|
width: "100%"
|
||||||
|
}}
|
||||||
|
contentContainerStyle={{
|
||||||
|
gap: 2
|
||||||
|
}}
|
||||||
|
showsVerticalScrollIndicator={false}
|
||||||
|
renderDraggableItem={({ item, index }) => {
|
||||||
|
return (
|
||||||
|
<MenuItem
|
||||||
|
key={item.title}
|
||||||
|
item={{
|
||||||
|
...item,
|
||||||
|
title:
|
||||||
|
strings.routes[
|
||||||
|
item.title as keyof typeof strings.routes
|
||||||
|
]?.() || item.title
|
||||||
|
}}
|
||||||
|
testID={item.title}
|
||||||
|
index={index}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<ColorSection />
|
||||||
|
<PinnedSection />
|
||||||
|
</DraxScrollView>
|
||||||
|
</DraxProvider>
|
||||||
|
) : null}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
450
apps/mobile/app/components/side-menu/side-menu-notebooks.tsx
Normal file
450
apps/mobile/app/components/side-menu/side-menu-notebooks.tsx
Normal file
@@ -0,0 +1,450 @@
|
|||||||
|
/*
|
||||||
|
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 { Notebook } from "@notesnook/core";
|
||||||
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
|
import React, { useEffect } from "react";
|
||||||
|
import { FlatList, ListRenderItemInfo, View } from "react-native";
|
||||||
|
import { UseBoundStore } from "zustand";
|
||||||
|
import { db } from "../../common/database";
|
||||||
|
import { useTotalNotes } from "../../hooks/use-db-item";
|
||||||
|
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
|
||||||
|
import NotebookScreen from "../../screens/notebook";
|
||||||
|
import {
|
||||||
|
eSubscribeEvent,
|
||||||
|
eUnSubscribeEvent
|
||||||
|
} from "../../services/event-manager";
|
||||||
|
import { TreeItem } from "../../stores/create-notebook-tree-stores";
|
||||||
|
import { SelectionStore } from "../../stores/item-selection-store";
|
||||||
|
import useNavigationStore from "../../stores/use-navigation-store";
|
||||||
|
import { useNotebooks } from "../../stores/use-notebook-store";
|
||||||
|
import { eOnNotebookUpdated } from "../../utils/events";
|
||||||
|
import { SIZE } from "../../utils/size";
|
||||||
|
import { DefaultAppStyles } from "../../utils/styles";
|
||||||
|
import { Properties } from "../properties";
|
||||||
|
import { AddNotebookSheet } from "../sheets/add-notebook";
|
||||||
|
import AppIcon from "../ui/AppIcon";
|
||||||
|
import { IconButton } from "../ui/icon-button";
|
||||||
|
import { Pressable } from "../ui/pressable";
|
||||||
|
import Paragraph from "../ui/typography/paragraph";
|
||||||
|
import { SideMenuHeader } from "./side-menu-header";
|
||||||
|
import {
|
||||||
|
useSideMenuNotebookExpandedStore,
|
||||||
|
useSideMenuNotebookSelectionStore,
|
||||||
|
useSideMenuNotebookTreeStore
|
||||||
|
} from "./stores";
|
||||||
|
|
||||||
|
const NotebookItem = ({
|
||||||
|
index,
|
||||||
|
item,
|
||||||
|
expanded,
|
||||||
|
selected,
|
||||||
|
onToggleExpanded,
|
||||||
|
focused,
|
||||||
|
selectionEnabled,
|
||||||
|
selectionStore,
|
||||||
|
onItemUpdate,
|
||||||
|
onPress,
|
||||||
|
onLongPress
|
||||||
|
}: {
|
||||||
|
index: number;
|
||||||
|
item: TreeItem;
|
||||||
|
expanded?: boolean;
|
||||||
|
onToggleExpanded?: () => void;
|
||||||
|
selected?: boolean;
|
||||||
|
focused?: boolean;
|
||||||
|
selectionEnabled?: boolean;
|
||||||
|
selectionStore: UseBoundStore<SelectionStore>;
|
||||||
|
onItemUpdate: (id?: string) => void;
|
||||||
|
onPress?: () => void;
|
||||||
|
onLongPress?: () => void;
|
||||||
|
}) => {
|
||||||
|
const notebook = item.notebook;
|
||||||
|
const [nestedNotebooksSelected, setNestedNotebooksSelected] =
|
||||||
|
React.useState(false);
|
||||||
|
const isFocused = focused;
|
||||||
|
const { totalNotes, getTotalNotes } = useTotalNotes("notebook");
|
||||||
|
const getTotalNotesRef = React.useRef(getTotalNotes);
|
||||||
|
getTotalNotesRef.current = getTotalNotes;
|
||||||
|
const { colors } = useThemeColors("sheet");
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getTotalNotesRef.current([item.notebook.id]);
|
||||||
|
}, [item.notebook]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectionEnabled) {
|
||||||
|
const selector = db.relations.from(
|
||||||
|
{
|
||||||
|
type: "notebook",
|
||||||
|
id: item.notebook.id
|
||||||
|
},
|
||||||
|
"notebook"
|
||||||
|
).selector;
|
||||||
|
selector.ids().then((ids) => {
|
||||||
|
setNestedNotebooksSelected(
|
||||||
|
ids.length === 0
|
||||||
|
? true
|
||||||
|
: ids.every(
|
||||||
|
(id) => selectionStore.getState().selection[id] === "selected"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [selected, item.notebook.id, selectionEnabled, selectionStore]);
|
||||||
|
|
||||||
|
async function selectAll() {
|
||||||
|
const selector = db.relations.from(
|
||||||
|
{
|
||||||
|
type: "notebook",
|
||||||
|
id: item.notebook.id
|
||||||
|
},
|
||||||
|
"notebook"
|
||||||
|
).selector;
|
||||||
|
const ids = await selector.ids();
|
||||||
|
selectionStore.setState({
|
||||||
|
selection: {
|
||||||
|
...selectionStore.getState().selection,
|
||||||
|
...ids.reduce((acc: any, id) => {
|
||||||
|
acc[id] = "selected";
|
||||||
|
return acc;
|
||||||
|
}, {})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setNestedNotebooksSelected(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deselectAll() {
|
||||||
|
const selector = db.relations.from(
|
||||||
|
{
|
||||||
|
type: "notebook",
|
||||||
|
id: item.notebook.id
|
||||||
|
},
|
||||||
|
"notebook"
|
||||||
|
).selector;
|
||||||
|
const ids = await selector.ids();
|
||||||
|
useSideMenuNotebookSelectionStore.setState({
|
||||||
|
selection: {
|
||||||
|
...selectionStore.getState().selection,
|
||||||
|
...ids.reduce((acc: any, id) => {
|
||||||
|
acc[id] = "deselected";
|
||||||
|
return acc;
|
||||||
|
}, {})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setNestedNotebooksSelected(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const unsub = selectionStore.subscribe((state) => {
|
||||||
|
if (state.enabled) {
|
||||||
|
const selector = db.relations.from(
|
||||||
|
{
|
||||||
|
type: "notebook",
|
||||||
|
id: item.notebook.id
|
||||||
|
},
|
||||||
|
"notebook"
|
||||||
|
).selector;
|
||||||
|
selector.ids().then((ids) => {
|
||||||
|
if (!ids.length) return;
|
||||||
|
setNestedNotebooksSelected(
|
||||||
|
ids.length === 0
|
||||||
|
? true
|
||||||
|
: ids.every(
|
||||||
|
(id) => selectionStore.getState().selection[id] === "selected"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
unsub();
|
||||||
|
};
|
||||||
|
}, [item.notebook.id, selectionStore]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const onNotebookUpdate = (id?: string) => {
|
||||||
|
if (id && id !== notebook.id) return;
|
||||||
|
onItemUpdate(id);
|
||||||
|
};
|
||||||
|
|
||||||
|
eSubscribeEvent(eOnNotebookUpdated, onNotebookUpdate);
|
||||||
|
return () => {
|
||||||
|
eUnSubscribeEvent(eOnNotebookUpdated, onNotebookUpdate);
|
||||||
|
};
|
||||||
|
}, [notebook.id, onItemUpdate]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
paddingLeft: item.depth > 0 && item.depth < 6 ? 15 : undefined,
|
||||||
|
width: "100%",
|
||||||
|
marginTop: 2
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Pressable
|
||||||
|
type={isFocused ? "selected" : "transparent"}
|
||||||
|
onLongPress={() => {
|
||||||
|
onLongPress?.();
|
||||||
|
}}
|
||||||
|
testID={`notebook-sheet-item-${item.depth}-${index}`}
|
||||||
|
onPress={async () => {
|
||||||
|
if (selectionEnabled) {
|
||||||
|
if (selected && !nestedNotebooksSelected) {
|
||||||
|
console.log("Select all...");
|
||||||
|
return selectAll();
|
||||||
|
}
|
||||||
|
await deselectAll();
|
||||||
|
selectionStore
|
||||||
|
.getState()
|
||||||
|
.markAs(item.notebook, selected ? "deselected" : "selected");
|
||||||
|
if (selectionStore.getState().getSelectedItemIds().length === 0) {
|
||||||
|
selectionStore.setState({
|
||||||
|
enabled: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
onPress?.();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
justifyContent: "space-between",
|
||||||
|
width: "100%",
|
||||||
|
alignItems: "center",
|
||||||
|
flexDirection: "row",
|
||||||
|
borderRadius: 5,
|
||||||
|
paddingRight: DefaultAppStyles.GAP_SMALL
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconButton
|
||||||
|
size={SIZE.md}
|
||||||
|
color={selected ? colors.selected.icon : colors.primary.icon}
|
||||||
|
onPress={() => {
|
||||||
|
onToggleExpanded?.();
|
||||||
|
}}
|
||||||
|
top={0}
|
||||||
|
left={0}
|
||||||
|
bottom={0}
|
||||||
|
right={0}
|
||||||
|
style={{
|
||||||
|
width: 32,
|
||||||
|
height: 32,
|
||||||
|
borderRadius: 5
|
||||||
|
}}
|
||||||
|
name={expanded ? "chevron-down" : "chevron-right"}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Paragraph
|
||||||
|
color={
|
||||||
|
isFocused ? colors.selected.paragraph : colors.secondary.paragraph
|
||||||
|
}
|
||||||
|
size={SIZE.xs}
|
||||||
|
>
|
||||||
|
{notebook?.title}
|
||||||
|
</Paragraph>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{selectionEnabled ? (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
width: 22,
|
||||||
|
height: 22,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AppIcon
|
||||||
|
name={
|
||||||
|
selected
|
||||||
|
? !nestedNotebooksSelected
|
||||||
|
? "checkbox-intermediate"
|
||||||
|
: "checkbox-outline"
|
||||||
|
: "checkbox-blank-outline"
|
||||||
|
}
|
||||||
|
color={selected ? colors.selected.icon : colors.primary.icon}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{totalNotes(notebook?.id) ? (
|
||||||
|
<Paragraph size={SIZE.xxs} color={colors.secondary.paragraph}>
|
||||||
|
{totalNotes?.(notebook?.id)}
|
||||||
|
</Paragraph>
|
||||||
|
) : null}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SideMenuNotebooks = () => {
|
||||||
|
const tree = useSideMenuNotebookTreeStore((state) => state.tree);
|
||||||
|
const [notebooks, loading] = useNotebooks();
|
||||||
|
const insets = useGlobalSafeAreaInsets();
|
||||||
|
|
||||||
|
const loadRootNotebooks = React.useCallback(async () => {
|
||||||
|
if (!notebooks) return;
|
||||||
|
const _notebooks: Notebook[] = [];
|
||||||
|
for (let i = 0; i < notebooks.placeholders.length; i++) {
|
||||||
|
_notebooks[i] = (await notebooks?.item(i))?.item as Notebook;
|
||||||
|
}
|
||||||
|
useSideMenuNotebookTreeStore.getState().addNotebooks("root", _notebooks, 0);
|
||||||
|
}, [notebooks]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
(async () => {
|
||||||
|
if (!loading) {
|
||||||
|
loadRootNotebooks();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
}, [loadRootNotebooks, loading]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
useSideMenuNotebookSelectionStore.setState({
|
||||||
|
selectAll: async () => {
|
||||||
|
const allNotebooks = await db.notebooks.all.items();
|
||||||
|
const allSelected = allNotebooks.every((notebook) => {
|
||||||
|
return (
|
||||||
|
useSideMenuNotebookSelectionStore.getState().selection[
|
||||||
|
notebook.id
|
||||||
|
] === "selected"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (allSelected) {
|
||||||
|
useSideMenuNotebookSelectionStore.setState({
|
||||||
|
selection: {}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
useSideMenuNotebookSelectionStore.setState({
|
||||||
|
selection: allNotebooks.reduce((acc: any, item) => {
|
||||||
|
acc[item.id] = "selected";
|
||||||
|
return acc;
|
||||||
|
}, {})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const renderItem = React.useCallback((info: ListRenderItemInfo<TreeItem>) => {
|
||||||
|
return <NotebookItemWrapper index={info.index} item={info.item} />;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FlatList
|
||||||
|
style={{
|
||||||
|
paddingHorizontal: DefaultAppStyles.GAP,
|
||||||
|
paddingTop: DefaultAppStyles.GAP_SMALL
|
||||||
|
}}
|
||||||
|
data={tree}
|
||||||
|
keyExtractor={(item) => item.notebook.id}
|
||||||
|
windowSize={3}
|
||||||
|
ListHeaderComponent={
|
||||||
|
<SideMenuHeader
|
||||||
|
rightButtons={[
|
||||||
|
{
|
||||||
|
name: "plus",
|
||||||
|
onPress: () => {
|
||||||
|
AddNotebookSheet.present();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
stickyHeaderIndices={[0]}
|
||||||
|
renderItem={renderItem}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const NotebookItemWrapper = ({
|
||||||
|
item,
|
||||||
|
index
|
||||||
|
}: {
|
||||||
|
item: TreeItem;
|
||||||
|
index: number;
|
||||||
|
}) => {
|
||||||
|
const expanded = useSideMenuNotebookExpandedStore(
|
||||||
|
(state) => state.expanded[item.notebook.id]
|
||||||
|
);
|
||||||
|
const selectionEnabled = useSideMenuNotebookSelectionStore(
|
||||||
|
(state) => state.enabled
|
||||||
|
);
|
||||||
|
const selected = useSideMenuNotebookSelectionStore(
|
||||||
|
(state) => state.selection[item.notebook.id] === "selected"
|
||||||
|
);
|
||||||
|
const focused = useNavigationStore(
|
||||||
|
(state) => state.focusedRouteId === item.notebook.id
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (expanded) {
|
||||||
|
useSideMenuNotebookTreeStore
|
||||||
|
.getState()
|
||||||
|
.fetchAndAdd(item.notebook.id, item.depth + 1);
|
||||||
|
} else {
|
||||||
|
useSideMenuNotebookTreeStore.getState().removeChildren(item.notebook.id);
|
||||||
|
}
|
||||||
|
}, [expanded, item.depth, item.notebook]);
|
||||||
|
|
||||||
|
const onItemUpdate = React.useCallback(async () => {
|
||||||
|
const notebook = await db.notebooks.notebook(item.notebook.id);
|
||||||
|
if (notebook) {
|
||||||
|
useSideMenuNotebookTreeStore
|
||||||
|
.getState()
|
||||||
|
.updateItem(item.notebook.id, notebook);
|
||||||
|
} else {
|
||||||
|
useSideMenuNotebookTreeStore.getState().removeItem(item.notebook.id);
|
||||||
|
}
|
||||||
|
}, [item.notebook.id]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NotebookItem
|
||||||
|
item={item}
|
||||||
|
index={index}
|
||||||
|
expanded={expanded}
|
||||||
|
onToggleExpanded={() => {
|
||||||
|
useSideMenuNotebookExpandedStore
|
||||||
|
.getState()
|
||||||
|
.setExpanded(item.notebook.id);
|
||||||
|
}}
|
||||||
|
selected={selected}
|
||||||
|
selectionEnabled={selectionEnabled}
|
||||||
|
selectionStore={useSideMenuNotebookSelectionStore}
|
||||||
|
onItemUpdate={onItemUpdate}
|
||||||
|
focused={focused}
|
||||||
|
onPress={() => {
|
||||||
|
NotebookScreen.navigate(item.notebook, false);
|
||||||
|
}}
|
||||||
|
onLongPress={() => {
|
||||||
|
Properties.present(item.notebook, false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
207
apps/mobile/app/components/side-menu/side-menu-tags.tsx
Normal file
207
apps/mobile/app/components/side-menu/side-menu-tags.tsx
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
/*
|
||||||
|
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 { Tag, VirtualizedGrouping } from "@notesnook/core";
|
||||||
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
|
import React, { useEffect } from "react";
|
||||||
|
import { View } from "react-native";
|
||||||
|
import { FlashList } from "react-native-actions-sheet/dist/src/views/FlashList";
|
||||||
|
import { db } from "../../common/database";
|
||||||
|
import { useDBItem, useTotalNotes } from "../../hooks/use-db-item";
|
||||||
|
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
|
||||||
|
import { TaggedNotes } from "../../screens/notes/tagged";
|
||||||
|
import useNavigationStore from "../../stores/use-navigation-store";
|
||||||
|
import { useTags } from "../../stores/use-tag-store";
|
||||||
|
import { SIZE } from "../../utils/size";
|
||||||
|
import { DefaultAppStyles } from "../../utils/styles";
|
||||||
|
import { Properties } from "../properties";
|
||||||
|
import AppIcon from "../ui/AppIcon";
|
||||||
|
import { Pressable } from "../ui/pressable";
|
||||||
|
import Paragraph from "../ui/typography/paragraph";
|
||||||
|
import { SideMenuHeader } from "./side-menu-header";
|
||||||
|
import { useSideMenuTagsSelectionStore } from "./stores";
|
||||||
|
|
||||||
|
const TagItem = (props: {
|
||||||
|
tags: VirtualizedGrouping<Tag>;
|
||||||
|
id: number | string;
|
||||||
|
}) => {
|
||||||
|
const { colors } = useThemeColors();
|
||||||
|
const [item] = useDBItem(props.id, "tag", props.tags);
|
||||||
|
const isSelected = useSideMenuTagsSelectionStore((state) =>
|
||||||
|
item?.id ? state.selection[item.id] === "selected" : false
|
||||||
|
);
|
||||||
|
const enabled = useSideMenuTagsSelectionStore((state) => state.enabled);
|
||||||
|
const isFocused = useNavigationStore(
|
||||||
|
(state) => state.focusedRouteId === item?.id
|
||||||
|
);
|
||||||
|
const totalNotes = useTotalNotes("tag");
|
||||||
|
const totalNotesRef = React.useRef(totalNotes);
|
||||||
|
totalNotesRef.current = totalNotes;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (item?.id) {
|
||||||
|
totalNotesRef.current?.getTotalNotes([item?.id]);
|
||||||
|
}
|
||||||
|
}, [item]);
|
||||||
|
|
||||||
|
return item ? (
|
||||||
|
<Pressable
|
||||||
|
type={isSelected || isFocused ? "selected" : "transparent"}
|
||||||
|
onLongPress={() => {
|
||||||
|
Properties.present(item);
|
||||||
|
}}
|
||||||
|
testID={`tag-item-${props.id}`}
|
||||||
|
onPress={() => {
|
||||||
|
if (enabled) {
|
||||||
|
useSideMenuTagsSelectionStore
|
||||||
|
.getState()
|
||||||
|
.markAs(item, isSelected ? "deselected" : "selected");
|
||||||
|
if (
|
||||||
|
useSideMenuTagsSelectionStore.getState().getSelectedItemIds()
|
||||||
|
.length === 0
|
||||||
|
) {
|
||||||
|
useSideMenuTagsSelectionStore.setState({
|
||||||
|
enabled: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TaggedNotes.navigate(item, false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
style={{
|
||||||
|
justifyContent: "space-between",
|
||||||
|
width: "100%",
|
||||||
|
alignItems: "center",
|
||||||
|
flexDirection: "row",
|
||||||
|
borderRadius: 5,
|
||||||
|
paddingRight: DefaultAppStyles.GAP_SMALL
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
width: 32,
|
||||||
|
height: 32,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AppIcon
|
||||||
|
size={SIZE.md}
|
||||||
|
color={isFocused ? colors.selected.icon : colors.secondary.icon}
|
||||||
|
name="pound"
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<Paragraph
|
||||||
|
color={
|
||||||
|
isFocused ? colors.selected.paragraph : colors.secondary.paragraph
|
||||||
|
}
|
||||||
|
size={SIZE.xs}
|
||||||
|
>
|
||||||
|
{item?.title}
|
||||||
|
</Paragraph>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
{enabled ? (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
width: 22,
|
||||||
|
height: 22,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AppIcon
|
||||||
|
name={isSelected ? "checkbox-outline" : "checkbox-blank-outline"}
|
||||||
|
color={isSelected ? colors.selected.icon : colors.primary.icon}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{item?.id && totalNotes.totalNotes?.(item?.id) ? (
|
||||||
|
<Paragraph size={SIZE.xxs} color={colors.secondary.paragraph}>
|
||||||
|
{totalNotes.totalNotes(item?.id)}
|
||||||
|
</Paragraph>
|
||||||
|
) : null}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Pressable>
|
||||||
|
) : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const SideMenuTags = () => {
|
||||||
|
const [tags] = useTags();
|
||||||
|
const insets = useGlobalSafeAreaInsets();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
useSideMenuTagsSelectionStore.setState({
|
||||||
|
selectAll: async () => {
|
||||||
|
const tags = await db.tags.all.items();
|
||||||
|
const allSelected = tags.every((tag) => {
|
||||||
|
return (
|
||||||
|
useSideMenuTagsSelectionStore.getState().selection[tag.id] ===
|
||||||
|
"selected"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (allSelected) {
|
||||||
|
useSideMenuTagsSelectionStore.getState().setSelection({});
|
||||||
|
} else {
|
||||||
|
useSideMenuTagsSelectionStore.getState().setSelection(
|
||||||
|
tags.reduce((acc: any, tag) => {
|
||||||
|
acc[tag.id] = "selected";
|
||||||
|
return acc;
|
||||||
|
}, {})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const renderItem = React.useCallback(
|
||||||
|
(info: { index: number }) => {
|
||||||
|
return <TagItem id={info.index} tags={tags!} />;
|
||||||
|
},
|
||||||
|
[tags]
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
paddingHorizontal: DefaultAppStyles.GAP,
|
||||||
|
paddingTop: DefaultAppStyles.GAP_SMALL,
|
||||||
|
width: "100%",
|
||||||
|
height: "100%"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SideMenuHeader />
|
||||||
|
<FlashList
|
||||||
|
data={tags?.placeholders}
|
||||||
|
estimatedItemSize={32}
|
||||||
|
renderItem={renderItem}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
32
apps/mobile/app/components/side-menu/stores.ts
Normal file
32
apps/mobile/app/components/side-menu/stores.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
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 { createNotebookTreeStores } from "../../stores/create-notebook-tree-stores";
|
||||||
|
import { createItemSelectionStore } from "../../stores/item-selection-store";
|
||||||
|
|
||||||
|
export const {
|
||||||
|
useSideMenuNotebookExpandedStore,
|
||||||
|
useSideMenuNotebookSelectionStore,
|
||||||
|
useSideMenuNotebookTreeStore
|
||||||
|
} = createNotebookTreeStores(true, false);
|
||||||
|
|
||||||
|
export const useSideMenuTagsSelectionStore = createItemSelectionStore(
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
);
|
||||||
@@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { strings } from "@notesnook/intl";
|
||||||
import { useThemeColors } from "@notesnook/theme";
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
import { useNetInfo } from "@react-native-community/netinfo";
|
import { useNetInfo } from "@react-native-community/netinfo";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
@@ -30,13 +31,12 @@ import Sync from "../../services/sync";
|
|||||||
import { useThemeStore } from "../../stores/use-theme-store";
|
import { useThemeStore } from "../../stores/use-theme-store";
|
||||||
import { SyncStatus, useUserStore } from "../../stores/use-user-store";
|
import { SyncStatus, useUserStore } from "../../stores/use-user-store";
|
||||||
import { eOpenLoginDialog } from "../../utils/events";
|
import { eOpenLoginDialog } from "../../utils/events";
|
||||||
import { tabBarRef } from "../../utils/global-refs";
|
import { fluidTabsRef } from "../../utils/global-refs";
|
||||||
import { SIZE } from "../../utils/size";
|
import { SIZE } from "../../utils/size";
|
||||||
import { IconButton } from "../ui/icon-button";
|
import { IconButton } from "../ui/icon-button";
|
||||||
import { Pressable } from "../ui/pressable";
|
import { Pressable } from "../ui/pressable";
|
||||||
import { TimeSince } from "../ui/time-since";
|
import { TimeSince } from "../ui/time-since";
|
||||||
import Paragraph from "../ui/typography/paragraph";
|
import Paragraph from "../ui/typography/paragraph";
|
||||||
import { strings } from "@notesnook/intl";
|
|
||||||
|
|
||||||
export const UserStatus = () => {
|
export const UserStatus = () => {
|
||||||
const { colors, isDark } = useThemeColors();
|
const { colors, isDark } = useThemeColors();
|
||||||
@@ -71,7 +71,7 @@ export const UserStatus = () => {
|
|||||||
<Pressable
|
<Pressable
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
Navigation.navigate("Settings");
|
Navigation.navigate("Settings");
|
||||||
tabBarRef.current.closeDrawer();
|
fluidTabsRef.current.closeDrawer();
|
||||||
}}
|
}}
|
||||||
type="plain"
|
type="plain"
|
||||||
style={{
|
style={{
|
||||||
@@ -206,7 +206,7 @@ export const UserStatus = () => {
|
|||||||
if (user) {
|
if (user) {
|
||||||
Sync.run();
|
Sync.run();
|
||||||
} else {
|
} else {
|
||||||
tabBarRef.current?.closeDrawer();
|
fluidTabsRef.current?.closeDrawer();
|
||||||
eSendEvent(eOpenLoginDialog);
|
eSendEvent(eOpenLoginDialog);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import { RGB_Linear_Shade, hexToRGBA } from "../../../utils/colors";
|
|||||||
import { SIZE } from "../../../utils/size";
|
import { SIZE } from "../../../utils/size";
|
||||||
import NativeTooltip from "../../../utils/tooltip";
|
import NativeTooltip from "../../../utils/tooltip";
|
||||||
import { Pressable, PressableProps } from "../pressable";
|
import { Pressable, PressableProps } from "../pressable";
|
||||||
interface IconButtonProps extends PressableProps {
|
export interface IconButtonProps extends PressableProps {
|
||||||
name: string;
|
name: string;
|
||||||
color?: ColorValue;
|
color?: ColorValue;
|
||||||
size?: number;
|
size?: number;
|
||||||
|
|||||||
@@ -273,13 +273,12 @@ export const Pressable = ({
|
|||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
marginBottom: 0,
|
marginBottom: 0,
|
||||||
borderColor:
|
borderColor: pressed
|
||||||
pressed && !disabled
|
|
||||||
? customSelectedColor
|
? customSelectedColor
|
||||||
? getColorLinearShade(customSelectedColor, 0.3, false)
|
? getColorLinearShade(customSelectedColor, 0.3, false)
|
||||||
: borderSelectedColor || borderColor
|
: borderSelectedColor || borderColor
|
||||||
: borderColor || "transparent",
|
: borderColor || "transparent",
|
||||||
borderWidth: borderWidth
|
borderWidth: noborder ? 0 : borderWidth
|
||||||
},
|
},
|
||||||
style,
|
style,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -18,20 +18,17 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
*/
|
*/
|
||||||
/* eslint-disable no-inner-declarations */
|
/* eslint-disable no-inner-declarations */
|
||||||
import {
|
import {
|
||||||
Color,
|
Item,
|
||||||
createInternalLink,
|
|
||||||
ItemReference,
|
ItemReference,
|
||||||
Note,
|
Note,
|
||||||
Notebook,
|
VAULT_ERRORS,
|
||||||
Reminder,
|
createInternalLink
|
||||||
Tag,
|
|
||||||
TrashItem,
|
|
||||||
VAULT_ERRORS
|
|
||||||
} from "@notesnook/core";
|
} from "@notesnook/core";
|
||||||
import { strings } from "@notesnook/intl";
|
import { strings } from "@notesnook/intl";
|
||||||
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
import { DisplayedNotification } from "@notifee/react-native";
|
import { DisplayedNotification } from "@notifee/react-native";
|
||||||
import Clipboard from "@react-native-clipboard/clipboard";
|
import Clipboard from "@react-native-clipboard/clipboard";
|
||||||
import React, { useCallback, useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import { InteractionManager, Platform } from "react-native";
|
import { InteractionManager, Platform } from "react-native";
|
||||||
import Share from "react-native-share";
|
import Share from "react-native-share";
|
||||||
import { DatabaseLogger, db } from "../common/database";
|
import { DatabaseLogger, db } from "../common/database";
|
||||||
@@ -48,6 +45,11 @@ import { ReferencesList } from "../components/sheets/references";
|
|||||||
import { RelationsList } from "../components/sheets/relations-list/index";
|
import { RelationsList } from "../components/sheets/relations-list/index";
|
||||||
import ReminderSheet from "../components/sheets/reminder";
|
import ReminderSheet from "../components/sheets/reminder";
|
||||||
import { useSideBarDraggingStore } from "../components/side-menu/dragging-store";
|
import { useSideBarDraggingStore } from "../components/side-menu/dragging-store";
|
||||||
|
import {
|
||||||
|
useSideMenuNotebookSelectionStore,
|
||||||
|
useSideMenuTagsSelectionStore
|
||||||
|
} from "../components/side-menu/stores";
|
||||||
|
import { ButtonProps } from "../components/ui/button";
|
||||||
import { useTabStore } from "../screens/editor/tiptap/use-tab-store";
|
import { useTabStore } from "../screens/editor/tiptap/use-tab-store";
|
||||||
import {
|
import {
|
||||||
eSendEvent,
|
eSendEvent,
|
||||||
@@ -69,13 +71,83 @@ import { deleteItems } from "../utils/functions";
|
|||||||
import { convertNoteToText } from "../utils/note-to-text";
|
import { convertNoteToText } from "../utils/note-to-text";
|
||||||
import { sleep } from "../utils/time";
|
import { sleep } from "../utils/time";
|
||||||
|
|
||||||
|
export type ActionId =
|
||||||
|
| "select"
|
||||||
|
| "restore"
|
||||||
|
| "delete"
|
||||||
|
| "reorder"
|
||||||
|
| "rename-tag"
|
||||||
|
| "rename-color"
|
||||||
|
| "pin"
|
||||||
|
| "add-shortcut"
|
||||||
|
| "rename-notebook"
|
||||||
|
| "add-notebook"
|
||||||
|
| "edit-notebook"
|
||||||
|
| "default-notebook"
|
||||||
|
| "move-notes"
|
||||||
|
| "move-notebook"
|
||||||
|
| "disable-reminder"
|
||||||
|
| "edit-reminder"
|
||||||
|
| "delete-reminder"
|
||||||
|
| "delete"
|
||||||
|
| "delete-trash"
|
||||||
|
| "add-reminder"
|
||||||
|
| "copy"
|
||||||
|
| "share"
|
||||||
|
| "read-only"
|
||||||
|
| "local-only"
|
||||||
|
| "duplicate"
|
||||||
|
| "add-note"
|
||||||
|
| "attachments"
|
||||||
|
| "history"
|
||||||
|
| "copy-link"
|
||||||
|
| "reminders"
|
||||||
|
| "lock-unlock"
|
||||||
|
| "publish"
|
||||||
|
| "export"
|
||||||
|
| "notebooks"
|
||||||
|
| "add-tag"
|
||||||
|
| "references"
|
||||||
|
| "pin-to-notifications"
|
||||||
|
| "favorite"
|
||||||
|
| "remove-from-notebook"
|
||||||
|
| "trash";
|
||||||
|
|
||||||
|
export type Action = {
|
||||||
|
id: ActionId;
|
||||||
|
title: string;
|
||||||
|
icon: string;
|
||||||
|
onPress: () => void;
|
||||||
|
isToggle?: boolean;
|
||||||
|
checked?: boolean;
|
||||||
|
pro?: boolean;
|
||||||
|
hidden?: boolean;
|
||||||
|
activeColor?: string;
|
||||||
|
type?: ButtonProps["type"];
|
||||||
|
};
|
||||||
|
|
||||||
|
function isNotePinnedInNotifications(item: Item) {
|
||||||
|
const pinned = Notifications.getPinnedNotes();
|
||||||
|
if (!pinned || pinned.length === 0) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const index = pinned.findIndex((notif) => notif.id === item.id);
|
||||||
|
if (index !== -1) {
|
||||||
|
return pinned[index];
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
export const useActions = ({
|
export const useActions = ({
|
||||||
close,
|
close,
|
||||||
item
|
item,
|
||||||
|
customActionHandlers
|
||||||
}: {
|
}: {
|
||||||
item: Note | Notebook | Reminder | Tag | Color | TrashItem;
|
item: Item;
|
||||||
close: () => void;
|
close: () => void;
|
||||||
|
customActionHandlers?: Record<ActionId, () => void>;
|
||||||
}) => {
|
}) => {
|
||||||
|
const { colors } = useThemeColors();
|
||||||
const setMenuPins = useMenuStore((state) => state.setMenuPins);
|
const setMenuPins = useMenuStore((state) => state.setMenuPins);
|
||||||
const [isPinnedToMenu, setIsPinnedToMenu] = useState(
|
const [isPinnedToMenu, setIsPinnedToMenu] = useState(
|
||||||
db.shortcuts.exists(item.id)
|
db.shortcuts.exists(item.id)
|
||||||
@@ -83,15 +155,14 @@ export const useActions = ({
|
|||||||
const processingId = useRef<"shareNote" | "copyContent">();
|
const processingId = useRef<"shareNote" | "copyContent">();
|
||||||
const user = useUserStore((state) => state.user);
|
const user = useUserStore((state) => state.user);
|
||||||
const [notifPinned, setNotifPinned] = useState<DisplayedNotification>();
|
const [notifPinned, setNotifPinned] = useState<DisplayedNotification>();
|
||||||
|
|
||||||
const [defaultNotebook, setDefaultNotebook] = useState(
|
const [defaultNotebook, setDefaultNotebook] = useState(
|
||||||
db.settings.getDefaultNotebook()
|
db.settings.getDefaultNotebook()
|
||||||
);
|
);
|
||||||
const [noteInCurrentNotebook, setNoteInCurrentNotebook] = useState(false);
|
const [noteInCurrentNotebook, setNoteInCurrentNotebook] = useState(false);
|
||||||
|
const [locked, setLocked] = useState(false);
|
||||||
|
|
||||||
const isPublished =
|
const isPublished =
|
||||||
item.type === "note" && db.monographs.isPublished(item.id);
|
item.type === "note" && db.monographs.isPublished(item.id);
|
||||||
const [locked, setLocked] = useState(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (item.type === "note") {
|
if (item.type === "note") {
|
||||||
@@ -99,46 +170,41 @@ export const useActions = ({
|
|||||||
}
|
}
|
||||||
}, [item]);
|
}, [item]);
|
||||||
|
|
||||||
const checkNotifPinned = useCallback(() => {
|
|
||||||
const pinned = Notifications.getPinnedNotes();
|
|
||||||
|
|
||||||
if (!pinned || pinned.length === 0) {
|
|
||||||
setNotifPinned(undefined);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const index = pinned.findIndex((notif) => notif.id === item.id);
|
|
||||||
if (index !== -1) {
|
|
||||||
setNotifPinned(pinned[index]);
|
|
||||||
} else {
|
|
||||||
setNotifPinned(undefined);
|
|
||||||
}
|
|
||||||
}, [item.id]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (item.type !== "note") return;
|
if (item.type !== "note") return;
|
||||||
checkNotifPinned();
|
setNotifPinned(isNotePinnedInNotifications(item));
|
||||||
setIsPinnedToMenu(db.shortcuts.exists(item.id));
|
setIsPinnedToMenu(db.shortcuts.exists(item.id));
|
||||||
}, [checkNotifPinned, item]);
|
}, [item]);
|
||||||
|
|
||||||
const onUpdate = useCallback(
|
useEffect(() => {
|
||||||
|
const { currentRoute, focusedRouteId } = useNavigationStore.getState();
|
||||||
|
if (item.type !== "note" || currentRoute !== "Notebook" || !focusedRouteId)
|
||||||
|
return;
|
||||||
|
|
||||||
|
!!db.relations
|
||||||
|
.to(item, "notebook")
|
||||||
|
.selector.find((v) => v("id", "==", focusedRouteId))
|
||||||
|
.then((notebook) => {
|
||||||
|
setNoteInCurrentNotebook(!!notebook);
|
||||||
|
});
|
||||||
|
}, [item]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const sub = eSubscribeEvent(
|
||||||
|
Notifications.Events.onUpdate,
|
||||||
async (type: string) => {
|
async (type: string) => {
|
||||||
if (type === "unpin") {
|
if (type === "unpin") {
|
||||||
await Notifications.get();
|
await Notifications.get();
|
||||||
checkNotifPinned();
|
setNotifPinned(isNotePinnedInNotifications(item));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
[checkNotifPinned]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const sub = eSubscribeEvent(Notifications.Events.onUpdate, onUpdate);
|
|
||||||
return () => {
|
return () => {
|
||||||
sub?.unsubscribe();
|
sub?.unsubscribe();
|
||||||
};
|
};
|
||||||
}, [item, onUpdate]);
|
}, [item]);
|
||||||
|
|
||||||
async function restoreTrashItem() {
|
async function restoreTrashItem() {
|
||||||
if (!checkItemSynced()) return;
|
|
||||||
close();
|
close();
|
||||||
if ((await db.trash.restore(item.id)) === false) return;
|
if ((await db.trash.restore(item.id)) === false) return;
|
||||||
Navigation.queueRoutesForUpdate();
|
Navigation.queueRoutesForUpdate();
|
||||||
@@ -154,20 +220,16 @@ export const useActions = ({
|
|||||||
|
|
||||||
async function pinItem() {
|
async function pinItem() {
|
||||||
if (!item.id) return;
|
if (!item.id) return;
|
||||||
close();
|
|
||||||
if (item.type === "note") {
|
if (item.type === "note") {
|
||||||
await db.notes.pin(!item?.pinned, item.id);
|
await db.notes.pin(!item?.pinned, item.id);
|
||||||
} else if (item.type === "notebook") {
|
} else if (item.type === "notebook") {
|
||||||
await db.notebooks.pin(!item?.pinned, item.id);
|
await db.notebooks.pin(!item?.pinned, item.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
close();
|
||||||
Navigation.queueRoutesForUpdate();
|
Navigation.queueRoutesForUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkItemSynced = () => {
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
async function createMenuShortcut() {
|
async function createMenuShortcut() {
|
||||||
if (item.type !== "notebook" && item.type !== "tag") return;
|
if (item.type !== "notebook" && item.type !== "tag") return;
|
||||||
|
|
||||||
@@ -299,7 +361,6 @@ export const useActions = ({
|
|||||||
|
|
||||||
async function deleteTrashItem() {
|
async function deleteTrashItem() {
|
||||||
if (item.type !== "trash") return;
|
if (item.type !== "trash") return;
|
||||||
if (!checkItemSynced()) return;
|
|
||||||
close();
|
close();
|
||||||
await sleep(300);
|
await sleep(300);
|
||||||
presentDialog({
|
presentDialog({
|
||||||
@@ -323,42 +384,14 @@ export const useActions = ({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const actions: {
|
const actions: Action[] = [];
|
||||||
id: string;
|
|
||||||
title: string;
|
|
||||||
icon: string;
|
|
||||||
func: () => void;
|
|
||||||
close?: boolean;
|
|
||||||
check?: boolean;
|
|
||||||
on?: boolean;
|
|
||||||
pro?: boolean;
|
|
||||||
switch?: boolean;
|
|
||||||
hidden?: boolean;
|
|
||||||
type?: string;
|
|
||||||
color?: string;
|
|
||||||
}[] = [
|
|
||||||
// {
|
|
||||||
// id: "ReferencedIn",
|
|
||||||
// title: "References",
|
|
||||||
// icon: "link",
|
|
||||||
// func: async () => {
|
|
||||||
// close();
|
|
||||||
// RelationsList.present({
|
|
||||||
// reference: item,
|
|
||||||
// referenceType: "note",
|
|
||||||
// title: "Referenced in",
|
|
||||||
// relationType: "to",
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
];
|
|
||||||
|
|
||||||
if (item.type === "tag") {
|
if (item.type === "tag") {
|
||||||
actions.push({
|
actions.push({
|
||||||
id: "rename-tag",
|
id: "rename-tag",
|
||||||
title: strings.rename(),
|
title: strings.rename(),
|
||||||
icon: "square-edit-outline",
|
icon: "square-edit-outline",
|
||||||
func: renameTag
|
onPress: renameTag
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,14 +400,14 @@ export const useActions = ({
|
|||||||
id: "rename-color",
|
id: "rename-color",
|
||||||
title: strings.rename(),
|
title: strings.rename(),
|
||||||
icon: "square-edit-outline",
|
icon: "square-edit-outline",
|
||||||
func: renameColor
|
onPress: renameColor
|
||||||
});
|
});
|
||||||
|
|
||||||
actions.push({
|
actions.push({
|
||||||
id: "reorder",
|
id: "reorder",
|
||||||
title: strings.reorder(),
|
title: strings.reorder(),
|
||||||
icon: "sort-ascending",
|
icon: "sort-ascending",
|
||||||
func: () => {
|
onPress: () => {
|
||||||
useSideBarDraggingStore.setState({
|
useSideBarDraggingStore.setState({
|
||||||
dragging: true
|
dragging: true
|
||||||
});
|
});
|
||||||
@@ -391,7 +424,7 @@ export const useActions = ({
|
|||||||
? strings.turnOffReminder()
|
? strings.turnOffReminder()
|
||||||
: strings.turnOnReminder(),
|
: strings.turnOnReminder(),
|
||||||
icon: !item.disabled ? "bell-off-outline" : "bell",
|
icon: !item.disabled ? "bell-off-outline" : "bell",
|
||||||
func: async () => {
|
onPress: async () => {
|
||||||
close();
|
close();
|
||||||
await db.reminders.add({
|
await db.reminders.add({
|
||||||
...item,
|
...item,
|
||||||
@@ -406,10 +439,9 @@ export const useActions = ({
|
|||||||
id: "edit-reminder",
|
id: "edit-reminder",
|
||||||
title: strings.editReminder(),
|
title: strings.editReminder(),
|
||||||
icon: "pencil",
|
icon: "pencil",
|
||||||
func: async () => {
|
onPress: async () => {
|
||||||
ReminderSheet.present(item);
|
ReminderSheet.present(item);
|
||||||
},
|
}
|
||||||
close: false
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -420,13 +452,13 @@ export const useActions = ({
|
|||||||
id: "restore",
|
id: "restore",
|
||||||
title: strings.restore(),
|
title: strings.restore(),
|
||||||
icon: "delete-restore",
|
icon: "delete-restore",
|
||||||
func: restoreTrashItem
|
onPress: restoreTrashItem
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "delete",
|
id: "delete",
|
||||||
title: strings.delete(),
|
title: strings.delete(),
|
||||||
icon: "delete",
|
icon: "delete",
|
||||||
func: deleteTrashItem
|
onPress: deleteTrashItem
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -436,11 +468,27 @@ export const useActions = ({
|
|||||||
id: "add-shortcut",
|
id: "add-shortcut",
|
||||||
title: isPinnedToMenu ? strings.removeShortcut() : strings.addShortcut(),
|
title: isPinnedToMenu ? strings.removeShortcut() : strings.addShortcut(),
|
||||||
icon: isPinnedToMenu ? "link-variant-remove" : "link-variant",
|
icon: isPinnedToMenu ? "link-variant-remove" : "link-variant",
|
||||||
func: createMenuShortcut,
|
onPress: createMenuShortcut,
|
||||||
close: false,
|
isToggle: true,
|
||||||
check: true,
|
checked: isPinnedToMenu,
|
||||||
on: isPinnedToMenu,
|
activeColor: colors.error.paragraph
|
||||||
pro: true
|
});
|
||||||
|
actions.push({
|
||||||
|
id: "select",
|
||||||
|
title: strings.select() + " " + strings.dataTypes[item.type](),
|
||||||
|
icon: "checkbox-outline",
|
||||||
|
onPress: () => {
|
||||||
|
const store =
|
||||||
|
item.type === "tag"
|
||||||
|
? useSideMenuTagsSelectionStore
|
||||||
|
: useSideMenuNotebookSelectionStore;
|
||||||
|
store.setState({
|
||||||
|
enabled: true,
|
||||||
|
selection: {}
|
||||||
|
});
|
||||||
|
store.getState().markAs(item, "selected");
|
||||||
|
close();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,7 +498,7 @@ export const useActions = ({
|
|||||||
id: "add-notebook",
|
id: "add-notebook",
|
||||||
title: strings.addNotebook(),
|
title: strings.addNotebook(),
|
||||||
icon: "plus",
|
icon: "plus",
|
||||||
func: async () => {
|
onPress: async () => {
|
||||||
AddNotebookSheet.present(undefined, item);
|
AddNotebookSheet.present(undefined, item);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -458,7 +506,7 @@ export const useActions = ({
|
|||||||
id: "edit-notebook",
|
id: "edit-notebook",
|
||||||
title: strings.editNotebook(),
|
title: strings.editNotebook(),
|
||||||
icon: "square-edit-outline",
|
icon: "square-edit-outline",
|
||||||
func: async () => {
|
onPress: async () => {
|
||||||
AddNotebookSheet.present(item);
|
AddNotebookSheet.present(item);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -470,7 +518,7 @@ export const useActions = ({
|
|||||||
: strings.setAsDefault(),
|
: strings.setAsDefault(),
|
||||||
hidden: item.type !== "notebook",
|
hidden: item.type !== "notebook",
|
||||||
icon: "notebook",
|
icon: "notebook",
|
||||||
func: async () => {
|
onPress: async () => {
|
||||||
if (defaultNotebook === item.id) {
|
if (defaultNotebook === item.id) {
|
||||||
await db.settings.setDefaultNotebook(undefined);
|
await db.settings.setDefaultNotebook(undefined);
|
||||||
setDefaultNotebook(undefined);
|
setDefaultNotebook(undefined);
|
||||||
@@ -483,14 +531,14 @@ export const useActions = ({
|
|||||||
}
|
}
|
||||||
close();
|
close();
|
||||||
},
|
},
|
||||||
on: defaultNotebook === item.id
|
checked: defaultNotebook === item.id
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "move-notes",
|
id: "move-notes",
|
||||||
title: strings.moveNotes(),
|
title: strings.moveNotes(),
|
||||||
hidden: item.type !== "notebook",
|
hidden: item.type !== "notebook",
|
||||||
icon: "text",
|
icon: "text",
|
||||||
func: () => {
|
onPress: () => {
|
||||||
MoveNotes.present(item);
|
MoveNotes.present(item);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -498,7 +546,7 @@ export const useActions = ({
|
|||||||
id: "move-notebook",
|
id: "move-notebook",
|
||||||
title: strings.moveNotebookFix(),
|
title: strings.moveNotebookFix(),
|
||||||
icon: "arrow-right-bold-box-outline",
|
icon: "arrow-right-bold-box-outline",
|
||||||
func: () => {
|
onPress: () => {
|
||||||
MoveNotebookSheet.present([item]);
|
MoveNotebookSheet.present([item]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -510,10 +558,9 @@ export const useActions = ({
|
|||||||
id: "pin",
|
id: "pin",
|
||||||
title: item.pinned ? strings.unpin() : strings.pin(),
|
title: item.pinned ? strings.unpin() : strings.pin(),
|
||||||
icon: item.pinned ? "pin-off-outline" : "pin-outline",
|
icon: item.pinned ? "pin-off-outline" : "pin-outline",
|
||||||
func: pinItem,
|
onPress: pinItem,
|
||||||
close: false,
|
isToggle: true,
|
||||||
check: true,
|
checked: item.pinned,
|
||||||
on: item.pinned,
|
|
||||||
pro: true
|
pro: true
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -535,7 +582,7 @@ export const useActions = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function toggleLocalOnly() {
|
async function toggleLocalOnly() {
|
||||||
if (!checkItemSynced() || !user) return;
|
if (!user) return;
|
||||||
await db.notes.localOnly(!(item as Note).localOnly, item?.id);
|
await db.notes.localOnly(!(item as Note).localOnly, item?.id);
|
||||||
Navigation.queueRoutesForUpdate();
|
Navigation.queueRoutesForUpdate();
|
||||||
close();
|
close();
|
||||||
@@ -556,7 +603,6 @@ export const useActions = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const duplicateNote = async () => {
|
const duplicateNote = async () => {
|
||||||
if (!checkItemSynced()) return;
|
|
||||||
await db.notes.duplicate(item.id);
|
await db.notes.duplicate(item.id);
|
||||||
Navigation.queueRoutesForUpdate();
|
Navigation.queueRoutesForUpdate();
|
||||||
close();
|
close();
|
||||||
@@ -577,19 +623,16 @@ export const useActions = ({
|
|||||||
|
|
||||||
async function addToFavorites() {
|
async function addToFavorites() {
|
||||||
if (!item.id || item.type !== "note") return;
|
if (!item.id || item.type !== "note") return;
|
||||||
close();
|
|
||||||
await db.notes.favorite(!item.favorite, item.id);
|
await db.notes.favorite(!item.favorite, item.id);
|
||||||
Navigation.queueRoutesForUpdate();
|
Navigation.queueRoutesForUpdate();
|
||||||
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function pinToNotifications() {
|
async function pinToNotifications() {
|
||||||
if (!checkItemSynced()) return;
|
|
||||||
if (Platform.OS === "ios") return;
|
|
||||||
|
|
||||||
if (notifPinned) {
|
if (notifPinned) {
|
||||||
Notifications.remove(item.id);
|
Notifications.remove(item.id);
|
||||||
await Notifications.get();
|
await Notifications.get();
|
||||||
checkNotifPinned();
|
setNotifPinned(isNotePinnedInNotifications(item));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (locked) {
|
if (locked) {
|
||||||
@@ -603,7 +646,7 @@ export const useActions = ({
|
|||||||
const text = await convertNoteToText(item as Note, true);
|
const text = await convertNoteToText(item as Note, true);
|
||||||
const html = (text || "").replace(/\n/g, "<br />");
|
const html = (text || "").replace(/\n/g, "<br />");
|
||||||
await Notifications.displayNotification({
|
await Notifications.displayNotification({
|
||||||
title: item.title,
|
title: (item as Note).title,
|
||||||
message: (item as Note).headline || text || "",
|
message: (item as Note).headline || text || "",
|
||||||
subtitle: "",
|
subtitle: "",
|
||||||
bigText: html,
|
bigText: html,
|
||||||
@@ -612,11 +655,10 @@ export const useActions = ({
|
|||||||
id: item.id
|
id: item.id
|
||||||
});
|
});
|
||||||
await Notifications.get();
|
await Notifications.get();
|
||||||
checkNotifPinned();
|
setNotifPinned(isNotePinnedInNotifications(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function publishNote() {
|
async function publishNote() {
|
||||||
if (!checkItemSynced()) return;
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
ToastManager.show({
|
ToastManager.show({
|
||||||
heading: strings.loginRequired(),
|
heading: strings.loginRequired(),
|
||||||
@@ -657,7 +699,6 @@ export const useActions = ({
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!checkItemSynced()) return;
|
|
||||||
if (locked) {
|
if (locked) {
|
||||||
close();
|
close();
|
||||||
await sleep(300);
|
await sleep(300);
|
||||||
@@ -687,8 +728,6 @@ export const useActions = ({
|
|||||||
|
|
||||||
async function addToVault() {
|
async function addToVault() {
|
||||||
if (item.type !== "note") return;
|
if (item.type !== "note") return;
|
||||||
|
|
||||||
if (!checkItemSynced()) return;
|
|
||||||
if (locked) {
|
if (locked) {
|
||||||
close();
|
close();
|
||||||
await sleep(300);
|
await sleep(300);
|
||||||
@@ -709,10 +748,10 @@ export const useActions = ({
|
|||||||
Navigation.queueRoutesForUpdate();
|
Navigation.queueRoutesForUpdate();
|
||||||
eSendEvent(eUpdateNoteInEditor, item, true);
|
eSendEvent(eUpdateNoteInEditor, item, true);
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: unknown) {
|
||||||
close();
|
close();
|
||||||
await sleep(300);
|
await sleep(300);
|
||||||
switch (e.message) {
|
switch ((e as Error).message) {
|
||||||
case VAULT_ERRORS.noVault:
|
case VAULT_ERRORS.noVault:
|
||||||
openVault({
|
openVault({
|
||||||
item: item,
|
item: item,
|
||||||
@@ -775,37 +814,36 @@ export const useActions = ({
|
|||||||
id: "favorite",
|
id: "favorite",
|
||||||
title: !item.favorite ? strings.favorite() : strings.unfavorite(),
|
title: !item.favorite ? strings.favorite() : strings.unfavorite(),
|
||||||
icon: item.favorite ? "star-off" : "star-outline",
|
icon: item.favorite ? "star-off" : "star-outline",
|
||||||
func: addToFavorites,
|
onPress: addToFavorites,
|
||||||
close: false,
|
isToggle: true,
|
||||||
check: true,
|
checked: item.favorite,
|
||||||
on: item.favorite,
|
|
||||||
pro: true,
|
pro: true,
|
||||||
color: "orange"
|
activeColor: "orange"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "remove-from-notebook",
|
id: "remove-from-notebook",
|
||||||
title: strings.removeFromNotebook(),
|
title: strings.removeFromNotebook(),
|
||||||
hidden: noteInCurrentNotebook,
|
hidden: noteInCurrentNotebook,
|
||||||
icon: "minus-circle-outline",
|
icon: "minus-circle-outline",
|
||||||
func: removeNoteFromNotebook
|
onPress: removeNoteFromNotebook
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "attachments",
|
id: "attachments",
|
||||||
title: strings.attachments(),
|
title: strings.attachments(),
|
||||||
icon: "attachment",
|
icon: "attachment",
|
||||||
func: showAttachments
|
onPress: showAttachments
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "history",
|
id: "history",
|
||||||
title: strings.history(),
|
title: strings.history(),
|
||||||
icon: "history",
|
icon: "history",
|
||||||
func: openHistory
|
onPress: openHistory
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "copy-link",
|
id: "copy-link",
|
||||||
title: strings.copyLink(),
|
title: strings.copyLink(),
|
||||||
icon: "link",
|
icon: "link",
|
||||||
func: () => {
|
onPress: () => {
|
||||||
Clipboard.setString(createInternalLink("note", item.id));
|
Clipboard.setString(createInternalLink("note", item.id));
|
||||||
ToastManager.show({
|
ToastManager.show({
|
||||||
heading: strings.linkCopied(),
|
heading: strings.linkCopied(),
|
||||||
@@ -819,7 +857,7 @@ export const useActions = ({
|
|||||||
id: "reminders",
|
id: "reminders",
|
||||||
title: strings.dataTypesPluralCamelCase.reminder(),
|
title: strings.dataTypesPluralCamelCase.reminder(),
|
||||||
icon: "clock-outline",
|
icon: "clock-outline",
|
||||||
func: async () => {
|
onPress: async () => {
|
||||||
RelationsList.present({
|
RelationsList.present({
|
||||||
reference: item,
|
reference: item,
|
||||||
referenceType: "reminder",
|
referenceType: "reminder",
|
||||||
@@ -833,121 +871,108 @@ export const useActions = ({
|
|||||||
icon: "plus"
|
icon: "plus"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
}
|
||||||
close: false
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
id: "copy",
|
id: "copy",
|
||||||
title: strings.copy(),
|
title: strings.copy(),
|
||||||
icon: "content-copy",
|
icon: "content-copy",
|
||||||
func: copyContent
|
onPress: copyContent
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "share",
|
id: "share",
|
||||||
title: strings.share(),
|
title: strings.share(),
|
||||||
icon: "share-variant",
|
icon: "share-variant",
|
||||||
func: shareNote
|
onPress: shareNote
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "read-only",
|
id: "read-only",
|
||||||
title: strings.readOnly(),
|
title: strings.readOnly(),
|
||||||
icon: "pencil-lock",
|
icon: "pencil-lock",
|
||||||
func: toggleReadyOnlyMode,
|
onPress: toggleReadyOnlyMode,
|
||||||
on: item.readonly
|
checked: item.readonly
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "local-only",
|
id: "local-only",
|
||||||
title: strings.syncOff(),
|
title: strings.syncOff(),
|
||||||
icon: "sync-off",
|
icon: "sync-off",
|
||||||
func: toggleLocalOnly,
|
onPress: toggleLocalOnly,
|
||||||
on: item.localOnly
|
checked: item.localOnly
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "duplicate",
|
id: "duplicate",
|
||||||
title: strings.duplicate(),
|
title: strings.duplicate(),
|
||||||
icon: "content-duplicate",
|
icon: "content-duplicate",
|
||||||
func: duplicateNote
|
onPress: duplicateNote
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
id: "add-reminder",
|
id: "add-reminder",
|
||||||
title: strings.remindMe(),
|
title: strings.remindMe(),
|
||||||
icon: "clock-plus-outline",
|
icon: "clock-plus-outline",
|
||||||
func: () => {
|
onPress: () => {
|
||||||
ReminderSheet.present(undefined, { id: item.id, type: "note" });
|
ReminderSheet.present(undefined, { id: item.id, type: "note" });
|
||||||
},
|
}
|
||||||
close: true
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "lock-unlock",
|
id: "lock-unlock",
|
||||||
title: locked ? strings.unlock() : strings.lock(),
|
title: locked ? strings.unlock() : strings.lock(),
|
||||||
icon: locked ? "lock-open-outline" : "key-outline",
|
icon: locked ? "lock-open-outline" : "key-outline",
|
||||||
func: addToVault,
|
onPress: addToVault,
|
||||||
on: locked
|
checked: locked
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "publish",
|
id: "publish",
|
||||||
title: isPublished ? strings.published() : strings.publish(),
|
title: isPublished ? strings.published() : strings.publish(),
|
||||||
icon: "cloud-upload-outline",
|
icon: "cloud-upload-outline",
|
||||||
on: isPublished,
|
checked: isPublished,
|
||||||
func: publishNote
|
onPress: publishNote
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
id: "export",
|
id: "export",
|
||||||
title: strings.export(),
|
title: strings.export(),
|
||||||
icon: "export",
|
icon: "export",
|
||||||
func: exportNote
|
onPress: exportNote
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
id: "pin-to-notifications",
|
|
||||||
title: notifPinned
|
|
||||||
? strings.unpinFromNotifications()
|
|
||||||
: strings.pinToNotifications(),
|
|
||||||
icon: "message-badge-outline",
|
|
||||||
on: !!notifPinned,
|
|
||||||
func: pinToNotifications
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
id: "notebooks",
|
id: "notebooks",
|
||||||
title: strings.linkNotebooks(),
|
title: strings.linkNotebooks(),
|
||||||
icon: "book-outline",
|
icon: "book-outline",
|
||||||
func: addTo
|
onPress: addTo
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "add-tag",
|
id: "add-tag",
|
||||||
title: strings.addTags(),
|
title: strings.addTags(),
|
||||||
icon: "pound",
|
icon: "pound",
|
||||||
func: addTo
|
onPress: addTo
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "references",
|
id: "references",
|
||||||
title: strings.references(),
|
title: strings.references(),
|
||||||
icon: "vector-link",
|
icon: "vector-link",
|
||||||
func: () => {
|
onPress: () => {
|
||||||
ReferencesList.present({
|
ReferencesList.present({
|
||||||
reference: item as ItemReference
|
reference: item as ItemReference
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
if (Platform.OS === "android") {
|
||||||
const { currentRoute, focusedRouteId } = useNavigationStore.getState();
|
actions.push({
|
||||||
if (item.type !== "note" || currentRoute !== "Notebook" || !focusedRouteId)
|
id: "pin-to-notifications",
|
||||||
return;
|
title: notifPinned
|
||||||
|
? strings.unpinFromNotifications()
|
||||||
!!db.relations
|
: strings.pinToNotifications(),
|
||||||
.to(item, "notebook")
|
icon: "message-badge-outline",
|
||||||
.selector.find((v) => v("id", "==", focusedRouteId))
|
checked: !!notifPinned,
|
||||||
.then((notebook) => {
|
onPress: pinToNotifications
|
||||||
setNoteInCurrentNotebook(!!notebook);
|
|
||||||
});
|
});
|
||||||
}, [item]);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
actions.push({
|
actions.push({
|
||||||
id: "trash",
|
id: "trash",
|
||||||
@@ -960,7 +985,7 @@ export const useActions = ({
|
|||||||
: strings.moveToTrash(),
|
: strings.moveToTrash(),
|
||||||
icon: "delete-outline",
|
icon: "delete-outline",
|
||||||
type: "error",
|
type: "error",
|
||||||
func: deleteItem
|
onPress: deleteItem
|
||||||
});
|
});
|
||||||
|
|
||||||
return actions;
|
return actions;
|
||||||
|
|||||||
@@ -59,8 +59,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
clearAppState,
|
clearAppState,
|
||||||
editorController,
|
editorController,
|
||||||
editorState,
|
editorState
|
||||||
setAppState
|
|
||||||
} from "../screens/editor/tiptap/utils";
|
} from "../screens/editor/tiptap/utils";
|
||||||
import { useDragState } from "../screens/settings/editor/state";
|
import { useDragState } from "../screens/settings/editor/state";
|
||||||
import BackupService from "../services/backup";
|
import BackupService from "../services/backup";
|
||||||
@@ -103,7 +102,7 @@ import {
|
|||||||
refreshNotesPage
|
refreshNotesPage
|
||||||
} from "../utils/events";
|
} from "../utils/events";
|
||||||
import { getGithubVersion } from "../utils/github-version";
|
import { getGithubVersion } from "../utils/github-version";
|
||||||
import { tabBarRef } from "../utils/global-refs";
|
import { fluidTabsRef } from "../utils/global-refs";
|
||||||
import { NotesnookModule } from "../utils/notesnook-module";
|
import { NotesnookModule } from "../utils/notesnook-module";
|
||||||
import { sleep } from "../utils/time";
|
import { sleep } from "../utils/time";
|
||||||
|
|
||||||
@@ -168,7 +167,7 @@ const onAppOpenedFromURL = async (event: { url: string }) => {
|
|||||||
clearAppState();
|
clearAppState();
|
||||||
editorState().movedAway = false;
|
editorState().movedAway = false;
|
||||||
eSendEvent(eOnLoadNote, { newNote: true });
|
eSendEvent(eOnLoadNote, { newNote: true });
|
||||||
tabBarRef.current?.goToPage(1, false);
|
fluidTabsRef.current?.goToPage(1, false);
|
||||||
return;
|
return;
|
||||||
} else if (url.startsWith("https://notesnook.com/open_note")) {
|
} else if (url.startsWith("https://notesnook.com/open_note")) {
|
||||||
const id = new URL(url).searchParams.get("id");
|
const id = new URL(url).searchParams.get("id");
|
||||||
@@ -178,7 +177,7 @@ const onAppOpenedFromURL = async (event: { url: string }) => {
|
|||||||
eSendEvent(eOnLoadNote, {
|
eSendEvent(eOnLoadNote, {
|
||||||
item: note
|
item: note
|
||||||
});
|
});
|
||||||
tabBarRef.current?.goToPage(1, false);
|
fluidTabsRef.current?.goToPage(1, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (url.startsWith("https://notesnook.com/open_reminder")) {
|
} else if (url.startsWith("https://notesnook.com/open_reminder")) {
|
||||||
|
|||||||
@@ -19,13 +19,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
import {
|
import {
|
||||||
Attachment,
|
Attachment,
|
||||||
Color,
|
Color,
|
||||||
|
HistorySession,
|
||||||
Note,
|
Note,
|
||||||
Notebook,
|
Notebook,
|
||||||
Reminder,
|
Reminder,
|
||||||
Shortcut,
|
Shortcut,
|
||||||
Tag,
|
Tag,
|
||||||
VirtualizedGrouping,
|
VirtualizedGrouping
|
||||||
HistorySession
|
|
||||||
} from "@notesnook/core";
|
} from "@notesnook/core";
|
||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import { db } from "../common/database";
|
import { db } from "../common/database";
|
||||||
@@ -34,8 +34,8 @@ import {
|
|||||||
eSubscribeEvent,
|
eSubscribeEvent,
|
||||||
eUnSubscribeEvent
|
eUnSubscribeEvent
|
||||||
} from "../services/event-manager";
|
} from "../services/event-manager";
|
||||||
import { eDBItemUpdate } from "../utils/events";
|
|
||||||
import { useSettingStore } from "../stores/use-setting-store";
|
import { useSettingStore } from "../stores/use-setting-store";
|
||||||
|
import { eDBItemUpdate } from "../utils/events";
|
||||||
|
|
||||||
type ItemTypeKey = {
|
type ItemTypeKey = {
|
||||||
note: Note;
|
note: Note;
|
||||||
@@ -55,7 +55,8 @@ function isValidIdOrIndex(idOrIndex?: string | number) {
|
|||||||
export const useDBItem = <T extends keyof ItemTypeKey>(
|
export const useDBItem = <T extends keyof ItemTypeKey>(
|
||||||
idOrIndex?: string | number,
|
idOrIndex?: string | number,
|
||||||
type?: T,
|
type?: T,
|
||||||
items?: VirtualizedGrouping<ItemTypeKey[T]>
|
items?: VirtualizedGrouping<ItemTypeKey[T]>,
|
||||||
|
onItemUpdated?: (item?: ItemTypeKey[T]) => void
|
||||||
): [ItemTypeKey[T] | undefined, () => void] => {
|
): [ItemTypeKey[T] | undefined, () => void] => {
|
||||||
const [item, setItem] = useState<ItemTypeKey[T]>();
|
const [item, setItem] = useState<ItemTypeKey[T]>();
|
||||||
const itemIdRef = useRef<string>();
|
const itemIdRef = useRef<string>();
|
||||||
@@ -67,15 +68,15 @@ export const useDBItem = <T extends keyof ItemTypeKey>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const onUpdateItem = (itemId?: string) => {
|
const onUpdateItem = async (itemId?: string) => {
|
||||||
if (typeof itemId === "string" && itemId !== itemIdRef.current) return;
|
if (typeof itemId === "string" && itemId !== itemIdRef.current) return;
|
||||||
if (!isValidIdOrIndex(idOrIndex)) return;
|
if (!isValidIdOrIndex(idOrIndex)) return;
|
||||||
|
|
||||||
if (items && typeof idOrIndex === "number") {
|
if (items && typeof idOrIndex === "number") {
|
||||||
items.item(idOrIndex).then((item) => {
|
const item = (await items.item(idOrIndex))?.item;
|
||||||
setItem(item.item);
|
setItem(item);
|
||||||
itemIdRef.current = item.item?.id;
|
itemIdRef.current = item?.id;
|
||||||
});
|
onItemUpdated?.(item);
|
||||||
} else {
|
} else {
|
||||||
if (!(db as any)[type + "s"][type]) {
|
if (!(db as any)[type + "s"][type]) {
|
||||||
console.warn(
|
console.warn(
|
||||||
@@ -83,12 +84,12 @@ export const useDBItem = <T extends keyof ItemTypeKey>(
|
|||||||
`db.${type}s.${type}(id: string)`
|
`db.${type}s.${type}(id: string)`
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
(db as any)[type + "s"]
|
const item = await (db as any)[type + "s"]?.[type]?.(
|
||||||
?.[type]?.(idOrIndex as string)
|
idOrIndex as string
|
||||||
.then((item: ItemTypeKey[T]) => {
|
);
|
||||||
setItem(item);
|
setItem(item);
|
||||||
itemIdRef.current = item.id;
|
itemIdRef.current = item.id;
|
||||||
});
|
onItemUpdated?.(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -110,7 +111,7 @@ export const useDBItem = <T extends keyof ItemTypeKey>(
|
|||||||
return () => {
|
return () => {
|
||||||
eUnSubscribeEvent(eDBItemUpdate, onUpdateItem);
|
eUnSubscribeEvent(eDBItemUpdate, onUpdateItem);
|
||||||
};
|
};
|
||||||
}, [idOrIndex, type, items]);
|
}, [idOrIndex, type, items, onItemUpdated]);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
isValidIdOrIndex(idOrIndex) ? (item as ItemTypeKey[T]) : undefined,
|
isValidIdOrIndex(idOrIndex) ? (item as ItemTypeKey[T]) : undefined,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import { Notebook, VirtualizedGrouping } from "@notesnook/core";
|
import { Notebook, VirtualizedGrouping } from "@notesnook/core";
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import { db } from "../common/database";
|
import { db } from "../common/database";
|
||||||
import { eSubscribeEvent, eUnSubscribeEvent } from "../services/event-manager";
|
import { eSubscribeEvent, eUnSubscribeEvent } from "../services/event-manager";
|
||||||
import { eGroupOptionsUpdated, eOnNotebookUpdated } from "../utils/events";
|
import { eGroupOptionsUpdated, eOnNotebookUpdated } from "../utils/events";
|
||||||
@@ -26,17 +26,20 @@ import { useDBItem, useTotalNotes } from "./use-db-item";
|
|||||||
export const useNotebook = (
|
export const useNotebook = (
|
||||||
id?: string | number,
|
id?: string | number,
|
||||||
items?: VirtualizedGrouping<Notebook>,
|
items?: VirtualizedGrouping<Notebook>,
|
||||||
nestedNotebooks?: boolean
|
nestedNotebooks?: boolean,
|
||||||
|
countNotes?: boolean
|
||||||
) => {
|
) => {
|
||||||
const [item, refresh] = useDBItem(id, "notebook", items);
|
|
||||||
const groupOptions = db.settings.getGroupOptions("notebooks");
|
const groupOptions = db.settings.getGroupOptions("notebooks");
|
||||||
const [notebooks, setNotebooks] = useState<VirtualizedGrouping<Notebook>>();
|
const [notebooks, setNotebooks] = useState<VirtualizedGrouping<Notebook>>();
|
||||||
const { totalNotes: nestedNotebookNotesCount, getTotalNotes } =
|
const { totalNotes: nestedNotebookNotesCount, getTotalNotes } =
|
||||||
useTotalNotes("notebook");
|
useTotalNotes("notebook");
|
||||||
|
const getTotalNotesRef = useRef(getTotalNotes);
|
||||||
|
getTotalNotesRef.current = getTotalNotes;
|
||||||
|
const onItemUpdated = React.useCallback(
|
||||||
|
(item?: Notebook) => {
|
||||||
|
if (!item) return;
|
||||||
|
|
||||||
const onRequestUpdate = React.useCallback(() => {
|
if (nestedNotebooks) {
|
||||||
if (!item?.id) return;
|
|
||||||
|
|
||||||
const selector = db.relations.from(
|
const selector = db.relations.from(
|
||||||
{
|
{
|
||||||
type: "notebook",
|
type: "notebook",
|
||||||
@@ -44,9 +47,8 @@ export const useNotebook = (
|
|||||||
},
|
},
|
||||||
"notebook"
|
"notebook"
|
||||||
).selector;
|
).selector;
|
||||||
|
|
||||||
selector.ids().then((notebookIds) => {
|
selector.ids().then((notebookIds) => {
|
||||||
getTotalNotes(notebookIds);
|
getTotalNotesRef.current(notebookIds);
|
||||||
});
|
});
|
||||||
|
|
||||||
selector
|
selector
|
||||||
@@ -54,28 +56,31 @@ export const useNotebook = (
|
|||||||
.then((notebooks) => {
|
.then((notebooks) => {
|
||||||
setNotebooks(notebooks);
|
setNotebooks(notebooks);
|
||||||
});
|
});
|
||||||
}, [getTotalNotes, item?.id]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (nestedNotebooks) {
|
|
||||||
onRequestUpdate();
|
|
||||||
}
|
}
|
||||||
}, [item?.id, onRequestUpdate, nestedNotebooks]);
|
|
||||||
|
if (countNotes) {
|
||||||
|
getTotalNotesRef.current([item?.id]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[countNotes, nestedNotebooks]
|
||||||
|
);
|
||||||
|
|
||||||
|
const [item, refresh] = useDBItem(id, "notebook", items, onItemUpdated);
|
||||||
|
|
||||||
|
const itemRef = useRef(item);
|
||||||
|
itemRef.current = item;
|
||||||
|
const refreshRef = useRef(refresh);
|
||||||
|
refreshRef.current = refresh;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const onNotebookUpdate = (id?: string) => {
|
const onNotebookUpdate = (id?: string) => {
|
||||||
if (typeof id === "string" && id !== id) return;
|
if (typeof id === "string" && id !== id) return;
|
||||||
setImmediate(() => {
|
refreshRef.current();
|
||||||
if (nestedNotebooks) {
|
|
||||||
onRequestUpdate();
|
|
||||||
}
|
|
||||||
refresh();
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const onUpdate = (type: string) => {
|
const onUpdate = (type: string) => {
|
||||||
if (type !== "notebooks") return;
|
if (type !== "notebooks") return;
|
||||||
onRequestUpdate();
|
refreshRef.current();
|
||||||
};
|
};
|
||||||
|
|
||||||
eSubscribeEvent(eGroupOptionsUpdated, onUpdate);
|
eSubscribeEvent(eGroupOptionsUpdated, onUpdate);
|
||||||
@@ -84,13 +89,14 @@ export const useNotebook = (
|
|||||||
eUnSubscribeEvent(eGroupOptionsUpdated, onUpdate);
|
eUnSubscribeEvent(eGroupOptionsUpdated, onUpdate);
|
||||||
eUnSubscribeEvent(eOnNotebookUpdated, onNotebookUpdate);
|
eUnSubscribeEvent(eOnNotebookUpdated, onNotebookUpdate);
|
||||||
};
|
};
|
||||||
}, [onRequestUpdate, item?.id, refresh, nestedNotebooks]);
|
}, [nestedNotebooks]);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
notebook: item,
|
notebook: item,
|
||||||
nestedNotebookNotesCount,
|
nestedNotebookNotesCount,
|
||||||
nestedNotebooks: item ? notebooks : undefined,
|
nestedNotebooks: item ? notebooks : undefined,
|
||||||
onUpdate: onRequestUpdate,
|
onUpdate: () => refresh(),
|
||||||
groupOptions
|
groupOptions,
|
||||||
|
notesCount: !item ? 0 : nestedNotebookNotesCount(item?.id)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export const useShortcutManager = ({
|
|||||||
shortcuts = defaultShortcuts
|
shortcuts = defaultShortcuts
|
||||||
}: {
|
}: {
|
||||||
onShortcutPressed: (shortcut: ShortcutItem | null) => void;
|
onShortcutPressed: (shortcut: ShortcutItem | null) => void;
|
||||||
shortcuts: ShortcutItem[];
|
shortcuts?: ShortcutItem[];
|
||||||
}) => {
|
}) => {
|
||||||
const initialShortcutRecieved = useRef(false);
|
const initialShortcutRecieved = useRef(false);
|
||||||
|
|
||||||
|
|||||||
559
apps/mobile/app/navigation/fluid-panels-view.tsx
Normal file
559
apps/mobile/app/navigation/fluid-panels-view.tsx
Normal file
@@ -0,0 +1,559 @@
|
|||||||
|
/*
|
||||||
|
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 { ScopedThemeProvider, useThemeColors } from "@notesnook/theme";
|
||||||
|
import {
|
||||||
|
activateKeepAwake,
|
||||||
|
deactivateKeepAwake
|
||||||
|
} from "@sayem314/react-native-keep-awake";
|
||||||
|
import React, {
|
||||||
|
useCallback,
|
||||||
|
useEffect,
|
||||||
|
useMemo,
|
||||||
|
useRef,
|
||||||
|
useState
|
||||||
|
} from "react";
|
||||||
|
import { Dimensions, LayoutChangeEvent, Platform, View } from "react-native";
|
||||||
|
import {
|
||||||
|
addOrientationListener,
|
||||||
|
addSpecificOrientationListener,
|
||||||
|
getInitialOrientation,
|
||||||
|
getSpecificOrientation,
|
||||||
|
removeOrientationListener,
|
||||||
|
removeSpecificOrientationListener
|
||||||
|
} from "react-native-orientation";
|
||||||
|
import Animated, {
|
||||||
|
useAnimatedStyle,
|
||||||
|
useSharedValue,
|
||||||
|
withTiming
|
||||||
|
} from "react-native-reanimated";
|
||||||
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
|
import { notesnook } from "../../e2e/test.ids";
|
||||||
|
import { db } from "../common/database";
|
||||||
|
import { FluidPanels } from "../components/fluid-panels";
|
||||||
|
import { SideMenu } from "../components/side-menu";
|
||||||
|
import { useSideBarDraggingStore } from "../components/side-menu/dragging-store";
|
||||||
|
import useGlobalSafeAreaInsets from "../hooks/use-global-safe-area-insets";
|
||||||
|
import { useShortcutManager } from "../hooks/use-shortcut-manager";
|
||||||
|
import { hideAllTooltips } from "../hooks/use-tooltip";
|
||||||
|
import { useTabStore } from "../screens/editor/tiptap/use-tab-store";
|
||||||
|
import {
|
||||||
|
clearAppState,
|
||||||
|
editorController,
|
||||||
|
editorState,
|
||||||
|
getAppState
|
||||||
|
} from "../screens/editor/tiptap/utils";
|
||||||
|
import { EditorWrapper } from "../screens/editor/wrapper";
|
||||||
|
import { DDS } from "../services/device-detection";
|
||||||
|
import {
|
||||||
|
eSendEvent,
|
||||||
|
eSubscribeEvent,
|
||||||
|
eUnSubscribeEvent
|
||||||
|
} from "../services/event-manager";
|
||||||
|
import { useSettingStore } from "../stores/use-setting-store";
|
||||||
|
import {
|
||||||
|
eCloseFullscreenEditor,
|
||||||
|
eOnEnterEditor,
|
||||||
|
eOnExitEditor,
|
||||||
|
eOnLoadNote,
|
||||||
|
eOpenFullscreenEditor,
|
||||||
|
eUnlockNote
|
||||||
|
} from "../utils/events";
|
||||||
|
import { editorRef, fluidTabsRef } from "../utils/global-refs";
|
||||||
|
import { AppNavigationStack } from "./navigation-stack";
|
||||||
|
|
||||||
|
const MOBILE_SIDEBAR_SIZE = 0.85;
|
||||||
|
|
||||||
|
const valueLimiter = (value: number, min: number, max: number) => {
|
||||||
|
return value < min ? min : value > max ? max : value;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const FluidPanelsView = React.memo(
|
||||||
|
() => {
|
||||||
|
const { colors } = useThemeColors();
|
||||||
|
const deviceMode = useSettingStore((state) => state.deviceMode);
|
||||||
|
const setFullscreen = useSettingStore((state) => state.setFullscreen);
|
||||||
|
const fullscreen = useSettingStore((state) => state.fullscreen);
|
||||||
|
const setDeviceModeState = useSettingStore((state) => state.setDeviceMode);
|
||||||
|
const dimensions = useSettingStore((state) => state.dimensions);
|
||||||
|
const setDimensions = useSettingStore((state) => state.setDimensions);
|
||||||
|
const insets = useGlobalSafeAreaInsets();
|
||||||
|
const animatedOpacity = useSharedValue(0);
|
||||||
|
const animatedTranslateY = useSharedValue(-9999);
|
||||||
|
const overlayRef = useRef<Animated.View>(null);
|
||||||
|
const [orientation, setOrientation] = useState(getInitialOrientation());
|
||||||
|
|
||||||
|
useShortcutManager({
|
||||||
|
onShortcutPressed: async (item) => {
|
||||||
|
if (!item && getAppState()) {
|
||||||
|
editorState().movedAway = false;
|
||||||
|
fluidTabsRef.current?.goToPage(1, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (item?.type === "notesnook.action.newnote") {
|
||||||
|
clearAppState();
|
||||||
|
if (!fluidTabsRef.current) {
|
||||||
|
setTimeout(() => {
|
||||||
|
eSendEvent(eOnLoadNote, { newNote: true });
|
||||||
|
editorState().movedAway = false;
|
||||||
|
fluidTabsRef.current?.goToPage(1, false);
|
||||||
|
}, 3000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
eSendEvent(eOnLoadNote, { newNote: true });
|
||||||
|
editorState().movedAway = false;
|
||||||
|
fluidTabsRef.current?.goToPage(1, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const onOrientationChange = (o: string, o2: string) => {
|
||||||
|
setOrientation(o || o2);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (Platform.OS === "ios") {
|
||||||
|
addSpecificOrientationListener(onOrientationChange);
|
||||||
|
getSpecificOrientation && getSpecificOrientation(onOrientationChange);
|
||||||
|
} else {
|
||||||
|
addOrientationListener(onOrientationChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
removeSpecificOrientationListener(onOrientationChange);
|
||||||
|
removeOrientationListener(onOrientationChange);
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const showFullScreenEditor = useCallback(() => {
|
||||||
|
setFullscreen(true);
|
||||||
|
if (deviceMode === "smallTablet") {
|
||||||
|
fluidTabsRef.current?.openDrawer(false);
|
||||||
|
}
|
||||||
|
editorRef.current?.setNativeProps({
|
||||||
|
style: {
|
||||||
|
width: dimensions.width,
|
||||||
|
zIndex: 999,
|
||||||
|
paddingHorizontal:
|
||||||
|
deviceMode === "smallTablet"
|
||||||
|
? dimensions.width * 0
|
||||||
|
: dimensions.width * 0.15
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, [deviceMode, dimensions.width, setFullscreen]);
|
||||||
|
|
||||||
|
const closeFullScreenEditor = useCallback(
|
||||||
|
(current: string) => {
|
||||||
|
const _deviceMode = current || deviceMode;
|
||||||
|
if (_deviceMode === "smallTablet") {
|
||||||
|
fluidTabsRef.current?.closeDrawer(false);
|
||||||
|
}
|
||||||
|
setFullscreen(false);
|
||||||
|
editorController.current?.commands.updateSettings({
|
||||||
|
fullscreen: false
|
||||||
|
});
|
||||||
|
editorRef.current?.setNativeProps({
|
||||||
|
style: {
|
||||||
|
width:
|
||||||
|
_deviceMode === "smallTablet"
|
||||||
|
? dimensions.width -
|
||||||
|
valueLimiter(dimensions.width * 0.4, 300, 450)
|
||||||
|
: dimensions.width * 0.48,
|
||||||
|
zIndex: null,
|
||||||
|
paddingHorizontal: 0
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (_deviceMode === "smallTablet") {
|
||||||
|
fluidTabsRef.current?.goToIndex(1, false);
|
||||||
|
}
|
||||||
|
if (_deviceMode === "mobile") {
|
||||||
|
fluidTabsRef.current?.goToIndex(2, false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[deviceMode, dimensions.width, setFullscreen]
|
||||||
|
);
|
||||||
|
|
||||||
|
const toggleView = useCallback(
|
||||||
|
(show: boolean) => {
|
||||||
|
animatedTranslateY.value = show ? 0 : -9999;
|
||||||
|
},
|
||||||
|
[animatedTranslateY]
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!fluidTabsRef.current?.isDrawerOpen()) {
|
||||||
|
toggleView(false);
|
||||||
|
}
|
||||||
|
eSubscribeEvent(eOpenFullscreenEditor, showFullScreenEditor);
|
||||||
|
eSubscribeEvent(eCloseFullscreenEditor, closeFullScreenEditor);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
eUnSubscribeEvent(eOpenFullscreenEditor, showFullScreenEditor);
|
||||||
|
eUnSubscribeEvent(eCloseFullscreenEditor, closeFullScreenEditor);
|
||||||
|
};
|
||||||
|
}, [
|
||||||
|
deviceMode,
|
||||||
|
dimensions,
|
||||||
|
colors,
|
||||||
|
showFullScreenEditor,
|
||||||
|
closeFullScreenEditor,
|
||||||
|
toggleView
|
||||||
|
]);
|
||||||
|
|
||||||
|
const setDeviceMode = React.useCallback(
|
||||||
|
(current: string | null, size: { width: number; height: number }) => {
|
||||||
|
setDeviceModeState(current);
|
||||||
|
|
||||||
|
const needsLayout = current !== deviceMode;
|
||||||
|
|
||||||
|
if (fullscreen && current !== "mobile") {
|
||||||
|
// Runs after size is set via state.
|
||||||
|
setTimeout(() => {
|
||||||
|
editorRef.current?.setNativeProps({
|
||||||
|
style: {
|
||||||
|
width: size.width,
|
||||||
|
zIndex: 999,
|
||||||
|
paddingHorizontal:
|
||||||
|
current === "smallTablet" ? size.width * 0 : size.width * 0.15
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 1);
|
||||||
|
} else {
|
||||||
|
if (fullscreen) eSendEvent(eCloseFullscreenEditor, current);
|
||||||
|
editorRef.current?.setNativeProps({
|
||||||
|
style: {
|
||||||
|
position: "relative",
|
||||||
|
width:
|
||||||
|
current === "tablet"
|
||||||
|
? size.width * 0.48
|
||||||
|
: current === "smallTablet"
|
||||||
|
? size.width - valueLimiter(size.width * 0.4, 300, 450)
|
||||||
|
: size.width,
|
||||||
|
zIndex: null,
|
||||||
|
paddingHorizontal: 0
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (!needsLayout) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const state = getAppState();
|
||||||
|
switch (current) {
|
||||||
|
case "tablet":
|
||||||
|
fluidTabsRef.current?.goToIndex(0, false);
|
||||||
|
break;
|
||||||
|
case "smallTablet":
|
||||||
|
if (!fullscreen) {
|
||||||
|
fluidTabsRef.current?.closeDrawer(false);
|
||||||
|
} else {
|
||||||
|
fluidTabsRef.current?.openDrawer(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "mobile":
|
||||||
|
if (
|
||||||
|
state &&
|
||||||
|
editorState().movedAway === false &&
|
||||||
|
useTabStore.getState().getCurrentNoteId()
|
||||||
|
) {
|
||||||
|
fluidTabsRef.current?.goToIndex(2, false);
|
||||||
|
} else {
|
||||||
|
fluidTabsRef.current?.goToIndex(1, false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[deviceMode, fullscreen, setDeviceModeState]
|
||||||
|
);
|
||||||
|
|
||||||
|
const checkDeviceType = React.useCallback(
|
||||||
|
(size: { width: number; height: number }) => {
|
||||||
|
setDimensions({
|
||||||
|
width: size.width,
|
||||||
|
height: size.height
|
||||||
|
});
|
||||||
|
DDS.setSize(size, orientation);
|
||||||
|
const nextDeviceMode = DDS.isLargeTablet()
|
||||||
|
? "tablet"
|
||||||
|
: DDS.isSmallTab
|
||||||
|
? "smallTablet"
|
||||||
|
: "mobile";
|
||||||
|
|
||||||
|
setDeviceMode(nextDeviceMode, size);
|
||||||
|
},
|
||||||
|
[orientation, setDeviceMode, setDimensions]
|
||||||
|
);
|
||||||
|
|
||||||
|
const _onLayout = React.useCallback(
|
||||||
|
(event: LayoutChangeEvent) => {
|
||||||
|
const size = event?.nativeEvent?.layout;
|
||||||
|
if (!size || (size.width === dimensions.width && deviceMode !== null)) {
|
||||||
|
DDS.setSize(size, orientation);
|
||||||
|
setDeviceMode(deviceMode, size);
|
||||||
|
checkDeviceType(size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkDeviceType(size);
|
||||||
|
},
|
||||||
|
[
|
||||||
|
checkDeviceType,
|
||||||
|
deviceMode,
|
||||||
|
dimensions.width,
|
||||||
|
orientation,
|
||||||
|
setDeviceMode
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!deviceMode) {
|
||||||
|
const size = Dimensions.get("window");
|
||||||
|
checkDeviceType(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
const PANE_OFFSET = useMemo(
|
||||||
|
() => ({
|
||||||
|
mobile: {
|
||||||
|
sidebar: dimensions.width * MOBILE_SIDEBAR_SIZE,
|
||||||
|
list: dimensions.width + dimensions.width * MOBILE_SIDEBAR_SIZE,
|
||||||
|
editor: dimensions.width * 2 + dimensions.width * MOBILE_SIDEBAR_SIZE
|
||||||
|
},
|
||||||
|
smallTablet: {
|
||||||
|
sidebar: fullscreen
|
||||||
|
? 0
|
||||||
|
: valueLimiter(dimensions.width * 0.3, 300, 350),
|
||||||
|
list: fullscreen
|
||||||
|
? 0
|
||||||
|
: dimensions.width + valueLimiter(dimensions.width * 0.3, 300, 350),
|
||||||
|
editor: fullscreen
|
||||||
|
? 0
|
||||||
|
: dimensions.width + valueLimiter(dimensions.width * 0.3, 300, 350)
|
||||||
|
},
|
||||||
|
tablet: {
|
||||||
|
sidebar: 0,
|
||||||
|
list: 0,
|
||||||
|
editor: 0
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
[dimensions.width, fullscreen]
|
||||||
|
);
|
||||||
|
|
||||||
|
const PANE_WIDTHS = useMemo(
|
||||||
|
() => ({
|
||||||
|
mobile: {
|
||||||
|
sidebar: dimensions.width * MOBILE_SIDEBAR_SIZE,
|
||||||
|
list: dimensions.width,
|
||||||
|
editor: dimensions.width
|
||||||
|
},
|
||||||
|
smallTablet: {
|
||||||
|
sidebar: valueLimiter(dimensions.width * 0.3, 300, 350),
|
||||||
|
list: valueLimiter(dimensions.width * 0.4, 300, 450),
|
||||||
|
editor:
|
||||||
|
dimensions.width - valueLimiter(dimensions.width * 0.4, 300, 450)
|
||||||
|
},
|
||||||
|
tablet: {
|
||||||
|
sidebar: dimensions.width * 0.22,
|
||||||
|
list: dimensions.width * 0.3,
|
||||||
|
editor: dimensions.width * 0.48
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
[dimensions.width]
|
||||||
|
);
|
||||||
|
|
||||||
|
const onScroll = React.useCallback(
|
||||||
|
(scrollOffset: number) => {
|
||||||
|
if (!deviceMode) return;
|
||||||
|
hideAllTooltips();
|
||||||
|
if (
|
||||||
|
scrollOffset >
|
||||||
|
PANE_OFFSET[deviceMode as keyof typeof PANE_OFFSET].sidebar - 10
|
||||||
|
) {
|
||||||
|
animatedOpacity.value = 0;
|
||||||
|
toggleView(false);
|
||||||
|
} else {
|
||||||
|
const o = scrollOffset / 300;
|
||||||
|
const opacity = o < 0 ? 1 : 1 - o;
|
||||||
|
animatedOpacity.value = opacity;
|
||||||
|
toggleView(opacity < 0.1 ? false : true);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[PANE_OFFSET, animatedOpacity, deviceMode, toggleView]
|
||||||
|
);
|
||||||
|
|
||||||
|
const animatedStyle = useAnimatedStyle(() => {
|
||||||
|
return {
|
||||||
|
opacity: animatedOpacity.value,
|
||||||
|
transform: [
|
||||||
|
{
|
||||||
|
translateY: animatedTranslateY.value
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
onLayout={_onLayout}
|
||||||
|
testID={notesnook.ids.default.root}
|
||||||
|
style={{
|
||||||
|
height: "100%",
|
||||||
|
width: "100%",
|
||||||
|
backgroundColor: colors.primary.background,
|
||||||
|
paddingBottom: Platform.OS === "android" ? insets?.bottom : 0,
|
||||||
|
marginRight:
|
||||||
|
orientation === "LANDSCAPE-RIGHT" && Platform.OS === "ios"
|
||||||
|
? insets.right
|
||||||
|
: 0,
|
||||||
|
marginLeft:
|
||||||
|
orientation === "LANDSCAPE-LEFT" && Platform.OS === "ios"
|
||||||
|
? insets.left
|
||||||
|
: 0
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{deviceMode && PANE_WIDTHS[deviceMode as keyof typeof PANE_WIDTHS] ? (
|
||||||
|
<FluidPanels
|
||||||
|
ref={fluidTabsRef}
|
||||||
|
dimensions={dimensions}
|
||||||
|
widths={PANE_WIDTHS[deviceMode as keyof typeof PANE_WIDTHS]}
|
||||||
|
enabled={deviceMode !== "tablet" && !fullscreen}
|
||||||
|
onScroll={onScroll}
|
||||||
|
onChangeTab={onChangeTab}
|
||||||
|
onDrawerStateChange={(state) => {
|
||||||
|
if (!state) {
|
||||||
|
useSideBarDraggingStore.setState({
|
||||||
|
dragging: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
key="1"
|
||||||
|
style={{
|
||||||
|
height: "100%",
|
||||||
|
width: fullscreen
|
||||||
|
? 0
|
||||||
|
: PANE_WIDTHS[deviceMode as keyof typeof PANE_WIDTHS]?.sidebar
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ScopedThemeProvider value="navigationMenu">
|
||||||
|
<SideMenu />
|
||||||
|
</ScopedThemeProvider>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<View
|
||||||
|
key="2"
|
||||||
|
style={{
|
||||||
|
height: "100%",
|
||||||
|
width: fullscreen
|
||||||
|
? 0
|
||||||
|
: PANE_WIDTHS[deviceMode as keyof typeof PANE_WIDTHS]?.list
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ScopedThemeProvider value="list">
|
||||||
|
{deviceMode === "mobile" ? (
|
||||||
|
<Animated.View
|
||||||
|
onTouchEnd={() => {
|
||||||
|
if (useSideBarDraggingStore.getState().dragging) {
|
||||||
|
useSideBarDraggingStore.setState({
|
||||||
|
dragging: false
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fluidTabsRef.current?.closeDrawer();
|
||||||
|
animatedOpacity.value = withTiming(0);
|
||||||
|
animatedTranslateY.value = withTiming(-9999);
|
||||||
|
}}
|
||||||
|
style={[
|
||||||
|
{
|
||||||
|
position: "absolute",
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
zIndex: 999,
|
||||||
|
backgroundColor: colors.primary.backdrop
|
||||||
|
},
|
||||||
|
animatedStyle
|
||||||
|
]}
|
||||||
|
ref={overlayRef}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
|
||||||
|
<SafeAreaView
|
||||||
|
style={{
|
||||||
|
flex: 1
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AppNavigationStack />
|
||||||
|
</SafeAreaView>
|
||||||
|
</ScopedThemeProvider>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<ScopedThemeProvider value="editor">
|
||||||
|
<EditorWrapper key="3" widths={PANE_WIDTHS} />
|
||||||
|
</ScopedThemeProvider>
|
||||||
|
</FluidPanels>
|
||||||
|
) : null}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
() => true
|
||||||
|
);
|
||||||
|
FluidPanelsView.displayName = "FluidPanelsView";
|
||||||
|
|
||||||
|
const onChangeTab = async (event: { i: number; from: number }) => {
|
||||||
|
if (event.i === 2) {
|
||||||
|
editorState().movedAway = false;
|
||||||
|
editorState().isFocused = true;
|
||||||
|
activateKeepAwake();
|
||||||
|
eSendEvent(eOnEnterEditor);
|
||||||
|
|
||||||
|
if (!useTabStore.getState().getCurrentNoteId()) {
|
||||||
|
eSendEvent(eOnLoadNote, {
|
||||||
|
newNote: true
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (
|
||||||
|
useTabStore.getState().getTab(useTabStore.getState().currentTab)
|
||||||
|
?.session?.locked
|
||||||
|
) {
|
||||||
|
eSendEvent(eUnlockNote);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (event.from === 2) {
|
||||||
|
deactivateKeepAwake();
|
||||||
|
editorState().movedAway = true;
|
||||||
|
editorState().isFocused = false;
|
||||||
|
eSendEvent(eOnExitEditor);
|
||||||
|
|
||||||
|
// Lock all tabs with locked notes...
|
||||||
|
for (const tab of useTabStore.getState().tabs) {
|
||||||
|
const noteId = useTabStore.getState().getTab(tab.id)?.session?.noteId;
|
||||||
|
if (!noteId) continue;
|
||||||
|
const note = await db.notes.note(noteId);
|
||||||
|
const locked = note && (await db.vaults.itemExists(note));
|
||||||
|
if (locked) {
|
||||||
|
useTabStore.getState().updateTab(tab.id, {
|
||||||
|
session: {
|
||||||
|
locked: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,150 +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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { strings } from "@notesnook/intl";
|
|
||||||
import { useThemeColors } from "@notesnook/theme";
|
|
||||||
import { NavigationContainer } from "@react-navigation/native";
|
|
||||||
import { createNativeStackNavigator } from "@react-navigation/native-stack";
|
|
||||||
import * as React from "react";
|
|
||||||
import Container from "../components/container";
|
|
||||||
import Intro from "../components/intro";
|
|
||||||
import { NotebookSheet } from "../components/sheets/notebook-sheet";
|
|
||||||
import useGlobalSafeAreaInsets from "../hooks/use-global-safe-area-insets";
|
|
||||||
import { hideAllTooltips } from "../hooks/use-tooltip";
|
|
||||||
import Favorites from "../screens/favorites";
|
|
||||||
import Home from "../screens/home";
|
|
||||||
import NotebookScreen from "../screens/notebook";
|
|
||||||
import Notebooks from "../screens/notebooks";
|
|
||||||
import { ColoredNotes } from "../screens/notes/colored";
|
|
||||||
import { Monographs } from "../screens/notes/monographs";
|
|
||||||
import { TaggedNotes } from "../screens/notes/tagged";
|
|
||||||
import Reminders from "../screens/reminders";
|
|
||||||
import { Search } from "../screens/search";
|
|
||||||
import Settings from "../screens/settings";
|
|
||||||
import Tags from "../screens/tags";
|
|
||||||
import Trash from "../screens/trash";
|
|
||||||
import { eSendEvent } from "../services/event-manager";
|
|
||||||
import SettingsService from "../services/settings";
|
|
||||||
import useNavigationStore from "../stores/use-navigation-store";
|
|
||||||
import { useSelectionStore } from "../stores/use-selection-store";
|
|
||||||
import { useSettingStore } from "../stores/use-setting-store";
|
|
||||||
import { rootNavigatorRef } from "../utils/global-refs";
|
|
||||||
|
|
||||||
const NativeStack = createNativeStackNavigator();
|
|
||||||
const IntroStack = createNativeStackNavigator();
|
|
||||||
|
|
||||||
const IntroStackNavigator = () => {
|
|
||||||
const { colors } = useThemeColors();
|
|
||||||
const height = useSettingStore((state) => state.dimensions.height);
|
|
||||||
return (
|
|
||||||
<IntroStack.Navigator
|
|
||||||
screenOptions={{
|
|
||||||
headerShown: false,
|
|
||||||
lazy: false,
|
|
||||||
animation: "none",
|
|
||||||
contentStyle: {
|
|
||||||
backgroundColor: colors.primary.background,
|
|
||||||
minHeight: height
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
initialRouteName={"Intro"}
|
|
||||||
>
|
|
||||||
<NativeStack.Screen name="Intro" component={Intro} />
|
|
||||||
</IntroStack.Navigator>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const _Tabs = () => {
|
|
||||||
const { colors } = useThemeColors();
|
|
||||||
const homepage = SettingsService.get().homepage;
|
|
||||||
const introCompleted = useSettingStore(
|
|
||||||
(state) => state.settings.introCompleted
|
|
||||||
);
|
|
||||||
|
|
||||||
const height = useSettingStore((state) => state.dimensions.height);
|
|
||||||
const insets = useGlobalSafeAreaInsets();
|
|
||||||
const screenHeight = height - (50 + insets.top + insets.bottom);
|
|
||||||
React.useEffect(() => {
|
|
||||||
setTimeout(async () => {
|
|
||||||
useNavigationStore.getState().update(homepage);
|
|
||||||
}, 1000);
|
|
||||||
}, [homepage]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<NativeStack.Navigator
|
|
||||||
tabBar={() => null}
|
|
||||||
initialRouteName={!introCompleted ? "Welcome" : homepage}
|
|
||||||
backBehavior="history"
|
|
||||||
screenOptions={{
|
|
||||||
headerShown: false,
|
|
||||||
lazy: false,
|
|
||||||
animation: "none",
|
|
||||||
contentStyle: {
|
|
||||||
backgroundColor: colors.primary.background,
|
|
||||||
minHeight: !introCompleted ? undefined : screenHeight
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<NativeStack.Screen name="Welcome" component={IntroStackNavigator} />
|
|
||||||
<NativeStack.Screen name="Notes" component={Home} />
|
|
||||||
<NativeStack.Screen name="Notebooks" component={Notebooks} />
|
|
||||||
<NativeStack.Screen name="Favorites" component={Favorites} />
|
|
||||||
<NativeStack.Screen name="Trash" component={Trash} />
|
|
||||||
<NativeStack.Screen name="Tags" component={Tags} />
|
|
||||||
<NativeStack.Screen name="Settings" component={Settings} />
|
|
||||||
<NativeStack.Screen name="TaggedNotes" component={TaggedNotes} />
|
|
||||||
<NativeStack.Screen name="ColoredNotes" component={ColoredNotes} />
|
|
||||||
<NativeStack.Screen name="Reminders" component={Reminders} />
|
|
||||||
<NativeStack.Screen
|
|
||||||
name="Monographs"
|
|
||||||
initialParams={{
|
|
||||||
item: { type: "monograph" },
|
|
||||||
canGoBack: false,
|
|
||||||
title: strings.monographs()
|
|
||||||
}}
|
|
||||||
component={Monographs}
|
|
||||||
/>
|
|
||||||
<NativeStack.Screen name="Notebook" component={NotebookScreen} />
|
|
||||||
<NativeStack.Screen name="Search" component={Search} />
|
|
||||||
</NativeStack.Navigator>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
const Tabs = React.memo(_Tabs, () => true);
|
|
||||||
|
|
||||||
const _NavigationStack = () => {
|
|
||||||
const clearSelection = useSelectionStore((state) => state.clearSelection);
|
|
||||||
const loading = useSettingStore((state) => state.isAppLoading);
|
|
||||||
const onStateChange = React.useCallback(() => {
|
|
||||||
if (useSelectionStore.getState().selectionMode) {
|
|
||||||
clearSelection(true);
|
|
||||||
}
|
|
||||||
hideAllTooltips();
|
|
||||||
eSendEvent("navigate");
|
|
||||||
}, [clearSelection]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Container>
|
|
||||||
<NavigationContainer onStateChange={onStateChange} ref={rootNavigatorRef}>
|
|
||||||
<Tabs />
|
|
||||||
</NavigationContainer>
|
|
||||||
{loading ? null : <NotebookSheet />}
|
|
||||||
</Container>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
export const NavigationStack = React.memo(_NavigationStack, () => true);
|
|
||||||
158
apps/mobile/app/navigation/navigation-stack.tsx
Normal file
158
apps/mobile/app/navigation/navigation-stack.tsx
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
/*
|
||||||
|
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 { NavigationContainer } from "@react-navigation/native";
|
||||||
|
import { createNativeStackNavigator } from "@react-navigation/native-stack";
|
||||||
|
import * as React from "react";
|
||||||
|
import AppLockedScreen from "../components/app-lock-overlay";
|
||||||
|
import useGlobalSafeAreaInsets from "../hooks/use-global-safe-area-insets";
|
||||||
|
import { hideAllTooltips } from "../hooks/use-tooltip";
|
||||||
|
import Favorites from "../screens/favorites";
|
||||||
|
import Home from "../screens/home";
|
||||||
|
import NotebookScreen from "../screens/notebook";
|
||||||
|
import Notebooks from "../screens/notebooks";
|
||||||
|
import { ColoredNotes } from "../screens/notes/colored";
|
||||||
|
import { Monographs } from "../screens/notes/monographs";
|
||||||
|
import { TaggedNotes } from "../screens/notes/tagged";
|
||||||
|
import Reminders from "../screens/reminders";
|
||||||
|
import { Search } from "../screens/search";
|
||||||
|
import Settings from "../screens/settings";
|
||||||
|
import Tags from "../screens/tags";
|
||||||
|
import Trash from "../screens/trash";
|
||||||
|
import SettingsService from "../services/settings";
|
||||||
|
import useNavigationStore, {
|
||||||
|
RouteParams
|
||||||
|
} from "../stores/use-navigation-store";
|
||||||
|
import { useSelectionStore } from "../stores/use-selection-store";
|
||||||
|
import { useSettingStore } from "../stores/use-setting-store";
|
||||||
|
import {
|
||||||
|
appNavigatorRef,
|
||||||
|
fluidTabsRef,
|
||||||
|
rootNavigatorRef
|
||||||
|
} from "../utils/global-refs";
|
||||||
|
import { FluidPanelsView } from "./fluid-panels-view";
|
||||||
|
|
||||||
|
const RootStack = createNativeStackNavigator();
|
||||||
|
const AppStack = createNativeStackNavigator();
|
||||||
|
|
||||||
|
const AppNavigation = React.memo(
|
||||||
|
() => {
|
||||||
|
const { colors } = useThemeColors();
|
||||||
|
const homepage = SettingsService.get().homepage;
|
||||||
|
const introCompleted = useSettingStore(
|
||||||
|
(state) => state.settings.introCompleted
|
||||||
|
);
|
||||||
|
const height = useSettingStore((state) => state.dimensions.height);
|
||||||
|
const insets = useGlobalSafeAreaInsets();
|
||||||
|
const screenHeight = height - (50 + insets.top + insets.bottom);
|
||||||
|
React.useEffect(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
useNavigationStore.getState().update(homepage as keyof RouteParams);
|
||||||
|
}, 1000);
|
||||||
|
}, [homepage]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppStack.Navigator
|
||||||
|
initialRouteName={!introCompleted ? "Welcome" : homepage}
|
||||||
|
screenOptions={{
|
||||||
|
headerShown: false,
|
||||||
|
animation: "none",
|
||||||
|
contentStyle: {
|
||||||
|
backgroundColor: colors.primary.background,
|
||||||
|
minHeight: !introCompleted ? undefined : screenHeight
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AppStack.Screen name="Notes" component={Home} />
|
||||||
|
<AppStack.Screen name="Notebooks" component={Notebooks} />
|
||||||
|
<AppStack.Screen name="Favorites" component={Favorites} />
|
||||||
|
<AppStack.Screen name="Trash" component={Trash} />
|
||||||
|
<AppStack.Screen name="Tags" component={Tags} />
|
||||||
|
<AppStack.Screen name="TaggedNotes" component={TaggedNotes} />
|
||||||
|
<AppStack.Screen name="ColoredNotes" component={ColoredNotes} />
|
||||||
|
<AppStack.Screen name="Reminders" component={Reminders} />
|
||||||
|
<AppStack.Screen
|
||||||
|
name="Monographs"
|
||||||
|
initialParams={{
|
||||||
|
item: { type: "monograph" },
|
||||||
|
canGoBack: false,
|
||||||
|
title: strings.monographs()
|
||||||
|
}}
|
||||||
|
component={Monographs}
|
||||||
|
/>
|
||||||
|
<AppStack.Screen name="Notebook" component={NotebookScreen} />
|
||||||
|
<AppStack.Screen name="Search" component={Search} />
|
||||||
|
</AppStack.Navigator>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
() => true
|
||||||
|
);
|
||||||
|
AppNavigation.displayName = "AppNavigation";
|
||||||
|
|
||||||
|
export const RootNavigation = () => {
|
||||||
|
return (
|
||||||
|
<NavigationContainer ref={rootNavigatorRef} independent>
|
||||||
|
<RootStack.Navigator
|
||||||
|
screenOptions={{
|
||||||
|
headerShown: false
|
||||||
|
}}
|
||||||
|
screenListeners={{
|
||||||
|
focus: (props) => {
|
||||||
|
if (props.target?.startsWith("FluidPanelsView")) {
|
||||||
|
fluidTabsRef.current?.unlock();
|
||||||
|
} else {
|
||||||
|
fluidTabsRef.current?.lock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
initialRouteName="FluidPanelsView"
|
||||||
|
>
|
||||||
|
<RootStack.Screen name="FluidPanelsView" component={FluidPanelsView} />
|
||||||
|
<RootStack.Screen name="AppLock" component={AppLockedScreen} />
|
||||||
|
<AppStack.Screen name="Settings" component={Settings} />
|
||||||
|
</RootStack.Navigator>
|
||||||
|
</NavigationContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AppNavigationStack = React.memo(
|
||||||
|
() => {
|
||||||
|
const clearSelection = useSelectionStore((state) => state.clearSelection);
|
||||||
|
const onStateChange = React.useCallback(() => {
|
||||||
|
if (useSelectionStore.getState().selectionMode) {
|
||||||
|
clearSelection();
|
||||||
|
}
|
||||||
|
hideAllTooltips();
|
||||||
|
}, [clearSelection]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NavigationContainer
|
||||||
|
independent
|
||||||
|
onStateChange={onStateChange}
|
||||||
|
ref={appNavigatorRef}
|
||||||
|
>
|
||||||
|
<AppNavigation />
|
||||||
|
</NavigationContainer>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
() => true
|
||||||
|
);
|
||||||
|
AppNavigationStack.displayName = "AppNavigationStack";
|
||||||
@@ -1,541 +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/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { ScopedThemeProvider, useThemeColors } from "@notesnook/theme";
|
|
||||||
import {
|
|
||||||
activateKeepAwake,
|
|
||||||
deactivateKeepAwake
|
|
||||||
} from "@sayem314/react-native-keep-awake";
|
|
||||||
import React, { useCallback, useEffect, useRef, useState } from "react";
|
|
||||||
import { Dimensions, Platform, StatusBar, View } from "react-native";
|
|
||||||
import {
|
|
||||||
addOrientationListener,
|
|
||||||
addSpecificOrientationListener,
|
|
||||||
getInitialOrientation,
|
|
||||||
getSpecificOrientation,
|
|
||||||
removeOrientationListener,
|
|
||||||
removeSpecificOrientationListener
|
|
||||||
} from "react-native-orientation";
|
|
||||||
import Animated, {
|
|
||||||
useAnimatedStyle,
|
|
||||||
useSharedValue,
|
|
||||||
withTiming
|
|
||||||
} from "react-native-reanimated";
|
|
||||||
import { notesnook } from "../../e2e/test.ids";
|
|
||||||
import { db } from "../common/database";
|
|
||||||
import { SideMenu } from "../components/side-menu";
|
|
||||||
import { useSideBarDraggingStore } from "../components/side-menu/dragging-store";
|
|
||||||
import { FluidTabs } from "../components/tabs";
|
|
||||||
import useGlobalSafeAreaInsets from "../hooks/use-global-safe-area-insets";
|
|
||||||
import { useShortcutManager } from "../hooks/use-shortcut-manager";
|
|
||||||
import { hideAllTooltips } from "../hooks/use-tooltip";
|
|
||||||
import { useTabStore } from "../screens/editor/tiptap/use-tab-store";
|
|
||||||
import {
|
|
||||||
clearAppState,
|
|
||||||
editorController,
|
|
||||||
editorState,
|
|
||||||
getAppState
|
|
||||||
} from "../screens/editor/tiptap/utils";
|
|
||||||
import { EditorWrapper } from "../screens/editor/wrapper";
|
|
||||||
import { DDS } from "../services/device-detection";
|
|
||||||
import {
|
|
||||||
eSendEvent,
|
|
||||||
eSubscribeEvent,
|
|
||||||
eUnSubscribeEvent
|
|
||||||
} from "../services/event-manager";
|
|
||||||
import { useSettingStore } from "../stores/use-setting-store";
|
|
||||||
import {
|
|
||||||
eCloseFullscreenEditor,
|
|
||||||
eOnEnterEditor,
|
|
||||||
eOnExitEditor,
|
|
||||||
eOnLoadNote,
|
|
||||||
eOpenFullscreenEditor,
|
|
||||||
eUnlockNote
|
|
||||||
} from "../utils/events";
|
|
||||||
import { editorRef, tabBarRef } from "../utils/global-refs";
|
|
||||||
import { sleep } from "../utils/time";
|
|
||||||
import { NavigationStack } from "./navigation-stack";
|
|
||||||
|
|
||||||
const _TabsHolder = () => {
|
|
||||||
const { colors } = useThemeColors();
|
|
||||||
const deviceMode = useSettingStore((state) => state.deviceMode);
|
|
||||||
const setFullscreen = useSettingStore((state) => state.setFullscreen);
|
|
||||||
const fullscreen = useSettingStore((state) => state.fullscreen);
|
|
||||||
const setDeviceModeState = useSettingStore((state) => state.setDeviceMode);
|
|
||||||
const dimensions = useSettingStore((state) => state.dimensions);
|
|
||||||
const setDimensions = useSettingStore((state) => state.setDimensions);
|
|
||||||
const insets = useGlobalSafeAreaInsets();
|
|
||||||
const animatedOpacity = useSharedValue(0);
|
|
||||||
const animatedTranslateY = useSharedValue(-9999);
|
|
||||||
const overlayRef = useRef();
|
|
||||||
const [orientation, setOrientation] = useState(getInitialOrientation());
|
|
||||||
|
|
||||||
const introCompleted = useSettingStore(
|
|
||||||
(state) => state.settings.introCompleted
|
|
||||||
);
|
|
||||||
|
|
||||||
useShortcutManager({
|
|
||||||
onShortcutPressed: async (item) => {
|
|
||||||
if (!item && getAppState()) {
|
|
||||||
editorState().movedAway = false;
|
|
||||||
tabBarRef.current?.goToPage(1, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (item && item.type === "notesnook.action.newnote") {
|
|
||||||
clearAppState();
|
|
||||||
if (!tabBarRef.current) {
|
|
||||||
await sleep(3000);
|
|
||||||
eSendEvent(eOnLoadNote, { newNote: true });
|
|
||||||
editorState().movedAway = false;
|
|
||||||
tabBarRef.current?.goToPage(1, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
eSendEvent(eOnLoadNote, { newNote: true });
|
|
||||||
editorState().movedAway = false;
|
|
||||||
tabBarRef.current?.goToPage(1, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const onOrientationChange = (o, o2) => {
|
|
||||||
setOrientation(o || o2);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (Platform.OS === "ios") {
|
|
||||||
addSpecificOrientationListener(onOrientationChange);
|
|
||||||
getSpecificOrientation && getSpecificOrientation(onOrientationChange);
|
|
||||||
} else {
|
|
||||||
addOrientationListener(onOrientationChange);
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
removeSpecificOrientationListener(onOrientationChange);
|
|
||||||
removeOrientationListener(onOrientationChange);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const showFullScreenEditor = useCallback(() => {
|
|
||||||
setFullscreen(true);
|
|
||||||
if (deviceMode === "smallTablet") {
|
|
||||||
tabBarRef.current?.openDrawer(false);
|
|
||||||
}
|
|
||||||
editorRef.current?.setNativeProps({
|
|
||||||
style: {
|
|
||||||
width: dimensions.width,
|
|
||||||
zIndex: 999,
|
|
||||||
paddingHorizontal:
|
|
||||||
deviceMode === "smallTablet"
|
|
||||||
? dimensions.width * 0
|
|
||||||
: dimensions.width * 0.15
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, [deviceMode, dimensions.width, setFullscreen]);
|
|
||||||
|
|
||||||
const closeFullScreenEditor = useCallback(
|
|
||||||
(current) => {
|
|
||||||
const _deviceMode = current || deviceMode;
|
|
||||||
if (_deviceMode === "smallTablet") {
|
|
||||||
tabBarRef.current?.closeDrawer(false);
|
|
||||||
}
|
|
||||||
setFullscreen(false);
|
|
||||||
editorController.current?.commands.updateSettings({
|
|
||||||
fullscreen: false
|
|
||||||
});
|
|
||||||
editorRef.current?.setNativeProps({
|
|
||||||
style: {
|
|
||||||
width:
|
|
||||||
_deviceMode === "smallTablet"
|
|
||||||
? dimensions.width -
|
|
||||||
valueLimiter(dimensions.width * 0.4, 300, 450)
|
|
||||||
: dimensions.width * 0.48,
|
|
||||||
zIndex: null,
|
|
||||||
paddingHorizontal: 0
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (_deviceMode === "smallTablet") {
|
|
||||||
tabBarRef.current?.goToIndex(1, false);
|
|
||||||
}
|
|
||||||
if (_deviceMode === "mobile") {
|
|
||||||
tabBarRef.current?.goToIndex(2, false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[deviceMode, dimensions.width, setFullscreen]
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!tabBarRef.current?.isDrawerOpen()) {
|
|
||||||
toggleView(false);
|
|
||||||
}
|
|
||||||
eSubscribeEvent(eOpenFullscreenEditor, showFullScreenEditor);
|
|
||||||
eSubscribeEvent(eCloseFullscreenEditor, closeFullScreenEditor);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
eUnSubscribeEvent(eOpenFullscreenEditor, showFullScreenEditor);
|
|
||||||
eUnSubscribeEvent(eCloseFullscreenEditor, closeFullScreenEditor);
|
|
||||||
};
|
|
||||||
}, [
|
|
||||||
deviceMode,
|
|
||||||
dimensions,
|
|
||||||
colors,
|
|
||||||
showFullScreenEditor,
|
|
||||||
closeFullScreenEditor,
|
|
||||||
toggleView
|
|
||||||
]);
|
|
||||||
|
|
||||||
const _onLayout = (event) => {
|
|
||||||
let size = event?.nativeEvent?.layout;
|
|
||||||
if (!size || (size.width === dimensions.width && deviceMode !== null)) {
|
|
||||||
DDS.setSize(size, orientation);
|
|
||||||
setDeviceMode(deviceMode, size);
|
|
||||||
checkDeviceType(size);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkDeviceType(size);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!deviceMode) {
|
|
||||||
const size = Dimensions.get("window");
|
|
||||||
checkDeviceType(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkDeviceType(size) {
|
|
||||||
setDimensions({
|
|
||||||
width: size.width,
|
|
||||||
height: size.height
|
|
||||||
});
|
|
||||||
DDS.setSize(size, orientation);
|
|
||||||
const nextDeviceMode = DDS.isLargeTablet()
|
|
||||||
? "tablet"
|
|
||||||
: DDS.isSmallTab
|
|
||||||
? "smallTablet"
|
|
||||||
: "mobile";
|
|
||||||
|
|
||||||
setDeviceMode(nextDeviceMode, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
function setDeviceMode(current, size) {
|
|
||||||
setDeviceModeState(current);
|
|
||||||
|
|
||||||
let needsUpdate = current !== deviceMode;
|
|
||||||
|
|
||||||
if (fullscreen && current !== "mobile") {
|
|
||||||
// Runs after size is set via state.
|
|
||||||
setTimeout(() => {
|
|
||||||
editorRef.current?.setNativeProps({
|
|
||||||
style: {
|
|
||||||
width: size.width,
|
|
||||||
zIndex: 999,
|
|
||||||
paddingHorizontal:
|
|
||||||
current === "smallTablet" ? size.width * 0 : size.width * 0.15
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, 1);
|
|
||||||
} else {
|
|
||||||
if (fullscreen) eSendEvent(eCloseFullscreenEditor, current);
|
|
||||||
editorRef.current?.setNativeProps({
|
|
||||||
style: {
|
|
||||||
position: "relative",
|
|
||||||
width:
|
|
||||||
current === "tablet"
|
|
||||||
? size.width * 0.48
|
|
||||||
: current === "smallTablet"
|
|
||||||
? size.width - valueLimiter(size.width * 0.4, 300, 450)
|
|
||||||
: size.width,
|
|
||||||
zIndex: null,
|
|
||||||
paddingHorizontal: 0
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!needsUpdate) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const state = getAppState();
|
|
||||||
switch (current) {
|
|
||||||
case "tablet":
|
|
||||||
tabBarRef.current?.goToIndex(0, false);
|
|
||||||
break;
|
|
||||||
case "smallTablet":
|
|
||||||
if (!fullscreen) {
|
|
||||||
tabBarRef.current?.closeDrawer(false);
|
|
||||||
} else {
|
|
||||||
tabBarRef.current?.openDrawer(false);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "mobile":
|
|
||||||
if (
|
|
||||||
state &&
|
|
||||||
editorState().movedAway === false &&
|
|
||||||
useTabStore.getState().getCurrentNoteId()
|
|
||||||
) {
|
|
||||||
tabBarRef.current?.goToIndex(2, false);
|
|
||||||
} else {
|
|
||||||
tabBarRef.current?.goToIndex(1, false);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const onScroll = (scrollOffset) => {
|
|
||||||
hideAllTooltips();
|
|
||||||
if (scrollOffset > offsets[deviceMode].sidebar - 10) {
|
|
||||||
animatedOpacity.value = 0;
|
|
||||||
toggleView(false);
|
|
||||||
} else {
|
|
||||||
let o = scrollOffset / 300;
|
|
||||||
let op = 0;
|
|
||||||
if (o < 0) {
|
|
||||||
op = 1;
|
|
||||||
} else {
|
|
||||||
op = 1 - o;
|
|
||||||
}
|
|
||||||
animatedOpacity.value = op;
|
|
||||||
toggleView(op < 0.1 ? false : true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const toggleView = useCallback(
|
|
||||||
(show) => {
|
|
||||||
animatedTranslateY.value = show ? 0 : -9999;
|
|
||||||
},
|
|
||||||
[animatedTranslateY]
|
|
||||||
);
|
|
||||||
|
|
||||||
const valueLimiter = (value, min, max) => {
|
|
||||||
if (value < min) {
|
|
||||||
return min;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value > max) {
|
|
||||||
return max;
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
};
|
|
||||||
|
|
||||||
const offsets = {
|
|
||||||
mobile: {
|
|
||||||
sidebar: dimensions.width * 0.75,
|
|
||||||
list: dimensions.width + dimensions.width * 0.75,
|
|
||||||
editor: dimensions.width * 2 + dimensions.width * 0.75
|
|
||||||
},
|
|
||||||
smallTablet: {
|
|
||||||
sidebar: fullscreen ? 0 : valueLimiter(dimensions.width * 0.3, 300, 350),
|
|
||||||
list: fullscreen
|
|
||||||
? 0
|
|
||||||
: dimensions.width + valueLimiter(dimensions.width * 0.3, 300, 350),
|
|
||||||
editor: fullscreen
|
|
||||||
? 0
|
|
||||||
: dimensions.width + valueLimiter(dimensions.width * 0.3, 300, 350)
|
|
||||||
},
|
|
||||||
tablet: {
|
|
||||||
sidebar: 0,
|
|
||||||
list: 0,
|
|
||||||
editor: 0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const widths = {
|
|
||||||
mobile: {
|
|
||||||
sidebar: dimensions.width * 0.75,
|
|
||||||
list: dimensions.width,
|
|
||||||
editor: dimensions.width
|
|
||||||
},
|
|
||||||
smallTablet: {
|
|
||||||
sidebar: valueLimiter(dimensions.width * 0.3, 300, 350),
|
|
||||||
list: valueLimiter(dimensions.width * 0.4, 300, 450),
|
|
||||||
editor: dimensions.width - valueLimiter(dimensions.width * 0.4, 300, 450)
|
|
||||||
},
|
|
||||||
tablet: {
|
|
||||||
sidebar: dimensions.width * 0.22,
|
|
||||||
list: dimensions.width * 0.3,
|
|
||||||
editor: dimensions.width * 0.48
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const animatedStyle = useAnimatedStyle(() => {
|
|
||||||
return {
|
|
||||||
opacity: animatedOpacity.value,
|
|
||||||
transform: [
|
|
||||||
{
|
|
||||||
translateY: animatedTranslateY.value
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// useEffect(() => {
|
|
||||||
// changeSystemBarColors();
|
|
||||||
// setTimeout(() => {
|
|
||||||
// changeSystemBarColors();
|
|
||||||
// }, 1000);
|
|
||||||
// }, [colors.primary.background, isDark]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View
|
|
||||||
onLayout={_onLayout}
|
|
||||||
testID={notesnook.ids.default.root}
|
|
||||||
style={{
|
|
||||||
height: "100%",
|
|
||||||
width: "100%",
|
|
||||||
backgroundColor: colors.primary.background,
|
|
||||||
paddingBottom: Platform.OS === "android" ? insets?.bottom : 0,
|
|
||||||
marginRight:
|
|
||||||
orientation === "LANDSCAPE-RIGHT" && Platform.OS === "ios"
|
|
||||||
? insets.right
|
|
||||||
: 0,
|
|
||||||
marginLeft:
|
|
||||||
orientation === "LANDSCAPE-LEFT" && Platform.OS === "ios"
|
|
||||||
? insets.left
|
|
||||||
: 0
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<StatusBar translucent={true} backgroundColor="transparent" />
|
|
||||||
|
|
||||||
{!introCompleted ? (
|
|
||||||
<NavigationStack />
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
{deviceMode && widths[deviceMode] ? (
|
|
||||||
<FluidTabs
|
|
||||||
ref={tabBarRef}
|
|
||||||
dimensions={dimensions}
|
|
||||||
widths={widths[deviceMode]}
|
|
||||||
enabled={deviceMode !== "tablet" && !fullscreen}
|
|
||||||
onScroll={onScroll}
|
|
||||||
onChangeTab={onChangeTab}
|
|
||||||
onDrawerStateChange={(state) => {
|
|
||||||
if (!state) {
|
|
||||||
useSideBarDraggingStore.setState({
|
|
||||||
dragging: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
key="1"
|
|
||||||
style={{
|
|
||||||
height: "100%",
|
|
||||||
width: fullscreen ? 0 : widths[deviceMode]?.sidebar
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ScopedThemeProvider value="navigationMenu">
|
|
||||||
<SideMenu />
|
|
||||||
</ScopedThemeProvider>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<View
|
|
||||||
key="2"
|
|
||||||
style={{
|
|
||||||
height: "100%",
|
|
||||||
width: fullscreen ? 0 : widths[deviceMode]?.list
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ScopedThemeProvider value="list">
|
|
||||||
{deviceMode === "mobile" ? (
|
|
||||||
<Animated.View
|
|
||||||
onTouchEnd={() => {
|
|
||||||
if (useSideBarDraggingStore.getState().dragging) {
|
|
||||||
useSideBarDraggingStore.setState({
|
|
||||||
dragging: false
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
tabBarRef.current?.closeDrawer();
|
|
||||||
animatedOpacity.value = withTiming(0);
|
|
||||||
animatedTranslateY.value = withTiming(-9999);
|
|
||||||
}}
|
|
||||||
style={[
|
|
||||||
{
|
|
||||||
position: "absolute",
|
|
||||||
width: "100%",
|
|
||||||
height: "100%",
|
|
||||||
zIndex: 999,
|
|
||||||
backgroundColor: colors.primary.backdrop
|
|
||||||
},
|
|
||||||
animatedStyle
|
|
||||||
]}
|
|
||||||
ref={overlayRef}
|
|
||||||
/>
|
|
||||||
) : null}
|
|
||||||
|
|
||||||
<NavigationStack />
|
|
||||||
</ScopedThemeProvider>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<ScopedThemeProvider value="editor">
|
|
||||||
<EditorWrapper
|
|
||||||
key="3"
|
|
||||||
widths={widths}
|
|
||||||
dimensions={dimensions}
|
|
||||||
/>
|
|
||||||
</ScopedThemeProvider>
|
|
||||||
</FluidTabs>
|
|
||||||
) : null}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
export const TabHolder = React.memo(_TabsHolder, () => true);
|
|
||||||
|
|
||||||
const onChangeTab = async (event) => {
|
|
||||||
if (event.i === 2) {
|
|
||||||
editorState().movedAway = false;
|
|
||||||
editorState().isFocused = true;
|
|
||||||
activateKeepAwake();
|
|
||||||
eSendEvent(eOnEnterEditor);
|
|
||||||
|
|
||||||
if (!useTabStore.getState().getCurrentNoteId()) {
|
|
||||||
eSendEvent(eOnLoadNote, {
|
|
||||||
newNote: true
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (
|
|
||||||
useTabStore.getState().getTab(useTabStore.getState().currentTab).session
|
|
||||||
?.locked
|
|
||||||
) {
|
|
||||||
eSendEvent(eUnlockNote);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (event.from === 2) {
|
|
||||||
deactivateKeepAwake();
|
|
||||||
editorState().movedAway = true;
|
|
||||||
editorState().isFocused = false;
|
|
||||||
eSendEvent(eOnExitEditor);
|
|
||||||
|
|
||||||
// Lock all tabs with locked notes...
|
|
||||||
for (const tab of useTabStore.getState().tabs) {
|
|
||||||
const noteId = useTabStore.getState().getTab(tab.id)?.session?.noteId;
|
|
||||||
if (!noteId) continue;
|
|
||||||
const note = await db.notes.note(noteId);
|
|
||||||
const locked = note && (await db.vaults.itemExists(note));
|
|
||||||
if (locked) {
|
|
||||||
useTabStore.getState().updateTab(tab.id, {
|
|
||||||
session: {
|
|
||||||
locked: true
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -19,8 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||||
|
|
||||||
import { i18n } from "@lingui/core";
|
|
||||||
import { strings } from "@notesnook/intl";
|
|
||||||
import React, {
|
import React, {
|
||||||
forwardRef,
|
forwardRef,
|
||||||
useCallback,
|
useCallback,
|
||||||
@@ -48,7 +46,6 @@ import {
|
|||||||
eUnlockWithPassword
|
eUnlockWithPassword
|
||||||
} from "../../utils/events";
|
} from "../../utils/events";
|
||||||
import { openLinkInBrowser } from "../../utils/functions";
|
import { openLinkInBrowser } from "../../utils/functions";
|
||||||
import { tabBarRef } from "../../utils/global-refs";
|
|
||||||
import EditorOverlay from "./loading";
|
import EditorOverlay from "./loading";
|
||||||
import { EDITOR_URI } from "./source";
|
import { EDITOR_URI } from "./source";
|
||||||
import { EditorProps, useEditorType } from "./tiptap/types";
|
import { EditorProps, useEditorType } from "./tiptap/types";
|
||||||
@@ -61,6 +58,9 @@ import {
|
|||||||
openInternalLink,
|
openInternalLink,
|
||||||
randId
|
randId
|
||||||
} from "./tiptap/utils";
|
} from "./tiptap/utils";
|
||||||
|
import { fluidTabsRef } from "../../utils/global-refs";
|
||||||
|
import { strings } from "@notesnook/intl";
|
||||||
|
import { i18n } from "@lingui/core";
|
||||||
|
|
||||||
const style: ViewStyle = {
|
const style: ViewStyle = {
|
||||||
height: "100%",
|
height: "100%",
|
||||||
@@ -348,7 +348,7 @@ const useLockedNoteHandler = () => {
|
|||||||
}),
|
}),
|
||||||
eSubscribeEvent(eUnlockWithPassword, onSubmit)
|
eSubscribeEvent(eUnlockWithPassword, onSubmit)
|
||||||
];
|
];
|
||||||
if (tabRef.current?.session?.locked && tabBarRef.current?.page() === 2) {
|
if (tabRef.current?.session?.locked && fluidTabsRef.current?.page() === 2) {
|
||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
return () => {
|
return () => {
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ import {
|
|||||||
eUnlockWithPassword
|
eUnlockWithPassword
|
||||||
} from "../../../utils/events";
|
} from "../../../utils/events";
|
||||||
import { openLinkInBrowser } from "../../../utils/functions";
|
import { openLinkInBrowser } from "../../../utils/functions";
|
||||||
import { tabBarRef } from "../../../utils/global-refs";
|
import { fluidTabsRef } from "../../../utils/global-refs";
|
||||||
import { useDragState } from "../../settings/editor/state";
|
import { useDragState } from "../../settings/editor/state";
|
||||||
import { EditorMessage, EditorProps, useEditorType } from "./types";
|
import { EditorMessage, EditorProps, useEditorType } from "./types";
|
||||||
import { useTabStore } from "./use-tab-store";
|
import { useTabStore } from "./use-tab-store";
|
||||||
@@ -259,7 +259,7 @@ export const useEditorEvents = (
|
|||||||
|
|
||||||
if (deviceMode === "mobile") {
|
if (deviceMode === "mobile") {
|
||||||
editorState().movedAway = true;
|
editorState().movedAway = true;
|
||||||
tabBarRef.current?.goToPage(0);
|
fluidTabsRef.current?.goToPage(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -269,7 +269,7 @@ export const useEditorEvents = (
|
|||||||
}, [editor, deviceMode, fullscreen]);
|
}, [editor, deviceMode, fullscreen]);
|
||||||
|
|
||||||
const onHardwareBackPress = useCallback(() => {
|
const onHardwareBackPress = useCallback(() => {
|
||||||
if (tabBarRef.current?.page() === 2) {
|
if (fluidTabsRef.current?.page() === 2) {
|
||||||
onBackPress();
|
onBackPress();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ import {
|
|||||||
eShowMergeDialog,
|
eShowMergeDialog,
|
||||||
eUpdateNoteInEditor
|
eUpdateNoteInEditor
|
||||||
} from "../../../utils/events";
|
} from "../../../utils/events";
|
||||||
import { tabBarRef } from "../../../utils/global-refs";
|
import { fluidTabsRef } from "../../../utils/global-refs";
|
||||||
import { sleep } from "../../../utils/time";
|
import { sleep } from "../../../utils/time";
|
||||||
import { unlockVault } from "../../../utils/unlock-vault";
|
import { unlockVault } from "../../../utils/unlock-vault";
|
||||||
import { onNoteCreated } from "../../notes/common";
|
import { onNoteCreated } from "../../notes/common";
|
||||||
@@ -995,14 +995,14 @@ export const useEditor = (
|
|||||||
if (!appState) return;
|
if (!appState) return;
|
||||||
state.current.isRestoringState = true;
|
state.current.isRestoringState = true;
|
||||||
state.current.currentlyEditing = true;
|
state.current.currentlyEditing = true;
|
||||||
if (tabBarRef.current?.page() === 2) {
|
if (fluidTabsRef.current?.page() === 2) {
|
||||||
state.current.movedAway = false;
|
state.current.movedAway = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!state.current.editorStateRestored) {
|
if (!state.current.editorStateRestored) {
|
||||||
state.current.isRestoringState = true;
|
state.current.isRestoringState = true;
|
||||||
if (!DDS.isTab) {
|
if (!DDS.isTab) {
|
||||||
tabBarRef.current?.goToPage(1, false);
|
fluidTabsRef.current?.goToPage(1, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1081,12 +1081,12 @@ export const useEditor = (
|
|||||||
item: note
|
item: note
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
tabBarRef.current?.goToPage(1);
|
fluidTabsRef.current?.goToPage(1);
|
||||||
} else {
|
} else {
|
||||||
noteId = useTabStore.getState().getCurrentNoteId() || null;
|
noteId = useTabStore.getState().getCurrentNoteId() || null;
|
||||||
if (!noteId) {
|
if (!noteId) {
|
||||||
loadNote({ newNote: true });
|
loadNote({ newNote: true });
|
||||||
if (tabBarRef.current?.page() === 1) {
|
if (fluidTabsRef.current?.page() === 1) {
|
||||||
state.current.currentlyEditing = false;
|
state.current.currentlyEditing = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
66
apps/mobile/app/screens/home/filter-bar.tsx
Normal file
66
apps/mobile/app/screens/home/filter-bar.tsx
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
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 React from "react";
|
||||||
|
import { View } from "react-native";
|
||||||
|
import { Button } from "../../components/ui/button";
|
||||||
|
import { SIZE } from "../../utils/size";
|
||||||
|
import { DefaultAppStyles } from "../../utils/styles";
|
||||||
|
|
||||||
|
export const FilterBar = () => {
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
|
flexDirection: "row",
|
||||||
|
alignItems: "center",
|
||||||
|
gap: 10,
|
||||||
|
marginTop: DefaultAppStyles.GAP,
|
||||||
|
width: "93%",
|
||||||
|
alignSelf: "center"
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{[
|
||||||
|
{
|
||||||
|
name: "All"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Favorites"
|
||||||
|
}
|
||||||
|
].map((item) => (
|
||||||
|
<Button
|
||||||
|
key={item.name}
|
||||||
|
title={item.name}
|
||||||
|
type="secondary"
|
||||||
|
style={{
|
||||||
|
height: 25
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
<Button
|
||||||
|
key="add"
|
||||||
|
icon="plus"
|
||||||
|
type="secondary"
|
||||||
|
iconSize={SIZE.md}
|
||||||
|
style={{
|
||||||
|
height: 25
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { strings } from "@notesnook/intl";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { FloatingButton } from "../../components/container/floating-button";
|
import { FloatingButton } from "../../components/container/floating-button";
|
||||||
import DelayLayout from "../../components/delay-layout";
|
import DelayLayout from "../../components/delay-layout";
|
||||||
@@ -29,7 +30,7 @@ import SettingsService from "../../services/settings";
|
|||||||
import useNavigationStore from "../../stores/use-navigation-store";
|
import useNavigationStore from "../../stores/use-navigation-store";
|
||||||
import { useNotes } from "../../stores/use-notes-store";
|
import { useNotes } from "../../stores/use-notes-store";
|
||||||
import { openEditor } from "../notes/common";
|
import { openEditor } from "../notes/common";
|
||||||
import { strings } from "@notesnook/intl";
|
import { FilterBar } from "./filter-bar";
|
||||||
|
|
||||||
export const Home = ({ navigation, route }: NavigationProps<"Notes">) => {
|
export const Home = ({ navigation, route }: NavigationProps<"Notes">) => {
|
||||||
const [notes, loading] = useNotes();
|
const [notes, loading] = useNotes();
|
||||||
@@ -66,6 +67,9 @@ export const Home = ({ navigation, route }: NavigationProps<"Notes">) => {
|
|||||||
id={route.name}
|
id={route.name}
|
||||||
onPressDefaultRightButton={openEditor}
|
onPressDefaultRightButton={openEditor}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<FilterBar />
|
||||||
|
|
||||||
<DelayLayout wait={loading}>
|
<DelayLayout wait={loading}>
|
||||||
<List
|
<List
|
||||||
data={notes}
|
data={notes}
|
||||||
|
|||||||
@@ -17,15 +17,17 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
import { resolveItems } from "@notesnook/common";
|
import { resolveItems } from "@notesnook/common";
|
||||||
import { VirtualizedGrouping } from "@notesnook/core";
|
import { Note, Notebook, VirtualizedGrouping } from "@notesnook/core";
|
||||||
import { Note, Notebook } from "@notesnook/core";
|
import { strings } from "@notesnook/intl";
|
||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import { View } from "react-native";
|
import { View } from "react-native";
|
||||||
import { db } from "../../common/database";
|
import { db } from "../../common/database";
|
||||||
|
import { FloatingButton } from "../../components/container/floating-button";
|
||||||
import DelayLayout from "../../components/delay-layout";
|
import DelayLayout from "../../components/delay-layout";
|
||||||
import { Header } from "../../components/header";
|
import { Header } from "../../components/header";
|
||||||
import List from "../../components/list";
|
import List from "../../components/list";
|
||||||
import { NotebookHeader } from "../../components/list-items/headers/notebook-header";
|
import { NotebookHeader } from "../../components/list-items/headers/notebook-header";
|
||||||
|
import { Properties } from "../../components/properties";
|
||||||
import SelectionHeader from "../../components/selection-header";
|
import SelectionHeader from "../../components/selection-header";
|
||||||
import { AddNotebookSheet } from "../../components/sheets/add-notebook";
|
import { AddNotebookSheet } from "../../components/sheets/add-notebook";
|
||||||
import { IconButton } from "../../components/ui/icon-button";
|
import { IconButton } from "../../components/ui/icon-button";
|
||||||
@@ -40,8 +42,8 @@ import useNavigationStore, {
|
|||||||
import { eUpdateNotebookRoute } from "../../utils/events";
|
import { eUpdateNotebookRoute } from "../../utils/events";
|
||||||
import { findRootNotebookId } from "../../utils/notebooks";
|
import { findRootNotebookId } from "../../utils/notebooks";
|
||||||
import { SIZE } from "../../utils/size";
|
import { SIZE } from "../../utils/size";
|
||||||
|
import { DefaultAppStyles } from "../../utils/styles";
|
||||||
import { openEditor, setOnFirstSave } from "../notes/common";
|
import { openEditor, setOnFirstSave } from "../notes/common";
|
||||||
import { strings } from "@notesnook/intl";
|
|
||||||
|
|
||||||
const NotebookScreen = ({ route, navigation }: NavigationProps<"Notebook">) => {
|
const NotebookScreen = ({ route, navigation }: NavigationProps<"Notebook">) => {
|
||||||
const [notes, setNotes] = useState<VirtualizedGrouping<Note>>();
|
const [notes, setNotes] = useState<VirtualizedGrouping<Note>>();
|
||||||
@@ -125,6 +127,8 @@ const NotebookScreen = ({ route, navigation }: NavigationProps<"Notebook">) => {
|
|||||||
setNotes(notes);
|
setNotes(notes);
|
||||||
await notes.item(0, resolveItems);
|
await notes.item(0, resolveItems);
|
||||||
syncWithNavigation();
|
syncWithNavigation();
|
||||||
|
} else {
|
||||||
|
Navigation.goBack();
|
||||||
}
|
}
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -160,13 +164,18 @@ const NotebookScreen = ({ route, navigation }: NavigationProps<"Notebook">) => {
|
|||||||
renderedInRoute={route.name}
|
renderedInRoute={route.name}
|
||||||
title={params.current.item?.title}
|
title={params.current.item?.title}
|
||||||
canGoBack={params?.current?.canGoBack}
|
canGoBack={params?.current?.canGoBack}
|
||||||
|
rightButton={{
|
||||||
|
name: "dots-vertical",
|
||||||
|
onPress: () => {
|
||||||
|
Properties.present(params.current.item);
|
||||||
|
}
|
||||||
|
}}
|
||||||
hasSearch={true}
|
hasSearch={true}
|
||||||
onSearch={() => {
|
onSearch={() => {
|
||||||
const selector = db.relations.from(
|
const selector = db.relations.from(
|
||||||
params.current.item,
|
params.current.item,
|
||||||
"note"
|
"note"
|
||||||
).selector;
|
).selector;
|
||||||
|
|
||||||
Navigation.push("Search", {
|
Navigation.push("Search", {
|
||||||
placeholder: strings.searchInRoute(params.current.item?.title),
|
placeholder: strings.searchInRoute(params.current.item?.title),
|
||||||
type: "note",
|
type: "note",
|
||||||
@@ -175,19 +184,18 @@ const NotebookScreen = ({ route, navigation }: NavigationProps<"Notebook">) => {
|
|||||||
items: selector
|
items: selector
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
titleHiddenOnRender
|
|
||||||
id={params.current.item?.id}
|
id={params.current.item?.id}
|
||||||
onPressDefaultRightButton={openEditor}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{breadcrumbs && breadcrumbs.length > 0 ? (
|
{breadcrumbs && breadcrumbs.length > 0 ? (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
paddingHorizontal: 12,
|
paddingHorizontal: DefaultAppStyles.GAP,
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
flexWrap: "wrap"
|
flexWrap: "wrap",
|
||||||
|
marginTop: DefaultAppStyles.GAP_VERTICAL
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<IconButton
|
<IconButton
|
||||||
@@ -260,6 +268,7 @@ const NotebookScreen = ({ route, navigation }: NavigationProps<"Notebook">) => {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</DelayLayout>
|
</DelayLayout>
|
||||||
|
<FloatingButton onPress={openEditor} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import { useRelationStore } from "../../stores/use-relation-store";
|
|||||||
import { useTagStore } from "../../stores/use-tag-store";
|
import { useTagStore } from "../../stores/use-tag-store";
|
||||||
import { eOnLoadNote, eOnNotebookUpdated } from "../../utils/events";
|
import { eOnLoadNote, eOnNotebookUpdated } from "../../utils/events";
|
||||||
import { openLinkInBrowser } from "../../utils/functions";
|
import { openLinkInBrowser } from "../../utils/functions";
|
||||||
import { tabBarRef } from "../../utils/global-refs";
|
import { fluidTabsRef } from "../../utils/global-refs";
|
||||||
import { editorState } from "../editor/tiptap/utils";
|
import { editorState } from "../editor/tiptap/utils";
|
||||||
|
|
||||||
export const PLACEHOLDER_DATA = {
|
export const PLACEHOLDER_DATA = {
|
||||||
@@ -58,7 +58,7 @@ export function openEditor() {
|
|||||||
eSendEvent(eOnLoadNote, { newNote: true });
|
eSendEvent(eOnLoadNote, { newNote: true });
|
||||||
editorState().currentlyEditing = true;
|
editorState().currentlyEditing = true;
|
||||||
editorState().movedAway = false;
|
editorState().movedAway = false;
|
||||||
tabBarRef.current?.goToPage(1);
|
fluidTabsRef.current?.goToPage(1);
|
||||||
} else {
|
} else {
|
||||||
eSendEvent(eOnLoadNote, { newNote: true });
|
eSendEvent(eOnLoadNote, { newNote: true });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,18 +17,18 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { strings } from "@notesnook/intl";
|
||||||
import { useThemeColors } from "@notesnook/theme";
|
import { useThemeColors } from "@notesnook/theme";
|
||||||
import React, { useRef } from "react";
|
import React, { useRef } from "react";
|
||||||
import { Platform, View } from "react-native";
|
import { Platform, View } from "react-native";
|
||||||
import { TextInput } from "react-native-gesture-handler";
|
import { TextInput } from "react-native-gesture-handler";
|
||||||
import { IconButton } from "../../components/ui/icon-button";
|
import { IconButton } from "../../components/ui/icon-button";
|
||||||
import Navigation from "../../services/navigation";
|
|
||||||
import { SIZE } from "../../utils/size";
|
|
||||||
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
|
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
|
||||||
import { DDS } from "../../services/device-detection";
|
import Navigation from "../../services/navigation";
|
||||||
import { useSelectionStore } from "../../stores/use-selection-store";
|
|
||||||
import useNavigationStore from "../../stores/use-navigation-store";
|
import useNavigationStore from "../../stores/use-navigation-store";
|
||||||
import { strings } from "@notesnook/intl";
|
import { useSelectionStore } from "../../stores/use-selection-store";
|
||||||
|
import { SIZE } from "../../utils/size";
|
||||||
|
import { DefaultAppStyles } from "../../utils/styles";
|
||||||
export const SearchBar = ({
|
export const SearchBar = ({
|
||||||
onChangeText,
|
onChangeText,
|
||||||
loading
|
loading
|
||||||
@@ -50,13 +50,21 @@ export const SearchBar = ({
|
|||||||
return selectionMode && isFocused ? null : (
|
return selectionMode && isFocused ? null : (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
height: Platform.OS === "android" ? 50 + insets.top : 50,
|
width: "100%",
|
||||||
paddingTop: Platform.OS === "ios" ? 0 : insets.top,
|
paddingHorizontal: DefaultAppStyles.GAP,
|
||||||
|
paddingTop: Platform.OS === "ios" ? 0 : insets.top + 5
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View
|
||||||
|
style={{
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
flexShrink: 1,
|
|
||||||
width: "100%",
|
width: "100%",
|
||||||
paddingHorizontal: 12
|
paddingHorizontal: DefaultAppStyles.GAP_SMALL,
|
||||||
|
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL,
|
||||||
|
borderRadius: 10,
|
||||||
|
borderColor: colors.primary.border,
|
||||||
|
borderWidth: 1
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<IconButton
|
<IconButton
|
||||||
@@ -69,22 +77,17 @@ export const SearchBar = ({
|
|||||||
}}
|
}}
|
||||||
color={colors.primary.paragraph}
|
color={colors.primary.paragraph}
|
||||||
type="plain"
|
type="plain"
|
||||||
style={{
|
|
||||||
paddingLeft: 0,
|
|
||||||
marginLeft: -5,
|
|
||||||
marginRight: DDS.isLargeTablet() ? 10 : 7
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextInput
|
<TextInput
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
testID="search-input"
|
testID="search-input"
|
||||||
style={{
|
style={{
|
||||||
fontSize: SIZE.md + 1,
|
fontSize: SIZE.sm,
|
||||||
fontFamily: "OpenSans-Regular",
|
fontFamily: "OpenSans-Regular",
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
height: "100%",
|
color: colors.primary.paragraph,
|
||||||
color: colors.primary.paragraph
|
height: 40
|
||||||
}}
|
}}
|
||||||
autoFocus
|
autoFocus
|
||||||
onChangeText={_onChangeText}
|
onChangeText={_onChangeText}
|
||||||
@@ -97,5 +100,6 @@ export const SearchBar = ({
|
|||||||
placeholderTextColor={colors.primary.placeholder}
|
placeholderTextColor={colors.primary.placeholder}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
</View>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { NativeStackScreenProps } from "@react-navigation/native-stack";
|
import { NativeStackScreenProps } from "@react-navigation/native-stack";
|
||||||
import React, { useEffect } from "react";
|
import React from "react";
|
||||||
import { View } from "react-native";
|
import { View } from "react-native";
|
||||||
import { KeyboardAwareFlatList } from "react-native-keyboard-aware-scroll-view";
|
import { KeyboardAwareFlatList } from "react-native-keyboard-aware-scroll-view";
|
||||||
import Animated, { FadeInDown } from "react-native-reanimated";
|
import Animated, { FadeInDown } from "react-native-reanimated";
|
||||||
@@ -26,7 +26,6 @@ import DelayLayout from "../../components/delay-layout";
|
|||||||
import { Header } from "../../components/header";
|
import { Header } from "../../components/header";
|
||||||
import { useNavigationFocus } from "../../hooks/use-navigation-focus";
|
import { useNavigationFocus } from "../../hooks/use-navigation-focus";
|
||||||
import useNavigationStore from "../../stores/use-navigation-store";
|
import useNavigationStore from "../../stores/use-navigation-store";
|
||||||
import { tabBarRef } from "../../utils/global-refs";
|
|
||||||
import { components } from "./components";
|
import { components } from "./components";
|
||||||
import { SectionItem } from "./section-item";
|
import { SectionItem } from "./section-item";
|
||||||
import { RouteParams, SettingSection } from "./types";
|
import { RouteParams, SettingSection } from "./types";
|
||||||
@@ -42,16 +41,10 @@ const Group = ({
|
|||||||
}: NativeStackScreenProps<RouteParams, "SettingsGroup">) => {
|
}: NativeStackScreenProps<RouteParams, "SettingsGroup">) => {
|
||||||
useNavigationFocus(navigation, {
|
useNavigationFocus(navigation, {
|
||||||
onFocus: () => {
|
onFocus: () => {
|
||||||
tabBarRef.current?.lock();
|
|
||||||
useNavigationStore.getState().setFocusedRouteId("Settings");
|
useNavigationStore.getState().setFocusedRouteId("Settings");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
useEffect(() => {
|
|
||||||
return () => {
|
|
||||||
tabBarRef.current?.unlock();
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
const renderItem = ({ item }: { item: SettingSection; index: number }) => (
|
const renderItem = ({ item }: { item: SettingSection; index: number }) => (
|
||||||
<SectionItem item={item} />
|
<SectionItem item={item} />
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -56,7 +56,8 @@ const Home = ({
|
|||||||
<Header
|
<Header
|
||||||
renderedInRoute="Settings"
|
renderedInRoute="Settings"
|
||||||
title={strings.routes.Settings()}
|
title={strings.routes.Settings()}
|
||||||
canGoBack={false}
|
canGoBack={true}
|
||||||
|
hasSearch={false}
|
||||||
id="Settings"
|
id="Settings"
|
||||||
/>
|
/>
|
||||||
<DelayLayout delay={300} type="settings">
|
<DelayLayout delay={300} type="settings">
|
||||||
|
|||||||
@@ -24,11 +24,18 @@ import { useThemeColors } from "@notesnook/theme";
|
|||||||
import Group from "./group";
|
import Group from "./group";
|
||||||
import Home from "./home";
|
import Home from "./home";
|
||||||
import { RouteParams } from "./types";
|
import { RouteParams } from "./types";
|
||||||
|
import { SafeAreaView } from "react-native-safe-area-context";
|
||||||
const SettingsStack = createNativeStackNavigator<RouteParams>();
|
const SettingsStack = createNativeStackNavigator<RouteParams>();
|
||||||
|
|
||||||
export const Settings = () => {
|
export const Settings = () => {
|
||||||
const { colors } = useThemeColors();
|
const { colors } = useThemeColors();
|
||||||
return (
|
return (
|
||||||
|
<SafeAreaView
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: colors.primary.background
|
||||||
|
}}
|
||||||
|
>
|
||||||
<SettingsStack.Navigator
|
<SettingsStack.Navigator
|
||||||
initialRouteName="SettingsHome"
|
initialRouteName="SettingsHome"
|
||||||
screenListeners={{
|
screenListeners={{
|
||||||
@@ -49,6 +56,7 @@ export const Settings = () => {
|
|||||||
<SettingsStack.Screen name="SettingsHome" component={Home} />
|
<SettingsStack.Screen name="SettingsHome" component={Home} />
|
||||||
<SettingsStack.Screen name="SettingsGroup" component={Group} />
|
<SettingsStack.Screen name="SettingsGroup" component={Group} />
|
||||||
</SettingsStack.Navigator>
|
</SettingsStack.Navigator>
|
||||||
|
</SafeAreaView>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import { useReminderStore } from "../stores/use-reminder-store";
|
|||||||
import { useTagStore } from "../stores/use-tag-store";
|
import { useTagStore } from "../stores/use-tag-store";
|
||||||
import { useTrashStore } from "../stores/use-trash-store";
|
import { useTrashStore } from "../stores/use-trash-store";
|
||||||
import { eOnRefreshSearch, eUpdateNotebookRoute } from "../utils/events";
|
import { eOnRefreshSearch, eUpdateNotebookRoute } from "../utils/events";
|
||||||
import { rootNavigatorRef, tabBarRef } from "../utils/global-refs";
|
import { appNavigatorRef, fluidTabsRef } from "../utils/global-refs";
|
||||||
import { eSendEvent } from "./event-manager";
|
import { eSendEvent } from "./event-manager";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -122,30 +122,36 @@ function queueRoutesForUpdate(...routesToUpdate: RouteName[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function navigate<T extends RouteName>(screen: T, params?: RouteParams[T]) {
|
function navigate<T extends RouteName>(screen: T, params?: RouteParams[T]) {
|
||||||
rootNavigatorRef.current?.navigate(screen as any, params);
|
console.log(`Navigation.navigate ${screen} route`);
|
||||||
|
appNavigatorRef.current?.navigate(screen as any, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
function goBack() {
|
function goBack() {
|
||||||
rootNavigatorRef.current?.goBack();
|
appNavigatorRef.current?.goBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
function push<T extends RouteName>(screen: T, params: RouteParams[T]) {
|
function push<T extends RouteName>(screen: T, params: RouteParams[T]) {
|
||||||
rootNavigatorRef.current?.dispatch(StackActions.push(screen as any, params));
|
console.log(`Navigation.push ${screen} route`);
|
||||||
|
appNavigatorRef.current?.dispatch(StackActions.push(screen as any, params));
|
||||||
}
|
}
|
||||||
|
|
||||||
function replace<T extends RouteName>(screen: T, params: RouteParams[T]) {
|
function replace<T extends RouteName>(screen: T, params: RouteParams[T]) {
|
||||||
rootNavigatorRef.current?.dispatch(StackActions.replace(screen, params));
|
console.log(`Navigation.replace ${screen} route`);
|
||||||
|
appNavigatorRef.current?.dispatch(
|
||||||
|
StackActions.replace(screen as string, params)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function popToTop() {
|
function popToTop() {
|
||||||
rootNavigatorRef.current?.dispatch(StackActions.popToTop());
|
console.log(`Navigation.popToTop`);
|
||||||
|
appNavigatorRef.current?.dispatch(StackActions.popToTop());
|
||||||
}
|
}
|
||||||
|
|
||||||
function openDrawer() {
|
function openDrawer() {
|
||||||
tabBarRef.current?.openDrawer();
|
fluidTabsRef.current?.openDrawer();
|
||||||
}
|
}
|
||||||
function closeDrawer() {
|
function closeDrawer() {
|
||||||
tabBarRef.current?.closeDrawer();
|
fluidTabsRef.current?.closeDrawer();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Navigation = {
|
const Navigation = {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ import { useReminderStore } from "../stores/use-reminder-store";
|
|||||||
import { useSettingStore } from "../stores/use-setting-store";
|
import { useSettingStore } from "../stores/use-setting-store";
|
||||||
import { useUserStore } from "../stores/use-user-store";
|
import { useUserStore } from "../stores/use-user-store";
|
||||||
import { eOnLoadNote } from "../utils/events";
|
import { eOnLoadNote } from "../utils/events";
|
||||||
import { tabBarRef } from "../utils/global-refs";
|
import { fluidTabsRef } from "../utils/global-refs";
|
||||||
import { convertNoteToText } from "../utils/note-to-text";
|
import { convertNoteToText } from "../utils/note-to-text";
|
||||||
import { NotesnookModule } from "../utils/notesnook-module";
|
import { NotesnookModule } from "../utils/notesnook-module";
|
||||||
import { sleep } from "../utils/time";
|
import { sleep } from "../utils/time";
|
||||||
@@ -440,7 +440,7 @@ async function loadNote(id: string, jump: boolean) {
|
|||||||
const note = await db.notes.note(id);
|
const note = await db.notes.note(id);
|
||||||
if (!note) return;
|
if (!note) return;
|
||||||
if (!DDS.isTab && jump) {
|
if (!DDS.isTab && jump) {
|
||||||
tabBarRef.current?.goToPage(1);
|
fluidTabsRef.current?.goToPage(1);
|
||||||
}
|
}
|
||||||
NotesnookModule.setAppState(
|
NotesnookModule.setAppState(
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
|
|||||||
165
apps/mobile/app/stores/create-notebook-tree-stores.ts
Normal file
165
apps/mobile/app/stores/create-notebook-tree-stores.ts
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
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 { Notebook } from "@notesnook/core";
|
||||||
|
import create from "zustand";
|
||||||
|
import { db } from "../common/database";
|
||||||
|
import { createItemSelectionStore } from "./item-selection-store";
|
||||||
|
|
||||||
|
export type TreeItem = {
|
||||||
|
parentId: string;
|
||||||
|
notebook: Notebook;
|
||||||
|
depth: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
function removeTreeItem(tree: TreeItem[], id: string) {
|
||||||
|
const children: TreeItem[] = [];
|
||||||
|
let newTree = tree.filter((item) => {
|
||||||
|
if (item.parentId === id) children.push(item);
|
||||||
|
return item.notebook.id !== id;
|
||||||
|
});
|
||||||
|
for (const child of children) {
|
||||||
|
newTree = removeTreeItem(newTree, child.notebook.id);
|
||||||
|
}
|
||||||
|
return newTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createNotebookTreeStores(
|
||||||
|
multiSelect: boolean,
|
||||||
|
selectionEnabled: boolean
|
||||||
|
) {
|
||||||
|
const useSideMenuNotebookTreeStore = create<{
|
||||||
|
tree: TreeItem[];
|
||||||
|
setTree: (tree: TreeItem[]) => void;
|
||||||
|
removeItem: (id: string) => void;
|
||||||
|
addNotebooks: (
|
||||||
|
parentId: string,
|
||||||
|
notebooks: Notebook[],
|
||||||
|
depth: number
|
||||||
|
) => void;
|
||||||
|
updateItem: (id: string, notebook: Notebook) => void;
|
||||||
|
fetchAndAdd: (parentId: string, depth: number) => Promise<void>;
|
||||||
|
removeChildren: (id: string) => void;
|
||||||
|
}>((set, get) => ({
|
||||||
|
tree: [],
|
||||||
|
setTree(tree) {
|
||||||
|
set({ tree });
|
||||||
|
},
|
||||||
|
updateItem: (id, notebook) => {
|
||||||
|
const newTree = [...get().tree];
|
||||||
|
const index = newTree.findIndex((item) => item.notebook.id === id);
|
||||||
|
newTree[index] = {
|
||||||
|
...newTree[index],
|
||||||
|
notebook
|
||||||
|
};
|
||||||
|
set({
|
||||||
|
tree: newTree
|
||||||
|
});
|
||||||
|
},
|
||||||
|
addNotebooks: (parentId: string, notebooks: Notebook[], depth: number) => {
|
||||||
|
const parentIndex = get().tree.findIndex(
|
||||||
|
(item) => item.notebook.id === parentId
|
||||||
|
);
|
||||||
|
|
||||||
|
let newTree = get().tree.slice();
|
||||||
|
for (const item of newTree) {
|
||||||
|
if (item.parentId === parentId) {
|
||||||
|
newTree = removeTreeItem(newTree, item.notebook.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newTree.splice(
|
||||||
|
parentIndex + 1,
|
||||||
|
0,
|
||||||
|
...notebooks.map((notebook) => {
|
||||||
|
return {
|
||||||
|
parentId,
|
||||||
|
notebook,
|
||||||
|
depth: depth
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
set({
|
||||||
|
tree: newTree
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
removeItem(id) {
|
||||||
|
set({
|
||||||
|
tree: removeTreeItem(get().tree, id).slice()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
fetchAndAdd: async (parentId: string, depth: number) => {
|
||||||
|
const selector = db.relations.from(
|
||||||
|
{
|
||||||
|
type: "notebook",
|
||||||
|
id: parentId
|
||||||
|
},
|
||||||
|
"notebook"
|
||||||
|
).selector;
|
||||||
|
const grouped = await selector.sorted(
|
||||||
|
db.settings.getGroupOptions("notebooks")
|
||||||
|
);
|
||||||
|
|
||||||
|
const notebooks: Notebook[] = [];
|
||||||
|
for (let index = 0; index < grouped.placeholders.length; index++) {
|
||||||
|
const notebook = (await grouped.item(index)).item;
|
||||||
|
if (notebook) notebooks.push(notebook);
|
||||||
|
}
|
||||||
|
get().addNotebooks(parentId, notebooks, depth);
|
||||||
|
},
|
||||||
|
removeChildren(id: string) {
|
||||||
|
let newTree = get().tree.slice();
|
||||||
|
for (const item of newTree) {
|
||||||
|
if (item.parentId === id) {
|
||||||
|
newTree = removeTreeItem(newTree, item.notebook.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set({
|
||||||
|
tree: newTree
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
const useSideMenuNotebookSelectionStore = createItemSelectionStore(
|
||||||
|
multiSelect,
|
||||||
|
selectionEnabled
|
||||||
|
);
|
||||||
|
|
||||||
|
const useSideMenuNotebookExpandedStore = create<{
|
||||||
|
expanded: {
|
||||||
|
[id: string]: boolean;
|
||||||
|
};
|
||||||
|
setExpanded: (id: string) => void;
|
||||||
|
}>((set, get) => ({
|
||||||
|
expanded: {},
|
||||||
|
setExpanded(id: string) {
|
||||||
|
set({
|
||||||
|
expanded: {
|
||||||
|
...get().expanded,
|
||||||
|
[id]: !get().expanded[id]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
return {
|
||||||
|
useSideMenuNotebookTreeStore,
|
||||||
|
useSideMenuNotebookSelectionStore,
|
||||||
|
useSideMenuNotebookExpandedStore
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -33,6 +33,7 @@ export interface SelectionStore extends State {
|
|||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
getSelectedItemIds: () => string[];
|
getSelectedItemIds: () => string[];
|
||||||
getDeselectedItemIds: () => string[];
|
getDeselectedItemIds: () => string[];
|
||||||
|
selectAll?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createItemSelectionStore(
|
export function createItemSelectionStore(
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import {
|
|||||||
TrashItem
|
TrashItem
|
||||||
} from "@notesnook/core";
|
} from "@notesnook/core";
|
||||||
import create, { State } from "zustand";
|
import create, { State } from "zustand";
|
||||||
|
import { ParamListBase } from "@react-navigation/core";
|
||||||
|
|
||||||
export type GenericRouteParam = undefined;
|
export type GenericRouteParam = undefined;
|
||||||
|
|
||||||
@@ -55,7 +56,7 @@ export type AuthParams = {
|
|||||||
canGoBack?: boolean;
|
canGoBack?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type RouteParams = {
|
export interface RouteParams extends ParamListBase {
|
||||||
Notes: GenericRouteParam;
|
Notes: GenericRouteParam;
|
||||||
Notebooks: {
|
Notebooks: {
|
||||||
canGoBack?: boolean;
|
canGoBack?: boolean;
|
||||||
@@ -80,7 +81,7 @@ export type RouteParams = {
|
|||||||
AppLock: AppLockRouteParams;
|
AppLock: AppLockRouteParams;
|
||||||
Reminders: GenericRouteParam;
|
Reminders: GenericRouteParam;
|
||||||
SettingsGroup: GenericRouteParam;
|
SettingsGroup: GenericRouteParam;
|
||||||
};
|
}
|
||||||
|
|
||||||
export type RouteName = keyof RouteParams;
|
export type RouteName = keyof RouteParams;
|
||||||
|
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ export interface SettingStore extends State {
|
|||||||
dimensions: DimensionsType;
|
dimensions: DimensionsType;
|
||||||
setSettings: (settings: Settings) => void;
|
setSettings: (settings: Settings) => void;
|
||||||
setFullscreen: (fullscreen: boolean) => void;
|
setFullscreen: (fullscreen: boolean) => void;
|
||||||
setDeviceMode: (mode: string) => void;
|
setDeviceMode: (mode: string | null) => void;
|
||||||
setDimensions: (dimensions: DimensionsType) => void;
|
setDimensions: (dimensions: DimensionsType) => void;
|
||||||
isAppLoading: boolean;
|
isAppLoading: boolean;
|
||||||
setAppLoading: (isAppLoading: boolean) => void;
|
setAppLoading: (isAppLoading: boolean) => void;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import { presentDialog } from "../components/dialog/functions";
|
|||||||
import { eSendEvent, ToastManager } from "../services/event-manager";
|
import { eSendEvent, ToastManager } from "../services/event-manager";
|
||||||
import Navigation from "../services/navigation";
|
import Navigation from "../services/navigation";
|
||||||
import { useMenuStore } from "../stores/use-menu-store";
|
import { useMenuStore } from "../stores/use-menu-store";
|
||||||
|
import { useNotebookStore } from "../stores/use-notebook-store";
|
||||||
import { useRelationStore } from "../stores/use-relation-store";
|
import { useRelationStore } from "../stores/use-relation-store";
|
||||||
import { useTagStore } from "../stores/use-tag-store";
|
import { useTagStore } from "../stores/use-tag-store";
|
||||||
import { eOnNotebookUpdated, eUpdateNoteInEditor } from "./events";
|
import { eOnNotebookUpdated, eUpdateNoteInEditor } from "./events";
|
||||||
@@ -72,8 +73,10 @@ async function deleteNotebook(id: string, deleteNotes: boolean) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
await db.notebooks.moveToTrash(id);
|
await db.notebooks.moveToTrash(id);
|
||||||
if (parentId) {
|
|
||||||
eSendEvent(eOnNotebookUpdated, parentId);
|
eSendEvent(eOnNotebookUpdated, parentId);
|
||||||
|
if (!parentId) {
|
||||||
|
useNotebookStore.getState().refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,7 +116,6 @@ export const deleteItems = async (
|
|||||||
if (!result.delete) return;
|
if (!result.delete) return;
|
||||||
for (const id of itemIds) {
|
for (const id of itemIds) {
|
||||||
await deleteNotebook(id, result.deleteNotes);
|
await deleteNotebook(id, result.deleteNotes);
|
||||||
eSendEvent(eOnNotebookUpdated, await getParentNotebookId(id));
|
|
||||||
}
|
}
|
||||||
} else if (type === "tag") {
|
} else if (type === "tag") {
|
||||||
presentDialog({
|
presentDialog({
|
||||||
|
|||||||
@@ -20,10 +20,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
import { createNavigationContainerRef } from "@react-navigation/native";
|
import { createNavigationContainerRef } from "@react-navigation/native";
|
||||||
import { createRef } from "react";
|
import { createRef } from "react";
|
||||||
import { TextInput, View } from "react-native";
|
import { TextInput, View } from "react-native";
|
||||||
import { TabsRef } from "../components/tabs";
|
import { TabsRef } from "../components/fluid-panels";
|
||||||
import { RouteParams } from "../stores/use-navigation-store";
|
import { RouteParams } from "../stores/use-navigation-store";
|
||||||
|
|
||||||
export const inputRef = createRef<TextInput>();
|
export const inputRef = createRef<TextInput>();
|
||||||
export const rootNavigatorRef = createNavigationContainerRef<RouteParams>();
|
export const rootNavigatorRef = createNavigationContainerRef<{
|
||||||
export const tabBarRef = createRef<TabsRef>();
|
FluidPanelsView: undefined;
|
||||||
|
AppLock: undefined;
|
||||||
|
Settings: undefined;
|
||||||
|
}>();
|
||||||
|
export const appNavigatorRef = createNavigationContainerRef<RouteParams>();
|
||||||
|
export const fluidTabsRef = createRef<TabsRef>();
|
||||||
export const editorRef = createRef<View>();
|
export const editorRef = createRef<View>();
|
||||||
|
|||||||
@@ -17,51 +17,69 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Item, ItemType } from "@notesnook/core";
|
||||||
import { Monographs } from "../screens/notes/monographs";
|
import { Monographs } from "../screens/notes/monographs";
|
||||||
export const MenuItemsList = [
|
|
||||||
|
export type SideMenuItem = {
|
||||||
|
dataType?: ItemType | "monograph";
|
||||||
|
data?: Item;
|
||||||
|
title: string;
|
||||||
|
id: string;
|
||||||
|
icon: string;
|
||||||
|
onPress?: (item: SideMenuItem) => void;
|
||||||
|
onLongPress?: (item: SideMenuItem) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const MenuItemsList: SideMenuItem[] = [
|
||||||
{
|
{
|
||||||
id: "notes",
|
dataType: "note",
|
||||||
name: "Notes",
|
id: "Notes",
|
||||||
icon: "home-variant-outline",
|
title: "Notes",
|
||||||
close: true
|
icon: "note-outline"
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// dataType: "notebook",
|
||||||
|
// id: "Notebooks",
|
||||||
|
// title: "Notebooks",
|
||||||
|
// icon: "book-outline"
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
dataType: "note",
|
||||||
|
id: "Favorites",
|
||||||
|
title: "Favorites",
|
||||||
|
icon: "star-outline"
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// dataType: "tag",
|
||||||
|
// id: "Tags",
|
||||||
|
// title: "Tags",
|
||||||
|
// icon: "pound"
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
dataType: "reminder",
|
||||||
|
id: "Reminders",
|
||||||
|
title: "Reminders",
|
||||||
|
icon: "bell"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "notebooks",
|
dataType: "monograph",
|
||||||
name: "Notebooks",
|
id: "Monographs",
|
||||||
icon: "book-outline",
|
title: "Monographs",
|
||||||
close: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "favorites",
|
|
||||||
name: "Favorites",
|
|
||||||
icon: "star-outline",
|
|
||||||
close: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "tags",
|
|
||||||
name: "Tags",
|
|
||||||
icon: "pound",
|
|
||||||
close: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "reminders",
|
|
||||||
name: "Reminders",
|
|
||||||
icon: "bell",
|
|
||||||
close: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: "monographs",
|
|
||||||
name: "Monographs",
|
|
||||||
icon: "text-box-multiple-outline",
|
icon: "text-box-multiple-outline",
|
||||||
close: true,
|
onPress: () => {
|
||||||
func: () => {
|
|
||||||
Monographs.navigate();
|
Monographs.navigate();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "trash",
|
dataType: "note",
|
||||||
name: "Trash",
|
id: "Archive",
|
||||||
icon: "delete-outline",
|
title: "Archive",
|
||||||
close: true
|
icon: "archive"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dataType: "note",
|
||||||
|
id: "Trash",
|
||||||
|
title: "Trash",
|
||||||
|
icon: "delete-outline"
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
*/
|
*/
|
||||||
import { db } from "../common/database";
|
import { db } from "../common/database";
|
||||||
import { eSendEvent } from "../services/event-manager";
|
import { eSendEvent } from "../services/event-manager";
|
||||||
|
import { useNotebookStore } from "../stores/use-notebook-store";
|
||||||
import { eOnNotebookUpdated } from "./events";
|
import { eOnNotebookUpdated } from "./events";
|
||||||
|
|
||||||
export async function findRootNotebookId(id: string) {
|
export async function findRootNotebookId(id: string) {
|
||||||
@@ -51,9 +52,14 @@ export async function getParentNotebookId(id: string) {
|
|||||||
return relation?.[0]?.fromId;
|
return relation?.[0]?.fromId;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateNotebook(id?: string) {
|
export async function updateNotebook(id?: string, updateParent?: boolean) {
|
||||||
eSendEvent(eOnNotebookUpdated, id);
|
eSendEvent(eOnNotebookUpdated, id);
|
||||||
if (id) {
|
if (updateParent && id) {
|
||||||
eSendEvent(eOnNotebookUpdated, await getParentNotebookId(id));
|
const parent = await getParentNotebookId(id);
|
||||||
|
if (parent) {
|
||||||
|
eSendEvent(eOnNotebookUpdated, parent);
|
||||||
|
} else {
|
||||||
|
useNotebookStore.getState().refresh();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,9 +81,12 @@ export const normalize = (size) => {
|
|||||||
return correction(size, 1);
|
return correction(size, 1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
export const SIZE = {
|
|
||||||
xxs: normalize(11) * scale.fontScale,
|
function getSize() {
|
||||||
xs: normalize(12.5) * scale.fontScale,
|
return {
|
||||||
|
xxxs: normalize(11) * scale.fontScale,
|
||||||
|
xxs: normalize(12.5) * scale.fontScale,
|
||||||
|
xs: normalize(14) * scale.fontScale,
|
||||||
sm: normalize(15) * scale.fontScale,
|
sm: normalize(15) * scale.fontScale,
|
||||||
md: normalize(16.5) * scale.fontScale,
|
md: normalize(16.5) * scale.fontScale,
|
||||||
lg: normalize(22) * scale.fontScale,
|
lg: normalize(22) * scale.fontScale,
|
||||||
@@ -91,21 +94,20 @@ export const SIZE = {
|
|||||||
xxl: normalize(28) * scale.fontScale,
|
xxl: normalize(28) * scale.fontScale,
|
||||||
xxxl: normalize(32) * scale.fontScale
|
xxxl: normalize(32) * scale.fontScale
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SIZE = getSize();
|
||||||
|
|
||||||
export function updateSize() {
|
export function updateSize() {
|
||||||
SIZE.xxs = normalize(11) * scale.fontScale;
|
const newSize = getSize();
|
||||||
SIZE.xs = normalize(12.5) * scale.fontScale;
|
for (const key in SIZE) {
|
||||||
SIZE.sm = normalize(15) * scale.fontScale;
|
SIZE[key] = newSize[key];
|
||||||
SIZE.md = normalize(16.5) * scale.fontScale;
|
}
|
||||||
SIZE.lg = normalize(22) * scale.fontScale;
|
|
||||||
SIZE.xl = normalize(24) * scale.fontScale;
|
|
||||||
SIZE.xxl = normalize(28) * scale.fontScale;
|
|
||||||
SIZE.xxxl = normalize(32) * scale.fontScale;
|
|
||||||
ph = normalize(10) * scale.fontScale;
|
ph = normalize(10) * scale.fontScale;
|
||||||
pv = normalize(10) * scale.fontScale;
|
pv = normalize(10) * scale.fontScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const br = 5; // border radius
|
export const br = 8; // border radius
|
||||||
export var ph = normalize(10); // padding horizontal
|
export var ph = normalize(10); // padding horizontal
|
||||||
export var pv = normalize(10); // padding vertical
|
export var pv = normalize(10); // padding vertical
|
||||||
export const opacity = 0.5; // active opacity
|
export const opacity = 0.5; // active opacity
|
||||||
|
|||||||
@@ -16,21 +16,9 @@ GNU General Public License for more details.
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
export const DefaultAppStyles = {
|
||||||
import React from "react";
|
GAP: 16,
|
||||||
import DialogProvider from "../components/dialog-provider";
|
GAP_SMALL: 8,
|
||||||
import { Toast } from "../components/toast";
|
GAP_VERTICAL: 6,
|
||||||
import { TabHolder } from "./tabs-holder";
|
GAP_VERTICAL_SMALL: 4
|
||||||
import { ScopedThemeProvider } from "@notesnook/theme";
|
|
||||||
const _ApplicationHolder = () => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<TabHolder />
|
|
||||||
<ScopedThemeProvider value="dialog">
|
|
||||||
<Toast />
|
|
||||||
</ScopedThemeProvider>
|
|
||||||
<DialogProvider />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
export const ApplicationHolder = React.memo(_ApplicationHolder, () => true);
|
|
||||||
Binary file not shown.
@@ -24,7 +24,7 @@ import {
|
|||||||
} from "@notesnook/intl/dist/locales/$pseudo-LOCALE.json";
|
} from "@notesnook/intl/dist/locales/$pseudo-LOCALE.json";
|
||||||
|
|
||||||
i18n.load({
|
i18n.load({
|
||||||
en: __DEV__ ? $pseudo : $en
|
en: !__DEV__ ? $pseudo : $en
|
||||||
});
|
});
|
||||||
setI18nGlobal(i18n);
|
setI18nGlobal(i18n);
|
||||||
i18n.activate("en");
|
i18n.activate("en");
|
||||||
|
|||||||
@@ -73,7 +73,9 @@
|
|||||||
"react-native-begin-background-task": "github:blockfirm/react-native-begin-background-task",
|
"react-native-begin-background-task": "github:blockfirm/react-native-begin-background-task",
|
||||||
"react-native-privacy-snapshot": "github:standardnotes/react-native-privacy-snapshot",
|
"react-native-privacy-snapshot": "github:standardnotes/react-native-privacy-snapshot",
|
||||||
"@ammarahmed/react-native-fingerprint-scanner": "^5.0.0",
|
"@ammarahmed/react-native-fingerprint-scanner": "^5.0.0",
|
||||||
"@ammarahmed/react-native-share-extension": "^2.9.0"
|
"@ammarahmed/react-native-share-extension": "^2.9.0",
|
||||||
|
"react-native-pager-view": "^6.5.1",
|
||||||
|
"react-native-tab-view": "^4.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"detox": "^20.27.6",
|
"detox": "^20.27.6",
|
||||||
@@ -88,6 +90,7 @@
|
|||||||
"@tsconfig/react-native": "^3.0.2",
|
"@tsconfig/react-native": "^3.0.2",
|
||||||
"@types/html-to-text": "^8.0.1",
|
"@types/html-to-text": "^8.0.1",
|
||||||
"@types/metro-config": "^0.76.3",
|
"@types/metro-config": "^0.76.3",
|
||||||
|
"@types/react": "^18.2.39",
|
||||||
"@types/react-native": "^0.69.1",
|
"@types/react-native": "^0.69.1",
|
||||||
"@types/react-native-vector-icons": "^6.4.10",
|
"@types/react-native-vector-icons": "^6.4.10",
|
||||||
"@types/react-test-renderer": "^18.0.0",
|
"@types/react-test-renderer": "^18.0.0",
|
||||||
|
|||||||
190
apps/mobile/package-lock.json
generated
190
apps/mobile/package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "@notesnook/mobile",
|
"name": "@notesnook/mobile",
|
||||||
"version": "3.0.31",
|
"version": "3.0.32",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@notesnook/mobile",
|
"name": "@notesnook/mobile",
|
||||||
"version": "3.0.31",
|
"version": "3.0.32",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
@@ -14,7 +14,6 @@
|
|||||||
"app/"
|
"app/"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ammarahmed/react-native-share-extension": "^2.9.0",
|
|
||||||
"@notesnook/common": "file:../../packages/common",
|
"@notesnook/common": "file:../../packages/common",
|
||||||
"@notesnook/core": "file:../../packages/core",
|
"@notesnook/core": "file:../../packages/core",
|
||||||
"@notesnook/crypto": "file:../../packages/crypto",
|
"@notesnook/crypto": "file:../../packages/crypto",
|
||||||
@@ -3728,6 +3727,7 @@
|
|||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@notesnook-importer/core": "^2.1.1",
|
||||||
"@notesnook/common": "file:../common",
|
"@notesnook/common": "file:../common",
|
||||||
"@notesnook/intl": "file:../intl",
|
"@notesnook/intl": "file:../intl",
|
||||||
"@notesnook/theme": "file:../theme",
|
"@notesnook/theme": "file:../theme",
|
||||||
@@ -7743,7 +7743,7 @@
|
|||||||
},
|
},
|
||||||
"../../packages/editor-mobile/node_modules/@types/prop-types": {
|
"../../packages/editor-mobile/node_modules/@types/prop-types": {
|
||||||
"version": "15.7.11",
|
"version": "15.7.11",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"../../packages/editor-mobile/node_modules/@types/q": {
|
"../../packages/editor-mobile/node_modules/@types/q": {
|
||||||
@@ -7763,7 +7763,7 @@
|
|||||||
},
|
},
|
||||||
"../../packages/editor-mobile/node_modules/@types/react": {
|
"../../packages/editor-mobile/node_modules/@types/react": {
|
||||||
"version": "18.2.39",
|
"version": "18.2.39",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/prop-types": "*",
|
"@types/prop-types": "*",
|
||||||
@@ -7794,7 +7794,7 @@
|
|||||||
},
|
},
|
||||||
"../../packages/editor-mobile/node_modules/@types/scheduler": {
|
"../../packages/editor-mobile/node_modules/@types/scheduler": {
|
||||||
"version": "0.16.8",
|
"version": "0.16.8",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"../../packages/editor-mobile/node_modules/@types/semver": {
|
"../../packages/editor-mobile/node_modules/@types/semver": {
|
||||||
@@ -12619,7 +12619,7 @@
|
|||||||
},
|
},
|
||||||
"../../packages/editor-mobile/node_modules/immer": {
|
"../../packages/editor-mobile/node_modules/immer": {
|
||||||
"version": "9.0.21",
|
"version": "9.0.21",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@@ -23091,6 +23091,7 @@
|
|||||||
},
|
},
|
||||||
"../../packages/editor/node_modules/js-tokens": {
|
"../../packages/editor/node_modules/js-tokens": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"../../packages/editor/node_modules/jsesc": {
|
"../../packages/editor/node_modules/jsesc": {
|
||||||
@@ -23141,6 +23142,7 @@
|
|||||||
},
|
},
|
||||||
"../../packages/editor/node_modules/loose-envify": {
|
"../../packages/editor/node_modules/loose-envify": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"js-tokens": "^3.0.0 || ^4.0.0"
|
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||||
@@ -23652,6 +23654,7 @@
|
|||||||
},
|
},
|
||||||
"../../packages/editor/node_modules/react": {
|
"../../packages/editor/node_modules/react": {
|
||||||
"version": "18.3.1",
|
"version": "18.3.1",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.1.0"
|
"loose-envify": "^1.1.0"
|
||||||
@@ -23670,6 +23673,7 @@
|
|||||||
},
|
},
|
||||||
"../../packages/editor/node_modules/react-dom": {
|
"../../packages/editor/node_modules/react-dom": {
|
||||||
"version": "18.3.1",
|
"version": "18.3.1",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.1.0",
|
"loose-envify": "^1.1.0",
|
||||||
@@ -23808,6 +23812,7 @@
|
|||||||
},
|
},
|
||||||
"../../packages/editor/node_modules/scheduler": {
|
"../../packages/editor/node_modules/scheduler": {
|
||||||
"version": "0.23.2",
|
"version": "0.23.2",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.1.0"
|
"loose-envify": "^1.1.0"
|
||||||
@@ -28315,6 +28320,7 @@
|
|||||||
"@ammarahmed/react-native-background-fetch": "^4.2.2",
|
"@ammarahmed/react-native-background-fetch": "^4.2.2",
|
||||||
"@ammarahmed/react-native-eventsource": "1.1.0",
|
"@ammarahmed/react-native-eventsource": "1.1.0",
|
||||||
"@ammarahmed/react-native-fingerprint-scanner": "^5.0.0",
|
"@ammarahmed/react-native-fingerprint-scanner": "^5.0.0",
|
||||||
|
"@ammarahmed/react-native-share-extension": "^2.9.0",
|
||||||
"@ammarahmed/react-native-sodium": "^1.6.1",
|
"@ammarahmed/react-native-sodium": "^1.6.1",
|
||||||
"@bam.tech/react-native-image-resizer": "3.0.5",
|
"@bam.tech/react-native-image-resizer": "3.0.5",
|
||||||
"@callstack/repack": "^4.1.1",
|
"@callstack/repack": "^4.1.1",
|
||||||
@@ -28357,6 +28363,7 @@
|
|||||||
"react-native-navigation-bar-color": "2.0.2",
|
"react-native-navigation-bar-color": "2.0.2",
|
||||||
"react-native-notification-sounds": "0.5.5",
|
"react-native-notification-sounds": "0.5.5",
|
||||||
"react-native-orientation": "github:yamill/react-native-orientation",
|
"react-native-orientation": "github:yamill/react-native-orientation",
|
||||||
|
"react-native-pager-view": "^6.5.1",
|
||||||
"react-native-pdf": "6.6.2",
|
"react-native-pdf": "6.6.2",
|
||||||
"react-native-privacy-snapshot": "github:standardnotes/react-native-privacy-snapshot",
|
"react-native-privacy-snapshot": "github:standardnotes/react-native-privacy-snapshot",
|
||||||
"react-native-quick-sqlite": "^8.0.6",
|
"react-native-quick-sqlite": "^8.0.6",
|
||||||
@@ -28369,6 +28376,7 @@
|
|||||||
"react-native-share": "^12.0.3",
|
"react-native-share": "^12.0.3",
|
||||||
"react-native-svg": "^12.3.0",
|
"react-native-svg": "^12.3.0",
|
||||||
"react-native-swiper-flatlist": "3.2.2",
|
"react-native-swiper-flatlist": "3.2.2",
|
||||||
|
"react-native-tab-view": "^4.0.2",
|
||||||
"react-native-theme-switch-animation": "^0.6.0",
|
"react-native-theme-switch-animation": "^0.6.0",
|
||||||
"react-native-tooltips": "^1.0.3",
|
"react-native-tooltips": "^1.0.3",
|
||||||
"react-native-url-polyfill": "^2.0.0",
|
"react-native-url-polyfill": "^2.0.0",
|
||||||
@@ -28390,6 +28398,7 @@
|
|||||||
"@types/html-to-text": "^8.0.1",
|
"@types/html-to-text": "^8.0.1",
|
||||||
"@types/jest": "^29.5.14",
|
"@types/jest": "^29.5.14",
|
||||||
"@types/metro-config": "^0.76.3",
|
"@types/metro-config": "^0.76.3",
|
||||||
|
"@types/react": "^18.2.39",
|
||||||
"@types/react-native": "^0.69.1",
|
"@types/react-native": "^0.69.1",
|
||||||
"@types/react-native-vector-icons": "^6.4.10",
|
"@types/react-native-vector-icons": "^6.4.10",
|
||||||
"@types/react-test-renderer": "^18.0.0",
|
"@types/react-test-renderer": "^18.0.0",
|
||||||
@@ -28590,6 +28599,7 @@
|
|||||||
},
|
},
|
||||||
"node_modules/@babel/helper-builder-binary-assignment-operator-visitor": {
|
"node_modules/@babel/helper-builder-binary-assignment-operator-visitor": {
|
||||||
"version": "7.22.5",
|
"version": "7.22.5",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/types": "^7.22.5"
|
"@babel/types": "^7.22.5"
|
||||||
@@ -28709,6 +28719,7 @@
|
|||||||
},
|
},
|
||||||
"node_modules/@babel/helper-hoist-variables": {
|
"node_modules/@babel/helper-hoist-variables": {
|
||||||
"version": "7.22.5",
|
"version": "7.22.5",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/types": "^7.22.5"
|
"@babel/types": "^7.22.5"
|
||||||
@@ -28968,6 +28979,7 @@
|
|||||||
"version": "7.25.9",
|
"version": "7.25.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz",
|
||||||
"integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==",
|
"integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.25.9"
|
"@babel/helper-plugin-utils": "^7.25.9"
|
||||||
},
|
},
|
||||||
@@ -28982,6 +28994,7 @@
|
|||||||
"version": "7.24.7",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz",
|
||||||
"integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==",
|
"integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.22.5",
|
"@babel/helper-plugin-utils": "^7.22.5",
|
||||||
"@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
|
"@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
|
||||||
@@ -29130,6 +29143,7 @@
|
|||||||
"version": "7.21.0-placeholder-for-preset-env.2",
|
"version": "7.21.0-placeholder-for-preset-env.2",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz",
|
||||||
"integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==",
|
"integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==",
|
||||||
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
},
|
},
|
||||||
@@ -29142,6 +29156,7 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz",
|
||||||
"integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==",
|
"integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==",
|
||||||
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-unicode-property-regex instead.",
|
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-unicode-property-regex instead.",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-create-regexp-features-plugin": "^7.18.6",
|
"@babel/helper-create-regexp-features-plugin": "^7.18.6",
|
||||||
"@babel/helper-plugin-utils": "^7.18.6"
|
"@babel/helper-plugin-utils": "^7.18.6"
|
||||||
@@ -29176,6 +29191,7 @@
|
|||||||
},
|
},
|
||||||
"node_modules/@babel/plugin-syntax-class-properties": {
|
"node_modules/@babel/plugin-syntax-class-properties": {
|
||||||
"version": "7.12.13",
|
"version": "7.12.13",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.12.13"
|
"@babel/helper-plugin-utils": "^7.12.13"
|
||||||
@@ -29188,6 +29204,7 @@
|
|||||||
"version": "7.14.5",
|
"version": "7.14.5",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
|
||||||
"integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
|
"integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.14.5"
|
"@babel/helper-plugin-utils": "^7.14.5"
|
||||||
},
|
},
|
||||||
@@ -29225,6 +29242,7 @@
|
|||||||
"version": "7.8.3",
|
"version": "7.8.3",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
|
||||||
"integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
|
"integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.8.3"
|
"@babel/helper-plugin-utils": "^7.8.3"
|
||||||
},
|
},
|
||||||
@@ -29249,6 +29267,7 @@
|
|||||||
"version": "7.25.6",
|
"version": "7.25.6",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.6.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.6.tgz",
|
||||||
"integrity": "sha512-aABl0jHw9bZ2karQ/uUD6XP4u0SG22SJrOHFoL6XB1R7dTovOP4TzTlsxOYC5yQ1pdscVK2JTUnF6QL3ARoAiQ==",
|
"integrity": "sha512-aABl0jHw9bZ2karQ/uUD6XP4u0SG22SJrOHFoL6XB1R7dTovOP4TzTlsxOYC5yQ1pdscVK2JTUnF6QL3ARoAiQ==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.22.5"
|
"@babel/helper-plugin-utils": "^7.22.5"
|
||||||
},
|
},
|
||||||
@@ -29263,6 +29282,7 @@
|
|||||||
"version": "7.25.6",
|
"version": "7.25.6",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.6.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.6.tgz",
|
||||||
"integrity": "sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==",
|
"integrity": "sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.22.5"
|
"@babel/helper-plugin-utils": "^7.22.5"
|
||||||
},
|
},
|
||||||
@@ -29277,6 +29297,7 @@
|
|||||||
"version": "7.10.4",
|
"version": "7.10.4",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
|
||||||
"integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
|
"integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.10.4"
|
"@babel/helper-plugin-utils": "^7.10.4"
|
||||||
},
|
},
|
||||||
@@ -29288,6 +29309,7 @@
|
|||||||
"version": "7.8.3",
|
"version": "7.8.3",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
|
||||||
"integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
|
"integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.8.0"
|
"@babel/helper-plugin-utils": "^7.8.0"
|
||||||
},
|
},
|
||||||
@@ -29387,6 +29409,7 @@
|
|||||||
"version": "7.14.5",
|
"version": "7.14.5",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
|
||||||
"integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
|
"integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.14.5"
|
"@babel/helper-plugin-utils": "^7.14.5"
|
||||||
},
|
},
|
||||||
@@ -29414,6 +29437,7 @@
|
|||||||
"version": "7.18.6",
|
"version": "7.18.6",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz",
|
||||||
"integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==",
|
"integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-create-regexp-features-plugin": "^7.18.6",
|
"@babel/helper-create-regexp-features-plugin": "^7.18.6",
|
||||||
"@babel/helper-plugin-utils": "^7.18.6"
|
"@babel/helper-plugin-utils": "^7.18.6"
|
||||||
@@ -29442,6 +29466,7 @@
|
|||||||
"version": "7.25.4",
|
"version": "7.25.4",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.4.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.4.tgz",
|
||||||
"integrity": "sha512-jz8cV2XDDTqjKPwVPJBIjORVEmSGYhdRa8e5k5+vN+uwcjSrSxUaebBRa4ko1jqNF2uxyg8G6XYk30Jv285xzg==",
|
"integrity": "sha512-jz8cV2XDDTqjKPwVPJBIjORVEmSGYhdRa8e5k5+vN+uwcjSrSxUaebBRa4ko1jqNF2uxyg8G6XYk30Jv285xzg==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-environment-visitor": "^7.22.5",
|
"@babel/helper-environment-visitor": "^7.22.5",
|
||||||
"@babel/helper-plugin-utils": "^7.22.5",
|
"@babel/helper-plugin-utils": "^7.22.5",
|
||||||
@@ -29472,6 +29497,7 @@
|
|||||||
},
|
},
|
||||||
"node_modules/@babel/plugin-transform-block-scoped-functions": {
|
"node_modules/@babel/plugin-transform-block-scoped-functions": {
|
||||||
"version": "7.22.5",
|
"version": "7.22.5",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.22.5"
|
"@babel/helper-plugin-utils": "^7.22.5"
|
||||||
@@ -29500,6 +29526,7 @@
|
|||||||
"version": "7.25.4",
|
"version": "7.25.4",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.4.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.4.tgz",
|
||||||
"integrity": "sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==",
|
"integrity": "sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-create-class-features-plugin": "^7.22.5",
|
"@babel/helper-create-class-features-plugin": "^7.22.5",
|
||||||
"@babel/helper-plugin-utils": "^7.22.5"
|
"@babel/helper-plugin-utils": "^7.22.5"
|
||||||
@@ -29515,6 +29542,7 @@
|
|||||||
"version": "7.24.7",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz",
|
||||||
"integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==",
|
"integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-create-class-features-plugin": "^7.22.5",
|
"@babel/helper-create-class-features-plugin": "^7.22.5",
|
||||||
"@babel/helper-plugin-utils": "^7.22.5",
|
"@babel/helper-plugin-utils": "^7.22.5",
|
||||||
@@ -29579,6 +29607,7 @@
|
|||||||
"version": "7.24.7",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz",
|
||||||
"integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==",
|
"integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-create-regexp-features-plugin": "^7.22.5",
|
"@babel/helper-create-regexp-features-plugin": "^7.22.5",
|
||||||
"@babel/helper-plugin-utils": "^7.22.5"
|
"@babel/helper-plugin-utils": "^7.22.5"
|
||||||
@@ -29594,6 +29623,7 @@
|
|||||||
"version": "7.24.7",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz",
|
||||||
"integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==",
|
"integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.22.5"
|
"@babel/helper-plugin-utils": "^7.22.5"
|
||||||
},
|
},
|
||||||
@@ -29608,6 +29638,7 @@
|
|||||||
"version": "7.25.9",
|
"version": "7.25.9",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz",
|
||||||
"integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==",
|
"integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.25.9"
|
"@babel/helper-plugin-utils": "^7.25.9"
|
||||||
},
|
},
|
||||||
@@ -29620,6 +29651,7 @@
|
|||||||
},
|
},
|
||||||
"node_modules/@babel/plugin-transform-exponentiation-operator": {
|
"node_modules/@babel/plugin-transform-exponentiation-operator": {
|
||||||
"version": "7.22.5",
|
"version": "7.22.5",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5",
|
"@babel/helper-builder-binary-assignment-operator-visitor": "^7.22.5",
|
||||||
@@ -29636,6 +29668,7 @@
|
|||||||
"version": "7.24.7",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz",
|
||||||
"integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==",
|
"integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.22.5",
|
"@babel/helper-plugin-utils": "^7.22.5",
|
||||||
"@babel/plugin-syntax-export-namespace-from": "^7.8.3"
|
"@babel/plugin-syntax-export-namespace-from": "^7.8.3"
|
||||||
@@ -29663,6 +29696,7 @@
|
|||||||
},
|
},
|
||||||
"node_modules/@babel/plugin-transform-for-of": {
|
"node_modules/@babel/plugin-transform-for-of": {
|
||||||
"version": "7.22.5",
|
"version": "7.22.5",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.22.5"
|
"@babel/helper-plugin-utils": "^7.22.5"
|
||||||
@@ -29693,6 +29727,7 @@
|
|||||||
"version": "7.24.7",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz",
|
||||||
"integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==",
|
"integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.22.5",
|
"@babel/helper-plugin-utils": "^7.22.5",
|
||||||
"@babel/plugin-syntax-json-strings": "^7.8.3"
|
"@babel/plugin-syntax-json-strings": "^7.8.3"
|
||||||
@@ -29721,6 +29756,7 @@
|
|||||||
"version": "7.24.7",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz",
|
||||||
"integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==",
|
"integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.22.5",
|
"@babel/helper-plugin-utils": "^7.22.5",
|
||||||
"@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
|
"@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
|
||||||
@@ -29734,6 +29770,7 @@
|
|||||||
},
|
},
|
||||||
"node_modules/@babel/plugin-transform-member-expression-literals": {
|
"node_modules/@babel/plugin-transform-member-expression-literals": {
|
||||||
"version": "7.22.5",
|
"version": "7.22.5",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.22.5"
|
"@babel/helper-plugin-utils": "^7.22.5"
|
||||||
@@ -29749,6 +29786,7 @@
|
|||||||
"version": "7.24.7",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz",
|
||||||
"integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==",
|
"integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-module-transforms": "^7.22.5",
|
"@babel/helper-module-transforms": "^7.22.5",
|
||||||
"@babel/helper-plugin-utils": "^7.22.5"
|
"@babel/helper-plugin-utils": "^7.22.5"
|
||||||
@@ -29779,6 +29817,7 @@
|
|||||||
"version": "7.25.0",
|
"version": "7.25.0",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz",
|
||||||
"integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==",
|
"integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-hoist-variables": "^7.22.5",
|
"@babel/helper-hoist-variables": "^7.22.5",
|
||||||
"@babel/helper-module-transforms": "^7.22.5",
|
"@babel/helper-module-transforms": "^7.22.5",
|
||||||
@@ -29796,6 +29835,7 @@
|
|||||||
"version": "7.24.7",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz",
|
||||||
"integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==",
|
"integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-module-transforms": "^7.22.5",
|
"@babel/helper-module-transforms": "^7.22.5",
|
||||||
"@babel/helper-plugin-utils": "^7.22.5"
|
"@babel/helper-plugin-utils": "^7.22.5"
|
||||||
@@ -29825,6 +29865,7 @@
|
|||||||
"version": "7.24.7",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz",
|
||||||
"integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==",
|
"integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.22.5"
|
"@babel/helper-plugin-utils": "^7.22.5"
|
||||||
},
|
},
|
||||||
@@ -29854,6 +29895,7 @@
|
|||||||
"version": "7.24.7",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz",
|
||||||
"integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==",
|
"integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.22.5",
|
"@babel/helper-plugin-utils": "^7.22.5",
|
||||||
"@babel/plugin-syntax-numeric-separator": "^7.10.4"
|
"@babel/plugin-syntax-numeric-separator": "^7.10.4"
|
||||||
@@ -29869,6 +29911,7 @@
|
|||||||
"version": "7.24.7",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz",
|
||||||
"integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==",
|
"integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/compat-data": "^7.22.5",
|
"@babel/compat-data": "^7.22.5",
|
||||||
"@babel/helper-compilation-targets": "^7.22.5",
|
"@babel/helper-compilation-targets": "^7.22.5",
|
||||||
@@ -29885,6 +29928,7 @@
|
|||||||
},
|
},
|
||||||
"node_modules/@babel/plugin-transform-object-super": {
|
"node_modules/@babel/plugin-transform-object-super": {
|
||||||
"version": "7.22.5",
|
"version": "7.22.5",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.22.5",
|
"@babel/helper-plugin-utils": "^7.22.5",
|
||||||
@@ -29901,6 +29945,7 @@
|
|||||||
"version": "7.24.7",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz",
|
||||||
"integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==",
|
"integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.22.5",
|
"@babel/helper-plugin-utils": "^7.22.5",
|
||||||
"@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
|
"@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
|
||||||
@@ -29974,6 +30019,7 @@
|
|||||||
},
|
},
|
||||||
"node_modules/@babel/plugin-transform-property-literals": {
|
"node_modules/@babel/plugin-transform-property-literals": {
|
||||||
"version": "7.22.5",
|
"version": "7.22.5",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.22.5"
|
"@babel/helper-plugin-utils": "^7.22.5"
|
||||||
@@ -30043,6 +30089,7 @@
|
|||||||
},
|
},
|
||||||
"node_modules/@babel/plugin-transform-regenerator": {
|
"node_modules/@babel/plugin-transform-regenerator": {
|
||||||
"version": "7.22.5",
|
"version": "7.22.5",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.22.5",
|
"@babel/helper-plugin-utils": "^7.22.5",
|
||||||
@@ -30059,6 +30106,7 @@
|
|||||||
"version": "7.24.7",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz",
|
||||||
"integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==",
|
"integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.22.5"
|
"@babel/helper-plugin-utils": "^7.22.5"
|
||||||
},
|
},
|
||||||
@@ -30151,6 +30199,7 @@
|
|||||||
"version": "7.24.8",
|
"version": "7.24.8",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz",
|
||||||
"integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==",
|
"integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.22.5"
|
"@babel/helper-plugin-utils": "^7.22.5"
|
||||||
},
|
},
|
||||||
@@ -30181,6 +30230,7 @@
|
|||||||
"version": "7.24.7",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz",
|
||||||
"integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==",
|
"integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.22.5"
|
"@babel/helper-plugin-utils": "^7.22.5"
|
||||||
},
|
},
|
||||||
@@ -30195,6 +30245,7 @@
|
|||||||
"version": "7.24.7",
|
"version": "7.24.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz",
|
||||||
"integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==",
|
"integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-create-regexp-features-plugin": "^7.22.5",
|
"@babel/helper-create-regexp-features-plugin": "^7.22.5",
|
||||||
"@babel/helper-plugin-utils": "^7.22.5"
|
"@babel/helper-plugin-utils": "^7.22.5"
|
||||||
@@ -30224,6 +30275,7 @@
|
|||||||
"version": "7.25.4",
|
"version": "7.25.4",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.4.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.4.tgz",
|
||||||
"integrity": "sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==",
|
"integrity": "sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-create-regexp-features-plugin": "^7.22.5",
|
"@babel/helper-create-regexp-features-plugin": "^7.22.5",
|
||||||
"@babel/helper-plugin-utils": "^7.22.5"
|
"@babel/helper-plugin-utils": "^7.22.5"
|
||||||
@@ -30239,6 +30291,7 @@
|
|||||||
"version": "7.25.4",
|
"version": "7.25.4",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.4.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.4.tgz",
|
||||||
"integrity": "sha512-W9Gyo+KmcxjGahtt3t9fb14vFRWvPpu5pT6GBlovAK6BTBcxgjfVMSQCfJl4oi35ODrxP6xx2Wr8LNST57Mraw==",
|
"integrity": "sha512-W9Gyo+KmcxjGahtt3t9fb14vFRWvPpu5pT6GBlovAK6BTBcxgjfVMSQCfJl4oi35ODrxP6xx2Wr8LNST57Mraw==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/compat-data": "^7.22.5",
|
"@babel/compat-data": "^7.22.5",
|
||||||
"@babel/helper-compilation-targets": "^7.22.5",
|
"@babel/helper-compilation-targets": "^7.22.5",
|
||||||
@@ -30332,6 +30385,7 @@
|
|||||||
"version": "0.1.6",
|
"version": "0.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6.tgz",
|
||||||
"integrity": "sha512-ID2yj6K/4lKfhuU3+EX4UvNbIt7eACFbHmNUjzA+ep+B5971CknnA/9DEWKbRokfbbtblxxxXFJJrH47UEAMVg==",
|
"integrity": "sha512-ID2yj6K/4lKfhuU3+EX4UvNbIt7eACFbHmNUjzA+ep+B5971CknnA/9DEWKbRokfbbtblxxxXFJJrH47UEAMVg==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/helper-plugin-utils": "^7.0.0",
|
"@babel/helper-plugin-utils": "^7.0.0",
|
||||||
"@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
|
"@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
|
||||||
@@ -30347,6 +30401,7 @@
|
|||||||
"version": "6.3.1",
|
"version": "6.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||||
|
"dev": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"semver": "bin/semver.js"
|
"semver": "bin/semver.js"
|
||||||
}
|
}
|
||||||
@@ -33650,7 +33705,8 @@
|
|||||||
"node_modules/@types/estree": {
|
"node_modules/@types/estree": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
|
||||||
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw=="
|
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@types/graceful-fs": {
|
"node_modules/@types/graceful-fs": {
|
||||||
"version": "4.1.6",
|
"version": "4.1.6",
|
||||||
@@ -33756,14 +33812,14 @@
|
|||||||
},
|
},
|
||||||
"node_modules/@types/prop-types": {
|
"node_modules/@types/prop-types": {
|
||||||
"version": "15.7.5",
|
"version": "15.7.5",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/react": {
|
"node_modules/@types/react": {
|
||||||
"version": "18.3.18",
|
"version": "18.3.18",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz",
|
||||||
"integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==",
|
"integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/prop-types": "*",
|
"@types/prop-types": "*",
|
||||||
@@ -34119,6 +34175,7 @@
|
|||||||
"version": "1.12.1",
|
"version": "1.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz",
|
||||||
"integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==",
|
"integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@webassemblyjs/helper-numbers": "1.11.6",
|
"@webassemblyjs/helper-numbers": "1.11.6",
|
||||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6"
|
"@webassemblyjs/helper-wasm-bytecode": "1.11.6"
|
||||||
@@ -34127,22 +34184,26 @@
|
|||||||
"node_modules/@webassemblyjs/floating-point-hex-parser": {
|
"node_modules/@webassemblyjs/floating-point-hex-parser": {
|
||||||
"version": "1.11.6",
|
"version": "1.11.6",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz",
|
||||||
"integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw=="
|
"integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@webassemblyjs/helper-api-error": {
|
"node_modules/@webassemblyjs/helper-api-error": {
|
||||||
"version": "1.11.6",
|
"version": "1.11.6",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz",
|
||||||
"integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q=="
|
"integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@webassemblyjs/helper-buffer": {
|
"node_modules/@webassemblyjs/helper-buffer": {
|
||||||
"version": "1.12.1",
|
"version": "1.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz",
|
||||||
"integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw=="
|
"integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@webassemblyjs/helper-numbers": {
|
"node_modules/@webassemblyjs/helper-numbers": {
|
||||||
"version": "1.11.6",
|
"version": "1.11.6",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz",
|
||||||
"integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==",
|
"integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@webassemblyjs/floating-point-hex-parser": "1.11.6",
|
"@webassemblyjs/floating-point-hex-parser": "1.11.6",
|
||||||
"@webassemblyjs/helper-api-error": "1.11.6",
|
"@webassemblyjs/helper-api-error": "1.11.6",
|
||||||
@@ -34152,12 +34213,14 @@
|
|||||||
"node_modules/@webassemblyjs/helper-wasm-bytecode": {
|
"node_modules/@webassemblyjs/helper-wasm-bytecode": {
|
||||||
"version": "1.11.6",
|
"version": "1.11.6",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz",
|
||||||
"integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA=="
|
"integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@webassemblyjs/helper-wasm-section": {
|
"node_modules/@webassemblyjs/helper-wasm-section": {
|
||||||
"version": "1.12.1",
|
"version": "1.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz",
|
||||||
"integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==",
|
"integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@webassemblyjs/ast": "1.11.6",
|
"@webassemblyjs/ast": "1.11.6",
|
||||||
"@webassemblyjs/helper-buffer": "1.11.6",
|
"@webassemblyjs/helper-buffer": "1.11.6",
|
||||||
@@ -34169,6 +34232,7 @@
|
|||||||
"version": "1.11.6",
|
"version": "1.11.6",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz",
|
||||||
"integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==",
|
"integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@xtuc/ieee754": "^1.2.0"
|
"@xtuc/ieee754": "^1.2.0"
|
||||||
}
|
}
|
||||||
@@ -34177,6 +34241,7 @@
|
|||||||
"version": "1.11.6",
|
"version": "1.11.6",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz",
|
||||||
"integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==",
|
"integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@xtuc/long": "4.2.2"
|
"@xtuc/long": "4.2.2"
|
||||||
}
|
}
|
||||||
@@ -34184,12 +34249,14 @@
|
|||||||
"node_modules/@webassemblyjs/utf8": {
|
"node_modules/@webassemblyjs/utf8": {
|
||||||
"version": "1.11.6",
|
"version": "1.11.6",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz",
|
||||||
"integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA=="
|
"integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@webassemblyjs/wasm-edit": {
|
"node_modules/@webassemblyjs/wasm-edit": {
|
||||||
"version": "1.12.1",
|
"version": "1.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz",
|
||||||
"integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==",
|
"integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@webassemblyjs/ast": "1.11.6",
|
"@webassemblyjs/ast": "1.11.6",
|
||||||
"@webassemblyjs/helper-buffer": "1.11.6",
|
"@webassemblyjs/helper-buffer": "1.11.6",
|
||||||
@@ -34205,6 +34272,7 @@
|
|||||||
"version": "1.12.1",
|
"version": "1.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz",
|
||||||
"integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==",
|
"integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@webassemblyjs/ast": "1.11.6",
|
"@webassemblyjs/ast": "1.11.6",
|
||||||
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
|
||||||
@@ -34217,6 +34285,7 @@
|
|||||||
"version": "1.12.1",
|
"version": "1.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz",
|
||||||
"integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==",
|
"integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@webassemblyjs/ast": "1.11.6",
|
"@webassemblyjs/ast": "1.11.6",
|
||||||
"@webassemblyjs/helper-buffer": "1.11.6",
|
"@webassemblyjs/helper-buffer": "1.11.6",
|
||||||
@@ -34228,6 +34297,7 @@
|
|||||||
"version": "1.12.1",
|
"version": "1.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz",
|
||||||
"integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==",
|
"integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@webassemblyjs/ast": "1.11.6",
|
"@webassemblyjs/ast": "1.11.6",
|
||||||
"@webassemblyjs/helper-api-error": "1.11.6",
|
"@webassemblyjs/helper-api-error": "1.11.6",
|
||||||
@@ -34241,6 +34311,7 @@
|
|||||||
"version": "1.12.1",
|
"version": "1.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz",
|
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz",
|
||||||
"integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==",
|
"integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@webassemblyjs/ast": "1.11.6",
|
"@webassemblyjs/ast": "1.11.6",
|
||||||
"@xtuc/long": "4.2.2"
|
"@xtuc/long": "4.2.2"
|
||||||
@@ -34298,12 +34369,14 @@
|
|||||||
"node_modules/@xtuc/ieee754": {
|
"node_modules/@xtuc/ieee754": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
|
||||||
"integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="
|
"integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@xtuc/long": {
|
"node_modules/@xtuc/long": {
|
||||||
"version": "4.2.2",
|
"version": "4.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
|
||||||
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
|
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@yarnpkg/lockfile": {
|
"node_modules/@yarnpkg/lockfile": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
@@ -35302,6 +35375,7 @@
|
|||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
|
||||||
"integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==",
|
"integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==",
|
||||||
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.0"
|
"node": ">=6.0"
|
||||||
}
|
}
|
||||||
@@ -35732,7 +35806,7 @@
|
|||||||
},
|
},
|
||||||
"node_modules/csstype": {
|
"node_modules/csstype": {
|
||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"devOptional": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/date-fns": {
|
"node_modules/date-fns": {
|
||||||
@@ -36332,6 +36406,7 @@
|
|||||||
"version": "5.17.1",
|
"version": "5.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz",
|
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz",
|
||||||
"integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==",
|
"integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"graceful-fs": "^4.2.4",
|
"graceful-fs": "^4.2.4",
|
||||||
"tapable": "^2.2.0"
|
"tapable": "^2.2.0"
|
||||||
@@ -36451,7 +36526,8 @@
|
|||||||
"node_modules/es-module-lexer": {
|
"node_modules/es-module-lexer": {
|
||||||
"version": "1.5.4",
|
"version": "1.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz",
|
||||||
"integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw=="
|
"integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/es-object-atoms": {
|
"node_modules/es-object-atoms": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@@ -36796,6 +36872,7 @@
|
|||||||
"version": "5.1.1",
|
"version": "5.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
|
||||||
"integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
|
"integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esrecurse": "^4.3.0",
|
"esrecurse": "^4.3.0",
|
||||||
"estraverse": "^4.1.1"
|
"estraverse": "^4.1.1"
|
||||||
@@ -36808,6 +36885,7 @@
|
|||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
|
||||||
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
|
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
|
||||||
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=4.0"
|
"node": ">=4.0"
|
||||||
}
|
}
|
||||||
@@ -36971,6 +37049,7 @@
|
|||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
|
||||||
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
|
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"estraverse": "^5.2.0"
|
"estraverse": "^5.2.0"
|
||||||
},
|
},
|
||||||
@@ -36982,6 +37061,7 @@
|
|||||||
"version": "5.3.0",
|
"version": "5.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
|
||||||
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
|
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
|
||||||
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=4.0"
|
"node": ">=4.0"
|
||||||
}
|
}
|
||||||
@@ -36990,6 +37070,7 @@
|
|||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
|
||||||
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
|
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
|
||||||
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@@ -37749,7 +37830,8 @@
|
|||||||
"node_modules/glob-to-regexp": {
|
"node_modules/glob-to-regexp": {
|
||||||
"version": "0.4.1",
|
"version": "0.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
|
||||||
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="
|
"integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/global": {
|
"node_modules/global": {
|
||||||
"version": "4.4.0",
|
"version": "4.4.0",
|
||||||
@@ -39838,7 +39920,8 @@
|
|||||||
"node_modules/json-parse-even-better-errors": {
|
"node_modules/json-parse-even-better-errors": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
|
||||||
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
|
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/json-schema-ref-resolver": {
|
"node_modules/json-schema-ref-resolver": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@@ -40314,6 +40397,7 @@
|
|||||||
"version": "4.3.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
|
||||||
"integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
|
"integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
|
||||||
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6.11.5"
|
"node": ">=6.11.5"
|
||||||
}
|
}
|
||||||
@@ -42543,6 +42627,7 @@
|
|||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||||
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"safe-buffer": "^5.1.0"
|
"safe-buffer": "^5.1.0"
|
||||||
}
|
}
|
||||||
@@ -42564,30 +42649,6 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/react-dom": {
|
|
||||||
"version": "18.3.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
|
|
||||||
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"loose-envify": "^1.1.0",
|
|
||||||
"scheduler": "^0.23.2"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"react": "^18.3.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-dom/node_modules/scheduler": {
|
|
||||||
"version": "0.23.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
|
|
||||||
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
|
||||||
"loose-envify": "^1.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/react-freeze": {
|
"node_modules/react-freeze": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -43023,6 +43084,15 @@
|
|||||||
"react-native": ">=0.40"
|
"react-native": ">=0.40"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-native-pager-view": {
|
||||||
|
"version": "6.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-pager-view/-/react-native-pager-view-6.5.1.tgz",
|
||||||
|
"integrity": "sha512-YdX7bP+rPYvATMU7HzlMq9JaG3ui/+cVRbFZFGW+QshDULANFg9ECR1BA7H7JTIcO/ZgWCwF+1aVmYG5yBA9Og==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "*",
|
||||||
|
"react-native": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-native-pdf": {
|
"node_modules/react-native-pdf": {
|
||||||
"version": "6.6.2",
|
"version": "6.6.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -43187,6 +43257,27 @@
|
|||||||
"react-native": ">=0.59.0"
|
"react-native": ">=0.59.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/react-native-tab-view": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-native-tab-view/-/react-native-tab-view-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-u70Et9onvAGhcBRda8NO+JgM/10G3kg/jWsbDY7QQSOAri7F7+VVS/4uupxjbCDSkL1BJdUOqhUToK/M2AH34Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"use-latest-callback": "^0.2.1"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">= 18.2.0",
|
||||||
|
"react-native": "*",
|
||||||
|
"react-native-pager-view": ">= 6.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-native-tab-view/node_modules/use-latest-callback": {
|
||||||
|
"version": "0.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/use-latest-callback/-/use-latest-callback-0.2.3.tgz",
|
||||||
|
"integrity": "sha512-7vI3fBuyRcP91pazVboc4qu+6ZqM8izPWX9k7cRnT8hbD5svslcknsh3S9BUhaK11OmgTV4oWZZVSeQAiV53SQ==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=16.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/react-native-theme-switch-animation": {
|
"node_modules/react-native-theme-switch-animation": {
|
||||||
"version": "0.6.0",
|
"version": "0.6.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -43507,6 +43598,7 @@
|
|||||||
},
|
},
|
||||||
"node_modules/regenerator-transform": {
|
"node_modules/regenerator-transform": {
|
||||||
"version": "0.15.1",
|
"version": "0.15.1",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/runtime": "^7.8.4"
|
"@babel/runtime": "^7.8.4"
|
||||||
@@ -43859,6 +43951,7 @@
|
|||||||
},
|
},
|
||||||
"node_modules/serialize-javascript": {
|
"node_modules/serialize-javascript": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
|
"dev": true,
|
||||||
"license": "BSD-3-Clause",
|
"license": "BSD-3-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"randombytes": "^2.1.0"
|
"randombytes": "^2.1.0"
|
||||||
@@ -44516,6 +44609,7 @@
|
|||||||
},
|
},
|
||||||
"node_modules/tapable": {
|
"node_modules/tapable": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
@@ -44593,6 +44687,7 @@
|
|||||||
"version": "5.3.10",
|
"version": "5.3.10",
|
||||||
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz",
|
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz",
|
||||||
"integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==",
|
"integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/trace-mapping": "^0.3.17",
|
"@jridgewell/trace-mapping": "^0.3.17",
|
||||||
"jest-worker": "^27.4.5",
|
"jest-worker": "^27.4.5",
|
||||||
@@ -44626,6 +44721,7 @@
|
|||||||
"version": "27.5.1",
|
"version": "27.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
|
||||||
"integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
|
"integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"merge-stream": "^2.0.0",
|
"merge-stream": "^2.0.0",
|
||||||
@@ -44639,6 +44735,7 @@
|
|||||||
"version": "8.1.1",
|
"version": "8.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
|
||||||
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
|
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"has-flag": "^4.0.0"
|
"has-flag": "^4.0.0"
|
||||||
},
|
},
|
||||||
@@ -45215,6 +45312,7 @@
|
|||||||
"version": "2.4.2",
|
"version": "2.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz",
|
||||||
"integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==",
|
"integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"glob-to-regexp": "^0.4.1",
|
"glob-to-regexp": "^0.4.1",
|
||||||
"graceful-fs": "^4.1.2"
|
"graceful-fs": "^4.1.2"
|
||||||
@@ -45238,6 +45336,7 @@
|
|||||||
"version": "5.94.0",
|
"version": "5.94.0",
|
||||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz",
|
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz",
|
||||||
"integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==",
|
"integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/eslint-scope": "^3.7.3",
|
"@types/eslint-scope": "^3.7.3",
|
||||||
"@types/estree": "^1.0.0",
|
"@types/estree": "^1.0.0",
|
||||||
@@ -45353,6 +45452,7 @@
|
|||||||
"version": "3.2.3",
|
"version": "3.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
|
||||||
"integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
|
"integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
|
||||||
|
"dev": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.13.0"
|
"node": ">=10.13.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,7 +83,16 @@ const EXTRA_ICON_NAMES = [
|
|||||||
"arrow-up-bold",
|
"arrow-up-bold",
|
||||||
"login",
|
"login",
|
||||||
"gift",
|
"gift",
|
||||||
"share"
|
"share",
|
||||||
|
"note-outline",
|
||||||
|
"weather-sunny",
|
||||||
|
"weather-night",
|
||||||
|
"notebook-outline",
|
||||||
|
"archive",
|
||||||
|
"home-outline",
|
||||||
|
"checkbox-blank-outline",
|
||||||
|
"checkbox-outline",
|
||||||
|
"checkbox-intermediate"
|
||||||
];
|
];
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
|||||||
1
packages/editor-mobile/package-lock.json
generated
1
packages/editor-mobile/package-lock.json
generated
@@ -63,6 +63,7 @@
|
|||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@notesnook-importer/core": "^2.1.1",
|
||||||
"@notesnook/common": "file:../common",
|
"@notesnook/common": "file:../common",
|
||||||
"@notesnook/intl": "file:../intl",
|
"@notesnook/intl": "file:../intl",
|
||||||
"@notesnook/theme": "file:../theme",
|
"@notesnook/theme": "file:../theme",
|
||||||
|
|||||||
@@ -2443,5 +2443,13 @@ Use this if changes from other devices are not appearing on this device. This wi
|
|||||||
fontLigatures: () => t`Font ligatures`,
|
fontLigatures: () => t`Font ligatures`,
|
||||||
fontLigaturesDesc: () =>
|
fontLigaturesDesc: () =>
|
||||||
t`Enable ligatures for common symbols like →, ←, etc`,
|
t`Enable ligatures for common symbols like →, ←, etc`,
|
||||||
expandSidebar: () => t`Expand sidebar`
|
expandSidebar: () => t`Expand sidebar`,
|
||||||
|
viewAllLimits: () => `View all limits`,
|
||||||
|
freePlan: () => t`Free plan`,
|
||||||
|
proPlan: () => t`Pro plan`,
|
||||||
|
essentialPlan: () => t`Essential plan`,
|
||||||
|
believerPlan: () => t`Believer plan`,
|
||||||
|
storage: () => t`Storage`,
|
||||||
|
used: () => t`used`,
|
||||||
|
editProfile: () => t`Edit profile`
|
||||||
};
|
};
|
||||||
|
|||||||
6
packages/theme/package-lock.json
generated
6
packages/theme/package-lock.json
generated
@@ -417,9 +417,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@theme-ui/css": {
|
"node_modules/@theme-ui/css": {
|
||||||
"version": "0.16.1",
|
"version": "0.16.2",
|
||||||
"resolved": "https://registry.npmjs.org/@theme-ui/css/-/css-0.16.1.tgz",
|
"resolved": "https://registry.npmjs.org/@theme-ui/css/-/css-0.16.2.tgz",
|
||||||
"integrity": "sha512-8TO2DbiqPrRyTlGRIElDak/p0M4ykyd8LkeavyOF/sTE9s93AwyFcle6KYYMEULrJP49SyYiEvTif7J7Z50DhA==",
|
"integrity": "sha512-fNe+FhwKC5+7jQfxCRnm3oqYNhMFuiWiLA9OoLBEkt3b4egot29UK1+fqemwiNVjl206e2fPT5Z7uXRdb6LC2A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"csstype": "^3.0.10"
|
"csstype": "^3.0.10"
|
||||||
|
|||||||
Reference in New Issue
Block a user