Skip to content

Commit

Permalink
feat: Program Screen Error Handling
Browse files Browse the repository at this point in the history
  • Loading branch information
shafqat-muneer committed Jun 5, 2024
1 parent d8a7b46 commit aaf0cee
Show file tree
Hide file tree
Showing 10 changed files with 238 additions and 74 deletions.
12 changes: 12 additions & 0 deletions Core/Core.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@
141F1D302B7328D4009E81EB /* WebviewCookiesUpdateProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 141F1D2F2B7328D4009E81EB /* WebviewCookiesUpdateProtocol.swift */; };
142EDD6C2B831D1400F9F320 /* BranchSDK in Frameworks */ = {isa = PBXBuildFile; productRef = 142EDD6B2B831D1400F9F320 /* BranchSDK */; };
14769D3C2B9822EE00AB36D4 /* CoreAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14769D3B2B9822EE00AB36D4 /* CoreAnalytics.swift */; };
9784D47E2BF7762800AFEFFF /* FullScreenErrorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9784D47D2BF7762800AFEFFF /* FullScreenErrorView.swift */; };
A51CDBE72B6D21F2009B6D4E /* SegmentConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51CDBE62B6D21F2009B6D4E /* SegmentConfig.swift */; };
A53A32352B233DEC005FE38A /* ThemeConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A53A32342B233DEC005FE38A /* ThemeConfig.swift */; };
A595689B2B6173DF00ED4F90 /* BranchConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = A595689A2B6173DF00ED4F90 /* BranchConfig.swift */; };
Expand Down Expand Up @@ -340,6 +341,7 @@
349B90CD6579F7B8D257E515 /* Pods_App_Core.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_App_Core.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3B74C6685E416657F3C5F5A8 /* Pods-App-Core.releaseprod.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Core.releaseprod.xcconfig"; path = "Target Support Files/Pods-App-Core/Pods-App-Core.releaseprod.xcconfig"; sourceTree = "<group>"; };
60153262DBC2F9E660D7E11B /* Pods-App-Core.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Core.release.xcconfig"; path = "Target Support Files/Pods-App-Core/Pods-App-Core.release.xcconfig"; sourceTree = "<group>"; };
9784D47D2BF7762800AFEFFF /* FullScreenErrorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FullScreenErrorView.swift; sourceTree = "<group>"; };
9D5B06CAA99EA5CD49CBE2BB /* Pods-App-Core.debugdev.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-App-Core.debugdev.xcconfig"; path = "Target Support Files/Pods-App-Core/Pods-App-Core.debugdev.xcconfig"; sourceTree = "<group>"; };
A51CDBE62B6D21F2009B6D4E /* SegmentConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegmentConfig.swift; sourceTree = "<group>"; };
A53A32342B233DEC005FE38A /* ThemeConfig.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThemeConfig.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -717,6 +719,7 @@
0770DE7728D0C49E006D8A5D /* Base */ = {
isa = PBXGroup;
children = (
9784D47C2BF7761F00AFEFFF /* FullScreenErrorView */,
064987882B4D69FE0071642A /* Webview */,
E0D586352B314CD3009B4BA7 /* LogistrationBottomView.swift */,
02A4833B29B8C57800D33F33 /* DownloadView.swift */,
Expand Down Expand Up @@ -769,6 +772,14 @@
path = Analytics;
sourceTree = "<group>";
};
9784D47C2BF7761F00AFEFFF /* FullScreenErrorView */ = {
isa = PBXGroup;
children = (
9784D47D2BF7762800AFEFFF /* FullScreenErrorView.swift */,
);
path = FullScreenErrorView;
sourceTree = "<group>";
};
BA30427C2B20B235009B64B7 /* SocialAuth */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -1127,6 +1138,7 @@
0260E58028FD792800BBBE18 /* WebUnitViewModel.swift in Sources */,
02A4833A29B8A9AB00D33F33 /* DownloadManager.swift in Sources */,
06078B702BA49C3100576798 /* Dictionary+JSON.swift in Sources */,
9784D47E2BF7762800AFEFFF /* FullScreenErrorView.swift in Sources */,
027BD3AE2909475000392132 /* KeyboardScrollerOptions.swift in Sources */,
BAFB99922B14E23D007D09F9 /* AppleSignInConfig.swift in Sources */,
141F1D302B7328D4009E81EB /* WebviewCookiesUpdateProtocol.swift in Sources */,
Expand Down
96 changes: 96 additions & 0 deletions Core/Core/View/Base/FullScreenErrorView/FullScreenErrorView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
//
// FullScreenErrorView.swift
// Course
//
// Created by Shafqat Muneer on 5/14/24.
//

import SwiftUI
import Theme

public struct FullScreenErrorView: View {

public enum ErrorType {
case noInternet
case noInternetWithReload
case generic
}

private let errorType: ErrorType
private var reloadAction: () -> Void = {}

public init(
type: ErrorType
) {
self.errorType = type
}

public init(
type: ErrorType,
reloadAction: @escaping () -> Void
) {
self.errorType = type
self.reloadAction = reloadAction
}

public var body: some View {
GeometryReader { proxy in
VStack(spacing: 28) {
Spacer()
switch errorType {
case .noInternet, .noInternetWithReload:
CoreAssets.noWifi.swiftUIImage
.renderingMode(.template)
.foregroundStyle(Color.primary)
.scaledToFit()

Text(CoreLocalization.Error.Internet.noInternetTitle)
.font(Theme.Fonts.titleLarge)
.foregroundColor(Theme.Colors.textPrimary)

Text(CoreLocalization.Error.Internet.noInternetDescription)
.font(Theme.Fonts.bodyLarge)
.foregroundColor(Theme.Colors.textPrimary)
.multilineTextAlignment(.center)
.padding(.horizontal, 50)
case .generic:
CoreAssets.notAvaliable.swiftUIImage
.renderingMode(.template)
.foregroundStyle(Color.primary)
.scaledToFit()

Text(CoreLocalization.View.Snackbar.tryAgainBtn)
.font(Theme.Fonts.titleLarge)
.foregroundColor(Theme.Colors.textPrimary)

Text(CoreLocalization.Error.unknownError)
.font(Theme.Fonts.bodyLarge)
.foregroundColor(Theme.Colors.textPrimary)
.multilineTextAlignment(.center)
.padding(.horizontal, 50)
}

if errorType != .noInternet {
UnitButtonView(type: .reload, action: {
self.reloadAction()
})
}
Spacer()
}
.frame(maxWidth: .infinity, maxHeight: proxy.size.height)
.background(
Theme.Colors.background
)
}
}
}

#if DEBUG
//swiftlint:disable all
struct FullScreenErrorView_Previews: PreviewProvider {
static var previews: some View {
FullScreenErrorView(type: .noInternetWithReload)
}
}
//swiftlint:enable all
#endif
19 changes: 18 additions & 1 deletion Core/Core/View/Base/Webview/WebView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public protocol WebViewNavigationDelegate: AnyObject {
shouldLoad request: URLRequest,
navigationAction: WKNavigationAction
) async -> Bool

func showWebViewError()
}

public struct WebView: UIViewRepresentable {
Expand Down Expand Up @@ -70,6 +72,10 @@ public struct WebView: UIViewRepresentable {

public func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
webView.isHidden = false
DispatchQueue.main.async {
self.parent.isLoading = false
}
parent.webViewNavDelegate?.showWebViewError()
}

public func webView(
Expand All @@ -78,6 +84,10 @@ public struct WebView: UIViewRepresentable {
withError error: Error
) {
webView.isHidden = false
DispatchQueue.main.async {
self.parent.isLoading = false
}
parent.webViewNavDelegate?.showWebViewError()
}

public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
Expand Down Expand Up @@ -189,7 +199,14 @@ public struct WebView: UIViewRepresentable {

@objc private func reload() {
parent.isLoading = true
webview?.reload()
if webview?.url?.absoluteString.isEmpty ?? true {
if let url = URL(string: parent.viewModel.url) {
let request = URLRequest(url: url)
webview?.load(request)
}
} else {
webview?.reload()
}
}

public func userContentController(
Expand Down
14 changes: 11 additions & 3 deletions Course/Course.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,6 @@
02B6B3B528E1D10700232911 /* Domain */,
02EAE2CA28E1F0A700529644 /* Presentation */,
97EA4D822B84EFA900663F58 /* Managers */,
97CA95212B875EA200A9EDEA /* Views */,
02B6B3B428E1C49400232911 /* Localizable.strings */,
);
path = Course;
Expand Down Expand Up @@ -526,13 +525,20 @@
path = Mock;
sourceTree = "<group>";
};
97CA95212B875EA200A9EDEA /* Views */ = {
9784D4752BF39EEF00AFEFFF /* CalendarSyncProgressView */ = {
isa = PBXGroup;
children = (
97C99C352B9A08FE004EEDE2 /* CalendarSyncProgressView.swift */,
);
path = CalendarSyncProgressView;
sourceTree = "<group>";
};
9784D4762BF39EFD00AFEFFF /* DatesSuccessView */ = {
isa = PBXGroup;
children = (
97CA95242B875EE200A9EDEA /* DatesSuccessView.swift */,
);
path = Views;
path = DatesSuccessView;
sourceTree = "<group>";
};
97EA4D822B84EFA900663F58 /* Managers */ = {
Expand Down Expand Up @@ -592,6 +598,8 @@
BAD9CA482B2C88D500DE790A /* Subviews */ = {
isa = PBXGroup;
children = (
9784D4762BF39EFD00AFEFFF /* DatesSuccessView */,
9784D4752BF39EEF00AFEFFF /* CalendarSyncProgressView */,
02D4FC2C2BBD7C7500C47748 /* MessageSectionView */,
BAC0E0D92B32F0A2006B68A9 /* CourseVideoDownloadBarView */,
BA58CF622B471047005B102E /* VideoDownloadQualityBarView */,
Expand Down
File renamed without changes.
32 changes: 5 additions & 27 deletions Course/Course/Presentation/Unit/CourseUnitView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ public struct CourseUnitView: View {
Spacer(minLength: 150)
}
} else {
NoInternetView()
FullScreenErrorView(type: .noInternet)
}

} else {
Expand Down Expand Up @@ -219,7 +219,7 @@ public struct CourseUnitView: View {
Spacer(minLength: 150)
}
} else {
NoInternetView()
FullScreenErrorView(type: .noInternet)
}
}
// MARK: Web
Expand All @@ -233,7 +233,7 @@ public struct CourseUnitView: View {
)
// not need to add frame limit there because we did that with injection
} else {
NoInternetView()
FullScreenErrorView(type: .noInternet)
}
} else {
EmptyView()
Expand All @@ -247,7 +247,7 @@ public struct CourseUnitView: View {
Spacer()
.frame(minHeight: 100)
} else {
NoInternetView()
FullScreenErrorView(type: .noInternet)
}
} else {
EmptyView()
Expand Down Expand Up @@ -275,7 +275,7 @@ public struct CourseUnitView: View {
//No need iPad paddings there bacause they were added
//to PostsView that placed inside DiscussionView
} else {
NoInternetView()
FullScreenErrorView(type: .noInternet)
}
} else {
EmptyView()
Expand Down Expand Up @@ -569,25 +569,3 @@ struct CourseUnitView_Previews: PreviewProvider {
}
//swiftlint:enable all
#endif

struct NoInternetView: View {

var body: some View {
VStack(spacing: 28) {
Spacer()
CoreAssets.noWifi.swiftUIImage
.renderingMode(.template)
.foregroundStyle(Color.primary)
.scaledToFit()
Text(CoreLocalization.Error.Internet.noInternetTitle)
.font(Theme.Fonts.titleLarge)
.foregroundColor(Theme.Colors.textPrimary)
Text(CoreLocalization.Error.Internet.noInternetDescription)
.font(Theme.Fonts.bodyLarge)
.foregroundColor(Theme.Colors.textPrimary)
.multilineTextAlignment(.center)
.padding(.horizontal, 50)
Spacer()
}.frame(maxWidth: .infinity, maxHeight: .infinity)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public class DiscoveryWebviewViewModel: ObservableObject {
@Published var courseDetails: CourseDetails?
@Published private(set) var showProgress = false
@Published var showError: Bool = false
@Published var webViewError: Bool = false

var errorMessage: String? {
didSet {
withAnimation {
Expand Down Expand Up @@ -247,4 +249,10 @@ extension DiscoveryWebviewViewModel: WebViewNavigationDelegate {
private func isValidAppURLScheme(_ url: URL) -> Bool {
return url.scheme ?? "" == config.URIScheme
}

public func showWebViewError() {
DispatchQueue.main.async {
self.webViewError = true
}
}
}
Loading

0 comments on commit aaf0cee

Please sign in to comment.