Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[YiR] Share slide #5034

Merged
merged 12 commits into from
Oct 28, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public struct WMFYearInReview: View {
ToolbarItem(placement: .bottomBar) {
HStack(alignment: .center) {
Button(action: {
// TODO: Implement share
viewModel.handleShare(for: currentSlide)
}) {
HStack(alignment: .center, spacing: 6) {
if let uiImage = WMFSFSymbolIcon.for(symbol: .share, font: .semiboldHeadline) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import SwiftUI

struct WMFYearInReviewShareableSlideView: View {

@ObservedObject var appEnvironment = WMFAppEnvironment.current

var theme: WMFTheme {
return appEnvironment.theme
}

var slide: Int
var slideImage: String
var slideTitle: String
var slideSubtitle: String
var hashtag: String
var username: String?

var body: some View {
VStack {
Spacer()
VStack(alignment: .leading, spacing: 16) {
Image(slideImage, bundle: .module)
.frame(maxWidth: .infinity, alignment: .center)
Text(slideTitle)
.font(Font(WMFFont.for(.boldTitle1, compatibleWith: UITraitCollection(preferredContentSizeCategory: .medium))))
.foregroundStyle(Color(uiColor: theme.text))
Text(slideSubtitle)
.font(Font(WMFFont.for(.title3, compatibleWith: UITraitCollection(preferredContentSizeCategory: .medium))))
.foregroundStyle(Color(uiColor: theme.text))
}
.padding(28)
Spacer()
HStack {
Image("globe", bundle: .module)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 50, height: 50)
VStack(alignment: .leading) {
Text(hashtag)
.font(Font(WMFFont.for(.boldTitle3, compatibleWith: UITraitCollection(preferredContentSizeCategory: .medium))))
.foregroundStyle(Color(uiColor: theme.link))

if let username {
Text(username)
.font(Font(WMFFont.for(.georgiaTitle3, compatibleWith: UITraitCollection(preferredContentSizeCategory: .medium))))
.foregroundStyle(Color(uiColor: theme.text))
}
}
Spacer()
}
.padding()
.background(Color(uiColor: theme.paperBackground))
.cornerRadius(12)
.shadow(color: Color.gray.opacity(0.4), radius: 10, x: 0, y: 5)
.padding(.horizontal, 24)
.frame(height: 80)
}
.padding(.bottom, 70)
.background(Color(uiColor: theme.paperBackground))
.frame(width: 402, height: 847) // Fixed iPhone 16 size for iPad as well
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,28 @@ import SwiftUI

public class WMFYearInReviewViewModel: ObservableObject {
@Published var isFirstSlide = true
let localizedStrings: LocalizedStrings
public let localizedStrings: LocalizedStrings
var slides: [YearInReviewSlideContent]
let username: String?
public let shareLink: String
public let hashtag: String
weak var coordinatorDelegate: YearInReviewCoordinatorDelegate?
@Published public var isLoading: Bool = false

public init(localizedStrings: LocalizedStrings, slides: [YearInReviewSlideContent], coordinatorDelegate: YearInReviewCoordinatorDelegate?) {
public init(isFirstSlide: Bool = true, localizedStrings: LocalizedStrings, slides: [YearInReviewSlideContent], username: String?, shareLink: String, hashtag: String, coordinatorDelegate: YearInReviewCoordinatorDelegate?) {
self.isFirstSlide = isFirstSlide
self.localizedStrings = localizedStrings
self.slides = slides
self.username = username
self.shareLink = shareLink
self.hashtag = hashtag
self.coordinatorDelegate = coordinatorDelegate
}

public func getStarted() {
isFirstSlide = false
}

public struct LocalizedStrings {
let donateButtonTitle: String
let doneButtonTitle: String
Expand All @@ -27,8 +34,10 @@ public class WMFYearInReviewViewModel: ObservableObject {
let firstSlideSubtitle: String
let firstSlideCTA: String
let firstSlideHide: String

public init(donateButtonTitle: String, doneButtonTitle: String, shareButtonTitle: String, nextButtonTitle: String, firstSlideTitle: String, firstSlideSubtitle: String, firstSlideCTA: String, firstSlideHide: String) {
public let shareText: String
public let usernameTitle: String

public init(donateButtonTitle: String, doneButtonTitle: String, shareButtonTitle: String, nextButtonTitle: String, firstSlideTitle: String, firstSlideSubtitle: String, firstSlideCTA: String, firstSlideHide: String, shareText: String, usernameTitle: String) {
self.donateButtonTitle = donateButtonTitle
self.doneButtonTitle = doneButtonTitle
self.shareButtonTitle = shareButtonTitle
Expand All @@ -37,7 +46,23 @@ public class WMFYearInReviewViewModel: ObservableObject {
self.firstSlideSubtitle = firstSlideSubtitle
self.firstSlideCTA = firstSlideCTA
self.firstSlideHide = firstSlideHide
self.shareText = shareText
self.usernameTitle = usernameTitle
}

}

func getFomattedUsername() -> String? {
if let username {
return "\(localizedStrings.usernameTitle):\(username)"
}
return nil
}

func handleShare(for slide: Int) {
let view = WMFYearInReviewShareableSlideView(slide: slide, slideImage: slides[slide].imageName, slideTitle: slides[slide].title, slideSubtitle: slides[slide].subtitle, hashtag: hashtag, username: getFomattedUsername())
let shareView = view.snapshot()
coordinatorDelegate?.handleYearInReviewAction(.share(image: shareView))
}
}

Expand All @@ -46,7 +71,7 @@ public struct YearInReviewSlideContent: SlideShowProtocol {
public let title: String
let informationBubbleText: String?
public let subtitle: String

public init(imageName: String, title: String, informationBubbleText: String?, subtitle: String) {
self.imageName = imageName
self.title = title
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import Foundation
import UIKit

public protocol YearInReviewCoordinatorDelegate: AnyObject {
func handleYearInReviewAction(_ action: YearInReviewCoordinatorAction)
}

public enum YearInReviewCoordinatorAction {
case donate(sourceRect: CGRect)
case share(image: UIImage)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import UIKit
import SwiftUI

extension View {
/// Captures a snapshot of the SwiftUI view as a UIImage.
/// - Returns: A snapshot of the SwiftUI view as a UIImage.
func snapshot() -> UIImage {
// Create a UIHostingController hosting the SwiftUI view.
let controller = UIHostingController(rootView: self)

let view = controller.view
let targetSize = controller.view.intrinsicContentSize
view?.bounds = CGRect(origin: .zero, size: targetSize)
view?.backgroundColor = .clear

let renderer = UIGraphicsImageRenderer(size: targetSize)
return renderer.image { _ in
view?.drawHierarchy(in: view!.bounds, afterScreenUpdates: true)
}
}
}
37 changes: 30 additions & 7 deletions Wikipedia/Code/YearInReviewCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ final class YearInReviewCoordinator: NSObject, Coordinator {
let format = WMFLocalizedString("year-in-review-personalized-reading-subtitle-format", value: "You read {{PLURAL:%1$d|%1$d article|%1$d articles}} this year. This year Wikipedia had %2$@ available across over %3$@ this year. You joined millions in expanding knowledge and exploring diverse topics.", comment: "Year in review, personalized reading article count slide subtitle for users that read articles. %1$d is replaced with the number of articles the user read. %2$@ is replaced with the number of articles available across Wikipedia, for example, \"63.59 million articles\". %3$@ is replaced with the number of active languages available on Wikipedia, for example \"332 active languages\"")
return String.localizedStringWithFormat(format, readCount, collectiveNumArticlesText, collectiveNumLanguagesText)
}

func personalizedSlide3Title(editCount: Int) -> String {
let format = WMFLocalizedString("year-in-review-personalized-editing-title-format", value: "You edited Wikipedia {{PLURAL:%1$d|%1$d time|%1$d times}}", comment: "Year in review, personalized editing article count slide title for users that edited articles. %1$d is replaced with the number of edits the user made.")
return String.localizedStringWithFormat(format, editCount)
Expand Down Expand Up @@ -167,7 +167,6 @@ final class YearInReviewCoordinator: NSObject, Coordinator {
firstSlide = readCountSlide
}


if let editCountSlide = personalizedSlides.editCount {
thirdSlide = editCountSlide
}
Expand Down Expand Up @@ -195,10 +194,14 @@ final class YearInReviewCoordinator: NSObject, Coordinator {
firstSlideTitle: WMFLocalizedString("year-in-review-title", value: "Explore your Wikipedia Year in Review", comment: "Year in review page title"),
firstSlideSubtitle: WMFLocalizedString("year-in-review-subtitle", value: "See insights about which articles you read on the Wikipedia app and the edits you made. Share your journey and discover what stood out for you this year. Your reading history is kept protected. Reading insights are calculated using locally stored data on your device.", comment: "Year in review page information"),
firstSlideCTA: WMFLocalizedString("year-in-review-get-started", value: "Get Started", comment: "Button to continue to year in review"),
firstSlideHide: WMFLocalizedString("year-in-review-hide", value: "Hide this feature", comment: "Button to hide year in review feature")
firstSlideHide: WMFLocalizedString("year-in-review-hide", value: "Hide this feature", comment: "Button to hide year in review feature"),
shareText: WMFLocalizedString("year-in-review-share-text", value: "Here's my Wikipedia year in review. Created with the Wikipedia iOS app", comment: "Text shared the Year In Review slides"),
usernameTitle: CommonStrings.userTitle
)

let viewModel = WMFYearInReviewViewModel(localizedStrings: localizedStrings, slides: slides, coordinatorDelegate: self)

let appShareLink = "https://apps.apple.com/app/apple-store/id324715238?pt=208305&ct=yir_2024_share&mt=8"
let hashtag = "#WikipediaYearInReview"
let viewModel = WMFYearInReviewViewModel(localizedStrings: localizedStrings, slides: slides, username: dataStore.authenticationManager.authStatePermanentUsername, shareLink: appShareLink, hashtag: hashtag, coordinatorDelegate: self)

var yirview = WMFYearInReview(viewModel: viewModel)

Expand All @@ -218,10 +221,11 @@ final class YearInReviewCoordinator: NSObject, Coordinator {

navigationController.present(hostingController, animated: true, completion: nil)
}

}

extension YearInReviewCoordinator: YearInReviewCoordinatorDelegate {
func handleYearInReviewAction(_ action: YearInReviewCoordinatorAction) {
func handleYearInReviewAction(_ action: WMFComponents.YearInReviewCoordinatorAction) {
switch action {
case .donate(let rect):
let donateCoordinator = DonateCoordinator(navigationController: navigationController, donateButtonGlobalRect: rect, source: .yearInReview, dataStore: dataStore, theme: theme) { loading in
Expand All @@ -230,7 +234,26 @@ extension YearInReviewCoordinator: YearInReviewCoordinatorDelegate {
}
self.donateCoordinator = donateCoordinator
donateCoordinator.start()
case .share(let image):

guard let viewModel else { return }

let text = "\(viewModel.localizedStrings.shareText) (\(viewModel.shareLink))\(viewModel.hashtag)"

let activityItems: [Any] = [ShareAFactActivityImageItemProvider(image: image), text]

let activityController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil)
activityController.excludedActivityTypes = [.print, .assignToContact, .addToReadingList]

if let visibleVC = self.navigationController.visibleViewController {
if let popover = activityController.popoverPresentationController {
popover.sourceRect = visibleVC.view.bounds
popover.sourceView = visibleVC.view
popover.permittedArrowDirections = []
}

visibleVC.present(activityController, animated: true, completion: nil)
}
}
}

}
1 change: 1 addition & 0 deletions Wikipedia/Localizations/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -1417,6 +1417,7 @@
"year-in-review-personalized-reading-subtitle-format" = "You read {{PLURAL:$1|$1 article|$1 articles}} this year. This year Wikipedia had $2 available across over $3 this year. You joined millions in expanding knowledge and exploring diverse topics.";
"year-in-review-personalized-reading-title- format" = "You read {{PLURAL:$1|$1 article|$1 articles}} this year";
"year-in-review-share" = "Share";
"year-in-review-share-text" = "Here's my Wikipedia year in review. Created with the Wikipedia iOS app";
"year-in-review-subtitle" = "See insights about which articles you read on the Wikipedia app and the edits you made. Share your journey and discover what stood out for you this year. Your reading history is kept protected. Reading insights are calculated using locally stored data on your device.";
"year-in-review-title" = "Explore your Wikipedia Year in Review";
"yir-feature-announcement-body" = "See insights about the articles you read on the Wikipedia app, share your journey, and discover highlights from your year.";
Expand Down
1 change: 1 addition & 0 deletions Wikipedia/Localizations/qqq.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -1417,6 +1417,7 @@
"year-in-review-personalized-reading-subtitle-format" = "Year in review, personalized reading article count slide subtitle for users that read articles. $1 is replaced with the number of articles the user read. $2 is replaced with the number of articles available across Wikipedia, for example, \"63.59 million articles\". $3 is replaced with the number of active languages available on Wikipedia, for example \"332 active languages\"";
"year-in-review-personalized-reading-title- format" = "Year in review, personalized reading article count slide title for users that read articles. $1 is replaced with the number of articles the user read.";
"year-in-review-share" = "Year in review share button";
"year-in-review-share-text" = "Text shared the Year In Review slides";
"year-in-review-subtitle" = "Year in review page information";
"year-in-review-title" = "Year in review page title";
"yir-feature-announcement-body" = "Body for year in review feature announcement";
Expand Down
Binary file modified Wikipedia/iOS Native Localizations/en.lproj/Localizable.strings
Binary file not shown.