Skip to content

Commit

Permalink
Add contact us support
Browse files Browse the repository at this point in the history
  • Loading branch information
cp-amisha-i committed Apr 9, 2024
1 parent 22ca426 commit 9f59eb3
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 15 deletions.
4 changes: 4 additions & 0 deletions BaseStyle/BaseStyle.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
D8302D9C2B9EE1D2005ACA13 /* PrimaryFloatingButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D8302D9B2B9EE1D2005ACA13 /* PrimaryFloatingButton.swift */; };
D887213F2B99992A009DC5BE /* LoaderViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D887213E2B99992A009DC5BE /* LoaderViewModel.swift */; };
D89C933F2BC3C0F800FACD16 /* ForwardIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = D89C933E2BC3C0F800FACD16 /* ForwardIcon.swift */; };
D89C93462BC42DE500FACD16 /* MailComposeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D89C93452BC42DE500FACD16 /* MailComposeView.swift */; };
D89DBE2D2B88828300E5F1BD /* Countries.json in Resources */ = {isa = PBXBuildFile; fileRef = D89DBE2C2B88828300E5F1BD /* Countries.json */; };
D89DBE312B8884E300E5F1BD /* SectionHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D89DBE302B8884E300E5F1BD /* SectionHeaderView.swift */; };
D89DBE332B888F2D00E5F1BD /* SearchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = D89DBE322B888F2D00E5F1BD /* SearchBar.swift */; };
Expand Down Expand Up @@ -75,6 +76,7 @@
D8302D9B2B9EE1D2005ACA13 /* PrimaryFloatingButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrimaryFloatingButton.swift; sourceTree = "<group>"; };
D887213E2B99992A009DC5BE /* LoaderViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = LoaderViewModel.swift; path = BaseStyle/Views/LoaderViewModel.swift; sourceTree = SOURCE_ROOT; };
D89C933E2BC3C0F800FACD16 /* ForwardIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ForwardIcon.swift; sourceTree = "<group>"; };
D89C93452BC42DE500FACD16 /* MailComposeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MailComposeView.swift; sourceTree = "<group>"; };
D89DBE2C2B88828300E5F1BD /* Countries.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Countries.json; sourceTree = "<group>"; };
D89DBE302B8884E300E5F1BD /* SectionHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionHeaderView.swift; sourceTree = "<group>"; };
D89DBE322B888F2D00E5F1BD /* SearchBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchBar.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -308,6 +310,7 @@
D89DBE322B888F2D00E5F1BD /* SearchBar.swift */,
D8D42AAF2B872E44009B345D /* LoaderView.swift */,
D8D14A4F2BA090F000F45FF2 /* ShareSheetView.swift */,
D89C93452BC42DE500FACD16 /* MailComposeView.swift */,
D89DBE3B2B88AA1500E5F1BD /* CustomTextField.swift */,
D82174BD2BBAD86D00DB42C3 /* ProfileImageView.swift */,
D8E244C02B986CD800C6C82A /* ImagePickerView.swift */,
Expand Down Expand Up @@ -525,6 +528,7 @@
D8D42A8A2B85D525009B345D /* AppColors.swift in Sources */,
D8D42AAC2B872A7C009B345D /* ToastView.swift in Sources */,
D8D42A952B85F8A2009B345D /* Bundle+Extension.swift in Sources */,
D89C93462BC42DE500FACD16 /* MailComposeView.swift in Sources */,
D8E244C12B986CD800C6C82A /* ImagePickerView.swift in Sources */,
D89DBE312B8884E300E5F1BD /* SectionHeaderView.swift in Sources */,
D8D42A862B85D08F009B345D /* Font+Extension.swift in Sources */,
Expand Down
77 changes: 77 additions & 0 deletions BaseStyle/BaseStyle/CustomUI/MailComposeView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
//
// MailComposeView.swift
// BaseStyle
//
// Created by Amisha Italiya on 08/04/24.
//

import UIKit
import SwiftUI
import MessageUI

public struct MailComposeView: UIViewControllerRepresentable {

let logFilePath: URL?
var showToast: () -> Void

public init(logFilePath: URL?, showToast: @escaping () -> Void) {
self.logFilePath = logFilePath
self.showToast = showToast
}

public func makeUIViewController(context: Context) -> MFMailComposeViewController {
guard MFMailComposeViewController.canSendMail() else {
print("MailComposeView: Device cannot send email.")
return MFMailComposeViewController()
}

let mailComposeViewController = MFMailComposeViewController()
mailComposeViewController.setSubject("Log File")
mailComposeViewController.setMessageBody("Please find the attached logfile.", isHTML: false)
mailComposeViewController.mailComposeDelegate = context.coordinator

if let logFilePath {
do {
let attachmentData = try Data(contentsOf: logFilePath)
mailComposeViewController.addAttachmentData(attachmentData, mimeType: "application/zip", fileName: "logs.zip")
} catch {
print("MailComposeView: Failed to load attachment data: \(error.localizedDescription)")
}
}

// Set default recipient email address
mailComposeViewController.setToRecipients(["[email protected]"])

return mailComposeViewController
}

public func updateUIViewController(_ uiViewController: MFMailComposeViewController, context: Context) { }

public func makeCoordinator() -> Coordinator {
Coordinator(showToast: showToast)
}
}

public class Coordinator: NSObject, MFMailComposeViewControllerDelegate {
var showToast: () -> Void

public init(showToast: @escaping () -> Void) {
self.showToast = showToast
}

public func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: (any Error)?) {
var needToShowToast = false
switch result {
case .sent:
needToShowToast = true
default:
break
}

controller.dismiss(animated: true) {
if needToShowToast {
self.showToast()
}
}
}
}
10 changes: 8 additions & 2 deletions BaseStyle/BaseStyle/Helper/TopViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,14 @@ public class TopViewController {
static public let shared = TopViewController()

public func topViewController(controller: UIViewController? = nil) -> UIViewController? {
guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return nil }
guard let controller = controller ?? windowScene.windows.first?.rootViewController else { return nil }
guard let window = UIApplication.shared.connectedScenes
.compactMap({ $0 as? UIWindowScene })
.flatMap({ $0.windows }).first
else { return nil }

guard let controller = controller ?? window.rootViewController else {
return nil
}

if let navigationController = controller as? UINavigationController {
return topViewController(controller: navigationController.visibleViewController)
Expand Down
4 changes: 2 additions & 2 deletions BaseStyle/BaseStyle/Views/ForwardIcon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ public struct ForwardIcon: View {
VStack(spacing: 0) {
Image(systemName: "chevron.right")
.font(.system(size: 12).weight(.bold))
.foregroundColor(secondaryText)
.aspectRatio(contentMode: .fit)
}
.frame(width: 24, height: 24, alignment: .center)
.foregroundColor(secondaryText)
.frame(width: 26, height: 26, alignment: .center)
}
}

Expand Down
1 change: 1 addition & 0 deletions Data/Data/Helper/Logger/DDLogProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public extension DDFileLogger {

let now = df.string(from: Date())
let destination = FileManager.default.temporaryDirectory.appendingPathComponent("Logs/\(now).zip")

SSZipArchive.createZipFile(atPath: destination.path, withContentsOfDirectory: self.logFileManager.logsDirectory)
return destination
}
Expand Down
90 changes: 82 additions & 8 deletions Splito/UI/Home/Account/AccountHomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,36 @@ struct AccountHomeView: View {
LoaderView(tintColor: primaryColor, scaleSize: 2)
} else {
Text("Account")
.font(.Header3())
.font(.Header4())
.foregroundColor(primaryText)
.padding(.top, 10)

ScrollView(showsIndicators: false) {
VStack(spacing: 0) {
VStack(spacing: 20) {
VSpacer(20)

UserInfoHeaderView(onTap: viewModel.openUserProfileView)
AccountUserHeaderView(onTap: viewModel.openUserProfileView)

AccountFeedbackSectionView(onContactTap: viewModel.onContactUsTap,
onRateAppTap: viewModel.onRateAppTap)

AccountLogoutSectionView(onLogoutTap: viewModel.performLogoutAction)

VSpacer(20)
}
}
}
}
.background(backgroundColor)
.frame(maxWidth: isIpad ? 600 : nil, alignment: .center)
.toastView(toast: $viewModel.toast)
.sheet(isPresented: $viewModel.showShareSheet) {
MailComposeView(logFilePath: viewModel.logFilePath, showToast: viewModel.showMailSendToast)
}
}
}

private struct UserInfoHeaderView: View {
private struct AccountUserHeaderView: View {

@Inject var preference: SplitoPreference

Expand All @@ -48,21 +62,21 @@ private struct UserInfoHeaderView: View {
var body: some View {
VStack(alignment: .leading, spacing: 20) {
Text("Settings")
.font(.subTitle2())
.font(.subTitle4(14))
.foregroundColor(primaryText)
.padding(.horizontal, 18)
.padding(.horizontal, 16)
.padding(.bottom, 10)

HStack(alignment: .center, spacing: 16) {
MemberProfileImageView(imageUrl: preference.user?.imageUrl)

VStack(alignment: .leading, spacing: 3) {
VStack(alignment: .leading, spacing: 5) {
Text(userName)
.font(.subTitle1())
.foregroundColor(primaryText)

Text(preference.user?.emailId ?? "")
.font(.subTitle2())
.font(.subTitle3())
.foregroundColor(secondaryText)
}

Expand All @@ -80,6 +94,66 @@ private struct UserInfoHeaderView: View {
}
}

private struct AccountFeedbackSectionView: View {

var onContactTap: () -> Void
var onRateAppTap: () -> Void

var body: some View {
VStack(alignment: .leading, spacing: 10) {
Text("Feedback")
.font(.subTitle4(14))
.foregroundColor(primaryText)
.padding(.horizontal, 16)
.padding(.vertical, 10)

HStack(alignment: .center, spacing: 16) {
Text("Contact us")
.font(.subTitle2())
.foregroundColor(primaryText)

Spacer()

ForwardIcon()
}
.padding(.horizontal, 22)
.onTouchGesture { onContactTap() }

HStack(alignment: .center, spacing: 16) {
Text("Rate Splito")
.font(.subTitle2())
.foregroundColor(disableText)

Spacer()

ForwardIcon()
}
.padding(.top, 10)
.padding(.horizontal, 22)
// .onTouchGesture { onRateAppTap() }

Divider()
.frame(height: 1)
.background(disableLightText)
}
}
}

private struct AccountLogoutSectionView: View {

var onLogoutTap: () -> Void

var body: some View {
VStack(alignment: .center, spacing: 10) {
Text("Logout")
.font(.bodyBold(18))
.foregroundColor(primaryColor)
.padding(.top, 30)
.onTouchGesture { onLogoutTap() }
}
}
}

#Preview {
AccountHomeView(viewModel: AccountHomeViewModel(router: .init(root: .AccountHomeView)))
}
32 changes: 31 additions & 1 deletion Splito/UI/Home/Account/AccountHomeViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,20 @@
//

import Data
import MessageUI
import BaseStyle

class AccountHomeViewModel: BaseViewModel, ObservableObject {

@Inject var preference: SplitoPreference
@Inject var userRepository: UserRepository
@Inject private var ddLoggerProvider: DDLoggerProvider

@Published var currentState: ViewState = .initial

@Published var profileImageUrl: String?
@Published var logFilePath: URL?
@Published var showShareSheet = false
@Published var showMailToast = false

private let router: Router<AppRoute>

Expand All @@ -26,6 +31,31 @@ class AccountHomeViewModel: BaseViewModel, ObservableObject {
func openUserProfileView() {
router.push(.ProfileView)
}

func onContactUsTap() {
guard MFMailComposeViewController.canSendMail() else {
showToastFor(toast: ToastPrompt(type: .warning, title: "Warning", message: "Your device cannot send email."))
showMailToast = true
return
}
let logger = ddLoggerProvider.provideLogger()
logger.removeAllZipLogs()
logFilePath = logger.zipLogs()
showShareSheet = true
}

func showMailSendToast() {
showToastFor(toast: ToastPrompt(type: .success, title: "Success", message: "Email sent successfully!"))
showMailToast = true
}

func onRateAppTap() {

}

func performLogoutAction() {

}
}

// MARK: - Group States
Expand Down
2 changes: 1 addition & 1 deletion Splito/UI/Home/Groups/Add Member/InviteMemberView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ struct InviteMemberView: View {
.toastView(toast: $viewModel.toast)
.backport.alert(isPresented: $viewModel.showAlert, alertStruct: viewModel.alert)
.sheet(isPresented: $viewModel.showShareSheet) {
ShareSheetView(activityItems: ["Let's split the expnese! Use invite code \(viewModel.inviteCode) to join the \(viewModel.group?.name ?? "") group, don't have an app then please download it."]) { isCompleted in
ShareSheetView(activityItems: ["Let's split the expense! Use invite code \(viewModel.inviteCode) to join the \(viewModel.group?.name ?? "") group, don't have an app then please download it."]) { isCompleted in
if isCompleted {
viewModel.storeSharedCode()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class GroupSettingViewModel: BaseViewModel, ObservableObject {
self.goBackToGroupList()
} else {
self.showAlert = false
self.showToastFor(toast: ToastPrompt(type: .success, title: "", message: "Group member removed"))
self.showToastFor(toast: ToastPrompt(type: .success, title: "Success", message: "Group member removed"))
}
}.store(in: &cancelable)
}
Expand Down

0 comments on commit 9f59eb3

Please sign in to comment.