2023-03-16 21:22:21 +05:00
|
|
|
/*
|
|
|
|
|
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 qclone from "qclone";
|
|
|
|
|
import React, {
|
|
|
|
|
createContext,
|
2023-03-30 01:42:39 +05:00
|
|
|
useCallback,
|
2023-03-16 21:22:21 +05:00
|
|
|
useContext,
|
|
|
|
|
useEffect,
|
|
|
|
|
useRef,
|
2023-03-31 23:07:29 +05:00
|
|
|
useState,
|
|
|
|
|
RefObject
|
2023-03-16 21:22:21 +05:00
|
|
|
} from "react";
|
2023-03-31 01:40:34 +05:00
|
|
|
import { Platform, RefreshControl, View } from "react-native";
|
2023-03-16 21:22:21 +05:00
|
|
|
import ActionSheet, {
|
|
|
|
|
ActionSheetRef,
|
|
|
|
|
FlatList
|
|
|
|
|
} from "react-native-actions-sheet";
|
|
|
|
|
import { db } from "../../../common/database";
|
|
|
|
|
import { IconButton } from "../../../components/ui/icon-button";
|
|
|
|
|
import { PressableButton } from "../../../components/ui/pressable";
|
|
|
|
|
import Paragraph from "../../../components/ui/typography/paragraph";
|
|
|
|
|
import { TopicNotes } from "../../../screens/notes/topic-notes";
|
|
|
|
|
import {
|
|
|
|
|
eSendEvent,
|
|
|
|
|
eSubscribeEvent,
|
2023-03-30 01:42:39 +05:00
|
|
|
eUnSubscribeEvent,
|
|
|
|
|
presentSheet
|
2023-03-16 21:22:21 +05:00
|
|
|
} from "../../../services/event-manager";
|
|
|
|
|
import useNavigationStore, {
|
|
|
|
|
NotebookScreenParams
|
|
|
|
|
} from "../../../stores/use-navigation-store";
|
|
|
|
|
import { useThemeStore } from "../../../stores/use-theme-store";
|
2023-03-20 11:28:46 +05:00
|
|
|
import {
|
|
|
|
|
eOnNewTopicAdded,
|
|
|
|
|
eOnTopicSheetUpdate,
|
|
|
|
|
eOpenAddTopicDialog
|
|
|
|
|
} from "../../../utils/events";
|
2023-03-16 21:22:21 +05:00
|
|
|
import { normalize, SIZE } from "../../../utils/size";
|
2023-03-30 01:42:39 +05:00
|
|
|
import { GroupHeader, NotebookType, TopicType } from "../../../utils/types";
|
2023-03-16 21:22:21 +05:00
|
|
|
|
2023-03-31 00:55:12 +05:00
|
|
|
import { groupArray } from "@notesnook/core/utils/grouping";
|
|
|
|
|
import Config from "react-native-config";
|
2023-03-16 21:22:21 +05:00
|
|
|
import Icon from "react-native-vector-icons/MaterialCommunityIcons";
|
2023-03-31 00:55:12 +05:00
|
|
|
import { notesnook } from "../../../../e2e/test.ids";
|
2023-03-16 21:22:21 +05:00
|
|
|
import { openEditor } from "../../../screens/notes/common";
|
|
|
|
|
import { getTotalNotes, history } from "../../../utils";
|
|
|
|
|
import { deleteItems } from "../../../utils/functions";
|
|
|
|
|
import { presentDialog } from "../../dialog/functions";
|
2023-03-31 00:55:12 +05:00
|
|
|
import { Properties } from "../../properties";
|
2023-03-30 01:42:39 +05:00
|
|
|
import Sort from "../sort";
|
2023-03-31 23:07:29 +05:00
|
|
|
import { MMKV } from "../../../common/database/mmkv";
|
|
|
|
|
|
|
|
|
|
class TopicSheetConfig {
|
|
|
|
|
static storageKey: "$$sp";
|
|
|
|
|
static makeId(item: any) {
|
|
|
|
|
return `${TopicSheetConfig.storageKey}:${item.type}:${item.id}`;
|
|
|
|
|
}
|
|
|
|
|
static get(item: any) {
|
|
|
|
|
return MMKV.getInt(TopicSheetConfig.makeId(item)) || 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static set(item: any, index = 0) {
|
|
|
|
|
MMKV.setInt(TopicSheetConfig.makeId(item), index);
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-03-17 16:18:57 +05:00
|
|
|
|
2023-03-16 21:22:21 +05:00
|
|
|
export const TopicsSheet = () => {
|
2023-03-31 23:07:29 +05:00
|
|
|
const [collapsed, setCollapsed] = useState(false);
|
2023-03-16 21:22:21 +05:00
|
|
|
const currentScreen = useNavigationStore((state) => state.currentScreen);
|
|
|
|
|
const canShow =
|
|
|
|
|
currentScreen.name === "Notebook" || currentScreen.name === "TopicNotes";
|
|
|
|
|
const [notebook, setNotebook] = useState(
|
|
|
|
|
canShow
|
|
|
|
|
? db.notebooks?.notebook(
|
|
|
|
|
currentScreen?.notebookId || currentScreen?.id || ""
|
|
|
|
|
)?.data
|
|
|
|
|
: null
|
|
|
|
|
);
|
|
|
|
|
const [selection, setSelection] = useState<TopicType[]>([]);
|
|
|
|
|
const [enabled, setEnabled] = useState(false);
|
|
|
|
|
const colors = useThemeStore((state) => state.colors);
|
|
|
|
|
const ref = useRef<ActionSheetRef>(null);
|
2023-03-31 23:07:29 +05:00
|
|
|
const isTopic = currentScreen.name === "TopicNotes";
|
2023-03-30 01:42:39 +05:00
|
|
|
const [topics, setTopics] = useState(
|
|
|
|
|
notebook
|
|
|
|
|
? qclone(
|
|
|
|
|
groupArray(notebook.topics, db.settings?.getGroupOptions("topics"))
|
|
|
|
|
)
|
|
|
|
|
: []
|
|
|
|
|
);
|
2023-03-31 01:39:41 +05:00
|
|
|
|
2023-03-30 01:42:39 +05:00
|
|
|
const [groupOptions, setGroupOptions] = useState(
|
|
|
|
|
db.settings?.getGroupOptions("topics")
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const onUpdate = useCallback(() => {
|
|
|
|
|
setGroupOptions({ ...(db.settings?.getGroupOptions("topics") as any) });
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
eSubscribeEvent("groupOptionsUpdate", onUpdate);
|
|
|
|
|
return () => {
|
|
|
|
|
eUnSubscribeEvent("groupOptionsUpdate", onUpdate);
|
|
|
|
|
};
|
|
|
|
|
}, [onUpdate]);
|
|
|
|
|
|
2023-03-16 21:22:21 +05:00
|
|
|
const onRequestUpdate = React.useCallback(
|
|
|
|
|
(data?: NotebookScreenParams) => {
|
|
|
|
|
if (!canShow) return;
|
|
|
|
|
if (!data) data = { item: notebook } as NotebookScreenParams;
|
|
|
|
|
const _notebook = db.notebooks?.notebook(data.item?.id)
|
|
|
|
|
?.data as NotebookType;
|
|
|
|
|
if (_notebook) {
|
|
|
|
|
setNotebook(_notebook);
|
2023-03-30 01:42:39 +05:00
|
|
|
|
2023-03-31 23:07:29 +05:00
|
|
|
setTopics(
|
|
|
|
|
qclone(
|
|
|
|
|
groupArray(_notebook.topics, db.settings?.getGroupOptions("topics"))
|
|
|
|
|
)
|
|
|
|
|
);
|
2023-03-16 21:22:21 +05:00
|
|
|
}
|
|
|
|
|
},
|
2023-03-31 23:07:29 +05:00
|
|
|
[canShow, notebook]
|
2023-03-16 21:22:21 +05:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
2023-03-20 11:28:46 +05:00
|
|
|
const onTopicUpdate = () => {
|
|
|
|
|
onRequestUpdate();
|
|
|
|
|
};
|
|
|
|
|
eSubscribeEvent(eOnTopicSheetUpdate, onTopicUpdate);
|
2023-03-16 21:22:21 +05:00
|
|
|
eSubscribeEvent(eOnNewTopicAdded, onRequestUpdate);
|
|
|
|
|
return () => {
|
2023-03-20 11:28:46 +05:00
|
|
|
eUnSubscribeEvent(eOnTopicSheetUpdate, onRequestUpdate);
|
|
|
|
|
eUnSubscribeEvent(eOnNewTopicAdded, onTopicUpdate);
|
2023-03-16 21:22:21 +05:00
|
|
|
};
|
|
|
|
|
}, [onRequestUpdate]);
|
|
|
|
|
|
|
|
|
|
const PLACEHOLDER_DATA = {
|
|
|
|
|
heading: "Topics",
|
|
|
|
|
paragraph: "You have not added any topics yet.",
|
|
|
|
|
button: "Add first topic",
|
|
|
|
|
action: () => {
|
|
|
|
|
eSendEvent(eOpenAddTopicDialog, { notebookId: notebook.id });
|
|
|
|
|
},
|
|
|
|
|
loading: "Loading notebook topics"
|
|
|
|
|
};
|
|
|
|
|
|
2023-03-30 01:42:39 +05:00
|
|
|
const renderTopic = ({
|
|
|
|
|
item,
|
|
|
|
|
index
|
|
|
|
|
}: {
|
|
|
|
|
item: TopicType | GroupHeader;
|
|
|
|
|
index: number;
|
|
|
|
|
}) =>
|
|
|
|
|
(item as GroupHeader).type === "header" ? null : (
|
2023-03-31 23:07:29 +05:00
|
|
|
<TopicItem sheetRef={ref} item={item as TopicType} index={index} />
|
2023-03-30 01:42:39 +05:00
|
|
|
);
|
2023-03-16 21:22:21 +05:00
|
|
|
|
|
|
|
|
const selectionContext = {
|
|
|
|
|
selection: selection,
|
|
|
|
|
enabled,
|
|
|
|
|
setEnabled,
|
|
|
|
|
toggleSelection: (item: TopicType) => {
|
|
|
|
|
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) {
|
2023-03-31 23:07:29 +05:00
|
|
|
const id = isTopic ? currentScreen?.notebookId : currentScreen?.id;
|
|
|
|
|
const notebook = db.notebooks?.notebook(id as string)?.data;
|
|
|
|
|
ref.current?.show(
|
|
|
|
|
TopicSheetConfig.get({
|
|
|
|
|
type: isTopic ? "topic" : "notebook",
|
|
|
|
|
id: currentScreen.id
|
|
|
|
|
})
|
|
|
|
|
);
|
2023-03-31 00:55:12 +05:00
|
|
|
setTimeout(() => {
|
2023-03-31 23:07:29 +05:00
|
|
|
if (notebook) {
|
2023-03-31 01:39:41 +05:00
|
|
|
onRequestUpdate({
|
2023-03-31 23:07:29 +05:00
|
|
|
item: notebook
|
2023-03-31 01:39:41 +05:00
|
|
|
} as any);
|
|
|
|
|
}
|
2023-03-31 23:07:29 +05:00
|
|
|
}, 1);
|
2023-03-16 21:22:21 +05:00
|
|
|
} else {
|
|
|
|
|
ref.current?.hide();
|
|
|
|
|
}
|
|
|
|
|
}, [
|
|
|
|
|
canShow,
|
|
|
|
|
currentScreen?.id,
|
|
|
|
|
currentScreen.name,
|
|
|
|
|
currentScreen?.notebookId,
|
2023-03-31 23:07:29 +05:00
|
|
|
onRequestUpdate,
|
|
|
|
|
isTopic
|
2023-03-16 21:22:21 +05:00
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<ActionSheet
|
|
|
|
|
ref={ref}
|
|
|
|
|
isModal={false}
|
|
|
|
|
containerStyle={{
|
2023-03-31 00:55:12 +05:00
|
|
|
maxHeight: 300,
|
2023-03-16 21:22:21 +05:00
|
|
|
borderTopRightRadius: 15,
|
|
|
|
|
borderTopLeftRadius: 15,
|
|
|
|
|
backgroundColor: colors.bg,
|
|
|
|
|
borderWidth: 1,
|
2023-03-31 01:39:41 +05:00
|
|
|
borderColor: colors.nav,
|
2023-03-16 21:22:21 +05:00
|
|
|
borderBottomWidth: 0
|
|
|
|
|
}}
|
2023-03-31 01:39:41 +05:00
|
|
|
openAnimationConfig={{
|
|
|
|
|
friction: 10
|
|
|
|
|
}}
|
2023-03-31 23:07:29 +05:00
|
|
|
onSnapIndexChange={(index) => {
|
|
|
|
|
setCollapsed(index === 0);
|
|
|
|
|
TopicSheetConfig.set(
|
|
|
|
|
{
|
|
|
|
|
type: isTopic ? "topic" : "notebook",
|
|
|
|
|
id: currentScreen.id
|
|
|
|
|
},
|
|
|
|
|
index
|
|
|
|
|
);
|
|
|
|
|
}}
|
2023-03-16 21:22:21 +05:00
|
|
|
closable={!canShow}
|
|
|
|
|
elevation={10}
|
|
|
|
|
indicatorStyle={{
|
|
|
|
|
width: 100,
|
|
|
|
|
backgroundColor: colors.nav
|
|
|
|
|
}}
|
|
|
|
|
keyboardHandlerEnabled={false}
|
2023-03-30 13:51:05 +05:00
|
|
|
snapPoints={
|
|
|
|
|
Config.isTesting === "true"
|
|
|
|
|
? [100]
|
|
|
|
|
: [Platform.OS === "ios" ? 25 : 20, 100]
|
|
|
|
|
}
|
2023-03-31 23:07:29 +05:00
|
|
|
initialSnapIndex={1}
|
2023-03-16 21:22:21 +05:00
|
|
|
backgroundInteractionEnabled
|
|
|
|
|
gestureEnabled
|
2023-03-31 01:39:41 +05:00
|
|
|
>
|
|
|
|
|
<View
|
|
|
|
|
style={{
|
|
|
|
|
position: "absolute",
|
|
|
|
|
right: 12,
|
|
|
|
|
marginTop: -80
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<PressableButton
|
|
|
|
|
testID={notesnook.buttons.add}
|
|
|
|
|
type="accent"
|
|
|
|
|
accentColor={"accent"}
|
|
|
|
|
accentText="light"
|
|
|
|
|
onPress={openEditor}
|
|
|
|
|
customStyle={{
|
|
|
|
|
borderRadius: 100
|
2023-03-16 21:22:21 +05:00
|
|
|
}}
|
|
|
|
|
>
|
2023-03-31 01:39:41 +05:00
|
|
|
<View
|
|
|
|
|
style={{
|
|
|
|
|
alignItems: "center",
|
|
|
|
|
justifyContent: "center",
|
|
|
|
|
height: normalize(60),
|
|
|
|
|
width: normalize(60)
|
2023-03-16 21:22:21 +05:00
|
|
|
}}
|
|
|
|
|
>
|
2023-03-31 01:39:41 +05:00
|
|
|
<Icon name="plus" color="white" size={SIZE.xxl} />
|
|
|
|
|
</View>
|
|
|
|
|
</PressableButton>
|
|
|
|
|
</View>
|
2023-03-16 21:22:21 +05:00
|
|
|
<View
|
|
|
|
|
style={{
|
2023-03-31 00:55:12 +05:00
|
|
|
maxHeight: 300,
|
|
|
|
|
height: 300,
|
2023-03-16 21:22:21 +05:00
|
|
|
width: "100%"
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<View
|
|
|
|
|
style={{
|
|
|
|
|
flexDirection: "row",
|
|
|
|
|
justifyContent: "space-between",
|
|
|
|
|
paddingHorizontal: 12,
|
|
|
|
|
alignItems: "center"
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<Paragraph size={SIZE.xs} color={colors.icon}>
|
|
|
|
|
TOPICS
|
|
|
|
|
</Paragraph>
|
|
|
|
|
<View
|
|
|
|
|
style={{
|
|
|
|
|
flexDirection: "row"
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{enabled ? (
|
|
|
|
|
<IconButton
|
|
|
|
|
customStyle={{
|
|
|
|
|
marginLeft: 10
|
|
|
|
|
}}
|
|
|
|
|
onPress={async () => {
|
|
|
|
|
//@ts-ignore
|
|
|
|
|
history.selectedItemsList = selection;
|
|
|
|
|
presentDialog({
|
|
|
|
|
title: `Delete ${
|
|
|
|
|
selection.length > 1 ? "topics" : "topics"
|
|
|
|
|
}`,
|
|
|
|
|
paragraph: `Are you sure you want to delete ${
|
|
|
|
|
selection.length > 1 ? "these topicss?" : "this topics?"
|
|
|
|
|
}`,
|
|
|
|
|
positiveText: "Delete",
|
|
|
|
|
negativeText: "Cancel",
|
|
|
|
|
positivePress: async () => {
|
|
|
|
|
await deleteItems();
|
|
|
|
|
history.selectedItemsList = [];
|
|
|
|
|
setEnabled(false);
|
|
|
|
|
setSelection([]);
|
|
|
|
|
},
|
|
|
|
|
positiveType: "errorShade"
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}}
|
|
|
|
|
color={colors.pri}
|
|
|
|
|
tooltipText="Move to trash"
|
|
|
|
|
tooltipPosition={1}
|
|
|
|
|
name="delete"
|
|
|
|
|
size={22}
|
|
|
|
|
/>
|
|
|
|
|
) : (
|
2023-03-30 01:42:39 +05:00
|
|
|
<>
|
|
|
|
|
<IconButton
|
|
|
|
|
name={
|
|
|
|
|
groupOptions?.sortDirection === "asc"
|
|
|
|
|
? "sort-ascending"
|
|
|
|
|
: "sort-descending"
|
|
|
|
|
}
|
|
|
|
|
onPress={() => {
|
|
|
|
|
presentSheet({
|
|
|
|
|
component: <Sort screen="TopicSheet" type="topics" />
|
|
|
|
|
});
|
|
|
|
|
}}
|
|
|
|
|
testID="group-topic-button"
|
|
|
|
|
color={colors.pri}
|
|
|
|
|
size={22}
|
|
|
|
|
customStyle={{
|
|
|
|
|
width: 40,
|
|
|
|
|
height: 40
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
<IconButton
|
|
|
|
|
name="plus"
|
|
|
|
|
onPress={PLACEHOLDER_DATA.action}
|
|
|
|
|
testID="add-topic-button"
|
|
|
|
|
color={colors.pri}
|
|
|
|
|
size={22}
|
|
|
|
|
customStyle={{
|
|
|
|
|
width: 40,
|
|
|
|
|
height: 40
|
|
|
|
|
}}
|
|
|
|
|
/>
|
2023-03-31 23:07:29 +05:00
|
|
|
|
|
|
|
|
<IconButton
|
|
|
|
|
name={collapsed ? "chevron-up" : "chevron-down"}
|
|
|
|
|
onPress={() => {
|
|
|
|
|
if (ref.current?.currentSnapIndex() !== 0) {
|
|
|
|
|
setCollapsed(true);
|
|
|
|
|
ref.current?.snapToIndex(0);
|
|
|
|
|
} else {
|
|
|
|
|
setCollapsed(false);
|
|
|
|
|
ref.current?.snapToIndex(1);
|
|
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
color={colors.pri}
|
|
|
|
|
size={22}
|
|
|
|
|
customStyle={{
|
|
|
|
|
width: 40,
|
|
|
|
|
height: 40
|
|
|
|
|
}}
|
|
|
|
|
/>
|
2023-03-30 01:42:39 +05:00
|
|
|
</>
|
2023-03-16 21:22:21 +05:00
|
|
|
)}
|
|
|
|
|
</View>
|
|
|
|
|
</View>
|
|
|
|
|
<SelectionContext.Provider value={selectionContext}>
|
|
|
|
|
<FlatList
|
|
|
|
|
data={topics}
|
|
|
|
|
style={{
|
|
|
|
|
width: "100%"
|
|
|
|
|
}}
|
|
|
|
|
refreshControl={
|
|
|
|
|
<RefreshControl
|
|
|
|
|
refreshing={false}
|
|
|
|
|
onRefresh={() => {
|
|
|
|
|
onRequestUpdate();
|
|
|
|
|
}}
|
2023-03-17 14:26:48 +05:00
|
|
|
colors={[colors.accent]}
|
|
|
|
|
progressBackgroundColor={colors.bg}
|
2023-03-16 21:22:21 +05:00
|
|
|
/>
|
|
|
|
|
}
|
2023-03-30 01:42:39 +05:00
|
|
|
keyExtractor={(item) => (item as TopicType).id}
|
2023-03-16 21:22:21 +05:00
|
|
|
renderItem={renderTopic}
|
2023-03-17 14:21:32 +05:00
|
|
|
ListEmptyComponent={
|
|
|
|
|
<View
|
|
|
|
|
style={{
|
|
|
|
|
flex: 1,
|
|
|
|
|
justifyContent: "center",
|
|
|
|
|
alignItems: "center",
|
2023-03-31 23:07:29 +05:00
|
|
|
height: 200
|
2023-03-17 14:21:32 +05:00
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<Paragraph color={colors.icon}>No topics</Paragraph>
|
|
|
|
|
</View>
|
|
|
|
|
}
|
2023-03-16 21:22:21 +05:00
|
|
|
ListFooterComponent={<View style={{ height: 50 }} />}
|
|
|
|
|
/>
|
|
|
|
|
</SelectionContext.Provider>
|
|
|
|
|
</View>
|
|
|
|
|
</ActionSheet>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const SelectionContext = createContext<{
|
|
|
|
|
selection: TopicType[];
|
|
|
|
|
enabled: boolean;
|
|
|
|
|
setEnabled: (value: boolean) => void;
|
|
|
|
|
toggleSelection: (item: TopicType) => void;
|
|
|
|
|
}>({
|
|
|
|
|
selection: [],
|
|
|
|
|
enabled: false,
|
|
|
|
|
setEnabled: (value: boolean) => {},
|
|
|
|
|
toggleSelection: (item: TopicType) => {}
|
|
|
|
|
});
|
|
|
|
|
const useSelection = () => useContext(SelectionContext);
|
|
|
|
|
|
2023-03-31 23:07:29 +05:00
|
|
|
const TopicItem = ({
|
|
|
|
|
item,
|
|
|
|
|
index,
|
|
|
|
|
sheetRef
|
|
|
|
|
}: {
|
|
|
|
|
item: TopicType;
|
|
|
|
|
index: number;
|
|
|
|
|
sheetRef: RefObject<ActionSheetRef>;
|
|
|
|
|
}) => {
|
2023-03-16 21:22:21 +05:00
|
|
|
const screen = useNavigationStore((state) => state.currentScreen);
|
|
|
|
|
const colors = useThemeStore((state) => state.colors);
|
|
|
|
|
const selection = useSelection();
|
|
|
|
|
const isSelected =
|
|
|
|
|
selection.selection.findIndex((selected) => selected.id === item.id) > -1;
|
|
|
|
|
const isFocused = screen.id === item.id;
|
|
|
|
|
const notesCount = getTotalNotes(item);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<PressableButton
|
|
|
|
|
type={isSelected || isFocused ? "grayBg" : "transparent"}
|
|
|
|
|
onLongPress={() => {
|
|
|
|
|
if (selection.enabled) return;
|
|
|
|
|
selection.setEnabled(true);
|
|
|
|
|
selection.toggleSelection(item);
|
|
|
|
|
}}
|
2023-03-17 14:39:17 +05:00
|
|
|
testID={`topic-sheet-item-${index}`}
|
2023-03-16 21:22:21 +05:00
|
|
|
onPress={() => {
|
|
|
|
|
if (selection.enabled) {
|
|
|
|
|
selection.toggleSelection(item);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
TopicNotes.navigate(item, true);
|
2023-03-31 23:07:29 +05:00
|
|
|
sheetRef.current?.snapToIndex(0);
|
2023-03-16 21:22:21 +05:00
|
|
|
}}
|
|
|
|
|
customStyle={{
|
|
|
|
|
justifyContent: "space-between",
|
|
|
|
|
width: "100%",
|
|
|
|
|
alignItems: "center",
|
|
|
|
|
flexDirection: "row",
|
|
|
|
|
paddingHorizontal: 12,
|
|
|
|
|
borderRadius: 0
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<View
|
|
|
|
|
style={{
|
|
|
|
|
flexDirection: "row",
|
|
|
|
|
alignItems: "center"
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{selection.enabled ? (
|
|
|
|
|
<IconButton
|
|
|
|
|
size={SIZE.lg}
|
|
|
|
|
color={isSelected ? colors.accent : colors.icon}
|
|
|
|
|
name={
|
|
|
|
|
isSelected
|
|
|
|
|
? "check-circle-outline"
|
|
|
|
|
: "checkbox-blank-circle-outline"
|
|
|
|
|
}
|
|
|
|
|
/>
|
|
|
|
|
) : null}
|
|
|
|
|
<Paragraph size={SIZE.sm}>
|
|
|
|
|
{item.title}{" "}
|
|
|
|
|
{notesCount ? (
|
|
|
|
|
<Paragraph size={SIZE.xs} color={colors.icon}>
|
|
|
|
|
{notesCount}
|
|
|
|
|
</Paragraph>
|
|
|
|
|
) : null}
|
|
|
|
|
</Paragraph>
|
|
|
|
|
</View>
|
|
|
|
|
<IconButton
|
|
|
|
|
name="dots-horizontal"
|
|
|
|
|
customStyle={{
|
|
|
|
|
width: 40,
|
|
|
|
|
height: 40
|
|
|
|
|
}}
|
2023-03-17 16:18:57 +05:00
|
|
|
testID={notesnook.ids.notebook.menu}
|
2023-03-16 21:22:21 +05:00
|
|
|
onPress={() => {
|
|
|
|
|
Properties.present(item);
|
|
|
|
|
}}
|
|
|
|
|
left={0}
|
|
|
|
|
right={0}
|
|
|
|
|
bottom={0}
|
|
|
|
|
top={0}
|
|
|
|
|
color={colors.pri}
|
|
|
|
|
size={SIZE.xl}
|
|
|
|
|
/>
|
|
|
|
|
</PressableButton>
|
|
|
|
|
);
|
|
|
|
|
};
|