Skip to content

Commit

Permalink
Add share streak modal
Browse files Browse the repository at this point in the history
  • Loading branch information
ivan-magda committed Nov 8, 2023
1 parent cf20b45 commit e6e236d
Show file tree
Hide file tree
Showing 22 changed files with 345 additions and 7 deletions.
20 changes: 20 additions & 0 deletions iosHyperskillApp/iosHyperskillApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,9 @@
2C8409532805BF3C009C6BE9 /* StepTheoryContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C8409522805BF3C009C6BE9 /* StepTheoryContentView.swift */; };
2C863D932804279E0021EFED /* Require.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C863D922804279E0021EFED /* Require.swift */; };
2C8CD9AE2994EFC5008DC09D /* DebugFeatureViewStateKsExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C8CD9AD2994EFC5008DC09D /* DebugFeatureViewStateKsExtensions.swift */; };
2C8DD4092AFB7DFD00FD5359 /* ShareStreakModalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C8DD4082AFB7DFD00FD5359 /* ShareStreakModalViewController.swift */; };
2C8DD40C2AFB7E6A00FD5359 /* ShareStreakModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C8DD40B2AFB7E6A00FD5359 /* ShareStreakModalView.swift */; };
2C8DD40E2AFB907000FD5359 /* ShareStreakAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C8DD40D2AFB907000FD5359 /* ShareStreakAction.swift */; };
2C8E4F96284895A30011ADFA /* PanModalPresentableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C8E4F95284895A30011ADFA /* PanModalPresentableViewController.swift */; };
2C8E4F982848961C0011ADFA /* UIViewController+PresentPanModal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C8E4F972848961C0011ADFA /* UIViewController+PresentPanModal.swift */; };
2C8E4F9A284897360011ADFA /* PanModalSwiftUIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C8E4F99284897360011ADFA /* PanModalSwiftUIViewController.swift */; };
Expand Down Expand Up @@ -893,6 +896,9 @@
2C8409522805BF3C009C6BE9 /* StepTheoryContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StepTheoryContentView.swift; sourceTree = "<group>"; };
2C863D922804279E0021EFED /* Require.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Require.swift; sourceTree = "<group>"; };
2C8CD9AD2994EFC5008DC09D /* DebugFeatureViewStateKsExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugFeatureViewStateKsExtensions.swift; sourceTree = "<group>"; };
2C8DD4082AFB7DFD00FD5359 /* ShareStreakModalViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareStreakModalViewController.swift; sourceTree = "<group>"; };
2C8DD40B2AFB7E6A00FD5359 /* ShareStreakModalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareStreakModalView.swift; sourceTree = "<group>"; };
2C8DD40D2AFB907000FD5359 /* ShareStreakAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareStreakAction.swift; sourceTree = "<group>"; };
2C8E4F95284895A30011ADFA /* PanModalPresentableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PanModalPresentableViewController.swift; sourceTree = "<group>"; };
2C8E4F972848961C0011ADFA /* UIViewController+PresentPanModal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+PresentPanModal.swift"; sourceTree = "<group>"; };
2C8E4F99284897360011ADFA /* PanModalSwiftUIViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PanModalSwiftUIViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2408,6 +2414,16 @@
path = PlaceholderView;
sourceTree = "<group>";
};
2C8DD40A2AFB7E3100FD5359 /* ShareStreak */ = {
isa = PBXGroup;
children = (
2C8DD40D2AFB907000FD5359 /* ShareStreakAction.swift */,
2C8DD40B2AFB7E6A00FD5359 /* ShareStreakModalView.swift */,
2C8DD4082AFB7DFD00FD5359 /* ShareStreakModalViewController.swift */,
);
path = ShareStreak;
sourceTree = "<group>";
};
2C8E4F032848788D0011ADFA /* PanModal */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -3634,6 +3650,7 @@
children = (
E9ACD3402937342F0005E05B /* ProblemOfDaySolvedModalViewController.swift */,
E9B55A5C29C978E40066900E /* ProblemsLimitReachedModalViewController.swift */,
2C8DD40A2AFB7E3100FD5359 /* ShareStreak */,
);
path = Modals;
sourceTree = "<group>";
Expand Down Expand Up @@ -4103,6 +4120,7 @@
2C5F19152AE667C90039414D /* LeftAlignedCollectionViewFlowLayout.swift in Sources */,
E993E9A928426FF2005988EC /* StepQuizSortingViewData.swift in Sources */,
E9F59B90289FE053001CEA02 /* ProfileSettingsViewModel.swift in Sources */,
2C8DD40C2AFB7E6A00FD5359 /* ShareStreakModalView.swift in Sources */,
2C967434288824450091B6C9 /* StepQuizCodeView.swift in Sources */,
E94D238F280585110003273F /* AuthCredentialsFormView.swift in Sources */,
2C5CBBE52948FA7400113007 /* StepQuizSQLAssembly.swift in Sources */,
Expand Down Expand Up @@ -4236,6 +4254,7 @@
2C5261A52993CBF100B4E8F6 /* TopicProgressExtensions.swift in Sources */,
2C0DB90728644F2C001EA35E /* CodeEditorView.swift in Sources */,
2CDA98452944590800ADE539 /* ProfileStatisticsView.swift in Sources */,
2C8DD40E2AFB907000FD5359 /* ShareStreakAction.swift in Sources */,
2C7CB6822ADFDB45006F78DA /* UIFont+SizeOfString.swift in Sources */,
2CC4AAF1280DB513002276A0 /* WebOAuthService.swift in Sources */,
2CF2DA3A27EC5B2D0055426D /* Assembly.swift in Sources */,
Expand Down Expand Up @@ -4606,6 +4625,7 @@
ECD10958C8BA7D758D3D1F66 /* ProjectSelectionDetailsAssembly.swift in Sources */,
018CAC44EED7A992000ECF87 /* ProjectSelectionDetailsView.swift in Sources */,
AE0B2D1D267B8904498FA371 /* ProjectSelectionDetailsViewModel.swift in Sources */,
2C8DD4092AFB7DFD00FD5359 /* ShareStreakModalViewController.swift in Sources */,
0809817CFCC9D4C45457B3C8 /* ProgressScreenAssembly.swift in Sources */,
59B66CD4D1508049555D35AE /* ProgressScreenView.swift in Sources */,
2CE7B4842AB0593F00DCBE4D /* AttributedTextLabelWrapper.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "share-streak-day-1.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "share-streak-day-10.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "share-streak-day-100.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "share-streak-day-25.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "share-streak-day-5.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "share-streak-day-50.png",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,15 @@ enum Strings {
enum ProblemsLimitReachedModal {
static let title = sharedStrings.problems_limit_reached_modal_title.localized()
}

enum ShareStreakModal {
static let title = sharedStrings.share_streak_modal_title.localized()
static let shareButton = sharedStrings.share_streak_modal_share_button_text.localized()
static let noThanksButton = sharedStrings.share_streak_modal_no_thanks_button_text.localized()

static let sharingText = sharedStrings.share_streak_sharing_text.localized()
static let sharingURL = sharedStrings.share_streak_sharing_url.localized()
}
}

// MARK: - StepQuizChoice -
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,45 @@ extension StepViewModel: ProblemOfDaySolvedModalViewControllerDelegate {
)
}
}

// MARK: - StepViewModel: ShareStreakModalViewControllerDelegate -

extension StepViewModel: ShareStreakModalViewControllerDelegate {
func shareStreakModalViewControllerDidAppear(_ viewController: ShareStreakModalViewController, streak: Int) {
onNewMessage(
StepFeatureMessageStepCompletionMessage(
message: StepCompletionFeatureMessageShareStreakModalShownEventMessage(streak: Int32(streak))
)
)
}

func shareStreakModalViewControllerDidDisappear(_ viewController: ShareStreakModalViewController, streak: Int) {
onNewMessage(
StepFeatureMessageStepCompletionMessage(
message: StepCompletionFeatureMessageShareStreakModalHiddenEventMessage(streak: Int32(streak))
)
)
}

func shareStreakModalViewControllerDidTapShareButton(
_ viewController: ShareStreakModalViewController,
streak: Int
) {
onNewMessage(
StepFeatureMessageStepCompletionMessage(
message: StepCompletionFeatureMessageShareStreakModalShareClicked(streak: Int32(streak))
)
)
}

func shareStreakModalViewControllerDidTapNoThanksButton(
_ viewController: ShareStreakModalViewController,
streak: Int
) {
onNewMessage(
StepFeatureMessageStepCompletionMessage(
message: StepCompletionFeatureMessageShareStreakModalNoThanksClickedEventMessage(streak: Int32(streak))
)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,10 @@ struct StepView: View {
streakText: showProblemOfDaySolvedModalViewAction.streakText,
streak: showProblemOfDaySolvedModalViewAction.streak?.intValue
)
case .showShareStreakModal:
#warning("TODO: ALTAPPS-1027 Show share streak modal")
case .showShareStreakSystemModal:
#warning("TODO: ALTAPPS-1027 Show system share streak modal")
case .showShareStreakModal(let showShareStreakModalViewAction):
presentShareStreakModal(streak: Int(showShareStreakModalViewAction.streak))
case .showShareStreakSystemModal(let showShareStreakSystemModalViewAction):
presentShareStreakSystemModal(streak: Int(showShareStreakSystemModalViewAction.streak))
}
}

Expand Down Expand Up @@ -164,6 +164,19 @@ extension StepView {
)
panModalPresenter.presentPanModal(modal)
}

private func presentShareStreakModal(streak: Int) {
let modal = ShareStreakModalViewController(
streak: streak,
delegate: viewModel
)
panModalPresenter.presentPanModal(modal)
}

private func presentShareStreakSystemModal(streak: Int) {
let activityViewController = ShareStreakAction.makeActivityViewController(for: streak)
modalRouter.present(module: activityViewController, modalPresentationStyle: .automatic)
}
}

// MARK: - StepView (Alerts) -
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import Foundation
import UIKit

enum ShareStreakAction {
static func image(for streak: Int) -> UIImage? {
let imageName = "share-streak-day-\(streak)"
let image = UIImage(named: imageName)

#if DEBUG
if image == nil {
assertionFailure("ShareStreakAction: image for \(imageName) not found")
}
#endif

return image
}

static func makeActivityViewController(for streak: Int) -> UIActivityViewController {
var items: [Any] = [
ShareStreakActivityItemSource()
]
if let image = image(for: streak) {
items.append(image)
}

let activityViewController = UIActivityViewController(
activityItems: items,
applicationActivities: nil
)
activityViewController.excludedActivityTypes = [.airDrop]

return activityViewController
}
}

private final class ShareStreakActivityItemSource: NSObject, UIActivityItemSource {
func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
let urlString = Strings.StepQuiz.ShareStreakModal.sharingURL
return URL(string: urlString) ?? urlString
}

func activityViewController(
_ activityViewController: UIActivityViewController,
itemForActivityType activityType: UIActivity.ActivityType?
) -> Any? {
guard activityType?.rawValue != "com.burbn.instagram.shareextension" else {
return nil
}

return "\(Strings.StepQuiz.ShareStreakModal.sharingText)\n\(Strings.StepQuiz.ShareStreakModal.sharingURL)"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import SwiftUI

extension ShareStreakModalView {
struct Appearance {
let spacing = LayoutInsets.defaultInset * 2
let actionButtonsSpacing = LayoutInsets.defaultInset
}
}

struct ShareStreakModalView: View {
private(set) var appearance = Appearance()

let streak: Int

var onShareButtonTap: (() -> Void)?
var onNoThanksButtonTap: (() -> Void)?

var body: some View {
VStack(alignment: .leading, spacing: appearance.spacing) {
Text(Strings.StepQuiz.ShareStreakModal.title)
.foregroundColor(.primaryText)
.font(.title2)
.bold()

Image(uiImage: ShareStreakAction.image(for: streak))
.renderingMode(.original)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxWidth: .infinity)

VStack(spacing: appearance.actionButtonsSpacing) {
Button(
Strings.StepQuiz.ShareStreakModal.shareButton,
action: { onShareButtonTap?() }
)
.buttonStyle(RoundedRectangleButtonStyle(style: .violet))

Button(
Strings.StepQuiz.ShareStreakModal.noThanksButton,
action: { onNoThanksButtonTap?() }
)
.buttonStyle(OutlineButtonStyle(style: .violet))
}
}
.padding()
}
}

#Preview {
ShareStreakModalView(streak: 1)
}
Loading

0 comments on commit e6e236d

Please sign in to comment.