fix note not updating

This commit is contained in:
ammarahm-ed
2020-10-26 11:14:02 +05:00
parent e7f9b6e743
commit 92d77c1cdd
7 changed files with 361 additions and 356 deletions

View File

@@ -1,388 +1,389 @@
import React, {useCallback, useEffect, useMemo, useState} from 'react'; import React, {useCallback, useEffect, useMemo, useState} from 'react';
import {Platform, RefreshControl, StyleSheet, Text, useWindowDimensions, View} from 'react-native'; import {
Platform,
RefreshControl,
StyleSheet,
Text,
useWindowDimensions,
View,
} from 'react-native';
import {initialWindowMetrics} from 'react-native-safe-area-context'; import {initialWindowMetrics} from 'react-native-safe-area-context';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {DataProvider, LayoutProvider, RecyclerListView} from 'recyclerlistview'; import {DataProvider, LayoutProvider, RecyclerListView} from 'recyclerlistview';
import {useTracked} from '../../provider'; import {useTracked} from '../../provider';
import {Actions} from '../../provider/Actions'; import {Actions} from '../../provider/Actions';
import {eSendEvent, ToastEvent} from '../../services/EventManager'; import {eSendEvent, ToastEvent} from '../../services/EventManager';
import {eClearSearch, eOpenLoginDialog, eScrollEvent,} from '../../utils/Events'; import {eClearSearch, eOpenLoginDialog, eScrollEvent} from '../../utils/Events';
import {PressableButton} from '../PressableButton'; import {PressableButton} from '../PressableButton';
import {COLORS_NOTE} from "../../utils/Colors"; import {COLORS_NOTE} from '../../utils/Colors';
import {SIZE, WEIGHT} from "../../utils/SizeUtils"; import {SIZE, WEIGHT} from '../../utils/SizeUtils';
import {db} from "../../utils/DB"; import {db} from '../../utils/DB';
const header = { const header = {
type: 'MAIN_HEADER', type: 'MAIN_HEADER',
}; };
const SimpleList = ({ const SimpleList = ({
data, data,
type, type,
placeholder, placeholder,
RenderItem, RenderItem,
focused, focused,
customRefresh, customRefresh,
customRefreshing, customRefreshing,
refreshCallback, refreshCallback,
}) => { }) => {
const [state, dispatch] = useTracked(); const [state, dispatch] = useTracked();
const {colors, selectionMode, user} = state; const {colors, selectionMode, user, messageBoardState} = state;
const searchResults = {...state.searchResults}; const searchResults = {...state.searchResults};
const [refreshing, setRefreshing] = useState(false); const [refreshing, setRefreshing] = useState(false);
const [dataProvider, setDataProvider] = useState( const [dataProvider, setDataProvider] = useState(
new DataProvider((r1, r2) => { new DataProvider((r1, r2) => {
return r1 !== r2; return r1 !== r2;
}), }),
); );
const {width, fontScale} = useWindowDimensions(); const {width, fontScale} = useWindowDimensions();
const listData = data; const listData = data;
const dataType = type; const dataType = type;
const _onScroll = (event) => { const _onScroll = (event) => {
if (!event) return; if (!event) return;
let y = event.nativeEvent.contentOffset.y; let y = event.nativeEvent.contentOffset.y;
eSendEvent(eScrollEvent, y); eSendEvent(eScrollEvent, y);
}; };
useEffect(() => { useEffect(() => {
loadData(); loadData();
}, [listData]); }, [listData]);
const loadData =() => { const loadData = () => {
let mainData = let mainData =
searchResults.type === type && searchResults.type === type &&
focused() && focused() &&
searchResults.results.length > 0 searchResults.results.length > 0
? searchResults.results ? searchResults.results
: listData; : listData;
let d = [header, ...mainData]; let d = [header, ...mainData];
setDataProvider( setDataProvider(dataProvider.cloneWithRows(d));
dataProvider.cloneWithRows(d), };
);
const RenderSectionHeader = ({item}) => (
<Text
style={[
{
color: colors.accent,
},
styles.sectionHeader,
]}>
{item.title}
</Text>
);
const _onRefresh = useCallback(async () => {
if (Platform.OS === 'ios') {
dispatch({
type: Actions.SYNCING,
syncing: true,
});
} else {
setRefreshing(true);
} }
try {
const RenderSectionHeader = ({item}) => ( let user = await db.user.get();
<Text dispatch({type: Actions.USER, user: user});
style={[ await db.sync();
{ ToastEvent.show('Sync Complete', 'success');
color: colors.accent, } catch (e) {
}, ToastEvent.show(
styles.sectionHeader, 'You must login to sync.',
]}> 'error',
{item.title} 'global',
</Text> 5000,
); () => {
eSendEvent(eOpenLoginDialog);
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);
},
'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,
},
styles.emptyList,
]}>
<>{placeholder}</>
</View>
);
const _layoutProvider = new LayoutProvider(
(index) => {
return dataProvider.getDataForIndex(index).type;
}, },
(type, dim) => { 'Login',
);
} finally {
if (Platform.OS === 'ios') {
dispatch({
type: Actions.SYNCING,
syncing: false,
});
} else {
setRefreshing(false);
}
if (refreshCallback) {
refreshCallback();
}
}
dispatch({type: Actions.ALL});
}, []);
switch (type) { const _ListEmptyComponent = (
case 'note': <View
dim.width = width; style={[
dim.height = 100 * fontScale; {
break; backgroundColor: colors.bg,
case 'notebook':
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;
dim.height = 30 * fontScale;
break;
case 'MAIN_HEADER':
dim.width = width;
dim.height =
(user && user.Id) || !listData[0] || selectionMode
? 0
: 40 * fontScale;
break;
default:
dim.width = width;
dim.height = 0;
}
}, },
); styles.emptyList,
]}>
<>{placeholder}</>
</View>
);
const _renderRow = (type, data, index) => { const _layoutProvider = new LayoutProvider(
switch (type) { (index) => {
case 'note': return dataProvider.getDataForIndex(index).type;
return <RenderItem item={data} pinned={data.pinned} index={index}/>; },
case 'notebook': (type, dim) => {
return <RenderItem item={data} pinned={data.pinned} index={index}/>; switch (type) {
case 'MAIN_HEADER': case 'note':
return <ListHeaderComponent type={dataType} data={listData}/>; dim.width = width;
case 'header': dim.height = 100 * fontScale;
return <RenderSectionHeader item={data}/>; break;
default: case 'notebook':
return <RenderItem item={data} index={index}/>; 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;
dim.height = 30 * fontScale;
break;
case 'MAIN_HEADER':
dim.width = width;
dim.height =
!messageBoardState.visible || !listData[0] || selectionMode
? 0
: 40 * fontScale;
break;
default:
dim.width = width;
dim.height = 0;
}
},
);
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} data={listData} />;
case 'header':
return <RenderSectionHeader item={data} />;
default:
return <RenderItem item={data} index={index} />;
}
};
const listStyle = useMemo(() => {
return {
height: '100%',
backgroundColor: colors.bg,
width: '100%',
paddingTop:
Platform.OS === 'ios'
? listData[0] && !selectionMode
? 130
: 130 - 60
: listData[0] && !selectionMode
? 150 - initialWindowMetrics.insets.top
: (150 - initialWindowMetrics.insets.top) - 60,
}; };
}, [selectionMode, listData, colors]);
const listStyle = useMemo(() => { return !listData || listData.length === 0 || !dataProvider ? (
return { _ListEmptyComponent
height: '100%', ) : (
backgroundColor: colors.bg, <RecyclerListView
width: '100%', layoutProvider={_layoutProvider}
paddingTop: dataProvider={dataProvider}
Platform.OS === 'ios' rowRenderer={_renderRow}
? listData[0] && !selectionMode onScroll={_onScroll}
? 130 renderFooter={() => <View style={{height: 400}} />}
: 130 - 60 scrollViewProps={{
: listData[0] && !selectionMode refreshControl: (
? 155 - initialWindowMetrics.insets.top <RefreshControl
: 155 - initialWindowMetrics.insets.top - 60, tintColor={colors.accent}
}; colors={[colors.accent]}
}, [selectionMode, listData, colors]); progressViewOffset={150}
onRefresh={customRefresh ? customRefresh : _onRefresh}
return !listData || listData.length === 0 || !dataProvider ? ( refreshing={customRefresh ? customRefreshing : refreshing}
_ListEmptyComponent />
) : ( ),
<RecyclerListView contentContainerStyle: {
layoutProvider={_layoutProvider} width: '100%',
dataProvider={dataProvider} alignSelf: 'center',
rowRenderer={_renderRow} minHeight: '100%',
onScroll={_onScroll} },
renderFooter={() => <View style={{height:400}} />} }}
scrollViewProps={{ style={listStyle}
refreshControl: ( />
<RefreshControl );
tintColor={colors.accent}
colors={[colors.accent]}
progressViewOffset={150}
onRefresh={customRefresh ? customRefresh : _onRefresh}
refreshing={customRefresh ? customRefreshing : refreshing}
/>
),
contentContainerStyle: {
width: '100%',
alignSelf: 'center',
minHeight: '100%',
},
}}
style={listStyle}
/>
);
}; };
export default SimpleList; export default SimpleList;
const SearchHeader = () => { const SearchHeader = () => {
const [state,] = useTracked(); const [state] = useTracked();
const {colors} = state; const {colors} = state;
const searchResults = {...state.searchResults}; const searchResults = {...state.searchResults};
return ( return (
<View style={styles.searchHeader}> <View style={styles.searchHeader}>
<Text <Text
style={{ style={{
fontFamily: WEIGHT.bold, fontFamily: WEIGHT.bold,
color: colors.accent, color: colors.accent,
fontSize: SIZE.xs, fontSize: SIZE.xs,
}}> }}>
Showing Results for {searchResults.keyword} Showing Results for {searchResults.keyword}
</Text> </Text>
<Text <Text
onPress={() => { onPress={() => {
eSendEvent(eClearSearch); eSendEvent(eClearSearch);
}} }}
style={{ style={{
fontFamily: WEIGHT.regular, fontFamily: WEIGHT.regular,
color: colors.errorText, color: colors.errorText,
fontSize: SIZE.xs, fontSize: SIZE.xs,
}}> }}>
Clear Clear
</Text> </Text>
</View> </View>
); );
}; };
const LoginCard = ({type, data}) => { const MessageCard = ({data}) => {
const [state,] = useTracked(); const [state] = useTracked();
const {colors, selectionMode, user, currentScreen} = state; const {colors, selectionMode, currentScreen, messageBoardState} = state;
return ( return (
<View> <View>
{(user && user.Id) || !data[0] || selectionMode ? null : ( {!messageBoardState.visible || !data[0] || selectionMode ? null : (
<PressableButton <PressableButton
onPress={() => { onPress={messageBoardState.onPress}
eSendEvent(eOpenLoginDialog); color={
}} COLORS_NOTE[currentScreen]
color={ ? COLORS_NOTE[currentScreen]
COLORS_NOTE[currentScreen] : colors.shade
? COLORS_NOTE[currentScreen] }
: colors.shade selectedColor={
} COLORS_NOTE[currentScreen]
selectedColor={ ? COLORS_NOTE[currentScreen]
COLORS_NOTE[currentScreen] : colors.accent
? COLORS_NOTE[currentScreen] }
: colors.accent alpha={!colors.night ? -0.02 : 0.1}
} opacity={0.12}
alpha={!colors.night ? -0.02 : 0.1} customStyle={styles.loginCard}>
opacity={0.12} <View
customStyle={styles.loginCard}> style={{
<View width: 25,
style={{ backgroundColor: COLORS_NOTE[currentScreen]
width: 25, ? COLORS_NOTE[currentScreen]
backgroundColor: COLORS_NOTE[currentScreen] : colors.accent,
? COLORS_NOTE[currentScreen] height: 25,
: colors.accent, borderRadius: 100,
height: 25, alignItems: 'center',
borderRadius: 100, justifyContent: 'center',
alignItems: 'center', }}>
justifyContent: 'center', <Icon
}}> style={styles.loginIcon}
<Icon name={messageBoardState.icon}
style={styles.loginIcon} color="white"
name="account-outline" size={SIZE.xs}
color="white" />
size={SIZE.xs} </View>
/> <View
</View> style={{
<View marginLeft: 10,
style={{ }}>
marginLeft: 10, <Text
}}> style={{
<Text fontFamily: WEIGHT.regular,
style={{ color: colors.icon,
fontFamily: WEIGHT.regular, fontSize: SIZE.xxs - 1,
color: colors.icon, }}>
fontSize: SIZE.xxs - 1, {messageBoardState.message}
}}> </Text>
You are not logged in <Text
</Text> style={{
<Text color: COLORS_NOTE[currentScreen]
style={{ ? COLORS_NOTE[currentScreen]
color: COLORS_NOTE[currentScreen] : colors.accent,
? COLORS_NOTE[currentScreen] fontSize: SIZE.xxs,
: colors.accent, }}>
fontSize: SIZE.xxs, {messageBoardState.data.actionText}
}}> </Text>
Login to sync your {type}. </View>
</Text> </PressableButton>
</View> )}
</PressableButton> </View>
)} );
</View>
);
}; };
const ListHeaderComponent = ({type, data}) => { const ListHeaderComponent = ({type, data}) => {
const [state,] = useTracked(); const [state] = useTracked();
const searchResults = {...state.searchResults}; const searchResults = {...state.searchResults};
return searchResults.type === type && searchResults.results.length > 0 ? ( return searchResults.type === type && searchResults.results.length > 0 ? (
<SearchHeader/> <SearchHeader />
) : ( ) : (
<LoginCard type={type} data={data}/> <MessageCard type={type} data={data} />
); );
}; };
const styles = StyleSheet.create({ const styles = StyleSheet.create({
loginCard: { loginCard: {
width: '100%', width: '100%',
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
justifyContent: 'flex-start', justifyContent: 'flex-start',
paddingHorizontal: 12, paddingHorizontal: 12,
alignSelf: 'center', alignSelf: 'center',
height: 40, height: 40,
borderRadius: 0, borderRadius: 0,
position: 'relative', position: 'relative',
}, },
loginIcon: { loginIcon: {
textAlign: 'center', textAlign: 'center',
textAlignVertical: 'center', textAlignVertical: 'center',
}, },
searchHeader: { searchHeader: {
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
justifyContent: 'space-between', justifyContent: 'space-between',
paddingHorizontal: 12, paddingHorizontal: 12,
height: 40, height: 40,
}, },
sectionHeader: { sectionHeader: {
fontFamily: WEIGHT.bold, fontFamily: WEIGHT.bold,
fontSize: SIZE.xs + 1, fontSize: SIZE.xs + 1,
paddingHorizontal: 12, paddingHorizontal: 12,
width: '100%', width: '100%',
alignSelf: 'center', alignSelf: 'center',
marginTop: 10, marginTop: 10,
height: 25, height: 25,
textAlignVertical: 'center', textAlignVertical: 'center',
}, },
emptyList: { emptyList: {
height: '100%', height: '100%',
width: '100%', width: '100%',
alignItems: 'center', alignItems: 'center',
alignSelf: 'center', alignSelf: 'center',
justifyContent: 'center', justifyContent: 'center',
opacity: 1, opacity: 1,
}, },
}); });

View File

@@ -73,5 +73,13 @@ export const defaultState = {
bottomButtonOnPress: () => {}, bottomButtonOnPress: () => {},
bottomButtonText: 'Create a new note', bottomButtonText: 'Create a new note',
}, },
messageBoardState: {
visible:false,
message:null,
actionText:null,
onPress:() => {},
data:{},
icon:'account-outline'
},
keyword: [], keyword: [],
}; };

View File

@@ -24,7 +24,7 @@ async function run() {
await MMKV.setItem('backupDate', JSON.stringify(Date.now())); await MMKV.setItem('backupDate', JSON.stringify(Date.now()));
ToastEvent.show('Backup complete!', 'success'); ToastEvent.show('Backup complete!', 'success');
return path; return path;
} }
async function getLastBackupDate() { async function getLastBackupDate() {
let date; let date;

View File

@@ -9,7 +9,6 @@ export async function setSetting(settings, name, value) {
let s = {...settings}; let s = {...settings};
s[name] = value; s[name] = value;
await MMKV.setStringAsync('settings', JSON.stringify(s)); await MMKV.setStringAsync('settings', JSON.stringify(s));
updateEvent({type: Actions.SETTINGS, settings: s}); updateEvent({type: Actions.SETTINGS, settings: s});
} }
@@ -17,7 +16,6 @@ export const dirs = RNFetchBlob.fs.dirs;
export const ANDROID_PATH = dirs.SDCardDir + '/Notesnook/'; export const ANDROID_PATH = dirs.SDCardDir + '/Notesnook/';
export const IOS_PATH = dirs.DocumentDir; export const IOS_PATH = dirs.DocumentDir;
export const getElevation = (elevation) => { export const getElevation = (elevation) => {
return { return {
elevation, elevation,
@@ -45,8 +43,6 @@ export const history = {
selectedItemsList: [], selectedItemsList: [],
}; };
export async function showContext(event, title) { export async function showContext(event, title) {
eSendEvent('showContextMenu', { eSendEvent('showContextMenu', {
location: { location: {

View File

@@ -261,7 +261,7 @@ export async function saveNote(caller) {
}, },
id: id, id: id,
}); });
if (!id) { if (!id || saveCounter < 3) {
updateEvent({ updateEvent({
type: Actions.NOTES, type: Actions.NOTES,
}); });

View File

@@ -39,9 +39,8 @@ export const Notebook = ({route, navigation}) => {
}; };
}, []); }, []);
const onFocus = useCallback(() => { const onFocus = () => {
onLoad(); onLoad();
dispatch({ dispatch({
type: Actions.HEADER_TEXT_STATE, type: Actions.HEADER_TEXT_STATE,
state: { state: {
@@ -61,7 +60,7 @@ export const Notebook = ({route, navigation}) => {
type: Actions.CURRENT_SCREEN, type: Actions.CURRENT_SCREEN,
screen: 'notebook', screen: 'notebook',
}); });
}, []); }
useEffect(() => { useEffect(() => {
navigation.addListener('focus', onFocus); navigation.addListener('focus', onFocus);

View File

@@ -55,6 +55,7 @@ export const Notes = ({route, navigation}) => {
}, []); }, []);
const init = (data) => { const init = (data) => {
console.log('refreshing notes!');
params = route.params; params = route.params;
if (data) { if (data) {
params = data; params = data;