Skip to content
This repository has been archived by the owner on Dec 11, 2019. It is now read-only.

Converts urlBarSuggestions into redux #9051

Merged
merged 1 commit into from
Jun 7, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 48 additions & 1 deletion app/common/lib/suggestion.js
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,52 @@ const generateNewSearchXHRResults = debounce((state, windowId, tabId, input) =>
}
}, 10)

const filterSuggestionListByType = (suggestionList) => {
const bookmarkSuggestions = []
const historySuggestions = []
const aboutPagesSuggestions = []
const tabSuggestions = []
const searchSuggestions = []
const topSiteSuggestions = []

suggestionList.forEach(item => {
switch (item.get('type')) {
case suggestionTypes.BOOKMARK:
bookmarkSuggestions.push(item)
break

case suggestionTypes.HISTORY:
historySuggestions.push(item)
break

case suggestionTypes.ABOUT_PAGES:
aboutPagesSuggestions.push(item)
break

case suggestionTypes.TAB:
tabSuggestions.push(item)
break

case suggestionTypes.SEARCH:
searchSuggestions.push(item)
break

case suggestionTypes.TOP_SITE:
topSiteSuggestions.push(item)
break
}
})

return {
bookmarkSuggestions,
historySuggestions,
aboutPagesSuggestions,
tabSuggestions,
searchSuggestions,
topSiteSuggestions
}
}

module.exports = {
sortingPriority,
sortByAccessCountWithAgeDecay,
Expand All @@ -647,5 +693,6 @@ module.exports = {
getSearchSuggestions,
getAlexaSuggestions,
generateNewSuggestionsList,
generateNewSearchXHRResults
generateNewSearchXHRResults,
filterSuggestionListByType
}
6 changes: 2 additions & 4 deletions app/renderer/components/navigation/urlBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -612,10 +612,8 @@ class UrlBar extends React.Component {
{
this.shouldRenderUrlBarSuggestions
? <UrlBarSuggestions
selectedIndex={this.props.selectedIndex}
suggestionList={this.props.suggestionList}
hasSuggestionMatch={this.props.hasSuggestionMatch}
menubarVisible={this.props.menubarVisible} />
menubarVisible={this.props.menubarVisible}
/>
: null
}
</form>
Expand Down
39 changes: 36 additions & 3 deletions app/renderer/components/navigation/urlBarSuggestionItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,57 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */

const React = require('react')

// Components
const ImmutableComponent = require('../immutableComponent')

// Constants
const suggestionTypes = require('../../../../js/constants/suggestionTypes')

// Actions
const appActions = require('../../../../js/actions/appActions')
const windowActions = require('../../../../js/actions/windowActions')

// utils
const cx = require('../../../../js/lib/classSet')
const {isForSecondaryAction} = require('../../../../js/lib/eventUtil')
const {getCurrentWindowId} = require('../../currentWindow')

class UrlBarSuggestionItem extends ImmutableComponent {
constructor () {
super()
this.onMouseOver = this.onMouseOver.bind(this)
}

onMouseOver (e) {
let newIndex = parseInt(e.target.getAttribute('data-index'), 10)

if (newIndex < 0) {
newIndex = null
}

appActions.urlBarSelectedIndexChanged(getCurrentWindowId(), newIndex)
}

onClick (e) {
windowActions.activeSuggestionClicked(isForSecondaryAction(e), e.shiftKey)
}

componentDidMount () {
this.node.addEventListener('auxclick', this.props.onClick)
this.node.addEventListener('auxclick', this.onClick)
}

componentWillUpdate (nextProps) {
if (!this.props.selected && nextProps.selected) {
this.node.scrollIntoView()
}
}

render () {
return <li data-test-id='list-item'
data-index={this.props.currentIndex}
onMouseOver={this.props.onMouseOver.bind(this)}
onClick={this.props.onClick}
onMouseOver={this.onMouseOver}
onClick={this.onClick}
key={`${this.props.suggestion.get('location')}|${this.props.currentIndex + this.props.i}`}
ref={(node) => { this.node = node }}
className={cx({
Expand Down
135 changes: 63 additions & 72 deletions app/renderer/components/navigation/urlBarSuggestions.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,112 +3,103 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */

const React = require('react')
const ImmutableComponent = require('../immutableComponent')
const Immutable = require('immutable')

// Components
const ReduxComponent = require('../reduxComponent')
const UrlBarSuggestionItem = require('./urlBarSuggestionItem')
const windowActions = require('../../../../js/actions/windowActions')

// Actions
const appActions = require('../../../../js/actions/appActions')
const suggestionTypes = require('../../../../js/constants/suggestionTypes')

// Utils
const cx = require('../../../../js/lib/classSet')
const locale = require('../../../../js/l10n')
const {isForSecondaryAction} = require('../../../../js/lib/eventUtil')
const suggestions = require('../../../common/lib/suggestion')
const frameStateUtil = require('../../../../js/state/frameStateUtil')
const {getCurrentWindowId} = require('../../currentWindow')

class UrlBarSuggestions extends ImmutableComponent {
constructor () {
super()
this.onSuggestionClicked = this.onSuggestionClicked.bind(this)
this.onMouseOver = this.onMouseOver.bind(this)
}

get activeIndex () {
if (this.props.suggestionList === null) {
return -1
}
return this.props.selectedIndex
}

class UrlBarSuggestions extends React.Component {
blur () {
appActions.urlBarSuggestionsChanged(getCurrentWindowId(), null, null)
}

onSuggestionClicked (e) {
windowActions.activeSuggestionClicked(isForSecondaryAction(e), e.shiftKey)
}

render () {
const suggestions = this.props.suggestionList
const bookmarkSuggestions = suggestions.filter((s) => s.get('type') === suggestionTypes.BOOKMARK)
const historySuggestions = suggestions.filter((s) => s.get('type') === suggestionTypes.HISTORY)
const aboutPagesSuggestions = suggestions.filter((s) => s.get('type') === suggestionTypes.ABOUT_PAGES)
const tabSuggestions = suggestions.filter((s) => s.get('type') === suggestionTypes.TAB)
const searchSuggestions = suggestions.filter((s) => s.get('type') === suggestionTypes.SEARCH)
const topSiteSuggestions = suggestions.filter((s) => s.get('type') === suggestionTypes.TOP_SITE)

generateAllItems () {
let items = []
let index = 0

const addToItems = (suggestions, sectionKey, title, icon) => {
if (suggestions.size > 0) {
if (suggestions.length > 0) {
items.push(<li className='suggestionSection'>
{
icon
? <span className={cx({
suggestionSectionIcon: true,
[sectionKey]: true,
fa: true,
[icon]: true
})} />
: null
? <span className={cx({
suggestionSectionIcon: true,
[sectionKey]: true,
fa: true,
[icon]: true
})} />
: null
}
<span className='suggestionSectionTitle'>{title}</span>
</li>)
}

items = items.concat(suggestions.map((suggestion, i) => {
const currentIndex = index + i
const selected = this.activeIndex === currentIndex || (!this.activeIndex && currentIndex === 0 && this.props.hasSuggestionMatch)
const selected = this.props.activeIndex === currentIndex || (this.props.activeIndex == null && currentIndex === 0 && this.props.hasSuggestionMatch)
return <UrlBarSuggestionItem
suggestion={suggestion}
selected={selected}
currentIndex={currentIndex}
i={i}
onMouseOver={this.onMouseOver}
onClick={this.onSuggestionClicked} />
i={i} />
}))
index += suggestions.size
index += suggestions.length
}
addToItems(historySuggestions, 'historyTitle', locale.translation('historySuggestionTitle'), 'fa-clock-o')
addToItems(bookmarkSuggestions, 'bookmarksTitle', locale.translation('bookmarksSuggestionTitle'), 'fa-star-o')
addToItems(aboutPagesSuggestions, 'aboutPagesTitle', locale.translation('aboutPagesSuggestionTitle'), null)
addToItems(tabSuggestions, 'tabsTitle', locale.translation('tabsSuggestionTitle'), 'fa-external-link')
addToItems(searchSuggestions, 'searchTitle', locale.translation('searchSuggestionTitle'), 'fa-search')
addToItems(topSiteSuggestions, 'topSiteTitle', locale.translation('topSiteSuggestionTitle'), 'fa-link')
const documentHeight = Number.parseInt(window.getComputedStyle(document.querySelector(':root')).getPropertyValue('--navbar-height'), 10)
const menuHeight = this.props.menubarVisible ? 30 : 0
return <ul className='urlBarSuggestions' style={{
maxHeight: document.documentElement.offsetHeight - documentHeight - 2 - menuHeight
}}>
{items}
</ul>
}

onMouseOver (e) {
this.updateSuggestions(parseInt(e.target.dataset.index, 10))
const list = suggestions.filterSuggestionListByType(this.props.suggestionList)

addToItems(list.historySuggestions, 'historyTitle', locale.translation('historySuggestionTitle'), 'fa-clock-o')
addToItems(list.bookmarkSuggestions, 'bookmarksTitle', locale.translation('bookmarksSuggestionTitle'), 'fa-star-o')
addToItems(list.aboutPagesSuggestions, 'aboutPagesTitle', locale.translation('aboutPagesSuggestionTitle'), null)
addToItems(list.tabSuggestions, 'tabsTitle', locale.translation('tabsSuggestionTitle'), 'fa-external-link')
addToItems(list.searchSuggestions, 'searchTitle', locale.translation('searchSuggestionTitle'), 'fa-search')
addToItems(list.topSiteSuggestions, 'topSiteTitle', locale.translation('topSiteSuggestionTitle'), 'fa-link')

return items
}

componentDidMount () {
mergeProps (state, dispatchProps, ownProps) {
const currentWindow = state.get('currentWindow')
const activeFrame = frameStateUtil.getActiveFrame(currentWindow) || Immutable.Map()
const urlBar = activeFrame.getIn(['navbar', 'urlbar'], Immutable.Map())
const documentHeight = Number.parseInt(
window.getComputedStyle(document.querySelector(':root')).getPropertyValue('--navbar-height'), 10
)
const menuHeight = ownProps.menubarVisible ? 30 : 0

const props = {}
// used in renderer
props.maxHeight = document.documentElement.offsetHeight - documentHeight - 2 - menuHeight

// used in functions
props.menubarVisible = ownProps.menubarVisible
props.suggestionList = urlBar.getIn(['suggestions', 'suggestionList']) // TODO (nejc) improve, use primitives
props.hasSuggestionMatch = urlBar.getIn(['suggestions', 'hasSuggestionMatch'])
props.activeIndex = props.suggestionList === null
? -1
: urlBar.getIn(['suggestions', 'selectedIndex'])

return props
}

updateSuggestions (newIndex) {
const suggestions = this.suggestionList || this.props.suggestionList
if (!suggestions) {
return
}
// Update the urlbar preview content
if (newIndex > suggestions.size) {
newIndex = null
}
appActions.urlBarSuggestionsChanged(getCurrentWindowId(), suggestions, newIndex)
render () {
return <ul className='urlBarSuggestions' style={{
maxHeight: this.props.maxHeight
}}>
{this.generateAllItems()}
</ul>
}
}

module.exports = UrlBarSuggestions
module.exports = ReduxComponent.connect(UrlBarSuggestions)
7 changes: 7 additions & 0 deletions app/renderer/reducers/urlBarReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,13 @@ const urlBarReducer = (state, action) => {
case appConstants.APP_URL_BAR_TEXT_CHANGED:
state = setNavBarUserInput(state, action.input)
break
case appConstants.APP_URL_BAR_SELECTED_INDEX_CHANGED:
{
const suggestionList = state.getIn(activeFrameStatePath(state).concat(['navbar', 'urlbar', 'suggestions', 'suggestionList']))
state = state.setIn(activeFrameStatePath(state).concat(['navbar', 'urlbar', 'suggestions', 'selectedIndex']), action.selectedIndex)
state = updateUrlSuffix(state, suggestionList)
break
}
case appConstants.APP_URL_BAR_SUGGESTIONS_CHANGED:
if (action.selectedIndex !== undefined) {
state = state.setIn(activeFrameStatePath(state).concat(['navbar', 'urlbar', 'suggestions', 'selectedIndex']), action.selectedIndex)
Expand Down
12 changes: 12 additions & 0 deletions docs/appActions.md
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,18 @@ Indicates URL bar suggestions and selected index.



### urlBarSelectedIndexChanged(windowId, selectedIndex)

Indicates URL bar selected index

**Parameters**

**windowId**: `number`, the window ID

**selectedIndex**: `number`, The index for the selected item (users can select items with down arrow on their keyboard)



### defaultSearchEngineLoaded(searchDetail)

Dispatches a message to set the search engine details.
Expand Down
17 changes: 17 additions & 0 deletions js/actions/appActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -1393,6 +1393,23 @@ const appActions = {
})
},

/**
* Indicates URL bar selected index
*
* @param {number} windowId - the window ID
* @param {number} selectedIndex - The index for the selected item (users can select items with down arrow on their keyboard)
*/
urlBarSelectedIndexChanged: function (windowId, selectedIndex) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this change to pass the index instead of calculating the selections in the component

dispatch({
actionType: appConstants.APP_URL_BAR_SELECTED_INDEX_CHANGED,
selectedIndex,
windowId,
queryInfo: {
windowId
}
})
},

/**
* Dispatches a message to set the search engine details.
* @param {Object} searchDetail - the search details
Expand Down
3 changes: 2 additions & 1 deletion js/constants/appConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,8 @@ const appConstants = {
APP_REMOVE_PASSWORD: _, /** @param {Object} passwordDetail */
APP_REMOVE_PASSWORD_SITE: _, /** @param {Object} passwordDetail */
APP_CLEAR_PASSWORDS: _,
APP_UPDATE_LOG_OPENED: _
APP_UPDATE_LOG_OPENED: _,
APP_URL_BAR_SELECTED_INDEX_CHANGED: _
}

module.exports = mapValuesByKeys(appConstants)
Loading