mobile: fix notebooks & colors

This commit is contained in:
Ammar Ahmed
2024-02-10 18:56:33 +05:00
committed by Abdullah Atta
parent 5afdd88eb7
commit 920598f943
15 changed files with 786 additions and 810 deletions

View File

@@ -18,27 +18,25 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import React, { PropsWithChildren } from "react";
import { KeyboardAvoidingView, Platform } from "react-native";
import { Platform, View, useWindowDimensions } from "react-native";
import useGlobalSafeAreaInsets from "../../hooks/use-global-safe-area-insets";
import useIsFloatingKeyboard from "../../hooks/use-is-floating-keyboard";
export const Container = ({ children }: PropsWithChildren) => {
const floating = useIsFloatingKeyboard();
const insets = useGlobalSafeAreaInsets();
const dimensions = useWindowDimensions();
return (
<KeyboardAvoidingView
behavior="padding"
enabled={Platform.OS === "ios" && !floating}
<View
style={{
flex: 1,
overflow: "hidden",
paddingTop: Platform.OS === "android" ? 0 : insets.top,
paddingBottom: Platform.OS === "android" ? 0 : insets.bottom
paddingBottom: Platform.OS === "android" ? 0 : insets.bottom,
height: dimensions.height,
width: "100%"
}}
>
{children}
</KeyboardAvoidingView>
</View>
);
};

View File

@@ -16,131 +16,27 @@ 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 { Color } from "@notesnook/core";
import { useThemeColors } from "@notesnook/theme";
import React, { useRef, useState } from "react";
import { TextInput, View } from "react-native";
import { FlashList } from "react-native-actions-sheet/dist/src/views/FlashList";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import ColorPickerWheel from "react-native-wheel-color-picker";
import { db } from "../../../common/database";
import { useStoredRef } from "../../../hooks/use-stored-ref";
import { ToastManager } from "../../../services/event-manager";
import { useMenuStore } from "../../../stores/use-menu-store";
import { useRelationStore } from "../../../stores/use-relation-store";
import { useSettingStore } from "../../../stores/use-setting-store";
import { SIZE } from "../../../utils/size";
import BaseDialog from "../../dialog/base-dialog";
import DialogContainer from "../../dialog/dialog-container";
import { Toast } from "../../toast";
import { Button } from "../../ui/button";
import Input from "../../ui/input";
import { PressableButton } from "../../ui/pressable";
import { Color } from "@notesnook/core";
const arrayOfColors = [
"#FF5733",
"#33FF57",
"#339DFF",
"#FF33E9",
"#E9FF33",
"#FF3395",
"#95FF33",
"#FF3369",
"#6933FF",
"#33FFC7",
"#FF5733",
"#33FF57",
"#339DFF",
"#FF33E9",
"#E9FF33",
"#FF3395",
"#95FF33",
"#FF3369",
"#6933FF",
"#33FFC7",
"#FF5733",
"#33FF57",
"#339DFF",
"#FF33E9",
"#E9FF33",
"#FF3395",
"#95FF33",
"#FF3369",
"#6933FF",
"#33FFC7",
"#FF5733",
"#33FF57",
"#339DFF",
"#FF33E9",
"#E9FF33",
"#FF3395",
"#95FF33",
"#FF3369",
"#6933FF",
"#33FFC7",
"#FF5733",
"#33FF57",
"#339DFF",
"#FF33E9",
"#E9FF33",
"#FF3395",
"#95FF33",
"#FF3369",
"#6933FF",
"#33FFC7",
"#FF5733",
"#33FF57",
"#339DFF",
"#FF33E9",
"#E9FF33",
"#FF3395",
"#95FF33",
"#FF3369",
"#6933FF",
"#33FFC7",
"#FF5733",
"#33FF57",
"#339DFF",
"#FF33E9",
"#E9FF33",
"#FF3395",
"#95FF33",
"#FF3369",
"#6933FF",
"#33FFC7",
"#FF5733",
"#33FF57",
"#339DFF",
"#FF33E9",
"#E9FF33",
"#FF3395",
"#95FF33",
"#FF3369",
"#6933FF",
"#33FFC7",
"#FF5733",
"#33FF57",
"#339DFF",
"#FF33E9",
"#E9FF33",
"#FF3395",
"#95FF33",
"#FF3369",
"#6933FF",
"#33FFC7"
];
const HEX_COLOR_REGEX_ALPHA =
/^#(?:(?:[\da-fA-F]{3}){1,2}|(?:[\da-fA-F]{4}){1,2})$/;
const convertToColorObjects = (colors: string[]) => {
const colorObjects = [];
for (let i = 0; i < colors.length; i += 3) {
colorObjects.push({
colorOne: colors[i],
colorTwo: colors[i + 1],
colorThree: colors[i + 2]
});
}
return colorObjects;
};
const ColorPicker = ({
visible,
setVisible,
@@ -154,43 +50,7 @@ const ColorPicker = ({
const { colors } = useThemeColors();
const inputRef = useRef<TextInput>(null);
const title = useRef<string>();
const renderItem = ({
item
}: {
item: { colorOne: string; colorTwo: string; colorThree: string };
}) => (
<View>
{Object.keys(item).map((key) => (
<PressableButton
key={item[key as keyof typeof item]}
type="accent"
accentColor={item[key as keyof typeof item]}
customStyle={{
width: 40,
height: 40,
borderRadius: 100,
justifyContent: "center",
alignItems: "center",
marginRight: 10,
marginBottom: 10
}}
onPress={() => {
const color = item[key as keyof typeof item];
setSelectedColor(color);
inputRef.current?.setNativeProps({
placeholder: color,
text: color
});
}}
>
{selectedColor === item[key as keyof typeof item] ? (
<Icon name="check" color="white" size={SIZE.lg} />
) : null}
</PressableButton>
))}
</View>
);
const colorRef = useStoredRef("color-ref", "#f0f0f0");
return (
<BaseDialog
@@ -205,101 +65,127 @@ const ColorPicker = ({
<Toast context="color-picker" />
<DialogContainer
style={{
paddingTop: 0
paddingTop: 0,
maxHeight: 600
}}
>
<View
style={{
padding: 20
}}
>
<FlashList
extraData={selectedColor}
horizontal
data={convertToColorObjects(arrayOfColors)}
renderItem={renderItem}
/>
<View>
<View
style={{
flexDirection: "row",
alignItems: "center",
paddingTop: 10,
columnGap: 10,
marginBottom: 10
width: "100%",
height: 250,
backgroundColor: selectedColor,
borderRadius: 10
}}
>
<Input
fwdRef={inputRef}
placeholder="#f0f0f0"
marginBottom={0}
onChangeText={(value) => {
if (HEX_COLOR_REGEX_ALPHA.test(value)) {
setSelectedColor(value);
inputRef.current?.setNativeProps({
placeholder: value,
text: value
});
}
}}
/>
<PressableButton
type="accent"
accentColor={selectedColor || colors.secondary.background}
customStyle={{
width: 45,
height: 45,
borderRadius: 100,
justifyContent: "center",
alignItems: "center"
<ColorPickerWheel
onColorChangeComplete={(color) => {
if (color === selectedColor) return;
colorRef.current = color;
setSelectedColor(color);
inputRef.current?.setNativeProps({
placeholder: color,
text: color
});
}}
useNativeLayout={true}
autoResetSlider={true}
color={colorRef.current}
sliderSize={30}
thumbSize={25}
shadeWheelThumb
shadeSliderThumb={true}
swatchesOnly={false}
swatches={false}
useNativeDriver={true}
/>
</View>
<Input
marginBottom={10}
onChangeText={(value) => {
title.current = value;
<View
style={{
paddingHorizontal: 12
}}
placeholder={title.current || "Color title"}
/>
>
<View
style={{
flexDirection: "row",
alignItems: "center",
paddingTop: 10,
columnGap: 10,
marginBottom: 10
}}
>
<Input
fwdRef={inputRef}
placeholder="#f0f0f0"
marginBottom={0}
onChangeText={(value) => {
if (HEX_COLOR_REGEX_ALPHA.test(value)) {
colorRef.current = value;
setSelectedColor(value);
}
}}
defaultValue={colorRef.current}
/>
<PressableButton
type="accent"
accentColor={selectedColor || colors.secondary.background}
customStyle={{
width: 45,
height: 45,
borderRadius: 100,
justifyContent: "center",
alignItems: "center"
}}
/>
</View>
<Button
title="Add color"
onPress={async () => {
if (!selectedColor)
return ToastManager.error(
new Error("Select a color"),
undefined,
"color-picker"
);
if (!title.current)
return ToastManager.error(
new Error("Enter a title for the color")
);
const exists = await db.colors.all.find((v) =>
v.and([v(`colorCode`, "==", selectedColor)])
);
if (exists)
return ToastManager.error(
new Error(`Color #${selectedColor} already exists`)
);
<Input
marginBottom={10}
onChangeText={(value) => {
title.current = value;
}}
defaultValue={title.current}
placeholder={title.current || "Color title"}
/>
const id = await db.colors.add({
title: title.current,
colorCode: selectedColor
});
useRelationStore.getState().update();
useMenuStore.getState().setColorNotes();
setVisible(false);
const color = await db.colors.color(id);
if (color) {
onColorAdded?.(color);
}
}}
type={selectedColor ? "grayAccent" : "grayBg"}
width="100%"
/>
<Button
title="Add color"
onPress={async () => {
if (!selectedColor)
return ToastManager.error(
new Error("Select a color"),
undefined,
"color-picker"
);
if (!title.current)
return ToastManager.error(
new Error("Enter a title for the color")
);
const exists = await db.colors.all.find((v) =>
v.and([v(`colorCode`, "==", selectedColor)])
);
if (exists)
return ToastManager.error(
new Error(`Color #${selectedColor} already exists`)
);
const id = await db.colors.add({
title: title.current,
colorCode: selectedColor
});
useRelationStore.getState().update();
useMenuStore.getState().setColorNotes();
setVisible(false);
const color = await db.colors.color(id);
if (color) {
onColorAdded?.(color);
}
}}
type={selectedColor ? "grayAccent" : "grayBg"}
width="100%"
/>
</View>
</View>
</DialogContainer>
</BaseDialog>

View File

@@ -26,6 +26,7 @@ import { presentSheet } from "../../services/event-manager";
import { ColorValues } from "../../utils/colors";
import { SIZE } from "../../utils/size";
import SheetProvider from "../sheet-provider";
import { PressableButton } from "../ui/pressable";
import { ReminderTime } from "../ui/reminder-time";
import Heading from "../ui/typography/heading";
import Paragraph from "../ui/typography/paragraph";
@@ -34,7 +35,6 @@ import { Items } from "./items";
import Notebooks from "./notebooks";
import { Synced } from "./synced";
import { TagStrip, Tags } from "./tags";
import { PressableButton } from "../ui/pressable";
const Line = ({ top = 6, bottom = 6 }) => {
const { colors } = useThemeColors();
@@ -225,7 +225,8 @@ Properties.present = async (item, buttons = [], isSheet) => {
"add-shortcut",
"trash",
"default-notebook",
"add-notebook"
"add-notebook",
"move-notes"
]);
break;
case "tag":

View File

@@ -55,7 +55,10 @@ const SheetProvider = ({ context = "global" }) => {
async (payload) => {
if (!payload.context) payload.context = "global";
if (payload.context !== context) return;
setData(payload);
setData((state) => {
if (state?.onClose) state.onClose();
return payload;
});
setVisible(true);
if (payload.editor) {
editor.current.refocus = false;

View File

@@ -174,7 +174,8 @@ export const AddNotebookSheet = ({
AddNotebookSheet.present = (
notebook?: Notebook,
parentNotebook?: Notebook,
context?: string
context?: string,
onClose?: () => void
) => {
presentSheet({
context: context,
@@ -184,6 +185,7 @@ AddNotebookSheet.present = (
parentNotebook={parentNotebook}
close={close}
/>
)
),
onClose: onClose
});
};

View File

@@ -25,8 +25,10 @@ import { Platform, View, useWindowDimensions } from "react-native";
import { ActionSheetRef } from "react-native-actions-sheet";
import { FlashList } from "react-native-actions-sheet/dist/src/views/FlashList";
import { db } from "../../../common/database";
import { useDBItem } from "../../../hooks/use-db-item";
import { presentSheet } from "../../../services/event-manager";
import Navigation from "../../../services/navigation";
import { createItemSelectionStore } from "../../../stores/item-selection-store";
import { updateNotebook } from "../../../utils/notebooks";
import { SIZE } from "../../../utils/size";
import { Dialog } from "../../dialog";
@@ -36,7 +38,8 @@ import { IconButton } from "../../ui/icon-button";
import { PressableButton } from "../../ui/pressable";
import Seperator from "../../ui/seperator";
import Paragraph from "../../ui/typography/paragraph";
import { useDBItem } from "../../../hooks/use-db-item";
const useItemSelectionStore = createItemSelectionStore(true);
export const MoveNotes = ({
notebook,
@@ -47,11 +50,11 @@ export const MoveNotes = ({
}) => {
const { colors } = useThemeColors();
const currentNotebook = notebook;
const selectionCount = useItemSelectionStore(
(state) => Object.keys(state.selection)?.length > 0
);
const { height } = useWindowDimensions();
const [selectedNoteIds, setSelectedNoteIds] = useState<string[]>([]);
const [notes, setNotes] = useState<VirtualizedGrouping<Note>>();
const [existingNoteIds, setExistingNoteIds] = useState<string[]>([]);
useEffect(() => {
db.notes?.all.sorted(db.settings.getGroupOptions("notes")).then((notes) => {
@@ -61,45 +64,26 @@ export const MoveNotes = ({
.from(currentNotebook, "note")
.get()
.then((existingNotes) => {
setExistingNoteIds(
existingNotes.map((existingNote) => existingNote.toId)
);
const selection: { [name: string]: any } = {};
existingNotes.forEach((rel) => {
selection[rel.toId] = "selected";
});
useItemSelectionStore.setState({
selection: selection,
initialState: selection
});
});
}, [currentNotebook]);
const select = React.useCallback(
(id: string) => {
const index = selectedNoteIds.indexOf(id);
if (index > -1) {
setSelectedNoteIds((selectedNoteIds) => {
const next = [...selectedNoteIds];
next.splice(index, 1);
return next;
});
} else {
setSelectedNoteIds((selectedNoteIds) => {
const next = [...selectedNoteIds];
next.push(id);
return next;
});
}
},
[selectedNoteIds]
);
return () => {
useItemSelectionStore.getState().reset();
};
}, [currentNotebook]);
const renderItem = React.useCallback(
({ index }: { item: boolean; index: number }) => {
return (
<SelectableNoteItem
id={index}
items={notes}
select={select}
selected={(id) => selectedNoteIds?.indexOf(id) > -1}
exists={(id) => existingNoteIds.indexOf(id) > -1}
/>
);
return <SelectableNoteItem id={index} items={notes} />;
},
[existingNoteIds, notes, select, selectedNoteIds]
[notes]
);
return (
@@ -135,12 +119,12 @@ export const MoveNotes = ({
data={notes?.placeholders}
renderItem={renderItem}
/>
{selectedNoteIds.length > 0 ? (
{selectionCount ? (
<Button
onPress={async () => {
await db.notes?.addToNotebook(
currentNotebook.id,
...selectedNoteIds
...useItemSelectionStore.getState().getSelectedItemIds()
);
updateNotebook(currentNotebook.id);
Navigation.queueRoutesForUpdate();
@@ -157,26 +141,28 @@ export const MoveNotes = ({
const SelectableNoteItem = ({
id,
items,
select,
selected,
exists
items
}: {
id: string | number;
items?: VirtualizedGrouping<Note>;
select: (id: string) => void;
selected?: (id: string) => boolean;
exists: (id: string) => boolean;
}) => {
const { colors } = useThemeColors();
const [item] = useDBItem(id, "note", items);
const selected = useItemSelectionStore((state) =>
item?.id ? state.selection[item.id] === "selected" : false
);
const exists = useItemSelectionStore((state) =>
item?.id ? state.initialState[item.id] === "selected" : false
);
return !item || exists(item.id) ? null : (
return !item || exists ? null : (
<PressableButton
testID="listitem.select"
onPress={() => {
if (!item) return;
select(item?.id);
useItemSelectionStore
.getState()
.markAs(item, selected ? "deselected" : "selected");
}}
type={"transparent"}
customStyle={{
@@ -194,17 +180,15 @@ const SelectableNoteItem = ({
}}
onPress={() => {
if (!item) return;
select(item?.id);
useItemSelectionStore
.getState()
.markAs(item, selected ? "deselected" : "selected");
}}
name={
selected?.(item?.id)
? "check-circle-outline"
: "checkbox-blank-circle-outline"
selected ? "check-circle-outline" : "checkbox-blank-circle-outline"
}
type="selected"
color={
selected?.(item?.id) ? colors.selected.icon : colors.primary.icon
}
color={selected ? colors.selected.icon : colors.primary.icon}
/>
<View

View File

@@ -18,13 +18,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { Notebook, VirtualizedGrouping } from "@notesnook/core";
import { useThemeColors } from "@notesnook/theme";
import React, {
createContext,
useContext,
useEffect,
useRef,
useState
} from "react";
import React, { useEffect, useRef, useState } from "react";
import { RefreshControl, View, useWindowDimensions } from "react-native";
import ActionSheet, { ActionSheetRef } from "react-native-actions-sheet";
import { FlashList } from "react-native-actions-sheet/dist/src/views/FlashList";
@@ -37,6 +31,7 @@ import { useNotebook } from "../../../hooks/use-notebook";
import NotebookScreen from "../../../screens/notebook";
import { openEditor } from "../../../screens/notes/common";
import { eSendEvent, presentSheet } from "../../../services/event-manager";
import { createItemSelectionStore } from "../../../stores/item-selection-store";
import useNavigationStore from "../../../stores/use-navigation-store";
import { useSelectionStore } from "../../../stores/use-selection-store";
import { eOnNotebookUpdated } from "../../../utils/events";
@@ -50,18 +45,7 @@ import Paragraph from "../../ui/typography/paragraph";
import { AddNotebookSheet } from "../add-notebook";
import Sort from "../sort";
const SelectionContext = createContext<{
selection: Notebook[];
enabled: boolean;
setEnabled: (value: boolean) => void;
toggleSelection: (item: Notebook) => void;
}>({
selection: [],
enabled: false,
setEnabled: (_value: boolean) => {},
toggleSelection: (_item: Notebook) => {}
});
const useSelection = () => useContext(SelectionContext);
const useItemSelectionStore = createItemSelectionStore(true, false);
type NotebookParentProp = {
parent?: NotebookParentProp;
@@ -106,10 +90,8 @@ export const NotebookSheet = () => {
const [collapsed, setCollapsed] = useState(false);
const currentRoute = useNavigationStore((state) => state.currentRoute);
const focusedRouteId = useNavigationStore((state) => state.focusedRouteId);
const enabled = useItemSelectionStore((state) => state.enabled);
const canShow = currentRoute === "Notebook";
const [selection, setSelection] = useState<Notebook[]>([]);
const [enabled, setEnabled] = useState(false);
const { colors } = useThemeColors("sheet");
const ref = useRef<ActionSheetRef>(null);
const currentItem = useRef<string>();
@@ -147,29 +129,6 @@ export const NotebookSheet = () => {
/>
);
const selectionContext = {
selection: selection,
enabled,
setEnabled,
toggleSelection: (item: Notebook) => {
setSelection((state) => {
const selection = [...state];
const index = selection.findIndex(
(selected) => selected.id === item.id
);
if (index > -1) {
selection.splice(index, 1);
if (selection.length === 0) {
setEnabled(false);
}
return selection;
}
selection.push(item);
return selection;
});
}
};
useEffect(() => {
if (canShow) {
setImmediate(async () => {
@@ -181,8 +140,10 @@ export const NotebookSheet = () => {
"Root changed to",
nextRoot
);
setSelection([]);
setEnabled(false);
useItemSelectionStore.setState({
enabled: false,
selection: {}
});
}
currentItem.current = nextRoot;
const snapPoint = NotebookSheetConfig.get({
@@ -200,8 +161,10 @@ export const NotebookSheet = () => {
onRequestUpdate();
});
} else {
setSelection([]);
setEnabled(false);
useItemSelectionStore.setState({
enabled: false,
selection: {}
});
ref.current?.hide();
}
}, [canShow, onRequestUpdate, focusedRouteId]);
@@ -305,12 +268,14 @@ export const NotebookSheet = () => {
}}
onPress={async () => {
await deleteItems(
selection.map((notebook) => notebook.id),
useItemSelectionStore.getState().getSelectedItemIds(),
"notebook"
);
useSelectionStore.getState().clearSelection();
setEnabled(false);
setSelection([]);
useItemSelectionStore.setState({
enabled: false,
selection: {}
});
return;
}}
color={colors.primary.icon}
@@ -328,8 +293,10 @@ export const NotebookSheet = () => {
}}
onPress={() => {
useSelectionStore.getState().clearSelection();
setEnabled(false);
setSelection([]);
useItemSelectionStore.setState({
enabled: false,
selection: {}
});
}}
color={colors.primary.icon}
tooltipText="Clear selection"
@@ -361,7 +328,10 @@ export const NotebookSheet = () => {
/>
<IconButton
name="plus"
onPress={PLACEHOLDER_DATA.action}
onPress={() => {
if (!notebook) return;
AddNotebookSheet.present(undefined, notebook, undefined);
}}
testID="add-notebook-button"
color={colors.primary.icon}
size={22}
@@ -393,39 +363,36 @@ export const NotebookSheet = () => {
)}
</View>
</View>
<SelectionContext.Provider value={selectionContext}>
<FlashList
data={notebooks?.placeholders}
style={{
width: "100%"
}}
estimatedItemSize={50}
refreshControl={
<RefreshControl
refreshing={false}
onRefresh={() => {
eSendEvent(eOnNotebookUpdated);
}}
colors={[colors.primary.accent]}
progressBackgroundColor={colors.primary.background}
/>
}
renderItem={renderNotebook}
ListEmptyComponent={
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
height: 200
}}
>
<Paragraph color={colors.primary.icon}>No notebooks</Paragraph>
</View>
}
ListFooterComponent={<View style={{ height: 50 }} />}
/>
</SelectionContext.Provider>
<FlashList
data={notebooks?.placeholders}
style={{
width: "100%"
}}
estimatedItemSize={50}
refreshControl={
<RefreshControl
refreshing={false}
onRefresh={() => {
eSendEvent(eOnNotebookUpdated);
}}
colors={[colors.primary.accent]}
progressBackgroundColor={colors.primary.background}
/>
}
renderItem={renderNotebook}
ListEmptyComponent={
<View
style={{
flex: 1,
justifyContent: "center",
alignItems: "center",
height: 200
}}
>
<Paragraph color={colors.primary.icon}>No notebooks</Paragraph>
</View>
}
/>
</View>
</ActionSheet>
);
@@ -453,9 +420,10 @@ const NotebookItem = ({
} = useNotebook(id, items, true);
const isFocused = useNavigationStore((state) => state.focusedRouteId === id);
const { colors } = useThemeColors("sheet");
const selection = useSelection();
const isSelected =
selection.selection.findIndex((selected) => selected.id === item?.id) > -1;
const isSelected = useItemSelectionStore((state) =>
item?.id ? state.selection[item.id] === "selected" : false
);
const enabled = useItemSelectionStore((state) => state.enabled);
const { fontScale } = useWindowDimensions();
const expanded = useNotebookExpandedStore((state) =>
@@ -472,15 +440,22 @@ const NotebookItem = ({
<PressableButton
type={isSelected || isFocused ? "selected" : "transparent"}
onLongPress={() => {
if (selection.enabled || !item) return;
selection.setEnabled(true);
selection.toggleSelection(item);
if (enabled || !item) return;
useItemSelectionStore.setState({
enabled: true,
selection: {}
});
useItemSelectionStore
.getState()
.markAs(item, isSelected ? "deselected" : "selected");
}}
testID={`notebook-sheet-item-${currentLevel}-${index}`}
onPress={() => {
if (!item) return;
if (selection.enabled) {
selection.toggleSelection(item);
if (enabled) {
useItemSelectionStore
.getState()
.markAs(item, isSelected ? "deselected" : "selected");
return;
}
NotebookScreen.navigate(item, true);
@@ -527,7 +502,7 @@ const NotebookItem = ({
/>
)}
{selection.enabled ? (
{enabled ? (
<IconButton
size={SIZE.lg}
color={isSelected ? colors.selected.icon : colors.primary.icon}

View File

@@ -38,9 +38,11 @@ import NoteHistory from "../components/note-history";
import { AddNotebookSheet } from "../components/sheets/add-notebook";
import MoveNoteSheet from "../components/sheets/add-to";
import ExportNotesSheet from "../components/sheets/export-notes";
import { MoveNotes } from "../components/sheets/move-notes/movenote";
import PublishNoteSheet from "../components/sheets/publish-note";
import { RelationsList } from "../components/sheets/relations-list/index";
import ReminderSheet from "../components/sheets/reminder";
import { useSideBarDraggingStore } from "../components/side-menu/dragging-store";
import {
ToastManager,
eSendEvent,
@@ -62,7 +64,6 @@ import { eOpenLoginDialog } from "../utils/events";
import { deleteItems } from "../utils/functions";
import { convertNoteToText } from "../utils/note-to-text";
import { sleep } from "../utils/time";
import { useSideBarDraggingStore } from "../components/side-menu/dragging-store";
export const useActions = ({
close,
@@ -469,6 +470,15 @@ export const useActions = ({
close();
},
on: defaultNotebook === item.id
},
{
id: "move-notes",
title: "Move notes",
hidden: item.type !== "notebook",
icon: "text",
func: () => {
MoveNotes.present(item);
}
}
);
}

View File

@@ -36,7 +36,6 @@ import { TaggedNotes } from "../screens/notes/tagged";
import Reminders from "../screens/reminders";
import { Search } from "../screens/search";
import Settings from "../screens/settings";
import AppLock from "../screens/settings/app-lock";
import Tags from "../screens/tags";
import Trash from "../screens/trash";
import { eSendEvent } from "../services/event-manager";

View File

@@ -32,7 +32,15 @@
"validator": "^13.5.2",
"zustand": "^3.6.0",
"katex": "0.16.2",
"@readme/data-urls": "3.0.0"
"@readme/data-urls": "3.0.0",
"react-native-wheel-color-picker": "^1.3.1",
"tinycolor2": "1.6.0",
"@azure/core-asynciterator-polyfill": "^1.0.2",
"@tanstack/react-query": "^4.29.19",
"@trpc/client": "10.38.3",
"@trpc/react-query": "10.38.3",
"@trpc/server": "10.38.3",
"kysely": "^0.26.3"
},
"sideEffects": false
}

View File

@@ -30,9 +30,14 @@ export interface SelectionStore extends State {
canEnableMultiSelectMode: boolean;
markAs: (item: Item, state: SelectionState | undefined) => void;
reset: () => void;
enabled?: boolean;
getSelectedItemIds: () => string[];
}
export function createItemSelectionStore(multiSelectMode = false) {
export function createItemSelectionStore(
multiSelectMode = false,
enabled = true
) {
return create<SelectionStore>((set, get) => ({
selection: {},
setSelection: (state) => {
@@ -45,6 +50,7 @@ export function createItemSelectionStore(multiSelectMode = false) {
selection: { ...get().initialState }
});
},
enabled: enabled,
canEnableMultiSelectMode: multiSelectMode,
initialState: {},
markAs: (item, state) => {
@@ -66,6 +72,18 @@ export function createItemSelectionStore(multiSelectMode = false) {
set({
multiSelect: !get().multiSelect
});
},
getSelectedItemIds: () => {
const selected: string[] = [];
if (!get().selection) return selected;
for (const item in get().selection) {
if (get().selection[item] === "selected") {
selected.push(item);
}
}
return selected;
}
}));
}

View File

@@ -71,6 +71,7 @@
"@babel/core": "^7.20.0",
"@babel/eslint-parser": "^7.16.5",
"@babel/plugin-transform-named-capturing-groups-regex": "^7.16.5",
"@babel/plugin-transform-private-methods": "^7.22.5",
"@babel/preset-env": "^7.20.0",
"@babel/runtime": "^7.20.0",
"@react-native/eslint-config": "^0.72.2",

File diff suppressed because it is too large Load Diff

View File

@@ -30,21 +30,13 @@
"react-refresh": "0.14.0"
},
"dependencies": {
"@azure/core-asynciterator-polyfill": "^1.0.2",
"@babel/plugin-transform-private-methods": "^7.22.5",
"@notesnook/common": "file:../../packages/common",
"@notesnook/core": "file:../../packages/core",
"@notesnook/editor": "file:../../packages/editor",
"@notesnook/editor-mobile": "file:../../packages/editor-mobile",
"@notesnook/logger": "file:../../packages/logger",
"@notesnook/themes-server": "file:../../servers/themes",
"@tanstack/react-query": "^4.29.19",
"@trpc/client": "10.38.3",
"@trpc/react-query": "10.38.3",
"@trpc/server": "10.38.3",
"kysely": "^0.26.3",
"react": "18.2.0",
"react-native": "0.72.0",
"tinycolor2": "1.6.0"
"react-native": "0.72.0"
}
}

View File

@@ -0,0 +1,18 @@
diff --git a/node_modules/react-native-wheel-color-picker/ColorPicker.js b/node_modules/react-native-wheel-color-picker/ColorPicker.js
index 5804b4f..fe2d3f0 100644
--- a/node_modules/react-native-wheel-color-picker/ColorPicker.js
+++ b/node_modules/react-native-wheel-color-picker/ColorPicker.js
@@ -706,8 +706,11 @@ module.exports = class ColorPicker extends Component {
</View>}
{!swatchesOnly && !sliderHidden && (discrete
? <View style={[ss.swatches, swatchStyle]} key={'$2'}>{this.disc}</View>
- : <View style={[ss.slider, sliderStyle]} key={'$2'}>
- <View style={[ss.grad, { backgroundColor: hex }]} key={'$2$1'}>
+ : <View style={[ss.slider, sliderStyle, {
+ marginBottom: 12,
+ paddingHorizontal: 12,
+ }]} key={'$2'}>
+ <View style={[ss.grad, { backgroundColor: hex, borderRadius: 10 }]} key={'$2$1'}>
<Image style={[ss.sliderImg, { opacity: !this.props.sliderLoadingIndicator || this.state.sliderImageLoaded ? 1 : 0 }]} source={row ? srcSliderRotated : srcSlider} onLoad={this.onSliderImageLoad} resizeMode="stretch" />
</View>
{(this.props.sliderLoadingIndicator ? this.state.sliderImageLoaded : true) && <Animated.View style={[ss.sliderThumb, sliderThumbStyle, Elevations[4], { pointerEvents: 'none' }]} key={'$2$2'} />}