update ActionSheetComponent

This commit is contained in:
Ammar Ahmed
2021-06-14 08:37:38 +05:00
parent c423a3b4f2
commit 9e6563749a
3 changed files with 235 additions and 287 deletions

View File

@@ -3,9 +3,7 @@ import { TextInput, TouchableOpacity, View } from 'react-native';
import {ScrollView} from 'react-native-gesture-handler'; import {ScrollView} from 'react-native-gesture-handler';
import {notesnook} from '../../../e2e/test.ids'; import {notesnook} from '../../../e2e/test.ids';
import {useTracked} from '../../provider'; import {useTracked} from '../../provider';
import { import {ToastEvent} from '../../services/EventManager';
ToastEvent
} from '../../services/EventManager';
import Navigation from '../../services/Navigation'; import Navigation from '../../services/Navigation';
import {db} from '../../utils/DB'; import {db} from '../../utils/DB';
import {SIZE} from '../../utils/SizeUtils'; import {SIZE} from '../../utils/SizeUtils';
@@ -250,7 +248,7 @@ export const ActionSheetTagsSection = ({item, close}) => {
onBlur={() => { onBlur={() => {
setFocused(false); setFocused(false);
}} }}
placeholder="#hashtag" placeholder="Add a tag"
onChangeText={_onChange} onChangeText={_onChange}
onSubmitEditing={_onSubmit} onSubmitEditing={_onSubmit}
onKeyPress={_onKeyPress} onKeyPress={_onKeyPress}

View File

@@ -6,39 +6,42 @@ import {
Keyboard, Keyboard,
ScrollView, ScrollView,
TouchableOpacity, TouchableOpacity,
View View,
} from 'react-native'; } from 'react-native';
import Share from 'react-native-share'; import Share from 'react-native-share';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {notesnook} from '../../../e2e/test.ids'; import {notesnook} from '../../../e2e/test.ids';
import { useTracked, useTrackedNotes } from '../../provider'; import {useTracked} from '../../provider';
import {Actions} from '../../provider/Actions'; import {Actions} from '../../provider/Actions';
import { useMenuStore, useNotebookStore, useNoteStore, useSelectionStore, useUserStore } from '../../provider/stores';
import { DDS } from '../../services/DeviceDetection';
import { import {
eSendEvent, useMenuStore,
openVault, useSelectionStore,
sendNoteEditedEvent, useUserStore,
ToastEvent } from '../../provider/stores';
} from '../../services/EventManager'; import {DDS} from '../../services/DeviceDetection';
import {eSendEvent, openVault, ToastEvent} from '../../services/EventManager';
import Navigation from '../../services/Navigation'; import Navigation from '../../services/Navigation';
import Sync from '../../services/Sync'; import Sync from '../../services/Sync';
import { doInBackground, editing, toTXT } from '../../utils'; import {editing, toTXT} from '../../utils';
import { import {
ACCENT, ACCENT,
COLOR_SCHEME, COLOR_SCHEME,
COLOR_SCHEME_DARK, COLOR_SCHEME_DARK,
COLOR_SCHEME_LIGHT, COLOR_SCHEME_LIGHT,
setColorScheme setColorScheme,
} from '../../utils/Colors'; } from '../../utils/Colors';
import {db} from '../../utils/DB'; import {db} from '../../utils/DB';
import { import {eOpenMoveNoteDialog, eOpenPublishNoteDialog} from '../../utils/Events';
eOpenMoveNoteDialog
} from '../../utils/Events';
import {deleteItems} from '../../utils/functions'; import {deleteItems} from '../../utils/functions';
import {MMKV} from '../../utils/mmkv'; import {MMKV} from '../../utils/mmkv';
import {opacity, pv, SIZE} from '../../utils/SizeUtils'; import {opacity, pv, SIZE} from '../../utils/SizeUtils';
import {sleep, timeConverter} from '../../utils/TimeUtils'; import {sleep, timeConverter} from '../../utils/TimeUtils';
import {Button} from '../Button';
import BaseDialog from '../Dialog/base-dialog';
import DialogButtons from '../Dialog/dialog-buttons';
import DialogContainer from '../Dialog/dialog-container';
import DialogHeader from '../Dialog/dialog-header';
import Input from '../Input';
import {PressableButton} from '../PressableButton'; import {PressableButton} from '../PressableButton';
import Heading from '../Typography/Heading'; import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph'; import Paragraph from '../Typography/Paragraph';
@@ -56,84 +59,61 @@ export const ActionSheetComponent = ({
getRef, getRef,
}) => { }) => {
const [state, dispatch] = useTracked(); const [state, dispatch] = useTracked();
const {colors,} = state; const {colors} = state;
const setNotes = useNoteStore(state => state.setNotes);
const setNotebooks = useNotebookStore(state => state.setNotebooks);
const clearSelection = useSelectionStore(state => state.clearSelection); const clearSelection = useSelectionStore(state => state.clearSelection);
const setSelectedItem = useSelectionStore(state => state.setSelectedItem); const setSelectedItem = useSelectionStore(state => state.setSelectedItem);
const setMenuPins = useMenuStore(state => state.setMenuPins); const setMenuPins = useMenuStore(state => state.setMenuPins);
const user = useUserStore(state => state.user); const user = useUserStore(state => state.user);
const lastSynced = useUserStore(state => state.lastSynced); const lastSynced = useUserStore(state => state.lastSynced);
const refreshing = false;
const [refreshing, setRefreshing] = useState(false); const [isPinnedToMenu, setIsPinnedToMenu] = useState(
const [isPinnedToMenu, setIsPinnedToMenu] = useState(false); db.settings.isPinned(item.id),
);
const [note, setNote] = useState(item); const [note, setNote] = useState(item);
const [noteInTopic, setNoteInTopic] = useState( const noteInTopic =
editing.actionAfterFirstSave.type === 'topic' && editing.actionAfterFirstSave.type === 'topic' &&
db.notebooks db.notebooks
.notebook(editing.actionAfterFirstSave.notebook) .notebook(editing.actionAfterFirstSave.notebook)
.topics.topic(editing.actionAfterFirstSave.id) .topics.topic(editing.actionAfterFirstSave.id)
.has(item.id), .has(item.id);
);
useEffect(() => {
if (item.id === null) return;
sleep(1000).then(() => {
setNote({...item});
if (item.type !== note) {
setIsPinnedToMenu(db.settings.isPinned(note.id));
}
});
}, [item]);
function changeColorScheme(colors = COLOR_SCHEME, accent = ACCENT) { function changeColorScheme(colors = COLOR_SCHEME, accent = ACCENT) {
let newColors = setColorScheme(colors, accent); let newColors = setColorScheme(colors, accent);
dispatch({type: Actions.THEME, colors: newColors}); dispatch({type: Actions.THEME, colors: newColors});
} }
useEffect(() => {
if (item.dateCreated !== null) {
setNote({...item});
if (item.type !== note) {
setIsPinnedToMenu(db.settings.isPinned(note.id));
}
}
}, [item]);
const localRefresh = (type, nodispatch = false) => { const localRefresh = (type, nodispatch = false) => {
if (!note || !note.id) return; if (!note || !note.id) return;
let toAdd; let _item;
switch (type) { switch (type) {
case 'note': { case 'note': {
toAdd = db.notes.note(note.id); _item = db.notes.note(note.id)?.data;
if (toAdd) {
toAdd = toAdd.data;
} else {
setTimeout(() => {
toAdd = db.notes.note(note.id);
if (toAdd) {
toAdd = toAdd.data;
}
}, 500);
}
break; break;
} }
case 'notebook': { case 'notebook': {
toAdd = db.notebooks.notebook(note.id); _item = db.notebooks.notebook(note.id)?.data;
if (toAdd) {
toAdd = toAdd.data;
} else {
setTimeout(() => {
toAdd = db.notebooks.notebook(note.id);
if (toAdd) {
toAdd = toAdd.data;
}
}, 500);
}
break; break;
} }
case 'topic': { case 'topic': {
toAdd = db.notebooks.notebook(note.notebookId).topics.topic(note.title); _item = db.notebooks.notebook(note.notebookId).topics.topic(note.title);
break; break;
} }
} }
if (!toAdd || !toAdd.id) return; if (!_item || !_item.id) return;
if (!nodispatch) { if (!nodispatch) {
Navigation.setRoutesToUpdate([ Navigation.setRoutesToUpdate([
@@ -147,7 +127,7 @@ export const ActionSheetComponent = ({
]); ]);
} }
setNote({...toAdd}); setNote({..._item});
}; };
const rowItemsData = [ const rowItemsData = [
@@ -156,7 +136,6 @@ export const ActionSheetComponent = ({
icon: 'book-outline', icon: 'book-outline',
func: () => { func: () => {
close(); close();
clearSelection(); clearSelection();
setSelectedItem(item); setSelectedItem(item);
setTimeout(() => { setTimeout(() => {
@@ -196,9 +175,28 @@ export const ActionSheetComponent = ({
close('export'); close('export');
}, },
}, },
{
name: 'Edit Notebook',
icon: 'square-edit-outline',
func: () => {
close('notebook');
},
},
{
name: 'Edit Topic',
icon: 'square-edit-outline',
func: () => {
close('topic');
},
},
{ {
name: 'Delete', name: 'Delete',
icon: 'delete', title:
note.type !== 'notebook' && note.type !== 'note'
? 'Delete ' + item.type
: 'Move to trash',
icon: 'delete-outline',
type: 'error',
func: async () => { func: async () => {
close(); close();
if (note.locked) { if (note.locked) {
@@ -215,24 +213,8 @@ export const ActionSheetComponent = ({
try { try {
close(); close();
await deleteItems(note); await deleteItems(note);
} catch (e) { } catch (e) {}
//console.log(e);
} }
}
},
},
{
name: 'Edit Notebook',
icon: 'square-edit-outline',
func: () => {
close('notebook');
},
},
{
name: 'Edit Topic',
icon: 'square-edit-outline',
func: () => {
close('topic');
}, },
}, },
{ {
@@ -293,6 +275,15 @@ export const ActionSheetComponent = ({
close('permanant_delete'); close('permanant_delete');
}, },
}, },
{
name: 'Publish',
icon: 'link-box-outline',
func: async () => {
close();
await sleep(300);
eSendEvent(eOpenPublishNoteDialog,note);
},
},
]; ];
const columnItemsData = [ const columnItemsData = [
@@ -314,9 +305,50 @@ export const ActionSheetComponent = ({
nopremium: true, nopremium: true,
id: notesnook.ids.dialogs.actionsheet.night, id: notesnook.ids.dialogs.actionsheet.night,
}, },
{
name: 'Vault',
title: note.locked ? 'Remove from vault' : 'Add to vault',
icon: note.locked ? 'shield-off-outline' : 'shield-outline',
func: async () => {
if (!note.id) return;
if (note.locked) {
close('unlock');
} else {
db.vault
.add(note.id)
.then(r => {
let n = db.notes.note(note.id).data;
if (n.locked) {
close();
}
Navigation.setRoutesToUpdate([
Navigation.routeNames.NotesPage,
Navigation.routeNames.Favorites,
Navigation.routeNames.Notes,
]);
localRefresh(note.type);
})
.catch(async e => {
switch (e.message) {
case db.vault.ERRORS.noVault:
close('novault');
break;
case db.vault.ERRORS.vaultLocked:
close('locked');
break;
case db.vault.ERRORS.wrongPassword:
close();
break;
}
});
}
},
on: note.locked,
},
{ {
name: 'Pin', name: 'Pin',
icon: 'pin', title: note.pinned ? 'Unpin from top' : 'Pin to top',
icon: note.pinned ? 'pin-off-outline' : 'pin-outline',
func: async () => { func: async () => {
if (!note.id) return; if (!note.id) return;
close(); close();
@@ -351,7 +383,8 @@ export const ActionSheetComponent = ({
}, },
{ {
name: 'Favorite', name: 'Favorite',
icon: 'star', title: !note.favorite ? 'Add to favorites' : 'Remove from favorites',
icon: note.favorite ? 'star-off' : 'star-outline',
func: async () => { func: async () => {
if (!note.id) return; if (!note.id) return;
close(); close();
@@ -375,9 +408,8 @@ export const ActionSheetComponent = ({
color: 'orange', color: 'orange',
}, },
{ {
name: isPinnedToMenu name: 'Add Shortcut to Menu',
? 'Remove Shortcut from Menu' title: isPinnedToMenu ? 'Remove Shortcut' : 'Add Shortcut to Menu',
: 'Add Shortcut to Menu',
icon: isPinnedToMenu ? 'link-variant-remove' : 'link-variant', icon: isPinnedToMenu ? 'link-variant-remove' : 'link-variant',
func: async () => { func: async () => {
close(); close();
@@ -404,6 +436,54 @@ export const ActionSheetComponent = ({
nopremium: true, nopremium: true,
id: notesnook.ids.dialogs.actionsheet.pinMenu, id: notesnook.ids.dialogs.actionsheet.pinMenu,
}, },
{
name: 'RemoveTopic',
title: 'Remove from topic',
hidden: !noteInTopic,
type: 'error',
func: async () => {
await db.notebooks
.notebook(editing.actionAfterFirstSave.notebook)
.topics.topic(editing.actionAfterFirstSave.id)
.delete(note.id);
Navigation.setRoutesToUpdate([
Navigation.routeNames.Notebooks,
Navigation.routeNames.Notes,
Navigation.routeNames.NotesPage,
Navigation.routeNames.Notebook,
]);
setNote(db.notes.note(note.id).data);
close();
},
},
{
name: 'Delete',
title:
note.type !== 'notebook' && note.type !== 'note'
? 'Delete ' + item.type
: 'Move to trash',
icon: 'delete-outline',
type: 'error',
func: async () => {
close();
if (note.locked) {
await sleep(300);
openVault({
deleteNote: true,
novault: true,
locked: true,
item: note,
title: 'Delete note',
description: 'Unlock note to delete it.',
});
} else {
try {
close();
await deleteItems(note);
} catch (e) {}
}
},
},
]; ];
const _renderRowItem = rowItem => const _renderRowItem = rowItem =>
@@ -437,105 +517,32 @@ export const ActionSheetComponent = ({
</TouchableOpacity> </TouchableOpacity>
) : null; ) : null;
const _renderColumnItem = item => const _renderColumnItem = (item, index) =>
(note.id && columnItems.includes(item.name)) || (note.id && columnItems.includes(item.name)) ||
(item.name === 'Dark Mode' && columnItems.includes(item.name)) ? ( (item.name === 'Dark Mode' && columnItems.includes(item.name)) ? (
<TouchableOpacity item.hidden ? null : (
key={item.name} <Button
activeOpacity={opacity} title={item.title}
testID={item.id} type={item.type ? item.type : item.on ? 'accent' : 'shade'}
onPress={() => { onPress={item.func}
item.func(); style={{
marginTop: 12,
}} }}
style={{ width={
width: '100%', columnItems.length % 2 !== 0 &&
alignSelf: 'center', ((item.type === 'note' &&
flexDirection: 'row', noteInTopic &&
justifyContent: 'space-between', index === columnItems.length - 2) ||
alignItems: 'flex-end', (!noteInTopic && index === columnItems.length - 1))
paddingHorizontal: 12, ? '100%'
paddingVertical: pv, : '48%'
height: 50,
}}>
<View
style={{
flexDirection: 'row',
alignItems: 'center',
}}>
<Icon
style={{
width: 30,
}}
name={item.icon}
color={item.color || colors.accent}
size={SIZE.md + 2}
/>
<Paragraph>{item.name}</Paragraph>
</View>
<View
style={{
flexDirection: 'row',
alignItems: 'center',
}}>
{item.switch ? (
<Icon
size={SIZE.xxxl}
color={item.on ? colors.accent : colors.icon}
name={item.on ? 'toggle-switch' : 'toggle-switch-off'}
/>
) : undefined}
{item.check ? (
<Icon
name={
item.on
? 'check-circle-outline'
: 'checkbox-blank-circle-outline'
} }
color={item.on ? colors.accent : colors.icon} icon={item.icon}
size={SIZE.lg + 2} height={50}
/> />
) : null} )
</View>
</TouchableOpacity>
) : null; ) : null;
const onPressVaultButton = async () => {
if (!note.id) return;
if (note.locked) {
close('unlock');
} else {
db.vault
.add(note.id)
.then(r => {
let n = db.notes.note(note.id).data;
if (n.locked) {
close();
}
Navigation.setRoutesToUpdate([
Navigation.routeNames.NotesPage,
Navigation.routeNames.Favorites,
Navigation.routeNames.Notes,
]);
localRefresh(note.type);
})
.catch(async e => {
switch (e.message) {
case db.vault.ERRORS.noVault:
close('novault');
break;
case db.vault.ERRORS.vaultLocked:
close('locked');
break;
case db.vault.ERRORS.wrongPassword:
close();
break;
}
});
}
};
const onScrollEnd = () => { const onScrollEnd = () => {
getRef().current?.handleChildScrollEnd(); getRef().current?.handleChildScrollEnd();
}; };
@@ -554,12 +561,13 @@ export const ActionSheetComponent = ({
} }
}} }}
style={{ style={{
paddingBottom: 30,
backgroundColor: colors.bg, backgroundColor: colors.bg,
paddingHorizontal: 0, paddingHorizontal: 0,
borderBottomRightRadius: DDS.isLargeTablet() ? 10 : 1, borderBottomRightRadius: DDS.isLargeTablet() ? 10 : 1,
borderBottomLeftRadius: DDS.isLargeTablet() ? 10 : 1, borderBottomLeftRadius: DDS.isLargeTablet() ? 10 : 1,
}}> }}>
<TouchableOpacity <TouchableOpacity
style={{ style={{
width: '100%', width: '100%',
@@ -675,7 +683,7 @@ export const ActionSheetComponent = ({
<TouchableOpacity <TouchableOpacity
activeOpacity={0.9} activeOpacity={0.9}
testID={notesnook.ids.dialogs.actionsheet.sync} testID={notesnook.ids.dialogs.actionsheet.sync}
onPress={async () => await Sync.run("local")} onPress={async () => await Sync.run('local')}
style={{ style={{
borderColor: colors.accent, borderColor: colors.accent,
paddingHorizontal: 5, paddingHorizontal: 5,
@@ -722,74 +730,6 @@ export const ActionSheetComponent = ({
</View> </View>
) : null} ) : null}
{note.type === 'note' ? (
<PressableButton
type={note.locked ? 'accent' : 'shade'}
accentColor="red"
customSelectedColor={note.locked && '#ff0000'}
customOpacity={note.locked && 0.12}
onPress={onPressVaultButton}
testID={notesnook.ids.dialogs.actionsheet.vault}
customStyle={{
width: '95%',
alignSelf: 'center',
height: 50,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
}}>
<Icon
name={note.locked ? 'shield-off' : 'shield'}
color={note.locked ? '#FF0000' : colors.accent}
size={SIZE.md}
/>
<Paragraph
color={note.locked ? '#FF0000' : colors.accent}
size={SIZE.md}
style={{
marginLeft: 5,
}}>
{note.locked ? 'Remove from Vault' : 'Add to Vault'}
</Paragraph>
</PressableButton>
) : null}
{noteInTopic ? (
<PressableButton
type="accent"
accentColor="red"
customSelectedColor="#ff0000"
customOpacity={0.12}
onPress={async () => {
await db.notebooks
.notebook(editing.actionAfterFirstSave.notebook)
.topics.topic(editing.actionAfterFirstSave.id)
.delete(note.id);
Navigation.setRoutesToUpdate([
Navigation.routeNames.Notebooks,
Navigation.routeNames.Notes,
Navigation.routeNames.NotesPage,
Navigation.routeNames.Notebook,
]);
setNote(db.notes.note(note.id).data);
close();
}}
testID={notesnook.ids.dialogs.actionsheet.vault}
customStyle={{
width: '95%',
alignSelf: 'center',
height: 50,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
marginTop: 10,
}}>
<Paragraph color="#FF0000" size={SIZE.md}>
Remove from Topic
</Paragraph>
</PressableButton>
) : null}
{hasColors && note.id ? ( {hasColors && note.id ? (
<ActionSheetColorsSection close={close} item={note} /> <ActionSheetColorsSection close={close} item={note} />
) : null} ) : null}
@@ -803,7 +743,16 @@ export const ActionSheetComponent = ({
) : null} ) : null}
{columnItems.length > 0 ? ( {columnItems.length > 0 ? (
<View>{columnItemsData.map(_renderColumnItem)}</View> <View
style={{
paddingHorizontal: 12,
flexDirection: 'row',
justifyContent: 'space-between',
flexWrap: 'wrap',
marginTop: 6,
}}>
{columnItemsData.map(_renderColumnItem)}
</View>
) : null} ) : null}
{note.type === 'note' && user && lastSynced >= note.dateEdited ? ( {note.type === 'note' && user && lastSynced >= note.dateEdited ? (
@@ -821,11 +770,12 @@ export const ActionSheetComponent = ({
flexDirection: 'row', flexDirection: 'row',
justifyContent: 'flex-start', justifyContent: 'flex-start',
}}> }}>
<Icon name="shield-check" color={colors.accent} size={40} /> <Icon name="shield-key-outline" color={colors.accent} size={40} />
<View <View
style={{ style={{
flex: 1, flex: 1,
marginLeft: 5,
}}> }}>
<Heading <Heading
color={colors.accent} color={colors.accent}