mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-22 22:49:45 +01:00
mobile: editor ui overhaul
This commit is contained in:
@@ -21,13 +21,14 @@ import { useThemeColors } from "@notesnook/theme";
|
||||
import React from "react";
|
||||
import { View } from "react-native";
|
||||
import { FlatList } from "react-native-actions-sheet";
|
||||
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||
import { db } from "../../common/database";
|
||||
import { DDS } from "../../services/device-detection";
|
||||
import { eSendEvent, presentSheet } from "../../services/event-manager";
|
||||
import { ColorValues } from "../../utils/colors";
|
||||
import { eOnLoadNote } from "../../utils/events";
|
||||
import { fluidTabsRef } from "../../utils/global-refs";
|
||||
import { AppFontSize } from "../../utils/size";
|
||||
import { DefaultAppStyles } from "../../utils/styles";
|
||||
import SheetProvider from "../sheet-provider";
|
||||
import { IconButton } from "../ui/icon-button";
|
||||
import { Pressable } from "../ui/pressable";
|
||||
@@ -38,8 +39,6 @@ import { DateMeta } from "./date-meta";
|
||||
import { Items } from "./items";
|
||||
import Notebooks from "./notebooks";
|
||||
import { TagStrip, Tags } from "./tags";
|
||||
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||
import { DefaultAppStyles } from "../../utils/styles";
|
||||
|
||||
const Line = ({ top = 6, bottom = 6 }) => {
|
||||
const { colors } = useThemeColors();
|
||||
|
||||
@@ -29,6 +29,10 @@ import { ColorTags } from "./color-tags";
|
||||
import { strings } from "@notesnook/intl";
|
||||
import { DefaultAppStyles } from "../../utils/styles";
|
||||
import ManageTags from "../../screens/manage-tags";
|
||||
import {
|
||||
paddingTop,
|
||||
paddingVertical
|
||||
} from "deprecated-react-native-prop-types/DeprecatedLayoutPropTypes";
|
||||
|
||||
export const Tags = ({ item, close }) => {
|
||||
const { colors } = useThemeColors();
|
||||
@@ -86,7 +90,6 @@ export const TagStrip = ({ item, close }) => {
|
||||
flexDirection: "row",
|
||||
flexWrap: "wrap",
|
||||
alignItems: "center",
|
||||
marginTop: DefaultAppStyles.GAP_VERTICAL,
|
||||
gap: 5
|
||||
}}
|
||||
>
|
||||
@@ -107,16 +110,13 @@ const TagItem = ({ tag, close }) => {
|
||||
|
||||
const style = {
|
||||
paddingHorizontal: 0,
|
||||
borderRadius: 100,
|
||||
marginTop: 0,
|
||||
backgroundColor: "transparent"
|
||||
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL
|
||||
};
|
||||
return (
|
||||
<Button
|
||||
onPress={onPress}
|
||||
title={"#" + tag.title}
|
||||
type="plain"
|
||||
height={20}
|
||||
fontSize={AppFontSize.xs}
|
||||
style={style}
|
||||
textStyle={{
|
||||
|
||||
@@ -89,10 +89,10 @@ function getSize() {
|
||||
xs: normalize(13.5) * scale.fontScale,
|
||||
sm: normalize(14.5) * scale.fontScale,
|
||||
md: normalize(16.5) * scale.fontScale,
|
||||
lg: normalize(22) * scale.fontScale,
|
||||
xl: normalize(24) * scale.fontScale,
|
||||
xxl: normalize(28) * scale.fontScale,
|
||||
xxxl: normalize(32) * scale.fontScale
|
||||
lg: normalize(20) * scale.fontScale,
|
||||
xl: normalize(22) * scale.fontScale,
|
||||
xxl: normalize(25) * scale.fontScale,
|
||||
xxxl: normalize(30) * scale.fontScale
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
325
apps/mobile/package-lock.json
generated
325
apps/mobile/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -33,6 +33,10 @@
|
||||
color: var(--nn_primary_placeholder) !important;
|
||||
}
|
||||
|
||||
.main-editor *:first-child {
|
||||
margin-top: 0.5em !important;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
|
||||
@@ -558,12 +558,28 @@ const Tiptap = ({
|
||||
height: "100%",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
position: "relative"
|
||||
position: "relative",
|
||||
paddingTop: "12px"
|
||||
}}
|
||||
>
|
||||
{settings.noHeader || tab.session?.locked ? null : (
|
||||
<>
|
||||
<div
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
padding: "0px 16px"
|
||||
}}
|
||||
>
|
||||
<Tags settings={settings} loading={controller.loading} />
|
||||
<StatusBar
|
||||
container={containerRef}
|
||||
loading={controller.loading}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Title
|
||||
titlePlaceholder={controller.titlePlaceholder}
|
||||
readonly={settings.readonly}
|
||||
@@ -574,11 +590,6 @@ const Tiptap = ({
|
||||
timeFormat={settings.timeFormat}
|
||||
loading={controller.loading}
|
||||
/>
|
||||
|
||||
<StatusBar
|
||||
container={containerRef}
|
||||
loading={controller.loading}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -918,7 +929,7 @@ const TiptapProvider = (): JSX.Element => {
|
||||
editorContainer.classList.add("selectable", "main-editor", "searching");
|
||||
editorContainer.style.flex = "1";
|
||||
editorContainer.style.cursor = "text";
|
||||
editorContainer.style.padding = "0px 12px";
|
||||
editorContainer.style.padding = "0px 16px";
|
||||
editorContainer.style.color = colors.primary.paragraph;
|
||||
editorContainer.style.fontSize = `${settings.fontSize}px`;
|
||||
editorContainer.style.fontFamily =
|
||||
|
||||
@@ -58,6 +58,43 @@ const MenuItem = (props: any) => (
|
||||
<MenuItemInner {...props} className={menuItemClassName} />
|
||||
);
|
||||
|
||||
const iconButtonStyle: React.CSSProperties = {
|
||||
borderWidth: 0,
|
||||
borderRadius: 100,
|
||||
color: "var(--nn_primary_icon)",
|
||||
width: 39,
|
||||
height: 39,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
position: "relative"
|
||||
};
|
||||
|
||||
function IconButton({
|
||||
onPress,
|
||||
children,
|
||||
fwdRef,
|
||||
style = {},
|
||||
preventDefault = false
|
||||
}: {
|
||||
onPress?: () => void;
|
||||
children: React.ReactNode;
|
||||
fwdRef?: any;
|
||||
style?: React.CSSProperties;
|
||||
preventDefault?: boolean;
|
||||
}) {
|
||||
return (
|
||||
<Button
|
||||
onPress={onPress}
|
||||
fwdRef={fwdRef}
|
||||
preventDefault={preventDefault}
|
||||
style={{ ...iconButtonStyle, ...style }}
|
||||
>
|
||||
{children}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
const Button = ({
|
||||
onPress,
|
||||
children,
|
||||
@@ -120,7 +157,8 @@ function Header({
|
||||
backgroundColor: "var(--nn_primary_background)",
|
||||
position: "sticky",
|
||||
width: "100vw",
|
||||
zIndex: 999
|
||||
zIndex: 999,
|
||||
borderBottom: "0.5px solid var(--nn_primary_separator)"
|
||||
}}
|
||||
>
|
||||
{noHeader ? null : (
|
||||
@@ -132,51 +170,39 @@ function Header({
|
||||
flexDirection: "row",
|
||||
paddingTop: insets.top,
|
||||
height: 50,
|
||||
alignItems: "center"
|
||||
alignItems: "center",
|
||||
paddingLeft: 12,
|
||||
paddingRight: 16
|
||||
}}
|
||||
id="header"
|
||||
>
|
||||
{settings.deviceMode !== "mobile" && !settings.fullscreen ? (
|
||||
<div />
|
||||
) : (
|
||||
<Button
|
||||
<IconButton
|
||||
onPress={() => {
|
||||
post(EditorEvents.back, undefined, tab.id, tab.session?.noteId);
|
||||
}}
|
||||
preventDefault={false}
|
||||
style={{
|
||||
borderWidth: 0,
|
||||
borderRadius: 100,
|
||||
color: "var(--nn_primary_icon)",
|
||||
marginLeft: 6,
|
||||
width: 40,
|
||||
height: 40,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
flexDirection: "column",
|
||||
position: "relative"
|
||||
}}
|
||||
style={{ width: 40, height: 40 }}
|
||||
>
|
||||
<ArrowBackIcon
|
||||
size={28 * settings.fontScale}
|
||||
style={{
|
||||
position: "absolute"
|
||||
}}
|
||||
size={25 * settings.fontScale}
|
||||
style={{ position: "absolute" }}
|
||||
color="var(--nn_primary_icon)"
|
||||
/>
|
||||
</Button>
|
||||
</IconButton>
|
||||
)}
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
flexDirection: "row"
|
||||
flexDirection: "row",
|
||||
gap: 8
|
||||
}}
|
||||
>
|
||||
{settings.deviceMode !== "mobile" && !settings.fullscreen ? (
|
||||
<Button
|
||||
<IconButton
|
||||
onPress={() => {
|
||||
post(
|
||||
EditorEvents.fullscreen,
|
||||
@@ -185,32 +211,17 @@ function Header({
|
||||
tab.session?.noteId
|
||||
);
|
||||
}}
|
||||
preventDefault={false}
|
||||
style={{
|
||||
borderWidth: 0,
|
||||
borderRadius: 100,
|
||||
color: "var(--nn_primary_icon)",
|
||||
marginRight: 10,
|
||||
width: 39,
|
||||
height: 39,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
<FullscreenIcon
|
||||
size={25 * settings.fontScale}
|
||||
style={{
|
||||
position: "absolute"
|
||||
}}
|
||||
style={{ position: "absolute" }}
|
||||
color="var(--nn_primary_icon)"
|
||||
/>
|
||||
</Button>
|
||||
</IconButton>
|
||||
) : null}
|
||||
|
||||
{tab.session?.readonly ? (
|
||||
<Button
|
||||
<IconButton
|
||||
onPress={() => {
|
||||
post(
|
||||
"editor-events:disable-readonly-mode",
|
||||
@@ -218,46 +229,20 @@ function Header({
|
||||
);
|
||||
}}
|
||||
fwdRef={btnRef}
|
||||
preventDefault={false}
|
||||
style={{
|
||||
borderWidth: 0,
|
||||
borderRadius: 100,
|
||||
color: "var(--nn_primary_accent)",
|
||||
marginRight: 12,
|
||||
width: 39,
|
||||
height: 39,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
position: "relative"
|
||||
}}
|
||||
style={{ color: "var(--nn_primary_accent)" }}
|
||||
>
|
||||
<PencilLockIcon
|
||||
size={25 * settings.fontScale}
|
||||
style={{
|
||||
position: "absolute"
|
||||
}}
|
||||
style={{ position: "absolute" }}
|
||||
color="var(--nn_primary_accent)"
|
||||
/>
|
||||
</Button>
|
||||
</IconButton>
|
||||
) : null}
|
||||
|
||||
<Button
|
||||
<IconButton
|
||||
onPress={() => {
|
||||
editor?.commands.undo();
|
||||
}}
|
||||
style={{
|
||||
borderWidth: 0,
|
||||
borderRadius: 100,
|
||||
color: "var(--nn_primary_icon)",
|
||||
marginRight: 10,
|
||||
width: 39,
|
||||
height: 39,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
<ArrowULeftTopIcon
|
||||
color={
|
||||
@@ -266,28 +251,14 @@ function Header({
|
||||
: "var(--nn_primary_icon)"
|
||||
}
|
||||
size={25 * settings.fontScale}
|
||||
style={{
|
||||
position: "absolute"
|
||||
}}
|
||||
style={{ position: "absolute" }}
|
||||
/>
|
||||
</Button>
|
||||
</IconButton>
|
||||
|
||||
<Button
|
||||
<IconButton
|
||||
onPress={() => {
|
||||
editor?.commands.redo();
|
||||
}}
|
||||
style={{
|
||||
borderWidth: 0,
|
||||
borderRadius: 100,
|
||||
color: "var(--nn_primary_icon)",
|
||||
marginRight: 10,
|
||||
width: 39,
|
||||
height: 39,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
<ArrowURightTopIcon
|
||||
color={
|
||||
@@ -296,13 +267,11 @@ function Header({
|
||||
: "var(--nn_primary_icon)"
|
||||
}
|
||||
size={25 * settings.fontScale}
|
||||
style={{
|
||||
position: "absolute"
|
||||
}}
|
||||
style={{ position: "absolute" }}
|
||||
/>
|
||||
</Button>
|
||||
</IconButton>
|
||||
|
||||
<Button
|
||||
<IconButton
|
||||
onPress={() => {
|
||||
post(
|
||||
EditorEvents.showTabs,
|
||||
@@ -311,26 +280,13 @@ function Header({
|
||||
tab.session?.noteId
|
||||
);
|
||||
}}
|
||||
preventDefault={false}
|
||||
style={{
|
||||
borderWidth: 0,
|
||||
borderRadius: 100,
|
||||
color: "var(--nn_primary_icon)",
|
||||
marginRight: 12,
|
||||
width: 39,
|
||||
height: 39,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
border: "2px solid var(--nn_primary_icon)",
|
||||
width: 19 * settings.fontScale,
|
||||
height: 19 * settings.fontScale,
|
||||
minWidth: 19 * settings.fontScale,
|
||||
width: 17 * settings.fontScale,
|
||||
height: 17 * settings.fontScale,
|
||||
minWidth: 17 * settings.fontScale,
|
||||
borderRadius: 5,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
@@ -348,9 +304,9 @@ function Header({
|
||||
{openedTabsCount}
|
||||
</p>
|
||||
</div>
|
||||
</Button>
|
||||
</IconButton>
|
||||
|
||||
<Button
|
||||
<IconButton
|
||||
fwdRef={btnRef}
|
||||
onPress={() => {
|
||||
if (tab.session?.locked) {
|
||||
@@ -364,38 +320,21 @@ function Header({
|
||||
setOpen(!isOpen);
|
||||
}
|
||||
}}
|
||||
preventDefault={false}
|
||||
style={{
|
||||
borderWidth: 0,
|
||||
borderRadius: 100,
|
||||
color: "var(--nn_primary_icon)",
|
||||
marginRight: 12,
|
||||
width: 39,
|
||||
height: 39,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
{tab.session?.locked ? (
|
||||
<DotsHorizontalIcon
|
||||
size={25 * settings.fontScale}
|
||||
style={{
|
||||
position: "absolute"
|
||||
}}
|
||||
style={{ position: "absolute" }}
|
||||
color="var(--nn_primary_icon)"
|
||||
/>
|
||||
) : (
|
||||
<DotsVerticalIcon
|
||||
size={25 * settings.fontScale}
|
||||
style={{
|
||||
position: "absolute"
|
||||
}}
|
||||
style={{ position: "absolute" }}
|
||||
color="var(--nn_primary_icon)"
|
||||
/>
|
||||
)}
|
||||
</Button>
|
||||
</IconButton>
|
||||
|
||||
<ControlledMenu
|
||||
align="end"
|
||||
@@ -470,7 +409,7 @@ function Header({
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
gap: 10,
|
||||
gap: 8,
|
||||
alignItems: "center",
|
||||
flexDirection: "row",
|
||||
justifyContent: "center",
|
||||
@@ -478,7 +417,7 @@ function Header({
|
||||
paddingTop: 5
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
<IconButton
|
||||
onPress={() => {
|
||||
post(
|
||||
EditorEvents.goBack,
|
||||
@@ -488,17 +427,6 @@ function Header({
|
||||
);
|
||||
setOpen(false);
|
||||
}}
|
||||
style={{
|
||||
borderWidth: 0,
|
||||
borderRadius: 100,
|
||||
color: "var(--nn_primary_icon)",
|
||||
width: 39,
|
||||
height: 39,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
<ArrowBackIcon
|
||||
color={
|
||||
@@ -507,13 +435,11 @@ function Header({
|
||||
: "var(--nn_primary_icon)"
|
||||
}
|
||||
size={25 * settings.fontScale}
|
||||
style={{
|
||||
position: "absolute"
|
||||
}}
|
||||
style={{ position: "absolute" }}
|
||||
/>
|
||||
</Button>
|
||||
</IconButton>
|
||||
|
||||
<Button
|
||||
<IconButton
|
||||
onPress={() => {
|
||||
post(
|
||||
EditorEvents.goForward,
|
||||
@@ -523,17 +449,6 @@ function Header({
|
||||
);
|
||||
setOpen(false);
|
||||
}}
|
||||
style={{
|
||||
borderWidth: 0,
|
||||
borderRadius: 100,
|
||||
color: "var(--nn_primary_icon)",
|
||||
width: 39,
|
||||
height: 39,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
<ArrowForwardIcon
|
||||
color={
|
||||
@@ -542,37 +457,22 @@ function Header({
|
||||
: "var(--nn_primary_icon)"
|
||||
}
|
||||
size={25 * settings.fontScale}
|
||||
style={{
|
||||
position: "absolute"
|
||||
}}
|
||||
style={{ position: "absolute" }}
|
||||
/>
|
||||
</Button>
|
||||
</IconButton>
|
||||
|
||||
<Button
|
||||
<IconButton
|
||||
onPress={() => {
|
||||
editor?.commands.startSearch();
|
||||
setOpen(false);
|
||||
}}
|
||||
style={{
|
||||
borderWidth: 0,
|
||||
borderRadius: 100,
|
||||
color: "var(--nn_primary_icon)",
|
||||
width: 39,
|
||||
height: 39,
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
position: "relative"
|
||||
}}
|
||||
>
|
||||
<MagnifyIcon
|
||||
size={28 * settings.fontScale}
|
||||
style={{
|
||||
position: "absolute"
|
||||
}}
|
||||
size={25 * settings.fontScale}
|
||||
style={{ position: "absolute" }}
|
||||
color="var(--nn_primary_icon)"
|
||||
/>
|
||||
</Button>
|
||||
</IconButton>
|
||||
</div>
|
||||
|
||||
<MenuItem
|
||||
@@ -584,7 +484,7 @@ function Header({
|
||||
}}
|
||||
>
|
||||
<PlusIcon
|
||||
size={22 * settings.fontScale}
|
||||
size={20 * settings.fontScale}
|
||||
color="var(--nn_primary_icon)"
|
||||
/>
|
||||
<span
|
||||
@@ -605,7 +505,7 @@ function Header({
|
||||
}}
|
||||
>
|
||||
<TableOfContentsIcon
|
||||
size={22 * settings.fontScale}
|
||||
size={20 * settings.fontScale}
|
||||
color="var(--nn_primary_icon)"
|
||||
/>
|
||||
<span
|
||||
@@ -625,7 +525,7 @@ function Header({
|
||||
}}
|
||||
>
|
||||
<ArrowTopIcon
|
||||
size={22 * settings.fontScale}
|
||||
size={20 * settings.fontScale}
|
||||
color="var(--nn_primary_icon)"
|
||||
/>
|
||||
<span
|
||||
@@ -646,7 +546,7 @@ function Header({
|
||||
}}
|
||||
>
|
||||
<ArrowDownIcon
|
||||
size={22 * settings.fontScale}
|
||||
size={20 * settings.fontScale}
|
||||
color="var(--nn_primary_icon)"
|
||||
/>
|
||||
<span
|
||||
@@ -666,7 +566,7 @@ function Header({
|
||||
}}
|
||||
>
|
||||
<DotsHorizontalIcon
|
||||
size={22 * settings.fontScale}
|
||||
size={20 * settings.fontScale}
|
||||
color="var(--nn_primary_icon)"
|
||||
/>
|
||||
<span
|
||||
|
||||
@@ -29,19 +29,13 @@ function StatusBar({
|
||||
container: RefObject<HTMLDivElement>;
|
||||
loading?: boolean;
|
||||
}) {
|
||||
const [status, setStatus] = useState({
|
||||
date: "",
|
||||
saved: ""
|
||||
});
|
||||
const tab = useTabContext();
|
||||
const [sticky, setSticky] = useState(false);
|
||||
const stickyRef = useRef(false);
|
||||
const prevScroll = useRef(0);
|
||||
const lastStickyChangeTime = useRef(0);
|
||||
const [showChars, setShowChars] = useState(false);
|
||||
const [words, setWords] = useState(strings.totalWords(0));
|
||||
const currentWords = useRef(words);
|
||||
const [chars, setChars] = useState(0);
|
||||
const statusBar = useRef({
|
||||
set: setStatus,
|
||||
set: () => {},
|
||||
updateWords: () => {
|
||||
const editor = editors[tab.id];
|
||||
if (!editor) return;
|
||||
@@ -57,110 +51,44 @@ function StatusBar({
|
||||
|
||||
useEffect(() => {
|
||||
globalThis.statusBars[tab.id] = statusBar;
|
||||
if (showChars) {
|
||||
editors[tab.id]?.on("selectionUpdate", (event) => {
|
||||
setChars(event.editor.extensionStorage.characterCount.characters());
|
||||
});
|
||||
}
|
||||
if (editors[tab.id]) {
|
||||
setChars(
|
||||
editors[tab.id]?.extensionStorage.characterCount.characters() || 0
|
||||
);
|
||||
}
|
||||
|
||||
return () => {
|
||||
globalThis.statusBars[tab.id] = undefined;
|
||||
};
|
||||
}, [tab.id, statusBar]);
|
||||
|
||||
const scrollState = useRef({
|
||||
isMovingUp: false,
|
||||
startingOffset: 0
|
||||
});
|
||||
const onScroll = React.useCallback((event: Event) => {
|
||||
const currentOffset = (event.target as HTMLElement)?.scrollTop;
|
||||
if (currentOffset < 200) {
|
||||
if (stickyRef.current) {
|
||||
stickyRef.current = false;
|
||||
setSticky(false);
|
||||
lastStickyChangeTime.current = Date.now();
|
||||
prevScroll.current = currentOffset;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (Date.now() - lastStickyChangeTime.current < 300) return;
|
||||
if (currentOffset > prevScroll.current) {
|
||||
if (
|
||||
!scrollState.current.startingOffset ||
|
||||
scrollState.current.isMovingUp
|
||||
) {
|
||||
scrollState.current.startingOffset = currentOffset;
|
||||
}
|
||||
scrollState.current.isMovingUp = false;
|
||||
} else {
|
||||
if (
|
||||
!scrollState.current.startingOffset ||
|
||||
!scrollState.current.isMovingUp
|
||||
) {
|
||||
scrollState.current.startingOffset = currentOffset;
|
||||
}
|
||||
scrollState.current.isMovingUp = true;
|
||||
}
|
||||
|
||||
if (scrollState.current.isMovingUp) {
|
||||
if (currentOffset < scrollState.current.startingOffset - 50) {
|
||||
if (!stickyRef.current) {
|
||||
stickyRef.current = true;
|
||||
setSticky(true);
|
||||
}
|
||||
scrollState.current.startingOffset = 0;
|
||||
}
|
||||
} else {
|
||||
if (currentOffset > scrollState.current.startingOffset + 50) {
|
||||
if (stickyRef.current) {
|
||||
stickyRef.current = false;
|
||||
setSticky(false);
|
||||
}
|
||||
scrollState.current.startingOffset = 0;
|
||||
}
|
||||
}
|
||||
lastStickyChangeTime.current = Date.now();
|
||||
prevScroll.current = currentOffset;
|
||||
}, []);
|
||||
}, [tab.id, statusBar, showChars]);
|
||||
|
||||
useEffect(() => {
|
||||
currentWords.current = words;
|
||||
}, [words]);
|
||||
|
||||
useEffect(() => {
|
||||
const node = container.current;
|
||||
node?.addEventListener("scroll", onScroll);
|
||||
return () => {
|
||||
node?.removeEventListener("scroll", onScroll);
|
||||
};
|
||||
}, [onScroll, container]);
|
||||
|
||||
const paragraphStyle: React.CSSProperties = {
|
||||
marginTop: 0,
|
||||
marginBottom: 0,
|
||||
fontSize: "12px",
|
||||
fontSize: 12,
|
||||
color: "var(--nn_secondary_paragraph)",
|
||||
marginRight: 8,
|
||||
paddingBottom: 0,
|
||||
userSelect: "none",
|
||||
pointerEvents: "none"
|
||||
userSelect: "none"
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
display: loading ? "none" : "flex",
|
||||
paddingRight: 12,
|
||||
paddingLeft: 12,
|
||||
position: sticky ? "sticky" : "relative",
|
||||
top: -3,
|
||||
backgroundColor: "var(--nn_primary_background)",
|
||||
zIndex: 10,
|
||||
justifyContent: sticky ? "center" : "flex-start",
|
||||
paddingTop: 4,
|
||||
paddingBottom: 2
|
||||
<p
|
||||
onMouseDown={(e) => {
|
||||
setShowChars(!showChars);
|
||||
}}
|
||||
id="statusbar"
|
||||
style={paragraphStyle}
|
||||
>
|
||||
<p style={paragraphStyle}>{words}</p>
|
||||
<p style={paragraphStyle}>{status.date}</p>
|
||||
<p style={paragraphStyle}>{status.saved}</p>
|
||||
</div>
|
||||
{showChars ? strings.characters(chars) : words}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,14 +50,15 @@
|
||||
z-index: 999;
|
||||
list-style: none;
|
||||
user-select: none;
|
||||
padding: 0px;
|
||||
font-family: sans-serif;
|
||||
font-size: 0.95em;
|
||||
border: 1px solid var(--nn_primary_border);
|
||||
box-shadow: 1px 1px 20px 1px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 6px;
|
||||
border-radius: 8px;
|
||||
background-color: var(--nn_secondary_background);
|
||||
min-width: 12rem;
|
||||
min-width: 13rem;
|
||||
padding: 0 !important;
|
||||
|
||||
}
|
||||
|
||||
.menuOpening {
|
||||
@@ -73,10 +74,11 @@
|
||||
.menuItem {
|
||||
cursor: pointer;
|
||||
border-radius: 0;
|
||||
padding: 1rem 0.6rem !important;
|
||||
padding: 0.5rem 0.6rem !important;
|
||||
color: var(--nn_primary_paragraph);
|
||||
font-family: "Inter";
|
||||
padding: 12px 6px;
|
||||
font-size: 0.9em;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
.menuItemHover {
|
||||
|
||||
@@ -22,7 +22,6 @@ import { Settings } from "../utils";
|
||||
import { EditorEvents } from "../utils/editor-events";
|
||||
import styles from "./styles.module.css";
|
||||
import { useTabContext } from "../hooks/useTabStore";
|
||||
import { strings } from "@notesnook/intl";
|
||||
|
||||
function Tags(props: { settings: Settings; loading?: boolean }): JSX.Element {
|
||||
const [tags, setTags] = useState<
|
||||
@@ -54,80 +53,32 @@ function Tags(props: { settings: Settings; loading?: boolean }): JSX.Element {
|
||||
<div
|
||||
className={styles.container}
|
||||
style={{
|
||||
padding: "0px 12px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
overflowX: "scroll",
|
||||
minHeight: "40px",
|
||||
opacity: props.loading ? 0 : 1
|
||||
opacity: props.loading ? 0 : 1,
|
||||
gap: 6
|
||||
}}
|
||||
>
|
||||
<button
|
||||
className={styles.btn}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
openManageTagsSheet();
|
||||
}}
|
||||
style={{
|
||||
border: `1px solid var(--nn_primary_border)`,
|
||||
backgroundColor: "var(--nn_secondary_background)",
|
||||
marginRight: 5,
|
||||
borderRadius: 100,
|
||||
padding: "0px 10px",
|
||||
fontFamily: "Inter",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
height: "30px",
|
||||
userSelect: "none",
|
||||
WebkitUserSelect: "none"
|
||||
}}
|
||||
>
|
||||
{tags.length === 0 ? (
|
||||
<p
|
||||
style={{
|
||||
marginRight: 4,
|
||||
fontSize: 13,
|
||||
color: "var(--nn_primary_icon)",
|
||||
userSelect: "none"
|
||||
}}
|
||||
>
|
||||
{strings.addATag()}
|
||||
</p>
|
||||
) : null}
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
version="1.1"
|
||||
width={20 * fontScale}
|
||||
height={20 * fontScale}
|
||||
viewBox={`0 0 24 24`}
|
||||
>
|
||||
<path
|
||||
fill="var(--nn_primary_accent)"
|
||||
d="M19,13H13V19H11V13H5V11H11V5H13V11H19V13Z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
{tags.map((tag) => (
|
||||
<button
|
||||
key={tag.title}
|
||||
className={styles.btn}
|
||||
style={{
|
||||
border: "1px solid var(--nn_primary_border)",
|
||||
backgroundColor: "var(--nn_secondary_background)",
|
||||
marginRight: 5,
|
||||
borderRadius: 100,
|
||||
padding: "0px 10px",
|
||||
height: "30px",
|
||||
borderRadius: 6,
|
||||
padding: "0px 4px",
|
||||
height: "24px",
|
||||
fontFamily: "Inter",
|
||||
fontSize: 13,
|
||||
fontSize: 12,
|
||||
color: "var(--nn_primary_icon)",
|
||||
userSelect: "none",
|
||||
WebkitUserSelect: "none"
|
||||
}}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
post(EditorEvents.tag, tag, tab.id, tab.session?.noteId);
|
||||
openManageTagsSheet();
|
||||
}}
|
||||
>
|
||||
#{tag.alias}
|
||||
|
||||
@@ -49,9 +49,9 @@ function Title({
|
||||
if (!titleSizeDiv.current || !titleRef.current) return;
|
||||
titleSizeDiv.current.innerText = titleRef.current.value;
|
||||
titleRef.current.style.height = `${titleSizeDiv.current.clientHeight}px`;
|
||||
titleRef.current.style.minHeight = `${titleSizeDiv.current.clientHeight}px`;
|
||||
titleSizeDiv.current.style.width = `${titleRef.current.clientWidth}px`;
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (titleRef.current) {
|
||||
titleRef.current.value = title;
|
||||
@@ -88,8 +88,8 @@ function Title({
|
||||
maxWidth: "100%",
|
||||
minHeight: 40,
|
||||
opacity: 0,
|
||||
paddingRight: 10,
|
||||
paddingLeft: 10,
|
||||
paddingRight: 16,
|
||||
paddingLeft: 16,
|
||||
fontWeight: 600,
|
||||
fontFamily: getFontById(fontFamily)?.font || "Inter",
|
||||
boxSizing: "border-box",
|
||||
@@ -119,8 +119,8 @@ function Title({
|
||||
boxSizing: "border-box",
|
||||
border: 0,
|
||||
opacity: 1,
|
||||
paddingRight: 10,
|
||||
paddingLeft: 10,
|
||||
paddingRight: 16,
|
||||
paddingLeft: 16,
|
||||
fontWeight: 600,
|
||||
fontFamily: getFontById(fontFamily)?.font || "Inter",
|
||||
backgroundColor: "transparent",
|
||||
|
||||
@@ -491,6 +491,10 @@ msgstr "{count, plural, one {Unpublish item} other {Unpublish # items}}"
|
||||
msgid "{count, plural, one {Unpublish note} other {Unpublish # notes}}"
|
||||
msgstr "{count, plural, one {Unpublish note} other {Unpublish # notes}}"
|
||||
|
||||
#: src/strings.ts:2492
|
||||
msgid "{count} characters"
|
||||
msgstr "{count} characters"
|
||||
|
||||
#: src/strings.ts:1563
|
||||
msgid "{days, plural, one {1 day} other {# days}}"
|
||||
msgstr "{days, plural, one {1 day} other {# days}}"
|
||||
|
||||
@@ -491,6 +491,10 @@ msgstr ""
|
||||
msgid "{count, plural, one {Unpublish note} other {Unpublish # notes}}"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:2492
|
||||
msgid "{count} characters"
|
||||
msgstr ""
|
||||
|
||||
#: src/strings.ts:1563
|
||||
msgid "{days, plural, one {1 day} other {# days}}"
|
||||
msgstr ""
|
||||
|
||||
@@ -2488,5 +2488,6 @@ Use this if changes from other devices are not appearing on this device. This wi
|
||||
t`Select a notebook to move this notebook into, or unselect to move it to the root level.`,
|
||||
noNotebooksSelectedToMove: () => t`No notebooks selected to move`,
|
||||
scrollToTop: () => t`Scroll to top`,
|
||||
scrollToBottom: () => t`Scroll to bottom`
|
||||
scrollToBottom: () => t`Scroll to bottom`,
|
||||
characters: (count: number) => t`${count} characters`
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user