Skip to content

Commit

Permalink
Merge branch 'main' into dominik/xcode-16
Browse files Browse the repository at this point in the history
  • Loading branch information
jotaemepereira committed Nov 1, 2024
2 parents 5ebab3e + 9280027 commit 5aa1c0f
Show file tree
Hide file tree
Showing 309 changed files with 14,226 additions and 763,564 deletions.
35 changes: 35 additions & 0 deletions .github/workflows/update_phishing_detection_data.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Update Phishing Detection Datasets
on:
schedule:
- cron: '0 0 * * 0' # Midnight UTC every Sunday
jobs:
update_data:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
repository: duckduckgo/macos-browser
path: macos/
token: ${{ secrets.DAX_MACOS_BROWSER_PHISHING_AUTOMATION }}
- name: Execute Update Script
run: |
cd ./macos
REVISION="$(bash ./scripts/update_phishing_detection_data.sh | grep -oP 'Updated revision from \K\d+')"
echo "REVISION=$REVISION" >> $GITHUB_ENV
TEMPLATE="$(bash ./scripts/update_phishing_detection_data.sh pr-body)"
PR_BODY_MACOS="${TEMPLATE//\{\{revision\}\}/$REVISION}"
echo "PR_BODY_MACOS<<EOF" >> $GITHUB_ENV
echo "$PR_BODY_MACOS" >> $GITHUB_ENV
echo "EOF" >> $GITHUB_ENV
- name: Create PR for macOS
uses: peter-evans/create-pull-request@88bf0de51c7487d91e1abbb4899332e602c58bbf
id: create-pr
with:
path: macos/
add-paths: |
./DuckDuckGo/PhishingDetection/
commit-message: Update phishing detection data to revision ${{ env.REVISION }}
branch: update-phishing-protection-${{ env.REVISION }}
title: Update phishing protection datasets to ${{ env.REVISION }}
body: "${{ env.PR_BODY_MACOS }}"
2 changes: 1 addition & 1 deletion Configuration/BuildNumber.xcconfig
Original file line number Diff line number Diff line change
@@ -1 +1 @@
CURRENT_PROJECT_VERSION = 286
CURRENT_PROJECT_VERSION = 293
2 changes: 1 addition & 1 deletion Configuration/Version.xcconfig
Original file line number Diff line number Diff line change
@@ -1 +1 @@
MARKETING_VERSION = 1.111.0
MARKETING_VERSION = 1.112.0
348 changes: 334 additions & 14 deletions DuckDuckGo.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/content-scope-scripts",
"state" : {
"revision" : "1ed569676555d493c9c5575eaed22aa02569aac9",
"version" : "6.19.0"
"revision" : "48fee2508995d4ac02d18b3d55424adedcb4ce4f",
"version" : "6.28.0"
}
},
{
"identity" : "duckduckgo-autofill",
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/duckduckgo-autofill.git",
"state" : {
"revision" : "945ac09a0189dc6736db617867fde193ea984b20",
"version" : "15.0.0"
"revision" : "c992041d16ec10d790e6204dce9abf9966d1363c",
"version" : "15.1.0"
}
},
{
Expand All @@ -74,7 +74,7 @@
{
"identity" : "lottie-spm",
"kind" : "remoteSourceControl",
"location" : "https://github.com/airbnb/lottie-spm",
"location" : "https://github.com/airbnb/lottie-spm.git",
"state" : {
"revision" : "1d29eccc24cc8b75bff9f6804155112c0ffc9605",
"version" : "4.4.3"
Expand Down
53 changes: 34 additions & 19 deletions DuckDuckGo/AIChat/AIChatMenuVisibilityConfigurable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,56 +21,71 @@ import Combine
protocol AIChatMenuVisibilityConfigurable {
var shouldDisplayApplicationMenuShortcut: Bool { get }
var shouldDisplayToolbarShortcut: Bool { get }

var isFeatureEnabledForApplicationMenuShortcut: Bool { get }
var isFeatureEnabledForToolbarShortcut: Bool { get }

var shortcutURL: URL { get }
var valuesChangedPublisher: PassthroughSubject<Void, Never> { get }
}

final class AIChatMenuConfiguration: AIChatMenuVisibilityConfigurable {
var valuesChangedPublisher = PassthroughSubject<Void, Never>()
private var cancellables = Set<AnyCancellable>()
private let preferences: AIChatPreferences

enum ShortcutType {
case applicationMenu
case toolbar
}

// MARK: - Public
private var cancellables = Set<AnyCancellable>()
private var storage: AIChatPreferencesStorage

var shouldDisplayApplicationMenuShortcut: Bool {
return isFeatureEnabledFor(shortcutType: .applicationMenu) && preferences.showShortcutInApplicationMenu
var valuesChangedPublisher = PassthroughSubject<Void, Never>()

var isFeatureEnabledForApplicationMenuShortcut: Bool {
isFeatureEnabledFor(shortcutType: .applicationMenu)
}

var isFeatureEnabledForToolbarShortcut: Bool {
isFeatureEnabledFor(shortcutType: .toolbar)
}

var shouldDisplayToolbarShortcut: Bool {
return isFeatureEnabledFor(shortcutType: .toolbar) && preferences.showShortcutInToolbar
return isFeatureEnabledForToolbarShortcut && storage.shouldDisplayToolbarShortcut
}

var shouldDisplayApplicationMenuShortcut: Bool {
return isFeatureEnabledForApplicationMenuShortcut && storage.showShortcutInApplicationMenu
}

var shortcutURL: URL {
URL(string: "https://duckduckgo.com/?q=DuckDuckGo+AI+Chat&ia=chat&duckai=2")!
}

init(preferences: AIChatPreferences = .shared) {
self.preferences = preferences
subscribeToValueChanges()
init(storage: AIChatPreferencesStorage = DefaultAIChatPreferencesStorage()) {
self.storage = storage
self.subscribeToValuesChanged()
}

// MARK: - Private
private func subscribeToValuesChanged() {
storage.shouldDisplayToolbarShortcutPublisher
.removeDuplicates()
.sink { [weak self] _ in
self?.valuesChangedPublisher.send()
}.store(in: &cancellables)

private func subscribeToValueChanges() {
preferences.$showShortcutInToolbar
.merge(with: preferences.$showShortcutInApplicationMenu)
.dropFirst()
storage.showShortcutInApplicationMenuPublisher
.removeDuplicates()
.sink { [weak self] _ in
self?.valuesChangedPublisher.send(())
}
.store(in: &cancellables)
self?.valuesChangedPublisher.send()
}.store(in: &cancellables)
}

private func isFeatureEnabledFor(shortcutType: ShortcutType) -> Bool {
switch shortcutType {
case .applicationMenu:
// Use privacy config here
return true
case .toolbar:
// Use privacy config here
return true
}
}
Expand Down
101 changes: 101 additions & 0 deletions DuckDuckGo/AIChat/AIChatPreferencesStorage.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
//
// AIChatPreferencesStorage.swift
//
// Copyright © 2024 DuckDuckGo. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import Combine

protocol AIChatPreferencesStorage {
var showShortcutInApplicationMenu: Bool { get set }
var shouldDisplayToolbarShortcut: Bool { get set }

var showShortcutInApplicationMenuPublisher: AnyPublisher<Bool, Never> { get }
var shouldDisplayToolbarShortcutPublisher: AnyPublisher<Bool, Never> { get }
}

struct DefaultAIChatPreferencesStorage: AIChatPreferencesStorage {
var showShortcutInApplicationMenuPublisher: AnyPublisher<Bool, Never> {
userDefaults.showAIChatShortcutInApplicationMenuPublisher
}

var shouldDisplayToolbarShortcutPublisher: AnyPublisher<Bool, Never> {
NotificationCenter.default.publisher(for: .PinnedViewsChanged)
.compactMap { notification -> PinnableView? in
guard let userInfo = notification.userInfo as? [String: Any],
let viewType = userInfo[LocalPinningManager.pinnedViewChangedNotificationViewTypeKey] as? String,
let view = PinnableView(rawValue: viewType) else {
return nil
}
return view == .aiChat ? view : nil
}
.flatMap { view -> AnyPublisher<Bool, Never> in
return Just(self.pinningManager.isPinned(view)).eraseToAnyPublisher()
}
.eraseToAnyPublisher()
}

private let userDefaults: UserDefaults
private let pinningManager: PinningManager

init(userDefaults: UserDefaults = .standard,
pinningManager: PinningManager = LocalPinningManager.shared) {
self.userDefaults = userDefaults
self.pinningManager = pinningManager
}

var shouldDisplayToolbarShortcut: Bool {
get { pinningManager.isPinned(.aiChat) }
set {
if newValue {
pinningManager.pin(.aiChat)
} else {
pinningManager.unpin(.aiChat)
}
}
}

var showShortcutInApplicationMenu: Bool {
get { userDefaults.showAIChatShortcutInApplicationMenu }
set { userDefaults.showAIChatShortcutInApplicationMenu = newValue }
}
}

private extension UserDefaults {
private var showAIChatShortcutInApplicationMenuKey: String {
"aichat.showAIChatShortcutInApplicationMenu"
}

static let showAIChatShortcutInApplicationMenuDefaultValue = false

@objc
dynamic var showAIChatShortcutInApplicationMenu: Bool {
get {
value(forKey: showAIChatShortcutInApplicationMenuKey) as? Bool ?? Self.showAIChatShortcutInApplicationMenuDefaultValue
}

set {
guard newValue != showAIChatShortcutInApplicationMenu else {
return
}

set(newValue, forKey: showAIChatShortcutInApplicationMenuKey)
}
}

var showAIChatShortcutInApplicationMenuPublisher: AnyPublisher<Bool, Never> {
publisher(for: \.showAIChatShortcutInApplicationMenu).eraseToAnyPublisher()
}
}
Loading

0 comments on commit 5aa1c0f

Please sign in to comment.