diff --git a/app/common/lib/bookmarkUtil.js b/app/common/lib/bookmarkUtil.js new file mode 100644 index 00000000000..01108a29b05 --- /dev/null +++ b/app/common/lib/bookmarkUtil.js @@ -0,0 +1,34 @@ +function bookmarkHangerHeading (detail, isFolder, shouldShowLocation) { + if (isFolder) { + return shouldShowLocation + ? 'bookmarkFolderEditing' + : 'bookmarkFolderAdding' + } + return shouldShowLocation + ? (!detail || !detail.has('location')) + ? 'bookmarkCreateNew' + : 'bookmarkEdit' + : 'bookmarkAdded' +} + +function displayBookmarkName (detail) { + const customTitle = detail.get('customTitle') + if (customTitle !== undefined && customTitle !== '') { + return customTitle || '' + } + return detail.get('title') || '' +} + +function isBookmarkNameValid (detail, isFolder) { + const title = detail.get('title') || detail.get('customTitle') + const location = detail.get('location') + return isFolder + ? (typeof title === 'string' && title.trim().length > 0) + : (typeof location === 'string' && location.trim().length > 0) +} + +module.exports = { + bookmarkHangerHeading, + displayBookmarkName, + isBookmarkNameValid +} diff --git a/app/renderer/components/bookmarks/addEditBookmark.js b/app/renderer/components/bookmarks/addEditBookmark.js deleted file mode 100644 index 575bee7c917..00000000000 --- a/app/renderer/components/bookmarks/addEditBookmark.js +++ /dev/null @@ -1,38 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const React = require('react') - -// Components -const ImmutableComponent = require('../immutableComponent') -const AddEditBookmarkHanger = require('./addEditBookmarkHanger') - -// Actions -const windowActions = require('../../../../js/actions/windowActions') - -class AddEditBookmark extends ImmutableComponent { - constructor () { - super() - this.onClose = this.onClose.bind(this) - } - onClose () { - windowActions.setBookmarkDetail() - } - componentDidMount () { - this.refs.bookmarkHanger.setDefaultFocus() - } - render () { - return - } -} - -module.exports = AddEditBookmark diff --git a/app/renderer/components/bookmarks/addEditBookmarkHanger.js b/app/renderer/components/bookmarks/addEditBookmarkHanger.js index da5a432ed02..812ef9bc573 100644 --- a/app/renderer/components/bookmarks/addEditBookmarkHanger.js +++ b/app/renderer/components/bookmarks/addEditBookmarkHanger.js @@ -5,7 +5,7 @@ const React = require('react') // Components -const ImmutableComponent = require('../immutableComponent') +const ReduxComponent = require('../reduxComponent') const Dialog = require('../common/dialog') const BrowserButton = require('../common/browserButton') @@ -22,7 +22,8 @@ const settings = require('../../../../js/constants/settings') const cx = require('../../../../js/lib/classSet') const siteUtil = require('../../../../js/state/siteUtil') const UrlUtil = require('../../../../js/lib/urlutil') -const getSetting = require('../../../../js/settings').getSetting +const {getSetting} = require('../../../../js/settings') +const {bookmarkHangerHeading, displayBookmarkName, isBookmarkNameValid} = require('../../../common/lib/bookmarkUtil') const {StyleSheet, css} = require('aphrodite/no-important') const globalStyles = require('../styles/global') @@ -38,7 +39,7 @@ const { commonFormStyles } = require('../common/commonForm') -class AddEditBookmarkHanger extends ImmutableComponent { +class AddEditBookmarkHanger extends React.Component { constructor () { super() this.onNameChange = this.onNameChange.bind(this) @@ -51,52 +52,12 @@ class AddEditBookmarkHanger extends ImmutableComponent { this.onViewBookmarks = this.onViewBookmarks.bind(this) this.onRemoveBookmark = this.onRemoveBookmark.bind(this) } - get bookmarkNameValid () { - const title = this.props.currentDetail.get('title') || this.props.currentDetail.get('customTitle') - const location = this.props.currentDetail.get('location') - return this.isFolder - ? (typeof title === 'string' && title.trim().length > 0) - : (typeof location === 'string' && location.trim().length > 0) - } - get displayBookmarkName () { - const customTitle = this.props.currentDetail.get('customTitle') - if (customTitle !== undefined && customTitle !== '') { - return customTitle || '' - } - return this.props.currentDetail.get('title') || '' - } - get heading () { - if (this.isFolder) { - return this.props.shouldShowLocation - ? 'bookmarkFolderEditing' - : 'bookmarkFolderAdding' - } - return this.props.shouldShowLocation - ? (!this.props.originalDetail || !this.props.originalDetail.has('location')) - ? 'bookmarkCreateNew' - : 'bookmarkEdit' - : 'bookmarkAdded' - } - get isFolder () { - // Fake a folderId property so that the bookmark is considered a bookmark folder. - // This is ImmutableJS so it doesn't actually set a value, it just returns a new one. - return siteUtil.isFolder(this.props.currentDetail.set('folderId', 0)) - } + setDefaultFocus () { this.bookmarkName.select() this.bookmarkName.focus() } - updateFolders (props) { - this.folders = siteUtil.getFolders(this.props.sites, props.currentDetail.get('folderId')) - } - componentWillMount () { - this.updateFolders(this.props) - } - componentWillUpdate (nextProps) { - if (this.props.sites !== nextProps.sites) { - this.updateFolders(nextProps) - } - } + componentDidMount () { // Automatically save if this is triggered by the url star if (!this.props.isModal && !this.props.shouldShowLocation) { @@ -104,6 +65,7 @@ class AddEditBookmarkHanger extends ImmutableComponent { } this.setDefaultFocus() } + onKeyDown (e) { switch (e.keyCode) { case KeyCodes.ENTER: @@ -114,12 +76,15 @@ class AddEditBookmarkHanger extends ImmutableComponent { break } } + onClose () { windowActions.setBookmarkDetail() } + onClick (e) { e.stopPropagation() } + onNameChange (e) { let currentDetail = this.props.currentDetail let name = e.target.value @@ -134,12 +99,13 @@ class AddEditBookmarkHanger extends ImmutableComponent { } else { // '' is reserved for the default customTitle value of synced bookmarks, // so replace '' with 0 if the user is deleting the customTitle. - // Note that non-string bookmark titles fail bookmarkNameValid so they + // Note that non-string bookmark titles fail isBookmarkNameValid so they // are not saved. currentDetail = currentDetail.set('customTitle', name || 0) } windowActions.setBookmarkDetail(currentDetail, this.props.originalDetail, this.props.destinationDetail, this.props.shouldShowLocation, !this.props.isModal) } + onLocationChange (e) { let location = e.target.value if (typeof location === 'string') { @@ -151,62 +117,95 @@ class AddEditBookmarkHanger extends ImmutableComponent { const currentDetail = this.props.currentDetail.set('location', location) windowActions.setBookmarkDetail(currentDetail, this.props.originalDetail, this.props.destinationDetail, this.props.shouldShowLocation, !this.props.isModal) } + onParentFolderChange (e) { const currentDetail = this.props.currentDetail.set('parentFolderId', Number(e.target.value)) windowActions.setBookmarkDetail(currentDetail, this.props.originalDetail, this.props.destinationDetail, undefined, !this.props.isModal) } + showToolbarOnFirstBookmark () { - const hasBookmarks = this.props.sites.find( - (site) => siteUtil.isBookmark(site) || siteUtil.isFolder(site) - ) - if (!hasBookmarks && !getSetting(settings.SHOW_BOOKMARKS_TOOLBAR)) { + if (!this.props.hasBookmarks && !getSetting(settings.SHOW_BOOKMARKS_TOOLBAR)) { appActions.changeSetting(settings.SHOW_BOOKMARKS_TOOLBAR, true) } } + onSave (closeDialog = true) { // First check if the title of the currentDetail is set - if (!this.bookmarkNameValid) { + if (!this.props.isBookmarkNameValid) { return false } this.showToolbarOnFirstBookmark() - const tag = this.isFolder ? siteTags.BOOKMARK_FOLDER : siteTags.BOOKMARK + const tag = this.props.isFolder ? siteTags.BOOKMARK_FOLDER : siteTags.BOOKMARK appActions.addSite(this.props.currentDetail, tag, this.props.originalDetail, this.props.destinationDetail) + if (closeDialog) { this.onClose() } } + onRemoveBookmark () { - const tag = this.isFolder ? siteTags.BOOKMARK_FOLDER : siteTags.BOOKMARK + const tag = this.props.isFolder ? siteTags.BOOKMARK_FOLDER : siteTags.BOOKMARK appActions.removeSite(this.props.currentDetail, tag) this.onClose() } + onViewBookmarks () { this.onClose() appActions.createTabRequested({url: 'about:bookmarks'}) } - render () { - const arrowUp = this.props.isModal - ? null - : { - className: cx({ - [css(styles.bookmarkHanger__arrowUp)]: true, - [css(styles.bookmarkHanger__withHomeButton)]: this.props.withHomeButton, - withStopButton: this.props.withStopButton, - withoutButtons: this.props.withoutButtons - }) - } + mergeProps (state, dispatchProps, ownProps) { + const currentWindow = state.get('currentWindow') + const bookmarkDetail = currentWindow.get('bookmarkDetail') + const currentDetail = bookmarkDetail.get('currentDetail') + const originalDetail = bookmarkDetail.get('originalDetail') + + const props = {} + // used in renderer + props.isModal = ownProps.isModal + props.withHomeButton = getSetting(settings.SHOW_HOME_BUTTON) + // Fake a folderId property so that the bookmark is considered a bookmark folder. + // This is ImmutableJS so it doesn't actually set a value, it just returns a new one. + props.isFolder = siteUtil.isFolder(currentDetail.set('folderId', 0)) + props.shouldShowLocation = bookmarkDetail.get('shouldShowLocation') + props.heading = bookmarkHangerHeading(originalDetail, props.isFolder, props.shouldShowLocation) + props.location = currentDetail.get('location') + props.parentFolderId = currentDetail.get('parentFolderId') + props.hasOriginalDetail = !!originalDetail + props.displayBookmarkName = displayBookmarkName(currentDetail) + props.isBookmarkNameValid = isBookmarkNameValid(currentDetail, props.isFolder) + props.folders = siteUtil.getFolders(state.get('sites'), currentDetail.get('folderId')) + + // used in functions + props.currentDetail = currentDetail // TODO (nejc) improve, primitives only + props.originalDetail = originalDetail // TODO (nejc) improve, primitives only + props.destinationDetail = bookmarkDetail.get('destinationDetail') // TODO (nejc) improve, primitives only + props.hasBookmarks = state.get('sites').find( + (site) => siteUtil.isBookmark(site) || siteUtil.isFolder(site) + ) + + return props + } + + render () { return -
+ { + !this.props.isModal + ?
+ : null + }
+ })} data-l10n-id={this.props.heading} />
@@ -226,13 +225,13 @@ class AddEditBookmarkHanger extends ImmutableComponent { spellCheck='false' onKeyDown={this.onKeyDown} onChange={this.onNameChange} - value={this.displayBookmarkName} + value={this.props.displayBookmarkName} ref={(bookmarkName) => { this.bookmarkName = bookmarkName }} />
{ - !this.isFolder && this.props.shouldShowLocation + !this.props.isFolder && this.props.shouldShowLocation ?
@@ -260,11 +259,11 @@ class AddEditBookmarkHanger extends ImmutableComponent { data-l10n-id='parentFolderField' htmlFor='bookmarkParentFolder' /> ) + this.props.folders.map((folder) => ) }
@@ -272,7 +271,7 @@ class AddEditBookmarkHanger extends ImmutableComponent { { - this.props.originalDetail + this.props.hasOriginalDetail ? @@ -368,4 +367,4 @@ const styles = StyleSheet.create({ } }) -module.exports = AddEditBookmarkHanger +module.exports = ReduxComponent.connect(AddEditBookmarkHanger) diff --git a/app/renderer/components/main/main.js b/app/renderer/components/main/main.js index 270795cdacf..5a186284601 100644 --- a/app/renderer/components/main/main.js +++ b/app/renderer/components/main/main.js @@ -31,7 +31,7 @@ const ImportBrowserDataPanel = require('./importBrowserDataPanel') const WidevinePanel = require('./widevinePanel') const AutofillAddressPanel = require('../autofill/autofillAddressPanel') const AutofillCreditCardPanel = require('../autofill/autofillCreditCardPanel') -const AddEditBookmark = require('../bookmarks/addEditBookmark') +const AddEditBookmarkHanger = require('../bookmarks/addEditBookmarkHanger') const LoginRequired = require('./loginRequired') const ReleaseNotes = require('./releaseNotes') const BookmarksToolbar = require('../bookmarks/bookmarksToolbar') @@ -784,17 +784,13 @@ class Main extends ImmutableComponent { } { this.props.windowState.get('bookmarkDetail') && !this.props.windowState.getIn(['bookmarkDetail', 'isBookmarkHanger']) - ? + ? : null } { noScriptIsVisible - ? : null } diff --git a/app/renderer/components/navigation/navigationBar.js b/app/renderer/components/navigation/navigationBar.js index 091d1e381c7..d15406c976b 100644 --- a/app/renderer/components/navigation/navigationBar.js +++ b/app/renderer/components/navigation/navigationBar.js @@ -25,7 +25,6 @@ const settings = require('../../../../js/constants/settings') // State const tabState = require('../../../common/state/tabState') const frameStateUtil = require('../../../../js/state/frameStateUtil') -const menuBarState = require('../../../common/state/menuBarState') // Store const windowStore = require('../../../../js/stores/windowStore') @@ -151,17 +150,16 @@ class NavigationBar extends React.Component { const props = {} props.navbar = navbar - props.sites = state.get('sites') + props.sites = state.get('sites') // TODO(nejc) remove, primitives only props.activeFrameKey = activeFrameKey props.location = location props.title = title props.partitionNumber = activeFrame.get('partitionNumber') || 0 props.isSecure = activeFrame.getIn(['security', 'isSecure']) props.loading = loading - props.bookmarkDetail = bookmarkDetail + props.showBookmarkHanger = bookmarkDetail && bookmarkDetail.get('isBookmarkHanger') props.mouseInTitlebar = mouseInTitlebar props.settings = state.get('settings') - props.menubarVisible = menuBarState.isMenuBarVisible(currentWindow) props.siteSettings = state.get('siteSettings') props.synopsis = state.getIn(['publisherInfo', 'synopsis']) || new Immutable.Map() props.activeTabShowingMessageBox = activeTabShowingMessageBox @@ -185,14 +183,8 @@ class NavigationBar extends React.Component { titleMode: this.props.titleMode })}> { - this.props.bookmarkDetail && this.props.bookmarkDetail.get('isBookmarkHanger') - ? + this.props.showBookmarkHanger + ? : null } { @@ -243,7 +235,6 @@ class NavigationBar extends React.Component { { isSourceAboutUrl(this.props.location) diff --git a/app/renderer/components/navigation/urlBar.js b/app/renderer/components/navigation/urlBar.js index da2370c1240..9430b94def7 100644 --- a/app/renderer/components/navigation/urlBar.js +++ b/app/renderer/components/navigation/urlBar.js @@ -26,6 +26,7 @@ const frameStateUtil = require('../../../../js/state/frameStateUtil') const siteSettings = require('../../../../js/state/siteSettings') const tabState = require('../../../common/state/tabState') const siteSettingsState = require('../../../common/state/siteSettingsState') +const menuBarState = require('../../../common/state/menuBarState') // Utils const urlParse = require('../../../common/urlParse') @@ -537,6 +538,7 @@ class UrlBar extends React.Component { props.autocompleteEnabled = urlbar.getIn(['suggestions', 'autocompleteEnabled']) props.searchURL = searchURL props.searchShortcut = searchShortcut + props.menubarVisible = menuBarState.isMenuBarVisible(currentWindow) return props }