1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-11-24 08:12:24 +02:00

Added context menu

This commit is contained in:
Laurent Cozic 2017-05-16 20:25:19 +00:00
parent 6d0c033e32
commit 5aa5b3d7b2
9 changed files with 119 additions and 73 deletions

View File

@ -10,6 +10,7 @@
"react": "16.0.0-alpha.6", "react": "16.0.0-alpha.6",
"react-native": "0.44.0", "react-native": "0.44.0",
"react-native-checkbox": "^1.1.0", "react-native-checkbox": "^1.1.0",
"react-native-popup-menu": "^0.7.4",
"react-native-vector-icons": "^2.0.3", "react-native-vector-icons": "^2.0.3",
"react-navigation": "^1.0.0-beta.9", "react-navigation": "^1.0.0-beta.9",
"uuid": "^3.0.1" "uuid": "^3.0.1"

View File

@ -37,6 +37,15 @@ class BaseModel {
return this.db().exec(query.sql, query.params).then(() => { return o; }); return this.db().exec(query.sql, query.params).then(() => { return o; });
} }
static delete(id) {
if (!id) {
Log.warn('Cannot delete object without an ID');
return;
}
return this.db().exec('DELETE FROM ' + this.tableName() + ' WHERE id = ?', [id]);
}
static db() { static db() {
return Registry.db(); return Registry.db();
} }

View File

@ -1,8 +0,0 @@
import React, { Component } from 'react';
import { Log } from 'src/log.js'
class BaseScreenComponent extends React.Component {
}
export { BaseScreenComponent };

View File

@ -1,30 +0,0 @@
import React, { Component } from 'react';
import { connect } from 'react-redux'
import { Button } from 'react-native';
import { _ } from 'src/locale.js';
class LoginButtonComponent extends Component {
render() {
return <Button onPress={this.props.onPress} title={_("Login")} />
}
}
const LoginButton = connect(
(state) => {
return {};
//return { label: state.myButtonLabel };
},
(dispatch) => {
return {
onPress: function() {
dispatch({
type: 'INC_COUNTER'
});
}
}
}
)(LoginButtonComponent)
export { LoginButton };

View File

@ -1,29 +0,0 @@
import React, { Component } from 'react';
import { connect } from 'react-redux'
import { Button } from 'react-native';
import { _ } from 'src/locale.js';
class OfflineButtonComponent extends Component {
render() {
return <Button onPress={this.props.onPress} title={_(this.props.label)} />
}
}
const OfflineButton = connect(
(state) => {
//return { label: state.myButtonLabel };
},
(dispatch) => {
return {
onPress: function() {
dispatch({
type: 'WORK_OFFLINE'
});
}
}
}
)(OfflineButtonComponent)
export { OfflineButton };

View File

@ -1,11 +1,25 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { View, Text, Button } from 'react-native'; import { View, Text, Button, StyleSheet } from 'react-native';
import { Log } from 'src/log.js'; import { Log } from 'src/log.js';
import { Menu, MenuOptions, MenuOption, MenuTrigger } from 'react-native-popup-menu';
import { _ } from 'src/locale.js'; import { _ } from 'src/locale.js';
const styles = StyleSheet.create({
divider: {
marginVertical: 5,
marginHorizontal: 2,
borderBottomWidth: 1,
borderColor: '#ccc'
},
});
class ScreenHeaderComponent extends Component { class ScreenHeaderComponent extends Component {
static defaultProps = {
menuOptions: [],
};
showBackButton() { showBackButton() {
// Note: this is hardcoded for now because navigation.state doesn't tell whether // Note: this is hardcoded for now because navigation.state doesn't tell whether
// it's possible to go back or not. Maybe it's possible to get this information // it's possible to go back or not. Maybe it's possible to get this information
@ -17,11 +31,44 @@ class ScreenHeaderComponent extends Component {
this.props.dispatch({ type: 'Navigation/BACK' }); this.props.dispatch({ type: 'Navigation/BACK' });
} }
menu_select = (value) => {
if (typeof(value) == 'function') {
value();
}
}
render() { render() {
let menuOptionComponents = [];
for (let i = 0; i < this.props.menuOptions.length; i++) {
let o = this.props.menuOptions[i];
let key = 'menuOption_' + i;
menuOptionComponents.push(
<MenuOption value={o.onPress} key={key}>
<Text>{o.title}</Text>
</MenuOption>
);
if (i == this.props.menuOptions.length - 1) {
menuOptionComponents.push(<View key={'menuDivider_' + i} style={styles.divider}/>);
}
}
let title = 'title' in this.props && this.props.title !== null ? this.props.title : _(this.props.navState.routeName);
return ( return (
<View style={{ flexDirection: 'row', padding: 10, backgroundColor: '#ffffff', alignItems: 'center' }} > <View style={{ flexDirection: 'row', padding: 10, backgroundColor: '#ffffff', alignItems: 'center' }} >
<Button disabled={!this.showBackButton()} title="<" onPress={this.backButton_press}></Button> <Button disabled={!this.showBackButton()} title="<" onPress={this.backButton_press}></Button>
<Text style={{ marginLeft: 10 }} >{_(this.props.navState.routeName)}</Text> <Text style={{ flex:1, marginLeft: 10 }} >{title}</Text>
<Menu onSelect={this.menu_select}>
<MenuTrigger>
<Text style={{ fontSize: 20 }}> &#8942; </Text>
</MenuTrigger>
<MenuOptions>
{ menuOptionComponents }
<MenuOption value={1}>
<Text>{_('Configuration')}</Text>
</MenuOption>
</MenuOptions>
</Menu>
</View> </View>
); );
} }

View File

@ -3,7 +3,6 @@ import { View, Button, Picker, Text } from 'react-native';
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { Log } from 'src/log.js' import { Log } from 'src/log.js'
import { FolderList } from 'src/components/folder-list.js' import { FolderList } from 'src/components/folder-list.js'
import { BaseScreenComponent } from 'src/components/base-screen.js'
import { ScreenHeader } from 'src/components/screen-header.js'; import { ScreenHeader } from 'src/components/screen-header.js';
import { _ } from 'src/locale.js'; import { _ } from 'src/locale.js';

View File

@ -3,7 +3,9 @@ import { View, Button, Picker } from 'react-native';
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { Log } from 'src/log.js' import { Log } from 'src/log.js'
import { NoteList } from 'src/components/note-list.js' import { NoteList } from 'src/components/note-list.js'
import { Folder } from 'src/models/folder.js'
import { ScreenHeader } from 'src/components/screen-header.js'; import { ScreenHeader } from 'src/components/screen-header.js';
import { MenuOption, Text } from 'react-native-popup-menu';
import { _ } from 'src/locale.js'; import { _ } from 'src/locale.js';
class NotesScreenComponent extends React.Component { class NotesScreenComponent extends React.Component {
@ -37,11 +39,42 @@ class NotesScreenComponent extends React.Component {
Log.info('SYNC'); Log.info('SYNC');
} }
deleteFolder_onPress = (folderId) => {
Folder.delete(folderId).then(() => {
this.props.dispatch({
type: 'FOLDER_DELETE',
folderId: folderId,
});
this.props.dispatch({
type: 'Navigation/NAVIGATE',
routeName: 'Folders',
});
});
}
editFolder_onPress = (folderId) => {
this.props.dispatch({
type: 'Navigation/NAVIGATE',
routeName: 'Folder',
folderId: folderId,
});
}
menuOptions = () => {
return [
{ title: _('Delete folder'), onPress: () => { this.deleteFolder_onPress(this.props.selectedFolderId); } },
{ title: _('Edit folder'), onPress: () => { this.editFolder_onPress(this.props.selectedFolderId); } },
];
}
render() { render() {
let folder = Folder.byId(this.props.folders, this.props.selectedFolderId);
let title = folder ? folder.title : null;
const { navigate } = this.props.navigation; const { navigate } = this.props.navigation;
return ( return (
<View style={{flex: 1}}> <View style={{flex: 1}}>
<ScreenHeader navState={this.props.navigation.state} /> <ScreenHeader title={title} navState={this.props.navigation.state} menuOptions={this.menuOptions()} />
<NoteList style={{flex: 1}}/> <NoteList style={{flex: 1}}/>
<View style={{flexDirection: 'row'}}> <View style={{flexDirection: 'row'}}>
<Button title="Create note" onPress={this.createNoteButton_press} /> <Button title="Create note" onPress={this.createNoteButton_press} />
@ -57,7 +90,8 @@ class NotesScreenComponent extends React.Component {
const NotesScreen = connect( const NotesScreen = connect(
(state) => { (state) => {
return { return {
folders: state.folders folders: state.folders,
selectedFolderId: state.selectedFolderId,
}; };
} }
)(NotesScreenComponent) )(NotesScreenComponent)

View File

@ -19,6 +19,14 @@ import { FoldersScreen } from 'src/components/screens/folders.js'
import { LoginScreen } from 'src/components/screens/login.js' import { LoginScreen } from 'src/components/screens/login.js'
import { Setting } from 'src/models/setting.js' import { Setting } from 'src/models/setting.js'
import { MenuContext } from 'react-native-popup-menu';
let defaultState = { let defaultState = {
notes: [], notes: [],
folders: [], folders: [],
@ -97,7 +105,7 @@ const reducer = (state = defaultState, action) => {
case 'FOLDERS_UPDATE_ONE': case 'FOLDERS_UPDATE_ONE':
let newFolders = state.folders.splice(0); var newFolders = state.folders.splice(0);
var found = false; var found = false;
for (let i = 0; i < newFolders.length; i++) { for (let i = 0; i < newFolders.length; i++) {
let n = newFolders[i]; let n = newFolders[i];
@ -114,6 +122,19 @@ const reducer = (state = defaultState, action) => {
newState.folders = newFolders; newState.folders = newFolders;
break; break;
case 'FOLDER_DELETE':
var newFolders = [];
for (let i = 0; i < state.folders.length; i++) {
let f = state.folders[i];
if (f.id == action.folderId) continue;
newFolders.push(f);
}
newState = Object.assign({}, state);
newState.folders = newFolders;
break;
case 'SET_LIST_MODE': case 'SET_LIST_MODE':
newState = Object.assign({}, state); newState = Object.assign({}, state);
@ -167,10 +188,12 @@ class AppComponent extends React.Component {
render() { render() {
return ( return (
<MenuContext style={{ flex: 1 }}>
<AppNavigator navigation={addNavigationHelpers({ <AppNavigator navigation={addNavigationHelpers({
dispatch: this.props.dispatch, dispatch: this.props.dispatch,
state: this.props.nav, state: this.props.nav,
})} /> })} />
</MenuContext>
); );
} }
} }