mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Started config screen
This commit is contained in:
parent
d05c62f69f
commit
04cd9a1e7b
@ -7,6 +7,7 @@ import { Checkbox } from 'lib/components/checkbox.js';
|
||||
import { NoteItem } from 'lib/components/note-item.js';
|
||||
import { reg } from 'lib/registry.js';
|
||||
import { Note } from 'lib/models/note.js';
|
||||
import { Setting } from 'lib/models/setting.js';
|
||||
import { time } from 'lib/time-utils.js';
|
||||
import { globalStyle } from 'lib/components/global-style.js';
|
||||
|
||||
@ -33,15 +34,35 @@ class ItemListComponent extends Component {
|
||||
};
|
||||
}
|
||||
|
||||
filterNotes(notes) {
|
||||
const todoFilter = Setting.value('todoFilter');
|
||||
if (todoFilter == 'all') return notes;
|
||||
|
||||
const now = time.unixMs();
|
||||
const maxInterval = 1000 * 60 * 60 * 24 * 2;
|
||||
const notRecentTime = now - maxInterval;
|
||||
|
||||
let output = [];
|
||||
for (let i = 0; i < notes.length; i++) {
|
||||
const note = notes[i];
|
||||
if (note.is_todo) {
|
||||
if (todoFilter == 'recent' && note.updated_time < notRecentTime) continue;
|
||||
if (todoFilter == 'nonCompleted' && !!note.todo_completed) continue;
|
||||
}
|
||||
output.push(note);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const newDataSource = this.state.dataSource.cloneWithRows(this.props.items);
|
||||
const newDataSource = this.state.dataSource.cloneWithRows(this.filterNotes(this.props.items));
|
||||
this.state = { dataSource: newDataSource };
|
||||
}
|
||||
|
||||
componentWillReceiveProps(newProps) {
|
||||
// https://stackoverflow.com/questions/38186114/react-native-redux-and-listview
|
||||
this.setState({
|
||||
dataSource: this.state.dataSource.cloneWithRows(newProps.items),
|
||||
dataSource: this.state.dataSource.cloneWithRows(this.filterNotes(newProps.items)),
|
||||
});
|
||||
}
|
||||
|
||||
@ -49,7 +70,6 @@ class ItemListComponent extends Component {
|
||||
let note = await Note.load(itemId);
|
||||
await Note.save({ id: note.id, todo_completed: checked ? time.unixMs() : 0 });
|
||||
reg.scheduleSync();
|
||||
|
||||
}
|
||||
|
||||
listView_itemLongPress(itemId) {}
|
||||
|
@ -9,7 +9,7 @@ import { Note } from 'lib/models/note.js';
|
||||
import { time } from 'lib/time-utils.js';
|
||||
import { globalStyle } from 'lib/components/global-style.js';
|
||||
|
||||
const styleObject = {
|
||||
let styles = {
|
||||
listItem: {
|
||||
flexDirection: 'row',
|
||||
height: 40,
|
||||
@ -24,7 +24,10 @@ const styleObject = {
|
||||
},
|
||||
};
|
||||
|
||||
const styles = StyleSheet.create(styleObject);
|
||||
styles.listItemFadded = Object.assign({}, styles.listItem);
|
||||
styles.listItemFadded.opacity = 0.4;
|
||||
|
||||
styles = StyleSheet.create(styles);
|
||||
|
||||
class NoteItemComponent extends Component {
|
||||
|
||||
@ -45,9 +48,11 @@ class NoteItemComponent extends Component {
|
||||
const checkboxStyle = !Number(note.is_todo) ? { display: 'none' } : { color: globalStyle.color };
|
||||
const checkboxChecked = !!Number(note.todo_completed);
|
||||
|
||||
const listItemStyle = !!Number(note.is_todo) && checkboxChecked ? styles.listItemFadded : styles.listItem;
|
||||
|
||||
return (
|
||||
<TouchableHighlight onPress={() => onPress ? onPress(note) : this.noteItem_press(note.id)} onLongPress={() => onLongPress(note)} underlayColor="#0066FF">
|
||||
<View style={ styles.listItem }>
|
||||
<View style={ listItemStyle }>
|
||||
<Checkbox style={checkboxStyle} checked={checkboxChecked} onChange={(checked) => { onCheckboxChange(note, checked) }}/><Text style={styles.listItemText}>{note.title}</Text>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
|
@ -144,6 +144,13 @@ class ScreenHeaderComponent extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
config_press() {
|
||||
this.props.dispatch({
|
||||
type: 'Navigation/NAVIGATE',
|
||||
routeName: 'Config',
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
function sideMenuButton(styles, onPress) {
|
||||
@ -213,6 +220,15 @@ class ScreenHeaderComponent extends Component {
|
||||
<Text style={styles.contextMenuItemText}>{_('Status')}</Text>
|
||||
</MenuOption>);
|
||||
|
||||
if (menuOptionComponents.length) {
|
||||
menuOptionComponents.push(<View key={'menuOption_' + key++} style={styles.divider}/>);
|
||||
}
|
||||
|
||||
menuOptionComponents.push(
|
||||
<MenuOption value={() => this.config_press()} key={'menuOption_' + key++} style={styles.contextMenuItem}>
|
||||
<Text style={styles.contextMenuItemText}>{_('Configuration')}</Text>
|
||||
</MenuOption>);
|
||||
|
||||
const createTitleComponent = () => {
|
||||
const p = this.props.titlePicker;
|
||||
if (p) {
|
||||
|
114
ReactNativeClient/lib/components/screens/config.js
Normal file
114
ReactNativeClient/lib/components/screens/config.js
Normal file
@ -0,0 +1,114 @@
|
||||
import React, { Component } from 'react';
|
||||
import { View, StyleSheet, Picker, Text, Button } from 'react-native';
|
||||
import { connect } from 'react-redux'
|
||||
import { ScreenHeader } from 'lib/components/screen-header.js';
|
||||
import { _ } from 'lib/locale.js';
|
||||
import { BaseScreenComponent } from 'lib/components/base-screen.js';
|
||||
import { globalStyle } from 'lib/components/global-style.js';
|
||||
import { Setting } from 'lib/models/setting.js';
|
||||
|
||||
let styles = {
|
||||
body: {}
|
||||
}
|
||||
|
||||
styles = StyleSheet.create(styles);
|
||||
|
||||
class ConfigScreenComponent extends BaseScreenComponent {
|
||||
|
||||
static navigationOptions(options) {
|
||||
return { header: null };
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
values: {},
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const settings = Setting.publicSettings(Setting.value('appType'));
|
||||
|
||||
let values = {};
|
||||
for (let key in settings) {
|
||||
if (!settings.hasOwnProperty(key)) continue;
|
||||
values[key] = settings[key].value;
|
||||
}
|
||||
|
||||
this.setState({ values: values });
|
||||
}
|
||||
|
||||
settingToComponent(key, setting) {
|
||||
let output = null;
|
||||
|
||||
const updateSettingValue = (key, value) => {
|
||||
let values = this.state.values;
|
||||
values[key] = value;
|
||||
this.setState({ values: values });
|
||||
}
|
||||
|
||||
const value = this.state.values[key];
|
||||
|
||||
if (setting.type == 'enum') {
|
||||
let items = [];
|
||||
const settingOptions = setting.options();
|
||||
for (let k in settingOptions) {
|
||||
if (!settingOptions.hasOwnProperty(k)) continue;
|
||||
items.push(<Picker.Item label={settingOptions[k]} value={k} key={k}/>);
|
||||
}
|
||||
|
||||
return (
|
||||
<View key={key}>
|
||||
<Text key="label">{setting.label()}</Text>
|
||||
<Picker key="control" selectedValue={value} onValueChange={(itemValue, itemIndex) => updateSettingValue(key, itemValue)} >
|
||||
{ items }
|
||||
</Picker>
|
||||
</View>
|
||||
);
|
||||
} else {
|
||||
//throw new Error('Unsupported setting type: ' + setting.type);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
saveButton_press() {
|
||||
const values = this.state.values;
|
||||
for (let key in values) {
|
||||
if (!values.hasOwnProperty(key)) continue;
|
||||
Setting.setValue(key, values[key]);
|
||||
}
|
||||
Setting.saveAll();
|
||||
}
|
||||
|
||||
render() {
|
||||
const settings = Setting.publicSettings(Setting.value('appType'));
|
||||
|
||||
let settingComps = [];
|
||||
for (let key in settings) {
|
||||
if (!settings.hasOwnProperty(key)) continue;
|
||||
const comp = this.settingToComponent(key, settings[key]);
|
||||
if (!comp) continue;
|
||||
settingComps.push(comp);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={this.styles().screen}>
|
||||
<ScreenHeader navState={this.props.navigation.state} />
|
||||
<View style={styles.body}>
|
||||
{ settingComps }
|
||||
</View>
|
||||
<Button title={_('Save')} onPress={() => this.saveButton_press()} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const ConfigScreen = connect(
|
||||
(state) => {
|
||||
return {};
|
||||
}
|
||||
)(ConfigScreenComponent)
|
||||
|
||||
export { ConfigScreen };
|
@ -90,8 +90,16 @@ class SearchScreenComponent extends BaseScreenComponent {
|
||||
let notes = []
|
||||
|
||||
if (query) {
|
||||
let p = query.split(' ');
|
||||
let temp = [];
|
||||
for (let i = 0; i < p.length; i++) {
|
||||
let t = p[i].trim();
|
||||
if (!t) continue;
|
||||
temp.push(t);
|
||||
}
|
||||
|
||||
notes = await Note.previews(null, {
|
||||
anywherePattern: '*' + query + '*',
|
||||
anywherePattern: '*' + temp.join('*') + '*',
|
||||
});
|
||||
}
|
||||
|
||||
@ -112,6 +120,7 @@ class SearchScreenComponent extends BaseScreenComponent {
|
||||
<View style={styles.searchContainer}>
|
||||
<TextInput
|
||||
style={styles.searchTextInput}
|
||||
autoFocus={true}
|
||||
underlineColorAndroid="#ffffff00"
|
||||
onSubmitEditing={() => { this.searchTextInput_submit() }}
|
||||
onChangeText={(text) => this.searchTextInput_changeText(text) }
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { BaseModel } from 'lib/base-model.js';
|
||||
import { Database } from 'lib/database.js';
|
||||
import { _ } from 'lib/locale.js';
|
||||
|
||||
class Setting extends BaseModel {
|
||||
|
||||
@ -120,6 +121,9 @@ class Setting extends BaseModel {
|
||||
for (let i = 0; i < this.cache_.length; i++) {
|
||||
let s = Object.assign({}, this.cache_[i]);
|
||||
delete s.public;
|
||||
delete s.appTypes;
|
||||
delete s.label;
|
||||
delete s.options;
|
||||
queries.push(Database.insertQuery(this.tableName(), s));
|
||||
}
|
||||
|
||||
@ -141,17 +145,37 @@ class Setting extends BaseModel {
|
||||
this.updateTimeoutId_ = null;
|
||||
}
|
||||
|
||||
static publicSettings(appType) {
|
||||
if (!appType) throw new Error('appType is required');
|
||||
|
||||
let output = {};
|
||||
for (let key in Setting.defaults_) {
|
||||
if (!Setting.defaults_.hasOwnProperty(key)) continue;
|
||||
let s = Object.assign({}, Setting.defaults_[key]);
|
||||
if (!s.public) continue;
|
||||
if (s.appTypes && s.appTypes.indexOf(appType) < 0) continue;
|
||||
s.value = this.value(key);
|
||||
output[key] = s;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Setting.defaults_ = {
|
||||
'activeFolderId': { value: '', type: 'string', public: false },
|
||||
'sync.onedrive.auth': { value: '', type: 'string', public: false },
|
||||
'sync.filesystem.path': { value: '', type: 'string', public: true },
|
||||
'sync.target': { value: 'onedrive', type: 'string', public: true },
|
||||
'sync.filesystem.path': { value: '', type: 'string', public: true, appTypes: ['cli'] },
|
||||
'sync.target': { value: 'onedrive', type: 'string', public: true, label: () => _('Synchronisation target') },
|
||||
'sync.context': { value: '', type: 'string', public: false },
|
||||
'editor': { value: '', type: 'string', public: true },
|
||||
'editor': { value: '', type: 'string', public: true, appTypes: ['cli'] },
|
||||
'locale': { value: 'en_GB', type: 'string', public: true },
|
||||
'aliases': { value: '', type: 'string', public: true },
|
||||
//'aliases': { value: '', type: 'string', public: true },
|
||||
'todoFilter': { value: 'all', type: 'enum', public: true, appTypes: ['mobile'], label: () => _('Todo filter'), options: () => ({
|
||||
all: _('Show all'),
|
||||
recent: _('Non-completed and recently completed ones'),
|
||||
nonCompleted: _('Non-completed ones only'),
|
||||
})},
|
||||
};
|
||||
|
||||
// Contains constants that are set by the application and
|
||||
|
@ -20,6 +20,7 @@ import { ItemList } from 'lib/components/item-list.js'
|
||||
import { NotesScreen } from 'lib/components/screens/notes.js'
|
||||
import { NotesScreenUtils } from 'lib/components/screens/notes-utils.js'
|
||||
import { NoteScreen } from 'lib/components/screens/note.js'
|
||||
import { ConfigScreen } from 'lib/components/screens/config.js'
|
||||
import { FolderScreen } from 'lib/components/screens/folder.js'
|
||||
import { FoldersScreen } from 'lib/components/screens/folders.js'
|
||||
import { LogScreen } from 'lib/components/screens/log.js'
|
||||
@ -409,6 +410,11 @@ async function initialize(dispatch, backButtonHandler) {
|
||||
let folderId = Setting.value('activeFolderId');
|
||||
let folder = await Folder.load(folderId);
|
||||
|
||||
// dispatch({
|
||||
// type: 'Navigation/NAVIGATE',
|
||||
// routeName: 'Config',
|
||||
// });
|
||||
|
||||
if (folder) {
|
||||
await NotesScreenUtils.openNoteList(folderId);
|
||||
} else {
|
||||
@ -490,6 +496,7 @@ class AppComponent extends React.Component {
|
||||
Log: { screen: LogScreen },
|
||||
Status: { screen: StatusScreen },
|
||||
Search: { screen: SearchScreen },
|
||||
Config: { screen: ConfigScreen },
|
||||
};
|
||||
|
||||
return (
|
||||
|
Loading…
Reference in New Issue
Block a user