mirror of
https://github.com/laurent22/joplin.git
synced 2025-01-11 18:24:43 +02:00
Refactoring note list
This commit is contained in:
parent
e4c0345f4b
commit
ae0eac0f3b
@ -13,6 +13,13 @@ class BaseModel {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static byId(items, id) {
|
||||||
|
for (let i = 0; i < items.length; i++) {
|
||||||
|
if (items[i].id == id) return items[i];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
static save(o) {
|
static save(o) {
|
||||||
let isNew = !o.id;
|
let isNew = !o.id;
|
||||||
let query = '';
|
let query = '';
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
// import React, { Component } from 'react';
|
|
||||||
// import { connect } from 'react-redux'
|
|
||||||
// import { Button } from 'react-native';
|
|
||||||
// import { _ } from 'src/locale.js';
|
|
||||||
|
|
||||||
// class CreateNoteButtonComponent extends Component {
|
|
||||||
|
|
||||||
// render() {
|
|
||||||
// return <Button onPress={this.props.onPress} title={_("Create note")} />
|
|
||||||
// }
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// const CreateNoteButton = connect(
|
|
||||||
// (state) => {
|
|
||||||
// return {
|
|
||||||
// selectedNoteId: selectedNoteId,
|
|
||||||
// };
|
|
||||||
// },
|
|
||||||
// (dispatch) => {
|
|
||||||
// return {
|
|
||||||
// onPress: function() {
|
|
||||||
// dispatch({
|
|
||||||
// type: 'VIEW_NOTE'
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// )(CreateNoteButtonComponent)
|
|
||||||
|
|
||||||
// export { CreateNoteButton };
|
|
@ -13,13 +13,13 @@ class ItemListComponent extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount() {
|
componentWillMount() {
|
||||||
const newDataSource = this.state.dataSource.cloneWithRows(this.props.notes);
|
const newDataSource = this.state.dataSource.cloneWithRows(this.props.items);
|
||||||
this.state = { dataSource: newDataSource };
|
this.state = { dataSource: newDataSource };
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillReceiveProps(newProps) {
|
componentWillReceiveProps(newProps) {
|
||||||
// https://stackoverflow.com/questions/38186114/react-native-redux-and-listview
|
// https://stackoverflow.com/questions/38186114/react-native-redux-and-listview
|
||||||
this.setState({ dataSource: this.state.dataSource.cloneWithRows(newProps.notes) });
|
this.setState({ dataSource: this.state.dataSource.cloneWithRows(newProps.items) });
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -45,21 +45,4 @@ class ItemListComponent extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ItemList = connect(
|
export { ItemListComponent };
|
||||||
(state) => {
|
|
||||||
return { notes: state.notes };
|
|
||||||
},
|
|
||||||
(dispatch) => {
|
|
||||||
return {
|
|
||||||
onItemClick: (noteId) => {
|
|
||||||
dispatch({
|
|
||||||
type: 'Navigation/NAVIGATE',
|
|
||||||
routeName: 'Note',
|
|
||||||
noteId: noteId,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)(ItemListComponent)
|
|
||||||
|
|
||||||
export { ItemList };
|
|
27
ReactNativeClient/src/components/note-list.js
Normal file
27
ReactNativeClient/src/components/note-list.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
import { ListView, Text, TouchableHighlight } from 'react-native';
|
||||||
|
import { Log } from 'src/log.js';
|
||||||
|
import { ItemListComponent } from 'src/components/item-list.js';
|
||||||
|
import { _ } from 'src/locale.js';
|
||||||
|
|
||||||
|
class NoteListComponent extends ItemListComponent {}
|
||||||
|
|
||||||
|
const NoteList = connect(
|
||||||
|
(state) => {
|
||||||
|
return { items: state.notes };
|
||||||
|
},
|
||||||
|
(dispatch) => {
|
||||||
|
return {
|
||||||
|
onItemClick: (noteId) => {
|
||||||
|
dispatch({
|
||||||
|
type: 'Navigation/NAVIGATE',
|
||||||
|
routeName: 'Note',
|
||||||
|
noteId: noteId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)(NoteListComponent)
|
||||||
|
|
||||||
|
export { NoteList };
|
64
ReactNativeClient/src/components/screens/folder.js
Normal file
64
ReactNativeClient/src/components/screens/folder.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
import React, { Component } from 'react';
|
||||||
|
import { View, Button, TextInput } from 'react-native';
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
import { Log } from 'src/log.js'
|
||||||
|
import { Folder } from 'src/models/folder.js'
|
||||||
|
|
||||||
|
class FolderScreenComponent extends React.Component {
|
||||||
|
|
||||||
|
static navigationOptions = {
|
||||||
|
title: 'Folder',
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.state = { folder: Folder.newFolder() }
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
this.setState({ folder: this.props.folder });
|
||||||
|
}
|
||||||
|
|
||||||
|
folderComponent_change = (propName, propValue) => {
|
||||||
|
this.setState((prevState, props) => {
|
||||||
|
let folder = Object.assign({}, prevState.folder);
|
||||||
|
folder[propName] = propValue;
|
||||||
|
return { folder: folder }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
title_changeText = (text) => {
|
||||||
|
this.folderComponent_change('title', text);
|
||||||
|
}
|
||||||
|
|
||||||
|
saveFolderButton_press = () => {
|
||||||
|
Folder.save(this.state.folder).then((folder) => {
|
||||||
|
this.props.dispatch({
|
||||||
|
type: 'FOLDERS_UPDATE_ONE',
|
||||||
|
folder: folder,
|
||||||
|
});
|
||||||
|
}).catch((error) => {
|
||||||
|
Log.warn('Cannot save folder', error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<View style={{flex: 1}}>
|
||||||
|
<TextInput value={this.state.folder.title} onChangeText={this.title_changeText} />
|
||||||
|
<Button title="Save folder" onPress={this.saveFolderButton_press} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const FolderScreen = connect(
|
||||||
|
(state) => {
|
||||||
|
return {
|
||||||
|
folder: state.selectedFolderId ? Folder.byId(state.folders, state.selectedFolderId) : Folder.newFolder(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
)(FolderScreenComponent)
|
||||||
|
|
||||||
|
export { FolderScreen };
|
@ -61,7 +61,7 @@ class NoteScreenComponent extends React.Component {
|
|||||||
const NoteScreen = connect(
|
const NoteScreen = connect(
|
||||||
(state) => {
|
(state) => {
|
||||||
return {
|
return {
|
||||||
note: state.selectedNoteId ? Note.noteById(state.notes, state.selectedNoteId) : Note.newNote(),
|
note: state.selectedNoteId ? Note.byId(state.notes, state.selectedNoteId) : Note.newNote(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
)(NoteScreenComponent)
|
)(NoteScreenComponent)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import { View, Button } from 'react-native';
|
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 { ItemList } from 'src/components/item-list.js'
|
import { NoteList } from 'src/components/note-list.js'
|
||||||
|
|
||||||
class NotesScreenComponent extends React.Component {
|
class NotesScreenComponent extends React.Component {
|
||||||
|
|
||||||
@ -17,6 +17,13 @@ class NotesScreenComponent extends React.Component {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createFolderButton_press = () => {
|
||||||
|
this.props.dispatch({
|
||||||
|
type: 'Navigation/NAVIGATE',
|
||||||
|
routeName: 'Folder',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
loginButton_press = () => {
|
loginButton_press = () => {
|
||||||
this.props.dispatch({
|
this.props.dispatch({
|
||||||
type: 'Navigation/NAVIGATE',
|
type: 'Navigation/NAVIGATE',
|
||||||
@ -32,9 +39,10 @@ class NotesScreenComponent extends React.Component {
|
|||||||
const { navigate } = this.props.navigation;
|
const { navigate } = this.props.navigation;
|
||||||
return (
|
return (
|
||||||
<View style={{flex: 1}}>
|
<View style={{flex: 1}}>
|
||||||
<ItemList 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} />
|
||||||
|
<Button title="Create folder" onPress={this.createFolderButton_press} />
|
||||||
<Button title="Login" onPress={this.loginButton_press} />
|
<Button title="Login" onPress={this.loginButton_press} />
|
||||||
<Button title="Sync" onPress={this.syncButton_press} />
|
<Button title="Sync" onPress={this.syncButton_press} />
|
||||||
</View>
|
</View>
|
||||||
@ -45,7 +53,9 @@ class NotesScreenComponent extends React.Component {
|
|||||||
|
|
||||||
const NotesScreen = connect(
|
const NotesScreen = connect(
|
||||||
(state) => {
|
(state) => {
|
||||||
return {};
|
return {
|
||||||
|
folders: state.folders
|
||||||
|
};
|
||||||
}
|
}
|
||||||
)(NotesScreenComponent)
|
)(NotesScreenComponent)
|
||||||
|
|
||||||
|
33
ReactNativeClient/src/models/folder.js
Normal file
33
ReactNativeClient/src/models/folder.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { BaseModel } from 'src/base-model.js';
|
||||||
|
import { Log } from 'src/log.js';
|
||||||
|
|
||||||
|
class Folder extends BaseModel {
|
||||||
|
|
||||||
|
static tableName() {
|
||||||
|
return 'folders';
|
||||||
|
}
|
||||||
|
|
||||||
|
static useUuid() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static newFolder() {
|
||||||
|
return {
|
||||||
|
id: null,
|
||||||
|
title: '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static all() {
|
||||||
|
return this.db().selectAll('SELECT * FROM folders').then((r) => {
|
||||||
|
let output = [];
|
||||||
|
for (let i = 0; i < r.rows.length; i++) {
|
||||||
|
output.push(r.rows.item(i));
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Folder };
|
@ -11,13 +11,6 @@ class Note extends BaseModel {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static noteById(notes, id) {
|
|
||||||
for (let i = 0; i < notes.length; i++) {
|
|
||||||
if (notes[i].id == id) return notes[i];
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newNote() {
|
static newNote() {
|
||||||
return {
|
return {
|
||||||
id: null,
|
id: null,
|
||||||
|
@ -13,13 +13,21 @@ import { Registry } from 'src/registry.js'
|
|||||||
import { ItemList } from 'src/components/item-list.js'
|
import { ItemList } from 'src/components/item-list.js'
|
||||||
import { NotesScreen } from 'src/components/screens/notes.js'
|
import { NotesScreen } from 'src/components/screens/notes.js'
|
||||||
import { NoteScreen } from 'src/components/screens/note.js'
|
import { NoteScreen } from 'src/components/screens/note.js'
|
||||||
|
import { FolderScreen } from 'src/components/screens/folder.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'
|
||||||
|
|
||||||
let defaultState = {
|
let defaultState = {
|
||||||
defaultText: 'bla',
|
defaultText: 'bla',
|
||||||
notes: [],
|
notes: [],
|
||||||
|
folders: [
|
||||||
|
{ id: 'abcdabcdabcdabcdabcdabcdabcdab01', title: "un" },
|
||||||
|
{ id: 'abcdabcdabcdabcdabcdabcdabcdab02', title: "deux" },
|
||||||
|
{ id: 'abcdabcdabcdabcdabcdabcdabcdab03', title: "trois" },
|
||||||
|
{ id: 'abcdabcdabcdabcdabcdabcdabcdab04', title: "quatre" },
|
||||||
|
],
|
||||||
selectedNoteId: null,
|
selectedNoteId: null,
|
||||||
|
selectedFolderId: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const reducer = (state = defaultState, action) => {
|
const reducer = (state = defaultState, action) => {
|
||||||
@ -62,7 +70,7 @@ const reducer = (state = defaultState, action) => {
|
|||||||
case 'NOTES_UPDATE_ONE':
|
case 'NOTES_UPDATE_ONE':
|
||||||
|
|
||||||
let newNotes = state.notes.splice(0);
|
let newNotes = state.notes.splice(0);
|
||||||
let found = false;
|
var found = false;
|
||||||
for (let i = 0; i < newNotes.length; i++) {
|
for (let i = 0; i < newNotes.length; i++) {
|
||||||
let n = newNotes[i];
|
let n = newNotes[i];
|
||||||
if (n.id == action.note.id) {
|
if (n.id == action.note.id) {
|
||||||
@ -78,6 +86,25 @@ const reducer = (state = defaultState, action) => {
|
|||||||
newState.notes = newNotes;
|
newState.notes = newNotes;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'FOLDERS_UPDATE_ONE':
|
||||||
|
|
||||||
|
let newFolders = state.folders.splice(0);
|
||||||
|
var found = false;
|
||||||
|
for (let i = 0; i < newFolders.length; i++) {
|
||||||
|
let n = newFolders[i];
|
||||||
|
if (n.id == action.folder.id) {
|
||||||
|
newFolders[i] = action.folder;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) newFolders.push(action.folder);
|
||||||
|
|
||||||
|
newState = Object.assign({}, state);
|
||||||
|
newState.folders = newFolders;
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return newState;
|
return newState;
|
||||||
@ -88,6 +115,7 @@ let store = createStore(reducer);
|
|||||||
const AppNavigator = StackNavigator({
|
const AppNavigator = StackNavigator({
|
||||||
Notes: {screen: NotesScreen},
|
Notes: {screen: NotesScreen},
|
||||||
Note: {screen: NoteScreen},
|
Note: {screen: NoteScreen},
|
||||||
|
Folder: {screen: FolderScreen},
|
||||||
Login: {screen: LoginScreen},
|
Login: {screen: LoginScreen},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -53,13 +53,11 @@ class WebApi {
|
|||||||
let responseClone = response.clone();
|
let responseClone = response.clone();
|
||||||
return response.json().then(function(data) {
|
return response.json().then(function(data) {
|
||||||
if (data && data.error) {
|
if (data && data.error) {
|
||||||
let e = new Error(data.error);
|
reject(new Error(data.error));
|
||||||
reject(e);
|
|
||||||
} else {
|
} else {
|
||||||
resolve(data);
|
resolve(data);
|
||||||
}
|
}
|
||||||
})
|
}).catch(function(error) {
|
||||||
.catch(function(error) {
|
|
||||||
responseClone.text().then(function(text) {
|
responseClone.text().then(function(text) {
|
||||||
reject(new Error('Cannot parse JSON: ' + text));
|
reject(new Error('Cannot parse JSON: ' + text));
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user