From bf4ca408e33ab1b3cced222be58fd7ec12c888e5 Mon Sep 17 00:00:00 2001 From: Andrii Date: Tue, 12 Nov 2024 13:16:25 +0100 Subject: [PATCH] Feature/boost notifications (#1385) * add view and icon * view implementation * polish UI * remove unused spacing * Update notificationsBoost resources * bottomSheet implementation * incapsulate icons * configure bottom sheet * Polish UI for PushNotificationBoostView * Polish NotificationBoost views * set folder * fix format * Configure AllSet view * refactore viewModel * reuse view * fix ui * Refactore push notification boost views * isClosable * close button * Aligne UI * Implement layoutMarginsGuide * improve UI * rename * polish configuration * link action * refactore * add demoes * fix typo * fix paddings * fix padding * revert * set bg * fix * test * fix color and text size * Revert "revert" This reverts commit 078209746e8f92c25893622a40cb6c7091ee8c59. * fix fonts * fix VO * fix accesibility * ignore emojies --------- Co-authored-by: Andrii Momot --- Demo/Demo.xcodeproj/project.pbxproj | 8 ++ .../PushNotificationNudging/Contents.json | 6 + .../bell.imageset/Contents.json | 12 ++ .../bell.imageset/bell.pdf | Bin 0 -> 2546 bytes .../bellOff.imageset/Contents.json | 12 ++ .../bellOff.imageset/bellOff.pdf | Bin 0 -> 3793 bytes .../bottomSheetBell.imageset/Contents.json | 15 +++ .../bottomSheetBell.pdf | Bin 0 -> 2922 bytes .../Contents.json | 15 +++ .../bottomSheetFeedback.pdf | Bin 0 -> 2266 bytes .../Contents.json | 15 +++ .../bottomSheetSearchFavorites.pdf | Bin 0 -> 2704 bytes Demo/Sources/Assets/ImageAsset.swift | 10 ++ .../Demo/DemoViews/SwiftUIDemoViews.swift | 6 + ...tificationNudgingBottomSheetDemoView.swift | 38 ++++++ .../PushNotificationNudgingDemoView.swift | 30 +++++ .../FinniversKit.xcodeproj/project.pbxproj | 40 +++++++ .../bell.imageset/Contents.json | 12 ++ .../Assets.xcassets/bell.imageset/bell.pdf | Bin 0 -> 2546 bytes .../bellOff.imageset/Contents.json | 12 ++ .../bellOff.imageset/bellOff.pdf | Bin 0 -> 3793 bytes .../closeCross.imageset/Contents.json | 15 +++ .../closeCross.imageset/closeCross.pdf | Bin 0 -> 994 bytes FinniversKit/Sources/Assets/ImageAsset.swift | 6 + .../PushNotificationNudgingBottomSheet.swift | 110 ++++++++++++++++++ ...ificationNudgingBottomSheetViewModel.swift | 62 ++++++++++ .../PushNotificationNudgingView.swift | 102 ++++++++++++++++ .../PushNotificationNudgingViewModel.swift | 39 +++++++ .../Foundation/StringExtensions.swift | 5 + 29 files changed, 570 insertions(+) create mode 100644 Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/Contents.json create mode 100644 Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bell.imageset/Contents.json create mode 100644 Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bell.imageset/bell.pdf create mode 100644 Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bellOff.imageset/Contents.json create mode 100644 Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bellOff.imageset/bellOff.pdf create mode 100644 Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bottomSheetBell.imageset/Contents.json create mode 100644 Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bottomSheetBell.imageset/bottomSheetBell.pdf create mode 100644 Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bottomSheetFeedback.imageset/Contents.json create mode 100644 Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bottomSheetFeedback.imageset/bottomSheetFeedback.pdf create mode 100644 Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bottomSheetSearchFavorites.imageset/Contents.json create mode 100644 Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bottomSheetSearchFavorites.imageset/bottomSheetSearchFavorites.pdf create mode 100644 Demo/Sources/SwiftUI/PushNotificationNudgingBottomSheetDemoView.swift create mode 100644 Demo/Sources/SwiftUI/PushNotificationNudgingDemoView.swift create mode 100644 FinniversKit/Sources/Assets/Assets.xcassets/bell.imageset/Contents.json create mode 100644 FinniversKit/Sources/Assets/Assets.xcassets/bell.imageset/bell.pdf create mode 100644 FinniversKit/Sources/Assets/Assets.xcassets/bellOff.imageset/Contents.json create mode 100644 FinniversKit/Sources/Assets/Assets.xcassets/bellOff.imageset/bellOff.pdf create mode 100644 FinniversKit/Sources/Assets/Assets.xcassets/closeCross.imageset/Contents.json create mode 100644 FinniversKit/Sources/Assets/Assets.xcassets/closeCross.imageset/closeCross.pdf create mode 100644 FinniversKit/Sources/Components/PushNotificationNudgingView/PushNotificationNudgingBottomSheet/PushNotificationNudgingBottomSheet.swift create mode 100644 FinniversKit/Sources/Components/PushNotificationNudgingView/PushNotificationNudgingBottomSheet/PushNotificationNudgingBottomSheetViewModel.swift create mode 100644 FinniversKit/Sources/Components/PushNotificationNudgingView/PushNotificationNudgingView/PushNotificationNudgingView.swift create mode 100644 FinniversKit/Sources/Components/PushNotificationNudgingView/PushNotificationNudgingView/PushNotificationNudgingViewModel.swift diff --git a/Demo/Demo.xcodeproj/project.pbxproj b/Demo/Demo.xcodeproj/project.pbxproj index 50dac62f97..1da4d33657 100644 --- a/Demo/Demo.xcodeproj/project.pbxproj +++ b/Demo/Demo.xcodeproj/project.pbxproj @@ -177,6 +177,8 @@ 9BBC904024FD252B0003D2D8 /* UITraitCollection+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9BBC903F24FD252B0003D2D8 /* UITraitCollection+Extensions.swift */; }; B26B58342B4BFEFB000E0245 /* InfoboxSwiftUIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B26B58332B4BFEFB000E0245 /* InfoboxSwiftUIViewController.swift */; }; B2B8F16B2B483F2F0090573E /* NMPInfoboxViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2B8F16A2B483F2F0090573E /* NMPInfoboxViewController.swift */; }; + B656EA972CC289AB00751289 /* PushNotificationNudgingDemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B656EA962CC289AB00751289 /* PushNotificationNudgingDemoView.swift */; }; + B656EA992CC28A2600751289 /* PushNotificationNudgingBottomSheetDemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B656EA982CC28A2600751289 /* PushNotificationNudgingBottomSheetDemoView.swift */; }; D75E14D727371692008EB126 /* FrontPageSavedSearchFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = D75E14D627371692008EB126 /* FrontPageSavedSearchFactory.swift */; }; D7C750382731C61A002BDE98 /* FrontPageSavedSearchesDemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7C750372731C61A002BDE98 /* FrontPageSavedSearchesDemoView.swift */; }; D7D514C7272942E10065E2F6 /* PromotionDemoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7D514C6272942E10065E2F6 /* PromotionDemoView.swift */; }; @@ -386,6 +388,8 @@ 9BBC903F24FD252B0003D2D8 /* UITraitCollection+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITraitCollection+Extensions.swift"; sourceTree = ""; }; B26B58332B4BFEFB000E0245 /* InfoboxSwiftUIViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfoboxSwiftUIViewController.swift; sourceTree = ""; }; B2B8F16A2B483F2F0090573E /* NMPInfoboxViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NMPInfoboxViewController.swift; sourceTree = ""; }; + B656EA962CC289AB00751289 /* PushNotificationNudgingDemoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationNudgingDemoView.swift; sourceTree = ""; }; + B656EA982CC28A2600751289 /* PushNotificationNudgingBottomSheetDemoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushNotificationNudgingBottomSheetDemoView.swift; sourceTree = ""; }; D75E14D627371692008EB126 /* FrontPageSavedSearchFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrontPageSavedSearchFactory.swift; sourceTree = ""; }; D7C750372731C61A002BDE98 /* FrontPageSavedSearchesDemoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FrontPageSavedSearchesDemoView.swift; sourceTree = ""; }; D7D514C6272942E10065E2F6 /* PromotionDemoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromotionDemoView.swift; sourceTree = ""; }; @@ -1595,6 +1599,8 @@ 17F8EEC529409FE3000E26C9 /* SwiftUISelectionListDemoView.swift */, 27FAFCB72988FE6100FEDAE0 /* ToastSwiftUIDemoView.swift */, 277307E4298C108800B8E27F /* ResultSwiftUIDemoView.swift */, + B656EA962CC289AB00751289 /* PushNotificationNudgingDemoView.swift */, + B656EA982CC28A2600751289 /* PushNotificationNudgingBottomSheetDemoView.swift */, ); path = SwiftUI; sourceTree = ""; @@ -1847,6 +1853,7 @@ DA083C2E2462BCA800B26235 /* SwiftUIDemoViews.swift in Sources */, 46E77469242CEF0A008A5E93 /* FavoriteFoldersListViewDemoViewHelpers.swift in Sources */, 46E7741F242CEF0A008A5E93 /* ButtonDemoView.swift in Sources */, + B656EA992CC28A2600751289 /* PushNotificationNudgingBottomSheetDemoView.swift in Sources */, 277307E5298C108800B8E27F /* ResultSwiftUIDemoView.swift in Sources */, 46E773D3242CEF0A008A5E93 /* EmptyViewDemoView.swift in Sources */, 46E77459242CEF0A008A5E93 /* AdRecommendationsGridViewDemoViewHelpers.swift in Sources */, @@ -1919,6 +1926,7 @@ D7D514C7272942E10065E2F6 /* PromotionDemoView.swift in Sources */, 46E773D7242CEF0A008A5E93 /* FavoriteAdsListDemoViewController.swift in Sources */, 46E77406242CEF0A008A5E93 /* VisibilityDrivenTitleDemoView.swift in Sources */, + B656EA972CC289AB00751289 /* PushNotificationNudgingDemoView.swift in Sources */, 46E773F5242CEF0A008A5E93 /* SelectorTitleViewDemoView.swift in Sources */, 17EE08632AA8ABCC00A623F2 /* FrontPageTransactionListDemoViewController.swift in Sources */, 46E77435242CEF0A008A5E93 /* PhaseListViewDemo.swift in Sources */, diff --git a/Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/Contents.json b/Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/Contents.json new file mode 100644 index 0000000000..73c00596a7 --- /dev/null +++ b/Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bell.imageset/Contents.json b/Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bell.imageset/Contents.json new file mode 100644 index 0000000000..45f609bc71 --- /dev/null +++ b/Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bell.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "bell.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bell.imageset/bell.pdf b/Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bell.imageset/bell.pdf new file mode 100644 index 0000000000000000000000000000000000000000..cffca78c4bbe41100764bd28c627b1e30adcaeb2 GIT binary patch literal 2546 zcmZXWc|6qp7RT!;OQTyxgA(;4WKhg7B>ULLkPIG6*_qo6W5#TfrNUSe!;od74UbSn znv@6Gg+|7%o06qMlqK>|-I@08J%9XO-{1T7JLh}O`Tg)juORrZT*DGipkXP1h9$v=hBe3fk^Hgz41Q?XVu>ecI6#a4xdR{Z zD^O_^tWOXqbYn)g4O0;z9=AeItlOX$@}X8paiAWIjxm{**^=D6y85ZSlifSgV?tD3 zvx(o=I8WhTzheA(aq#0J>B0Jkh2FPSM_+lZ+^Tv&niu_4!+6!XeJ$wBd1QWnNs8h7 z+@{WtJvUUeP(ne!H9r$vN~Rzzx9Q3fkpY9;` z>X0Q#Sy9jC=y|0Mo~47_Iv6o00ycMhA?CoXV4DY*d!(0*E6;9TiqGP-tWdoTjN6tW zVea0>kD#r&!M85Ns=vq((O(#yA_OC!O3dCAQbu6(O1D>bfKHF{SO^8Bwz)H?@h@1`+ZyW9h zLi|x-CP!8Lk+=3BhMR!$(}i2A#Am+S%?ojT^NH<@`%p%YE4F5xS6Z{tcbJV35=!2f zlc(o;S3NtxuI4PR)D~(#ntuKzT;|51nt@lFcbH2GZwj>D)Mirax(rcu^YFs;F;3fe z!KTckwieo5+yIt+EfE0TBEOB8hl`4gMNW5)N@$h3cONq7u`lwyoFC9U#FL>l!5eM* zkji8sM}<{6mO(p<+|GU|Q)wysr;*g=bc{r_PZEa-R5wUTXzcjwF9ai~ydpmwY>m%T zWH>xOu&f;O+(kI=ZQw&pp{T4-G#rdL%qWU|b4)H|k)B*>dc(dHQk-8;pf+C%EOF#y z$a>}(-o0N&A67Kq_LyFvFc))p#8Y^t<=0t0{Du&1_%zkpW?a0?iJs>=LbU;1s$-uBWGToQ*Dh_+^?!aU*B*09wn<@OwAj~5g)0= zo4xhZUrgHbmVI)UQx0C`k5JT;ewoN5lTf2L>8X^z4UVuAfd)JxDKdhd#?5ikS-(<1 zehiTxE3rBOdE*Z)auqvSZwgM-CMMX0=5~kD7JM^a>bk8w6Dnqjnt-_VTTa>y?}GDq z!{_M5;6PPZFf+9>uDiS-Wq!C{7?p7#DteRg5qxu(vMe9 zpozI>x#y$%YOlT{xqDy>-}7D=*Fp7;)4nfEVZpo2?OJKkd>|A*m8jVq5h=kU%^&99ZjxH^2oq}nzO{K>>wx4JjKD;&|TU72Vj zS9Pa3mZAQ9iBQP8GQ+zk;xW`^2mctUR%k}t3El7y^W~1U%^oe|FSoT1)hwCAY9Mp59M=BpOCq~HIfVXO>#sI(b*2_7Uz8acSZm9cN$(D_nY*r( z)BbYx{Iu6+mrFc>Jb%;I??Nq5-md}z#&zkdbS`I$(g_}~dx3P|wxtj+oBP@$57uuwn+?+^XD o6b%Owi3SJ;{<2^VM|>ET-~AT{=0l-<83(Qf*9IvmSsb(^b literal 0 HcmV?d00001 diff --git a/Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bellOff.imageset/Contents.json b/Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bellOff.imageset/Contents.json new file mode 100644 index 0000000000..18b8a77580 --- /dev/null +++ b/Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bellOff.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "bellOff.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bellOff.imageset/bellOff.pdf b/Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bellOff.imageset/bellOff.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e02b7028a9836ebd4be07f93e1f6456b1ca28265 GIT binary patch literal 3793 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 a8&q`v>83%XGe6m}Kv-HrpwQh|*Z%=^?ahP$ literal 0 HcmV?d00001 diff --git a/Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bottomSheetSearchFavorites.imageset/Contents.json b/Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bottomSheetSearchFavorites.imageset/Contents.json new file mode 100644 index 0000000000..447cf77309 --- /dev/null +++ b/Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bottomSheetSearchFavorites.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "bottomSheetSearchFavorites.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bottomSheetSearchFavorites.imageset/bottomSheetSearchFavorites.pdf b/Demo/Sources/Assets/Assets.xcassets/PushNotificationNudging/bottomSheetSearchFavorites.imageset/bottomSheetSearchFavorites.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b4071eef7eb57a40299ef598fec09af7b6469f91 GIT binary patch literal 2704 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 literal 0 HcmV?d00001 diff --git a/Demo/Sources/Assets/ImageAsset.swift b/Demo/Sources/Assets/ImageAsset.swift index 5bef748303..be66cd500a 100644 --- a/Demo/Sources/Assets/ImageAsset.swift +++ b/Demo/Sources/Assets/ImageAsset.swift @@ -44,8 +44,13 @@ enum ImageAsset: String { case autovex case avatar case bapShippable + case bell + case bellOff case betaImageSearch case blinkRocketMini + case bottomSheetBell + case bottomSheetFeedback + case bottomSheetSearchFavorites case cabin case car case carFront @@ -158,8 +163,13 @@ enum ImageAsset: String { .autovex, .avatar, .bapShippable, + .bell, + .bellOff, .betaImageSearch, .blinkRocketMini, + .bottomSheetBell, + .bottomSheetFeedback, + .bottomSheetSearchFavorites, .cabin, .car, .carFront, diff --git a/Demo/Sources/Demo/DemoViews/SwiftUIDemoViews.swift b/Demo/Sources/Demo/DemoViews/SwiftUIDemoViews.swift index d67f6899e1..3e6ffd0b55 100644 --- a/Demo/Sources/Demo/DemoViews/SwiftUIDemoViews.swift +++ b/Demo/Sources/Demo/DemoViews/SwiftUIDemoViews.swift @@ -18,6 +18,8 @@ enum SwiftUIDemoViews: String, CaseIterable, DemoGroup, DemoGroupItem { case textView case toast case resultView + case pushNotificationNudging + case pushNotificationNudgingBottomSheet static var groupTitle: String { "SwiftUI" } static var numberOfDemos: Int { allCases.count } @@ -54,6 +56,10 @@ enum SwiftUIDemoViews: String, CaseIterable, DemoGroup, DemoGroupItem { return ToastSwiftUIDemoView_Previews() case .resultView: return ResultSwiftUIDemoViewController() + case .pushNotificationNudging: + return PushNotificationNudgingDemoView_Previews() + case .pushNotificationNudgingBottomSheet: + return PushNotificationNudgingBottomSheetDemoView_Previews() } } } diff --git a/Demo/Sources/SwiftUI/PushNotificationNudgingBottomSheetDemoView.swift b/Demo/Sources/SwiftUI/PushNotificationNudgingBottomSheetDemoView.swift new file mode 100644 index 0000000000..c6e80789c8 --- /dev/null +++ b/Demo/Sources/SwiftUI/PushNotificationNudgingBottomSheetDemoView.swift @@ -0,0 +1,38 @@ +import DemoKit +import FinniversKit +import Foundation +import SwiftUI + +struct PushNotificationNudgingBottomSheetDemoView_Previews: PreviewProvider, Demoable { + static var previews: some View { + let section1 = PushNotificationNudgingBottomSheetViewModel.Section( + icon: Image(uiImage: UIImage(named: .bottomSheetBell)), + description: "Get real-time alerts when somebody wants to buy your item." + ) + let section2 = PushNotificationNudgingBottomSheetViewModel.Section( + icon: Image(uiImage: UIImage(named: .bottomSheetFeedback)), + description: "Reply faster to messages and increase your chances to a quick sale." + ) + let section3 = PushNotificationNudgingBottomSheetViewModel.Section( + icon: Image(uiImage: UIImage(named: .bottomSheetSearchFavorites)), + description: "Hear instantly of a new match in your saved search or a price drop on a favourite." + ) + + let allowButton = PushNotificationNudgingBottomSheetViewModel.Button( + kind: .allow, + title: "Allow Push Notifications" + ) + let notNowButton = PushNotificationNudgingBottomSheetViewModel.Button( + kind: .notNow, + title: "Not now" + ) + + let viewModel = PushNotificationNudgingBottomSheetViewModel( + title: "Don’t miss out on important stuff", + sections: [section1, section2, section3], + buttons: [allowButton, notNowButton] + ) + + return PushNotificationNudgingBottomSheet(viewModel: viewModel) + } +} diff --git a/Demo/Sources/SwiftUI/PushNotificationNudgingDemoView.swift b/Demo/Sources/SwiftUI/PushNotificationNudgingDemoView.swift new file mode 100644 index 0000000000..5a488df3c7 --- /dev/null +++ b/Demo/Sources/SwiftUI/PushNotificationNudgingDemoView.swift @@ -0,0 +1,30 @@ +import DemoKit +import FinniversKit +import Foundation +import SwiftUI + +struct PushNotificationNudgingDemoView_Previews: PreviewProvider, Demoable { + static var previews: some View { + VStack { + PushNotificationNudgingView(viewModel: PushNotificationNudgingViewModel( + icon: Image(uiImage: UIImage(named: .bellOff)), + title: "Boost your chances of a quick sale!", + description: "Get real-time alerts when buyers message you or express interest in your items.", + state: .initialPrompt + )) + + PushNotificationNudgingView(viewModel: PushNotificationNudgingViewModel( + icon: Image(uiImage: UIImage(named: .bellOff)), + title: "You won’t get notifications for now", + description: "If you change your mind, you can edit your notification settings anytime.", + state: .turnedOff + )) + + PushNotificationNudgingView(viewModel: PushNotificationNudgingViewModel( + icon: Image(uiImage: UIImage(named: .bell)), + title: "You’re all set!", + state: .allSet + )) + } + } +} diff --git a/FinniversKit/FinniversKit.xcodeproj/project.pbxproj b/FinniversKit/FinniversKit.xcodeproj/project.pbxproj index 727b557124..3dbcbb12fc 100644 --- a/FinniversKit/FinniversKit.xcodeproj/project.pbxproj +++ b/FinniversKit/FinniversKit.xcodeproj/project.pbxproj @@ -296,6 +296,10 @@ B2829E2D2C7F054F0032BDFA /* HTMLAttributeStack.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2829E2C2C7F054F0032BDFA /* HTMLAttributeStack.swift */; }; B2829E2F2C7F05D20032BDFA /* LocalizedStringKey+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2829E2E2C7F05D20032BDFA /* LocalizedStringKey+Extensions.swift */; }; B6801C1C2982ECCA004A0F4F /* SettingsHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6801C1B2982ECCA004A0F4F /* SettingsHeaderView.swift */; }; + B6F5ECB12CB56CCA00E24EC3 /* PushNotificationNudgingBottomSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F5ECAA2CB56CCA00E24EC3 /* PushNotificationNudgingBottomSheet.swift */; }; + B6F5ECB22CB56CCA00E24EC3 /* PushNotificationNudgingBottomSheetViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F5ECAB2CB56CCA00E24EC3 /* PushNotificationNudgingBottomSheetViewModel.swift */; }; + B6F5ECB32CB56CCA00E24EC3 /* PushNotificationNudgingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F5ECAD2CB56CCA00E24EC3 /* PushNotificationNudgingView.swift */; }; + B6F5ECB42CB56CCA00E24EC3 /* PushNotificationNudgingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6F5ECAE2CB56CCA00E24EC3 /* PushNotificationNudgingViewModel.swift */; }; CBD2F08D20615990002AA385 /* TextField+State.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBD2F08C20615990002AA385 /* TextField+State.swift */; }; CF05B7E023325968003A7F1C /* FavoriteFolderActionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF05B7DF23325968003A7F1C /* FavoriteFolderActionButton.swift */; }; CF05BA02233B78BC003A7F1C /* FavoriteSearchEmptyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF05BA01233B78BC003A7F1C /* FavoriteSearchEmptyView.swift */; }; @@ -736,6 +740,10 @@ B2829E2C2C7F054F0032BDFA /* HTMLAttributeStack.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HTMLAttributeStack.swift; sourceTree = ""; }; B2829E2E2C7F05D20032BDFA /* LocalizedStringKey+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "LocalizedStringKey+Extensions.swift"; sourceTree = ""; }; B6801C1B2982ECCA004A0F4F /* SettingsHeaderView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsHeaderView.swift; sourceTree = ""; }; + B6F5ECAA2CB56CCA00E24EC3 /* PushNotificationNudgingBottomSheet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PushNotificationNudgingBottomSheet.swift; sourceTree = ""; }; + B6F5ECAB2CB56CCA00E24EC3 /* PushNotificationNudgingBottomSheetViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PushNotificationNudgingBottomSheetViewModel.swift; sourceTree = ""; }; + B6F5ECAD2CB56CCA00E24EC3 /* PushNotificationNudgingView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PushNotificationNudgingView.swift; sourceTree = ""; }; + B6F5ECAE2CB56CCA00E24EC3 /* PushNotificationNudgingViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PushNotificationNudgingViewModel.swift; sourceTree = ""; }; CB3CF1561F73E5870041EF20 /* FinniversKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = FinniversKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; CBD2F08C20615990002AA385 /* TextField+State.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TextField+State.swift"; sourceTree = ""; }; CF05B7DF23325968003A7F1C /* FavoriteFolderActionButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteFolderActionButton.swift; sourceTree = ""; }; @@ -1392,6 +1400,7 @@ CF0F6B902360682100CA62FD /* Priming */, D7D514C227293F5D0065E2F6 /* PromotionView */, F2C3E95A22CB634700CED7E0 /* QuestionnaireView */, + B6F5ECB02CB56CCA00E24EC3 /* PushNotificationNudgingView */, CF8F024321DE0FF9004C4042 /* RefreshControl */, 9A37D8B81C3158FE1373F3E4 /* RemoteImageView */, F2772F3F2280397E0002D21F /* ReviewButtonView */, @@ -2343,6 +2352,33 @@ path = Sources/Components/NMPInfobox; sourceTree = SOURCE_ROOT; }; + B6F5ECAC2CB56CCA00E24EC3 /* PushNotificationNudgingBottomSheet */ = { + isa = PBXGroup; + children = ( + B6F5ECAA2CB56CCA00E24EC3 /* PushNotificationNudgingBottomSheet.swift */, + B6F5ECAB2CB56CCA00E24EC3 /* PushNotificationNudgingBottomSheetViewModel.swift */, + ); + path = PushNotificationNudgingBottomSheet; + sourceTree = ""; + }; + B6F5ECAF2CB56CCA00E24EC3 /* PushNotificationNudgingView */ = { + isa = PBXGroup; + children = ( + B6F5ECAD2CB56CCA00E24EC3 /* PushNotificationNudgingView.swift */, + B6F5ECAE2CB56CCA00E24EC3 /* PushNotificationNudgingViewModel.swift */, + ); + path = PushNotificationNudgingView; + sourceTree = ""; + }; + B6F5ECB02CB56CCA00E24EC3 /* PushNotificationNudgingView */ = { + isa = PBXGroup; + children = ( + B6F5ECAC2CB56CCA00E24EC3 /* PushNotificationNudgingBottomSheet */, + B6F5ECAF2CB56CCA00E24EC3 /* PushNotificationNudgingView */, + ); + path = PushNotificationNudgingView; + sourceTree = ""; + }; CF0F6B902360682100CA62FD /* Priming */ = { isa = PBXGroup; children = ( @@ -3125,12 +3161,14 @@ 44D9125F2077AC8A00486848 /* EmptyView.swift in Sources */, 44A557B622E72187001667AE /* CheckboxTableViewCell.swift in Sources */, CF376C18231D452100ED2B24 /* Array+Step.swift in Sources */, + B6F5ECB32CB56CCA00E24EC3 /* PushNotificationNudgingView.swift in Sources */, E65085DA292BC03400A43B07 /* SwiftUIRadioButton.swift in Sources */, CF164CFD230EB0F900250822 /* CheckmarkImageView.swift in Sources */, 9B06096823F14B0A005CB592 /* SafetyElementViewModel.swift in Sources */, CF164D15230FFB7400250822 /* FavoriteAdActionViewModel.swift in Sources */, CF136ACD2203211100247B30 /* InfoboxView.swift in Sources */, 4447F6D21FDB2B110033DBC1 /* Label.swift in Sources */, + B6F5ECB12CB56CCA00E24EC3 /* PushNotificationNudgingBottomSheet.swift in Sources */, 179D06A92906A39D00A65E3A /* HTMLStringParser.swift in Sources */, 9B06097023F14BB4005CB592 /* HeaderView.swift in Sources */, AF91BBA1202C8B72003E6366 /* Broadcast+Style.swift in Sources */, @@ -3425,6 +3463,7 @@ E65085D4292BBF7500A43B07 /* StatefulPreviewWrapper.swift in Sources */, 9A37D9EDC4E78EC664D528FE /* FeedbackView.swift in Sources */, 5DCE0882280FDDF100ED7407 /* MonthAndYearPickerView.swift in Sources */, + B6F5ECB42CB56CCA00E24EC3 /* PushNotificationNudgingViewModel.swift in Sources */, 9F213438F5413991D1B3D7CD /* FullscreenGalleryViewModel.swift in Sources */, 9F2138937E903BEA8F7A8C7C /* FullscreenGalleryViewController.swift in Sources */, CFF54E2E234E192A008E18BE /* FavoriteAdsSubtitleView.swift in Sources */, @@ -3457,6 +3496,7 @@ DA083E7324630BC400B26235 /* SettingsSection.swift in Sources */, 494047FE23CDBBA100ECBCFD /* ViewingItemViewModel.swift in Sources */, CF05B7E023325968003A7F1C /* FavoriteFolderActionButton.swift in Sources */, + B6F5ECB22CB56CCA00E24EC3 /* PushNotificationNudgingBottomSheetViewModel.swift in Sources */, F253C50E2313F9F5008175FD /* VerificationView.swift in Sources */, 0379D1EE2AB3321300CC1B38 /* UIImage+FinniversKit.swift in Sources */, 9A37DC6E6F0401357C564B93 /* RemoteImageView.swift in Sources */, diff --git a/FinniversKit/Sources/Assets/Assets.xcassets/bell.imageset/Contents.json b/FinniversKit/Sources/Assets/Assets.xcassets/bell.imageset/Contents.json new file mode 100644 index 0000000000..45f609bc71 --- /dev/null +++ b/FinniversKit/Sources/Assets/Assets.xcassets/bell.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "bell.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/FinniversKit/Sources/Assets/Assets.xcassets/bell.imageset/bell.pdf b/FinniversKit/Sources/Assets/Assets.xcassets/bell.imageset/bell.pdf new file mode 100644 index 0000000000000000000000000000000000000000..cffca78c4bbe41100764bd28c627b1e30adcaeb2 GIT binary patch literal 2546 zcmZXWc|6qp7RT!;OQTyxgA(;4WKhg7B>ULLkPIG6*_qo6W5#TfrNUSe!;od74UbSn znv@6Gg+|7%o06qMlqK>|-I@08J%9XO-{1T7JLh}O`Tg)juORrZT*DGipkXP1h9$v=hBe3fk^Hgz41Q?XVu>ecI6#a4xdR{Z zD^O_^tWOXqbYn)g4O0;z9=AeItlOX$@}X8paiAWIjxm{**^=D6y85ZSlifSgV?tD3 zvx(o=I8WhTzheA(aq#0J>B0Jkh2FPSM_+lZ+^Tv&niu_4!+6!XeJ$wBd1QWnNs8h7 z+@{WtJvUUeP(ne!H9r$vN~Rzzx9Q3fkpY9;` z>X0Q#Sy9jC=y|0Mo~47_Iv6o00ycMhA?CoXV4DY*d!(0*E6;9TiqGP-tWdoTjN6tW zVea0>kD#r&!M85Ns=vq((O(#yA_OC!O3dCAQbu6(O1D>bfKHF{SO^8Bwz)H?@h@1`+ZyW9h zLi|x-CP!8Lk+=3BhMR!$(}i2A#Am+S%?ojT^NH<@`%p%YE4F5xS6Z{tcbJV35=!2f zlc(o;S3NtxuI4PR)D~(#ntuKzT;|51nt@lFcbH2GZwj>D)Mirax(rcu^YFs;F;3fe z!KTckwieo5+yIt+EfE0TBEOB8hl`4gMNW5)N@$h3cONq7u`lwyoFC9U#FL>l!5eM* zkji8sM}<{6mO(p<+|GU|Q)wysr;*g=bc{r_PZEa-R5wUTXzcjwF9ai~ydpmwY>m%T zWH>xOu&f;O+(kI=ZQw&pp{T4-G#rdL%qWU|b4)H|k)B*>dc(dHQk-8;pf+C%EOF#y z$a>}(-o0N&A67Kq_LyFvFc))p#8Y^t<=0t0{Du&1_%zkpW?a0?iJs>=LbU;1s$-uBWGToQ*Dh_+^?!aU*B*09wn<@OwAj~5g)0= zo4xhZUrgHbmVI)UQx0C`k5JT;ewoN5lTf2L>8X^z4UVuAfd)JxDKdhd#?5ikS-(<1 zehiTxE3rBOdE*Z)auqvSZwgM-CMMX0=5~kD7JM^a>bk8w6Dnqjnt-_VTTa>y?}GDq z!{_M5;6PPZFf+9>uDiS-Wq!C{7?p7#DteRg5qxu(vMe9 zpozI>x#y$%YOlT{xqDy>-}7D=*Fp7;)4nfEVZpo2?OJKkd>|A*m8jVq5h=kU%^&99ZjxH^2oq}nzO{K>>wx4JjKD;&|TU72Vj zS9Pa3mZAQ9iBQP8GQ+zk;xW`^2mctUR%k}t3El7y^W~1U%^oe|FSoT1)hwCAY9Mp59M=BpOCq~HIfVXO>#sI(b*2_7Uz8acSZm9cN$(D_nY*r( z)BbYx{Iu6+mrFc>Jb%;I??Nq5-md}z#&zkdbS`I$(g_}~dx3P|wxtj+oBP@$57uuwn+?+^XD o6b%Owi3SJ;{<2^VM|>ET-~AT{=0l-<83(Qf*9IvmSsb(^b literal 0 HcmV?d00001 diff --git a/FinniversKit/Sources/Assets/Assets.xcassets/bellOff.imageset/Contents.json b/FinniversKit/Sources/Assets/Assets.xcassets/bellOff.imageset/Contents.json new file mode 100644 index 0000000000..18b8a77580 --- /dev/null +++ b/FinniversKit/Sources/Assets/Assets.xcassets/bellOff.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "bellOff.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/FinniversKit/Sources/Assets/Assets.xcassets/bellOff.imageset/bellOff.pdf b/FinniversKit/Sources/Assets/Assets.xcassets/bellOff.imageset/bellOff.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e02b7028a9836ebd4be07f93e1f6456b1ca28265 GIT binary patch literal 3793 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 some View { + HStack(alignment: .center, spacing: Warp.Spacing.spacing200) { + section.icon + .padding(.leading, Warp.Spacing.spacing100) + .accessibilityHidden(true) + + VStack(alignment: .leading, spacing: Warp.Spacing.spacing50) { + if let title = section.title { + Text(title) + .font(from: .bodyStrong) + .fixedSize(horizontal: false, vertical: true) + } + Text(section.description) + .font(from: .body) + .fixedSize(horizontal: false, vertical: true) + } + + Spacer() + } + } + + private func buttonView(_ button: PushNotificationNudgingBottomSheetViewModel.Button) -> some View { + switch button.kind { + case .allow: + return Warp.Button.create( + for: .primary, + title: button.title, + action: { + button.action?() + }, + fullWidth: true + ) + case .notNow: + return Warp.Button.create( + for: .secondary, + title: button.title, + action: { + button.action?() + }, + fullWidth: true + ) + } + } +} + +#Preview { + let section1 = PushNotificationNudgingBottomSheetViewModel.Section( + icon: Image(named: .bell), + description: "Receive alerts the moment a buyer shows interest in your items." + ) + let section2 = PushNotificationNudgingBottomSheetViewModel.Section( + icon: Image(named: .bell), + description: "Respond faster to messages, increasing your chances of making a sale." + ) + let section3 = PushNotificationNudgingBottomSheetViewModel.Section( + icon: Image(named: .bell), + description: "Be the first to know when there’s a new match for your listings or a price drop on items you’re following." + ) + + let allowButton = PushNotificationNudgingBottomSheetViewModel.Button( + kind: .allow, + title: "Allow Push Notifications" + ) + let notNowButton = PushNotificationNudgingBottomSheetViewModel.Button( + kind: .notNow, + title: "Not now" + ) + + let viewModel = PushNotificationNudgingBottomSheetViewModel( + title: "Never miss a beat!", + sections: [section1, section2, section3], + buttons: [allowButton, notNowButton] + ) + + return PushNotificationNudgingBottomSheet(viewModel: viewModel) +} diff --git a/FinniversKit/Sources/Components/PushNotificationNudgingView/PushNotificationNudgingBottomSheet/PushNotificationNudgingBottomSheetViewModel.swift b/FinniversKit/Sources/Components/PushNotificationNudgingView/PushNotificationNudgingBottomSheet/PushNotificationNudgingBottomSheetViewModel.swift new file mode 100644 index 0000000000..cfb2aa9663 --- /dev/null +++ b/FinniversKit/Sources/Components/PushNotificationNudgingView/PushNotificationNudgingBottomSheet/PushNotificationNudgingBottomSheetViewModel.swift @@ -0,0 +1,62 @@ +import SwiftUI + +public struct PushNotificationNudgingBottomSheetViewModel { + let title: String + let sections: [Section] + let buttons: [Button] + + public init(title: String, sections: [Section], buttons: [Button]) { + self.title = title + self.sections = sections + self.buttons = buttons + } + + public struct Section { + let icon: Image + let title: String? + let description: String + + public init(icon: Image, title: String? = nil, description: String) { + self.icon = icon + self.title = title + self.description = description + } + } + + public struct Button { + public enum Kind: Hashable { + case allow + case notNow + } + + let kind: Kind + let title: String + let action: (() -> Void)? + + public init(kind: Kind, title: String, action: (() -> Void)? = nil) { + self.kind = kind + self.title = title + self.action = action + } + } + + +} + +extension PushNotificationNudgingBottomSheetViewModel.Section: Hashable { + public func hash(into hasher: inout Hasher) { + hasher.combine(title) + hasher.combine(description) + } +} + +extension PushNotificationNudgingBottomSheetViewModel.Button: Hashable { + public static func == (lhs: PushNotificationNudgingBottomSheetViewModel.Button, rhs: PushNotificationNudgingBottomSheetViewModel.Button) -> Bool { + lhs.kind == rhs.kind && lhs.title == rhs.title + } + + public func hash(into hasher: inout Hasher) { + hasher.combine(kind) + hasher.combine(title) + } +} diff --git a/FinniversKit/Sources/Components/PushNotificationNudgingView/PushNotificationNudgingView/PushNotificationNudgingView.swift b/FinniversKit/Sources/Components/PushNotificationNudgingView/PushNotificationNudgingView/PushNotificationNudgingView.swift new file mode 100644 index 0000000000..f1e0689812 --- /dev/null +++ b/FinniversKit/Sources/Components/PushNotificationNudgingView/PushNotificationNudgingView/PushNotificationNudgingView.swift @@ -0,0 +1,102 @@ +import SwiftUI +import Warp + +public struct PushNotificationNudgingView: View { + private let layoutMarginsGuideWidth: CGFloat = 685 // Designed to replicate layoutMarginsGuide for cellLayoutMarginsFollowReadableWidth UIKit's tableViews + public static let pushNotificationNudgingViewCellIdentifier = "pushNotificationNudgingViewCellIdentifier" + let viewModel: PushNotificationNudgingViewModel + + public init(viewModel: PushNotificationNudgingViewModel) { + self.viewModel = viewModel + } + + public var body: some View { + if viewModel.layoutMarginsFollowReadableWidth { + HStack { + if UIDevice.current.userInterfaceIdiom == .pad { + Spacer() + } + content + .frame(idealWidth: layoutMarginsGuideWidth, maxWidth: layoutMarginsGuideWidth) + if UIDevice.current.userInterfaceIdiom == .pad { + Spacer() + } + } + } else { + content + } + } + + var content: some View { + VStack(alignment: .leading, spacing: Warp.Spacing.spacing200) { + Divider() + .foregroundColor(.border) + + HStack { + viewModel.icon + .padding(.leading, Warp.Spacing.spacing200) + .padding(.trailing, Warp.Spacing.spacing100) + + VStack(alignment: .leading, spacing: Warp.Spacing.spacing50) { + Text(viewModel.title) + .font(from: .bodyStrong) + .accessibilityLabel(viewModel.title.withoutEmoji()) + if let description = viewModel.description { + Text(description) + .font(from: .caption) + .foregroundColor(.text) + .accessibilityLabel(description.withoutEmoji()) + } + if let linkDescription = viewModel.linkDescription { + Text(linkDescription) + .font(from: .caption) + .foregroundColor(.text) + .multilineTextAlignment(.leading) + .onTapGesture { + viewModel.linkAction?() + } + } + } + + Spacer() + + if viewModel.state == .initialPrompt { + Image(named: .arrowRight) + .padding(.trailing, Warp.Spacing.spacing200) + } + + if viewModel.state == .turnedOff { + SwiftUI.Button(action: { + viewModel.closeButtonAction?() + }, label: { + Image(named: .closeCross) + .renderingMode(.original) + .padding(.trailing, Warp.Spacing.spacing200) + }) + } + + } + + Divider() + .foregroundColor(.border) + } + .accessibilityElement(children: .combine) + } +} + +#Preview { + PushNotificationNudgingView(viewModel: PushNotificationNudgingViewModel( + icon: Image(named: .bellOff), + title: "Boost your chances of a quick sale!", + description: "Get real-time alerts when buyers message you or express interest in your items.", + state: .initialPrompt + )) +} + +#Preview { + PushNotificationNudgingView(viewModel: PushNotificationNudgingViewModel( + icon: Image(named: .bell), + title: "You’re all set!", + state: .allSet + )) +} diff --git a/FinniversKit/Sources/Components/PushNotificationNudgingView/PushNotificationNudgingView/PushNotificationNudgingViewModel.swift b/FinniversKit/Sources/Components/PushNotificationNudgingView/PushNotificationNudgingView/PushNotificationNudgingViewModel.swift new file mode 100644 index 0000000000..1c5c5d59b3 --- /dev/null +++ b/FinniversKit/Sources/Components/PushNotificationNudgingView/PushNotificationNudgingView/PushNotificationNudgingViewModel.swift @@ -0,0 +1,39 @@ +import Foundation +import SwiftUI + +public enum PushNotificationNudgingState { + case initialPrompt + case turnedOff + case allSet +} + +public struct PushNotificationNudgingViewModel { + let icon: Image + let title: String + let description: String? + let linkDescription: AttributedString? + let state: PushNotificationNudgingState + let layoutMarginsFollowReadableWidth: Bool + let linkAction: (() -> Void)? + let closeButtonAction: (() -> Void)? + + public init( + icon: Image, + title: String, + description: String? = nil, + linkDescription: AttributedString? = nil, + state: PushNotificationNudgingState, + layoutMarginsFollowReadableWidth: Bool = false, + linkAction: (() -> Void)? = nil, + closeButtonAction: (() -> Void)? = nil + ) { + self.icon = icon + self.title = title + self.description = description + self.linkDescription = linkDescription + self.state = state + self.layoutMarginsFollowReadableWidth = layoutMarginsFollowReadableWidth + self.linkAction = linkAction + self.closeButtonAction = closeButtonAction + } +} diff --git a/FinniversKit/Sources/Extensions/Foundation/StringExtensions.swift b/FinniversKit/Sources/Extensions/Foundation/StringExtensions.swift index 6c8ddf26ef..f31061a0ac 100644 --- a/FinniversKit/Sources/Extensions/Foundation/StringExtensions.swift +++ b/FinniversKit/Sources/Extensions/Foundation/StringExtensions.swift @@ -32,6 +32,11 @@ public extension String { func asAttributedString(attributes: [NSAttributedString.Key: Any]? = nil) -> NSAttributedString { NSAttributedString(string: self, attributes: attributes) } + + // Extension if we want to ignore emojies for VoiceOver reader + func withoutEmoji() -> String { + filter { $0.isASCII } + } } extension Optional where Wrapped == String {