Files
notesnook/apps/mobile/src/components/SimpleList/index.js

320 lines
7.7 KiB
JavaScript
Raw Normal View History

2020-11-09 19:20:18 +05:00
import React, {useCallback, useEffect, useState} from 'react';
2020-11-04 15:06:06 +05:00
import {
Platform,
RefreshControl,
StyleSheet,
Text,
useWindowDimensions,
View,
} from 'react-native';
2020-09-09 14:55:59 +05:00
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
2020-09-18 20:47:52 +05:00
import {DataProvider, LayoutProvider, RecyclerListView} from 'recyclerlistview';
import {useTracked} from '../../provider';
2020-10-13 17:02:14 +05:00
import {Actions} from '../../provider/Actions';
import {eSendEvent, ToastEvent} from '../../services/EventManager';
2020-11-04 20:29:45 +05:00
import {
eOpenJumpToDialog,
eOpenLoginDialog,
eScrollEvent,
} from '../../utils/Events';
2020-09-18 20:47:52 +05:00
import {PressableButton} from '../PressableButton';
2020-10-26 11:14:02 +05:00
import {COLORS_NOTE} from '../../utils/Colors';
import {SIZE, WEIGHT} from '../../utils/SizeUtils';
import {db} from '../../utils/DB';
2020-11-04 15:06:06 +05:00
import {HeaderMenu} from '../Header/HeaderMenu';
2020-11-10 17:18:19 +05:00
import Heading from '../Typography/Heading';
import {ListHeaderComponent} from './ListHeaderComponent';
import Paragraph from '../Typography/Paragraph';
import {Button} from '../Button';
import Seperator from '../Seperator';
2020-09-18 20:47:52 +05:00
const header = {
2020-11-04 15:06:06 +05:00
type: 'MAIN_HEADER',
2020-09-18 20:47:52 +05:00
};
2020-05-10 22:19:23 +05:00
2020-03-09 20:06:55 +05:00
const SimpleList = ({
2020-11-04 15:06:06 +05:00
data,
type,
placeholder,
RenderItem,
customRefresh,
customRefreshing,
refreshCallback,
sortMenuButton,
scrollRef,
2020-11-04 20:29:45 +05:00
jumpToDialog,
2020-11-10 17:18:19 +05:00
placeholderData,
2020-11-04 15:06:06 +05:00
}) => {
const [state, dispatch] = useTracked();
2020-11-10 17:18:19 +05:00
const {colors, selectionMode} = state;
2020-11-04 15:06:06 +05:00
const searchResults = {...state.searchResults};
const [refreshing, setRefreshing] = useState(false);
const [dataProvider, setDataProvider] = useState(
new DataProvider((r1, r2) => {
return r1 !== r2;
}),
);
const {width, fontScale} = useWindowDimensions();
2020-11-04 15:06:06 +05:00
const listData = data;
const dataType = type;
const _onScroll = (event) => {
if (!event) return;
let y = event.nativeEvent.contentOffset.y;
eSendEvent(eScrollEvent, y);
};
2020-09-18 20:47:52 +05:00
2020-11-04 15:06:06 +05:00
useEffect(() => {
loadData();
2020-11-04 20:29:45 +05:00
}, [listData, searchResults.results]);
2020-11-04 15:06:06 +05:00
const loadData = () => {
2020-11-09 19:20:18 +05:00
let mainData = [header, ...listData];
setDataProvider(dataProvider.cloneWithRows(mainData));
2020-11-04 15:06:06 +05:00
};
2020-10-18 13:15:24 +05:00
2020-11-04 15:06:06 +05:00
const RenderSectionHeader = ({item, index}) => (
<View
style={{
flexDirection: 'row',
alignItems: 'center',
width: '100%',
justifyContent: 'space-between',
paddingHorizontal: 12,
2020-11-10 17:18:19 +05:00
height: 35,
2020-11-04 15:06:06 +05:00
}}>
<Text
onPress={() => {
2020-11-04 20:29:45 +05:00
console.log('clicekd');
if (jumpToDialog) {
eSendEvent(eOpenJumpToDialog);
}
2020-11-04 15:06:06 +05:00
}}
style={[
styles.sectionHeader,
{
color: colors.accent,
2020-11-10 17:18:19 +05:00
height: 35,
2020-11-04 20:29:45 +05:00
minWidth: 60,
2020-11-04 15:06:06 +05:00
},
]}>
{item.title}
</Text>
{index === 1 && sortMenuButton ? <HeaderMenu /> : null}
</View>
);
2020-10-26 11:14:02 +05:00
2020-11-04 15:06:06 +05:00
const _onRefresh = useCallback(async () => {
if (Platform.OS === 'ios') {
dispatch({
type: Actions.SYNCING,
syncing: true,
});
} else {
setRefreshing(true);
}
try {
let user = await db.user.get();
dispatch({type: Actions.USER, user: user});
await db.sync();
ToastEvent.show('Sync Complete', 'success');
} catch (e) {
ToastEvent.show(
'You must login to sync.',
'error',
'global',
5000,
() => {
eSendEvent(eOpenLoginDialog);
},
2020-11-04 15:06:06 +05:00
'Login',
);
} finally {
if (Platform.OS === 'ios') {
dispatch({
type: Actions.SYNCING,
syncing: false,
});
} else {
setRefreshing(false);
}
if (refreshCallback) {
refreshCallback();
}
}
dispatch({type: Actions.ALL});
}, []);
const _ListEmptyComponent = (
<View
style={[
{
backgroundColor: colors.bg,
2020-11-10 17:18:19 +05:00
height: '100%',
},
2020-11-04 15:06:06 +05:00
]}>
2020-11-10 17:18:19 +05:00
<ListHeaderComponent type={type} />
<View
style={{
flexGrow: 1,
justifyContent: 'center',
alignItems: 'center',
}}>
<Heading>{placeholderData.heading}</Heading>
<Paragraph color={colors.icon}>{placeholderData.paragraph}</Paragraph>
<Seperator />
{placeholderData.button && <Button
onPress={placeholderData.action}
color="bg"
title={placeholderData.button}
icon="plus"
iconColor="accent"
fontSize={SIZE.md}
/> }
</View>
2020-11-04 15:06:06 +05:00
</View>
);
const _layoutProvider = new LayoutProvider(
(index) => {
return dataProvider.getDataForIndex(index).type;
},
(type, dim) => {
switch (type) {
case 'note':
dim.width = width;
dim.height = 100 * fontScale;
break;
case 'notebook':
dim.width = width;
dim.height = 110 * fontScale;
break;
case 'trash':
dim.width = width;
dim.height = 110 * fontScale;
break;
case 'topic':
dim.width = width;
dim.height = 80 * fontScale;
break;
case 'tag':
dim.width = width;
dim.height = 80 * fontScale;
break;
case 'header':
dim.width = width;
2020-11-10 17:18:19 +05:00
dim.height = 35 * fontScale;
2020-11-04 15:06:06 +05:00
break;
case 'MAIN_HEADER':
dim.width = width;
2020-11-10 17:18:19 +05:00
dim.height = 200;
2020-11-04 15:06:06 +05:00
break;
default:
dim.width = width;
dim.height = 0;
}
},
);
2020-11-01 09:22:28 +05:00
2020-11-04 15:06:06 +05:00
const _renderRow = (type, data, index) => {
switch (type) {
case 'note':
return <RenderItem item={data} pinned={data.pinned} index={index} />;
case 'notebook':
return <RenderItem item={data} pinned={data.pinned} index={index} />;
case 'MAIN_HEADER':
return (
<ListHeaderComponent type={dataType} index={index} data={listData} />
);
case 'header':
return <RenderSectionHeader item={data} index={index} />;
default:
return <RenderItem item={data} index={index} />;
}
};
2020-09-27 10:15:19 +05:00
2020-11-04 15:06:06 +05:00
return !listData || listData.length === 0 || !dataProvider ? (
_ListEmptyComponent
) : (
<RecyclerListView
ref={scrollRef}
layoutProvider={_layoutProvider}
dataProvider={dataProvider}
rowRenderer={_renderRow}
onScroll={_onScroll}
2020-11-10 17:18:19 +05:00
canChangeSize={true}
2020-11-04 15:06:06 +05:00
renderFooter={() => <View style={{height: 400}} />}
scrollViewProps={{
refreshControl: (
<RefreshControl
2020-11-09 19:20:18 +05:00
style={{
opacity: 0,
elevation: 0,
}}
2020-11-04 15:06:06 +05:00
tintColor={colors.accent}
colors={[colors.accent]}
progressViewOffset={150}
onRefresh={customRefresh ? customRefresh : _onRefresh}
refreshing={customRefresh ? customRefreshing : refreshing}
/>
),
2020-11-09 19:20:18 +05:00
overScrollMode: 'always',
2020-11-04 15:06:06 +05:00
contentContainerStyle: {
width: '100%',
alignSelf: 'center',
minHeight: '100%',
},
}}
2020-11-09 18:13:47 +05:00
style={{
height: '100%',
backgroundColor: colors.bg,
width: '100%',
}}
2020-11-04 15:06:06 +05:00
/>
);
2020-03-09 20:06:55 +05:00
};
export default SimpleList;
2020-09-21 13:13:18 +05:00
2020-09-27 10:15:19 +05:00
const styles = StyleSheet.create({
2020-11-04 15:06:06 +05:00
loginCard: {
width: '100%',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-start',
paddingHorizontal: 12,
alignSelf: 'center',
height: 40,
borderRadius: 0,
position: 'relative',
},
loginIcon: {
textAlign: 'center',
textAlignVertical: 'center',
},
searchHeader: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
paddingHorizontal: 12,
height: 40,
},
sectionHeader: {
fontFamily: WEIGHT.bold,
2020-11-10 17:18:19 +05:00
fontSize: SIZE.sm,
2020-11-04 15:06:06 +05:00
alignSelf: 'center',
textAlignVertical: 'center',
},
emptyList: {
height: '100%',
width: '100%',
alignItems: 'center',
alignSelf: 'center',
justifyContent: 'center',
opacity: 1,
},
2020-09-27 10:15:19 +05:00
});