Skip to content

Commit

Permalink
Add UI for displaying Duck Player contingency message #3065 (#3181)
Browse files Browse the repository at this point in the history
Task/Issue URL:
https://app.asana.com/0/1204167627774280/1207871109767442/f
Tech Design URL:
CC:

**Description**:
Add UI for displaying Duck Player contingency message
  • Loading branch information
Bunn authored Aug 6, 2024
1 parent 3dc474f commit 6fb037f
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 2 deletions.
4 changes: 4 additions & 0 deletions DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@
1EFDCBC127D2393C00916BC5 /* DownloadsDeleteHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1EFDCBC027D2393C00916BC5 /* DownloadsDeleteHelper.swift */; };
22CB1ED8203DDD2C00D2C724 /* AppDeepLinksTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 22CB1ED7203DDD2C00D2C724 /* AppDeepLinksTests.swift */; };
2DC3FC65C6D9DA634426672D /* AutofillNoAuthAvailableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DC3FBD62FBAF21E87610FA8 /* AutofillNoAuthAvailableView.swift */; };
31009B382C5D32D100510782 /* DuckPlayerContingencyHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 31009B372C5D32D100510782 /* DuckPlayerContingencyHandler.swift */; };
310742A62848CD780012660B /* BackForwardMenuHistoryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 310742A52848CD780012660B /* BackForwardMenuHistoryItem.swift */; };
310742AB2848E6FD0012660B /* BackForwardMenuHistoryItemURLSanitizerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 310742A92848E5B70012660B /* BackForwardMenuHistoryItemURLSanitizerTests.swift */; };
310C4B45281B5A9A00BA79A9 /* AutofillLoginDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 310C4B44281B5A9A00BA79A9 /* AutofillLoginDetailsView.swift */; };
Expand Down Expand Up @@ -1332,6 +1333,7 @@
1EFDCBC027D2393C00916BC5 /* DownloadsDeleteHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadsDeleteHelper.swift; sourceTree = "<group>"; };
22CB1ED7203DDD2C00D2C724 /* AppDeepLinksTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDeepLinksTests.swift; sourceTree = "<group>"; };
2DC3FBD62FBAF21E87610FA8 /* AutofillNoAuthAvailableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AutofillNoAuthAvailableView.swift; sourceTree = "<group>"; };
31009B372C5D32D100510782 /* DuckPlayerContingencyHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DuckPlayerContingencyHandler.swift; sourceTree = "<group>"; };
310742A52848CD780012660B /* BackForwardMenuHistoryItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackForwardMenuHistoryItem.swift; sourceTree = "<group>"; };
310742A92848E5B70012660B /* BackForwardMenuHistoryItemURLSanitizerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BackForwardMenuHistoryItemURLSanitizerTests.swift; sourceTree = "<group>"; };
310C4B44281B5A9A00BA79A9 /* AutofillLoginDetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillLoginDetailsView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -4948,6 +4950,7 @@
D63FF8922C1B67D1006DE24D /* DuckPlayer */ = {
isa = PBXGroup;
children = (
31009B372C5D32D100510782 /* DuckPlayerContingencyHandler.swift */,
31DE43C82C2DAA8F00F8C51F /* Modal */,
31DE43C72C2DAA7F00F8C51F /* Resources */,
D63FF8972C1B6A45006DE24D /* DuckPlayer.swift */,
Expand Down Expand Up @@ -7018,6 +7021,7 @@
F1386BA41E6846C40062FC3C /* TabDelegate.swift in Sources */,
37CF91602BB4737300BADCAE /* CrashCollectionOnboarding.swift in Sources */,
C1B924B72ACD6E6800EE7B06 /* AutofillNeverSavedTableViewCell.swift in Sources */,
31009B382C5D32D100510782 /* DuckPlayerContingencyHandler.swift in Sources */,
3132FA2A27A0788F00DD7A12 /* QuickLookPreviewHelper.swift in Sources */,
D670E5BB2BB6A75300941A42 /* SubscriptionNavigationCoordinator.swift in Sources */,
6F9FFE262C579BCD00A238BE /* NewTabPageShortcutsSettingsStorage.swift in Sources */,
Expand Down
36 changes: 36 additions & 0 deletions DuckDuckGo/DuckPlayer/DuckPlayerContingencyHandler.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//
// DuckPlayerContingencyHandler.swift
// DuckDuckGo
//
// 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 Foundation

protocol DuckPlayerContingencyHandler {
var shouldDisplayContingencyMessage: Bool { get }
var learnMoreURL: URL { get }
}

struct DefaultDuckPlayerContingencyHandler: DuckPlayerContingencyHandler {
var shouldDisplayContingencyMessage: Bool {
false
}

var learnMoreURL: URL {
#warning("DuckPlayer - Replace this with real URL")
return URL(string: "https://duckduckgo.com/duckduckgo-help-pages/duck-player/")!
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "WarningYoutube.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Binary file not shown.
54 changes: 54 additions & 0 deletions DuckDuckGo/SettingsDuckPlayerView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,22 @@
import Core
import SwiftUI
import DesignResourcesKit
import DuckUI

struct SettingsDuckPlayerView: View {
private static let learnMoreURL = URL(string: "https://duckduckgo.com/duckduckgo-help-pages/duck-player/")!

@EnvironmentObject var viewModel: SettingsViewModel
var body: some View {
List {
if viewModel.shouldDisplayDuckPlayerContingencyMessage() {
Section {
ContingencyMessageView {
viewModel.openDuckPlayerContingencyMessageSite()
}
}
}

VStack(alignment: .center) {
Image("SettingsDuckPlayerHero")
.padding(.top, -20) // Adjust for the image padding
Expand Down Expand Up @@ -62,3 +71,48 @@ struct SettingsDuckPlayerView: View {
viewModel: viewModel)
}
}

private struct ContingencyMessageView: View {
let buttonCallback: () -> Void

private enum Copy {
static let title: String = UserText.duckPlayerContingencyMessageTitle
static let message: String = UserText.duckPlayerContingencyMessageBody
static let buttonTitle: String = UserText.duckPlayerContingencyMessageCTA
}
private enum Constants {
static let imageName: String = "WarningYoutube"
static let imageSize: CGSize = CGSize(width: 50, height: 50)
static let buttonCornerRadius: CGFloat = 8.0
}

var body: some View {
VStack(alignment: .center, spacing: 8) {
Image(Constants.imageName)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: Constants.imageSize.width, height: Constants.imageSize.height)
.padding(.bottom, 8)

Text(Copy.title)
.daxHeadline()
.foregroundColor(Color(designSystemColor: .textPrimary))

Text(Copy.message)
.daxBodyRegular()
.multilineTextAlignment(.center)
.lineLimit(nil)
.foregroundColor(Color(designSystemColor: .textPrimary))

Button {
buttonCallback()
} label: {
Text(Copy.buttonTitle)
.foregroundColor(Color(designSystemColor: .textPrimary))
.bold()
}
.buttonStyle(SecondaryFillButtonStyle(fullWidth: false))
.padding(10)
}
}
}
14 changes: 12 additions & 2 deletions DuckDuckGo/SettingsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ final class SettingsViewModel: ObservableObject {
var emailManager: EmailManager { EmailManager() }
private let historyManager: HistoryManaging
let privacyProDataReporter: PrivacyProDataReporting?

// Subscription Dependencies
private let subscriptionManager: SubscriptionManager
private var subscriptionSignOutObserver: Any?

var duckPlayerContingencyHandler: DuckPlayerContingencyHandler { DefaultDuckPlayerContingencyHandler() }

private enum UserDefaultsCacheKey: String, UserDefaultsCacheKeyStore {
case subscriptionState = "com.duckduckgo.ios.subscription.state"
}
Expand Down Expand Up @@ -539,6 +539,16 @@ extension SettingsViewModel {
completionHandler: nil)
}

func shouldDisplayDuckPlayerContingencyMessage() -> Bool {
duckPlayerContingencyHandler.shouldDisplayContingencyMessage
}

func openDuckPlayerContingencyMessageSite() {
UIApplication.shared.open(duckPlayerContingencyHandler.learnMoreURL,
options: [:],
completionHandler: nil)
}

@MainActor func openCookiePopupManagement() {
pushViewController(legacyViewProvider.autoConsent)
}
Expand Down
4 changes: 4 additions & 0 deletions DuckDuckGo/UserText.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1187,6 +1187,10 @@ But if you *do* want a peek under the hood, you can find more information about
public static let duckPlayerPresentationModalBody = NSLocalizedString("duckplayer.presentation.modal.body", value: "Duck Player lets you watch YouTube without targeted ads in a theater-like experience in DuckDuckGo and what you watch won’t influence your recommendations.", comment: "Body text for the modal feature explanation")
public static let duckPlayerPresentationModalDismissButton = NSLocalizedString("duckplayer.presentation.modal.dismiss-button", value: "Got it!", comment: "Button that will dismiss the modal")

static let duckPlayerContingencyMessageTitle = NSLocalizedString("duck-player.contingency-title", value: "Duck Player Unavailable", comment: "Title for message explaining to the user that Duck Player is not available")
static let duckPlayerContingencyMessageBody = NSLocalizedString("duck-player.video-contingency-message", value: "Duck Player's functionality has been affected by recent changes to YouTube. We’re working to fix these issues and appreciate your understanding.", comment: "Message explaining to the user that Duck Player is not available")
static let duckPlayerContingencyMessageCTA = NSLocalizedString("duck-player.video-contingency-cta", value: "Learn More", comment: "Button for the message explaining to the user that Duck Player is not available so the user can learn more")

// MARK: - New Tab Page

// MARK: Shortcuts
Expand Down
9 changes: 9 additions & 0 deletions DuckDuckGo/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,15 @@
/* Message confirming that the download process has started. Parameter is downloaded file's filename */
"downloads.message.download-started" = "Download started for %@";

/* Title for message explaining to the user that Duck Player is not available */
"duck-player.contingency-title" = "Duck Player Unavailable";

/* Button for the message explaining to the user that Duck Player is not available so the user can learn more */
"duck-player.video-contingency-cta" = "Learn More";

/* Message explaining to the user that Duck Player is not available */
"duck-player.video-contingency-message" = "Duck Player's functionality has been affected by recent changes to YouTube. We’re working to fix these issues and appreciate your understanding.";

/* Text displayed when DuckPlayer is always enabled */
"duckPlayer.alwaysEnabled.label" = "Always";

Expand Down

0 comments on commit 6fb037f

Please sign in to comment.