From ca3946689a68fbfac577b1fc662874c0a66d782c Mon Sep 17 00:00:00 2001 From: Laurent Cozic Date: Sat, 17 Mar 2018 23:00:01 +0000 Subject: [PATCH] Mobile: Made tag UI a dialog --- .../lib/components/ModalDialog.js | 13 ++-- .../{note-tags.js => NoteTagsDialog.js} | 63 +++++++++---------- .../lib/components/screens/note.js | 17 +++-- ReactNativeClient/lib/fs-driver-rn.js | 2 +- ReactNativeClient/package-lock.json | 5 ++ ReactNativeClient/package.json | 1 + ReactNativeClient/root.js | 4 +- 7 files changed, 55 insertions(+), 50 deletions(-) rename ReactNativeClient/lib/components/screens/{note-tags.js => NoteTagsDialog.js} (78%) diff --git a/ReactNativeClient/lib/components/ModalDialog.js b/ReactNativeClient/lib/components/ModalDialog.js index 2ecc2c3e3..92ea99902 100644 --- a/ReactNativeClient/lib/components/ModalDialog.js +++ b/ReactNativeClient/lib/components/ModalDialog.js @@ -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 ( { }} > - - Title + + {this.props.title} {ContentComponent} - + - + diff --git a/ReactNativeClient/lib/components/screens/note-tags.js b/ReactNativeClient/lib/components/screens/NoteTagsDialog.js similarity index 78% rename from ReactNativeClient/lib/components/screens/note-tags.js rename to ReactNativeClient/lib/components/screens/NoteTagsDialog.js index c34caad4e..c768e5724 100644 --- a/ReactNativeClient/lib/components/screens/note-tags.js +++ b/ReactNativeClient/lib/components/screens/NoteTagsDialog.js @@ -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 ( - - + const dialogContent = ( + + + {_('New tags:')} { this.setState({ newTags: value }) }} style={{flex:1}}/> + - - {_('Or type tags:')} { this.setState({ newTags: value }) }} style={{flex:1}}/> - - - - - - - - - ); + + return } } -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 }; \ No newline at end of file +module.exports = NoteTagsDialog; \ No newline at end of file diff --git a/ReactNativeClient/lib/components/screens/note.js b/ReactNativeClient/lib/components/screens/note.js index 9b9a53b42..fd9b9116b 100644 --- a/ReactNativeClient/lib/components/screens/note.js +++ b/ReactNativeClient/lib/components/screens/note.js @@ -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 { ); + const noteTagDialog = !this.state.noteTagDialogShown ? null : ; + return ( { this.dialogbox = dialogbox }}/> + { noteTagDialog } ); } diff --git a/ReactNativeClient/lib/fs-driver-rn.js b/ReactNativeClient/lib/fs-driver-rn.js index 53b486fdc..4cbb2a2ca 100644 --- a/ReactNativeClient/lib/fs-driver-rn.js +++ b/ReactNativeClient/lib/fs-driver-rn.js @@ -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) { diff --git a/ReactNativeClient/package-lock.json b/ReactNativeClient/package-lock.json index 34659157b..0f1a55947 100644 --- a/ReactNativeClient/package-lock.json +++ b/ReactNativeClient/package-lock.json @@ -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", diff --git a/ReactNativeClient/package.json b/ReactNativeClient/package.json index b7357bd34..1c8ee0b96 100644 --- a/ReactNativeClient/package.json +++ b/ReactNativeClient/package.json @@ -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", diff --git a/ReactNativeClient/root.js b/ReactNativeClient/root.js index 79475b358..89abe22ad 100644 --- a/ReactNativeClient/root.js +++ b/ReactNativeClient/root.js @@ -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 (