Skip to content

Commit

Permalink
Merge branch 'trunk' into danieleb/Winback/2444-2445-current-subscrip…
Browse files Browse the repository at this point in the history
…tion-screen
  • Loading branch information
danielebogo committed Nov 25, 2024
2 parents 26cd2f9 + 735a65d commit 85131bd
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 10 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- Fix background sync when more than 2000 episodes are changed [#2448](https://github.com/Automattic/pocket-casts-ios/pull/2448)
- File downloads use switch instead of check box for include starred [#2455](https://github.com/Automattic/pocket-casts-ios/pull/2455)
- Show download management banner and modal when running low in disk space [#2430](https://github.com/Automattic/pocket-casts-ios/pull/2430)
- Referrals: update share message and add image [#2468](https://github.com/Automattic/pocket-casts-ios/pull/2468)

7.77
-----
Expand Down
3 changes: 1 addition & 2 deletions Dangerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
github.dismiss_out_of_range_messages

# `files: []` forces rubocop to scan all files, not just the ones modified in the PR
# Added a custom `rubocop_cmd` to prevent RuboCop from running using `bundle exec`, which we don't want on the linter agent
rubocop.lint(files: [], force_exclusion: true, inline_comment: true, fail_on_inline_comment: true, include_cop_names: true, rubocop_cmd: ': | rubocop')
rubocop.lint(files: [], force_exclusion: true, inline_comment: true, fail_on_inline_comment: true, include_cop_names: true)

manifest_pr_checker.check_all_manifest_lock_updated

Expand Down
2 changes: 1 addition & 1 deletion config/Version.xcconfig
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
VERSION_LONG = 7.77.0.5
VERSION_LONG = 7.77.0.6
VERSION_SHORT = 7.77
2 changes: 2 additions & 0 deletions podcasts/End of Year/EndOfYear.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ struct EndOfYear {
storyModelType = Self.currentYear.modelType
}


func showPrompt(in viewController: UIViewController) {
guard Self.isEligible, let storyModelType, !Settings.hasShownModalForEndOfYear(storyModelType.year) else {
return
Expand All @@ -105,6 +106,7 @@ struct EndOfYear {
}

BottomSheetSwiftUIWrapper.present(EndOfYearModal(year: storyModelType.year, model: viewModel), autoSize: true, in: viewController)
Settings.setHasShownModalForEndOfYear(true, year: storyModelType.year)
}

func showPromptBasedOnState(in viewController: UIViewController) {
Expand Down
12 changes: 7 additions & 5 deletions podcasts/Referrals/ReferralCardView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ struct ReferralCardView: View {
.overlay {
ReferralCardAnimatedGradientView()
}
.cornerRadius(Constants.cardRadius)
.overlay(alignment: .bottomLeading) {
Text(L10n.referralsGuestPassOffer(offerDuration))
.font(size: 12, style: .body, weight: .semibold)
Expand All @@ -32,9 +31,9 @@ struct ReferralCardView: View {
}
.overlay(
RoundedRectangle(cornerRadius: Constants.cardRadius)
.inset(by: -0.5)
.stroke(Constants.cardStrokeColor, lineWidth: 1)
.stroke(Constants.cardStrokeColor)
)
.cornerRadius(Constants.cardRadius)
}

enum Constants {
Expand All @@ -46,6 +45,9 @@ struct ReferralCardView: View {
}

#Preview {
ReferralCardView(offerDuration: "2-Month")
.frame(width: 315, height: 200)
HStack {
ReferralCardView(offerDuration: "2-Month")
.frame(width: 315, height: 200)
}
.background(.white)
}
65 changes: 65 additions & 0 deletions podcasts/Referrals/ReferralSendPassVC.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import Foundation
import LinkPresentation
import SwiftUI
import PocketCastsServer

class ReferralSendPassVC: ThemedHostingController<ReferralSendPassView> {

Expand Down Expand Up @@ -36,6 +38,9 @@ class ReferralSendPassVC: ThemedHostingController<ReferralSendPassView> {
if let url = viewModel.referralURL {
items.append(url)
}
if let imageSource = ImageShareSource(image: snapshot(), title: viewModel.shareSubject) {
items.append(imageSource)
}
let viewController = UIActivityViewController(activityItems: items, applicationActivities: nil)
viewController.completionWithItemsHandler = { _, completed, _, _ in
if completed {
Expand All @@ -60,6 +65,12 @@ class ReferralSendPassVC: ThemedHostingController<ReferralSendPassView> {
super.viewWillLayoutSubviews()
popoverVC?.sourceRect = centerBottomSourceRect
}

func snapshot() -> UIImage {
return ReferralCardView(offerDuration: viewModel.offerInfo.localizedOfferDurationAdjective)
.frame(width: ReferralCardView.Constants.defaultCardSize.width, height: ReferralCardView.Constants.defaultCardSize.height)
.snapshot(scale: 2)
}
}

class TextAndURLShareSource: NSObject, UIActivityItemSource {
Expand Down Expand Up @@ -94,3 +105,57 @@ extension TextAndURLShareSource {
return TextAndURLShareSource(url: viewModel.referralURL, text: viewModel.shareText, subject: viewModel.shareSubject)
}
}

class ImageShareSource: NSObject, UIActivityItemSource {
private let image: UIImage
private let url: URL?
private let title: String

init?(image: UIImage, title: String) {
self.title = title
self.image = image
if let data = image.pngData(),
let url = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first?.appendingPathComponent(UUID().uuidString + ".png") {
do {
try data.write(to: url)
self.url = url
}
catch {
self.url = nil
}
} else {
self.url = nil
}
}

func activityViewControllerPlaceholderItem(_: UIActivityViewController) -> Any {
return image
}

func activityViewController(_: UIActivityViewController, itemForActivityType type: UIActivity.ActivityType?) -> Any? {
// Instagram and twitter don't like to have an URL and image at the same time, so we are ignoring the image for those.
if type?.rawValue == "com.burbn.instagram.shareextension" || type == .postToTwitter {
return nil
}
return url
}

func activityViewController(_: UIActivityViewController, dataTypeIdentifierForActivityType _: UIActivity.ActivityType?) -> String {
return UTType.image.identifier
}

func activityViewController(_: UIActivityViewController, thumbnailImageForActivityType _: UIActivity.ActivityType?, suggestedSize size: CGSize) -> UIImage? {
image.resized(to: size)
}

func activityViewControllerLinkMetadata(_: UIActivityViewController) -> LPLinkMetadata? {
let metadata = LPLinkMetadata()

metadata.originalURL = URL(string: ServerConstants.Urls.pocketcastsDotCom)
metadata.url = URL(string: ServerConstants.Urls.pocketcastsDotCom)
metadata.title = title
metadata.imageProvider = NSItemProvider.init(contentsOf: url)

return metadata
}
}
2 changes: 1 addition & 1 deletion podcasts/Referrals/ReferralSendPassView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class ReferralSendPassModel: ObservableObject {
}

var shareText: String {
L10n.referralsSharePassMessage(self.offerInfo.localizedOfferDurationAdjective)
L10n.referralsSharePassLongMessage(self.offerInfo.localizedOfferDurationAdjective)
}

var shareSubject: String {
Expand Down
7 changes: 7 additions & 0 deletions podcasts/Strings+Generated.swift

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion podcasts/Zendesk/MessageSupportViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,16 @@ class MessageSupportViewModel: ObservableObject {
if containsWatch && customFields.first(where: { $0.value.contains(FileLog.noWearableLogsAvailable) }) != nil && !ignoreUnavailableWatchLogs {
return Fail(error: MessageSupportFailure.watchLogMissing).eraseToAnyPublisher()
} else {
let hasLogs = customFields.contains(where: { $0.id == SupportCustomField.debugLog.rawValue && !$0.value.hasSuffix("User opted out")})
var extraText = ""
if hasLogs {
extraText = "\n\nNote: Logs Attached"
}

let requestObject = ZDSupportRequest(subject: self.config.subject,
name: self.requesterName,
email: self.requesterEmail,
comment: self.comment,
comment: self.comment + extraText,
customFields: customFields,
tags: self.config.tags)

Expand Down
4 changes: 4 additions & 0 deletions podcasts/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -4683,3 +4683,7 @@

/* Title for the claim offer button */
"cancel_subscription_claim_offer_button" = "Claim offer";

/* Referrals - Share Pass message. `%1$@' is a placeholder for the duration of free period offered on the Plus subscription*/
"referrals_share_pass_long_message" = "Hi there!\n\nHere is a %1$@ guest pass for Pocket Casts Plus–my favorite podcast player. It's packed with unique features like bookmarks, folders, and more that you won't find anywhere else. I think you'll love it too!\n";

0 comments on commit 85131bd

Please sign in to comment.