mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Mobile: More rendering optimisations to make animations smoother and to allow typing fast on large notes
This commit is contained in:
parent
981c97cca5
commit
c2a80b12f0
@ -158,8 +158,12 @@ class ScreenHeaderComponent extends React.PureComponent {
|
||||
}
|
||||
|
||||
async backButton_press() {
|
||||
if (this.props.noteSelectionEnabled) {
|
||||
this.props.dispatch({ type: 'NOTE_SELECTION_END' });
|
||||
} else {
|
||||
await BackButtonService.back();
|
||||
}
|
||||
}
|
||||
|
||||
searchButton_press() {
|
||||
NavService.go('Search');
|
||||
@ -374,22 +378,30 @@ class ScreenHeaderComponent extends React.PureComponent {
|
||||
</TouchableOpacity>
|
||||
) : null;
|
||||
|
||||
const showSideMenuButton = this.props.showSideMenuButton !== false && !this.props.noteSelectionEnabled;
|
||||
const showSearchButton = this.props.showSearchButton !== false && !this.props.noteSelectionEnabled;
|
||||
const showSideMenuButton = !!this.props.showSideMenuButton && !this.props.noteSelectionEnabled;
|
||||
const showSearchButton = !!this.props.showSearchButton && !this.props.noteSelectionEnabled;
|
||||
const showContextMenuButton = this.props.showContextMenuButton !== false;
|
||||
const showBackButton = this.props.showBackButton !== false;
|
||||
const showBackButton = !!this.props.noteSelectionEnabled || this.props.showBackButton !== false;
|
||||
|
||||
let backButtonDisabled = !this.props.historyCanGoBack;
|
||||
if (!!this.props.noteSelectionEnabled) backButtonDisabled = false;
|
||||
|
||||
const titleComp = createTitleComponent();
|
||||
const sideMenuComp = !showSideMenuButton ? null : sideMenuButton(this.styles(), () => this.sideMenuButton_press());
|
||||
const backButtonComp = !showBackButton ? null : backButton(this.styles(), () => this.backButton_press(), !this.props.historyCanGoBack);
|
||||
const backButtonComp = !showBackButton ? null : backButton(this.styles(), () => this.backButton_press(), backButtonDisabled);
|
||||
const searchButtonComp = !showSearchButton ? null : searchButton(this.styles(), () => this.searchButton_press());
|
||||
const deleteButtonComp = this.props.noteSelectionEnabled ? deleteButton(this.styles(), () => this.deleteButton_press()) : null;
|
||||
const sortButtonComp = this.props.sortButton_press ? sortButton(this.styles(), () => this.props.sortButton_press()) : null;
|
||||
const sortButtonComp = !this.props.noteSelectionEnabled && this.props.sortButton_press ? sortButton(this.styles(), () => this.props.sortButton_press()) : null;
|
||||
const windowHeight = Dimensions.get('window').height - 50;
|
||||
|
||||
const contextMenuStyle = { paddingTop: PADDING_V, paddingBottom: PADDING_V };
|
||||
|
||||
// HACK: if this button is removed during selection mode, the header layout is broken, so for now just make it 1 pixel large (normally it should be hidden)
|
||||
if (!!this.props.noteSelectionEnabled) contextMenuStyle.width = 1;
|
||||
|
||||
const menuComp = !menuOptionComponents.length || !showContextMenuButton ? null : (
|
||||
<Menu onSelect={(value) => this.menu_select(value)} style={this.styles().contextMenu}>
|
||||
<MenuTrigger style={{ paddingTop: PADDING_V, paddingBottom: PADDING_V }}>
|
||||
<MenuTrigger style={contextMenuStyle}>
|
||||
<Icon name='md-more' style={this.styles().contextMenuTrigger} />
|
||||
</MenuTrigger>
|
||||
<MenuOptions>
|
||||
|
@ -190,13 +190,20 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
this.sideMenuOptions = this.sideMenuOptions.bind(this);
|
||||
this.folderPickerOptions_valueChanged = this.folderPickerOptions_valueChanged.bind(this);
|
||||
this.saveNoteButton_press = this.saveNoteButton_press.bind(this);
|
||||
this.onAlarmDialogAccept = this.onAlarmDialogAccept.bind(this);
|
||||
this.onAlarmDialogReject = this.onAlarmDialogReject.bind(this);
|
||||
this.todoCheckbox_change = this.todoCheckbox_change.bind(this);
|
||||
this.titleTextInput_contentSizeChange = this.titleTextInput_contentSizeChange.bind(this);
|
||||
this.title_changeText = this.title_changeText.bind(this);
|
||||
}
|
||||
|
||||
styles() {
|
||||
const themeId = this.props.theme;
|
||||
const theme = themeStyle(themeId);
|
||||
|
||||
if (this.styles_[themeId]) return this.styles_[themeId];
|
||||
const cacheKey = [themeId, this.state.titleTextInputHeight, this.state.HACK_webviewLoadingState].join('_');
|
||||
|
||||
if (this.styles_[cacheKey]) return this.styles_[cacheKey];
|
||||
this.styles_ = {};
|
||||
|
||||
let styles = {
|
||||
@ -216,6 +223,13 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
paddingTop: theme.marginTop,
|
||||
paddingBottom: theme.marginBottom,
|
||||
},
|
||||
checkbox: {
|
||||
color: theme.color,
|
||||
paddingRight: 10,
|
||||
paddingLeft: theme.marginLeft,
|
||||
paddingTop: 10, // Added for iOS (Not needed for Android??)
|
||||
paddingBottom: 10, // Added for iOS (Not needed for Android??)
|
||||
},
|
||||
};
|
||||
|
||||
styles.titleContainer = {
|
||||
@ -230,8 +244,23 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
styles.titleContainerTodo = Object.assign({}, styles.titleContainer);
|
||||
styles.titleContainerTodo.paddingLeft = 0;
|
||||
|
||||
this.styles_[themeId] = StyleSheet.create(styles);
|
||||
return this.styles_[themeId];
|
||||
styles.titleTextInput = {
|
||||
flex: 1,
|
||||
marginTop: 0,
|
||||
paddingLeft: 0,
|
||||
color: theme.color,
|
||||
backgroundColor: theme.backgroundColor,
|
||||
fontWeight: 'bold',
|
||||
fontSize: theme.fontSize,
|
||||
paddingTop: 10, // Added for iOS (Not needed for Android??)
|
||||
paddingBottom: 10, // Added for iOS (Not needed for Android??)
|
||||
};
|
||||
|
||||
if (this.enableMultilineTitle_) styles.titleTextInput.height = this.state.titleTextInputHeight;
|
||||
if (this.state.HACK_webviewLoadingState === 1) styles.titleTextInput.marginTop = 1;
|
||||
|
||||
this.styles_[cacheKey] = StyleSheet.create(styles);
|
||||
return this.styles_[cacheKey];
|
||||
}
|
||||
|
||||
isModified() {
|
||||
@ -783,7 +812,7 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
},
|
||||
});
|
||||
|
||||
if (this.state.mode == 'edit') return null;//<ActionButton style={{display:'none'}}/>;
|
||||
if (this.state.mode == 'edit') return null;
|
||||
|
||||
return <ActionButton multiStates={true} buttons={buttons} buttonIndex={0} />
|
||||
}
|
||||
@ -797,46 +826,20 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
|
||||
const titleContainerStyle = isTodo ? this.styles().titleContainerTodo : this.styles().titleContainer;
|
||||
|
||||
let titleTextInputStyle = {
|
||||
flex: 1,
|
||||
marginTop: 0,
|
||||
paddingLeft: 0,
|
||||
color: theme.color,
|
||||
backgroundColor: theme.backgroundColor,
|
||||
fontWeight: 'bold',
|
||||
fontSize: theme.fontSize,
|
||||
paddingTop: 10, // Added for iOS (Not needed for Android??)
|
||||
paddingBottom: 10, // Added for iOS (Not needed for Android??)
|
||||
};
|
||||
|
||||
if (this.enableMultilineTitle_) titleTextInputStyle.height = this.state.titleTextInputHeight;
|
||||
|
||||
let checkboxStyle = {
|
||||
color: theme.color,
|
||||
paddingRight: 10,
|
||||
paddingLeft: theme.marginLeft,
|
||||
paddingTop: 10, // Added for iOS (Not needed for Android??)
|
||||
paddingBottom: 10, // Added for iOS (Not needed for Android??)
|
||||
}
|
||||
|
||||
if (this.state.HACK_webviewLoadingState === 1) {
|
||||
titleTextInputStyle.marginTop = 1;
|
||||
}
|
||||
|
||||
const dueDate = isTodo && note.todo_due ? new Date(note.todo_due) : null;
|
||||
const dueDate = Note.dueDateObject(note);
|
||||
|
||||
const titleComp = (
|
||||
<View style={titleContainerStyle}>
|
||||
{ isTodo && <Checkbox style={checkboxStyle} checked={!!Number(note.todo_completed)} onChange={(checked) => { this.todoCheckbox_change(checked) }} /> }
|
||||
{ isTodo && <Checkbox style={this.styles().checkbox} checked={!!Number(note.todo_completed)} onChange={this.todoCheckbox_change} /> }
|
||||
<TextInput
|
||||
onContentSizeChange={(event) => this.titleTextInput_contentSizeChange(event)}
|
||||
onContentSizeChange={this.titleTextInput_contentSizeChange}
|
||||
multiline={this.enableMultilineTitle_}
|
||||
ref="titleTextField"
|
||||
underlineColorAndroid="#ffffff00"
|
||||
autoCapitalize="sentences"
|
||||
style={titleTextInputStyle}
|
||||
style={this.styles().titleTextInput}
|
||||
value={note.title}
|
||||
onChangeText={(text) => this.title_changeText(text)}
|
||||
onChangeText={this.title_changeText}
|
||||
selectionColor={theme.textSelectionColor}
|
||||
placeholder={_('Add title')}
|
||||
/>
|
||||
@ -863,8 +866,8 @@ class NoteScreenComponent extends BaseScreenComponent {
|
||||
<SelectDateTimeDialog
|
||||
shown={this.state.alarmDialogShown}
|
||||
date={dueDate}
|
||||
onAccept={(date) => this.onAlarmDialogAccept(date) }
|
||||
onReject={() => this.onAlarmDialogReject() }
|
||||
onAccept={this.onAlarmDialogAccept}
|
||||
onReject={this.onAlarmDialogReject}
|
||||
/>
|
||||
|
||||
<DialogBox ref={dialogbox => { this.dialogbox = dialogbox }}/>
|
||||
|
@ -1,5 +1,5 @@
|
||||
const React = require('react'); const Component = React.Component;
|
||||
const { AppState, View, Button, Text } = require('react-native');
|
||||
const { AppState, View, Button, Text, StyleSheet } = require('react-native');
|
||||
const { stateUtils } = require('lib/reducer.js');
|
||||
const { connect } = require('react-redux');
|
||||
const { reg } = require('lib/registry.js');
|
||||
@ -72,6 +72,25 @@ class NotesScreenComponent extends BaseScreenComponent {
|
||||
}
|
||||
}
|
||||
|
||||
styles() {
|
||||
if (!this.styles_) this.styles_ = {};
|
||||
const themeId = this.props.theme;
|
||||
const theme = themeStyle(themeId);
|
||||
const cacheKey = themeId;
|
||||
|
||||
if (this.styles_[cacheKey]) return this.styles_[cacheKey];
|
||||
this.styles_ = {};
|
||||
|
||||
let styles = {
|
||||
noteList: {
|
||||
flex: 1,
|
||||
},
|
||||
};
|
||||
|
||||
this.styles_[cacheKey] = StyleSheet.create(styles);
|
||||
return this.styles_[cacheKey];
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
await this.refreshNotes();
|
||||
AppState.addEventListener('change', this.onAppStateChange_);
|
||||
@ -151,23 +170,6 @@ class NotesScreenComponent extends BaseScreenComponent {
|
||||
});
|
||||
}
|
||||
|
||||
menuOptions() {
|
||||
if (this.props.notesParentType == 'Folder') {
|
||||
if (this.props.selectedFolderId == Folder.conflictFolderId()) return [];
|
||||
|
||||
const folder = this.parentItem();
|
||||
if (!folder) return [];
|
||||
|
||||
let output = [];
|
||||
// if (!folder.encryption_applied) output.push({ title: _('Edit notebook'), onPress: () => { this.editFolder_onPress(this.props.selectedFolderId); } });
|
||||
// output.push({ title: _('Delete notebook'), onPress: () => { this.deleteFolder_onPress(this.props.selectedFolderId); } });
|
||||
|
||||
return output;
|
||||
} else {
|
||||
return []; // For tags - TODO
|
||||
}
|
||||
}
|
||||
|
||||
parentItem(props = null) {
|
||||
if (!props) props = this.props;
|
||||
|
||||
@ -185,6 +187,18 @@ class NotesScreenComponent extends BaseScreenComponent {
|
||||
return output;
|
||||
}
|
||||
|
||||
folderPickerOptions() {
|
||||
const options = {
|
||||
enabled: this.props.noteSelectionEnabled,
|
||||
mustSelect: true,
|
||||
};
|
||||
|
||||
if (this.folderPickerOptions_ && options.enabled === this.folderPickerOptions_.enabled) return this.folderPickerOptions_;
|
||||
|
||||
this.folderPickerOptions_ = options;
|
||||
return this.folderPickerOptions_;
|
||||
}
|
||||
|
||||
render() {
|
||||
const parent = this.parentItem();
|
||||
const theme = themeStyle(this.props.theme);
|
||||
@ -201,7 +215,7 @@ class NotesScreenComponent extends BaseScreenComponent {
|
||||
if (!parent) {
|
||||
return (
|
||||
<View style={rootStyle}>
|
||||
<ScreenHeader title={title} menuOptions={this.menuOptions()} />
|
||||
<ScreenHeader title={title} />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@ -216,15 +230,13 @@ class NotesScreenComponent extends BaseScreenComponent {
|
||||
<ScreenHeader
|
||||
title={title}
|
||||
showBackButton={false}
|
||||
menuOptions={this.menuOptions()}
|
||||
parentComponent={thisComp}
|
||||
sortButton_press={this.sortButton_press}
|
||||
folderPickerOptions={{
|
||||
enabled: this.props.noteSelectionEnabled,
|
||||
mustSelect: true,
|
||||
}}
|
||||
folderPickerOptions={this.folderPickerOptions()}
|
||||
showSearchButton={true}
|
||||
showSideMenuButton={true}
|
||||
/>
|
||||
<NoteList style={{flex: 1}}/>
|
||||
<NoteList style={this.styles().noteList}/>
|
||||
{ actionButtonComp }
|
||||
<DialogBox ref={dialogbox => { this.dialogbox = dialogbox }}/>
|
||||
</View>
|
||||
|
@ -5,13 +5,15 @@ import DatePicker from 'react-native-datepicker'
|
||||
import moment from 'moment';
|
||||
import { _ } from 'lib/locale.js';
|
||||
|
||||
class SelectDateTimeDialog extends Component {
|
||||
class SelectDateTimeDialog extends React.PureComponent {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.dialog_ = null;
|
||||
this.shown_ = false;
|
||||
this.state = { date: null };
|
||||
|
||||
this.onReject = this.onReject.bind(this);
|
||||
}
|
||||
|
||||
UNSAFE_componentWillReceiveProps(newProps) {
|
||||
@ -72,6 +74,7 @@ class SelectDateTimeDialog extends Component {
|
||||
ref={(dialog) => { this.dialog_ = dialog; }}
|
||||
dialogTitle={<DialogTitle title={_('Set alarm')} />}
|
||||
actions={popupActions}
|
||||
dismissOnTouchOutside={false}
|
||||
width={0.9}
|
||||
height={350}
|
||||
>
|
||||
|
@ -603,6 +603,17 @@ class Note extends BaseItem {
|
||||
return note.is_todo && !note.todo_completed && note.todo_due >= time.unixMs() && !note.is_conflict;
|
||||
}
|
||||
|
||||
static dueDateObject(note) {
|
||||
if (!!note.is_todo && note.todo_due) {
|
||||
if (!this.dueDateObjects_) this.dueDateObjects_ = {};
|
||||
if (this.dueDateObjects_[note.todo_due]) return this.dueDateObjects_[note.todo_due];
|
||||
this.dueDateObjects_[note.todo_due] = new Date(note.todo_due);
|
||||
return this.dueDateObjects_[note.todo_due];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Tells whether the conflict between the local and remote note can be ignored.
|
||||
static mustHandleConflict(localNote, remoteNote) {
|
||||
// That shouldn't happen so throw an exception
|
||||
|
Loading…
Reference in New Issue
Block a user