Skip to content

Commit

Permalink
feat: App navigational flow for deep links/push notifications (#329)
Browse files Browse the repository at this point in the history
* chore: add router to deep link manager

* chore: add deep link router

* chore: add discussion threads

* chore: program, discovery details, user profile

* chore:  disable animation for progress and refactor

* chore: move deep link router to folder

* chore: show user profile as sheet

* chore: fix close presented screen

* chore: not open again programs or discovery content

* chore: improve deep link navigation

* chore: improve deep link navigation

* chore: improve deep link navigation

* chore: check if ids isEmpty

* chore: add open announcement

* chore: improve deep link discussion

* chore: remove empty line

* chore: generate test files

* chore: remove extra codes and add strings

* chore: resolve PR commnets

* chore: resolve PR comments

* chore:  avatar can be changed in "limited profile" mode

* chore: make dashboard as default tab
  • Loading branch information
eyatsenkoperpetio authored Mar 15, 2024
1 parent a08380e commit 016cf09
Show file tree
Hide file tree
Showing 52 changed files with 1,611 additions and 394 deletions.
46 changes: 24 additions & 22 deletions Authorization/AuthorizationTests/AuthorizationMock.generated.swift

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions Core/Core.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@
BA8FA66C2AD59BBC00EA029A /* GoogleSignIn in Frameworks */ = {isa = PBXBuildFile; productRef = BA8FA66B2AD59BBC00EA029A /* GoogleSignIn */; };
BA8FA66E2AD59E7D00EA029A /* FacebookAuthProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA8FA66D2AD59E7D00EA029A /* FacebookAuthProvider.swift */; };
BA8FA6702AD59EA300EA029A /* MicrosoftAuthProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA8FA66F2AD59EA300EA029A /* MicrosoftAuthProvider.swift */; };
BA981BCE2B8F5C49005707C2 /* Sequence+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA981BCD2B8F5C49005707C2 /* Sequence+Extensions.swift */; };
BA981BD02B91ED50005707C2 /* FullScreenProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA981BCF2B91ED50005707C2 /* FullScreenProgressView.swift */; };
BAAD62C62AFCF00B000E6103 /* CustomDisclosureGroup.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAAD62C52AFCF00B000E6103 /* CustomDisclosureGroup.swift */; };
BAD9CA2F2B289B3500DE790A /* ajaxHandler.js in Resources */ = {isa = PBXBuildFile; fileRef = BAD9CA2E2B289B3500DE790A /* ajaxHandler.js */; };
BAD9CA332B28A8F300DE790A /* AjaxProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = BAD9CA322B28A8F300DE790A /* AjaxProvider.swift */; };
Expand Down Expand Up @@ -321,6 +323,8 @@
BA8FA6692AD59B5500EA029A /* GoogleAuthProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoogleAuthProvider.swift; sourceTree = "<group>"; };
BA8FA66D2AD59E7D00EA029A /* FacebookAuthProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FacebookAuthProvider.swift; sourceTree = "<group>"; };
BA8FA66F2AD59EA300EA029A /* MicrosoftAuthProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MicrosoftAuthProvider.swift; sourceTree = "<group>"; };
BA981BCD2B8F5C49005707C2 /* Sequence+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Sequence+Extensions.swift"; sourceTree = "<group>"; };
BA981BCF2B91ED50005707C2 /* FullScreenProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FullScreenProgressView.swift; sourceTree = "<group>"; };
BAAD62C52AFCF00B000E6103 /* CustomDisclosureGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomDisclosureGroup.swift; sourceTree = "<group>"; };
BAD9CA2E2B289B3500DE790A /* ajaxHandler.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = ajaxHandler.js; sourceTree = "<group>"; };
BAD9CA322B28A8F300DE790A /* AjaxProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AjaxProvider.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -456,6 +460,7 @@
BADB3F5A2AD6EC56004D5CFA /* ResultExtension.swift */,
02D400602B0678190029D168 /* SKStoreReviewControllerExtension.swift */,
E0D5861B2B2FF85B009B4BA7 /* RawStringExtactable.swift */,
BA981BCD2B8F5C49005707C2 /* Sequence+Extensions.swift */,
);
path = Extensions;
sourceTree = "<group>";
Expand Down Expand Up @@ -701,6 +706,7 @@
BAAD62C52AFCF00B000E6103 /* CustomDisclosureGroup.swift */,
BA8FA6672AD59A5700EA029A /* SocialAuthButton.swift */,
02E93F862AEBAED4006C4750 /* AppReview */,
BA981BCF2B91ED50005707C2 /* FullScreenProgressView.swift */,
);
path = Base;
sourceTree = "<group>";
Expand Down Expand Up @@ -1028,6 +1034,7 @@
BAFB99822B0E2354007D09F9 /* FacebookConfig.swift in Sources */,
027BD3B32909475900392132 /* Publishers+KeyboardState.swift in Sources */,
0727877D28D25212002E9142 /* ProgressBar.swift in Sources */,
BA981BD02B91ED50005707C2 /* FullScreenProgressView.swift in Sources */,
0236961F28F9A2F600EEF206 /* AuthEndpoint.swift in Sources */,
02B3E3B32930198600A50475 /* AVPlayerViewControllerExtension.swift in Sources */,
BAD9CA332B28A8F300DE790A /* AjaxProvider.swift in Sources */,
Expand Down Expand Up @@ -1063,6 +1070,7 @@
076F297F2A1F80C800967E7D /* Pagination.swift in Sources */,
02AFCC1A2AEFDC18000360F0 /* ThirdPartyMailer.swift in Sources */,
0770DE5F28D0B22C006D8A5D /* Strings.swift in Sources */,
BA981BCE2B8F5C49005707C2 /* Sequence+Extensions.swift in Sources */,
02C917F029CDA99E00DBB8BD /* Data_Dashboard.swift in Sources */,
024FCD0028EF1CD300232339 /* WebBrowser.swift in Sources */,
027BD3B52909475900392132 /* KeyboardStateObserver.swift in Sources */,
Expand Down
4 changes: 2 additions & 2 deletions Core/Core/Configuration/BaseRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public protocol BaseRouter {

func presentView(transitionStyle: UIModalTransitionStyle, view: any View)

func presentView(transitionStyle: UIModalTransitionStyle, content: () -> any View)
func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View)

}

Expand Down Expand Up @@ -123,7 +123,7 @@ open class BaseRouterMock: BaseRouter {

public func presentView(transitionStyle: UIModalTransitionStyle, view: any View) {}

public func presentView(transitionStyle: UIModalTransitionStyle, content: () -> any View) {}
public func presentView(transitionStyle: UIModalTransitionStyle, animated: Bool, content: () -> any View) {}

}
#endif
1 change: 1 addition & 0 deletions Core/Core/Extensions/Notification.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ public extension Notification.Name {
static let webviewReloadNotification = Notification.Name("webviewReloadNotification")
static let onBlockCompletion = Notification.Name.init("onBlockCompletion")
static let shiftCourseDates = Notification.Name("shiftCourseDates")
static let profileUpdated = Notification.Name("profileUpdated")
}
2 changes: 1 addition & 1 deletion Core/Core/Extensions/RawStringExtactable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ extension Dictionary: DictionaryExtractionExtension {}

public extension DictionaryExtractionExtension where Self.Key == String {

subscript(key :RawStringExtractable) -> Value? {
subscript(key: RawStringExtractable) -> Value? {
return self[key.rawValue]
}
}
14 changes: 14 additions & 0 deletions Core/Core/Extensions/Sequence+Extensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// Sequence+Extensions.swift
// Core
//
// Created by Eugene Yatsenko on 28.02.2024.
//

import Foundation

public extension Sequence {
func firstAs<T>(_ type: T.Type = T.self) -> T? {
first { $0 is T } as? T
}
}
16 changes: 15 additions & 1 deletion Core/Core/Extensions/ViewExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -258,10 +258,24 @@ public extension View {

public extension View {
@ViewBuilder
func sheetNavigation(isSheet: Bool) -> some View {
func sheetNavigation(isSheet: Bool, onDismiss: (() -> Void)? = nil) -> some View {
if isSheet {
NavigationView {
self
.if(onDismiss != nil) { view in
view
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
Button {
onDismiss?()
} label: {
Image(systemName: "xmark")
.foregroundColor(Theme.Colors.accentColor)
}
.accessibilityIdentifier("close_button")
}
}
}
}
} else {
self
Expand Down
2 changes: 2 additions & 0 deletions Core/Core/SwiftGen/Strings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public enum CoreLocalization {
public static let socialSignCanceled = CoreLocalization.tr("Localizable", "SOCIAL_SIGN_CANCELED", fallback: "The user canceled the sign-in flow.")
/// Tomorrow
public static let tomorrow = CoreLocalization.tr("Localizable", "TOMORROW", fallback: "Tomorrow")
/// View
public static let view = CoreLocalization.tr("Localizable", "VIEW ", fallback: "View")
/// Yesterday
public static let yesterday = CoreLocalization.tr("Localizable", "YESTERDAY", fallback: "Yesterday")
public enum Alert {
Expand Down
147 changes: 81 additions & 66 deletions Core/Core/View/Base/AlertView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ public enum AlertViewType: Equatable {
case logOut
case leaveProfile
case deleteVideo
case deepLink

var contentPadding: CGFloat {
switch self {
case .`default`:
return 16
case .action, .logOut, .leaveProfile, .deleteVideo:
case .action, .logOut, .leaveProfile, .deleteVideo, .deepLink:
return 36
}
}
Expand Down Expand Up @@ -146,15 +147,14 @@ public struct AlertView: View {
.multilineTextAlignment(.center)
.padding(.horizontal, 40)
.frame(maxWidth: 250)
case .leaveProfile, .deleteVideo:
case .leaveProfile, .deleteVideo, .deepLink:
VStack(spacing: 20) {
if type == .deleteVideo {
CoreAssets.warning.swiftUIImage.renderingMode(.template)
.foregroundColor(Theme.Colors.textPrimary)
switch type {
case .deleteVideo, .deepLink:
CoreAssets.warning.swiftUIImage
.padding(.top, isHorizontal ? 20 : 54)
} else {
CoreAssets.leaveProfile.swiftUIImage.renderingMode(.template)
.foregroundColor(Theme.Colors.textPrimary)
default:
CoreAssets.leaveProfile.swiftUIImage
.padding(.top, isHorizontal ? 20 : 54)
}
Text(alertTitle)
Expand Down Expand Up @@ -353,69 +353,84 @@ public struct AlertView: View {
}
.padding(.trailing, isHorizontal ? 20 : 0)
case .deleteVideo:
VStack(spacing: 0) {
Button {
okTapped()
} label: {
ZStack {
Text(CoreLocalization.Alert.delete)
.foregroundColor(Theme.Colors.primaryButtonTextColor)
.font(Theme.Fonts.labelLarge)
.frame(maxWidth: .infinity)
.padding(.horizontal, 16)
}
.frame(maxWidth: 215, minHeight: 48)
}
.background(
Theme.Shapes.buttonShape
.fill(Theme.Colors.accentColor)
)
.overlay(
RoundedRectangle(cornerRadius: 8)
.stroke(style: .init(
lineWidth: 1,
lineCap: .round,
lineJoin: .round,
miterLimit: 1
))
.foregroundColor(.clear)
)
.frame(maxWidth: 215)
.padding(.bottom, isHorizontal ? 10 : 24)
Button(action: {
onCloseTapped()
}, label: {
ZStack {
Text(CoreLocalization.Alert.cancel)
.foregroundColor(Theme.Colors.secondaryButtonTextColor)
.font(Theme.Fonts.labelLarge)
.frame(maxWidth: .infinity)
.padding(.horizontal, 16)
}
.frame(maxWidth: 215, minHeight: 48)
})
.background(
Theme.Shapes.buttonShape
.fill(.clear)
)
.overlay(
RoundedRectangle(cornerRadius: 8)
.stroke(style: .init(
lineWidth: 1,
lineCap: .round,
lineJoin: .round,
miterLimit: 1
))
.foregroundColor(Theme.Colors.secondaryButtonBorderColor)
)
.frame(maxWidth: 215)
}
.padding(.trailing, isHorizontal ? 20 : 0)
configure(
primaryButtonTitle: CoreLocalization.Alert.delete,
secondaryButtonTitle: CoreLocalization.Alert.cancel
)
case .deepLink:
configure(
primaryButtonTitle: CoreLocalization.view,
secondaryButtonTitle: CoreLocalization.Alert.cancel
)
}
}
.padding(.top, 16)
.padding(.bottom, isHorizontal ? 16 : type.contentPadding)
}

private func configure(
primaryButtonTitle: String,
secondaryButtonTitle: String
) -> some View {
VStack(spacing: 0) {
Button {
okTapped()
} label: {
ZStack {
Text(primaryButtonTitle)
.foregroundColor(Theme.Colors.primaryButtonTextColor)
.font(Theme.Fonts.labelLarge)
.frame(maxWidth: .infinity)
.padding(.horizontal, 16)
}
.frame(maxWidth: 215, minHeight: 48)
}
.background(
Theme.Shapes.buttonShape
.fill(Theme.Colors.accentColor)
)
.overlay(
RoundedRectangle(cornerRadius: 8)
.stroke(style: .init(
lineWidth: 1,
lineCap: .round,
lineJoin: .round,
miterLimit: 1
))
.foregroundColor(.clear)
)
.frame(maxWidth: 215)
.padding(.bottom, isHorizontal ? 10 : 24)
Button(action: {
onCloseTapped()
}, label: {
ZStack {
Text(secondaryButtonTitle)
.foregroundColor(Theme.Colors.secondaryButtonTextColor)
.font(Theme.Fonts.labelLarge)
.frame(maxWidth: .infinity)
.padding(.horizontal, 16)
}
.frame(maxWidth: 215, minHeight: 48)
})
.background(
Theme.Shapes.buttonShape
.fill(.clear)
)
.overlay(
RoundedRectangle(cornerRadius: 8)
.stroke(style: .init(
lineWidth: 1,
lineCap: .round,
lineJoin: .round,
miterLimit: 1
))
.foregroundColor(Theme.Colors.secondaryButtonBorderColor)
)
.frame(maxWidth: 215)
}
.padding(.trailing, isHorizontal ? 20 : 0)
}
}

// swiftlint:disable all
Expand Down
51 changes: 51 additions & 0 deletions Core/Core/View/Base/FullScreenProgressView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// FullScreenProgressView.swift
// Core
//
// Created by Eugene Yatsenko on 01.03.2024.
//

import SwiftUI
import Theme

public struct FullScreenProgressView: View {

@Environment(\.dismiss) private var dismiss

public init() {}

public var body: some View {
ZStack(alignment: .center) {
Color.black.opacity(0.8)
.onTapGesture {
dismiss()
}
VStack(alignment: .center) {
ProgressBar(size: 40, lineWidth: 8)
.padding(.horizontal)
.padding(.vertical, 50)
}
.frame(maxWidth: 140)
.background(
Theme.Shapes.cardShape
.fill(Theme.Colors.cardViewBackground)
.shadow(radius: 24)
.fixedSize(horizontal: false, vertical: false)
)
.overlay(
RoundedRectangle(cornerRadius: 12)
.stroke(
style: .init(
lineWidth: 1,
lineCap: .round,
lineJoin: .round,
miterLimit: 1
)
)
.foregroundColor(Theme.Colors.backgroundStroke)
.fixedSize(horizontal: false, vertical: false)
)
}
.ignoresSafeArea()
}
}
5 changes: 4 additions & 1 deletion Core/Core/View/Base/PickerView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ public struct PickerView: View {
Animation.easeInOut(duration: 0.3)
) {
let pickerItems = config.field.options.map { PickerItem(key: $0.value, value: $0.name) }
router.presentView(transitionStyle: .crossDissolve) {
router.presentView(
transitionStyle: .crossDissolve,
animated: true
) {
PickerMenu(items: pickerItems,
titleText: config.field.label,
router: router,
Expand Down
1 change: 1 addition & 0 deletions Core/Core/en.lproj/Localizable.strings
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
"SETTINGS.DOWNLOAD_QUALITY_720_DESCRIPTION" = "Best quality";

"DONE" = "Done";
"VIEW " = "View";

"PICKER.SEARCH" = "Search";
"PICKER.ACCEPT" = "Accept";
Expand Down
2 changes: 1 addition & 1 deletion Course/Course/Domain/Model/CourseUpdate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import Foundation

public struct CourseUpdate {
public struct CourseUpdate: Hashable {
public let id: Int
public let date: String
public var content: String
Expand Down
Loading

0 comments on commit 016cf09

Please sign in to comment.