mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-09-01 19:49:54 +02:00
mobile: push ui updates
This commit is contained in:
committed by
Abdullah Atta
parent
7a2bf15015
commit
eebd6542e7
@@ -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/>.
|
||||
*/
|
||||
|
||||
import { KeyboardTypeOptions, TextInput } from "react-native";
|
||||
import { KeyboardTypeOptions, TextInput, TextInputProps } from "react-native";
|
||||
import { eSendEvent } from "../../services/event-manager";
|
||||
import { eCloseSimpleDialog, eOpenSimpleDialog } from "../../utils/events";
|
||||
import { ButtonProps } from "../ui/button";
|
||||
@@ -58,6 +58,7 @@ export type DialogInfo = {
|
||||
validators: FieldValidator[];
|
||||
defaultValue?: string;
|
||||
ref: RefObject<TextInput | null>;
|
||||
inputProps?: TextInputProps;
|
||||
}[];
|
||||
onFormSubmit?: (form: FormRef) => Promise<boolean>;
|
||||
};
|
||||
|
||||
@@ -39,7 +39,7 @@ import { defaultBorderRadius } from "../../utils/size";
|
||||
import { DefaultAppStyles } from "../../utils/styles";
|
||||
import { sleep } from "../../utils/time";
|
||||
import { Toast } from "../toast";
|
||||
import { Button } from "../ui/button";
|
||||
import { Checkbox } from "../ui/checkbox";
|
||||
import Input from "../ui/input";
|
||||
import { FormInput, type FormRef } from "../ui/input/form-input";
|
||||
import { Notice } from "../ui/notice";
|
||||
@@ -233,6 +233,7 @@ export const Dialog = ({ context = "global" }: { context?: string }) => {
|
||||
>
|
||||
{dialogInfo.form.items.map((item, index) => (
|
||||
<FormInput
|
||||
{...item.inputProps}
|
||||
key={item.name}
|
||||
fwdRef={item.ref}
|
||||
name={item.name}
|
||||
@@ -289,29 +290,16 @@ export const Dialog = ({ context = "global" }: { context?: string }) => {
|
||||
) : null}
|
||||
|
||||
{dialogInfo.check ? (
|
||||
<>
|
||||
<Button
|
||||
onPress={() => {
|
||||
setChecked(!checked);
|
||||
}}
|
||||
icon={
|
||||
checked
|
||||
? "check-circle-outline"
|
||||
: "checkbox-blank-circle-outline"
|
||||
}
|
||||
iconColor={
|
||||
checked ? colors.secondary.icon : colors.primary.icon
|
||||
}
|
||||
style={{
|
||||
justifyContent: "flex-start"
|
||||
}}
|
||||
height={35}
|
||||
iconSize={20}
|
||||
width="100%"
|
||||
title={dialogInfo.check.info}
|
||||
type={checked ? dialogInfo.check.type || "plain" : "plain"}
|
||||
/>
|
||||
</>
|
||||
<Checkbox
|
||||
checked={checked}
|
||||
onPress={() => {
|
||||
setChecked(!checked);
|
||||
}}
|
||||
title={dialogInfo.check.info}
|
||||
style={{
|
||||
marginTop: -Spacing.LEVEL_1
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
</View>
|
||||
<DialogButtons
|
||||
|
||||
@@ -107,7 +107,6 @@ export const Header = ({
|
||||
<View
|
||||
style={{
|
||||
paddingHorizontal: DefaultAppStyles.GAP,
|
||||
marginBottom: Spacing.LEVEL_3,
|
||||
marginTop: Platform.OS === "android" ? 5 : 0
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -71,6 +71,7 @@ export const SearchResult = (props: SearchResultProps) => {
|
||||
}}
|
||||
onLongPress={async () => {
|
||||
const note = await db.notes.note(props.item.id);
|
||||
if (!note) return;
|
||||
Properties.present(note);
|
||||
}}
|
||||
onPress={async () => openNote()}
|
||||
@@ -151,6 +152,7 @@ export const SearchResult = (props: SearchResultProps) => {
|
||||
}}
|
||||
onLongPress={async () => {
|
||||
const note = await db.notes.note(props.item.id);
|
||||
if (!note) return;
|
||||
Properties.present(note);
|
||||
}}
|
||||
onPress={() => {
|
||||
|
||||
@@ -24,7 +24,6 @@ import { AppFontSize } from "../../utils/size";
|
||||
import Paragraph from "../ui/typography/paragraph";
|
||||
import { getFormattedDate } from "@notesnook/common";
|
||||
import { strings } from "@notesnook/intl";
|
||||
import { DefaultAppStyles } from "../../utils/styles";
|
||||
import DateTimePickerModal from "react-native-modal-datetime-picker";
|
||||
import { db } from "../../common/database";
|
||||
import { Item, Note } from "@notesnook/core";
|
||||
@@ -60,7 +59,11 @@ export const DateMeta = ({ item }: { item: Item }) => {
|
||||
alignItems: "center"
|
||||
}}
|
||||
>
|
||||
<View>
|
||||
<View
|
||||
style={{
|
||||
gap: Spacing.LEVEL_0
|
||||
}}
|
||||
>
|
||||
<Paragraph size={AppFontSize.xs} color={colors.secondary.paragraph}>
|
||||
{strings.dateDescFromKey(
|
||||
key as
|
||||
@@ -73,7 +76,7 @@ export const DateMeta = ({ item }: { item: Item }) => {
|
||||
</Paragraph>
|
||||
<Paragraph
|
||||
size={AppFontSize.xs}
|
||||
color={colors.primary.paragraph}
|
||||
color={colors.primary.heading}
|
||||
fontFamily="MEDIUM"
|
||||
onPress={
|
||||
item.type !== "note"
|
||||
@@ -127,9 +130,6 @@ export const DateMeta = ({ item }: { item: Item }) => {
|
||||
|
||||
<View
|
||||
style={{
|
||||
borderTopWidth: 1,
|
||||
borderColor: colors.primary.border,
|
||||
paddingVertical: Spacing.LEVEL_2,
|
||||
flexDirection: "row",
|
||||
gap: Spacing.LEVEL_2
|
||||
}}
|
||||
|
||||
@@ -20,7 +20,7 @@ import { strings } from "@notesnook/intl";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { View } from "react-native";
|
||||
import { FlatList } from "react-native-actions-sheet";
|
||||
import { ScrollView } from "react-native-actions-sheet";
|
||||
import { db } from "../../common/database";
|
||||
import { DDS } from "../../services/device-detection";
|
||||
import {
|
||||
@@ -54,17 +54,53 @@ import Navigation from "../../services/navigation";
|
||||
import { useIsFeatureAvailable } from "@notesnook/common";
|
||||
import PaywallSheet from "../sheets/paywall";
|
||||
import { useSettingStore } from "../../stores/use-setting-store";
|
||||
import { Action, useActions } from "../../hooks/use-actions";
|
||||
import {
|
||||
Color,
|
||||
Note,
|
||||
Notebook,
|
||||
Reminder,
|
||||
Tag,
|
||||
TrashItem
|
||||
} from "@notesnook/core";
|
||||
|
||||
export const Properties = ({ close = () => {}, item, buttons = [] }) => {
|
||||
export type PropertiesItem =
|
||||
| Note
|
||||
| Notebook
|
||||
| Tag
|
||||
| Color
|
||||
| Reminder
|
||||
| TrashItem;
|
||||
|
||||
export const Properties = ({
|
||||
close,
|
||||
item,
|
||||
buttons = []
|
||||
}: {
|
||||
close?: (ctx?: string | undefined) => void;
|
||||
item: PropertiesItem;
|
||||
buttons: Action[];
|
||||
}) => {
|
||||
const { colors } = useThemeColors();
|
||||
const colorFeature = useIsFeatureAvailable("colors");
|
||||
const [noteNotebooks, setNoteNotebooks] = useState([]);
|
||||
const [tags, setTags] = useState([]);
|
||||
const [noteNotebooks, setNoteNotebooks] = useState<Notebook[]>([]);
|
||||
const [tags, setTags] = useState<Tag[]>([]);
|
||||
const [visible, setVisible] = useState(false);
|
||||
const colorNotes = useMenuStore((state) => state.colorNotes);
|
||||
const actions = useActions({
|
||||
item,
|
||||
close: () => {
|
||||
close?.();
|
||||
}
|
||||
});
|
||||
const editAction = actions.find(
|
||||
(action) => action.id === "edit-notebook" || action.id === "rename-tag"
|
||||
);
|
||||
useEffect(() => {
|
||||
async function getNotebooks() {
|
||||
let filteredNotebooks = await db.relations.to(item, "notebook").resolve();
|
||||
const filteredNotebooks = await db.relations
|
||||
.to(item, "notebook")
|
||||
.resolve();
|
||||
return filteredNotebooks || [];
|
||||
}
|
||||
if (item.type === "note") {
|
||||
@@ -87,7 +123,7 @@ export const Properties = ({ close = () => {}, item, buttons = [] }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<FlatList
|
||||
<ScrollView
|
||||
keyboardShouldPersistTaps="always"
|
||||
keyboardDismissMode="none"
|
||||
style={{
|
||||
@@ -95,39 +131,39 @@ export const Properties = ({ close = () => {}, item, buttons = [] }) => {
|
||||
borderBottomRightRadius: DDS.isLargeTablet() ? 10 : 1,
|
||||
borderBottomLeftRadius: DDS.isLargeTablet() ? 10 : 1,
|
||||
maxHeight: "100%",
|
||||
paddingTop: Spacing.LEVEL_3
|
||||
paddingTop: Spacing.LEVEL_2
|
||||
}}
|
||||
nestedScrollEnabled
|
||||
bounces={false}
|
||||
data={[0]}
|
||||
keyExtractor={() => "properties-scroll-item"}
|
||||
renderItem={() => (
|
||||
>
|
||||
<View>
|
||||
{item.type === "note" ? (
|
||||
<ColorPicker
|
||||
visible={visible}
|
||||
setVisible={setVisible}
|
||||
onColorAdded={async (color) => {
|
||||
await db.relations.to(item, "color").unlink();
|
||||
await db.relations.add(color, item);
|
||||
useRelationStore.getState().update();
|
||||
useMenuStore.getState().setColorNotes();
|
||||
Navigation.queueRoutesForUpdate();
|
||||
sendItemUpdateEvent(color.id, "color");
|
||||
eSendEvent(refreshNotesPage);
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
<View
|
||||
style={{
|
||||
gap: Spacing.LEVEL_1
|
||||
paddingHorizontal: Spacing.LEVEL_3
|
||||
}}
|
||||
>
|
||||
{item.type === "note" ? (
|
||||
<ColorPicker
|
||||
visible={visible}
|
||||
setVisible={setVisible}
|
||||
onColorAdded={async (color) => {
|
||||
await db.relations.to(item, "color").unlink();
|
||||
await db.relations.add(color, item);
|
||||
useRelationStore.getState().update();
|
||||
useMenuStore.getState().setColorNotes();
|
||||
Navigation.queueRoutesForUpdate();
|
||||
sendItemUpdateEvent(color.id, "color");
|
||||
eSendEvent(refreshNotesPage);
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
<View
|
||||
style={{
|
||||
paddingHorizontal: Spacing.LEVEL_3
|
||||
gap: Spacing.LEVEL_1,
|
||||
paddingBottom: Spacing.LEVEL_3
|
||||
}}
|
||||
>
|
||||
<View>
|
||||
{item.type === "note" && (noteNotebooks.length || tags.length) ? (
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
@@ -183,95 +219,101 @@ export const Properties = ({ close = () => {}, item, buttons = [] }) => {
|
||||
) : null
|
||||
)}
|
||||
</View>
|
||||
) : null}
|
||||
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between"
|
||||
}}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between"
|
||||
alignItems: "center",
|
||||
flexShrink: 1,
|
||||
gap: Spacing.LEVEL_1
|
||||
}}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
flexShrink: 1,
|
||||
gap: Spacing.LEVEL_1
|
||||
}}
|
||||
>
|
||||
{item.type === "color" ? (
|
||||
<Pressable
|
||||
type="accent"
|
||||
accentColor={item.colorCode}
|
||||
accentText={colors.static.white}
|
||||
style={{
|
||||
width: 8,
|
||||
height: 8,
|
||||
borderRadius: 100
|
||||
}}
|
||||
/>
|
||||
) : item.type === "tag" ? (
|
||||
<AppIcon
|
||||
name="shopping-mode"
|
||||
iconFamily="evilicons"
|
||||
size={AppFontSize.lg}
|
||||
color={colors.primary.icon}
|
||||
/>
|
||||
) : null}
|
||||
{item.type === "color" ? (
|
||||
<Pressable
|
||||
type="accent"
|
||||
accentColor={item.colorCode}
|
||||
accentText={colors.static.white}
|
||||
style={{
|
||||
width: 8,
|
||||
height: 8,
|
||||
borderRadius: 100
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
<Heading size={AppFontSize.xl}>{item.title}</Heading>
|
||||
</View>
|
||||
<Heading size={AppFontSize.xl}>{item.title}</Heading>
|
||||
|
||||
{item.type === "note" ? (
|
||||
{editAction ? (
|
||||
<IconButton
|
||||
name="square-out"
|
||||
name="edit-pencil"
|
||||
iconFamily="notesnook"
|
||||
type="plain"
|
||||
color={colors.primary.icon}
|
||||
size={AppFontSize.lg}
|
||||
style={{
|
||||
alignSelf: "flex-start"
|
||||
}}
|
||||
onPress={() => {
|
||||
close();
|
||||
eSendEvent(eOnLoadNote, {
|
||||
item: item,
|
||||
newTab: true
|
||||
});
|
||||
if (!DDS.isTab) {
|
||||
fluidTabsRef.current?.goToPage("editor");
|
||||
}
|
||||
}}
|
||||
size={AppFontSize.md}
|
||||
onPress={editAction.onPress}
|
||||
/>
|
||||
) : null}
|
||||
</View>
|
||||
|
||||
{(item.type === "notebook" || item.type === "reminder") &&
|
||||
item.description ? (
|
||||
<Paragraph>{item.description}</Paragraph>
|
||||
) : null}
|
||||
|
||||
{item.type === "reminder" ? (
|
||||
<ReminderTime
|
||||
reminder={item}
|
||||
{item.type === "note" ? (
|
||||
<IconButton
|
||||
name="square-out"
|
||||
iconFamily="notesnook"
|
||||
type="plain"
|
||||
color={colors.primary.icon}
|
||||
size={AppFontSize.lg}
|
||||
style={{
|
||||
justifyContent: "flex-start",
|
||||
borderWidth: 0,
|
||||
alignSelf: "flex-start",
|
||||
backgroundColor: "transparent",
|
||||
paddingHorizontal: 0,
|
||||
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL
|
||||
alignSelf: "flex-start"
|
||||
}}
|
||||
onPress={() => {
|
||||
close?.();
|
||||
eSendEvent(eOnLoadNote, {
|
||||
item: item,
|
||||
newTab: true
|
||||
});
|
||||
if (!DDS.isTab) {
|
||||
fluidTabsRef.current?.goToPage("editor");
|
||||
}
|
||||
}}
|
||||
fontSize={AppFontSize.xs}
|
||||
/>
|
||||
) : null}
|
||||
</View>
|
||||
|
||||
<DateMeta item={item} />
|
||||
|
||||
{item.type === "note" && colorNotes.length > 0 ? (
|
||||
<Tags close={close} item={item} />
|
||||
{(item.type === "notebook" || item.type === "reminder") &&
|
||||
item.description ? (
|
||||
<Paragraph>{item.description}</Paragraph>
|
||||
) : null}
|
||||
|
||||
{item.type === "reminder" ? (
|
||||
<ReminderTime
|
||||
reminder={item}
|
||||
style={{
|
||||
justifyContent: "flex-start",
|
||||
borderWidth: 0,
|
||||
alignSelf: "flex-start",
|
||||
backgroundColor: "transparent",
|
||||
paddingHorizontal: 0,
|
||||
paddingVertical: DefaultAppStyles.GAP_VERTICAL_SMALL
|
||||
}}
|
||||
fontSize={AppFontSize.xs}
|
||||
/>
|
||||
) : null}
|
||||
</View>
|
||||
|
||||
<DateMeta item={item} />
|
||||
|
||||
{item.type === "note" && colorNotes.length > 0 ? (
|
||||
<Tags close={close} item={item} />
|
||||
) : null}
|
||||
|
||||
{item.type === "note" ? (
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
@@ -286,7 +328,7 @@ export const Properties = ({ close = () => {}, item, buttons = [] }) => {
|
||||
<Button
|
||||
onPress={async () => {
|
||||
ManageTags.present([item.id]);
|
||||
close();
|
||||
close?.();
|
||||
}}
|
||||
buttonType={{
|
||||
text: colors.primary.paragraph
|
||||
@@ -333,37 +375,54 @@ export const Properties = ({ close = () => {}, item, buttons = [] }) => {
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
) : null}
|
||||
</View>
|
||||
|
||||
{/* {item.type === "note" ? (
|
||||
<Notebooks note={item} close={close} />
|
||||
) : null} */}
|
||||
<Items
|
||||
item={item}
|
||||
buttons={buttons}
|
||||
close={() => {
|
||||
close();
|
||||
<View
|
||||
style={{
|
||||
paddingHorizontal: Spacing.LEVEL_3
|
||||
}}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
marginVertical: Spacing.LEVEL_3,
|
||||
width: "100%",
|
||||
borderBottomWidth: 1,
|
||||
borderColor: colors.primary.separator
|
||||
}}
|
||||
/>
|
||||
|
||||
{DDS.isTab ? (
|
||||
<View
|
||||
style={{
|
||||
height: 20
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
<SheetProvider context="properties" />
|
||||
<Dialog context="properties" />
|
||||
</View>
|
||||
)}
|
||||
/>
|
||||
|
||||
<Items
|
||||
item={item}
|
||||
buttons={buttons}
|
||||
actions={actions}
|
||||
close={() => {
|
||||
close?.();
|
||||
}}
|
||||
/>
|
||||
|
||||
{DDS.isTab ? (
|
||||
<View
|
||||
style={{
|
||||
height: 20
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
<SheetProvider context="properties" />
|
||||
<Dialog context="properties" />
|
||||
</View>
|
||||
</ScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
Properties.present = async (item, isSheet, buttons = []) => {
|
||||
Properties.present = async (
|
||||
item: PropertiesItem,
|
||||
isSheet: boolean = false,
|
||||
buttons: Action[] = []
|
||||
) => {
|
||||
if (!item) return;
|
||||
let type = item?.type;
|
||||
const type = item?.type;
|
||||
let dbItem;
|
||||
switch (type) {
|
||||
case "trash":
|
||||
@@ -387,15 +446,12 @@ Properties.present = async (item, isSheet, buttons = []) => {
|
||||
}
|
||||
}
|
||||
|
||||
if (!dbItem) return;
|
||||
|
||||
presentSheet({
|
||||
context: isSheet ? "local" : undefined,
|
||||
component: (ref, close) => (
|
||||
<Properties
|
||||
close={close}
|
||||
actionSheetRef={ref}
|
||||
item={dbItem}
|
||||
buttons={buttons}
|
||||
/>
|
||||
<Properties close={close} item={dbItem} buttons={buttons} />
|
||||
)
|
||||
});
|
||||
};
|
||||
@@ -18,19 +18,18 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Item } from "@notesnook/core";
|
||||
import { strings } from "@notesnook/intl";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import React from "react";
|
||||
import { Dimensions, View } from "react-native";
|
||||
import SwiperFlatList from "react-native-swiper-flatlist";
|
||||
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
||||
import { Action, ActionId, useActions } from "../../hooks/use-actions";
|
||||
import { Action, ActionId } 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 { AppFontSize } from "../../utils/size";
|
||||
import { DefaultAppStyles } from "../../utils/styles";
|
||||
import AppIcon from "../ui/AppIcon";
|
||||
import { Button } from "../ui/button";
|
||||
import { Pressable } from "../ui/pressable";
|
||||
import Paragraph from "../ui/typography/paragraph";
|
||||
import { Radius, Spacing } from "../../common/design/spacing";
|
||||
@@ -64,10 +63,18 @@ const BOTTOM_BAR_ITEMS: ActionId[] = [
|
||||
"trash"
|
||||
];
|
||||
|
||||
const PREFERENCE_ITEMS: ActionId[] = [
|
||||
"add-shortcut",
|
||||
"pin",
|
||||
"default-notebook",
|
||||
"default-tag",
|
||||
"default-homepage"
|
||||
];
|
||||
|
||||
const COLUMN_BAR_ITEMS: ActionId[] = [
|
||||
"select",
|
||||
"add-notebook",
|
||||
"edit-notebook",
|
||||
// "edit-notebook",
|
||||
"move-notes",
|
||||
"move-notebook",
|
||||
"edit-reminder",
|
||||
@@ -79,7 +86,7 @@ const COLUMN_BAR_ITEMS: ActionId[] = [
|
||||
"add-shortcut",
|
||||
"reorder",
|
||||
"rename-color",
|
||||
"rename-tag",
|
||||
// "rename-tag",
|
||||
"launcher-shortcut",
|
||||
"copy-id",
|
||||
"copy-link",
|
||||
@@ -91,11 +98,13 @@ const COLUMN_BAR_ITEMS: ActionId[] = [
|
||||
export const Items = ({
|
||||
item,
|
||||
close,
|
||||
buttons
|
||||
buttons,
|
||||
actions
|
||||
}: {
|
||||
item: Item;
|
||||
close: () => void;
|
||||
buttons: Action[];
|
||||
actions: Action[];
|
||||
}) => {
|
||||
const { colors } = useThemeColors();
|
||||
const topBarSorting = useStoredRef<{ [name: string]: number }>(
|
||||
@@ -103,14 +112,12 @@ export const Items = ({
|
||||
{}
|
||||
);
|
||||
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;
|
||||
Dimensions.get("window").fontScale > 1 && dimensions.width < 450;
|
||||
|
||||
const columnItemsCount = deviceMode === "tablet" ? 7 : shouldShrink ? 4 : 5;
|
||||
|
||||
@@ -136,16 +143,23 @@ export const Items = ({
|
||||
BOTTOM_BAR_ITEMS.indexOf(a.id) > BOTTOM_BAR_ITEMS.indexOf(b.id) ? 1 : -1
|
||||
);
|
||||
|
||||
const preferenceItems = selectedActions
|
||||
.filter((item) => PREFERENCE_ITEMS.indexOf(item.id) > -1)
|
||||
.sort((a, b) =>
|
||||
PREFERENCE_ITEMS.indexOf(a.id) > PREFERENCE_ITEMS.indexOf(b.id) ? 1 : -1
|
||||
);
|
||||
|
||||
const columnItems = selectedActions
|
||||
.filter((item) => COLUMN_BAR_ITEMS.indexOf(item.id) > -1)
|
||||
.filter(
|
||||
(item) =>
|
||||
COLUMN_BAR_ITEMS.indexOf(item.id) > -1 &&
|
||||
PREFERENCE_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 actionItems = [...buttons, ...columnItems];
|
||||
|
||||
const renderRowItem = React.useCallback(
|
||||
({ item }: { item: Action }) => (
|
||||
@@ -170,9 +184,10 @@ export const Items = ({
|
||||
marginBottom: 6
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
<AppIcon
|
||||
allowFontScaling
|
||||
name={item.icon}
|
||||
iconFamily="notesnook"
|
||||
size={
|
||||
DDS.isTab
|
||||
? AppFontSize.xxl
|
||||
@@ -208,33 +223,79 @@ export const Items = ({
|
||||
]
|
||||
);
|
||||
|
||||
const renderColumnItem = React.useCallback(
|
||||
const renderPreferenceItem = React.useCallback(
|
||||
(item: Action) => (
|
||||
<Button
|
||||
<Pressable
|
||||
key={item.id}
|
||||
buttonType={{
|
||||
text: item.checked
|
||||
? item.activeColor || colors.primary.accent
|
||||
: item.id === "delete" || item.id === "trash"
|
||||
? colors.error.paragraph
|
||||
: colors.primary.paragraph
|
||||
}}
|
||||
testID={"icon-" + item.id}
|
||||
onPress={item.onPress}
|
||||
title={item.title}
|
||||
icon={item.icon}
|
||||
type={item.checked ? "inverted" : "plain"}
|
||||
fontSize={AppFontSize.sm}
|
||||
type={item.checked ? "shade" : "transparent"}
|
||||
testID={"icon-" + item.id}
|
||||
style={{
|
||||
borderRadius: 0,
|
||||
justifyContent: "flex-start",
|
||||
alignSelf: "flex-start",
|
||||
width: "100%",
|
||||
opacity: item.locked ? 0.5 : 1
|
||||
width: "48.5%",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
gap: Spacing.LEVEL_1,
|
||||
paddingVertical: Spacing.LEVEL_2,
|
||||
paddingHorizontal: Spacing.LEVEL_2,
|
||||
borderRadius: Radius.XS,
|
||||
borderWidth: item.checked ? 0 : 1,
|
||||
borderColor: colors.primary.border,
|
||||
opacity: item.locked ? 0.7 : 1
|
||||
}}
|
||||
/>
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
gap: Spacing.LEVEL_1,
|
||||
flexShrink: 1
|
||||
}}
|
||||
>
|
||||
<AppIcon
|
||||
name={item.icon}
|
||||
iconFamily="notesnook"
|
||||
allowFontScaling
|
||||
size={AppFontSize.md}
|
||||
color={item.checked ? colors.primary.icon : colors.secondary.icon}
|
||||
/>
|
||||
<Paragraph
|
||||
numberOfLines={1}
|
||||
fontSize="XS"
|
||||
fontFamily="MEDIUM"
|
||||
color={
|
||||
item.checked
|
||||
? colors.primary.paragraph
|
||||
: colors.secondary.paragraph
|
||||
}
|
||||
style={{ flexShrink: 1 }}
|
||||
>
|
||||
{item.title}
|
||||
</Paragraph>
|
||||
</View>
|
||||
|
||||
<AppIcon
|
||||
name={item.checked ? "toggle-on" : "toggle-off"}
|
||||
iconFamily="notesnook"
|
||||
size={16}
|
||||
color={
|
||||
item.checked
|
||||
? [colors.primary.accent, colors.primary.background]
|
||||
: [colors.disabled.icon, colors.primary.background]
|
||||
}
|
||||
/>
|
||||
</Pressable>
|
||||
),
|
||||
[colors.error.paragraph, colors.primary.accent, colors.primary.paragraph]
|
||||
[
|
||||
colors.disabled.icon,
|
||||
colors.primary.accent,
|
||||
colors.primary.background,
|
||||
colors.primary.border,
|
||||
colors.primary.icon,
|
||||
colors.primary.paragraph,
|
||||
colors.secondary.icon,
|
||||
colors.secondary.paragraph
|
||||
]
|
||||
);
|
||||
|
||||
const renderTopBarItem = React.useCallback(
|
||||
@@ -274,8 +335,9 @@ export const Items = ({
|
||||
paddingHorizontal: Spacing.LEVEL_2
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
<AppIcon
|
||||
name={item.icon}
|
||||
iconFamily="notesnook"
|
||||
allowFontScaling
|
||||
size={16}
|
||||
color={
|
||||
@@ -351,11 +413,7 @@ export const Items = ({
|
||||
};
|
||||
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
gap: DefaultAppStyles.GAP
|
||||
}}
|
||||
>
|
||||
<View>
|
||||
{item.type === "note" ? (
|
||||
<>
|
||||
<View>
|
||||
@@ -416,9 +474,61 @@ export const Items = ({
|
||||
</View>
|
||||
</>
|
||||
) : (
|
||||
<View>
|
||||
{buttons.map(renderColumnItem)}
|
||||
{columnItems.map(renderColumnItem)}
|
||||
<View
|
||||
style={{
|
||||
paddingHorizontal: DefaultAppStyles.GAP
|
||||
}}
|
||||
>
|
||||
{preferenceItems.length > 0 ? (
|
||||
<View style={{ gap: Spacing.LEVEL_2 }}>
|
||||
<Paragraph
|
||||
fontFamily="MEDIUM"
|
||||
fontSize="SM"
|
||||
color={colors.secondary.paragraph}
|
||||
>
|
||||
{strings.preferences()}
|
||||
</Paragraph>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
flexWrap: "wrap",
|
||||
gap: Spacing.LEVEL_1
|
||||
}}
|
||||
>
|
||||
{preferenceItems.map(renderPreferenceItem)}
|
||||
</View>
|
||||
</View>
|
||||
) : null}
|
||||
|
||||
<View
|
||||
style={{
|
||||
marginVertical: Spacing.LEVEL_3,
|
||||
width: "100%",
|
||||
borderBottomWidth: 1,
|
||||
borderColor: colors.primary.separator
|
||||
}}
|
||||
/>
|
||||
|
||||
{actionItems.length > 0 ? (
|
||||
<View style={{ gap: Spacing.LEVEL_2 }}>
|
||||
<Paragraph
|
||||
fontFamily="MEDIUM"
|
||||
fontSize="SM"
|
||||
color={colors.secondary.paragraph}
|
||||
>
|
||||
{strings.actionsHeading()}
|
||||
</Paragraph>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
flexWrap: "wrap",
|
||||
gap: Spacing.LEVEL_1
|
||||
}}
|
||||
>
|
||||
{actionItems.map((item) => renderRowItem({ item }))}
|
||||
</View>
|
||||
</View>
|
||||
) : null}
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
|
||||
@@ -31,7 +31,7 @@ import { Properties } from "../properties";
|
||||
import { useSideBarDraggingStore } from "./dragging-store";
|
||||
import { MenuItem } from "./menu-item";
|
||||
import { Default_Drag_Action } from "../../hooks/use-actions";
|
||||
import { Spacing } from "../../common/design/spacing";
|
||||
|
||||
|
||||
export const ColorSection = React.memo(
|
||||
function ColorSection() {
|
||||
|
||||
@@ -49,6 +49,7 @@ import { isFeatureAvailable } from "@notesnook/common";
|
||||
import PaywallSheet from "../sheets/paywall";
|
||||
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
|
||||
import { Spacing } from "../../common/design/spacing";
|
||||
import { createFormRef, validators } from "../ui/input/form-input";
|
||||
|
||||
/**
|
||||
* Simple Tab View Implementation for the Side bar
|
||||
@@ -428,25 +429,34 @@ const TabBar = (props: SimpleTabBarProps) => {
|
||||
}
|
||||
presentDialog({
|
||||
title: strings.addTag(),
|
||||
inputLabel: "Enter title",
|
||||
inputPlaceholder: "eg. journal",
|
||||
input: true,
|
||||
positiveText: "Add",
|
||||
positivePress: async (tag) => {
|
||||
if (tag) {
|
||||
await db.tags.add({
|
||||
title: tag
|
||||
});
|
||||
useTagStore.getState().refresh();
|
||||
return true;
|
||||
form: {
|
||||
formRef: createFormRef({
|
||||
title: ""
|
||||
}),
|
||||
items: [
|
||||
{
|
||||
label: strings.enterTitle(),
|
||||
name: "title",
|
||||
placeholder: "eg. journal",
|
||||
ref: React.createRef(),
|
||||
validators: [validators.required(strings.allFieldsRequired())]
|
||||
}
|
||||
],
|
||||
onFormSubmit: async (form) => {
|
||||
try {
|
||||
if (!form.validate()) return false;
|
||||
await db.tags.add({
|
||||
title: form.getValue("title").trim()
|
||||
});
|
||||
useTagStore.getState().refresh();
|
||||
return true;
|
||||
} catch (e) {
|
||||
form.setError("title", (e as Error).message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ToastManager.show({
|
||||
context: "local",
|
||||
type: "error",
|
||||
message: strings.allFieldsRequired()
|
||||
});
|
||||
return false;
|
||||
}
|
||||
},
|
||||
positiveText: strings.add()
|
||||
});
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -175,7 +175,7 @@ export function MenuItem({
|
||||
item.icon === "crown"
|
||||
? colors.static.yellow
|
||||
: isFocused
|
||||
? colors.primary.icon
|
||||
? colors.selected.icon
|
||||
: colors.secondary.icon
|
||||
}
|
||||
size={AppFontSize.md}
|
||||
@@ -196,7 +196,7 @@ export function MenuItem({
|
||||
<Paragraph
|
||||
fontSize="XS"
|
||||
color={
|
||||
isFocused ? colors.primary.paragraph : colors.secondary.paragraph
|
||||
isFocused ? colors.selected.paragraph : colors.secondary.paragraph
|
||||
}
|
||||
>
|
||||
{menuItemCount}
|
||||
|
||||
@@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import React, { useEffect } from "react";
|
||||
import { View } from "react-native";
|
||||
import { View, ViewStyle } from "react-native";
|
||||
import { StoreApi, UseBoundStore } from "zustand";
|
||||
import { useTotalNotes } from "../../hooks/use-db-item";
|
||||
import {
|
||||
@@ -38,6 +38,7 @@ import { useRelationStore } from "../../stores/use-relation-store";
|
||||
import { Radius, Spacing } from "../../common/design/spacing";
|
||||
import Heading from "../ui/typography/heading";
|
||||
import { AddNotebookSheet } from "../sheets/add-notebook";
|
||||
import { strings } from "@notesnook/intl";
|
||||
|
||||
export const NotebookItem = ({
|
||||
index,
|
||||
@@ -53,7 +54,10 @@ export const NotebookItem = ({
|
||||
onLongPress,
|
||||
onAddNotebook,
|
||||
canDisableSelectionMode,
|
||||
disableExpand
|
||||
disableExpand,
|
||||
hideNoteCount,
|
||||
style,
|
||||
subNotebookButtonStyle
|
||||
}: {
|
||||
index: number;
|
||||
item: TreeItem;
|
||||
@@ -69,6 +73,9 @@ export const NotebookItem = ({
|
||||
onAddNotebook?: () => void;
|
||||
canDisableSelectionMode?: boolean;
|
||||
disableExpand?: boolean;
|
||||
hideNoteCount?: boolean;
|
||||
style?: ViewStyle;
|
||||
subNotebookButtonStyle?: ViewStyle;
|
||||
}) => {
|
||||
const notebook = item.notebook;
|
||||
const isFocused = focused;
|
||||
@@ -96,207 +103,222 @@ export const NotebookItem = ({
|
||||
}, [item.notebook.id, notebook.id, onItemUpdate]);
|
||||
|
||||
const itemPadding =
|
||||
item.depth === 0 ? undefined : item.depth < 6 ? 15 * item.depth : 15 * 5;
|
||||
item.depth === 0
|
||||
? undefined
|
||||
: item.depth < 6
|
||||
? Spacing.LEVEL_2 * item.depth
|
||||
: Spacing.LEVEL_2 * 5;
|
||||
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
paddingLeft: itemPadding,
|
||||
width: "100%",
|
||||
opacity: item.disabled ? 0.5 : 1,
|
||||
paddingBottom: Spacing.LEVEL_0
|
||||
opacity: item.disabled ? 0.5 : 1
|
||||
}}
|
||||
>
|
||||
{item.depth > 0 ? (
|
||||
<View
|
||||
style={{
|
||||
height: "100%",
|
||||
width: 1,
|
||||
backgroundColor: colors.primary.border,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
position: "absolute",
|
||||
left: itemPadding
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
<Pressable
|
||||
type={isFocused || selected ? "selected" : "transparent"}
|
||||
onLongPress={onLongPress}
|
||||
testID={`notebook-item-${item.depth}-${index}`}
|
||||
onPress={async () => {
|
||||
if (selectionEnabled) {
|
||||
const state = selectionStore.getState();
|
||||
|
||||
if (selected) {
|
||||
state.markAs(item.notebook, "deselected");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!state.multiSelect) {
|
||||
const keys = Object.keys(state.selection);
|
||||
const nextState: any = {};
|
||||
for (const key in keys) {
|
||||
nextState[key] = !state.initialState[key]
|
||||
? undefined
|
||||
: "deselected";
|
||||
}
|
||||
|
||||
state.setSelection({
|
||||
[item.notebook.id]: "selected",
|
||||
...nextState
|
||||
});
|
||||
} else {
|
||||
state.markAs(item.notebook, "selected");
|
||||
}
|
||||
|
||||
if (
|
||||
selectionStore.getState().getSelectedItemIds().length === 0 &&
|
||||
canDisableSelectionMode
|
||||
) {
|
||||
selectionStore.setState({
|
||||
enabled: false
|
||||
});
|
||||
}
|
||||
} else {
|
||||
onPress?.();
|
||||
}
|
||||
}}
|
||||
<View
|
||||
style={{
|
||||
justifyContent: "space-between",
|
||||
width: "100%",
|
||||
alignItems: "center",
|
||||
flexDirection: "row",
|
||||
borderRadius: Radius.XS,
|
||||
paddingVertical: Spacing.LEVEL_1,
|
||||
paddingHorizontal: Spacing.LEVEL_1,
|
||||
marginBottom:
|
||||
expanded && item.hasChildren ? Spacing.LEVEL_0 : undefined
|
||||
flexDirection: "row"
|
||||
}}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
gap: Spacing.LEVEL_1
|
||||
}}
|
||||
>
|
||||
{item.depth === 0 ? (
|
||||
<AppIcon
|
||||
size={AppFontSize.md}
|
||||
color={
|
||||
selected || isFocused
|
||||
? colors.selected.icon
|
||||
: colors.primary.icon
|
||||
{item.depth > 0 ? (
|
||||
<View
|
||||
style={{
|
||||
height: "100%",
|
||||
width: 1,
|
||||
backgroundColor: colors.primary.border,
|
||||
marginRight: Spacing.LEVEL_1
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
<Pressable
|
||||
type={isFocused || selected ? "selected" : "transparent"}
|
||||
onLongPress={onLongPress}
|
||||
testID={`notebook-item-${item.depth}-${index}`}
|
||||
onPress={async () => {
|
||||
if (selectionEnabled) {
|
||||
const state = selectionStore.getState();
|
||||
|
||||
if (selected) {
|
||||
state.markAs(item.notebook, "deselected");
|
||||
return;
|
||||
}
|
||||
testID={item.hasChildren ? `expand-notebook-${index}` : ""}
|
||||
style={{
|
||||
borderRadius: defaultBorderRadius
|
||||
}}
|
||||
iconFamily="notesnook"
|
||||
name={"bookmark"}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
<Paragraph
|
||||
color={
|
||||
isFocused ? colors.selected.paragraph : colors.secondary.heading
|
||||
if (!state.multiSelect) {
|
||||
const keys = Object.keys(state.selection);
|
||||
const nextState: any = {};
|
||||
for (const key in keys) {
|
||||
nextState[key] = !state.initialState[key]
|
||||
? undefined
|
||||
: "deselected";
|
||||
}
|
||||
|
||||
state.setSelection({
|
||||
[item.notebook.id]: "selected",
|
||||
...nextState
|
||||
});
|
||||
} else {
|
||||
state.markAs(item.notebook, "selected");
|
||||
}
|
||||
|
||||
if (
|
||||
selectionStore.getState().getSelectedItemIds().length === 0 &&
|
||||
canDisableSelectionMode
|
||||
) {
|
||||
selectionStore.setState({
|
||||
enabled: false
|
||||
});
|
||||
}
|
||||
} else {
|
||||
onPress?.();
|
||||
}
|
||||
size={AppFontSize.sm}
|
||||
>
|
||||
{notebook?.title}
|
||||
</Paragraph>
|
||||
</View>
|
||||
|
||||
<View
|
||||
}}
|
||||
style={{
|
||||
gap: Spacing.LEVEL_1,
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
flexShrink: 1,
|
||||
alignItems: "center",
|
||||
justifyContent: "center"
|
||||
flexDirection: "row",
|
||||
borderRadius: Radius.XS,
|
||||
paddingVertical: Spacing.LEVEL_1,
|
||||
paddingHorizontal: Spacing.LEVEL_1,
|
||||
marginBottom:
|
||||
expanded && item.hasChildren ? Spacing.LEVEL_0 : undefined,
|
||||
...style
|
||||
}}
|
||||
>
|
||||
{selectionEnabled ? (
|
||||
<View
|
||||
style={{
|
||||
justifyContent: "center",
|
||||
alignItems: "center"
|
||||
}}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
gap: Spacing.LEVEL_1
|
||||
}}
|
||||
>
|
||||
{item.depth === 0 ? (
|
||||
<AppIcon
|
||||
name={selected ? "checkbox" : "box-empty"}
|
||||
iconFamily="notesnook"
|
||||
size={AppFontSize.md}
|
||||
color={
|
||||
selected
|
||||
? [colors.selected.accent, colors.selected.accentForeground]
|
||||
selected || isFocused
|
||||
? colors.selected.icon
|
||||
: colors.primary.icon
|
||||
}
|
||||
testID={item.hasChildren ? `expand-notebook-${index}` : ""}
|
||||
style={{
|
||||
borderRadius: defaultBorderRadius
|
||||
}}
|
||||
iconFamily="notesnook"
|
||||
name={"bookmark"}
|
||||
/>
|
||||
</View>
|
||||
) : (
|
||||
<>
|
||||
<Paragraph fontSize="SM" color={colors.secondary.paragraph}>
|
||||
{totalNotes?.(notebook?.id) || 0}
|
||||
</Paragraph>
|
||||
</>
|
||||
)}
|
||||
) : null}
|
||||
|
||||
{onAddNotebook ? (
|
||||
<IconButton
|
||||
name="plus"
|
||||
size={AppFontSize.md}
|
||||
testID={`add-notebook-${index}`}
|
||||
color={colors.primary.icon}
|
||||
top={0}
|
||||
left={0}
|
||||
bottom={0}
|
||||
right={40}
|
||||
style={{
|
||||
width: 32,
|
||||
height: 32,
|
||||
borderRadius: defaultBorderRadius
|
||||
}}
|
||||
onPress={() => {
|
||||
onAddNotebook();
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{item.hasChildren ? (
|
||||
<IconButton
|
||||
size={12}
|
||||
<Paragraph
|
||||
color={
|
||||
selected || isFocused
|
||||
? colors.selected.icon
|
||||
: colors.primary.icon
|
||||
isFocused ? colors.selected.paragraph : colors.primary.paragraph
|
||||
}
|
||||
testID={item.hasChildren ? `expand-notebook-${index}` : ""}
|
||||
onPress={() => {
|
||||
if (item.hasChildren && !disableExpand) {
|
||||
onToggleExpanded?.();
|
||||
size={AppFontSize.sm}
|
||||
>
|
||||
{notebook?.title}
|
||||
</Paragraph>
|
||||
</View>
|
||||
|
||||
<View
|
||||
style={{
|
||||
gap: Spacing.LEVEL_1,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "center"
|
||||
}}
|
||||
>
|
||||
{selectionEnabled ? (
|
||||
<View
|
||||
style={{
|
||||
justifyContent: "center",
|
||||
alignItems: "center"
|
||||
}}
|
||||
>
|
||||
<AppIcon
|
||||
name={selected ? "checkbox" : "box-empty"}
|
||||
iconFamily="notesnook"
|
||||
size={AppFontSize.md}
|
||||
color={
|
||||
selected
|
||||
? [
|
||||
colors.selected.accent,
|
||||
colors.selected.accentForeground
|
||||
]
|
||||
: colors.primary.icon
|
||||
}
|
||||
/>
|
||||
</View>
|
||||
) : (
|
||||
<>
|
||||
{item.hasChildren || hideNoteCount ? null : (
|
||||
<Paragraph fontSize="SM" color={colors.secondary.paragraph}>
|
||||
{totalNotes?.(notebook?.id) || 0}
|
||||
</Paragraph>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
|
||||
{onAddNotebook ? (
|
||||
<IconButton
|
||||
name="plus"
|
||||
iconFamily="notesnook"
|
||||
size={AppFontSize.md}
|
||||
testID={`add-notebook-${index}`}
|
||||
color={colors.primary.icon}
|
||||
top={0}
|
||||
left={0}
|
||||
bottom={0}
|
||||
right={40}
|
||||
style={{
|
||||
width: undefined,
|
||||
height: undefined,
|
||||
borderRadius: defaultBorderRadius
|
||||
}}
|
||||
onPress={() => {
|
||||
onAddNotebook();
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{item.hasChildren ? (
|
||||
<IconButton
|
||||
size={12}
|
||||
color={
|
||||
selected || isFocused
|
||||
? colors.selected.icon
|
||||
: colors.primary.icon
|
||||
}
|
||||
}}
|
||||
top={0}
|
||||
left={20}
|
||||
bottom={0}
|
||||
right={20}
|
||||
style={{
|
||||
borderRadius: defaultBorderRadius,
|
||||
width: undefined,
|
||||
height: undefined
|
||||
}}
|
||||
iconFamily="notesnook"
|
||||
name={expanded ? "chevron-up" : "chevron-down"}
|
||||
/>
|
||||
) : null}
|
||||
</View>
|
||||
</Pressable>
|
||||
testID={item.hasChildren ? `expand-notebook-${index}` : ""}
|
||||
onPress={() => {
|
||||
if (item.hasChildren && !disableExpand) {
|
||||
onToggleExpanded?.();
|
||||
}
|
||||
}}
|
||||
top={0}
|
||||
bottom={0}
|
||||
right={0}
|
||||
left={0}
|
||||
style={{
|
||||
borderRadius: defaultBorderRadius,
|
||||
width: undefined,
|
||||
height: undefined
|
||||
}}
|
||||
iconFamily="notesnook"
|
||||
name={expanded ? "chevron-up" : "chevron-down"}
|
||||
/>
|
||||
) : null}
|
||||
</View>
|
||||
</Pressable>
|
||||
</View>
|
||||
|
||||
{expanded && item.hasChildren && !selectionEnabled ? (
|
||||
<View
|
||||
style={{
|
||||
width: "100%",
|
||||
paddingLeft: (item.depth + 1) * 15
|
||||
flexDirection: "row",
|
||||
paddingLeft: (item.depth + 1) * Spacing.LEVEL_2
|
||||
}}
|
||||
>
|
||||
<View
|
||||
@@ -304,22 +326,18 @@ export const NotebookItem = ({
|
||||
height: "100%",
|
||||
width: 1,
|
||||
backgroundColor: colors.primary.border,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
position: "absolute",
|
||||
left: (item.depth + 1) * 15
|
||||
marginRight: Spacing.LEVEL_1
|
||||
}}
|
||||
/>
|
||||
<Pressable
|
||||
style={{
|
||||
// borderLeftWidth: 1,
|
||||
// borderLeftColor: colors.primary.border,
|
||||
flexDirection: "row",
|
||||
gap: Spacing.LEVEL_1,
|
||||
justifyContent: "flex-start",
|
||||
paddingVertical: Spacing.LEVEL_1,
|
||||
paddingHorizontal: Spacing.LEVEL_1,
|
||||
alignItems: "center"
|
||||
alignItems: "center",
|
||||
...subNotebookButtonStyle
|
||||
}}
|
||||
onPress={() => {
|
||||
AddNotebookSheet.present(undefined, item.notebook);
|
||||
@@ -333,8 +351,8 @@ export const NotebookItem = ({
|
||||
}}
|
||||
iconFamily="notesnook"
|
||||
/>
|
||||
<Heading fontSize="SM">Create sub-notebook</Heading>
|
||||
</Pressable>{" "}
|
||||
<Heading fontSize="SM">{strings.createSubnotebook()}</Heading>
|
||||
</Pressable>
|
||||
</View>
|
||||
) : null}
|
||||
</View>
|
||||
|
||||
@@ -105,7 +105,6 @@ export const SideMenuListEmpty = (props: SideMenuListEmptyProps) => {
|
||||
<Button
|
||||
title={props.placeholderButtonTitle}
|
||||
onPress={props.onPressPlaceholderButton}
|
||||
fontSize={AppFontSize.sm}
|
||||
style={{
|
||||
marginTop: Spacing.LEVEL_2,
|
||||
paddingVertical: Spacing.LEVEL_3,
|
||||
|
||||
@@ -29,7 +29,6 @@ import { TreeItem } from "../../stores/create-notebook-tree-stores";
|
||||
import useNavigationStore from "../../stores/use-navigation-store";
|
||||
import { useNotebooks } from "../../stores/use-notebook-store";
|
||||
import { AppFontSize } from "../../utils/size";
|
||||
import { DefaultAppStyles } from "../../utils/styles";
|
||||
import { Properties } from "../properties";
|
||||
import { NotebookItem } from "./notebook-item";
|
||||
import { SideMenuHeader } from "./side-menu-header";
|
||||
@@ -291,8 +290,8 @@ const NotebookItemWrapper = React.memo(
|
||||
Properties.present(item.notebook, false, [
|
||||
{
|
||||
id: "select",
|
||||
title: strings.select() + " " + strings.dataTypes["notebook"](),
|
||||
icon: "checkbox-outline",
|
||||
title: strings.select(),
|
||||
icon: "check-square",
|
||||
onPress: () => {
|
||||
const store = useSideMenuNotebookSelectionStore;
|
||||
store.setState({
|
||||
|
||||
@@ -27,7 +27,6 @@ import { useDBItem, useTotalNotes } from "../../hooks/use-db-item";
|
||||
import { TaggedNotes } from "../../screens/notes/tagged";
|
||||
import { presentDialog } from "../dialog/functions";
|
||||
import Navigation from "../../services/navigation";
|
||||
import { ToastManager } from "../../services/event-manager";
|
||||
import useNavigationStore from "../../stores/use-navigation-store";
|
||||
import { useTags, useTagStore } from "../../stores/use-tag-store";
|
||||
import { AppFontSize } from "../../utils/size";
|
||||
@@ -42,6 +41,7 @@ import { useSideMenuTagsSelectionStore } from "./stores";
|
||||
import { LegendList, LegendListRenderItemProps } from "@legendapp/list";
|
||||
import { useRelationStore } from "../../stores/use-relation-store";
|
||||
import { Radius, Spacing } from "../../common/design/spacing";
|
||||
import { createFormRef, validators } from "../ui/input/form-input";
|
||||
|
||||
const TagItem = (props: {
|
||||
tags: VirtualizedGrouping<Tag>;
|
||||
@@ -81,8 +81,8 @@ const TagItem = (props: {
|
||||
Properties.present(item, false, [
|
||||
{
|
||||
id: "select",
|
||||
title: strings.select() + " " + strings.dataTypes["tag"](),
|
||||
icon: "checkbox-outline",
|
||||
title: strings.select(),
|
||||
icon: "check-square",
|
||||
onPress: () => {
|
||||
const store = useSideMenuTagsSelectionStore;
|
||||
store.setState({
|
||||
@@ -230,26 +230,37 @@ export const SideMenuTags = () => {
|
||||
const onPressAddTag = React.useCallback(() => {
|
||||
presentDialog({
|
||||
title: strings.addTag(),
|
||||
// paragraph: strings.addTagDesc(),
|
||||
input: true,
|
||||
inputLabel: "Enter title",
|
||||
inputPlaceholder: "eg. journal",
|
||||
positiveText: strings.add(),
|
||||
positivePress: async (tag) => {
|
||||
if (tag) {
|
||||
await db.tags.add({
|
||||
title: tag
|
||||
});
|
||||
useTagStore.getState().refresh();
|
||||
return true;
|
||||
form: {
|
||||
formRef: createFormRef({
|
||||
title: ""
|
||||
}),
|
||||
items: [
|
||||
{
|
||||
label: strings.enterTitle(),
|
||||
name: "title",
|
||||
placeholder: "eg. journal",
|
||||
ref: React.createRef(),
|
||||
validators: [validators.required(strings.allFieldsRequired())],
|
||||
inputProps: {
|
||||
autoCapitalize: "none"
|
||||
}
|
||||
}
|
||||
],
|
||||
onFormSubmit: async (form) => {
|
||||
try {
|
||||
if (!form.validate()) return false;
|
||||
await db.tags.add({
|
||||
title: form.getValue("title").trim()
|
||||
});
|
||||
useTagStore.getState().refresh();
|
||||
return true;
|
||||
} catch (e) {
|
||||
form.setError("title", (e as Error).message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ToastManager.show({
|
||||
context: "local",
|
||||
type: "error",
|
||||
message: strings.allFieldsRequired()
|
||||
});
|
||||
return false;
|
||||
}
|
||||
},
|
||||
positiveText: strings.add()
|
||||
});
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -80,13 +80,13 @@ export const TabBarButton = ({
|
||||
backgroundColor: "transparent",
|
||||
borderWidth: 0
|
||||
}}
|
||||
type={"plain"}
|
||||
type={"plain"}
|
||||
>
|
||||
<Animated.View
|
||||
style={[
|
||||
{
|
||||
backgroundColor: isActive ? colors.primary.shade : undefined,
|
||||
borderRadius: Radius.XXS,
|
||||
borderRadius: Radius.XS,
|
||||
padding: Spacing.LEVEL_1
|
||||
},
|
||||
animatedIconStyle
|
||||
@@ -95,7 +95,7 @@ export const TabBarButton = ({
|
||||
<AppIcon
|
||||
name={icon}
|
||||
iconFamily="notesnook"
|
||||
color={isActive ? colors.primary.icon : colors.secondary.icon}
|
||||
color={isActive ? colors.selected.icon : colors.secondary.icon}
|
||||
size={16}
|
||||
/>
|
||||
</Animated.View>
|
||||
|
||||
116
apps/mobile/app/components/ui/checkbox.tsx
Normal file
116
apps/mobile/app/components/ui/checkbox.tsx
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
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 { ColorValue, DimensionValue, TextStyle, ViewStyle } from "react-native";
|
||||
import { FontFamily } from "../../common/design/font";
|
||||
import { Radius, Spacing } from "../../common/design/spacing";
|
||||
import { AppFontSize } from "../../utils/size";
|
||||
import AppIcon from "./AppIcon";
|
||||
import { Pressable, PressableProps } from "./pressable";
|
||||
import Paragraph from "./typography/paragraph";
|
||||
|
||||
export interface CheckboxProps extends Omit<PressableProps, "style"> {
|
||||
checked?: boolean;
|
||||
title?: string | null;
|
||||
onPress?: () => void;
|
||||
type?: PressableProps["type"];
|
||||
style?: ViewStyle;
|
||||
textStyle?: TextStyle;
|
||||
fontSize?: number;
|
||||
fontFamily?: keyof typeof FontFamily;
|
||||
iconSize?: number;
|
||||
iconColor?: ColorValue | ColorValue[];
|
||||
width?: DimensionValue | null;
|
||||
disabled?: boolean;
|
||||
/**
|
||||
* Hide the whole component when set to false.
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
visible?: boolean;
|
||||
}
|
||||
|
||||
export const Checkbox = ({
|
||||
checked,
|
||||
title = null,
|
||||
onPress,
|
||||
type = "shade",
|
||||
style,
|
||||
textStyle,
|
||||
fontSize = AppFontSize.xs,
|
||||
fontFamily = "MEDIUM",
|
||||
iconSize = 16,
|
||||
iconColor,
|
||||
width = "100%",
|
||||
disabled,
|
||||
visible = true,
|
||||
...restProps
|
||||
}: CheckboxProps) => {
|
||||
const { colors } = useThemeColors();
|
||||
|
||||
if (!visible) return null;
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
{...restProps}
|
||||
onPress={onPress}
|
||||
disabled={disabled}
|
||||
type={type}
|
||||
style={{
|
||||
width: width || undefined,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "flex-start",
|
||||
flexShrink: 1,
|
||||
gap: Spacing.LEVEL_1,
|
||||
paddingHorizontal: Spacing.LEVEL_2,
|
||||
paddingVertical: Spacing.LEVEL_2,
|
||||
borderRadius: Radius.XS,
|
||||
opacity: disabled ? 0.5 : 1,
|
||||
...style
|
||||
}}
|
||||
>
|
||||
<AppIcon
|
||||
name={checked ? "checkbox" : "box-empty"}
|
||||
iconFamily="notesnook"
|
||||
size={iconSize}
|
||||
color={
|
||||
iconColor ||
|
||||
(checked
|
||||
? [colors.primary.accent, colors.primary.accentForeground]
|
||||
: colors.primary.icon)
|
||||
}
|
||||
/>
|
||||
|
||||
{title ? (
|
||||
<Paragraph
|
||||
numberOfLines={1}
|
||||
size={fontSize}
|
||||
fontFamily={fontFamily}
|
||||
color={colors.primary.paragraph}
|
||||
style={[{ flexShrink: 1 }, textStyle]}
|
||||
>
|
||||
{title}
|
||||
</Paragraph>
|
||||
) : null}
|
||||
</Pressable>
|
||||
);
|
||||
};
|
||||
116
apps/mobile/app/components/ui/checkbox/index.tsx
Normal file
116
apps/mobile/app/components/ui/checkbox/index.tsx
Normal file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
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 { ColorValue, DimensionValue, TextStyle, ViewStyle } from "react-native";
|
||||
import { FontFamily } from "../../../common/design/font";
|
||||
import { Radius, Spacing } from "../../../common/design/spacing";
|
||||
import { AppFontSize } from "../../../utils/size";
|
||||
import AppIcon from "../AppIcon";
|
||||
import { Pressable, PressableProps } from "../pressable";
|
||||
import Paragraph from "../typography/paragraph";
|
||||
|
||||
export interface CheckboxProps extends Omit<PressableProps, "style"> {
|
||||
checked?: boolean;
|
||||
title?: string | null;
|
||||
onPress?: () => void;
|
||||
type?: PressableProps["type"];
|
||||
style?: ViewStyle;
|
||||
textStyle?: TextStyle;
|
||||
fontSize?: number;
|
||||
fontFamily?: keyof typeof FontFamily;
|
||||
iconSize?: number;
|
||||
iconColor?: ColorValue | ColorValue[];
|
||||
width?: DimensionValue | null;
|
||||
disabled?: boolean;
|
||||
/**
|
||||
* Hide the whole component when set to false.
|
||||
*
|
||||
* @default true
|
||||
*/
|
||||
visible?: boolean;
|
||||
}
|
||||
|
||||
export const Checkbox = ({
|
||||
checked,
|
||||
title = null,
|
||||
onPress,
|
||||
type = "shade",
|
||||
style,
|
||||
textStyle,
|
||||
fontSize = AppFontSize.xs,
|
||||
fontFamily = "MEDIUM",
|
||||
iconSize = 16,
|
||||
iconColor,
|
||||
width = "100%",
|
||||
disabled,
|
||||
visible = true,
|
||||
...restProps
|
||||
}: CheckboxProps) => {
|
||||
const { colors } = useThemeColors();
|
||||
|
||||
if (!visible) return null;
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
{...restProps}
|
||||
onPress={onPress}
|
||||
disabled={disabled}
|
||||
type={type}
|
||||
style={{
|
||||
width: width || undefined,
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "flex-start",
|
||||
flexShrink: 1,
|
||||
gap: Spacing.LEVEL_1,
|
||||
paddingHorizontal: Spacing.LEVEL_2,
|
||||
paddingVertical: Spacing.LEVEL_2,
|
||||
borderRadius: Radius.XS,
|
||||
opacity: disabled ? 0.5 : 1,
|
||||
...style
|
||||
}}
|
||||
>
|
||||
<AppIcon
|
||||
name={checked ? "checkbox" : "box-empty"}
|
||||
iconFamily="notesnook"
|
||||
size={iconSize}
|
||||
color={
|
||||
iconColor ||
|
||||
(checked
|
||||
? [colors.primary.accent, colors.primary.accentForeground]
|
||||
: colors.primary.icon)
|
||||
}
|
||||
/>
|
||||
|
||||
{title ? (
|
||||
<Paragraph
|
||||
numberOfLines={1}
|
||||
size={fontSize}
|
||||
fontFamily={fontFamily}
|
||||
color={colors.primary.paragraph}
|
||||
style={[{ flexShrink: 1 }, textStyle]}
|
||||
>
|
||||
{title}
|
||||
</Paragraph>
|
||||
) : null}
|
||||
</Pressable>
|
||||
);
|
||||
};
|
||||
@@ -219,7 +219,6 @@ const Input = ({
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
paddingHorizontal: Spacing.LEVEL_2,
|
||||
paddingRight: Spacing.LEVEL_3,
|
||||
...containerStyle
|
||||
};
|
||||
|
||||
@@ -230,6 +229,7 @@ const Input = ({
|
||||
onPress && loading ? colors.primary.accent : colors.primary.paragraph,
|
||||
paddingTop: Spacing.LEVEL_3,
|
||||
paddingBottom: Spacing.LEVEL_3,
|
||||
lineHeight: fontSize + fontSize * 0.3,
|
||||
flexGrow: 1,
|
||||
flexShrink: 1,
|
||||
fontFamily: "Inter-Regular",
|
||||
|
||||
@@ -18,21 +18,39 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { View } from "react-native";
|
||||
import { DimensionValue, View, ViewStyle } from "react-native";
|
||||
import { useThemeColors } from "@notesnook/theme";
|
||||
import { Spacing } from "../../../common/design/spacing";
|
||||
|
||||
const LineSeparator = ({ padding }: { padding: keyof typeof Spacing }) => {
|
||||
const LineSeparator = ({
|
||||
style,
|
||||
paddingHorizontal,
|
||||
paddingVertical,
|
||||
stroke = 1
|
||||
}: {
|
||||
style?: ViewStyle;
|
||||
paddingHorizontal?: DimensionValue;
|
||||
paddingVertical?: DimensionValue;
|
||||
stroke?: number;
|
||||
}) => {
|
||||
const { colors } = useThemeColors();
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
width: "100%",
|
||||
height: 1,
|
||||
backgroundColor: colors.primary.border
|
||||
// marginVertical: Spacing[padding]
|
||||
}}
|
||||
/>
|
||||
style={[
|
||||
style,
|
||||
{
|
||||
paddingHorizontal,
|
||||
paddingVertical
|
||||
}
|
||||
]}
|
||||
>
|
||||
<View
|
||||
style={{
|
||||
width: "100%",
|
||||
height: stroke,
|
||||
backgroundColor: colors.primary.separator
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -488,7 +488,7 @@ export const useActions = ({
|
||||
actions.push({
|
||||
id: "rename-tag",
|
||||
title: strings.rename(),
|
||||
icon: "square-edit-outline",
|
||||
icon: "mode-edit",
|
||||
onPress: renameTag
|
||||
});
|
||||
}
|
||||
@@ -497,7 +497,7 @@ export const useActions = ({
|
||||
actions.push({
|
||||
id: "rename-color",
|
||||
title: strings.rename(),
|
||||
icon: "square-edit-outline",
|
||||
icon: "mode-edit",
|
||||
onPress: renameColor
|
||||
});
|
||||
}
|
||||
@@ -544,7 +544,7 @@ export const useActions = ({
|
||||
{
|
||||
id: "delete",
|
||||
title: strings.delete(),
|
||||
icon: "delete",
|
||||
icon: "trash-alt",
|
||||
onPress: deleteTrashItem
|
||||
}
|
||||
);
|
||||
@@ -557,7 +557,7 @@ export const useActions = ({
|
||||
title: isPinnedToMenu
|
||||
? strings.removeShortcut()
|
||||
: strings.addShortcut(),
|
||||
icon: isPinnedToMenu ? "link-variant-remove" : "link-variant",
|
||||
icon: "arrow-square-out",
|
||||
onPress: createMenuShortcut,
|
||||
isToggle: true,
|
||||
checked: isPinnedToMenu,
|
||||
@@ -570,7 +570,7 @@ export const useActions = ({
|
||||
? strings.removeAsDefault()
|
||||
: strings.setAsDefault(),
|
||||
hidden: item.type !== "tag",
|
||||
icon: "pound",
|
||||
icon: "check",
|
||||
onPress: async () => {
|
||||
if (defaultTag === item.id) {
|
||||
await db.settings.setDefaultTag(undefined);
|
||||
@@ -605,7 +605,7 @@ export const useActions = ({
|
||||
{
|
||||
id: "add-notebook",
|
||||
title: strings.addNotebook(),
|
||||
icon: "plus",
|
||||
icon: "bookmark",
|
||||
onPress: async () => {
|
||||
if (features && !features.notebooks.isAllowed) {
|
||||
ToastManager.show({
|
||||
@@ -626,16 +626,16 @@ export const useActions = ({
|
||||
},
|
||||
locked: !features?.notebooks.isAllowed
|
||||
},
|
||||
{
|
||||
id: "edit-notebook",
|
||||
title: strings.editNotebook(),
|
||||
icon: "square-edit-outline",
|
||||
onPress: async () => {
|
||||
close();
|
||||
await sleep(300);
|
||||
AddNotebookSheet.present(item);
|
||||
}
|
||||
},
|
||||
// {
|
||||
// id: "edit-notebook",
|
||||
// title: strings.editNotebook(),
|
||||
// icon: "square-edit-outline",
|
||||
// onPress: async () => {
|
||||
// close();
|
||||
// await sleep(300);
|
||||
// AddNotebookSheet.present(item);
|
||||
// }
|
||||
// },
|
||||
{
|
||||
id: "default-notebook",
|
||||
title:
|
||||
@@ -643,7 +643,7 @@ export const useActions = ({
|
||||
? strings.removeAsDefault()
|
||||
: strings.setAsDefault(),
|
||||
hidden: item.type !== "notebook",
|
||||
icon: "notebook",
|
||||
icon: "check",
|
||||
onPress: async () => {
|
||||
if (defaultNotebook === item.id) {
|
||||
await db.settings.setDefaultNotebook(undefined);
|
||||
@@ -678,7 +678,7 @@ export const useActions = ({
|
||||
id: "move-notes",
|
||||
title: strings.addNotes(),
|
||||
hidden: item.type !== "notebook",
|
||||
icon: "text",
|
||||
icon: "file-text",
|
||||
onPress: () => {
|
||||
close();
|
||||
Navigation.navigate("MoveNotes", {
|
||||
@@ -689,7 +689,7 @@ export const useActions = ({
|
||||
{
|
||||
id: "move-notebook",
|
||||
title: strings.moveNotebookFix(),
|
||||
icon: "arrow-right-bold-box-outline",
|
||||
icon: "drive-file-move",
|
||||
onPress: () => {
|
||||
close();
|
||||
Navigation.navigate("MoveNotebook", {
|
||||
@@ -704,7 +704,7 @@ export const useActions = ({
|
||||
actions.push({
|
||||
id: "pin",
|
||||
title: item.pinned ? strings.unpin() : strings.pin(),
|
||||
icon: item.pinned ? "pin-off-outline" : "pin-outline",
|
||||
icon: "pin",
|
||||
onPress: pinItem,
|
||||
isToggle: true,
|
||||
checked: item.pinned,
|
||||
@@ -720,7 +720,7 @@ export const useActions = ({
|
||||
actions.push({
|
||||
id: "default-homepage",
|
||||
title: isHomepage ? strings.unsetAsHomepage() : strings.setAsHomepage(),
|
||||
icon: "home-outline",
|
||||
icon: "house",
|
||||
isToggle: true,
|
||||
checked: isHomepage,
|
||||
onPress: async () => {
|
||||
@@ -1014,7 +1014,7 @@ export const useActions = ({
|
||||
{
|
||||
id: "favorite",
|
||||
title: !item.favorite ? strings.favorite() : strings.unfavorite(),
|
||||
icon: item.favorite ? "star-off" : "star-outline",
|
||||
icon: "star",
|
||||
onPress: addToFavorites,
|
||||
isToggle: true,
|
||||
checked: item.favorite,
|
||||
@@ -1053,19 +1053,19 @@ export const useActions = ({
|
||||
{
|
||||
id: "attachments",
|
||||
title: strings.attachedFiles(),
|
||||
icon: "attachment",
|
||||
icon: "paperclip",
|
||||
onPress: showAttachments
|
||||
},
|
||||
{
|
||||
id: "history",
|
||||
title: strings.history(),
|
||||
icon: "history",
|
||||
icon: "clock-counter-clockwise",
|
||||
onPress: openHistory
|
||||
},
|
||||
{
|
||||
id: "reminders",
|
||||
title: strings.dataTypesPluralCamelCase.reminder(),
|
||||
icon: "clock-outline",
|
||||
icon: "clock",
|
||||
onPress: async () => {
|
||||
close();
|
||||
RelationsList.present({
|
||||
@@ -1095,40 +1095,40 @@ export const useActions = ({
|
||||
{
|
||||
id: "copy",
|
||||
title: strings.copy(),
|
||||
icon: "content-copy",
|
||||
icon: "copy",
|
||||
onPress: copyContent
|
||||
},
|
||||
{
|
||||
id: "share",
|
||||
title: strings.share(),
|
||||
icon: "share-variant",
|
||||
icon: "share",
|
||||
onPress: shareNote
|
||||
},
|
||||
{
|
||||
id: "read-only",
|
||||
title: strings.readOnly(),
|
||||
icon: "pencil-lock",
|
||||
icon: "pencil-simple-slash",
|
||||
onPress: toggleReadyOnlyMode,
|
||||
checked: item.readonly
|
||||
},
|
||||
{
|
||||
id: "local-only",
|
||||
title: strings.syncOff(),
|
||||
icon: "sync-off",
|
||||
icon: "sync-disabled",
|
||||
onPress: toggleLocalOnly,
|
||||
checked: item.localOnly
|
||||
},
|
||||
{
|
||||
id: "duplicate",
|
||||
title: strings.duplicate(),
|
||||
icon: "content-duplicate",
|
||||
icon: "duplicate",
|
||||
onPress: duplicateNote
|
||||
},
|
||||
|
||||
{
|
||||
id: "add-reminder",
|
||||
title: strings.remindMe(),
|
||||
icon: "clock-plus-outline",
|
||||
icon: "bell",
|
||||
onPress: async () => {
|
||||
close();
|
||||
await sleep(100);
|
||||
@@ -1138,7 +1138,7 @@ export const useActions = ({
|
||||
{
|
||||
id: "lock-unlock",
|
||||
title: locked ? strings.unlock() : strings.lock(),
|
||||
icon: locked ? "lock-open-outline" : "key-outline",
|
||||
icon: "lock",
|
||||
onPress: addToVault,
|
||||
checked: locked
|
||||
},
|
||||
@@ -1163,16 +1163,16 @@ export const useActions = ({
|
||||
icon: "book-outline",
|
||||
onPress: addTo
|
||||
},
|
||||
{
|
||||
id: "add-tag",
|
||||
title: strings.addTags(),
|
||||
icon: "pound",
|
||||
onPress: addTo
|
||||
},
|
||||
// {
|
||||
// id: "add-tag",
|
||||
// title: strings.addTags(),
|
||||
// icon: "pound",
|
||||
// onPress: addTo
|
||||
// },
|
||||
{
|
||||
id: "references",
|
||||
title: strings.references(),
|
||||
icon: "vector-link",
|
||||
icon: "link-alt",
|
||||
onPress: () => {
|
||||
ReferencesList.present({
|
||||
reference: item as ItemReference
|
||||
@@ -1272,7 +1272,7 @@ export const useActions = ({
|
||||
item.type !== "notebook" && item.type !== "note"
|
||||
? strings.doActions.delete.unknown(item.type, 1)
|
||||
: strings.moveToTrash(),
|
||||
icon: "delete-outline",
|
||||
icon: "trash-alt",
|
||||
type: "error",
|
||||
onPress: deleteItem,
|
||||
locked: isPublished
|
||||
@@ -1289,7 +1289,7 @@ export const useActions = ({
|
||||
actions.push({
|
||||
id: "launcher-shortcut",
|
||||
title: strings.addToHome(),
|
||||
icon: "cellphone-arrow-down",
|
||||
icon: "home",
|
||||
locked: !features?.androidLauncherShortcuts.isAllowed,
|
||||
onPress: async () => {
|
||||
if (features && !features?.androidLauncherShortcuts.isAllowed) {
|
||||
|
||||
@@ -139,6 +139,7 @@ const showActionsheet = async () => {
|
||||
.getNoteIdForTab(useTabStore.getState().currentTab!);
|
||||
if (noteId) {
|
||||
const note = await db.notes?.note(noteId);
|
||||
if (!note) return;
|
||||
Properties.present(note, false);
|
||||
} else {
|
||||
ToastManager.show({
|
||||
|
||||
@@ -67,7 +67,7 @@ export const Home = ({ navigation, route }: NavigationProps<"Notes">) => {
|
||||
onPressDefaultRightButton={openEditor}
|
||||
/>
|
||||
|
||||
<LineSeparator padding="LEVEL_3" />
|
||||
<LineSeparator />
|
||||
|
||||
<DelayLayout wait={loading}>
|
||||
<List
|
||||
|
||||
@@ -55,6 +55,8 @@ import { eSendEvent, ToastManager } from "../../services/event-manager";
|
||||
import { eUpdateNotebookRoute } from "../../utils/events";
|
||||
import { isFeatureAvailable } from "@notesnook/common";
|
||||
import PaywallSheet from "../../components/sheets/paywall";
|
||||
import { Radius, Spacing } from "../../common/design/spacing";
|
||||
import LineSeparator from "../../components/ui/seperator/line-separator";
|
||||
|
||||
const {
|
||||
useNotebookExpandedStore,
|
||||
@@ -136,14 +138,14 @@ export const MoveNotebook = (props: NavigationProps<"MoveNotebook">) => {
|
||||
excludedItems.push(notebook.id);
|
||||
}
|
||||
// Exclude and disable items as needed
|
||||
const filtered = tree.filter(item => !excludedItems.includes(item.notebook.id)).map(
|
||||
(treeItem) => {
|
||||
const filtered = tree
|
||||
.filter((item) => !excludedItems.includes(item.notebook.id))
|
||||
.map((treeItem) => {
|
||||
return {
|
||||
...treeItem,
|
||||
disabled: disabledItems.includes(treeItem.notebook.id)
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
});
|
||||
return filtered;
|
||||
}
|
||||
filterNotebooks().then((filtered) => {
|
||||
@@ -157,13 +159,14 @@ export const MoveNotebook = (props: NavigationProps<"MoveNotebook">) => {
|
||||
<NotebookItemWrapper
|
||||
index={index}
|
||||
item={item}
|
||||
hideNoteCount
|
||||
onPress={async () => {
|
||||
if (item.disabled) {
|
||||
ToastManager.show({
|
||||
type: "info",
|
||||
"message": "You cannot move the selected notebook(s) here"
|
||||
})
|
||||
return;
|
||||
if (item.disabled) {
|
||||
ToastManager.show({
|
||||
type: "info",
|
||||
message: "You cannot move the selected notebook(s) here"
|
||||
});
|
||||
return;
|
||||
}
|
||||
const selectedNotebook = item.notebook;
|
||||
presentDialog({
|
||||
@@ -223,7 +226,6 @@ export const MoveNotebook = (props: NavigationProps<"MoveNotebook">) => {
|
||||
return (
|
||||
<SafeAreaView
|
||||
style={{
|
||||
gap: DefaultAppStyles.GAP_VERTICAL,
|
||||
flex: 1,
|
||||
backgroundColor: colors.primary.background
|
||||
}}
|
||||
@@ -233,6 +235,9 @@ export const MoveNotebook = (props: NavigationProps<"MoveNotebook">) => {
|
||||
selectedNotebooks.length,
|
||||
selectedNotebooks[0].title
|
||||
)}
|
||||
style={{
|
||||
backgroundColor: "transparent"
|
||||
}}
|
||||
canGoBack
|
||||
/>
|
||||
|
||||
@@ -244,7 +249,7 @@ export const MoveNotebook = (props: NavigationProps<"MoveNotebook">) => {
|
||||
ListHeaderComponent={
|
||||
<View
|
||||
style={{
|
||||
paddingHorizontal: DefaultAppStyles.GAP
|
||||
paddingHorizontal: Spacing.LEVEL_3
|
||||
}}
|
||||
>
|
||||
<Input
|
||||
@@ -255,13 +260,17 @@ export const MoveNotebook = (props: NavigationProps<"MoveNotebook">) => {
|
||||
updateNotebooks();
|
||||
}, 300);
|
||||
}}
|
||||
containerStyle={{
|
||||
backgroundColor: colors.secondary.background,
|
||||
borderWidth: 0,
|
||||
borderRadius: Radius.S
|
||||
}}
|
||||
testID="move-notebook-search"
|
||||
button={{
|
||||
icon: "plus",
|
||||
onPress: async () => {
|
||||
const notebooksFeature = await isFeatureAvailable(
|
||||
"notebooks"
|
||||
);
|
||||
const notebooksFeature =
|
||||
await isFeatureAvailable("notebooks");
|
||||
if (!notebooksFeature.isAllowed) {
|
||||
ToastManager.show({
|
||||
message: notebooksFeature.error,
|
||||
@@ -287,17 +296,19 @@ export const MoveNotebook = (props: NavigationProps<"MoveNotebook">) => {
|
||||
color: colors.primary.icon
|
||||
}}
|
||||
/>
|
||||
|
||||
{moveToTopEnabled && tree.length > 0 ? (
|
||||
<Button
|
||||
title={strings.moveToTop()}
|
||||
style={{
|
||||
alignSelf: "flex-start",
|
||||
width: "100%",
|
||||
justifyContent: "space-between"
|
||||
justifyContent: "space-between",
|
||||
marginTop: Spacing.LEVEL_2
|
||||
}}
|
||||
icon="arrow-up-bold"
|
||||
iconPosition="right"
|
||||
type="secondaryAccented"
|
||||
type="accent"
|
||||
onPress={async () => {
|
||||
for (const notebook of selectedNotebooks) {
|
||||
if (
|
||||
@@ -325,6 +336,13 @@ export const MoveNotebook = (props: NavigationProps<"MoveNotebook">) => {
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
<LineSeparator
|
||||
paddingVertical={Spacing.LEVEL_3}
|
||||
style={{
|
||||
paddingBottom: Spacing.LEVEL_0
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
}
|
||||
ListEmptyComponent={
|
||||
@@ -354,11 +372,13 @@ const NotebookItemWrapper = React.memo(
|
||||
({
|
||||
item,
|
||||
index,
|
||||
onPress
|
||||
onPress,
|
||||
hideNoteCount
|
||||
}: {
|
||||
item: TreeItem;
|
||||
index: number;
|
||||
onPress: () => void;
|
||||
hideNoteCount?: boolean;
|
||||
}) => {
|
||||
const expanded = useNotebookExpandedStore(
|
||||
(state) => state.expanded[item.notebook.id]
|
||||
@@ -393,8 +413,7 @@ const NotebookItemWrapper = React.memo(
|
||||
return (
|
||||
<View
|
||||
style={{
|
||||
paddingHorizontal: DefaultAppStyles.GAP,
|
||||
marginTop: index === 0 ? DefaultAppStyles.GAP : 0
|
||||
paddingHorizontal: Spacing.LEVEL_3
|
||||
}}
|
||||
>
|
||||
<NotebookItem
|
||||
@@ -415,6 +434,13 @@ const NotebookItemWrapper = React.memo(
|
||||
useNotebookTreeStore.getState().removeChildren(item.notebook.id);
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
paddingVertical: Spacing.LEVEL_2
|
||||
}}
|
||||
subNotebookButtonStyle={{
|
||||
paddingVertical: Spacing.LEVEL_2
|
||||
}}
|
||||
hideNoteCount={hideNoteCount}
|
||||
disableExpand={disableExpand}
|
||||
selected={selected}
|
||||
selectionEnabled={selectionEnabled}
|
||||
|
||||
@@ -166,6 +166,7 @@ const NotebookScreen = ({ route, navigation }: NavigationProps<"Notebook">) => {
|
||||
rightButton={{
|
||||
name: "dots-vertical",
|
||||
onPress: () => {
|
||||
if (!notebook) return;
|
||||
Properties.present(notebook);
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -59,9 +59,14 @@ function confirmDeleteAllNotes(
|
||||
) {
|
||||
return new Promise<{ delete: boolean; deleteNotes: boolean }>((resolve) => {
|
||||
presentDialog({
|
||||
title: strings.doActions.delete.notebook(items.length),
|
||||
title: strings.moveToTrash() + "?",
|
||||
paragraph: `The selected notebook${items.length > 1 ? `s` : ``} will be moved to trash. You can restore them later.`,
|
||||
positiveText: strings.delete(),
|
||||
negativeText: strings.cancel(),
|
||||
icon: "warning-circle",
|
||||
iconType: "error",
|
||||
iconFamily: "notesnook",
|
||||
centered: true,
|
||||
positivePress: async (_inputValue, value) => {
|
||||
setTimeout(() => {
|
||||
resolve({ delete: true, deleteNotes: value });
|
||||
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user