diff --git a/app/ghostery-browser-hub/Views/OnboardingViews/Step3_ChooseDefaultSearchView/ChooseDefaultSearchConstants.js b/app/ghostery-browser-hub/Views/OnboardingViews/Step3_ChooseDefaultSearchView/ChooseDefaultSearchConstants.js index 874dfcb5e..e1cbe5caf 100644 --- a/app/ghostery-browser-hub/Views/OnboardingViews/Step3_ChooseDefaultSearchView/ChooseDefaultSearchConstants.js +++ b/app/ghostery-browser-hub/Views/OnboardingViews/Step3_ChooseDefaultSearchView/ChooseDefaultSearchConstants.js @@ -16,3 +16,4 @@ export const SEARCH_GHOSTERY = 'Ghostery'; export const SEARCH_BING = 'Bing'; export const SEARCH_YAHOO = 'Yahoo'; export const SEARCH_STARTPAGE = 'Startpage'; +export const SEARCH_OTHER = t('ghostery_dawn_onboarding_other'); diff --git a/app/ghostery-browser-hub/Views/OnboardingViews/Step3_ChooseDefaultSearchView/ChooseDefaultSearchView.jsx b/app/ghostery-browser-hub/Views/OnboardingViews/Step3_ChooseDefaultSearchView/ChooseDefaultSearchView.jsx index 70541c9c7..ac0ad7dab 100644 --- a/app/ghostery-browser-hub/Views/OnboardingViews/Step3_ChooseDefaultSearchView/ChooseDefaultSearchView.jsx +++ b/app/ghostery-browser-hub/Views/OnboardingViews/Step3_ChooseDefaultSearchView/ChooseDefaultSearchView.jsx @@ -20,7 +20,8 @@ import { SEARCH_GHOSTERY, SEARCH_YAHOO, SEARCH_STARTPAGE, - SEARCH_BING + SEARCH_BING, + SEARCH_OTHER } from './ChooseDefaultSearchConstants'; import { Modal } from '../../../../shared-components'; @@ -31,10 +32,20 @@ class ChooseDefaultSearchView extends Component { this.state = { chosenSearch: SEARCH_GHOSTERY, searchBeingConsidered: null, + otherSearchSelected: null, + otherListOpen: false, modalActive: false, }; } + componentDidMount() { + document.addEventListener('click', this.handleClickAway); + } + + componentWillUnmount() { + document.removeEventListener('click', this.handleClickAway); + } + updateSelection = () => this.setState(prevState => ( { chosenSearch: prevState.searchBeingConsidered, @@ -45,13 +56,33 @@ class ChooseDefaultSearchView extends Component { cancelSelection = () => this.setState({ modalActive: false, searchBeingConsidered: null }); + updateOtherSearchSelection = otherSelected => this.setState({ otherSearchSelected: otherSelected }); + + updateOtherListOpen = open => this.setState({ otherListOpen: open }); + triggerConfirmationModal = selection => this.setState({ modalActive: true, searchBeingConsidered: selection }); + handleClickAway = (e) => { + const { otherListOpen } = this.state; + + const closeDropdownOnClickAway = (open, key, ref) => { + if (open && !ref.contains(e.target)) { + this.setState({ [`${key}`]: false }); + } + }; + closeDropdownOnClickAway(otherListOpen, 'otherListOpen', this.otherListRef); + } + handleSubmit = () => { - const { chosenSearch } = this.state; + let { chosenSearch } = this.state; + const { otherSearchSelected } = this.state; const { actions, history } = this.props; const { setSetupStep, setDefaultSearch } = actions; + if (chosenSearch === SEARCH_OTHER && otherSearchSelected) { + chosenSearch = otherSearchSelected; + } + const payload = { type: 'setDefaultSearch', search: chosenSearch, @@ -87,7 +118,68 @@ class ChooseDefaultSearchView extends Component { renderStartpageOptionDescription = () => (
{t('ghostery_dawn_onboarding_ad_supported_private_search')}
- ) + ); + + renderOtherOptionDescription = () => { + const { otherSearchSelected, otherListOpen } = this.state; + const dropdownOpen = otherListOpen ? 'expanded' : ''; + return ( + +
+
{SEARCH_OTHER}
+
{t('ghostery_dawn_onboarding_choose_alternate_search')}
+
+
{ this.otherListRef = node; }} + className={`ChooseSearchView__optionDropdownContainer ${dropdownOpen}`} + onClick={() => this.updateOtherListOpen(!otherListOpen)} + > +
+
+ {otherSearchSelected || t('ghostery_dawn_onboarding_select_option')} + +
+ {otherListOpen && this.renderOtherOptionsList()} +
+
+
+ ); + } + + renderOtherOptionsList = () => { + const otherSearchOptions = [ + 'DuckDuck Go', + 'Ecosia', + 'Ekoru', + 'Gibiru', + 'Google', + 'OneSearch', + 'Privado', + 'Qwant', + 'Search Encrypt', + 'Tailcat', + ]; + + return ( + + {otherSearchOptions.map(otherSearchOption => ( +
{ + this.updateOtherSearchSelection(otherSearchOption); + this.triggerConfirmationModal(SEARCH_OTHER); + }} + > + {otherSearchOption} +
+ ))} +
+ ); + } renderOptionContainer = (chosenSearch, optionName) => { const selected = (chosenSearch === optionName); @@ -95,25 +187,38 @@ class ChooseDefaultSearchView extends Component { const logoFilename = `/app/images/hub/ChooseDefaultSearchView/search-engine-logo-${optionName.toLocaleLowerCase()}.svg`; return ( -
this.triggerConfirmationModal(optionName)} className={containerClasses}> +
{ + if (optionName !== SEARCH_OTHER) { + this.triggerConfirmationModal(optionName); + } + }} + className={containerClasses} + >
- {}} - altDesign - /> + {(optionName !== SEARCH_OTHER || (optionName === SEARCH_OTHER && selected)) && ( + {}} + altDesign + /> + ) + }
- + {(optionName !== SEARCH_OTHER) && ( + + )} {(optionName === SEARCH_GHOSTERY) && this.renderGhosteryOptionDescription()} {(optionName === SEARCH_STARTPAGE) && this.renderStartpageOptionDescription()} + {(optionName === SEARCH_OTHER) && this.renderOtherOptionDescription()}
); } renderConfirmationModal = () => { - const { searchBeingConsidered } = this.state; + const { searchBeingConsidered, otherSearchSelected } = this.state; const logoFilename = `/app/images/hub/ChooseDefaultSearchView/search-engine-logo-${searchBeingConsidered.toLocaleLowerCase()}.svg`; return ( @@ -121,12 +226,26 @@ class ChooseDefaultSearchView extends Component {
- + {searchBeingConsidered === SEARCH_OTHER ? ( +
+ {SEARCH_OTHER} +
+ ) : + + }
{searchBeingConsidered === SEARCH_STARTPAGE && t('ghostery_dawn_onboarding_startpage_warning')} {searchBeingConsidered === SEARCH_BING && t('ghostery_dawn_onboarding_bing_warning')} {searchBeingConsidered === SEARCH_YAHOO && t('ghostery_dawn_onboarding_yahoo_warning')} {searchBeingConsidered === SEARCH_GHOSTERY && t('ghostery_dawn_onboarding_glow_benefit')} + {(searchBeingConsidered === SEARCH_OTHER) && ( + + { + `${t('ghostery_dawn_onboarding_you_have_selected_an_alternate_serach_engine')} \n + ${otherSearchSelected}` + } + + )}