diff --git a/Core/PartiallyRoundedRectangleView.swift b/Core/PartiallyRoundedRectangleView.swift new file mode 100644 index 0000000000..d6df85a4ae --- /dev/null +++ b/Core/PartiallyRoundedRectangleView.swift @@ -0,0 +1,45 @@ +// +// PartiallyRoundedRectangleView.swift +// DuckDuckGo +// +// Created by Mia Alexiou on 15/03/2017. +// Copyright © 2017 DuckDuckGo. All rights reserved. +// + +import UIKit + +@IBDesignable +public class PartiallyRoundedRectangleView: UIView { + + @IBInspectable var borderColor: UIColor = UIColor.white { + didSet { + layer.borderColor = borderColor.cgColor + } + } + + @IBInspectable var borderWidth: CGFloat = 2.0 { + didSet { + layer.borderWidth = borderWidth + } + } + + @IBInspectable var cornerRadius: CGFloat = 0.0 + + @IBInspectable var topLeftCorner: Bool = true + + @IBInspectable var topRightCorner: Bool = true + + @IBInspectable var bottomLeftCorner: Bool = true + + @IBInspectable var bottomRightCorner: Bool = true + + override public func layoutSubviews() { + super.layoutSubviews() + var corners = UIRectCorner() + if topLeftCorner { corners.insert(.topLeft) } + if topRightCorner { corners.insert(.topRight) } + if bottomLeftCorner { corners.insert(.bottomLeft) } + if bottomRightCorner { corners.insert(.bottomRight) } + round(corners: corners, radius: cornerRadius) + } +} diff --git a/Core/UIViewExtension.swift b/Core/UIViewExtension.swift index 6c1aae9392..57e2bbdbbb 100644 --- a/Core/UIViewExtension.swift +++ b/Core/UIViewExtension.swift @@ -30,4 +30,11 @@ extension UIView { attribute: .width, multiplier: 1, constant: 0)) } + public func round(corners: UIRectCorner, radius: CGFloat) { + let cornerRadii = CGSize(width: radius, height: radius) + let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: cornerRadii) + let maskLayer = CAShapeLayer() + maskLayer.path = path.cgPath + layer.mask = maskLayer + } } diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index ba522a9cd2..9c555ab085 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -51,6 +51,7 @@ F1617C151E57336D00DEDCAF /* TabManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1617C141E57336D00DEDCAF /* TabManager.swift */; }; F1617C191E573EA800DEDCAF /* TabSwitcherDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1617C181E573EA800DEDCAF /* TabSwitcherDelegate.swift */; }; F16390821E648B7A005B4550 /* HomeTabViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F16390811E648B7A005B4550 /* HomeTabViewController.swift */; }; + F1668BCB1E796366008CBA04 /* PartiallyRoundedRectangleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1668BCA1E796366008CBA04 /* PartiallyRoundedRectangleView.swift */; }; F176699A1E3FA5EE003D3222 /* Version.swift in Sources */ = {isa = PBXBuildFile; fileRef = F17669991E3FA5EE003D3222 /* Version.swift */; }; F176699F1E40BC86003D3222 /* Settings.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F176699D1E40BC86003D3222 /* Settings.storyboard */; }; F17669A31E411DB8003D3222 /* Version.swift in Sources */ = {isa = PBXBuildFile; fileRef = F17669991E3FA5EE003D3222 /* Version.swift */; }; @@ -201,6 +202,7 @@ F1617C141E57336D00DEDCAF /* TabManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabManager.swift; sourceTree = ""; }; F1617C181E573EA800DEDCAF /* TabSwitcherDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabSwitcherDelegate.swift; sourceTree = ""; }; F16390811E648B7A005B4550 /* HomeTabViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HomeTabViewController.swift; sourceTree = ""; }; + F1668BCA1E796366008CBA04 /* PartiallyRoundedRectangleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PartiallyRoundedRectangleView.swift; sourceTree = ""; }; F17669991E3FA5EE003D3222 /* Version.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Version.swift; sourceTree = ""; }; F176699E1E40BC86003D3222 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Settings.storyboard; sourceTree = ""; }; F17669A71E412A12003D3222 /* MockBundle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockBundle.swift; sourceTree = ""; }; @@ -324,7 +326,7 @@ F1BE54481E69DD5F00FCF649 /* Onboarding */, F1C5ECFA1E37B15B00C599A4 /* Main */, F16390801E648B68005B4550 /* Tabs */, - F1386BA21E6846320062FC3C /* TabSelector */, + F1386BA21E6846320062FC3C /* TabSwitcher */, F1C4A70C1E5771F800A6CA1B /* OmniBar */, F15D43211E70849A00BF2CDC /* Autocomplete */, F1AB2B401E3F75A000868554 /* Settings */, @@ -357,14 +359,14 @@ name = UserInterfaceResources; sourceTree = ""; }; - F1386BA21E6846320062FC3C /* TabSelector */ = { + F1386BA21E6846320062FC3C /* TabSwitcher */ = { isa = PBXGroup; children = ( F1617C181E573EA800DEDCAF /* TabSwitcherDelegate.swift */, F1617C121E572E0300DEDCAF /* TabSwitcherViewController.swift */, F1DE78571E5CAE350058895A /* TabViewCell.swift */, ); - name = TabSelector; + name = TabSwitcher; sourceTree = ""; }; F143C2E51E4A4CD400CFDE3A /* Core */ = { @@ -406,6 +408,7 @@ children = ( F143C3411E4A9C9A00CFDE3A /* UserText.swift */, F143C32B1E4A9A4800CFDE3A /* RoundedRectangleView.swift */, + F1668BCA1E796366008CBA04 /* PartiallyRoundedRectangleView.swift */, F143C3451E4AA32D00CFDE3A /* SearchBarExtension.swift */, F143C32C1E4A9A4800CFDE3A /* UIViewControllerExtension.swift */, F1B745211E549D550072547E /* UIColorExtension.swift */, @@ -931,6 +934,7 @@ F143C3291E4A9A0E00CFDE3A /* URLExtension.swift in Sources */, F143C3271E4A9A0E00CFDE3A /* Logger.swift in Sources */, F143C32F1E4A9A4800CFDE3A /* UIViewControllerExtension.swift in Sources */, + F1668BCB1E796366008CBA04 /* PartiallyRoundedRectangleView.swift in Sources */, F143C32E1E4A9A4800CFDE3A /* RoundedRectangleView.swift in Sources */, F1DE785A1E5CD2A70058895A /* UIViewExtension.swift in Sources */, F143C3261E4A9A0E00CFDE3A /* GroupData.swift in Sources */, diff --git a/DuckDuckGo/AutocompleteViewController.swift b/DuckDuckGo/AutocompleteViewController.swift index 1a650b1dde..c4cd8901ec 100644 --- a/DuckDuckGo/AutocompleteViewController.swift +++ b/DuckDuckGo/AutocompleteViewController.swift @@ -11,6 +11,8 @@ import Core class AutocompleteViewController: UIViewController { + @IBOutlet weak var widthConstraint: NSLayoutConstraint! + var delegate: AutocompleteViewControllerDelegate? private lazy var parser = AutocompleteParser() @@ -59,6 +61,11 @@ class AutocompleteViewController: UIViewController { requestSuggestions(query: query) } + @IBAction func onPlusButtonPressed(_ button: UIButton) { + let suggestion = suggestions[button.tag] + delegate?.autocomplete(pressedPlusButtonForSuggestion: suggestion.suggestion) + } + private func cancelInFlightRequests() { if let inFlightRequest = lastRequest { inFlightRequest.cancel() @@ -95,6 +102,7 @@ extension AutocompleteViewController: UITableViewDataSource { let type = SuggestionTableViewCell.reuseIdentifier let cell = tableView.dequeueReusableCell(withIdentifier: type, for: indexPath) as! SuggestionTableViewCell cell.updateFor(query: query, suggestion: suggestions[indexPath.row]) + cell.plusButton.tag = indexPath.row return cell } diff --git a/DuckDuckGo/AutocompleteViewControllerDelegate.swift b/DuckDuckGo/AutocompleteViewControllerDelegate.swift index 3c2d9155c5..f8181d317f 100644 --- a/DuckDuckGo/AutocompleteViewControllerDelegate.swift +++ b/DuckDuckGo/AutocompleteViewControllerDelegate.swift @@ -12,4 +12,6 @@ import Foundation protocol AutocompleteViewControllerDelegate { func autocomplete(selectedSuggestion suggestion: String) + + func autocomplete(pressedPlusButtonForSuggestion suggestion: String) } diff --git a/DuckDuckGo/Base.lproj/Autocomplete.storyboard b/DuckDuckGo/Base.lproj/Autocomplete.storyboard index 1ed8366689..d00498569d 100644 --- a/DuckDuckGo/Base.lproj/Autocomplete.storyboard +++ b/DuckDuckGo/Base.lproj/Autocomplete.storyboard @@ -21,7 +21,7 @@ - + @@ -42,34 +42,38 @@ - - - - - - - - + + + - + - - - + @@ -105,6 +109,7 @@ + @@ -120,23 +125,27 @@ + + + + - - + + - + diff --git a/DuckDuckGo/Base.lproj/Main.storyboard b/DuckDuckGo/Base.lproj/Main.storyboard index b2160cdef6..b29ad19320 100644 --- a/DuckDuckGo/Base.lproj/Main.storyboard +++ b/DuckDuckGo/Base.lproj/Main.storyboard @@ -32,7 +32,7 @@ - + @@ -40,7 +40,7 @@ - + @@ -166,6 +166,7 @@ + @@ -234,7 +235,7 @@ - + @@ -242,8 +243,7 @@ - - + @@ -259,7 +259,7 @@ - + @@ -448,7 +448,7 @@ - + @@ -485,7 +485,7 @@ - + @@ -499,7 +499,6 @@ - diff --git a/DuckDuckGo/Base.lproj/Settings.storyboard b/DuckDuckGo/Base.lproj/Settings.storyboard index 03a0d78a18..36b9adc855 100644 --- a/DuckDuckGo/Base.lproj/Settings.storyboard +++ b/DuckDuckGo/Base.lproj/Settings.storyboard @@ -62,43 +62,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -138,7 +105,6 @@ - diff --git a/DuckDuckGo/HomeTabDelegate.swift b/DuckDuckGo/HomeTabDelegate.swift index 7f9565d390..b5555e6549 100644 --- a/DuckDuckGo/HomeTabDelegate.swift +++ b/DuckDuckGo/HomeTabDelegate.swift @@ -9,12 +9,14 @@ import Foundation protocol HomeTabDelegate: class { - + func homeTabDidActivateOmniBar(homeTab: HomeTabViewController) func homeTabDidDeactivateOmniBar(homeTab: HomeTabViewController) func homeTabDidRequestTabsSwitcher(homeTab: HomeTabViewController) + + func homeTabDidRequestTabCount(homeTab: HomeTabViewController) -> Int func homeTab(_ homeTab: HomeTabViewController, didRequestUrl url: URL) diff --git a/DuckDuckGo/HomeTabViewController.swift b/DuckDuckGo/HomeTabViewController.swift index 2f12cf186c..dfeabb71c5 100644 --- a/DuckDuckGo/HomeTabViewController.swift +++ b/DuckDuckGo/HomeTabViewController.swift @@ -11,6 +11,7 @@ import Core class HomeTabViewController: UIViewController, Tab { + @IBOutlet weak var tabIcon: UIButton! @IBOutlet weak var passiveContainerView: UIView! @IBOutlet weak var centreBar: UIView! @@ -26,6 +27,7 @@ class HomeTabViewController: UIViewController, Tab { var canGoForward: Bool = false private var activeMode = false + private lazy var tabIconMaker = TabIconMaker() static func loadFromStoryboard() -> HomeTabViewController { return UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "HomeTabViewController") as! HomeTabViewController @@ -35,6 +37,7 @@ class HomeTabViewController: UIViewController, Tab { resetNavigationBar() activeMode = false refreshMode() + refreshTabIcon() super.viewWillAppear(animated) } @@ -52,6 +55,14 @@ class HomeTabViewController: UIViewController, Tab { } } + private func refreshTabIcon() { + guard let count = tabDelegate?.homeTabDidRequestTabCount(homeTab: self) else { return } + if count > 1 { + let image = tabIconMaker.icon(forTabs: count) + tabIcon.setImage(image, for: .normal) + } + } + @IBAction func onEnterActiveModeTapped(_ sender: Any) { enterActiveMode() } diff --git a/DuckDuckGo/MainViewController.swift b/DuckDuckGo/MainViewController.swift index a51b177656..2cb097ffca 100644 --- a/DuckDuckGo/MainViewController.swift +++ b/DuckDuckGo/MainViewController.swift @@ -34,6 +34,11 @@ class MainViewController: UIViewController { launchTab(active: false) } + override func viewDidLayoutSubviews() { + updateAutocompleteSize() + super.viewDidLayoutSubviews() + } + func loadQueryInNewWebTab(query: String) { if let url = AppUrls.url(forQuery: query) { loadUrlInNewWebTab(url: url) @@ -58,7 +63,7 @@ class MainViewController: UIViewController { } fileprivate func launchTab(active: Bool? = nil) { - let active = active ?? settings.launchNewTabInActiveMode + let active = active ?? true attachHomeTab(active: active) refreshControls() } @@ -111,7 +116,7 @@ class MainViewController: UIViewController { addToView(tab: selectedTab) refreshControls() } - + fileprivate func remove(tabAt index: Int) { tabManager.remove(at: index) @@ -184,11 +189,18 @@ class MainViewController: UIViewController { addChildViewController(controller) containerView.addSubview(controller.view) autocompleteController = controller + updateAutocompleteSize() } guard let autocompleteController = autocompleteController else { return } autocompleteController.updateQuery(query: query) } + private func updateAutocompleteSize() { + if let omniBarWidth = omniBar?.frame.width, let autocompleteController = autocompleteController { + autocompleteController.widthConstraint.constant = omniBarWidth + } + } + fileprivate func dismissOmniBar() { dismissAutcompleteSuggestions() refreshOmniText() @@ -223,24 +235,18 @@ class MainViewController: UIViewController { } } + @IBAction func onLaunchTabSwitcher(_ sender: UIBarButtonItem) { + launchTabSwitcher() + } + fileprivate func launchTabSwitcher() { let controller = TabSwitcherViewController.loadFromStoryboard() controller.delegate = self controller.modalPresentationStyle = .overCurrentContext + controller.modalTransitionStyle = .crossDissolve present(controller, animated: true, completion: nil) } - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - if let controller = segue.destination as? TabSwitcherViewController { - onTabSwitcherViewControllerSegue(controller: controller) - return - } - } - - private func onTabSwitcherViewControllerSegue(controller: TabSwitcherViewController) { - controller.delegate = self - } - private func makeToast(text: String) { let x = view.bounds.size.width / 2.0 let y = view.bounds.size.height - 80 @@ -280,6 +286,10 @@ extension MainViewController: AutocompleteViewControllerDelegate { loadQueryInCurrentTab(query: suggestion) omniBar?.resignFirstResponder() } + + func autocomplete(pressedPlusButtonForSuggestion suggestion: String) { + omniBar?.textField.text = suggestion + } } extension MainViewController: HomeTabDelegate { @@ -304,6 +314,10 @@ extension MainViewController: HomeTabDelegate { func homeTabDidRequestTabsSwitcher(homeTab: HomeTabViewController) { launchTabSwitcher() } + + func homeTabDidRequestTabCount(homeTab: HomeTabViewController) -> Int { + return tabManager.count + } } extension MainViewController: WebTabDelegate { @@ -334,7 +348,7 @@ extension MainViewController: TabSwitcherDelegate { func tabSwitcher(_ tabSwitcher: TabSwitcherViewController, didRemoveTabAt index: Int) { remove(tabAt: index) } - + func tabSwitcherDidRequestClearAll(tabSwitcher: TabSwitcherViewController) { clearAllTabs() } diff --git a/DuckDuckGo/Settings.swift b/DuckDuckGo/Settings.swift index b79b9197a0..3cc12b12ba 100644 --- a/DuckDuckGo/Settings.swift +++ b/DuckDuckGo/Settings.swift @@ -14,7 +14,6 @@ struct Settings { private struct Keys { static let hasSeenOnboarding = "hasSeenOnboarding" - static let launchNewTabInActiveMode = "launchNewTabInActiveMode" } public var hasSeenOnboarding: Bool { @@ -26,15 +25,6 @@ struct Settings { } } - public var launchNewTabInActiveMode: Bool { - get { - return userDefaults()?.bool(forKey: Keys.launchNewTabInActiveMode) ?? false - } - set(newValue) { - userDefaults()?.set(newValue, forKey: Keys.launchNewTabInActiveMode) - } - } - private func userDefaults() -> UserDefaults? { return UserDefaults(suiteName: suit) } diff --git a/DuckDuckGo/SettingsViewController.swift b/DuckDuckGo/SettingsViewController.swift index 82dbf17814..d71a0437e5 100644 --- a/DuckDuckGo/SettingsViewController.swift +++ b/DuckDuckGo/SettingsViewController.swift @@ -10,30 +10,19 @@ import UIKit class SettingsViewController: UITableViewController { - @IBOutlet weak var newTabeModeToggle: UISwitch! @IBOutlet weak var versionText: UILabel! private lazy var settings = Settings() override func viewDidLoad() { super.viewDidLoad() - configureNewTabModeToggle() configureVersionText() } - - private func configureNewTabModeToggle() { - newTabeModeToggle.isOn = settings.launchNewTabInActiveMode - } private func configureVersionText() { let version = Version() versionText.text = version.localized() } - - - @IBAction func onNewTabModeToggled(_ sender: UISwitch) { - settings.launchNewTabInActiveMode = newTabeModeToggle.isOn - } @IBAction func onDonePressed(_ sender: Any) { dismiss(animated: true, completion: nil) diff --git a/DuckDuckGo/SuggestionTableViewCell.swift b/DuckDuckGo/SuggestionTableViewCell.swift index 5dc7ffccc7..f7e3680cde 100644 --- a/DuckDuckGo/SuggestionTableViewCell.swift +++ b/DuckDuckGo/SuggestionTableViewCell.swift @@ -15,16 +15,16 @@ class SuggestionTableViewCell: UITableViewCell { @IBOutlet weak var label: UILabel! @IBOutlet weak var typeImage: UIImageView! - @IBOutlet weak var plusImage: UIImageView! + @IBOutlet weak var plusButton: UIButton! func updateFor(query: String, suggestion: Suggestion) { let text = suggestion.suggestion if URL.isWebUrl(text: text) { typeImage.image = #imageLiteral(resourceName: "GlobeSmall") - plusImage.isHidden = true + plusButton.isHidden = true } else { typeImage.image = #imageLiteral(resourceName: "searchLoupeSmall") - plusImage.isHidden = false + plusButton.isHidden = false } styleText(query: query, text: suggestion.suggestion) }