Skip to content
This repository has been archived by the owner. It is now read-only.

[IP-618] [Search] Onboarding for existing users #397

Merged
merged 7 commits into from Jul 22, 2019
Merged
Changes from all commits
Commits
File filter
Filter file types
Jump to
Jump to file
Failed to load files.

Always

Just for now

@@ -890,7 +890,7 @@ class BrowserViewController: UIViewController {
}
}

fileprivate func showSearchController() {
func showSearchController() {
/* Cliqz: Replace Search Controller
if searchController != nil {
return
@@ -915,15 +915,20 @@ class BrowserViewController: UIViewController {
searchController!.didMove(toParentViewController: self)
*/
if (searchController != nil && SettingsPrefs.shared.getCliqzSearchPref() == false) ||
(cliqzSearchController != nil && SettingsPrefs.shared.getCliqzSearchPref() == true){
let shouldShowCliqzSearch = SettingsPrefs.shared.getCliqzSearchPref() || self.shouldShowSearchOnboarding()
if (searchController != nil && !shouldShowCliqzSearch) ||
(cliqzSearchController != nil && shouldShowCliqzSearch){
return
}

searchLoader = SearchLoader(profile: profile, urlBar: urlBar)
searchLoader!.addListener(HistoryListener.shared)

if SettingsPrefs.shared.getCliqzSearchPref() {
if shouldShowCliqzSearch {
if self.shouldShowSearchOnboarding() {
LegacyTelemetryHelper.logOnboarding(action: "show", topic: "search")
}

homePanelController?.view?.isHidden = true

cliqzSearchController = CliqzSearchViewController(profile: self.profile)
@@ -1000,7 +1005,11 @@ class BrowserViewController: UIViewController {
}
}

fileprivate func hideSearchController() {
private func shouldShowSearchOnboarding() -> Bool {
return UserPreferences.instance.showSearchOnboarding
}

func hideSearchController() {
/*Cliqz: Hide cliqzSearch or firefoxSearch
if let searchController = searchController {
searchController.willMove(toParentViewController: nil)
@@ -1681,15 +1690,19 @@ extension BrowserViewController: URLBarDelegate {
searchController?.searchQuery = text
searchLoader?.query = text
*/
if !text.isEmpty {
cliqzSearchController?.searchQuery = text
searchController?.searchQuery = text
searchLoader?.query = text
}
self.updateSearchQuery(query: text)
// End Cliqz
}
}

func updateSearchQuery(query: String) {
if !query.isEmpty {
cliqzSearchController?.searchQuery = query
searchController?.searchQuery = query
searchLoader?.query = query
}
}

func urlBar(_ urlBar: URLBarView, didSubmitText text: String) {
guard let currentTab = tabManager.selectedTab else { return }
if let fixupURL = URIFixup.getURL(text) {
@@ -2348,7 +2361,13 @@ extension BrowserViewController: IntroViewControllerDelegate {
#endif
// End Cliqz
if force || profile.prefs.intForKey(PrefsKeys.IntroSeen) == nil {
/* Cliqz: determining the first launch. */
let isFirstLaunch = profile.prefs.intForKey(PrefsKeys.IntroSeen) == nil
if isFirstLaunch {
UserPreferences.instance.showSearchOnboarding = false
}

if force || isFirstLaunch {
#if PAID
let introViewController = LumenIntroViewController()
#else
@@ -23,4 +23,21 @@ extension BrowserViewController: SearchViewDelegate {
func dismissKeyboard() {
urlBar.hideKeyboard()
}

func closeSearchOnboarding() {
let query = cliqzSearchController?.searchQuery
hideSearchController()
showSearchController()
if let query = query {
updateSearchQuery(query: query)
}
}

func makeLumenDefaultSearch() {
let lumenSearchEngine = self.profile.searchEngines.orderedEngines.filter { $0.shortName == LumenSearchEngineDisplayName }.first
if let engine = lumenSearchEngine {
self.profile.searchEngines.defaultEngine = engine
self.urlBar.updatePlaceHolders()
}
}
}
@@ -52,6 +52,7 @@ extension Notification.Name {

let IsDeveloperModeOnKey = "IsDeveloperModeOnKey"
let ShowPromoCodeKey = "ShowPromoCodeKey"
let ShowSearchOnboarding = "showSearchOnboarding"
let ShowNonPrivateSearchWarningKey = "ShowNonPrivateSearchWarningKey"

/// If `true`, send a `developer` flag in the telemetry data.
@@ -86,6 +87,23 @@ extension Notification.Name {
}
}

var showSearchOnboarding: Bool {
get {
#if PAID
if let val = userDefaults().value(forKey: ShowSearchOnboarding) as? Bool {
return val
}

return true
#else
return false
#endif
}
set {
userDefaults().set(newValue, forKey: ShowSearchOnboarding)
}
}

var shouldShowNonPrivateSearchWarningMessage: Bool {
get {
if let val = userDefaults().value(forKey: ShowNonPrivateSearchWarningKey) as? Bool {
@@ -30,8 +30,8 @@ open class Engine {
#else
let jsCodeLocation = Bundle.main.url(forResource: "jsengine.bundle", withExtension: "js")
#endif
rootView = RCTRootView( bundleURL: jsCodeLocation, moduleName: "ExtensionApp", initialProperties: ["showSearchOnboarding": true], launchOptions: nil )

rootView = RCTRootView( bundleURL: jsCodeLocation, moduleName: "ExtensionApp", initialProperties: nil, launchOptions: nil )
bridge = rootView.bridge
//ConnectManager.sharedInstance.refresh()
}
@@ -93,6 +93,14 @@ class JSBridge : RCTEventEmitter {
}
}
}

@objc(getConfig:reject:)
func getConfig(resolve: @escaping RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {
if SettingsPrefs.shared.isLumenDefaultSearchEngine {
UserPreferences.instance.showSearchOnboarding = false
}
resolve(["onboarding": UserPreferences.instance.showSearchOnboarding])
}

/// Call an action over the JSBridge and execute a callback with the result. Invokation of the callback is
/// not guaranteed, for example if the function is never registered. Unlike the synchronous version, this
@@ -13,5 +13,6 @@ @interface RCT_EXTERN_MODULE(JSBridge, NSObject)
RCT_EXTERN_METHOD(replyToAction:(nonnull NSInteger *)actionId result:(NSDictionary *)result)
RCT_EXTERN_METHOD(registerAction:)
RCT_EXTERN_METHOD(pushEvent:(nonnull NSString *)eventId data:(NSArray *)data)
RCT_EXTERN_METHOD(getConfig:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)

@end
@@ -19,9 +19,13 @@ class Onboarding: RCTEventEmitter {
func tryLumenSearch(accepted: Bool) {
debugPrint("tryLumenSearch -- \(accepted)")
if accepted {
// TODO: PK this is try now case. Change Lumen to default search engine. UI will be handled by extenstion
DispatchQueue.main.async {
NotificationCenter.default.post(name: MakeLumenDefaultSearchNotification, object: nil, userInfo: nil)
}
} else {
// TODO: PK close cliqz search and open queary with default search engine
DispatchQueue.main.async {
NotificationCenter.default.post(name: CloseSearchOnboardingNotification, object: nil, userInfo: nil)
}
}
}
}
@@ -28,6 +28,8 @@ protocol SearchViewDelegate: class {
func didSelectURL(_ url: URL, searchQuery: String?)
func autoCompeleteQuery(_ autoCompleteText: String)
func dismissKeyboard()
func closeSearchOnboarding()
func makeLumenDefaultSearch()
}

let OpenURLIsSearchEngineKey = "OpenURLIsSearchEngineKey"
@@ -37,6 +39,8 @@ let HideKeyboardSearchNotification = NSNotification.Name(rawValue: "mobile-searc
let CallSearchNotification = NSNotification.Name(rawValue: "mobile-search:call")
let MapSearchNotification = NSNotification.Name(rawValue: "mobile-search:map")
let ShareLocationSearchNotification = NSNotification.Name(rawValue: "mobile-search:share-location")
let MakeLumenDefaultSearchNotification = NSNotification.Name(rawValue: "mobile-search:makeLumenDefaultSearchEngine")
let CloseSearchOnboardingNotification = NSNotification.Name(rawValue: "mobile-search:closeSearchOnboarding")

let SearchEngineChangedNotification = Notification.Name(rawValue: "SearchEngineChangedNotification")

@@ -120,6 +124,8 @@ class CliqzSearchViewController : UIViewController, KeyboardHelperDelegate, UIAl
NotificationCenter.default.addObserver(self, selector: #selector(openMap), name: MapSearchNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(shareLocation), name: ShareLocationSearchNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(autocomplete(_:)), name: AutoCompleteNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(closeSearchOnboarding(_:)), name: CloseSearchOnboardingNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(makeLumenDefaultSearch(_:)), name: MakeLumenDefaultSearchNotification, object: nil)

//TODO: Send notification when search engine is changed
NotificationCenter.default.addObserver(self, selector: #selector(searchEngineChanged), name: SearchEngineChangedNotification, object: nil)
@@ -286,6 +292,20 @@ extension CliqzSearchViewController {
LocationManager.sharedInstance.shareLocation()
}

@objc func closeSearchOnboarding(_ notification: Notification) {
LegacyTelemetryHelper.logOnboarding(action: "click", target: "cancel", topic: "search")
UserPreferences.instance.showSearchOnboarding = false
delegate?.closeSearchOnboarding()
}

@objc func makeLumenDefaultSearch(_ notification: Notification) {
LegacyTelemetryHelper.logOnboarding(action: "click", target: "try", topic: "search")
UserPreferences.instance.showSearchOnboarding = false
if !SettingsPrefs.shared.isLumenDefaultSearchEngine {
delegate?.makeLumenDefaultSearch()
}
}

fileprivate func showLumenSearchLeavingWarning(url: URL) {
LegacyTelemetryHelper.logLumenSearchWarning(action: "show")
UserPreferences.instance.shouldShowNonPrivateSearchWarningMessage = false
@@ -10,9 +10,11 @@ import UIKit

class LegacyTelemetryHelper: NSObject {

class func logOnboarding(action: String, page: Int, target: String? = nil) {
var signal: [String : Any] = ["type": "onboarding", "action": action, "page": page, "version": 1]
class func logOnboarding(action: String, page: Int? = nil, target: String? = nil, topic: String? = nil) {
var signal: [String : Any] = ["type": "onboarding", "action": action, "version": 1]
if let target = target { signal["target"] = target }
if let page = page { signal["page"] = page }
if let topic = topic { signal["topic"] = topic }

sendSignal(signal)
}
@@ -102,9 +102,9 @@ export default class Onboarding extends React.Component {
</Animated.View>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback disabled={this.state.isClicked} onPress={() => this.onPress(false)}>
<>
<View>
<Animated.Text style={{ letterSpacing: -0.2, marginTop: 20, fontSize: 14, lineHeight: 17, fontWeight: '700', color: this.interpolateColor('#3647D0', '#3647D0')}}>{noThanksText}</Animated.Text>
</>
</View>
</TouchableWithoutFeedback>
</View>
);
@@ -59,19 +59,29 @@ class MobileCards extends React.Component {
constructor(props) {
super(props);
this.state = {
onboarding: props.showSearchOnboarding,
onboarding: false,
results: {
results: [],
meta: {}
},
isReady: false,
hasQuery: false,
theme: 'lumen-light'
}

this.cliqz = new Cliqz();
this.isDeveloper = prefs.get('developer', false);
this.appStart = appStart || Promise.resolve();
this.init();
}

async init() {
await this.appStart;
const config = await nativeBridge.getConfig();
this.setState({
onboarding: config.onboarding,
isReady: true,
});
events.sub('search:results', this.updateResults);
events.sub('mobile-browser:notify-preferences', this.updatePreferences);
events.sub('mobile-browser:set-search-engine', this.setSearchEngine);
@@ -138,6 +148,9 @@ class MobileCards extends React.Component {
}

render() {
if (!this.state.isReady) {
return null;
}
const { results, suggestions, meta, query } = this.state.results;
const appearance = this.state.theme;
const layout = 'vertical';
ProTip! Use n and p to navigate between commits in a pull request.