1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00

Mobile: Made tag UI a dialog

This commit is contained in:
Laurent Cozic 2018-03-17 23:00:01 +00:00
parent d6f7893c56
commit ca3946689a
7 changed files with 55 additions and 50 deletions

View File

@ -30,21 +30,21 @@ class ModalDialog extends React.Component {
borderColor:theme.dividerColor,
margin: 20,
padding: 10,
borderRadius: 5,
},
modalContentWrapper2: {
paddingTop: 10,
flex:1,
},
title: {
borderBottomWidth: 1,
borderBottomColor: theme.dividerColor,
paddingBottom: 10,
fontWeight: 'bold',
},
buttonRow: {
flexDirection: 'row',
borderTopWidth: 1,
borderTopColor: theme.dividerColor,
paddingTop: 10,
},
};
@ -54,21 +54,22 @@ class ModalDialog extends React.Component {
render() {
const ContentComponent = this.props.ContentComponent;
const buttonBarEnabled = this.props.buttonBarEnabled !== false;
return (
<View style={this.styles().modalWrapper}>
<Modal transparent={true} visible={true} onRequestClose={() => { }} >
<View style={this.styles().modalContentWrapper}>
<Text style={this.styles().title}>Title</Text>
<View elevation={10} style={this.styles().modalContentWrapper}>
<Text style={this.styles().title}>{this.props.title}</Text>
<View style={this.styles().modalContentWrapper2}>
{ContentComponent}
</View>
<View style={this.styles().buttonRow}>
<View style={{flex:1}}>
<Button title={_('OK')} onPress={() => {}}></Button>
<Button disabled={!buttonBarEnabled} title={_('OK')} onPress={this.props.onOkPress}></Button>
</View>
<View style={{flex:1, marginLeft: 5}}>
<Button title={_('Cancel')} onPress={() => {}}></Button>
<Button disabled={!buttonBarEnabled} title={_('Cancel')} onPress={this.props.onCancelPress}></Button>
</View>
</View>
</View>

View File

@ -12,18 +12,12 @@ const { Database } = require('lib/database.js');
const Folder = require('lib/models/Folder.js');
const { ReportService } = require('lib/services/report.js');
const { _ } = require('lib/locale.js');
const { BaseScreenComponent } = require('lib/components/base-screen.js');
const { globalStyle, themeStyle } = require('lib/components/global-style.js');
const Icon = require('react-native-vector-icons/Ionicons').default;
const ModalDialog = require('lib/components/ModalDialog');
const naturalCompare = require('string-natural-compare');
const styles = StyleSheet.create({
body: {
flex: 1,
margin: globalStyle.margin,
},
});
class NoteTagsScreenComponent extends BaseScreenComponent {
class NoteTagsDialogComponent extends React.Component {
constructor() {
super();
@ -94,15 +88,11 @@ class NoteTagsScreenComponent extends BaseScreenComponent {
this.setState({ savingTags: false });
}
this.props.dispatch({
type: 'NAV_BACK',
});
if (this.props.onCloseRequested) this.props.onCloseRequested();
}
this.cancelButton_press = () => {
this.props.dispatch({
type: 'NAV_BACK',
});
if (this.props.onCloseRequested) this.props.onCloseRequested();
}
}
@ -122,6 +112,11 @@ class NoteTagsScreenComponent extends BaseScreenComponent {
selected: tagIds.indexOf(tag.id) >= 0,
}});
tagListData.sort((a, b) => {
return naturalCompare.caseInsensitive(a.title, b.title);
//return a.title.toLowerCase() < b.title.toLowerCase() ? -1 : +1;
});
this.setState({ tagListData: tagListData });
}
@ -151,8 +146,8 @@ class NoteTagsScreenComponent extends BaseScreenComponent {
alignItems: 'center',
paddingLeft: theme.marginLeft,
paddingRight: theme.marginRight,
borderTopWidth: 1,
borderTopColor: theme.dividerColor
borderBottomWidth: 1,
borderBottomColor: theme.dividerColor
},
};
@ -163,32 +158,32 @@ class NoteTagsScreenComponent extends BaseScreenComponent {
render() {
const theme = themeStyle(this.props.theme);
return (
<View style={this.rootStyle(this.props.theme).root}>
<ScreenHeader title={_('Note tags')} showSideMenuButton={false} showSearchButton={false} showContextMenuButton={false}/>
const dialogContent = (
<View style={{flex:1}}>
<View style={this.styles().newTagBox}>
<Text>{_('New tags:')}</Text><TextInput value={this.state.newTags} onChangeText={value => { this.setState({ newTags: value }) }} style={{flex:1}}/>
</View>
<FlatList
data={this.state.tagListData}
renderItem={this.renderTag}
keyExtractor={this.tagKeyExtractor}
/>
<View style={this.styles().newTagBox}>
<Text>{_('Or type tags:')}</Text><TextInput value={this.state.newTags} onChangeText={value => { this.setState({ newTags: value }) }} style={{flex:1}}/>
</View>
<View style={theme.buttonRow}>
<View style={{flex:1}}>
<Button disabled={this.state.savingTags} title={_('OK')} onPress={this.okButton_press}></Button>
</View>
<View style={{flex:1, marginLeft: 5}}>
<Button disabled={this.state.savingTags} title={_('Cancel')} onPress={this.cancelButton_press}></Button>
</View>
</View>
</View>
);
return <ModalDialog
theme={this.props.theme}
ContentComponent={dialogContent}
title={_('Type new tags or select from list')}
onOkPress={this.okButton_press}
onCancelPress={this.cancelButton_press}
buttonBarEnabled={!this.state.savingTags}
/>
}
}
const NoteTagsScreen = connect(
const NoteTagsDialog = connect(
(state) => {
return {
theme: state.settings.theme,
@ -196,6 +191,6 @@ const NoteTagsScreen = connect(
noteId: state.selectedNoteIds.length ? state.selectedNoteIds[0] : null,
};
}
)(NoteTagsScreenComponent)
)(NoteTagsDialogComponent)
module.exports = { NoteTagsScreen };
module.exports = NoteTagsDialog;

View File

@ -15,6 +15,7 @@ const Icon = require('react-native-vector-icons/Ionicons').default;
const { fileExtension, basename, safeFileExtension } = require('lib/path-utils.js');
const mimeUtils = require('lib/mime-utils.js').mime;
const { ScreenHeader } = require('lib/components/screen-header.js');
const NoteTagsDialog = require('lib/components/screens/NoteTagsDialog');
const { time } = require('lib/time-utils.js');
const { Checkbox } = require('lib/components/checkbox.js');
const { _ } = require('lib/locale.js');
@ -51,7 +52,8 @@ class NoteScreenComponent extends BaseScreenComponent {
isLoading: true,
titleTextInputHeight: 20,
alarmDialogShown: false,
heightBumpView:0
heightBumpView:0,
noteTagDialogShown: false,
};
// iOS doesn't support multiline text fields properly so disable it
@ -101,6 +103,10 @@ class NoteScreenComponent extends BaseScreenComponent {
return false;
};
this.noteTagDialog_closeRequested = () => {
this.setState({ noteTagDialogShown: false });
}
}
styles() {
@ -360,11 +366,7 @@ class NoteScreenComponent extends BaseScreenComponent {
tags_onPress() {
if (!this.state.note || !this.state.note.id) return;
this.props.dispatch({
type: 'NAV_GO',
routeName: 'NoteTags',
noteId: this.state.note.id,
});
this.setState({ noteTagDialogShown: true });
}
setAlarm_onPress() {
@ -547,6 +549,8 @@ class NoteScreenComponent extends BaseScreenComponent {
</View>
);
const noteTagDialog = !this.state.noteTagDialogShown ? null : <NoteTagsDialog onCloseRequested={this.noteTagDialog_closeRequested}/>;
return (
<View style={this.rootStyle(this.props.theme).root}>
<ScreenHeader
@ -584,6 +588,7 @@ class NoteScreenComponent extends BaseScreenComponent {
/>
<DialogBox ref={dialogbox => { this.dialogbox = dialogbox }}/>
{ noteTagDialog }
</View>
);
}

View File

@ -17,7 +17,7 @@ class FsDriverRN extends FsDriverBase {
// same as rm -rf
async remove(path) {
throw new Error('Not implemented');
return await this.unlink(path);
}
writeBinaryFile(path, content) {

View File

@ -6533,6 +6533,11 @@
"strip-ansi": "3.0.1"
}
},
"string-natural-compare": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-2.0.2.tgz",
"integrity": "sha1-xc5OJ4q10SZa5vxVQ1rre3b8sAE="
},
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",

View File

@ -46,6 +46,7 @@
"react-redux": "4.4.8",
"redux": "3.6.0",
"stream": "0.0.2",
"string-natural-compare": "^2.0.2",
"timers": "^0.1.1",
"url-parse": "^1.2.0",
"uuid": "^3.0.1",

View File

@ -32,7 +32,6 @@ const { ConfigScreen } = require('lib/components/screens/config.js');
const { FolderScreen } = require('lib/components/screens/folder.js');
const { LogScreen } = require('lib/components/screens/log.js');
const { StatusScreen } = require('lib/components/screens/status.js');
const { NoteTagsScreen } = require('lib/components/screens/note-tags.js');
const { WelcomeScreen } = require('lib/components/screens/welcome.js');
const { SearchScreen } = require('lib/components/screens/search.js');
const { OneDriveLoginScreen } = require('lib/components/screens/onedrive-login.js');
@ -129,7 +128,7 @@ const generalMiddleware = store => next => async (action) => {
let navHistory = [];
function historyCanGoBackTo(route, nextRoute) {
if (route.routeName === 'Note' && nextRoute.routeName !== 'NoteTags') return false;
if (route.routeName === 'Note') return false;
if (route.routeName === 'Folder') return false;
return true;
@ -565,7 +564,6 @@ class AppComponent extends React.Component {
Status: { screen: StatusScreen },
Search: { screen: SearchScreen },
Config: { screen: ConfigScreen },
NoteTags: { screen: NoteTagsScreen },
};
return (