mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-16 11:47:54 +01:00
mobile: fix orientation changing and fullscreen mode on tablets
This commit is contained in:
@@ -111,7 +111,6 @@ export const FluidPanels = forwardRef<TabsRef, TabProps>(function FluidTabs(
|
||||
const containerWidth = widths
|
||||
? widths.sidebar + widths.list + widths.editor
|
||||
: dimensions.width;
|
||||
|
||||
const drawerPosition = 0;
|
||||
const homePosition = widths.sidebar;
|
||||
const editorPosition = widths.sidebar + widths.list;
|
||||
@@ -440,15 +439,7 @@ export const FluidPanels = forwardRef<TabsRef, TabProps>(function FluidTabs(
|
||||
width: containerWidth,
|
||||
flexDirection: "row"
|
||||
},
|
||||
deviceMode === "tablet"
|
||||
? {
|
||||
transform: [
|
||||
{
|
||||
translateX: 0
|
||||
}
|
||||
]
|
||||
}
|
||||
: animatedStyles
|
||||
animatedStyles
|
||||
]}
|
||||
>
|
||||
{children}
|
||||
|
||||
@@ -58,6 +58,7 @@ import { Button } from "../ui/button";
|
||||
import SettingsService from "../../services/settings";
|
||||
import { isFeatureAvailable } from "@notesnook/common";
|
||||
import PaywallSheet from "../sheets/paywall";
|
||||
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
|
||||
const renderScene = SceneMap({
|
||||
home: SideMenuHome,
|
||||
notebooks: SideMenuNotebooks,
|
||||
@@ -68,6 +69,7 @@ const renderScene = SceneMap({
|
||||
export const SideMenu = React.memo(
|
||||
function SideMenu() {
|
||||
const { colors } = useThemeColors();
|
||||
const insets = useGlobalSafeAreaInsets();
|
||||
const [index, setIndex] = React.useState(
|
||||
SettingsService.getProperty("defaultSidebarTab")
|
||||
);
|
||||
@@ -87,10 +89,13 @@ export const SideMenu = React.memo(
|
||||
]);
|
||||
|
||||
return (
|
||||
<SafeAreaView
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
backgroundColor: colors.primary.background
|
||||
backgroundColor: colors.primary.background,
|
||||
paddingTop: insets.top,
|
||||
paddingBottom: insets.bottom,
|
||||
paddingLeft: insets.left
|
||||
}}
|
||||
>
|
||||
<TabView
|
||||
@@ -103,7 +108,7 @@ export const SideMenu = React.memo(
|
||||
animationEnabled={false}
|
||||
lazy
|
||||
/>
|
||||
</SafeAreaView>
|
||||
</View>
|
||||
);
|
||||
},
|
||||
() => true
|
||||
@@ -351,9 +356,8 @@ const TabBar = (
|
||||
color={colors.primary.icon}
|
||||
onPress={async () => {
|
||||
if (props.navigationState.index === 1) {
|
||||
const notebooksFeature = await isFeatureAvailable(
|
||||
"notebooks"
|
||||
);
|
||||
const notebooksFeature =
|
||||
await isFeatureAvailable("notebooks");
|
||||
if (!notebooksFeature.isAllowed) {
|
||||
PaywallSheet.present(notebooksFeature);
|
||||
return;
|
||||
|
||||
@@ -29,7 +29,7 @@ import React, {
|
||||
useRef,
|
||||
useState
|
||||
} from "react";
|
||||
import { Dimensions, LayoutChangeEvent, Platform, View } from "react-native";
|
||||
import { LayoutChangeEvent, View } from "react-native";
|
||||
import Orientation, {
|
||||
OrientationType,
|
||||
useDeviceOrientationChange
|
||||
@@ -39,7 +39,6 @@ import Animated, {
|
||||
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";
|
||||
@@ -69,15 +68,13 @@ import {
|
||||
eOpenFullscreenEditor,
|
||||
eUnlockNote
|
||||
} from "../utils/events";
|
||||
import { editorRef, fluidTabsRef } from "../utils/global-refs";
|
||||
import { valueLimiter } from "../utils/functions";
|
||||
import { fluidTabsRef } from "../utils/global-refs";
|
||||
import { AppNavigationStack } from "./navigation-stack";
|
||||
import type { PaneWidths } from "../screens/editor/wrapper";
|
||||
|
||||
const MOBILE_SIDEBAR_SIZE = 0.85;
|
||||
|
||||
const valueLimiter = (value: number, min: number, max: number) => {
|
||||
return value < min ? min : value > max ? max : value;
|
||||
};
|
||||
|
||||
let SideMenu: any = null;
|
||||
let EditorWrapper: any = null;
|
||||
|
||||
@@ -93,7 +90,6 @@ export const FluidPanelsView = React.memo(
|
||||
const insets = useGlobalSafeAreaInsets();
|
||||
const animatedOpacity = useSharedValue(0);
|
||||
const animatedTranslateY = useSharedValue(-9999);
|
||||
|
||||
const overlayRef = useRef<Animated.View>(null);
|
||||
const [orientation, setOrientation] = useState<OrientationType>(
|
||||
Orientation.getInitialOrientation()
|
||||
@@ -102,10 +98,17 @@ export const FluidPanelsView = React.memo(
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
||||
useDeviceOrientationChange((o) => {
|
||||
setOrientation(o);
|
||||
if (
|
||||
o !== OrientationType.UNKNOWN &&
|
||||
o !== OrientationType["FACE-UP"] &&
|
||||
o !== OrientationType["FACE-DOWN"] &&
|
||||
o !== OrientationType["PORTRAIT-UPSIDEDOWN"]
|
||||
) {
|
||||
setOrientation(o);
|
||||
}
|
||||
});
|
||||
|
||||
const isLandscape = orientation.includes("LANDSCAPE");
|
||||
console.log(orientation);
|
||||
|
||||
useEffect(() => {
|
||||
if (!appLoading) {
|
||||
@@ -147,16 +150,6 @@ export const FluidPanelsView = React.memo(
|
||||
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(
|
||||
@@ -169,17 +162,6 @@ export const FluidPanelsView = React.memo(
|
||||
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);
|
||||
}
|
||||
@@ -221,38 +203,8 @@ export const FluidPanelsView = React.memo(
|
||||
(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;
|
||||
eSendEvent(eCloseFullscreenEditor, current);
|
||||
}
|
||||
|
||||
const state = getAppState();
|
||||
@@ -280,40 +232,42 @@ export const FluidPanelsView = React.memo(
|
||||
}
|
||||
break;
|
||||
}
|
||||
}, 32);
|
||||
}, 400);
|
||||
},
|
||||
[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]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (orientation !== "UNKNOWN") {
|
||||
checkDeviceType(dimensions);
|
||||
}
|
||||
}, [orientation, dimensions]);
|
||||
|
||||
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;
|
||||
setDimensions({
|
||||
width: size.width,
|
||||
height: size.height
|
||||
});
|
||||
if (size.width > size.height) {
|
||||
setOrientation(OrientationType["LANDSCAPE-RIGHT"]);
|
||||
} else {
|
||||
setOrientation(OrientationType["PORTRAIT"]);
|
||||
}
|
||||
|
||||
checkDeviceType(size);
|
||||
},
|
||||
[
|
||||
checkDeviceType,
|
||||
@@ -324,11 +278,6 @@ export const FluidPanelsView = React.memo(
|
||||
]
|
||||
);
|
||||
|
||||
if (!deviceMode) {
|
||||
const size = Dimensions.get("window");
|
||||
checkDeviceType(size);
|
||||
}
|
||||
|
||||
const PANE_OFFSET = useMemo(
|
||||
() => ({
|
||||
mobile: {
|
||||
@@ -356,7 +305,7 @@ export const FluidPanelsView = React.memo(
|
||||
[dimensions.width, fullscreen]
|
||||
);
|
||||
|
||||
const PANE_WIDTHS = useMemo(
|
||||
const PANE_WIDTHS: PaneWidths = useMemo(
|
||||
() => ({
|
||||
mobile: {
|
||||
sidebar: dimensions.width * MOBILE_SIDEBAR_SIZE,
|
||||
@@ -382,6 +331,7 @@ export const FluidPanelsView = React.memo(
|
||||
(scrollOffset: number) => {
|
||||
if (!deviceMode) return;
|
||||
hideAllTooltips();
|
||||
|
||||
if (
|
||||
scrollOffset >
|
||||
PANE_OFFSET[deviceMode as keyof typeof PANE_OFFSET].sidebar - 10
|
||||
@@ -409,7 +359,7 @@ export const FluidPanelsView = React.memo(
|
||||
};
|
||||
}, []);
|
||||
|
||||
if (!isLoading) {
|
||||
if (!isLoading && !SideMenu && !EditorWrapper) {
|
||||
SideMenu = require("../components/side-menu").SideMenu;
|
||||
EditorWrapper = require("../screens/editor/wrapper").EditorWrapper;
|
||||
}
|
||||
@@ -421,15 +371,7 @@ export const FluidPanelsView = React.memo(
|
||||
style={{
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
backgroundColor: colors.primary.background,
|
||||
marginRight:
|
||||
orientation === "LANDSCAPE-RIGHT" && Platform.OS === "ios"
|
||||
? insets.right
|
||||
: 0,
|
||||
marginLeft:
|
||||
orientation === "LANDSCAPE-LEFT" && Platform.OS === "ios"
|
||||
? insets.left
|
||||
: 0
|
||||
backgroundColor: colors.primary.background
|
||||
}}
|
||||
>
|
||||
{deviceMode && PANE_WIDTHS[deviceMode as keyof typeof PANE_WIDTHS] ? (
|
||||
@@ -503,9 +445,7 @@ export const FluidPanelsView = React.memo(
|
||||
style={{
|
||||
flex: 1,
|
||||
paddingTop: insets.top,
|
||||
paddingBottom: insets.bottom,
|
||||
paddingLeft: insets.left,
|
||||
paddingRight: insets.right
|
||||
paddingBottom: insets.bottom
|
||||
}}
|
||||
>
|
||||
<AppNavigationStack />
|
||||
|
||||
@@ -23,21 +23,36 @@ import {
|
||||
AppState,
|
||||
AppStateStatus,
|
||||
KeyboardAvoidingView,
|
||||
Platform,
|
||||
TextInput,
|
||||
View
|
||||
} from "react-native";
|
||||
import Editor from ".";
|
||||
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
|
||||
import useIsFloatingKeyboard from "../../hooks/use-is-floating-keyboard";
|
||||
import useKeyboard from "../../hooks/use-keyboard";
|
||||
import { DDS } from "../../services/device-detection";
|
||||
import { useSettingStore } from "../../stores/use-setting-store";
|
||||
import { editorRef } from "../../utils/global-refs";
|
||||
import { editorController, textInput } from "./tiptap/utils";
|
||||
import deviceInfo from "react-native-device-info";
|
||||
|
||||
export const EditorWrapper = ({ widths }: { widths: any }) => {
|
||||
export type PaneWidths = {
|
||||
mobile: {
|
||||
sidebar: number;
|
||||
list: number;
|
||||
editor: number;
|
||||
};
|
||||
smallTablet: {
|
||||
sidebar: number;
|
||||
list: number;
|
||||
editor: number;
|
||||
};
|
||||
tablet: {
|
||||
sidebar: number;
|
||||
list: number;
|
||||
editor: number;
|
||||
};
|
||||
};
|
||||
|
||||
export const EditorWrapper = ({ widths }: { widths: PaneWidths }) => {
|
||||
const { colors } = useThemeColors();
|
||||
const { colors: toolBarColors } = useThemeColors("editorToolbar");
|
||||
const deviceMode = useSettingStore((state) => state.deviceMode);
|
||||
@@ -47,8 +62,9 @@ export const EditorWrapper = ({ widths }: { widths: any }) => {
|
||||
const introCompleted = useSettingStore(
|
||||
(state) => state.settings.introCompleted
|
||||
);
|
||||
const keyboard = useKeyboard();
|
||||
const prevState = useRef<AppStateStatus>(undefined);
|
||||
const isFullscreen = useSettingStore((state) => state.fullscreen);
|
||||
const dimensions = useSettingStore((state) => state.dimensions);
|
||||
|
||||
const onAppStateChanged = async (state: AppStateStatus) => {
|
||||
if (!prevState.current) {
|
||||
@@ -72,32 +88,37 @@ export const EditorWrapper = ({ widths }: { widths: any }) => {
|
||||
};
|
||||
}, [loading]);
|
||||
|
||||
const getMarginBottom = () => {
|
||||
const bottomInsets =
|
||||
Platform.OS === "android" ? 12 : insets.bottom + 16 || 14;
|
||||
if (!keyboard.keyboardShown) return bottomInsets / 1.5;
|
||||
if (deviceInfo.isTablet() && Platform.OS === "ios" && !floating)
|
||||
return bottomInsets;
|
||||
if (Platform.OS === "ios") return bottomInsets / 1.5;
|
||||
return 0;
|
||||
};
|
||||
|
||||
return (
|
||||
<View
|
||||
testID="editor-wrapper"
|
||||
ref={editorRef}
|
||||
style={{
|
||||
width: widths[!introCompleted ? "mobile" : (deviceMode as any)]?.editor,
|
||||
height: "100%",
|
||||
minHeight: "100%",
|
||||
backgroundColor: toolBarColors.primary.background,
|
||||
borderLeftWidth: DDS.isTab ? 1 : 0,
|
||||
borderLeftColor: DDS.isTab
|
||||
? colors.secondary.background
|
||||
: "transparent",
|
||||
paddingBottom:
|
||||
Platform.OS === "android" ? insets.bottom + 10 : insets.bottom
|
||||
}}
|
||||
style={[
|
||||
{
|
||||
width: isFullscreen
|
||||
? dimensions.width
|
||||
: widths[
|
||||
!introCompleted ? "mobile" : (deviceMode as keyof PaneWidths)
|
||||
]?.editor,
|
||||
height: "100%",
|
||||
minHeight: "100%",
|
||||
backgroundColor: toolBarColors.primary.background,
|
||||
paddingLeft: isFullscreen
|
||||
? deviceMode === "smallTablet"
|
||||
? 0
|
||||
: dimensions.width * 0.15
|
||||
: null,
|
||||
paddingRight: isFullscreen
|
||||
? deviceMode === "smallTablet"
|
||||
? 0
|
||||
: dimensions.width * 0.15
|
||||
: insets.right,
|
||||
borderLeftWidth: DDS.isTab ? 1 : 0,
|
||||
borderLeftColor: DDS.isTab
|
||||
? colors.secondary.background
|
||||
: "transparent",
|
||||
paddingBottom: insets.bottom
|
||||
}
|
||||
]}
|
||||
>
|
||||
{loading || !introCompleted ? null : (
|
||||
<KeyboardAvoidingView
|
||||
|
||||
@@ -35,6 +35,10 @@ import { useTagStore } from "../stores/use-tag-store";
|
||||
import { eUpdateNoteInEditor } from "./events";
|
||||
import { unlockVault } from "./unlock-vault";
|
||||
|
||||
export const valueLimiter = (value: number, min: number, max: number) => {
|
||||
return value < min ? min : value > max ? max : value;
|
||||
};
|
||||
|
||||
export function getObfuscatedEmail(email: string) {
|
||||
if (!email) return "";
|
||||
const [username, provider] = email.split("@");
|
||||
|
||||
Reference in New Issue
Block a user