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:
parent
6d0c033e32
commit
5aa5b3d7b2
@ -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"
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
import React, { Component } from 'react';
|
|
||||||
import { Log } from 'src/log.js'
|
|
||||||
|
|
||||||
class BaseScreenComponent extends React.Component {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export { BaseScreenComponent };
|
|
@ -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 };
|
|
@ -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 };
|
|
@ -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 }}> ⋮ </Text>
|
||||||
|
</MenuTrigger>
|
||||||
|
<MenuOptions>
|
||||||
|
{ menuOptionComponents }
|
||||||
|
<MenuOption value={1}>
|
||||||
|
<Text>{_('Configuration')}</Text>
|
||||||
|
</MenuOption>
|
||||||
|
</MenuOptions>
|
||||||
|
</Menu>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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';
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user