diff --git a/apps/mobile/app/components/dialog/dialog-container.js b/apps/mobile/app/components/dialog/dialog-container.tsx
similarity index 69%
rename from apps/mobile/app/components/dialog/dialog-container.js
rename to apps/mobile/app/components/dialog/dialog-container.tsx
index 4ed387e35..db2584fc0 100644
--- a/apps/mobile/app/components/dialog/dialog-container.js
+++ b/apps/mobile/app/components/dialog/dialog-container.tsx
@@ -18,25 +18,36 @@ along with this program. If not, see .
*/
import React from "react";
-import { View } from "react-native";
+import { View, ViewProps } from "react-native";
import { DDS } from "../../services/device-detection";
import { useThemeColors } from "@notesnook/theme";
import { getElevationStyle } from "../../utils/elevation";
-const DialogContainer = ({ width, height, ...restProps }) => {
+const DialogContainer = ({
+ width,
+ height,
+ style,
+ ...restProps
+}: ViewProps & {
+ width?: any;
+ height?: any;
+}) => {
const { colors } = useThemeColors();
return (
);
};
diff --git a/apps/mobile/app/components/dialogs/color-picker/index.tsx b/apps/mobile/app/components/dialogs/color-picker/index.tsx
new file mode 100644
index 000000000..a80d1060f
--- /dev/null
+++ b/apps/mobile/app/components/dialogs/color-picker/index.tsx
@@ -0,0 +1,302 @@
+/*
+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 .
+*/
+import { isThemeColor, useThemeColors } from "@notesnook/theme";
+import React, { useRef, useState } from "react";
+import { TextInput, View } from "react-native";
+import { FlashList } from "react-native-actions-sheet";
+import Icon from "react-native-vector-icons/MaterialCommunityIcons";
+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 { Button } from "../../ui/button";
+import Input from "../../ui/input";
+import { PressableButton } from "../../ui/pressable";
+import { ToastManager } from "../../../services/event-manager";
+import { Toast } from "../../toast";
+import { db } from "../../../common/database";
+import { useRelationStore } from "../../../stores/use-relation-store";
+import { useMenuStore } from "../../../stores/use-menu-store";
+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
+}: {
+ visible: boolean;
+ setVisible: (value: boolean) => void;
+}) => {
+ const [selectedColor, setSelectedColor] = useState();
+ const { colors } = useThemeColors();
+ const inputRef = useRef(null);
+ const title = useRef();
+
+ const renderItem = ({
+ item
+ }: {
+ item: { colorOne: string; colorTwo: string; colorThree: string };
+ }) => (
+
+ {Object.keys(item).map((key) => (
+ {
+ const color = item[key as keyof typeof item];
+ setSelectedColor(color);
+ inputRef.current?.setNativeProps({
+ placeholder: color,
+ text: color
+ });
+ }}
+ >
+ {selectedColor === item[key as keyof typeof item] ? (
+
+ ) : null}
+
+ ))}
+
+ );
+
+ return (
+ {
+ setVisible(false);
+ useSettingStore.getState().setSheetKeyboardHandler(true);
+ }}
+ statusBarTranslucent={false}
+ centered
+ >
+
+
+
+
+
+
+ {
+ if (HEX_COLOR_REGEX_ALPHA.test(value)) {
+ setSelectedColor(value);
+ inputRef.current?.setNativeProps({
+ placeholder: value,
+ text: value
+ });
+ }
+ }}
+ />
+
+
+
+ {
+ title.current = value;
+ }}
+ placeholder={title.current || "Color title"}
+ />
+
+
+
+
+ );
+};
+
+export default ColorPicker;
diff --git a/apps/mobile/app/components/properties/color-tags.tsx b/apps/mobile/app/components/properties/color-tags.tsx
index 7f593aa0c..1bc8fdced 100644
--- a/apps/mobile/app/components/properties/color-tags.tsx
+++ b/apps/mobile/app/components/properties/color-tags.tsx
@@ -17,11 +17,10 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
-import { DefaultColors } from "@notesnook/core/dist/collections/colors";
-import { Color, ItemReference, Note } from "@notesnook/core/dist/types";
+import { Color, Note } from "@notesnook/core/dist/types";
import { useThemeColors } from "@notesnook/theme";
-import React, { useEffect, useState } from "react";
-import { View } from "react-native";
+import React, { useCallback, useEffect, useState } from "react";
+import { ScrollView, View } from "react-native";
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
import { notesnook } from "../../../e2e/test.ids";
import { db } from "../../common/database";
@@ -32,87 +31,29 @@ import { useRelationStore } from "../../stores/use-relation-store";
import { useSettingStore } from "../../stores/use-setting-store";
import { refreshNotesPage } from "../../utils/events";
import { SIZE } from "../../utils/size";
+import ColorPicker from "../dialogs/color-picker";
import { PressableButton } from "../ui/pressable";
+import { FlashList } from "react-native-actions-sheet";
+import { Button } from "../ui/button";
-export const ColorTags = ({ item }: { item: Note }) => {
+const ColorItem = ({ item, note }: { item: Color; note: Note }) => {
const { colors } = useThemeColors();
+ const [isLinked, setIsLinked] = useState();
const setColorNotes = useMenuStore((state) => state.setColorNotes);
- const isTablet = useSettingStore((state) => state.deviceMode) !== "mobile";
- const updater = useRelationStore((state) => state.updater);
-
- const getColorInfo = async (colorCode: string) => {
- const dbColor = await db.colors.all.find((v) =>
- v.and([v(`colorCode`, "==", colorCode)])
- );
- let isLinked = false;
-
- if (dbColor) {
- const hasRelation = await db.relations.from(dbColor, "note").has(item.id);
- if (hasRelation) {
- isLinked = true;
- }
- }
-
- return {
- linked: isLinked,
- item: dbColor
+ useEffect(() => {
+ const checkIsLinked = async (color: Color) => {
+ const hasRelation = await db.relations.from(color, "note").has(note.id);
+ return hasRelation;
};
- };
- const ColorItem = ({ name }: { name: keyof typeof DefaultColors }) => {
- const color = DefaultColors[name];
- const [colorInfo, setColorInfo] = useState<{
- linked: boolean;
- item: Color | undefined;
- }>();
+ checkIsLinked(item).then((info) => setIsLinked(info));
+ }, [item, note.id]);
- useEffect(() => {
- getColorInfo(color).then((info) => setColorInfo(info));
- }, [color]);
+ const toggleColor = async () => {
+ await db.relations.unlinkOfType("color", [item.id]);
- return (
- changeColor(name)}
- customStyle={{
- width: 30,
- height: 30,
- borderRadius: 100,
- justifyContent: "center",
- alignItems: "center",
- marginRight: isTablet ? 10 : undefined
- }}
- >
- {colorInfo?.linked ? (
-
- ) : null}
-
- );
- };
-
- const changeColor = async (color: string) => {
- const colorInfo = await getColorInfo(DefaultColors[color]);
-
- if (colorInfo.item) {
- if (colorInfo.linked) {
- await db.relations.unlink(colorInfo.item, item);
- } else {
- await db.relations.add(colorInfo.item, item);
- }
- } else {
- const colorId = await db.colors.add({
- title: color,
- colorCode: DefaultColors[color]
- });
-
- const dbColor = await db.colors.color(colorId);
- if (dbColor) {
- await db.relations.add(dbColor as unknown as ItemReference, item);
- }
+ if (!isLinked) {
+ await db.relations.add(item, note);
}
useRelationStore.getState().update();
@@ -122,20 +63,109 @@ export const ColorTags = ({ item }: { item: Note }) => {
};
return (
-
- {Object.keys(DefaultColors).map((name: keyof typeof DefaultColors) => {
- return ;
- })}
-
+ {isLinked ? (
+
+ ) : null}
+
+ );
+};
+
+export const ColorTags = ({ item }: { item: Note }) => {
+ const { colors } = useThemeColors();
+ const colorNotes = useMenuStore((state) => state.colorNotes);
+ const isTablet = useSettingStore((state) => state.deviceMode) !== "mobile";
+ const updater = useRelationStore((state) => state.updater);
+ const [visible, setVisible] = useState(false);
+ const note = item;
+
+ const renderItem = useCallback(
+ ({ item }: { item: Color }) => (
+
+ ),
+ [note]
+ );
+
+ return (
+ <>
+
+
+ {!colorNotes || !colorNotes.length ? (
+
+ >
);
};
diff --git a/apps/mobile/app/components/properties/items.js b/apps/mobile/app/components/properties/items.js
index 0ea79702a..fecf9a726 100644
--- a/apps/mobile/app/components/properties/items.js
+++ b/apps/mobile/app/components/properties/items.js
@@ -218,8 +218,7 @@ export const Items = ({ item, buttons, close }) => {
{topBarItems.map(renderTopBarItem)}
diff --git a/apps/mobile/app/services/event-manager.ts b/apps/mobile/app/services/event-manager.ts
index 90603b946..b9ef45752 100644
--- a/apps/mobile/app/services/event-manager.ts
+++ b/apps/mobile/app/services/event-manager.ts
@@ -64,6 +64,7 @@ export const eSubscribeEvent = (
eventName: string,
action: EventHandler
) => {
+ if (!action) return;
return eventManager.subscribe(eventName, action);
};
@@ -71,6 +72,7 @@ export const eUnSubscribeEvent = (
eventName: string,
action: EventHandler
) => {
+ if (!action) return;
eventManager.unsubscribe(eventName, action);
};
@@ -132,7 +134,7 @@ export function hideSheet() {
export type ToastOptions = {
heading?: string;
message?: string;
- context?: "global" | "local";
+ context?: any;
type?: "error" | "success" | "info";
duration?: number;
func?: () => void;
@@ -160,7 +162,7 @@ export const ToastManager = {
});
},
hide: () => eSendEvent(eHideToast),
- error: (e: Error, title?: string, context?: "global" | "local") => {
+ error: (e: Error, title?: string, context?: any) => {
ToastManager.show({
heading: title,
message: e?.message || "",