2017-05-09 21:59:14 +02:00
|
|
|
import React, { Component } from 'react';
|
2017-05-09 22:46:54 +02:00
|
|
|
import { View, Button, TextInput } from 'react-native';
|
2017-05-09 21:59:14 +02:00
|
|
|
import { connect } from 'react-redux'
|
|
|
|
import { Provider } from 'react-redux'
|
|
|
|
import { createStore } from 'redux';
|
|
|
|
import { combineReducers } from 'redux';
|
|
|
|
import { StackNavigator } from 'react-navigation';
|
|
|
|
import { addNavigationHelpers } from 'react-navigation';
|
2017-05-09 22:46:54 +02:00
|
|
|
import { Log } from 'src/log.js'
|
2017-05-10 21:21:09 +02:00
|
|
|
import { Note } from 'src/models/note.js'
|
2017-05-09 22:46:54 +02:00
|
|
|
import { ItemList } from 'src/components/item-list.js'
|
|
|
|
|
|
|
|
let defaultState = {
|
|
|
|
defaultText: 'bla',
|
|
|
|
notes: [
|
|
|
|
{ id: 1, title: "hello", body: "just testing\nmultiple\nlines" },
|
|
|
|
{ id: 2, title: "hello2", body: "2 just testing\nmultiple\nlines" },
|
|
|
|
{ id: 3, title: "hello3", body: "3 just testing\nmultiple\nlines" },
|
|
|
|
{ id: 4, title: "hello4", body: "4 just testing\nmultiple\nlines" },
|
|
|
|
],
|
|
|
|
selectedNoteId: null,
|
|
|
|
};
|
|
|
|
|
|
|
|
const reducer = (state = defaultState, action) => {
|
|
|
|
Log.info('Reducer action', action);
|
|
|
|
|
2017-05-10 21:21:09 +02:00
|
|
|
let newState = state;
|
|
|
|
|
2017-05-09 22:46:54 +02:00
|
|
|
switch (action.type) {
|
|
|
|
|
2017-05-10 20:58:02 +02:00
|
|
|
case 'Navigation/NAVIGATE':
|
|
|
|
case 'Navigation/BACK':
|
2017-05-09 22:46:54 +02:00
|
|
|
|
2017-05-10 21:21:09 +02:00
|
|
|
const nextStateNav = AppNavigator.router.getStateForAction(action, state.nav);
|
|
|
|
newState = Object.assign({}, state);
|
|
|
|
if (nextStateNav) {
|
|
|
|
newState.nav = nextStateNav;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action.noteId) {
|
|
|
|
newState.selectedNoteId = action.noteId;
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
2017-05-09 22:46:54 +02:00
|
|
|
|
2017-05-11 23:02:47 +02:00
|
|
|
// Replace all the notes with the provided array
|
|
|
|
case 'NOTES_UPDATE_ALL':
|
2017-05-09 22:46:54 +02:00
|
|
|
|
2017-05-10 21:21:09 +02:00
|
|
|
newState = Object.assign({}, state);
|
2017-05-11 22:14:01 +02:00
|
|
|
newState.notes = action.notes;
|
|
|
|
break;
|
|
|
|
|
2017-05-11 23:02:47 +02:00
|
|
|
// Insert the note into the note list if it's new, or
|
|
|
|
// update it if it already exists.
|
|
|
|
case 'NOTES_UPDATE_ONE':
|
|
|
|
|
|
|
|
let newNotes = state.notes.splice(0);
|
|
|
|
let found = false;
|
|
|
|
for (let i = 0; i < newNotes.length; i++) {
|
|
|
|
let n = newNotes[i];
|
|
|
|
if (n.id == action.note.id) {
|
|
|
|
newNotes[i] = action.note;
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2017-05-10 21:21:09 +02:00
|
|
|
|
2017-05-11 23:02:47 +02:00
|
|
|
if (!found) newNotes.push(action.note);
|
2017-05-11 22:14:01 +02:00
|
|
|
|
2017-05-11 23:02:47 +02:00
|
|
|
newState = Object.assign({}, state);
|
|
|
|
newState.notes = newNotes;
|
2017-05-11 22:14:01 +02:00
|
|
|
break;
|
2017-05-09 22:46:54 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-05-10 21:21:09 +02:00
|
|
|
return newState;
|
2017-05-09 22:46:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
let store = createStore(reducer);
|
|
|
|
|
2017-05-10 21:21:09 +02:00
|
|
|
class NotesScreenComponent extends React.Component {
|
2017-05-09 22:46:54 +02:00
|
|
|
static navigationOptions = {
|
|
|
|
title: 'Notes',
|
|
|
|
};
|
|
|
|
render() {
|
|
|
|
const { navigate } = this.props.navigation;
|
|
|
|
return (
|
|
|
|
<View style={{flex: 1}}>
|
|
|
|
<ItemList style={{flex: 1}}/>
|
|
|
|
<Button
|
|
|
|
title="Create note"
|
|
|
|
onPress={() =>
|
|
|
|
navigate('Note')
|
|
|
|
}
|
|
|
|
/>
|
|
|
|
</View>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-10 21:21:09 +02:00
|
|
|
const NotesScreen = connect(
|
|
|
|
(state) => {
|
|
|
|
return {};
|
|
|
|
},
|
|
|
|
(dispatch) => {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
)(NotesScreenComponent)
|
|
|
|
|
|
|
|
class NoteScreenComponent extends React.Component {
|
2017-05-10 21:51:43 +02:00
|
|
|
|
2017-05-09 22:46:54 +02:00
|
|
|
static navigationOptions = {
|
|
|
|
title: 'Note',
|
|
|
|
};
|
2017-05-10 21:51:43 +02:00
|
|
|
|
|
|
|
constructor() {
|
|
|
|
super();
|
|
|
|
this.state = { note: Note.newNote() }
|
|
|
|
}
|
|
|
|
|
|
|
|
componentWillMount() {
|
|
|
|
this.setState({ note: this.props.note });
|
|
|
|
}
|
|
|
|
|
2017-05-11 22:14:01 +02:00
|
|
|
noteComponent_change = (propName, propValue) => {
|
2017-05-10 21:51:43 +02:00
|
|
|
this.setState((prevState, props) => {
|
|
|
|
let note = Object.assign({}, prevState.note);
|
|
|
|
note[propName] = propValue;
|
|
|
|
return { note: note }
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2017-05-11 22:14:01 +02:00
|
|
|
title_changeText = (text) => {
|
|
|
|
this.noteComponent_change('title', text);
|
2017-05-10 21:51:43 +02:00
|
|
|
}
|
|
|
|
|
2017-05-11 22:14:01 +02:00
|
|
|
body_changeText = (text) => {
|
|
|
|
this.noteComponent_change('body', text);
|
2017-05-10 21:51:43 +02:00
|
|
|
}
|
|
|
|
|
2017-05-11 22:14:01 +02:00
|
|
|
saveNoteButton_press = () => {
|
|
|
|
// TODO: if state changes are asynchronous, how to be sure that, when
|
|
|
|
// the button is presssed, this.state.note contains the actual note?
|
2017-05-11 23:02:47 +02:00
|
|
|
Note.save(this.state.note).then((note) => {
|
|
|
|
this.props.dispatch({
|
|
|
|
type: 'NOTES_UPDATE_ONE',
|
|
|
|
note: note,
|
|
|
|
});
|
2017-05-11 22:14:01 +02:00
|
|
|
}).catch((error) => {
|
2017-05-11 23:02:47 +02:00
|
|
|
Log.warn('Cannot save note', error);
|
2017-05-11 22:14:01 +02:00
|
|
|
});
|
|
|
|
}
|
2017-05-10 21:51:43 +02:00
|
|
|
|
2017-05-11 22:14:01 +02:00
|
|
|
render() {
|
2017-05-09 22:46:54 +02:00
|
|
|
return (
|
|
|
|
<View style={{flex: 1}}>
|
2017-05-11 22:14:01 +02:00
|
|
|
<TextInput value={this.state.note.title} onChangeText={this.title_changeText} />
|
|
|
|
<TextInput style={{flex: 1, textAlignVertical: 'top'}} multiline={true} value={this.state.note.body} onChangeText={this.body_changeText} />
|
|
|
|
<Button title="Save note" onPress={this.saveNoteButton_press} />
|
2017-05-09 22:46:54 +02:00
|
|
|
</View>
|
|
|
|
);
|
|
|
|
}
|
2017-05-10 21:51:43 +02:00
|
|
|
|
2017-05-09 21:59:14 +02:00
|
|
|
}
|
|
|
|
|
2017-05-10 21:21:09 +02:00
|
|
|
const NoteScreen = connect(
|
|
|
|
(state) => {
|
2017-05-10 21:51:43 +02:00
|
|
|
return {
|
|
|
|
note: state.selectedNoteId ? Note.noteById(state.notes, state.selectedNoteId) : Note.newNote(),
|
|
|
|
};
|
2017-05-10 21:21:09 +02:00
|
|
|
}
|
|
|
|
)(NoteScreenComponent)
|
|
|
|
|
2017-05-09 21:59:14 +02:00
|
|
|
const AppNavigator = StackNavigator({
|
2017-05-09 22:46:54 +02:00
|
|
|
Notes: {screen: NotesScreen},
|
|
|
|
Note: {screen: NoteScreen},
|
2017-05-09 21:59:14 +02:00
|
|
|
});
|
|
|
|
|
2017-05-10 20:58:02 +02:00
|
|
|
class AppComponent extends React.Component {
|
2017-05-11 22:14:01 +02:00
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
Note.previews().then((notes) => {
|
|
|
|
this.props.dispatch({
|
2017-05-11 23:02:47 +02:00
|
|
|
type: 'NOTES_UPDATE_ALL',
|
2017-05-11 22:14:01 +02:00
|
|
|
notes: notes,
|
|
|
|
});
|
|
|
|
}).catch((error) => {
|
|
|
|
Log.warn('Cannot load notes', error);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
return (
|
|
|
|
<AppNavigator navigation={addNavigationHelpers({
|
|
|
|
dispatch: this.props.dispatch,
|
|
|
|
state: this.props.nav,
|
|
|
|
})} />
|
|
|
|
);
|
|
|
|
}
|
2017-05-10 20:58:02 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
defaultState.nav = AppNavigator.router.getStateForAction(AppNavigator.router.getActionForPathAndParams('Notes'));
|
|
|
|
|
|
|
|
const mapStateToProps = (state) => {
|
|
|
|
return {
|
|
|
|
nav: state.nav
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
const App = connect(mapStateToProps)(AppComponent);
|
|
|
|
|
2017-05-09 22:46:54 +02:00
|
|
|
class Root extends React.Component {
|
|
|
|
render() {
|
|
|
|
return (
|
|
|
|
<Provider store={store}>
|
2017-05-10 20:58:02 +02:00
|
|
|
<App />
|
2017-05-09 22:46:54 +02:00
|
|
|
</Provider>
|
|
|
|
);
|
|
|
|
}
|
2017-05-09 21:59:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export { Root };
|