Skip to content

Commit

Permalink
Fix brave/brave-ios#7855: Add 'Private tabs' settings section (brave/…
Browse files Browse the repository at this point in the history
  • Loading branch information
soner-yuksel authored Aug 15, 2023
1 parent 4314e58 commit f00987c
Show file tree
Hide file tree
Showing 48 changed files with 179 additions and 128 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import Combine
import Data
import SnapKit
import BraveUI
import LocalAuthentication

protocol TabTrayDelegate: AnyObject {
/// Notifies the delegate that order of tabs on tab tray has changed.
Expand Down Expand Up @@ -600,7 +601,12 @@ class TabTrayController: AuthenticationController {

@objc func togglePrivateModeAction() {
if !privateMode, Preferences.Privacy.privateBrowsingLock.value {
askForAuthentication(viewType: .tabTray)
askForAuthentication(viewType: .tabTray) { [weak self] success, error in
if !success, error == LAError.passcodeNotSet {
// If Pin code is not set in this device, private mode is enabled default
self?.toggleModeChanger()
}
}
} else {
toggleModeChanger()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,26 +53,6 @@ struct OtherPrivacySettingsSectionView: View {
})
)
})

if !Preferences.Privacy.privateBrowsingOnly.value {
OptionToggleView(title: Strings.persistentPrivateBrowsing,
subtitle: nil,
option: Preferences.Privacy.persistentPrivateBrowsing) { newValue in
Task { @MainActor in
if newValue {
settings.tabManager.saveAllTabs()
} else {
let tabs = settings.tabManager.allTabs.filter({ $0.isPrivate })
SessionTab.deleteAll(tabIds: tabs.map({ $0.id }))

if !settings.tabManager.privateBrowsingManager.isPrivateBrowsing {
settings.tabManager.willSwitchTabMode(leavingPBM: true)
}
}
}
}
}

ShieldToggleView(
title: Strings.blockMobileAnnoyances,
subtitle: nil,
Expand Down

This file was deleted.

20 changes: 14 additions & 6 deletions Sources/Brave/Frontend/Settings/SettingsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,19 @@ class SettingsViewController: TableViewController {
}

tabs.rows.append(autoCloseTabsRow)

if !Preferences.Privacy.privateBrowsingOnly.value {
let privateTabsRow = Row(
text: Strings.TabsSettings.privateTabsSettingsTitle,
selection: { [unowned self] in
let vc = UIHostingController(rootView: PrivateTabsView(tabManager: tabManager))
self.navigationController?.pushViewController(vc, animated: true)
},
image: UIImage(braveSystemNamed: "leo.product.private-window"),
accessory: .disclosureIndicator)

tabs.rows.append(privateTabsRow)
}

return tabs
}()
Expand Down Expand Up @@ -594,11 +607,6 @@ class SettingsViewController: TableViewController {
detailText: Strings.Privacy.browserLockDescription,
option: Preferences.Privacy.lockWithPasscode,
image: UIImage(braveSystemNamed: "leo.biometric.login")),
.boolRow(
title: Strings.Privacy.privateBrowsingLock,
detailText: Strings.Privacy.privateBrowsingLockDescription,
option: Preferences.Privacy.privateBrowsingLock,
image: UIImage(braveSystemNamed: "leo.lock")),
Row(
text: Strings.Login.loginListNavigationTitle,
selection: { [unowned self] in
Expand All @@ -607,7 +615,7 @@ class SettingsViewController: TableViewController {
windowProtection: self.windowProtection)
loginsPasswordsViewController.settingsDelegate = self.settingsDelegate
self.navigationController?.pushViewController(loginsPasswordsViewController, animated: true)
}, image: UIImage(braveSystemNamed: "leo.outside"), accessory: .disclosureIndicator),
}, image: UIImage(braveSystemNamed: "leo.outside"), accessory: .disclosureIndicator)
]
)
}()
Expand Down
117 changes: 117 additions & 0 deletions Sources/Brave/Frontend/Settings/Tabs/PrivateTabsView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright 2023 The Brave Authors. All rights reserved.
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

import SwiftUI
import BraveStrings
import Preferences
import BraveUI
import Data
import LocalAuthentication

struct PrivateTabsView: View {
enum AuthenticationType {
case faceID, touchID, pinCode, noAuthentication
}

@ObservedObject var privateBrowsingOnly = Preferences.Privacy.privateBrowsingOnly
var tabManager: TabManager?

private var localAuthenticationType: AuthenticationType {
let context = LAContext()

if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: nil) {
switch context.biometryType {
case .faceID:
return .faceID
case .touchID:
return .touchID
default:
return .noAuthentication
}
}

var error: NSError?
let policyEvaluation = context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error)

if policyEvaluation {
return .pinCode
}

return .noAuthentication
}

private var browsingLockTitle: String {
var title: String

switch localAuthenticationType {
case .faceID:
title = Strings.TabsSettings.privateBrowsingLockTitleFaceID
case .touchID:
title = Strings.TabsSettings.privateBrowsingLockTitleTouchID
default:
title = Strings.TabsSettings.privateBrowsingLockTitlePinCode
}

return title
}

var body: some View {
Form {
Section(
header: Text(Strings.TabsSettings.privateTabsSettingsTitle.uppercased()),
footer: privateBrowsingOnly.value ? Text("") : Text(Strings.TabsSettings.persistentPrivateBrowsingDescription)) {
if !privateBrowsingOnly.value {
OptionToggleView(title: Strings.TabsSettings.persistentPrivateBrowsingTitle,
subtitle: nil,
option: Preferences.Privacy.persistentPrivateBrowsing) { newValue in
Task { @MainActor in
if newValue {
tabManager?.saveAllTabs()
} else {
if let tabs = tabManager?.allTabs.filter({ $0.isPrivate }) {
SessionTab.deleteAll(tabIds: tabs.map({ $0.id }))
}

if tabManager?.privateBrowsingManager.isPrivateBrowsing == true {
tabManager?.willSwitchTabMode(leavingPBM: true)
}
}
}
}
}

switch localAuthenticationType {
case .faceID, .touchID, .pinCode:
OptionToggleView(title: browsingLockTitle,
subtitle: nil,
option: Preferences.Privacy.privateBrowsingLock)
case .noAuthentication:
Toggle(isOn: .constant(false)) {
VStack(alignment: .leading, spacing: 4) {
Text(browsingLockTitle)
.foregroundColor(Color(.bravePrimary))
}
.opacity(0.25)
}
.disabled(true)
.listRowBackground(Color(.secondaryBraveGroupedBackground))
.toggleStyle(SwitchToggleStyle(tint: .accentColor))
}
}
.listRowBackground(Color(.secondaryBraveGroupedBackground))
}
.navigationBarTitle(Strings.TabsSettings.privateTabsSettingsTitle)
.navigationBarTitleDisplayMode(.inline)
.listBackgroundColor(Color(UIColor.braveGroupedBackground))
}
}

#if DEBUG
struct PrivateTabsView_Previews: PreviewProvider {
static var previews: some View {
PrivateTabsView()
}
}
#endif
8 changes: 6 additions & 2 deletions Sources/Brave/Frontend/Widgets/LoadingViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,12 @@ public class AuthenticationController: LoadingViewController {
}

if !windowProtection.isPassCodeAvailable {
showSetPasscodeError(viewType: viewType) {
if viewType == .tabTray {
completion?(false, LAError.passcodeNotSet)
} else {
showSetPasscodeError(viewType: viewType) {
completion?(false, LAError.passcodeNotSet)
}
}
} else {
windowProtection.presentAuthenticationForViewController(
Expand All @@ -91,7 +95,7 @@ public class AuthenticationController: LoadingViewController {

alert.addAction(
UIAlertAction(title: Strings.OKString, style: .default, handler: { _ in
completion()
completion()
})
)

Expand Down
45 changes: 35 additions & 10 deletions Sources/BraveStrings/BraveStrings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3340,16 +3340,6 @@ extension Strings {
"BrowserLockDescription", tableName: "BraveShared", bundle: .module,
value: "Unlock Brave with Touch ID, Face ID or system passcode.",
comment: "Description for setting to enable the browser lock privacy feature")
public static let privateBrowsingLock =
NSLocalizedString(
"privacy.private.browsing.lock.title", tableName: "BraveShared", bundle: .module,
value: "Private Browsing Lock",
comment: "Title for setting to enable the private browsing lock privacy feature")
public static let privateBrowsingLockDescription =
NSLocalizedString(
"privacy.private.browsing.lock.description", tableName: "BraveShared", bundle: .module,
value: "Require Passcode to Unlock Private Browsing",
comment: "Description for setting to enable the browser lock privacy feature")
public static let tabTraySetPasscodeAlertDescription =
NSLocalizedString(
"privacy.tab.tray.passcode.alert",
Expand All @@ -3360,6 +3350,41 @@ extension Strings {
}
}

extension Strings {
public struct TabsSettings {
public static let privateTabsSettingsTitle =
NSLocalizedString(
"tabs.settings.privateTabsSettingsTitle", tableName: "BraveShared", bundle: .module,
value: "Private Tabs",
comment: "")
public static let privateBrowsingLockTitleFaceID =
NSLocalizedString(
"tabs.settings.privateBrowsingLockTitleFaceID", tableName: "BraveShared", bundle: .module,
value: "Require Face ID",
comment: "")
public static let privateBrowsingLockTitleTouchID =
NSLocalizedString(
"tabs.settings.privateBrowsingLockTitleTouchID", tableName: "BraveShared", bundle: .module,
value: "Require Touch ID",
comment: "")
public static let privateBrowsingLockTitlePinCode =
NSLocalizedString(
"tabs.settings.privateBrowsingLockTitlePinCode", tableName: "BraveShared", bundle: .module,
value: "Require Pin Code",
comment: "")
public static let persistentPrivateBrowsingTitle =
NSLocalizedString(
"tabs.settings.persistentPrivateBrowsingTitle", tableName: "BraveShared", bundle: .module,
value: "Keep Private Tabs",
comment: "")
public static let persistentPrivateBrowsingDescription =
NSLocalizedString(
"tabs.settings.persistentPrivateBrowsingTitle", tableName: "BraveShared", bundle: .module,
value: "Keep private browsing tabs open when you close the app, ensuring private browsing sessions continue seamlessly.",
comment: "")
}
}

extension Strings {
public struct Login {
public static let loginListEmptyScreenTitle =
Expand Down

0 comments on commit f00987c

Please sign in to comment.