Skip to content

Commit

Permalink
DuckPlayer PiP settings (#2830)
Browse files Browse the repository at this point in the history
Task/Issue URL:
https://app.asana.com/0/1204167627774280/1207452548013008/f

**Description**:
Adds settings for C-S-S to enable/disable PiP
ps. This adds no changes to the user experience yet, the PiP button will
be enabled at a later time via C-S-S
  • Loading branch information
Bunn authored Jun 4, 2024
1 parent 31ac5d3 commit 447a20d
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ import WebKit

extension WKWebViewConfiguration {

var allowsPictureInPictureMediaPlayback: Bool {
get {
return preferences.value(forKey: "allowsPictureInPictureMediaPlayback") as? Bool ?? false
}
set {
preferences.setValue(newValue, forKey: "allowsPictureInPictureMediaPlayback")
}
}

@MainActor
func applyStandardConfiguration(contentBlocking: some ContentBlockingProtocol, burnerMode: BurnerMode) {
if case .burner(let websiteDataStore) = burnerMode {
Expand All @@ -34,7 +43,11 @@ extension WKWebViewConfiguration {
} else {
preferences.setValue(true, forKey: "fullScreenEnabled")
}
preferences.setValue(true, forKey: "allowsPictureInPictureMediaPlayback")

#if !APPSTORE
allowsPictureInPictureMediaPlayback = true
#endif

preferences.setValue(true, forKey: "developerExtrasEnabled")
preferences.setValue(false, forKey: "backspaceKeyNavigationEnabled")
preferences.javaScriptCanOpenWindowsAutomatically = true
Expand Down
37 changes: 37 additions & 0 deletions DuckDuckGo/YoutubePlayer/DuckPlayer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,25 @@ enum DuckPlayerMode: Equatable, Codable {
}

/// Values that the Frontend can use to determine the current state.
struct InitialSetupSettings: Codable {
struct PlayerSettings: Codable {
let pip: PIP
}

struct PIP: Codable {
let status: Status
}

enum Status: String, Codable {
case enabled
case disabled
}

let userValues: UserValues
let settings: PlayerSettings
}

/// Values that the Frontend can use to determine user settings
public struct UserValues: Codable {
enum CodingKeys: String, CodingKey {
case duckPlayerMode = "privatePlayerMode"
Expand Down Expand Up @@ -168,13 +187,30 @@ final class DuckPlayer {
encodeUserValues()
}

public func initialSetup(with webView: WKWebView?) -> (_ params: Any, _ message: UserScriptMessage) async -> Encodable? {
return { _, _ in
return await self.encodedSettings(with: webView)
}
}

private func encodeUserValues() -> UserValues {
UserValues(
duckPlayerMode: self.preferences.duckPlayerMode,
overlayInteracted: self.preferences.youtubeOverlayInteracted
)
}

@MainActor
private func encodedSettings(with webView: WKWebView?) async -> InitialSetupSettings {
let isPiPEnabled = webView?.configuration.allowsPictureInPictureMediaPlayback == true
let pip = InitialSetupSettings.PIP(status: isPiPEnabled ? .enabled : .disabled)

let playerSettings = InitialSetupSettings.PlayerSettings(pip: pip)
let userValues = encodeUserValues()

return InitialSetupSettings(userValues: userValues, settings: playerSettings)
}

// MARK: - Private

private static let websiteTitlePrefix = "\(commonName) - "
Expand Down Expand Up @@ -253,6 +289,7 @@ extension DuckPlayer {
}
return actualTitle.dropping(prefix: Self.websiteTitlePrefix)
}

}

#if DEBUG
Expand Down
3 changes: 3 additions & 0 deletions DuckDuckGo/YoutubePlayer/YoutubePlayerUserScript.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ final class YoutubePlayerUserScript: NSObject, Subfeature {
enum MessageNames: String, CaseIterable {
case setUserValues
case getUserValues
case initialSetup
}

func handler(forMethodNamed methodName: String) -> Subfeature.Handler? {
Expand All @@ -53,6 +54,8 @@ final class YoutubePlayerUserScript: NSObject, Subfeature {
return DuckPlayer.shared.handleGetUserValues
case .setUserValues:
return DuckPlayer.shared.handleSetUserValuesMessage(from: .duckPlayer)
case .initialSetup:
return DuckPlayer.shared.initialSetup(with: webView)
default:
assertionFailure("YoutubePlayerUserScript: Failed to parse User Script message: \(methodName)")
return nil
Expand Down
14 changes: 14 additions & 0 deletions UnitTests/YoutubePlayer/DuckPlayerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import BrowserServicesKit
import Combine
import XCTest
import Common

@testable import DuckDuckGo_Privacy_Browser

Expand Down Expand Up @@ -89,6 +90,19 @@ final class DuckPlayerTests: XCTestCase {
XCTAssertNil(duckPlayer.title(for: feedItem))
}

@MainActor
func testEnabledPiPFlag() async {
let configuration = WKWebViewConfiguration()

configuration.applyStandardConfiguration(contentBlocking: ContentBlockingMock(),
burnerMode: .regular)
#if APPSTORE
XCTAssertFalse(configuration.allowsPictureInPictureMediaPlayback)
#else
XCTAssertTrue(configuration.allowsPictureInPictureMediaPlayback)
#endif
}

func testThatTitleForRecentlyVisitedPageIsNotAdjustedForNonDuckPlayerFeedItems() {
let feedItem = HomePage.Models.RecentlyVisitedPageModel(
actualTitle: "Duck Player - A sample video title",
Expand Down

0 comments on commit 447a20d

Please sign in to comment.