add support for pinning items to menu

This commit is contained in:
ammarahm-ed
2020-11-25 18:49:21 +05:00
parent 2a45c846fb
commit ace65fee90
15 changed files with 248 additions and 70 deletions

View File

@@ -1,23 +1,23 @@
import React, {useEffect, useState} from 'react';
import React, { useEffect, useState } from 'react';
import {
ActivityIndicator,
Clipboard,
Dimensions,
StatusBar,
Text,
TouchableOpacity,
View,
View
} from 'react-native';
import Share from 'react-native-share';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import {useTracked} from '../../provider';
import {Actions} from '../../provider/Actions';
import {DDS} from '../../services/DeviceDetection';
import { useTracked } from '../../provider';
import { Actions } from '../../provider/Actions';
import { DDS } from '../../services/DeviceDetection';
import {
eSendEvent,
openVault,
sendNoteEditedEvent,
ToastEvent,
ToastEvent
} from '../../services/EventManager';
import PremiumService from '../../services/PremiumService';
import {
@@ -25,27 +25,25 @@ import {
COLOR_SCHEME,
COLOR_SCHEME_DARK,
COLOR_SCHEME_LIGHT,
setColorScheme,
setColorScheme
} from '../../utils/Colors';
import {db} from '../../utils/DB';
import { db } from '../../utils/DB';
import {
eOpenLoginDialog,
eOpenMoveNoteDialog,
eShowGetPremium,
eShowGetPremium
} from '../../utils/Events';
import {deleteItems} from '../../utils/functions';
import {MMKV} from '../../utils/mmkv';
import {opacity, ph, pv, SIZE, WEIGHT} from '../../utils/SizeUtils';
import {sleep, timeConverter} from '../../utils/TimeUtils';
import {Button} from '../Button';
import {PremiumTag} from '../Premium/PremiumTag';
import {PressableButton} from '../PressableButton';
import {Toast} from '../Toast';
import { deleteItems } from '../../utils/functions';
import { MMKV } from '../../utils/mmkv';
import { opacity, ph, pv, SIZE } from '../../utils/SizeUtils';
import { timeConverter } from '../../utils/TimeUtils';
import { PremiumTag } from '../Premium/PremiumTag';
import { PressableButton } from '../PressableButton';
import { Toast } from '../Toast';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
import {ActionSheetColorsSection} from './ActionSheetColorsSection';
import {ActionSheetTagsSection} from './ActionSheetTagsSection';
import {GetPremium} from './GetPremium';
import { ActionSheetColorsSection } from './ActionSheetColorsSection';
import { ActionSheetTagsSection } from './ActionSheetTagsSection';
const w = Dimensions.get('window').width;
export const ActionSheetComponent = ({
@@ -59,6 +57,8 @@ export const ActionSheetComponent = ({
const [state, dispatch] = useTracked();
const {colors, premiumUser, user} = state;
const [refreshing, setRefreshing] = useState(false);
const [isPinnedToMenu, setIsPinnedToMenu] = useState(false);
const [note, setNote] = useState(
item
? item
@@ -84,6 +84,11 @@ export const ActionSheetComponent = ({
useEffect(() => {
if (item.dateCreated !== null) {
setNote({...item});
if (item.type !== note) {
setIsPinnedToMenu(
db.settings.pins.findIndex((i) => i.id === item.id) > -1,
);
}
}
}, [item]);
@@ -313,6 +318,34 @@ export const ActionSheetComponent = ({
check: true,
on: note.favorite,
},
{
name: isPinnedToMenu ? 'Unpin from Menu' : 'Pin to Menu',
icon: 'tag-outline',
func: async () => {
try {
if (isPinnedToMenu) {
await db.settings.unpin(note.id);
} else {
if (item.type === 'notebook') {
await db.settings.pin(note.type, {id: note.id});
} else if (item.type === 'topic') {
await db.settings.pin(note.type, {
id: note.notebookId,
topic: note.id,
});
}
}
setIsPinnedToMenu(
db.settings.pins.findIndex((i) => i.id === item.id) > -1,
);
dispatch({type:Actions.MENU_PINS})
} catch (e) {}
},
close: false,
check: true,
on: isPinnedToMenu,
},
];
const _renderRowItem = (rowItem) =>

View File

@@ -7,5 +7,6 @@ export const dialogActions = {
ACTION_PERMANANT_DELETE: 516,
ACTION_APPLY_CHANGES: 517,
ACTION_UPIN:518,
ACTION_NEW_NOTE:519
ACTION_NEW_NOTE:519,
ACTION_UPIN_MENU:520,
};

View File

@@ -101,3 +101,11 @@ export const TEMPLATE_UNPIN = (type) => { return {
negativeText: 'Cancel',
action: dialogActions.ACTION_UPIN
}};
export const TEMPLATE_UNPIN_MENU = (name,type) => { return {
title: 'Unpin' + name,
paragraph: 'Remove this ' + type + 'from menu?',
positiveText: 'Unpin',
negativeText: 'Cancel',
action: dialogActions.ACTION_UPIN_MENU
}};

View File

@@ -8,7 +8,7 @@ import {
FAV_SVG,
TRASH_SVG,
SETTINGS_SVG,
SEARCH_SVG
SEARCH_SVG,
} from '../../assets/images/assets';
import {useTracked} from '../../provider';
export const Placeholder = ({type, w, h, color}) => {
@@ -20,6 +20,8 @@ export const Placeholder = ({type, w, h, color}) => {
return NOTE_SVG(color || colors.accent);
case 'notebooks':
return NOTEBOOK_SVG(colors.accent);
case 'topics':
return NOTEBOOK_SVG(colors.accent);
case 'tags':
return TAG_SVG(colors.accent);
case 'favorites':
@@ -28,8 +30,8 @@ export const Placeholder = ({type, w, h, color}) => {
return TRASH_SVG(colors.accent);
case 'settings':
return SETTINGS_SVG(colors.accent);
case 'search':
return SEARCH_SVG(colors.accent);
case 'search':
return SEARCH_SVG(colors.accent);
}
};

View File

@@ -1,21 +1,29 @@
import React, {useEffect} from 'react';
import {Text, View} from 'react-native';
import React, {useEffect, useState} from 'react';
import {FlatList, View} from 'react-native';
import {useTracked} from '../../provider';
import {Actions} from '../../provider/Actions';
import {eSendEvent} from '../../services/EventManager';
import NavigationService from '../../services/Navigation';
import {db} from '../../utils/DB';
import {refreshNotesPage} from '../../utils/Events';
import { sideMenuRef } from '../../utils/Refs';
import {SIZE, WEIGHT} from '../../utils/SizeUtils';
import {ph, pv, SIZE} from '../../utils/SizeUtils';
import {NotebookItem} from '../NotebookItem';
import {PressableButton} from '../PressableButton';
import Heading from '../Typography/Heading';
import Paragraph from '../Typography/Paragraph';
import Icon from 'react-native-vector-icons/MaterialCommunityIcons';
import BaseDialog from '../Dialog/base-dialog';
import DialogHeader from '../Dialog/dialog-header';
import DialogButtons from '../Dialog/dialog-buttons';
import {getElevation} from '../../utils';
import {DDS} from '../../services/DeviceDetection';
export const TagsSection = () => {
const [state, dispatch] = useTracked();
const {colors, tags, currentScreen} = state;
const {colors, menuPins} = state;
useEffect(() => {
dispatch({type: Actions.TAGS});
dispatch({type: Actions.MENU_PINS});
}, []);
const onPress = (item) => {
@@ -37,15 +45,144 @@ export const TagsSection = () => {
});
NavigationService.navigate('NotesPage', params);
eSendEvent(refreshNotesPage, params);
NavigationService.closeDrawer()
NavigationService.closeDrawer();
};
return (
<View
style={{
width: '100%',
flexGrow: 1,
}}>
{tags
<FlatList
data={menuPins}
ListEmptyComponent={
<View
style={{
width: '100%',
height: '100%',
justifyContent: 'center',
alignItems: 'center',
paddingHorizontal: '10%',
}}>
<Heading style={{marginBottom: 2.5}} size={SIZE.sm}>
Your Pins
</Heading>
<Paragraph
style={{textAlign: 'center'}}
color={colors.icon}
size={SIZE.xs}>
You have not pinned anything yet. You can pin topics and tags
here.
</Paragraph>
</View>
}
renderItem={({item, index}) => (
<PinItem key={item.id} item={item} index={index} onPress={onPress} />
)}
/>
</View>
);
};
const PinItem = ({item, index, onPress}) => {
const [state, dispatch] = useTracked();
const {colors, currentScreen} = state;
const [visible, setVisible] = useState(false);
return (
<>
{visible && (
<BaseDialog visible={true}>
<View
style={{
...getElevation(5),
width: DDS.isTab ? 350 : '80%',
maxHeight: 350,
borderRadius: 5,
backgroundColor: colors.bg,
paddingHorizontal: ph,
paddingVertical: pv,
}}>
<DialogHeader title="Unpin" paragraph="Remove item from menu" />
<DialogButtons
positiveTitle="Unpin"
negativeTitle="Cancel"
onPressNegative={() => setVisible(false)}
onPressPositive={async () => {
await db.settings.unpin(note.id);
dispatch({type: Actions.MENU_PINS});
}}
/>
</View>
</BaseDialog>
)}
<PressableButton
color={
currentScreen === item.title.toLowerCase()
? colors.shade
: 'transparent'
}
selectedColor={colors.accent}
alpha={!colors.night ? -0.02 : 0.02}
opacity={0.12}
onLongPress={() => setVisible(true)}
onPress={() => onPress(item)}
customStyle={{
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'center',
width: '100%',
borderRadius: 0,
paddingHorizontal: 10,
minHeight: 50,
borderBottomWidth: 1,
borderBottomColor: colors.nav,
}}>
<View
style={{
width: 35,
height: 35,
justifyContent: 'center',
alignItems: 'flex-start',
}}>
{item.type === 'notebook' ? (
<Icon color={colors.accent} size={SIZE.md} name="book-outline" />
) : item.type === 'tag' ? (
<Icon color={colors.accent} size={SIZE.md} name="pound" />
) : (
<Paragraph color={colors.accent} size={SIZE.md}>
T
</Paragraph>
)}
</View>
<View
style={{
alignItems: 'flex-start',
width: '85%',
}}>
<Paragraph size={SIZE.md} color={colors.heading}>
{item.title}
</Paragraph>
<Paragraph
style={{marginTop: 2.5}}
size={SIZE.xs}
color={colors.icon}>
{item.type.slice(0, 1).toUpperCase() +
item.type.slice(1, item.type.length)}{' '}
{item.type === 'topic'
? 'in ' + db.notebooks.notebook(item.notebookId).data.title
: null}
</Paragraph>
</View>
</PressableButton>
</>
);
};
/*
{tags
.filter((o) => o.noteIds.length > 1)
.slice(0, tags.length > 10 ? 10 : tags.length)
.map((item) => (
@@ -92,6 +229,4 @@ export const TagsSection = () => {
</View>
</PressableButton>
))}
</View>
);
};
*/

View File

@@ -62,7 +62,7 @@ export const Menu = React.memo(
style={{
height: '100%',
width: '100%',
backgroundColor:DDS.isLargeTablet()? colors.nav : colors.bg,
backgroundColor: DDS.isLargeTablet() ? colors.nav : colors.bg,
paddingTop: insets.top,
}}>
<ScrollView
@@ -81,27 +81,8 @@ export const Menu = React.memo(
noTextMode={noTextMode}
/>
))}
{noTextMode ? null : <TagsSection />}
<ColorSection noTextMode={noTextMode} />
<View
style={{
justifyContent: 'center',
alignItems: 'center',
flexGrow: 1,
paddingHorizontal: '10%',
}}>
<Heading style={{marginBottom: 2.5}} size={SIZE.sm}>
Your Pins
</Heading>
<Paragraph
style={{textAlign: 'center'}}
color={colors.icon}
size={SIZE.xs}>
You have not pinned anything yet. You can pin topics and tags
here.
</Paragraph>
</View>
<TagsSection />
</ScrollView>
<View

View File

@@ -188,7 +188,10 @@ export const NotebookItem = ({
'Delete',
];
let columnItems = item.type === 'topic' ? [] : ['Pin'];
let columnItems =
item.type === 'topic'
? ['Pin to Menu', 'Unpin from Menu']
: ['Pin', 'Pin to Menu', 'Unpin from Menu'];
ActionSheetEvent(item, false, false, rowItems, columnItems, {
notebookID: notebookID,

View File

@@ -7,7 +7,7 @@ import {
useWindowDimensions,
View,
} from 'react-native';
import {initialWindowMetrics} from 'react-native-safe-area-context';
import {initialWindowMetrics, useSafeAreaInsets} from 'react-native-safe-area-context';
import {DataProvider, LayoutProvider, RecyclerListView} from 'recyclerlistview';
import {useTracked} from '../../provider';
import {Actions} from '../../provider/Actions';
@@ -51,6 +51,7 @@ const SimpleList = ({
const {colors} = state;
const searchResults = {...state.searchResults};
const [refreshing, setRefreshing] = useState(false);
const insets = useSafeAreaInsets();
const [dataProvider, setDataProvider] = useState(
new DataProvider((r1, r2) => {
return r1 !== r2;
@@ -154,7 +155,7 @@ const SimpleList = ({
style={[
{
backgroundColor: colors.bg,
height: dHeight - 250 - initialWindowMetrics.insets.top,
height: dHeight - 250 - insets.top,
width: '100%',
},
]}>

View File

@@ -42,7 +42,7 @@ class SortDialog extends React.Component {
}
async getSettings() {
let settings = await MMKV.getItem('settings');
let settings = await MMKV.getItem('appSettings');
this.setState({
settings: JSON.parse(settings),
});

View File

@@ -30,5 +30,6 @@ export const Actions = {
MESSAGE_BOARD_STATE:'messageBoardState',
LOADING:"loading",
FULLSCREEN:"fullscreen",
DEVICE_MODE:"deviceMode"
DEVICE_MODE:"deviceMode",
MENU_PINS:"menuPins"
};

View File

@@ -81,4 +81,5 @@ export const defaultState = {
icon: 'account-outline',
},
keyword: [],
menuPins:[]
};

View File

@@ -17,6 +17,7 @@ export const reducer = (state, action) => {
tags: db.tags.all,
favorites: db.notes.favorites,
colorNotes: db.colors.all,
menuPins:db.settings.pins
};
}
case Actions.SYNCING: {
@@ -254,6 +255,13 @@ export const reducer = (state, action) => {
deviceMode: action.state,
};
}
case Actions.MENU_PINS: {
return {
...state,
menuPins: db.settings.pins,
};
}
default:
throw new Error('unknown action type');
}

View File

@@ -11,10 +11,10 @@ let settings = defaultState.settings;
async function init() {
scale.fontScale = 1;
settings = await MMKV.getStringAsync('settings');
settings = await MMKV.getStringAsync('appSettings');
if (!settings) {
settings = defaultState.settings;
await MMKV.setStringAsync('settings', JSON.stringify(settings));
await MMKV.setStringAsync('appSettings', JSON.stringify(settings));
} else {
settings = JSON.parse(settings);
}
@@ -51,7 +51,7 @@ const setTheme = async () => {
async function set(name, value) {
settings[name] = value;
await MMKV.setStringAsync('settings', JSON.stringify(settings));
await MMKV.setStringAsync('appSettings', JSON.stringify(settings));
updateEvent({type: Actions.SETTINGS, settings: settings});
}

View File

@@ -12,7 +12,7 @@ import {SIZE} from './SizeUtils';
export async function setSetting(settings, name, value) {
let s = {...settings};
s[name] = value;
await MMKV.setStringAsync('settings', JSON.stringify(s));
await MMKV.setStringAsync('appSettings', JSON.stringify(s));
updateEvent({type: Actions.SETTINGS, settings: s});
}

View File

@@ -104,8 +104,12 @@ export const Notebook = ({route, navigation}) => {
onLoad();
}}
focused={() => navigation.isFocused()}
placeholder={<></>}
placeholderText=""
placeholderData={{
heading: route.params.notebook.title,
paragraph: 'You have not added any topics yet.',
button: 'Add a Topic',
action:_onPressBottomButton
}}
/>
<ContainerBottomButton