mobile: editor ui overhaul

This commit is contained in:
Ammar Ahmed
2025-09-11 15:49:00 +05:00
parent b841c6e0eb
commit 4c97b3481d
14 changed files with 350 additions and 521 deletions

View File

@@ -21,13 +21,14 @@ import { useThemeColors } from "@notesnook/theme";
import React from "react"; import React from "react";
import { View } from "react-native"; import { View } from "react-native";
import { FlatList } from "react-native-actions-sheet"; import { FlatList } from "react-native-actions-sheet";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
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 { eOnLoadNote } from "../../utils/events"; import { eOnLoadNote } from "../../utils/events";
import { fluidTabsRef } from "../../utils/global-refs"; import { fluidTabsRef } from "../../utils/global-refs";
import { AppFontSize } from "../../utils/size"; import { AppFontSize } from "../../utils/size";
import { DefaultAppStyles } from "../../utils/styles";
import SheetProvider from "../sheet-provider"; import SheetProvider from "../sheet-provider";
import { IconButton } from "../ui/icon-button"; import { IconButton } from "../ui/icon-button";
import { Pressable } from "../ui/pressable"; import { Pressable } from "../ui/pressable";
@@ -38,8 +39,6 @@ import { DateMeta } from "./date-meta";
import { Items } from "./items"; import { Items } from "./items";
import Notebooks from "./notebooks"; import Notebooks from "./notebooks";
import { TagStrip, Tags } from "./tags"; 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 Line = ({ top = 6, bottom = 6 }) => {
const { colors } = useThemeColors(); const { colors } = useThemeColors();

View File

@@ -29,6 +29,10 @@ import { ColorTags } from "./color-tags";
import { strings } from "@notesnook/intl"; import { strings } from "@notesnook/intl";
import { DefaultAppStyles } from "../../utils/styles"; import { DefaultAppStyles } from "../../utils/styles";
import ManageTags from "../../screens/manage-tags"; import ManageTags from "../../screens/manage-tags";
import {
paddingTop,
paddingVertical
} from "deprecated-react-native-prop-types/DeprecatedLayoutPropTypes";
export const Tags = ({ item, close }) => { export const Tags = ({ item, close }) => {
const { colors } = useThemeColors(); const { colors } = useThemeColors();
@@ -86,7 +90,6 @@ export const TagStrip = ({ item, close }) => {
flexDirection: "row", flexDirection: "row",
flexWrap: "wrap", flexWrap: "wrap",
alignItems: "center", alignItems: "center",
marginTop: DefaultAppStyles.GAP_VERTICAL,
gap: 5 gap: 5
}} }}
> >
@@ -107,16 +110,13 @@ const TagItem = ({ tag, close }) => {
const style = { const style = {
paddingHorizontal: 0, paddingHorizontal: 0,
borderRadius: 100, paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL
marginTop: 0,
backgroundColor: "transparent"
}; };
return ( return (
<Button <Button
onPress={onPress} onPress={onPress}
title={"#" + tag.title} title={"#" + tag.title}
type="plain" type="plain"
height={20}
fontSize={AppFontSize.xs} fontSize={AppFontSize.xs}
style={style} style={style}
textStyle={{ textStyle={{

View File

@@ -89,10 +89,10 @@ function getSize() {
xs: normalize(13.5) * scale.fontScale, xs: normalize(13.5) * scale.fontScale,
sm: normalize(14.5) * scale.fontScale, sm: normalize(14.5) * scale.fontScale,
md: normalize(16.5) * scale.fontScale, md: normalize(16.5) * scale.fontScale,
lg: normalize(22) * scale.fontScale, lg: normalize(20) * scale.fontScale,
xl: normalize(24) * scale.fontScale, xl: normalize(22) * scale.fontScale,
xxl: normalize(28) * scale.fontScale, xxl: normalize(25) * scale.fontScale,
xxxl: normalize(32) * scale.fontScale xxxl: normalize(30) * scale.fontScale
}; };
} }

File diff suppressed because it is too large Load Diff

View File

@@ -33,6 +33,10 @@
color: var(--nn_primary_placeholder) !important; color: var(--nn_primary_placeholder) !important;
} }
.main-editor *:first-child {
margin-top: 0.5em !important;
}
#root { #root {
height: 100%; height: 100%;
display: flex; display: flex;

View File

@@ -558,12 +558,28 @@ const Tiptap = ({
height: "100%", height: "100%",
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
position: "relative" position: "relative",
paddingTop: "12px"
}} }}
> >
{settings.noHeader || tab.session?.locked ? null : ( {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} /> <Tags settings={settings} loading={controller.loading} />
<StatusBar
container={containerRef}
loading={controller.loading}
/>
</div>
<Title <Title
titlePlaceholder={controller.titlePlaceholder} titlePlaceholder={controller.titlePlaceholder}
readonly={settings.readonly} readonly={settings.readonly}
@@ -574,11 +590,6 @@ const Tiptap = ({
timeFormat={settings.timeFormat} timeFormat={settings.timeFormat}
loading={controller.loading} 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.classList.add("selectable", "main-editor", "searching");
editorContainer.style.flex = "1"; editorContainer.style.flex = "1";
editorContainer.style.cursor = "text"; editorContainer.style.cursor = "text";
editorContainer.style.padding = "0px 12px"; editorContainer.style.padding = "0px 16px";
editorContainer.style.color = colors.primary.paragraph; editorContainer.style.color = colors.primary.paragraph;
editorContainer.style.fontSize = `${settings.fontSize}px`; editorContainer.style.fontSize = `${settings.fontSize}px`;
editorContainer.style.fontFamily = editorContainer.style.fontFamily =

View File

@@ -58,6 +58,43 @@ const MenuItem = (props: any) => (
<MenuItemInner {...props} className={menuItemClassName} /> <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 = ({ const Button = ({
onPress, onPress,
children, children,
@@ -120,7 +157,8 @@ function Header({
backgroundColor: "var(--nn_primary_background)", backgroundColor: "var(--nn_primary_background)",
position: "sticky", position: "sticky",
width: "100vw", width: "100vw",
zIndex: 999 zIndex: 999,
borderBottom: "0.5px solid var(--nn_primary_separator)"
}} }}
> >
{noHeader ? null : ( {noHeader ? null : (
@@ -132,51 +170,39 @@ function Header({
flexDirection: "row", flexDirection: "row",
paddingTop: insets.top, paddingTop: insets.top,
height: 50, height: 50,
alignItems: "center" alignItems: "center",
paddingLeft: 12,
paddingRight: 16
}} }}
id="header" id="header"
> >
{settings.deviceMode !== "mobile" && !settings.fullscreen ? ( {settings.deviceMode !== "mobile" && !settings.fullscreen ? (
<div /> <div />
) : ( ) : (
<Button <IconButton
onPress={() => { onPress={() => {
post(EditorEvents.back, undefined, tab.id, tab.session?.noteId); post(EditorEvents.back, undefined, tab.id, tab.session?.noteId);
}} }}
preventDefault={false} style={{ width: 40, height: 40 }}
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"
}}
> >
<ArrowBackIcon <ArrowBackIcon
size={28 * settings.fontScale} size={25 * settings.fontScale}
style={{ style={{ position: "absolute" }}
position: "absolute"
}}
color="var(--nn_primary_icon)" color="var(--nn_primary_icon)"
/> />
</Button> </IconButton>
)} )}
<div <div
style={{ style={{
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
flexDirection: "row" flexDirection: "row",
gap: 8
}} }}
> >
{settings.deviceMode !== "mobile" && !settings.fullscreen ? ( {settings.deviceMode !== "mobile" && !settings.fullscreen ? (
<Button <IconButton
onPress={() => { onPress={() => {
post( post(
EditorEvents.fullscreen, EditorEvents.fullscreen,
@@ -185,32 +211,17 @@ function Header({
tab.session?.noteId 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 <FullscreenIcon
size={25 * settings.fontScale} size={25 * settings.fontScale}
style={{ style={{ position: "absolute" }}
position: "absolute"
}}
color="var(--nn_primary_icon)" color="var(--nn_primary_icon)"
/> />
</Button> </IconButton>
) : null} ) : null}
{tab.session?.readonly ? ( {tab.session?.readonly ? (
<Button <IconButton
onPress={() => { onPress={() => {
post( post(
"editor-events:disable-readonly-mode", "editor-events:disable-readonly-mode",
@@ -218,46 +229,20 @@ function Header({
); );
}} }}
fwdRef={btnRef} fwdRef={btnRef}
preventDefault={false} style={{ color: "var(--nn_primary_accent)" }}
style={{
borderWidth: 0,
borderRadius: 100,
color: "var(--nn_primary_accent)",
marginRight: 12,
width: 39,
height: 39,
display: "flex",
justifyContent: "center",
alignItems: "center",
position: "relative"
}}
> >
<PencilLockIcon <PencilLockIcon
size={25 * settings.fontScale} size={25 * settings.fontScale}
style={{ style={{ position: "absolute" }}
position: "absolute"
}}
color="var(--nn_primary_accent)" color="var(--nn_primary_accent)"
/> />
</Button> </IconButton>
) : null} ) : null}
<Button <IconButton
onPress={() => { onPress={() => {
editor?.commands.undo(); 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 <ArrowULeftTopIcon
color={ color={
@@ -266,28 +251,14 @@ function Header({
: "var(--nn_primary_icon)" : "var(--nn_primary_icon)"
} }
size={25 * settings.fontScale} size={25 * settings.fontScale}
style={{ style={{ position: "absolute" }}
position: "absolute"
}}
/> />
</Button> </IconButton>
<Button <IconButton
onPress={() => { onPress={() => {
editor?.commands.redo(); 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 <ArrowURightTopIcon
color={ color={
@@ -296,13 +267,11 @@ function Header({
: "var(--nn_primary_icon)" : "var(--nn_primary_icon)"
} }
size={25 * settings.fontScale} size={25 * settings.fontScale}
style={{ style={{ position: "absolute" }}
position: "absolute"
}}
/> />
</Button> </IconButton>
<Button <IconButton
onPress={() => { onPress={() => {
post( post(
EditorEvents.showTabs, EditorEvents.showTabs,
@@ -311,26 +280,13 @@ function Header({
tab.session?.noteId 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 <div
style={{ style={{
border: "2px solid var(--nn_primary_icon)", border: "2px solid var(--nn_primary_icon)",
width: 19 * settings.fontScale, width: 17 * settings.fontScale,
height: 19 * settings.fontScale, height: 17 * settings.fontScale,
minWidth: 19 * settings.fontScale, minWidth: 17 * settings.fontScale,
borderRadius: 5, borderRadius: 5,
display: "flex", display: "flex",
justifyContent: "center", justifyContent: "center",
@@ -348,9 +304,9 @@ function Header({
{openedTabsCount} {openedTabsCount}
</p> </p>
</div> </div>
</Button> </IconButton>
<Button <IconButton
fwdRef={btnRef} fwdRef={btnRef}
onPress={() => { onPress={() => {
if (tab.session?.locked) { if (tab.session?.locked) {
@@ -364,38 +320,21 @@ function Header({
setOpen(!isOpen); 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 ? ( {tab.session?.locked ? (
<DotsHorizontalIcon <DotsHorizontalIcon
size={25 * settings.fontScale} size={25 * settings.fontScale}
style={{ style={{ position: "absolute" }}
position: "absolute"
}}
color="var(--nn_primary_icon)" color="var(--nn_primary_icon)"
/> />
) : ( ) : (
<DotsVerticalIcon <DotsVerticalIcon
size={25 * settings.fontScale} size={25 * settings.fontScale}
style={{ style={{ position: "absolute" }}
position: "absolute"
}}
color="var(--nn_primary_icon)" color="var(--nn_primary_icon)"
/> />
)} )}
</Button> </IconButton>
<ControlledMenu <ControlledMenu
align="end" align="end"
@@ -470,7 +409,7 @@ function Header({
<div <div
style={{ style={{
display: "flex", display: "flex",
gap: 10, gap: 8,
alignItems: "center", alignItems: "center",
flexDirection: "row", flexDirection: "row",
justifyContent: "center", justifyContent: "center",
@@ -478,7 +417,7 @@ function Header({
paddingTop: 5 paddingTop: 5
}} }}
> >
<Button <IconButton
onPress={() => { onPress={() => {
post( post(
EditorEvents.goBack, EditorEvents.goBack,
@@ -488,17 +427,6 @@ function Header({
); );
setOpen(false); 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 <ArrowBackIcon
color={ color={
@@ -507,13 +435,11 @@ function Header({
: "var(--nn_primary_icon)" : "var(--nn_primary_icon)"
} }
size={25 * settings.fontScale} size={25 * settings.fontScale}
style={{ style={{ position: "absolute" }}
position: "absolute"
}}
/> />
</Button> </IconButton>
<Button <IconButton
onPress={() => { onPress={() => {
post( post(
EditorEvents.goForward, EditorEvents.goForward,
@@ -523,17 +449,6 @@ function Header({
); );
setOpen(false); 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 <ArrowForwardIcon
color={ color={
@@ -542,37 +457,22 @@ function Header({
: "var(--nn_primary_icon)" : "var(--nn_primary_icon)"
} }
size={25 * settings.fontScale} size={25 * settings.fontScale}
style={{ style={{ position: "absolute" }}
position: "absolute"
}}
/> />
</Button> </IconButton>
<Button <IconButton
onPress={() => { onPress={() => {
editor?.commands.startSearch(); editor?.commands.startSearch();
setOpen(false); 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 <MagnifyIcon
size={28 * settings.fontScale} size={25 * settings.fontScale}
style={{ style={{ position: "absolute" }}
position: "absolute"
}}
color="var(--nn_primary_icon)" color="var(--nn_primary_icon)"
/> />
</Button> </IconButton>
</div> </div>
<MenuItem <MenuItem
@@ -584,7 +484,7 @@ function Header({
}} }}
> >
<PlusIcon <PlusIcon
size={22 * settings.fontScale} size={20 * settings.fontScale}
color="var(--nn_primary_icon)" color="var(--nn_primary_icon)"
/> />
<span <span
@@ -605,7 +505,7 @@ function Header({
}} }}
> >
<TableOfContentsIcon <TableOfContentsIcon
size={22 * settings.fontScale} size={20 * settings.fontScale}
color="var(--nn_primary_icon)" color="var(--nn_primary_icon)"
/> />
<span <span
@@ -625,7 +525,7 @@ function Header({
}} }}
> >
<ArrowTopIcon <ArrowTopIcon
size={22 * settings.fontScale} size={20 * settings.fontScale}
color="var(--nn_primary_icon)" color="var(--nn_primary_icon)"
/> />
<span <span
@@ -646,7 +546,7 @@ function Header({
}} }}
> >
<ArrowDownIcon <ArrowDownIcon
size={22 * settings.fontScale} size={20 * settings.fontScale}
color="var(--nn_primary_icon)" color="var(--nn_primary_icon)"
/> />
<span <span
@@ -666,7 +566,7 @@ function Header({
}} }}
> >
<DotsHorizontalIcon <DotsHorizontalIcon
size={22 * settings.fontScale} size={20 * settings.fontScale}
color="var(--nn_primary_icon)" color="var(--nn_primary_icon)"
/> />
<span <span

View File

@@ -29,19 +29,13 @@ function StatusBar({
container: RefObject<HTMLDivElement>; container: RefObject<HTMLDivElement>;
loading?: boolean; loading?: boolean;
}) { }) {
const [status, setStatus] = useState({
date: "",
saved: ""
});
const tab = useTabContext(); const tab = useTabContext();
const [sticky, setSticky] = useState(false); const [showChars, setShowChars] = useState(false);
const stickyRef = useRef(false);
const prevScroll = useRef(0);
const lastStickyChangeTime = useRef(0);
const [words, setWords] = useState(strings.totalWords(0)); const [words, setWords] = useState(strings.totalWords(0));
const currentWords = useRef(words); const currentWords = useRef(words);
const [chars, setChars] = useState(0);
const statusBar = useRef({ const statusBar = useRef({
set: setStatus, set: () => {},
updateWords: () => { updateWords: () => {
const editor = editors[tab.id]; const editor = editors[tab.id];
if (!editor) return; if (!editor) return;
@@ -57,110 +51,44 @@ function StatusBar({
useEffect(() => { useEffect(() => {
globalThis.statusBars[tab.id] = statusBar; 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 () => { return () => {
globalThis.statusBars[tab.id] = undefined; globalThis.statusBars[tab.id] = undefined;
}; };
}, [tab.id, statusBar]); }, [tab.id, statusBar, showChars]);
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;
}, []);
useEffect(() => { useEffect(() => {
currentWords.current = words; currentWords.current = words;
}, [words]); }, [words]);
useEffect(() => {
const node = container.current;
node?.addEventListener("scroll", onScroll);
return () => {
node?.removeEventListener("scroll", onScroll);
};
}, [onScroll, container]);
const paragraphStyle: React.CSSProperties = { const paragraphStyle: React.CSSProperties = {
marginTop: 0, marginTop: 0,
marginBottom: 0, marginBottom: 0,
fontSize: "12px", fontSize: 12,
color: "var(--nn_secondary_paragraph)", color: "var(--nn_secondary_paragraph)",
marginRight: 8,
paddingBottom: 0, paddingBottom: 0,
userSelect: "none", userSelect: "none"
pointerEvents: "none"
}; };
return ( return (
<div <p
style={{ onMouseDown={(e) => {
flexDirection: "row", setShowChars(!showChars);
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
}} }}
id="statusbar" style={paragraphStyle}
> >
<p style={paragraphStyle}>{words}</p> {showChars ? strings.characters(chars) : words}
<p style={paragraphStyle}>{status.date}</p> </p>
<p style={paragraphStyle}>{status.saved}</p>
</div>
); );
} }

View File

@@ -50,14 +50,15 @@
z-index: 999; z-index: 999;
list-style: none; list-style: none;
user-select: none; user-select: none;
padding: 0px;
font-family: sans-serif; font-family: sans-serif;
font-size: 0.95em; font-size: 0.95em;
border: 1px solid var(--nn_primary_border); border: 1px solid var(--nn_primary_border);
box-shadow: 1px 1px 20px 1px rgba(0, 0, 0, 0.1); box-shadow: 1px 1px 20px 1px rgba(0, 0, 0, 0.1);
border-radius: 6px; border-radius: 8px;
background-color: var(--nn_secondary_background); background-color: var(--nn_secondary_background);
min-width: 12rem; min-width: 13rem;
padding: 0 !important;
} }
.menuOpening { .menuOpening {
@@ -73,10 +74,11 @@
.menuItem { .menuItem {
cursor: pointer; cursor: pointer;
border-radius: 0; border-radius: 0;
padding: 1rem 0.6rem !important; padding: 0.5rem 0.6rem !important;
color: var(--nn_primary_paragraph); color: var(--nn_primary_paragraph);
font-family: "Inter"; font-family: "Inter";
padding: 12px 6px; font-size: 0.9em;
flex-wrap: nowrap;
} }
.menuItemHover { .menuItemHover {

View File

@@ -22,7 +22,6 @@ import { Settings } from "../utils";
import { EditorEvents } from "../utils/editor-events"; import { EditorEvents } from "../utils/editor-events";
import styles from "./styles.module.css"; import styles from "./styles.module.css";
import { useTabContext } from "../hooks/useTabStore"; import { useTabContext } from "../hooks/useTabStore";
import { strings } from "@notesnook/intl";
function Tags(props: { settings: Settings; loading?: boolean }): JSX.Element { function Tags(props: { settings: Settings; loading?: boolean }): JSX.Element {
const [tags, setTags] = useState< const [tags, setTags] = useState<
@@ -54,80 +53,32 @@ function Tags(props: { settings: Settings; loading?: boolean }): JSX.Element {
<div <div
className={styles.container} className={styles.container}
style={{ style={{
padding: "0px 12px",
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
overflowX: "scroll", overflowX: "scroll",
minHeight: "40px", 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) => ( {tags.map((tag) => (
<button <button
key={tag.title} key={tag.title}
className={styles.btn}
style={{ style={{
border: "1px solid var(--nn_primary_border)", border: "1px solid var(--nn_primary_border)",
backgroundColor: "var(--nn_secondary_background)", backgroundColor: "var(--nn_secondary_background)",
marginRight: 5, borderRadius: 6,
borderRadius: 100, padding: "0px 4px",
padding: "0px 10px", height: "24px",
height: "30px",
fontFamily: "Inter", fontFamily: "Inter",
fontSize: 13, fontSize: 12,
color: "var(--nn_primary_icon)", color: "var(--nn_primary_icon)",
userSelect: "none", userSelect: "none",
WebkitUserSelect: "none" WebkitUserSelect: "none"
}} }}
onClick={(e) => { onClick={(e) => {
e.preventDefault(); e.preventDefault();
post(EditorEvents.tag, tag, tab.id, tab.session?.noteId); openManageTagsSheet();
}} }}
> >
#{tag.alias} #{tag.alias}

View File

@@ -49,9 +49,9 @@ function Title({
if (!titleSizeDiv.current || !titleRef.current) return; if (!titleSizeDiv.current || !titleRef.current) return;
titleSizeDiv.current.innerText = titleRef.current.value; titleSizeDiv.current.innerText = titleRef.current.value;
titleRef.current.style.height = `${titleSizeDiv.current.clientHeight}px`; titleRef.current.style.height = `${titleSizeDiv.current.clientHeight}px`;
titleRef.current.style.minHeight = `${titleSizeDiv.current.clientHeight}px`;
titleSizeDiv.current.style.width = `${titleRef.current.clientWidth}px`; titleSizeDiv.current.style.width = `${titleRef.current.clientWidth}px`;
}, []); }, []);
useEffect(() => { useEffect(() => {
if (titleRef.current) { if (titleRef.current) {
titleRef.current.value = title; titleRef.current.value = title;
@@ -88,8 +88,8 @@ function Title({
maxWidth: "100%", maxWidth: "100%",
minHeight: 40, minHeight: 40,
opacity: 0, opacity: 0,
paddingRight: 10, paddingRight: 16,
paddingLeft: 10, paddingLeft: 16,
fontWeight: 600, fontWeight: 600,
fontFamily: getFontById(fontFamily)?.font || "Inter", fontFamily: getFontById(fontFamily)?.font || "Inter",
boxSizing: "border-box", boxSizing: "border-box",
@@ -119,8 +119,8 @@ function Title({
boxSizing: "border-box", boxSizing: "border-box",
border: 0, border: 0,
opacity: 1, opacity: 1,
paddingRight: 10, paddingRight: 16,
paddingLeft: 10, paddingLeft: 16,
fontWeight: 600, fontWeight: 600,
fontFamily: getFontById(fontFamily)?.font || "Inter", fontFamily: getFontById(fontFamily)?.font || "Inter",
backgroundColor: "transparent", backgroundColor: "transparent",

View File

@@ -491,6 +491,10 @@ msgstr "{count, plural, one {Unpublish item} other {Unpublish # items}}"
msgid "{count, plural, one {Unpublish note} other {Unpublish # notes}}" msgid "{count, plural, one {Unpublish note} other {Unpublish # notes}}"
msgstr "{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 #: src/strings.ts:1563
msgid "{days, plural, one {1 day} other {# days}}" msgid "{days, plural, one {1 day} other {# days}}"
msgstr "{days, plural, one {1 day} other {# days}}" msgstr "{days, plural, one {1 day} other {# days}}"

View File

@@ -491,6 +491,10 @@ msgstr ""
msgid "{count, plural, one {Unpublish note} other {Unpublish # notes}}" msgid "{count, plural, one {Unpublish note} other {Unpublish # notes}}"
msgstr "" msgstr ""
#: src/strings.ts:2492
msgid "{count} characters"
msgstr ""
#: src/strings.ts:1563 #: src/strings.ts:1563
msgid "{days, plural, one {1 day} other {# days}}" msgid "{days, plural, one {1 day} other {# days}}"
msgstr "" msgstr ""

View File

@@ -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.`, 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`, noNotebooksSelectedToMove: () => t`No notebooks selected to move`,
scrollToTop: () => t`Scroll to top`, scrollToTop: () => t`Scroll to top`,
scrollToBottom: () => t`Scroll to bottom` scrollToBottom: () => t`Scroll to bottom`,
characters: (count: number) => t`${count} characters`
}; };