Skip to content

Commit

Permalink
Search Settings Panel: Search Suggestions (Part 1)
Browse files Browse the repository at this point in the history
  • Loading branch information
darkdh committed Jul 27, 2016
1 parent 4640446 commit 99019b3
Show file tree
Hide file tree
Showing 9 changed files with 173 additions and 21 deletions.
2 changes: 1 addition & 1 deletion docs/state.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ AppStore
'general.downloads.default-save-path': string, // default path for saving files
'general.autohide-menu': boolean, // true if the Windows menu should be autohidden
'general.disable-title-mode': boolean, // true if title mode should always be disabled
'search.default-search-engine': string, // path to the open search XML
'search.default-search-engine': string, // name of search engine, from js/data/searchProviders.js
'search.offer-search-suggestions': boolean, // true if suggestions should be offered from the default search engine when available.
'tabs.switch-to-new-tabs': boolean, // true if newly opened tabs should be focused immediately
'tabs.paint-tabs': boolean, // true if the page theme color and favicon color should be used for tabs
Expand Down
74 changes: 65 additions & 9 deletions js/about/preferences.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ const messages = require('../constants/messages')
const settings = require('../constants/settings')
const aboutActions = require('./aboutActions')
const getSetting = require('../settings').getSetting
const SortableTable = require('../components/sortableTable')
const searchProviders = require('../data/searchProviders')

const adblock = appConfig.resourceNames.ADBLOCK
const cookieblock = appConfig.resourceNames.COOKIEBLOCK
Expand Down Expand Up @@ -161,19 +163,73 @@ class GeneralTab extends ImmutableComponent {
}
}

class SearchSelectEntry extends ImmutableComponent {
shouldComponentUpdate (nextProps, nextState) {
return this.props.settings.get('search.default-search-engine') !== nextProps.settings.get('search.default-search-engine')
}
render () {
return <div>
{this.props.settings.get('search.default-search-engine') === this.props.name ? 'x' : ''}
</div>
}
}

class SearchEntry extends ImmutableComponent {
render () {
return <div>
<span style={this.props.iconStyle}>
</span>
<span style={this.props.textStyle}>{this.props.name}</span>
</div>
}
}

class SearchShortcutEntry extends ImmutableComponent {
render () {
return <div style={this.props.textStyle}>
{this.props.shortcut}
</div>
}
}

class SearchTab extends ImmutableComponent {
get searchProviders () {
let entries = searchProviders.providers
let array = []
const iconSize = 16
entries.forEach((entry) => {
let iconStyle = {
backgroundImage: `url(${entry.image})`,
minWidth: iconSize,
width: iconSize,
backgroundSize: iconSize,
height: iconSize,
display: 'inline-block',
verticalAlign: 'middle'
}
let textStyle = {
paddingLeft: '5px',
verticalAlign: 'middle'
}
array.push([<SearchSelectEntry name={entry.name} settings={this.props.settings} />,
<SearchEntry name={entry.name} iconStyle={iconStyle} textStyle={textStyle}
onChangeSetting={this.props.onChangeSetting} />,
<SearchShortcutEntry shortcut={entry.shortcut} textStyle={textStyle} />])
})
return array
}

hoverCallback (rows) {
this.props.onChangeSetting(settings.DEFAULT_SEARCH_ENGINE, rows[1].props.children.props.name)
}

render () {
return <div>
<div className='sectionTitle' data-l10n-id='searchSettings' />
<SettingsList>
<SettingItem dataL10nId='defaultSearchEngine'>
<select value={getSetting(settings.DEFAULT_SEARCH_ENGINE, this.props.settings)}
onChange={changeSetting.bind(null, this.props.onChangeSetting, settings.DEFAULT_SEARCH_ENGINE)}>
<option value='content/search/google.xml'>Google</option>
<option value='content/search/duckduckgo.xml'>DuckDuckGo</option>
</select>
</SettingItem>
</SettingsList>
<SettingItem dataL10nId='defaultSearchEngine'>
<SortableTable headings={['Default', 'Search Engines', 'Engine Go Key (type first)']} rows={this.searchProviders}
isHover hoverCallback={this.hoverCallback.bind(this)} />
</SettingItem>
<div className='sectionTitle' data-l10n-id='locationBarSettings' />
<SettingsList>
<SettingCheckbox dataL10nId='showHistoryMatches' prefKey={settings.HISTORY_SUGGESTIONS} settings={this.props.settings} onChangeSetting={this.props.onChangeSetting} />
Expand Down
24 changes: 17 additions & 7 deletions js/components/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ const remote = electron.remote
// Actions
const windowActions = require('../actions/windowActions')
const webviewActions = require('../actions/webviewActions')
const loadOpenSearch = require('../lib/openSearch').loadOpenSearch
const contextMenus = require('../contextMenus')
const getSetting = require('../settings').getSetting
const getOrigin = require('../state/siteUtil').getOrigin
Expand Down Expand Up @@ -49,6 +48,8 @@ const keyCodes = require('../constants/keyCodes')
// State handling
const FrameStateUtil = require('../state/frameStateUtil')

const searchProviders = require('../data/searchProviders')

// Util
const cx = require('../lib/classSet.js')
const eventUtil = require('../lib/eventUtil')
Expand Down Expand Up @@ -180,16 +181,25 @@ class Main extends ImmutableComponent {
ipc.on(messages.LEAVE_FULL_SCREEN, this.exitFullScreen.bind(this))
}

loadOpenSearch () {
loadSearchProviders () {
let entries = searchProviders.providers
let engine = getSetting(settings.DEFAULT_SEARCH_ENGINE)
if (this.lastLoadedOpenSearch === undefined || engine !== this.lastLoadedOpenSearch) {
loadOpenSearch(engine).then((searchDetail) => windowActions.setSearchDetail(searchDetail))
this.lastLoadedOpenSearch = engine
if (this.lastLoadedSearchProviders === undefined || engine !== this.lastLoadedSearchProviders) {
entries.forEach((entry) => {
if (entry.name === engine) {
windowActions.setSearchDetail(Immutable.fromJS({
searchURL: entry.search,
autocompleteURL: entry.autocomplete
}))
this.lastLoadedSearchProviders = engine
return false
}
})
}
}

componentDidUpdate (prevProps) {
this.loadOpenSearch()
this.loadSearchProviders()
const activeFrame = FrameStateUtil.getActiveFrame(this.props.windowState)
const activeFramePrev = FrameStateUtil.getActiveFrame(prevProps.windowState)
const activeFrameTitle = activeFrame && (activeFrame.get('title') || activeFrame.get('location')) || ''
Expand Down Expand Up @@ -346,7 +356,7 @@ class Main extends ImmutableComponent {
windowActions.setContextMenuDetail()
})

this.loadOpenSearch()
this.loadSearchProviders()

window.addEventListener('mousemove', (e) => {
self.checkForTitleMode(e.pageY)
Expand Down
8 changes: 6 additions & 2 deletions js/components/sortableTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class SortableTable extends ImmutableComponent {
componentDidMount (event) {
return tableSort(document.getElementsByClassName('sortableTable')[0])
}

render () {
var headings = []
var rows = []
Expand All @@ -26,7 +27,8 @@ class SortableTable extends ImmutableComponent {
headings[j] = headings[j] || <th className='sort-header' data-l10n-id={this.props.headings[j]} />
rows[i][j] = <td data-sort={this.props.rows[i][j]}>{this.props.rows[i][j] === true ? '✕' : this.props.rows[i][j]}</td>
}
rows[i] = <tr>{rows[i]}</tr>
rows[i] = <tr className={this.props.isHover ? 'rowHover' : ''}
onClick={this.props.hoverCallback.bind(this, rows[i])}>{rows[i]}</tr>
}
return <table className='sortableTable sort'>
<thead>
Expand All @@ -43,7 +45,9 @@ class SortableTable extends ImmutableComponent {

SortableTable.defaultProps = {
headings: React.PropTypes.array.isRequired,
rows: React.PropTypes.array.isRequired
rows: React.PropTypes.array.isRequired,
isHover: React.PropTypes.bool,
hoverCallback: React.PropTypes.func
}

module.exports = SortableTable
13 changes: 13 additions & 0 deletions js/components/urlBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const settings = require('../constants/settings')
const contextMenus = require('../contextMenus')
const dndData = require('../dndData')
const pdfjsExtensionId = require('../constants/config').PDFJSExtensionId
const searchProviders = require('../data/searchProviders')

const { isUrl, isIntermediateAboutPage } = require('../lib/appUrlUtil')

Expand Down Expand Up @@ -122,7 +123,19 @@ class UrlBar extends ImmutableComponent {
// load the selected suggestion
this.urlBarSuggestions.clickSelected(e)
} else {
let entries = searchProviders.providers
let searchUrl = this.searchDetail.get('searchURL').replace('{searchTerms}', encodeURIComponent(location))
if (!isLocationUrl) {
entries.forEach((entry) => {
const searchRE = new RegExp('^' + entry.shortcut + ' .*', 'g')
if (searchRE.test(location)) {
const replaceRE = new RegExp('^' + entry.shortcut + ' ', 'g')
location = location.replace(replaceRE, '')
searchUrl = entry.search.replace('{searchTerms}', encodeURIComponent(location))
return false
}
})
}
location = isLocationUrl ? location : searchUrl
// do search.
if (e.altKey) {
Expand Down
2 changes: 1 addition & 1 deletion js/constants/appConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ module.exports = {
'general.show-home-button': false,
'general.useragent.value': null, // Set at runtime
'general.autohide-menu': true,
'search.default-search-engine': 'content/search/google.xml',
'search.default-search-engine': 'Google',
'search.offer-search-suggestions': false, // false by default for privacy reasons
'tabs.switch-to-new-tabs': false,
'tabs.paint-tabs': true,
Expand Down
2 changes: 1 addition & 1 deletion js/contextMenus.js
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,7 @@ function mainTemplateInit (nodeProps, frame) {
},
copyAddressMenuItem('copyImageAddress', nodeProps.srcURL)
)
if (getSetting(settings.DEFAULT_SEARCH_ENGINE) === 'content/search/google.xml' &&
if (getSetting(settings.DEFAULT_SEARCH_ENGINE) === 'Google' &&
nodeProps.srcURL && urlParse(nodeProps.srcURL).protocol !== 'data:') {
template.push(
{
Expand Down
Loading

0 comments on commit 99019b3

Please sign in to comment.