Files
notesnook/apps/mobile/app/components/list/index.js

211 lines
5.5 KiB
JavaScript
Raw Normal View History

/*
This file is part of the Notesnook project (https://notesnook.com/)
Copyright (C) 2022 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/>.
*/
2022-08-30 16:13:11 +05:00
import React, { useRef } from "react";
import { FlatList, RefreshControl, View } from "react-native";
import Animated, { FadeInDown } from "react-native-reanimated";
import { notesnook } from "../../../e2e/test.ids";
import { eSendEvent } from "../../services/event-manager";
import Sync from "../../services/sync";
import { useThemeStore } from "../../stores/use-theme-store";
import { db } from "../../common/database";
import { eScrollEvent } from "../../utils/events";
import { tabBarRef } from "../../utils/global-refs";
import JumpToSectionDialog from "../dialogs/jump-to-section";
import { Footer } from "../list-items/footer";
import { Header } from "../list-items/headers/header";
import { SectionHeader } from "../list-items/headers/section-header";
import { NoteWrapper } from "../list-items/note/wrapper";
import { NotebookWrapper } from "../list-items/notebook/wrapper";
import TagItem from "../list-items/tag";
import { Empty } from "./empty";
2020-09-18 20:47:52 +05:00
2022-02-28 15:05:40 +05:00
const renderItems = {
2021-06-13 14:58:54 +05:00
note: NoteWrapper,
notebook: NotebookWrapper,
topic: NotebookWrapper,
tag: TagItem,
2021-12-05 00:05:27 +05:00
section: SectionHeader,
header: SectionHeader
2021-06-05 01:35:58 +05:00
};
2022-01-22 12:57:05 +05:00
const RenderItem = ({ item, index, type, ...restArgs }) => {
2021-12-05 00:05:27 +05:00
if (!item) return <View />;
const Item = renderItems[item.itemType || item.type] || View;
const groupOptions = db.settings?.getGroupOptions(type);
const dateBy =
groupOptions.sortBy !== "title" ? groupOptions.sortBy : "dateEdited";
2021-08-17 09:33:49 +05:00
2022-06-21 12:50:27 +05:00
const tags =
2021-12-06 21:14:06 +05:00
item.tags
?.slice(0, 3)
?.map((item) => {
2021-12-06 21:14:06 +05:00
let tag = db.tags.tag(item);
if (!tag) return null;
return {
title: tag.title,
id: tag.id,
alias: tag.alias
};
})
.filter((t) => t !== null) || [];
return (
<Item
item={item}
tags={tags}
dateBy={dateBy}
index={index}
type={type}
{...restArgs}
/>
);
2021-12-06 21:14:06 +05:00
};
2021-06-13 14:58:54 +05:00
2022-02-28 13:48:59 +05:00
const List = ({
2021-06-05 01:35:58 +05:00
listData,
type,
refreshCallback,
placeholderData,
loading,
headerProps = {
heading: "Home",
2022-04-24 05:59:14 +05:00
color: null
2021-06-05 01:35:58 +05:00
},
screen,
ListHeader,
warning
2021-06-05 01:35:58 +05:00
}) => {
const colors = useThemeStore((state) => state.colors);
2021-06-05 01:35:58 +05:00
const scrollRef = useRef();
2022-06-13 10:55:42 +05:00
2022-06-21 12:50:27 +05:00
const renderItem = React.useCallback(
({ item, index }) => (
<RenderItem
item={item}
index={index}
color={headerProps.color}
title={headerProps.heading}
type={screen === "Notes" ? "home" : type}
2022-06-21 12:50:27 +05:00
screen={screen}
/>
),
2022-08-30 18:27:09 +05:00
[headerProps.color, headerProps.heading, screen, type]
2021-06-05 01:35:58 +05:00
);
const _onRefresh = async () => {
Sync.run("global", false, true, () => {
2022-07-20 23:12:52 +05:00
if (refreshCallback) {
refreshCallback();
}
});
2021-06-05 01:35:58 +05:00
};
const _onScroll = React.useCallback(
(event) => {
2021-06-05 01:35:58 +05:00
if (!event) return;
let y = event.nativeEvent.contentOffset.y;
eSendEvent(eScrollEvent, {
y,
2021-08-17 09:33:49 +05:00
screen
2021-06-05 01:35:58 +05:00
});
},
2021-08-17 09:33:49 +05:00
[screen]
2021-06-05 01:35:58 +05:00
);
let styles = {
width: "100%",
2021-06-05 01:35:58 +05:00
minHeight: 1,
2022-06-21 12:50:27 +05:00
minWidth: 1
2021-06-05 01:35:58 +05:00
};
const _keyExtractor = (item) => item.id || item.title;
2021-06-05 01:35:58 +05:00
return (
<>
2022-07-11 16:18:24 +05:00
<Animated.View
style={{
flex: 1
2022-04-13 13:54:06 +05:00
}}
entering={type === "search" ? undefined : FadeInDown}
2022-07-11 16:18:24 +05:00
>
<FlatList
style={styles}
keyExtractor={_keyExtractor}
ref={scrollRef}
testID={notesnook.list.id}
data={listData}
renderItem={renderItem}
onScroll={_onScroll}
windowSize={5}
onMomentumScrollEnd={() => {
tabBarRef.current?.unlock();
}}
2022-07-20 21:44:35 +05:00
directionalLockEnabled={true}
2022-07-11 16:18:24 +05:00
initialNumToRender={10}
keyboardShouldPersistTaps="always"
keyboardDismissMode="interactive"
refreshControl={
<RefreshControl
tintColor={colors.accent}
colors={[colors.accent]}
progressBackgroundColor={colors.nav}
onRefresh={_onRefresh}
refreshing={false}
/>
}
ListEmptyComponent={
<Empty
loading={loading}
placeholderData={placeholderData}
headerProps={headerProps}
type={type}
screen={screen}
/>
}
ListFooterComponent={<Footer />}
ListHeaderComponent={
<>
{ListHeader ? (
ListHeader
) : (
<Header
title={headerProps.heading}
color={headerProps.color}
type={type}
screen={screen}
warning={warning}
/>
)}
</>
}
/>
</Animated.View>
2022-02-28 15:32:55 +05:00
<JumpToSectionDialog
2021-07-13 10:19:06 +05:00
screen={screen}
2021-07-13 14:10:51 +05:00
data={listData}
type={screen === "Notes" ? "home" : type}
2021-07-13 10:19:06 +05:00
scrollRef={scrollRef}
/>
2021-06-05 01:35:58 +05:00
</>
);
};
2022-02-28 13:48:59 +05:00
export default List;