Browse Source

Merge remote-tracking branch 'origin/dev-swift-d-m' into dev-swift-d

v0.17
Dibya 2 years ago
parent
commit
40a2a1779e
  1. 92
      GME Remit.xcodeproj/project.pbxproj
  2. 11
      GME Remit/Extensions/String+Ext.swift
  3. 8
      GME Remit/Extensions/UIColor+Ext.swift
  4. 30
      GME Remit/Extensions/UIFont+Ext.swift
  5. 110
      GME Remit/Extensions/UIView+Ext.swift
  6. 4
      GME Remit/Modules/ExchangeRates/Application Logic/Interactor/ExchangeRatesInteractorIO.swift
  7. 28
      GME Remit/Modules/ExchangeRates/User Interface/Presenter/ExchangeRatesPresenter.swift
  8. 3
      GME Remit/Modules/ExchangeRates/User Interface/View/ExchangeRatesViewController.swift
  9. 72
      GME Remit/Modules/Home/Application Logic/Interactor/HomeInteractor.swift
  10. 11
      GME Remit/Modules/Home/Application Logic/Interactor/HomeInteractorIO.swift
  11. 4
      GME Remit/Modules/Home/Module Interface/HomeModuleInterface.swift
  12. 25
      GME Remit/Modules/Home/User Interface/Presenter/HomePresenter.swift
  13. 67
      GME Remit/Modules/Home/User Interface/View/Cell/CarouselCell.swift
  14. 10
      GME Remit/Modules/Home/User Interface/View/Cell/HomeCollectionCollectionViewCell.swift
  15. 183
      GME Remit/Modules/Home/User Interface/View/Cell/HomeCollectionTableViewCell.swift
  16. 89
      GME Remit/Modules/Home/User Interface/View/Cell/HomeExchangeRateCollectionViewCell.swift
  17. 47
      GME Remit/Modules/Home/User Interface/View/Cell/HomeRemainingLimitTableViewCell.swift
  18. 184
      GME Remit/Modules/Home/User Interface/View/Custom/HomeAccountDetailView.swift
  19. 207
      GME Remit/Modules/Home/User Interface/View/Custom/HomeCarouselView.swift
  20. 527
      GME Remit/Modules/Home/User Interface/View/Custom/HomeExchangeRateView.swift
  21. 457
      GME Remit/Modules/Home/User Interface/View/Home.storyboard
  22. 244
      GME Remit/Modules/Home/User Interface/View/HomeViewController.swift
  23. 221
      GME Remit/Modules/Home/User Interface/View/HomeViewControllerNew.swift
  24. 7
      GME Remit/Modules/Home/User Interface/View/HomeViewInterface.swift
  25. 5
      GME Remit/Modules/Home/User Interface/Wireframe/HomeWireframe.swift
  26. 21
      GME Remit/Modules/Main/User Interface/View/MainViewController.swift
  27. 21
      GME Remit/Supported Files/Assets.xcassets/customer_support_new.imageset/Contents.json
  28. 14
      GME Remit/Supported Files/Assets.xcassets/customer_support_new.imageset/Group 10616.svg
  29. 21
      GME Remit/Supported Files/Assets.xcassets/exchangeRateButton.imageset/Contents.json
  30. 10
      GME Remit/Supported Files/Assets.xcassets/exchangeRateButton.imageset/exchangeRateButton.svg
  31. 21
      GME Remit/Supported Files/Assets.xcassets/exchange_rate_guranteed.imageset/Contents.json
  32. 11
      GME Remit/Supported Files/Assets.xcassets/exchange_rate_guranteed.imageset/guranteed.svg
  33. 21
      GME Remit/Supported Files/Assets.xcassets/exchange_rate_transfer_fee.imageset/Contents.json
  34. 14
      GME Remit/Supported Files/Assets.xcassets/exchange_rate_transfer_fee.imageset/transfer.svg
  35. 21
      GME Remit/Supported Files/Assets.xcassets/ic_notification_dot_new.imageset/Contents.json
  36. 15
      GME Remit/Supported Files/Assets.xcassets/ic_notification_dot_new.imageset/Group 10556.svg
  37. 21
      GME Remit/Supported Files/Assets.xcassets/notification_bell_new.imageset/Contents.json
  38. 9
      GME Remit/Supported Files/Assets.xcassets/notification_bell_new.imageset/Group 10401.svg
  39. 6
      GME Remit/Supported Files/Assets.xcassets/tabbar/Contents.json
  40. 21
      GME Remit/Supported Files/Assets.xcassets/tabbar/tab-contact-selected.imageset/Contents.json
  41. 8
      GME Remit/Supported Files/Assets.xcassets/tabbar/tab-contact-selected.imageset/style_black_24dp.svg
  42. 21
      GME Remit/Supported Files/Assets.xcassets/tabbar/tab-contact.imageset/Contents.json
  43. 8
      GME Remit/Supported Files/Assets.xcassets/tabbar/tab-contact.imageset/style_black_24dp (1).svg
  44. 21
      GME Remit/Supported Files/Assets.xcassets/tabbar/tab-home-selected.imageset/Contents.json
  45. 10
      GME Remit/Supported Files/Assets.xcassets/tabbar/tab-home-selected.imageset/Group 10878.svg
  46. 21
      GME Remit/Supported Files/Assets.xcassets/tabbar/tab-home.imageset/Contents.json
  47. 10
      GME Remit/Supported Files/Assets.xcassets/tabbar/tab-home.imageset/Group 10877.svg
  48. 27
      GME Remit/Supported Files/Info.plist
  49. BIN
      GME Remit/Supported Files/Volte/volte-bold.otf
  50. BIN
      GME Remit/Supported Files/Volte/volte-bolditalic.otf
  51. BIN
      GME Remit/Supported Files/Volte/volte-light.otf
  52. BIN
      GME Remit/Supported Files/Volte/volte-lightitalic.otf
  53. BIN
      GME Remit/Supported Files/Volte/volte-medium.otf
  54. BIN
      GME Remit/Supported Files/Volte/volte-mediumitalic.otf
  55. BIN
      GME Remit/Supported Files/Volte/volte-regular.otf
  56. BIN
      GME Remit/Supported Files/Volte/volte-regularitalic.otf
  57. BIN
      GME Remit/Supported Files/Volte/volte-semibold.otf
  58. BIN
      GME Remit/Supported Files/Volte/volte-semibolditalic.otf
  59. 95
      GME Remit/Utilities/CustomUI/CurrencyTextField.swift
  60. 130
      GME Remit/Utilities/CustomUI/CustomPageControl.swift
  61. 172
      GME Remit/Utilities/ExchangeRateCustomView.swift
  62. 6
      GME Remit/Utilities/TabBar Helper/CustomItemTabView.swift
  63. 3
      GME Remit/Utilities/TabBar Helper/CustomTabBar.swift
  64. 8
      GME Remit/Utilities/TabBar Helper/CustomTabItem.swift

92
GME Remit.xcodeproj/project.pbxproj

@ -32,7 +32,26 @@
241796D729B3825E005D8219 /* LoyalityPointsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 241796D629B3825E005D8219 /* LoyalityPointsModel.swift */; };
241796DE29B390DD005D8219 /* CustomTabItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 241796DD29B390DD005D8219 /* CustomTabItem.swift */; };
241796E029B3931C005D8219 /* CustomItemTabView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 241796DF29B3931C005D8219 /* CustomItemTabView.swift */; };
244C69B429B780A000D7B69A /* HomeViewControllerNew.swift in Sources */ = {isa = PBXBuildFile; fileRef = 244C69B329B780A000D7B69A /* HomeViewControllerNew.swift */; };
244C69B729B7A01600D7B69A /* HomeAccountDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 244C69B629B7A01600D7B69A /* HomeAccountDetailView.swift */; };
2454866629BA2AE60065E1DD /* volte-light.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2454865C29BA2AE60065E1DD /* volte-light.otf */; };
2454866729BA2AE60065E1DD /* volte-medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2454865D29BA2AE60065E1DD /* volte-medium.otf */; };
2454866829BA2AE60065E1DD /* volte-bold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2454865E29BA2AE60065E1DD /* volte-bold.otf */; };
2454866929BA2AE60065E1DD /* volte-mediumitalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2454865F29BA2AE60065E1DD /* volte-mediumitalic.otf */; };
2454866A29BA2AE60065E1DD /* volte-bolditalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2454866029BA2AE60065E1DD /* volte-bolditalic.otf */; };
2454866B29BA2AE60065E1DD /* volte-regular.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2454866129BA2AE60065E1DD /* volte-regular.otf */; };
2454866C29BA2AE60065E1DD /* volte-semibolditalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2454866229BA2AE60065E1DD /* volte-semibolditalic.otf */; };
2454866D29BA2AE60065E1DD /* volte-lightitalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2454866329BA2AE60065E1DD /* volte-lightitalic.otf */; };
2454866E29BA2AE60065E1DD /* volte-semibold.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2454866429BA2AE60065E1DD /* volte-semibold.otf */; };
2454866F29BA2AE60065E1DD /* volte-regularitalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 2454866529BA2AE60065E1DD /* volte-regularitalic.otf */; };
247222DE29C7419800732E55 /* HomeCarouselView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 247222DD29C7419800732E55 /* HomeCarouselView.swift */; };
247222E029C7425700732E55 /* CarouselCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 247222DF29C7425700732E55 /* CarouselCell.swift */; };
247222E529C74AE600732E55 /* CustomPageControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 247222E429C74AE600732E55 /* CustomPageControl.swift */; };
247A601629B4428500922B7F /* CustomTabBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 247A601529B4428500922B7F /* CustomTabBar.swift */; };
24A4502029B831EF0049CE29 /* HomeExchangeRateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A4501F29B831EF0049CE29 /* HomeExchangeRateView.swift */; };
24A4502229B83A710049CE29 /* HomeExchangeRateCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A4502129B83A710049CE29 /* HomeExchangeRateCollectionViewCell.swift */; };
24A4502429B8473B0049CE29 /* ExchangeRateCustomView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A4502329B8473B0049CE29 /* ExchangeRateCustomView.swift */; };
24A4502629B849920049CE29 /* CurrencyTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A4502529B849920049CE29 /* CurrencyTextField.swift */; };
281EF60028ACCC4D0092E5E6 /* HowToDepositModuleInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 281EF5ED28ACCC4D0092E5E6 /* HowToDepositModuleInterface.swift */; };
281EF60128ACCC4D0092E5E6 /* HowToDepositService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 281EF5F028ACCC4D0092E5E6 /* HowToDepositService.swift */; };
281EF60228ACCC4D0092E5E6 /* HowToDepositServiceType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 281EF5F128ACCC4D0092E5E6 /* HowToDepositServiceType.swift */; };
@ -863,7 +882,26 @@
241796D629B3825E005D8219 /* LoyalityPointsModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoyalityPointsModel.swift; sourceTree = "<group>"; };
241796DD29B390DD005D8219 /* CustomTabItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTabItem.swift; sourceTree = "<group>"; };
241796DF29B3931C005D8219 /* CustomItemTabView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomItemTabView.swift; sourceTree = "<group>"; };
244C69B329B780A000D7B69A /* HomeViewControllerNew.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeViewControllerNew.swift; sourceTree = "<group>"; };
244C69B629B7A01600D7B69A /* HomeAccountDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeAccountDetailView.swift; sourceTree = "<group>"; };
2454865C29BA2AE60065E1DD /* volte-light.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "volte-light.otf"; sourceTree = "<group>"; };
2454865D29BA2AE60065E1DD /* volte-medium.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "volte-medium.otf"; sourceTree = "<group>"; };
2454865E29BA2AE60065E1DD /* volte-bold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "volte-bold.otf"; sourceTree = "<group>"; };
2454865F29BA2AE60065E1DD /* volte-mediumitalic.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "volte-mediumitalic.otf"; sourceTree = "<group>"; };
2454866029BA2AE60065E1DD /* volte-bolditalic.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "volte-bolditalic.otf"; sourceTree = "<group>"; };
2454866129BA2AE60065E1DD /* volte-regular.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "volte-regular.otf"; sourceTree = "<group>"; };
2454866229BA2AE60065E1DD /* volte-semibolditalic.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "volte-semibolditalic.otf"; sourceTree = "<group>"; };
2454866329BA2AE60065E1DD /* volte-lightitalic.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "volte-lightitalic.otf"; sourceTree = "<group>"; };
2454866429BA2AE60065E1DD /* volte-semibold.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "volte-semibold.otf"; sourceTree = "<group>"; };
2454866529BA2AE60065E1DD /* volte-regularitalic.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "volte-regularitalic.otf"; sourceTree = "<group>"; };
247222DD29C7419800732E55 /* HomeCarouselView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeCarouselView.swift; sourceTree = "<group>"; };
247222DF29C7425700732E55 /* CarouselCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CarouselCell.swift; sourceTree = "<group>"; };
247222E429C74AE600732E55 /* CustomPageControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomPageControl.swift; sourceTree = "<group>"; };
247A601529B4428500922B7F /* CustomTabBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTabBar.swift; sourceTree = "<group>"; };
24A4501F29B831EF0049CE29 /* HomeExchangeRateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeExchangeRateView.swift; sourceTree = "<group>"; };
24A4502129B83A710049CE29 /* HomeExchangeRateCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeExchangeRateCollectionViewCell.swift; sourceTree = "<group>"; };
24A4502329B8473B0049CE29 /* ExchangeRateCustomView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExchangeRateCustomView.swift; sourceTree = "<group>"; };
24A4502529B849920049CE29 /* CurrencyTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CurrencyTextField.swift; sourceTree = "<group>"; };
281EF5ED28ACCC4D0092E5E6 /* HowToDepositModuleInterface.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HowToDepositModuleInterface.swift; sourceTree = "<group>"; };
281EF5F028ACCC4D0092E5E6 /* HowToDepositService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HowToDepositService.swift; sourceTree = "<group>"; };
281EF5F128ACCC4D0092E5E6 /* HowToDepositServiceType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HowToDepositServiceType.swift; sourceTree = "<group>"; };
@ -1836,6 +1874,33 @@
path = "TabBar Helper";
sourceTree = "<group>";
};
244C69B529B79FF500D7B69A /* Custom */ = {
isa = PBXGroup;
children = (
244C69B629B7A01600D7B69A /* HomeAccountDetailView.swift */,
24A4501F29B831EF0049CE29 /* HomeExchangeRateView.swift */,
247222DD29C7419800732E55 /* HomeCarouselView.swift */,
);
path = Custom;
sourceTree = "<group>";
};
2454865B29BA2AE60065E1DD /* Volte */ = {
isa = PBXGroup;
children = (
2454865C29BA2AE60065E1DD /* volte-light.otf */,
2454865D29BA2AE60065E1DD /* volte-medium.otf */,
2454865E29BA2AE60065E1DD /* volte-bold.otf */,
2454865F29BA2AE60065E1DD /* volte-mediumitalic.otf */,
2454866029BA2AE60065E1DD /* volte-bolditalic.otf */,
2454866129BA2AE60065E1DD /* volte-regular.otf */,
2454866229BA2AE60065E1DD /* volte-semibolditalic.otf */,
2454866329BA2AE60065E1DD /* volte-lightitalic.otf */,
2454866429BA2AE60065E1DD /* volte-semibold.otf */,
2454866529BA2AE60065E1DD /* volte-regularitalic.otf */,
);
path = Volte;
sourceTree = "<group>";
};
281EF5EB28ACCC4D0092E5E6 /* HowToDeposit */ = {
isa = PBXGroup;
children = (
@ -3013,6 +3078,7 @@
73168A1D22F3CAB600878038 /* Supported Files */ = {
isa = PBXGroup;
children = (
2454865B29BA2AE60065E1DD /* Volte */,
73AF9C6B275CB708003A701E /* GoogleService-Info.plist */,
731D05722341BE78005E6F7C /* Colors.xcassets */,
9FD260FE1FD00458007A511D /* Assets.xcassets */,
@ -3368,6 +3434,7 @@
733A3BA02355575F00E6B87E /* CustomUI */ = {
isa = PBXGroup;
children = (
24A4502529B849920049CE29 /* CurrencyTextField.swift */,
7310ED54272EE0A200B5CEF8 /* PasswordConfirm */,
7318F84823BD7A01002BE004 /* CheckBox */,
7327568823B052C000BF66C5 /* PDFVIewer */,
@ -3383,6 +3450,7 @@
7384B27F22CB375400DD04D9 /* GMEAlert */,
4099AF0025235C45003FA012 /* CircleBorderedView.swift */,
4073BA9125295F5B0043258E /* GradientView.swift */,
247222E429C74AE600732E55 /* CustomPageControl.swift */,
);
path = CustomUI;
sourceTree = "<group>";
@ -6108,11 +6176,13 @@
D950BECC21549242008367A1 /* View */ = {
isa = PBXGroup;
children = (
244C69B529B79FF500D7B69A /* Custom */,
D950BEDC215496C0008367A1 /* Cell */,
D950BECD21549242008367A1 /* ViewModels */,
D950BECE21549242008367A1 /* Home.storyboard */,
D950BECF21549242008367A1 /* HomeViewController.swift */,
D950BED021549242008367A1 /* HomeViewInterface.swift */,
244C69B329B780A000D7B69A /* HomeViewControllerNew.swift */,
);
path = View;
sourceTree = "<group>";
@ -6131,6 +6201,8 @@
D950BEDD215496F6008367A1 /* HomeRemainingLimitTableViewCell.swift */,
D9AFE855215C7166005F3A25 /* HomeCollectionTableViewCell.swift */,
D923EBB8215C7421008A3026 /* HomeCollectionCollectionViewCell.swift */,
24A4502129B83A710049CE29 /* HomeExchangeRateCollectionViewCell.swift */,
247222DF29C7425700732E55 /* CarouselCell.swift */,
);
path = Cell;
sourceTree = "<group>";
@ -6274,6 +6346,7 @@
7383F43422DEB864003D6393 /* Database */,
73895FF522C2F208003FEA90 /* TablePresenter */,
D95B7044213FB5F00053CC3D /* WebLinks */,
24A4502329B8473B0049CE29 /* ExchangeRateCustomView.swift */,
);
path = Utilities;
sourceTree = "<group>";
@ -7067,6 +7140,7 @@
5565FF1E1FE275E5002934E9 /* SanFranciscoText-RegularItalic.otf in Resources */,
73D3F3E4270C65B5006C3F97 /* CDDIViewController.storyboard in Resources */,
5E85DDE7289429AA00BE7CA5 /* Lawson.storyboard in Resources */,
2454866D29BA2AE60065E1DD /* volte-lightitalic.otf in Resources */,
D9DC1060216314BC008F3C51 /* SideMenu.storyboard in Resources */,
89739E4024459A630016251B /* SendMoneyReceipt.storyboard in Resources */,
4060B97924DBBA0300E90F8C /* KYCVerifyStep1.storyboard in Resources */,
@ -7081,6 +7155,7 @@
738714BA237CE86E0038FCB1 /* InboundReceipt.storyboard in Resources */,
7327568C23B052DB00BF66C5 /* PDFViewController.xib in Resources */,
7EDBFC0824B3031B00AD5D4D /* WithdrawFromWallet.storyboard in Resources */,
2454866829BA2AE60065E1DD /* volte-bold.otf in Resources */,
5565FF201FE275E5002934E9 /* SanFranciscoDisplay-Ultralight.otf in Resources */,
733A3BA52355580000E6B87E /* CreditCardView.xib in Resources */,
D96BD11D216479E200DFE7D8 /* WalletStatement.storyboard in Resources */,
@ -7093,6 +7168,7 @@
5565FF2B1FE275E5002934E9 /* SanFranciscoText-Heavy.otf in Resources */,
5565FF301FE275E5002934E9 /* SanFranciscoText-Light.otf in Resources */,
5565FF321FE275E5002934E9 /* SanFranciscoDisplay-Semibold.otf in Resources */,
2454866729BA2AE60065E1DD /* volte-medium.otf in Resources */,
89739E4D24459A630016251B /* SendMoneyExchangeRate.storyboard in Resources */,
405718D324D932AE0022CDDE /* NewUserRegister.storyboard in Resources */,
405718F524D93EB40022CDDE /* VerifyIDNumber.storyboard in Resources */,
@ -7114,6 +7190,7 @@
89EA0D8A243EC1C6003ACCC8 /* ChangePersonalInformation.storyboard in Resources */,
D9031144214786EA00AD5BA9 /* ForgotPassword.storyboard in Resources */,
405AA16E2541DB6D00508420 /* Localizable.strings in Resources */,
2454866F29BA2AE60065E1DD /* volte-regularitalic.otf in Resources */,
D97785A5215DC55F00754079 /* TransactionHistory.storyboard in Resources */,
5565FF231FE275E5002934E9 /* SanFranciscoText-BoldItalic.otf in Resources */,
5565FF221FE275E5002934E9 /* SanFranciscoDisplay-Light.otf in Resources */,
@ -7122,12 +7199,15 @@
73AEFF7A2334A13100A967FB /* TransactionHistoryGroup.storyboard in Resources */,
404654BA24E6666F000E5BFB /* PINKeyboardView.xib in Resources */,
89739E3424459A630016251B /* SendMoneyParent.storyboard in Resources */,
2454866A29BA2AE60065E1DD /* volte-bolditalic.otf in Resources */,
2454866C29BA2AE60065E1DD /* volte-semibolditalic.otf in Resources */,
5565FF271FE275E5002934E9 /* README.md in Resources */,
281EF60928ACCC4D0092E5E6 /* HowToDeposit.storyboard in Resources */,
D95B5E4221311057000C0B33 /* GmeContacts.storyboard in Resources */,
89EA0D25243EC0D2003ACCC8 /* Profile.storyboard in Resources */,
D950BED921549242008367A1 /* Home.storyboard in Resources */,
40B33AAD24CAF87A00AFE2AB /* ExistingUserRegistration.storyboard in Resources */,
2454866B29BA2AE60065E1DD /* volte-regular.otf in Resources */,
D931E22A216DCC2A008A8CD1 /* MessageCompose.storyboard in Resources */,
7327568623B0456400BF66C5 /* ManageAgreement.storyboard in Resources */,
7E364CEC24A4455A007D6E02 /* PasswordInputViewController.xib in Resources */,
@ -7143,9 +7223,12 @@
5565FF291FE275E5002934E9 /* SanFranciscoDisplay-Black.otf in Resources */,
FF6E7D9421BF951D00A003B9 /* AppUpdate.storyboard in Resources */,
D9692A1B221396AF00795EBC /* Setting.storyboard in Resources */,
2454866E29BA2AE60065E1DD /* volte-semibold.otf in Resources */,
73195ABC22FD14D500151434 /* SetupRecipient.storyboard in Resources */,
5EC4638028AA2611006B5FDC /* NotificationList.storyboard in Resources */,
2454866629BA2AE60065E1DD /* volte-light.otf in Resources */,
892F9E8E243DB0F300D9D88C /* ShowAPI.storyboard in Resources */,
2454866929BA2AE60065E1DD /* volte-mediumitalic.otf in Resources */,
735F68E22394A76800A2DBC8 /* NewRegister.storyboard in Resources */,
D96A4FDD21460B4A00CFD507 /* SplashScreen.storyboard in Resources */,
5565FF261FE275E5002934E9 /* SanFranciscoText-SemiboldItalic.otf in Resources */,
@ -7692,6 +7775,7 @@
D95B5E4121311057000C0B33 /* GmeContactsViewInterface.swift in Sources */,
73157BA022DC1EEC009B836F /* PopupNotificationPresenter.swift in Sources */,
73157BA322DC1EEC009B836F /* PopupNotificationViewInterface.swift in Sources */,
247222DE29C7419800732E55 /* HomeCarouselView.swift in Sources */,
7388A6D822E17F9400A57891 /* CountryEnum.swift in Sources */,
D97785A6215DC55F00754079 /* TransactionHistoryViewController.swift in Sources */,
40218EFB24D2B1940047FBF5 /* UserRegistrationInteractor.swift in Sources */,
@ -7760,6 +7844,7 @@
73FBBF2C23F231A8009D7627 /* DetailNotificationViewController.swift in Sources */,
D9DC107A21639078008F3C51 /* MessageComposeService.swift in Sources */,
7EDBFBFE24B3031B00AD5D4D /* WithdrawFromWalletModuleInterface.swift in Sources */,
247222E029C7425700732E55 /* CarouselCell.swift in Sources */,
73FBBF2623F231A8009D7627 /* DetailNotificationInteractor.swift in Sources */,
28AB139B28E552C200191695 /* NotificationDetailViewController.swift in Sources */,
D96A4FD521460B4A00CFD507 /* SplashScreenService.swift in Sources */,
@ -7787,6 +7872,7 @@
40CB8F5824D980D500E1E64E /* NewRegisterRequestModel.swift in Sources */,
73157B9C22DC1EEC009B836F /* PopupNotificationServiceType.swift in Sources */,
7327568323B0456400BF66C5 /* ManageAgreementPresenter.swift in Sources */,
244C69B429B780A000D7B69A /* HomeViewControllerNew.swift in Sources */,
89EA0D8B243EC1C6003ACCC8 /* ChangePersonalInformationViewInterface.swift in Sources */,
41F06FB729B712A2008E9E5D /* TransferListWireframeInput.swift in Sources */,
89739E3624459A630016251B /* SendMoneyReceiptModuleInterface.swift in Sources */,
@ -7932,6 +8018,7 @@
73195AB522FD14D500151434 /* SetupRecipientInteractorIO.swift in Sources */,
405718EE24D93EB40022CDDE /* VerifyIDNumberInteractorIO.swift in Sources */,
0496B8481FE7DFA20044810E /* RestApiManager.swift in Sources */,
24A4502629B849920049CE29 /* CurrencyTextField.swift in Sources */,
73FBBF2523F231A8009D7627 /* DetailNotificationServiceType.swift in Sources */,
73AEFF702334A13100A967FB /* TransactionHistoryGroupModuleInterface.swift in Sources */,
4060B97624DBBA0300E90F8C /* KYCVerifyStep1Presenter.swift in Sources */,
@ -8109,6 +8196,7 @@
89739E3124459A630016251B /* SendMoneyParentWireframeInput.swift in Sources */,
405AA0EF2541B32B00508420 /* PropertyUtility.swift in Sources */,
D950BED321549242008367A1 /* HomeService.swift in Sources */,
244C69B729B7A01600D7B69A /* HomeAccountDetailView.swift in Sources */,
7EDBFBDF24B2C5DA00AD5D4D /* RedeemCashPickUpWireframeInput.swift in Sources */,
7327568123B0456400BF66C5 /* ManageAgreementInteractorIO.swift in Sources */,
738714B6237CE86E0038FCB1 /* InboundReceiptInteractorIO.swift in Sources */,
@ -8122,6 +8210,7 @@
405213D224EA83A4000F8801 /* ProfileChangePinViewController.swift in Sources */,
7EC9DE0524A9AF65004A0AD8 /* BranchContainer.swift in Sources */,
949C5F7A28B2013800E50E31 /* InviteUserModuleInterface.swift in Sources */,
24A4502029B831EF0049CE29 /* HomeExchangeRateView.swift in Sources */,
73210DAF22FBF2BA00715D6C /* ViewModelType.swift in Sources */,
89739E3224459A630016251B /* SenMoneyPaymentModeRecipientViewModel.swift in Sources */,
241796CF29B3810C005D8219 /* LoyalityPointsInteractorIO.swift in Sources */,
@ -8171,6 +8260,7 @@
739F8187234AFF13003ABCF3 /* DebugManager.swift in Sources */,
40218EF724D2B1940047FBF5 /* UserRegistrationModuleInterface.swift in Sources */,
7E364CEF24A46D27007D6E02 /* BalanceModel.swift in Sources */,
24A4502229B83A710049CE29 /* HomeExchangeRateCollectionViewCell.swift in Sources */,
D96BD11B216479E200DFE7D8 /* WalletStatementWireframe.swift in Sources */,
D96BD116216479E200DFE7D8 /* WalletStatementServiceType.swift in Sources */,
D946719621426DFB003924DB /* LoginService.swift in Sources */,
@ -8193,6 +8283,7 @@
7318534E230EACA400BA9AE3 /* SendMoneyTransFerReasonViewModel.swift in Sources */,
281EF60528ACCC4D0092E5E6 /* HowToDepositPresenter.swift in Sources */,
73195ABB22FD14D500151434 /* SetupRecipientViewModelInterface.swift in Sources */,
247222E529C74AE600732E55 /* CustomPageControl.swift in Sources */,
7389601922C2FADD003FEA90 /* TableCell.swift in Sources */,
D92B802A2140C3CB00A25B26 /* MainPresenter.swift in Sources */,
738714B4237CE86E0038FCB1 /* InboundReceiptServiceType.swift in Sources */,
@ -8213,6 +8304,7 @@
7EDBFC0124B3031B00AD5D4D /* WithdrawFromWalletInteractorIO.swift in Sources */,
41F06FB429B712A2008E9E5D /* TransferListInteractor.swift in Sources */,
405718CE24D932AD0022CDDE /* NewUserRegisterPresenter.swift in Sources */,
24A4502429B8473B0049CE29 /* ExchangeRateCustomView.swift in Sources */,
89739E5F24459A630016251B /* SendMoneyVerificationPresenter.swift in Sources */,
89EA0D83243EC1C5003ACCC8 /* ChangePersonalInformationService.swift in Sources */,
D92B80272140C3CB00A25B26 /* MainServiceType.swift in Sources */,

11
GME Remit/Extensions/String+Ext.swift

@ -7,6 +7,7 @@
//
import Foundation
import UIKit
enum CurrencyType {
case usd
@ -128,3 +129,13 @@ extension String{
return predicate.evaluate(with: self)
}
}
extension String {
func attributedText(color: UIColor, font: UIFont) -> NSMutableAttributedString {
let range = (self as NSString).range(of: self)
let attributedString = NSMutableAttributedString(string:self)
attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: color, range: range)
attributedString.addAttribute(NSAttributedString.Key.font, value: font, range: range)
return attributedString
}
}

8
GME Remit/Extensions/UIColor+Ext.swift

@ -42,10 +42,18 @@ extension UIColor {
class var themeBlue: UIColor {
return UIColor(named: "ThemeBlue") ?? .init(hex: "#0C2169")
}
class var theme2E89FF: UIColor {
return UIColor.init(hex: "#2E89FF")
}
class var themeGreen: UIColor {
return .init(hex: "#08A384")
}
class var darkBlue: UIColor {
return .init(hex: "#2E89FF")
}
class var themeGray3: UIColor {
return UIColor(red:0.67, green:0.67, blue:0.67, alpha:1.0)

30
GME Remit/Extensions/UIFont+Ext.swift

@ -20,6 +20,8 @@ enum FontType {
case ultrathin
}
extension UIFont {
class func sanfrancisco(_ type: FontType, size: CGFloat) -> UIFont {
let font: UIFont?
@ -47,4 +49,32 @@ extension UIFont {
return font ?? .systemFont(ofSize: size)
}
class func volte(_ type: FontType, size: CGFloat) -> UIFont {
let font: UIFont?
switch type {
case .regular:
font = UIFont(name: "FONTSPRINGDEMO-Volte", size: size)
case .medium:
font = UIFont(name: "volte-medium", size: size)
case .bold:
font = UIFont(name: "volte-bold", size: size)
case .semibold:
font = UIFont(name: "volte-semibold", size: size)
case .black:
font = UIFont(name: "SanfranciscoDisplay-Black", size: size)
case .heavy:
font = UIFont(name: "SanfranciscoDisplay-Heavy", size: size)
case .light:
font = UIFont(name: "SanfranciscoDisplay-Light", size: size)
case .thin:
font = UIFont(name: "SanfranciscoDisplay-Thin", size: size)
case .ultrathin:
font = UIFont(name: "SanfranciscoDisplay-Ultralight", size: size)
}
return font ?? .systemFont(ofSize: size)
}
}

110
GME Remit/Extensions/UIView+Ext.swift

@ -542,6 +542,116 @@ extension UIView {
}
}
extension UIView {
func anchor(top : NSLayoutYAxisAnchor? = nil,
paddingTop : CGFloat = 0 ,
bottom : NSLayoutYAxisAnchor? = nil,
paddingBottom : CGFloat = 0 ,
left: NSLayoutXAxisAnchor? = nil,
paddingLeft: CGFloat = 0,
right: NSLayoutXAxisAnchor? = nil,
paddingRight: CGFloat = 0,
width: CGFloat? = nil,
height: CGFloat? = nil ){
if let top = top {
topAnchor.constraint(equalTo: top, constant: paddingTop).isActive = true
}
if let bottom = bottom {
bottomAnchor.constraint(equalTo: bottom, constant: paddingBottom).isActive = true
}
if let left = left {
leadingAnchor.constraint(equalTo: left, constant: paddingLeft).isActive = true
}
if let right = right {
trailingAnchor.constraint(equalTo: right, constant: paddingRight).isActive = true
}
if let width = width ,width != 0 {
widthAnchor.constraint(equalToConstant: width).isActive = true
}
if let height = height, height != 0 {
heightAnchor.constraint(equalToConstant: height).isActive = true
}
}
func anchorGreaterOreEqualTo(
top : NSLayoutYAxisAnchor? = nil,
paddingTop : CGFloat = 0 ,
bottom : NSLayoutYAxisAnchor? = nil,
paddingBottom : CGFloat = 0 ,
left: NSLayoutXAxisAnchor? = nil,
paddingLeft: CGFloat = 0,
right: NSLayoutXAxisAnchor? = nil,
paddingRight: CGFloat = 0
) {
if let top = top {
topAnchor.constraint(greaterThanOrEqualTo: top, constant: paddingTop).isActive = true
}
if let bottom = bottom {
bottomAnchor.constraint(greaterThanOrEqualTo: bottom, constant: paddingBottom).isActive = true
}
if let left = left {
leadingAnchor.constraint(greaterThanOrEqualTo: left, constant: paddingLeft).isActive = true
}
if let right = right {
trailingAnchor.constraint(greaterThanOrEqualTo: right, constant: paddingRight).isActive = true
}
}
func anchorLessThanEqualTo(
top : NSLayoutYAxisAnchor? = nil,
paddingTop : CGFloat = 0 ,
bottom : NSLayoutYAxisAnchor? = nil,
paddingBottom : CGFloat = 0 ,
left: NSLayoutXAxisAnchor? = nil,
paddingLeft: CGFloat = 0,
right: NSLayoutXAxisAnchor? = nil,
paddingRight: CGFloat = 0
) {
if let top = top {
topAnchor.constraint(lessThanOrEqualTo: top, constant: paddingTop).isActive = true
}
if let bottom = bottom {
bottomAnchor.constraint(lessThanOrEqualTo: bottom, constant: paddingBottom).isActive = true
}
if let left = left {
leadingAnchor.constraint(lessThanOrEqualTo: left, constant: paddingLeft).isActive = true
}
if let right = right {
trailingAnchor.constraint(lessThanOrEqualTo: right, constant: paddingRight).isActive = true
}
}
func center(centerX : NSLayoutXAxisAnchor? , paddingX : CGFloat ,
centerY : NSLayoutYAxisAnchor? , paddingY : CGFloat) {
translatesAutoresizingMaskIntoConstraints = false
if let centerX = centerX {
centerXAnchor.constraint(equalTo: centerX , constant: paddingX).isActive = true
}
if let centerY = centerY {
centerYAnchor.constraint(equalTo: centerY , constant: paddingY).isActive = true
}
}
}
extension UIStackView {
func addArrangedSubviews(_ subviews: [UIView]) {
subviews.forEach { addArrangedSubview($0) }

4
GME Remit/Modules/ExchangeRates/Application Logic/Interactor/ExchangeRatesInteractorIO.swift

@ -6,12 +6,12 @@
//Copyright © 2018 Gobal Money Express Co. Ltd. All rights reserved.
//
protocol ExchangeRatesInteractorInput: class {
protocol ExchangeRatesInteractorInput: AnyObject {
func fetchExchangeRate()
func exchangeCalculate(use model: ExchangeRateRequestModel)
}
protocol ExchangeRatesInteractorOutput: class {
protocol ExchangeRatesInteractorOutput: AnyObject {
func setModel(with model: [ExchangeRateModel]?)
func setModel(with model: ExchangeRateDetailModel?)
func setError(with error: Error)

28
GME Remit/Modules/ExchangeRates/User Interface/Presenter/ExchangeRatesPresenter.swift

@ -37,18 +37,18 @@ extension ExchangeRatesPresenter: ExchangeRatesModuleInterface {
// MARK: ExchangeRates interactor output interface
extension ExchangeRatesPresenter: ExchangeRatesInteractorOutput {
func setModel(with model: [ExchangeRateModel]?) {
view?.hideLoading()
view?.setModel(with: model)
}
func setModel(with model: ExchangeRateDetailModel?) {
view?.hideLoading()
view?.setModel(with: model)
}
func setError(with error: Error) {
view?.hideLoading()
view?.setError(with: error)
}
func setModel(with model: [ExchangeRateModel]?) {
view?.hideLoading()
view?.setModel(with: model)
}
func setModel(with model: ExchangeRateDetailModel?) {
view?.hideLoading()
view?.setModel(with: model)
}
func setError(with error: Error) {
view?.hideLoading()
view?.setError(with: error)
}
}

3
GME Remit/Modules/ExchangeRates/User Interface/View/ExchangeRatesViewController.swift

@ -241,7 +241,6 @@ class ExchangeRatesViewController: UIViewController {
model: exchangeRateModels,
source: self
)
}
// other function
@ -416,7 +415,7 @@ extension ExchangeRatesViewController: UICollectionViewDataSource {
return configureWalletDeliveryCell(collectionView: collectionView, indexPath: indexPath)
case .cardPayment:
return configureCardPaymentCell(collectionView: collectionView, indexPath: indexPath)
}
}

72
GME Remit/Modules/Home/Application Logic/Interactor/HomeInteractor.swift

@ -13,13 +13,15 @@ class HomeInteractor {
// MARK: Properties
private let exchangeRateService: ExchangeRatesServiceType
weak var output: HomeInteractorOutput?
private let service: HomeServiceType
// MARK: Initialization
init(service: HomeServiceType) {
init(service: HomeServiceType, exchangeRateService: ExchangeRatesServiceType) {
self.service = service
self.exchangeRateService = exchangeRateService
}
// MARK: Converting entities
}
@ -27,24 +29,84 @@ class HomeInteractor {
// MARK: Home interactor input interface
extension HomeInteractor: HomeInteractorInput {
func fetchExchangeRate() {
exchangeRateService.fetchCountryCurrencyInfo(
isAuth: false,
success: { self.output?.setModel(with: $0) },
failure: { self.output?.show(error: $0) }
)
}
func exchangeCalculate(use model: ExchangeRateRequestModel) {
exchangeRateService.getExchangeRateInformation(
isAuth: false,
model: model,
success: { self.output?.setModel(with: $0) },
failure: { self.output?.show(error: $0) }
)
}
func fetchUserInfo() {
var homeError: Error?
var user: User?
var exchangeRateModel: [ExchangeRateModel]?
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
GMEDB.shared.getFcmToken { (token, error) in
self.service.fetchUserInfo(
token: token ?? "",
success: { user in
self.output?.show(model: user)
success: { data in
user = data
dispatchGroup.leave()
},
failure: {
let error = $0 as NSError
if error.code == AppConstants.emergencyLogoutErrorCode {
self.output?.show(panicError: error)
homeError = error
dispatchGroup.leave()
return
}
self.output?.show(error: error)
homeError = error
dispatchGroup.leave()
})
}
dispatchGroup.enter()
exchangeRateService.fetchCountryCurrencyInfo(
isAuth: false,
success: {
exchangeRateModel = $0
dispatchGroup.leave()
},
failure: {
homeError = $0
dispatchGroup.leave()
}
)
dispatchGroup.notify(queue: .main) {
if let homeError = homeError {
self.output?.show(error: homeError)
}else{
if let user = user,
let exchangeRateModel = exchangeRateModel
{
self.output?.show(model: user,
with: exchangeRateModel)
}
}
}
}
func requestOTP(userId: String) {

11
GME Remit/Modules/Home/Application Logic/Interactor/HomeInteractorIO.swift

@ -6,17 +6,22 @@
//Copyright © 2018 Gobal Money Express Co. Ltd. All rights reserved.
//
protocol HomeInteractorInput: class {
protocol HomeInteractorInput: AnyObject {
func fetchUserInfo()
func checkOTP(otp: String, userId: String)
func requestOTP(userId: String)
func fetchExchangeRate()
func exchangeCalculate(use model: ExchangeRateRequestModel)
}
protocol HomeInteractorOutput: class {
protocol HomeInteractorOutput: AnyObject {
func success()
func show(model: User)
func show(model: User,
with rates: [ExchangeRateModel]?)
func show(error: Error)
func show(panicError: Error)
func checkOtpError(error: Error)
func showOTPView()
func setModel(with model: [ExchangeRateModel]?)
func setModel(with model: ExchangeRateDetailModel?)
}

4
GME Remit/Modules/Home/Module Interface/HomeModuleInterface.swift

@ -6,7 +6,7 @@
//Copyright © 2018 Gobal Money Express Co. Ltd. All rights reserved.
//
protocol HomeModuleInterface: class {
protocol HomeModuleInterface: AnyObject {
func openTransactionHistory(type: OverseasType)
func openTodaysRate()
func openSendMoney(parentType: RecipientParentType)
@ -25,4 +25,6 @@ protocol HomeModuleInterface: class {
func requestOtp(userId: String)
func showRenewId()
func openNotification()
func fetchExchangeRate()
func exchangeCalculate(use model: ExchangeRateRequestModel)
}

25
GME Remit/Modules/Home/User Interface/Presenter/HomePresenter.swift

@ -22,6 +22,11 @@ class HomePresenter {
// MARK: Home module interface
extension HomePresenter: HomeModuleInterface {
func fetchExchangeRate() {
view?.showLoading()
interactor?.fetchExchangeRate()
}
func openNotice() {
wireframe?.openNotice()
}
@ -95,6 +100,11 @@ extension HomePresenter: HomeModuleInterface {
func openNotification() {
self.wireframe?.openNotification()
}
func exchangeCalculate(use model: ExchangeRateRequestModel) {
view?.showLoading()
interactor?.exchangeCalculate(use: model)
}
}
// MARK: Home interactor output interface
@ -105,9 +115,11 @@ extension HomePresenter: HomeInteractorOutput {
self.view?.checkOtpError(error: error.localizedDescription)
}
func show(model: User) {
func show(model: User,
with rates: [ExchangeRateModel]?) {
self.view?.hideLoading()
self.view?.show(model: model)
self.view?.show(model: model,
with: rates)
}
func show(error: Error) {
@ -130,4 +142,13 @@ extension HomePresenter: HomeInteractorOutput {
self.view?.showOtpView()
}
func setModel(with model: [ExchangeRateModel]?){
view?.hideLoading()
view?.setModel(with: model)
}
func setModel(with model: ExchangeRateDetailModel?) {
view?.hideLoading()
view?.setModel(with: model)
}
}

67
GME Remit/Modules/Home/User Interface/View/Cell/CarouselCell.swift

@ -0,0 +1,67 @@
//
import Foundation
import UIKit
import SDWebImage
class CarouselCollectionCell: UICollectionViewCell{
static let identifier: String = "CarouselCollectionCellID"
private let backgroundImgView: UIImageView = {
let view = UIImageView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private let containerView: UIView = {
let view = UIView()
view.backgroundColor = .clear
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private let titleLabel: UILabel = {
let view = UILabel()
view.font = UIFont.sanfrancisco(.bold, size: 21)
view.textColor = .themeWhite
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
private func setup(){
containerView.backgroundColor = .blue
containerView.layer.cornerRadius = 10
containerView.clipsToBounds = true
contentView.addSubview(containerView)
containerView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
containerView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
containerView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16).isActive = true
containerView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16).isActive = true
containerView.addSubview(backgroundImgView)
backgroundImgView.topAnchor.constraint(equalTo: containerView.topAnchor).isActive = true
backgroundImgView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true
backgroundImgView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor).isActive = true
backgroundImgView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true
}
func update(_ event: String){
DispatchQueue.main.async {
//let imageUrl = UrlManager.sharedInstance.baseImageUrl + "/" + "\(event.imageUrl ?? "")"
self.backgroundImgView.sd_setImage(with: URL(string: event), placeholderImage: UIImage(named: "flag_bahamas"))
}
}
}

10
GME Remit/Modules/Home/User Interface/View/Cell/HomeCollectionCollectionViewCell.swift

@ -18,11 +18,11 @@ class HomeCollectionCollectionViewCell: UICollectionViewCell {
let image = model?.icon?.withRenderingMode(.alwaysOriginal)
self.imageview.image = image
// if model?.title == "Slip Upload" {
// let image = model?.icon?.withRenderingMode(.alwaysTemplate)
// self.imageview.tintColor = UIColor.init(hex: "9AA2B4")
// self.imageview.image = image
// }
if model?.title == "Slip Upload" {
let image = model?.icon?.withRenderingMode(.alwaysTemplate)
self.imageview.tintColor = UIColor.init(hex: "9AA2B4")
self.imageview.image = image
}
self.titleLabel.text = model?.title

183
GME Remit/Modules/Home/User Interface/View/Cell/HomeCollectionTableViewCell.swift

@ -20,14 +20,14 @@ struct MenuNotificationName {
static let collectionHeight = "height_height"
}
protocol HomeCollectionDelegate: class {
protocol HomeCollectionDelegate: AnyObject {
func didSelect(
_ collectionView: UICollectionView,
didSelectMenu: HomeCollectionTableViewCell.CollectionMenus
)
}
class HomeCollectionTableViewCell: UITableViewCell, UICollectionViewDelegateFlowLayout {
class HomeCollectionTableViewCell: UITableViewCell {
struct StringConstants {
let sendMoneyText = "send_money_text".localized()
@ -48,6 +48,13 @@ class HomeCollectionTableViewCell: UITableViewCell, UICollectionViewDelegateFlow
case receivers
}
private let exchangeRateView: HomeExchangeRateView = {
let view = HomeExchangeRateView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
@IBOutlet weak var containerView: UIStackView!
@IBOutlet weak var collectionView: UICollectionView!
private var menus: [HomeCollectionModel]?
@ -56,30 +63,50 @@ class HomeCollectionTableViewCell: UITableViewCell, UICollectionViewDelegateFlow
var parentViewController: HomeViewController?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.collectionView.delegate = self
self.collectionView.dataSource = self
self.collectionView.contentInset = UIEdgeInsets(top: 5, left: 10, bottom: 5, right: 10)
containerView.translatesAutoresizingMaskIntoConstraints = false
containerView.addArrangedSubview(exchangeRateView)
setupCallback()
NotificationCenter.default.addObserver(
self,
selector: #selector(configureLanguage),
name: NSNotification.Name(LCLLanguageChangeNotification),
object: nil
)
}
func setup() {
func setup(_ rates: [ExchangeRateModel]?) {
collectionView.addObserver(
self, forKeyPath: "contentSize",
options: NSKeyValueObservingOptions.old,
context: nil
)
NotificationCenter.default.addObserver(
self,
selector: #selector(configureLanguage),
name: NSNotification.Name(LCLLanguageChangeNotification),
object: nil
)
self.menus = self.configureMenu()
exchangeRateView.set(rates)
}
func setup(_ rate: ExchangeRateDetailModel?) {
exchangeRateView.set(rate)
}
func setup(_ detail: ExchangeRateModel?) {
exchangeRateView.selectedPaymentModeIndex = 0
exchangeRateView.set(detail)
}
private func setupCallback() {
exchangeRateView.openCountryList = { [weak self] in
self?.parentViewController?.showCountryList()
}
exchangeRateView.tappedCalculateExchangeRate = { [weak self] model in
self?.parentViewController?.presenter?.exchangeCalculate(use: model)
}
}
@objc func configureLanguage() {
self.collectionView.reloadData()
//self.collectionView.reloadData()
}
private func configureMenu() -> [HomeCollectionModel] {
@ -126,70 +153,70 @@ class HomeCollectionTableViewCell: UITableViewCell, UICollectionViewDelegateFlow
override func observeValue(
forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey : Any]?,
context: UnsafeMutableRawPointer?
) {
if let observedObject = object as? UICollectionView, observedObject == collectionView {
let height = self.collectionView.contentSize.height
let finalHeight = height + CGFloat(20)
NotificationCenter.default.post(
name: self.getCollectionHeightNotificationName(),
object: nil,
userInfo: [MenuNotificationName.collectionHeight : finalHeight]
)
}
}
func collectionView(
_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath
) -> CGSize {
let width = collectionView.frame.width
let itemSize = (width - (collectionView.contentInset.left + collectionView.contentInset.right + 30)) / 2
return CGSize(width: itemSize, height: itemSize)
}
// override func observeValue(
// forKeyPath keyPath: String?,
// of object: Any?,
// change: [NSKeyValueChangeKey : Any]?,
// context: UnsafeMutableRawPointer?
// ) {
// if let observedObject = object as? UICollectionView, observedObject == collectionView {
// let height = self.collectionView.contentSize.height
// let finalHeight = height + CGFloat(20)
// NotificationCenter.default.post(
// name: self.getCollectionHeightNotificationName(),
// object: nil,
// userInfo: [MenuNotificationName.collectionHeight : finalHeight]
// )
// }
// }
func getCollectionHeightNotificationName() -> Notification.Name {
return Notification.Name.init(rawValue: MenuNotificationName.collectionHeight)
}
// func collectionView(
// _ collectionView: UICollectionView,
// layout collectionViewLayout: UICollectionViewLayout,
// sizeForItemAt indexPath: IndexPath
// ) -> CGSize {
//
// let width = collectionView.frame.width
// let itemSize = (width - (collectionView.contentInset.left + collectionView.contentInset.right + 30)) / 2
//
// return CGSize(width: itemSize, height: itemSize)
// }
//
// func getCollectionHeightNotificationName() -> Notification.Name {
// return Notification.Name.init(rawValue: MenuNotificationName.collectionHeight)
// }
}
// MARK: - UICollectionViewDataSource
extension HomeCollectionTableViewCell: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return menus?.count ?? 0
}
func collectionView(
_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath
) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(
withReuseIdentifier: "HomeCollectionCollectionViewCell",
for: indexPath
) as? HomeCollectionCollectionViewCell else {
return HomeCollectionCollectionViewCell()
}
let menus = self.configureMenu()
cell.model = menus.elementAt(index: indexPath.row)
cell.setup()
return cell
}
}
extension HomeCollectionTableViewCell: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard
let idx = self.menus?.elementAt(index: indexPath.row)?.index,
let index = CollectionMenus.init(rawValue: idx) else {return}
homeCollectionDelegate?.didSelect(collectionView, didSelectMenu: index)
}
}
//extension HomeCollectionTableViewCell: UICollectionViewDataSource {
// func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// return menus?.count ?? 0
// }
//
// func collectionView(
// _ collectionView: UICollectionView,
// cellForItemAt indexPath: IndexPath
// ) -> UICollectionViewCell {
// guard let cell = collectionView.dequeueReusableCell(
// withReuseIdentifier: "HomeCollectionCollectionViewCell",
// for: indexPath
// ) as? HomeCollectionCollectionViewCell else {
// return HomeCollectionCollectionViewCell()
// }
//
// let menus = self.configureMenu()
// cell.model = menus.elementAt(index: indexPath.row)
// cell.setup()
// return cell
// }
//}
//
//extension HomeCollectionTableViewCell: UICollectionViewDelegate {
// func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// guard
// let idx = self.menus?.elementAt(index: indexPath.row)?.index,
// let index = CollectionMenus.init(rawValue: idx) else {return}
//
// homeCollectionDelegate?.didSelect(collectionView, didSelectMenu: index)
// }
//}

89
GME Remit/Modules/Home/User Interface/View/Cell/HomeExchangeRateCollectionViewCell.swift

@ -0,0 +1,89 @@
//
import UIKit
class HomeExchangeRateCollectionViewCell: UICollectionViewCell {
var paymentServiceMethod: PaymentServiceType?
var image: UIImage?
private let iconView: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.heightAnchor.constraint(equalToConstant: 10).isActive = true
imageView.widthAnchor.constraint(equalToConstant: 10).isActive = true
return imageView
}()
var availableServiceLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
private var stackView: UIStackView!
static var identifier: String {
return String(describing: self)
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
private func setup() {
uiSetup()
uiPropertiesSetup()
}
private func uiSetup(){
stackView = UIStackView(arrangedSubviews: [iconView, availableServiceLabel])
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .horizontal
stackView.distribution = .fill
stackView.spacing = 3
stackView.alignment = .center
contentView.addSubview(stackView)
stackView.anchor(top: contentView.topAnchor,
paddingTop: 8,
bottom: contentView.bottomAnchor,
paddingBottom: -8,
left: contentView.leadingAnchor,
paddingLeft: 8,
right: contentView.trailingAnchor,
paddingRight: -8
)
availableServiceLabel.font = .sanfrancisco(.semibold, size: 14)
}
private func uiPropertiesSetup() {
contentView.set(cornerRadius: 16)
contentView.set(borderWidth: 2, of: .init(hex: "#00001F"))
}
func setup(cellSelected: Bool) {
iconView.image = image
availableServiceLabel.text = paymentServiceMethod?.subtitle
cellSelected ? showBorderColor() : hideBorderColor()
}
private func showBorderColor() {
self.contentView.backgroundColor = .init(hex: "#2E89FF").withAlphaComponent(0.3)
contentView.set(borderWidth: 2, of: .init(hex: "#0052FF"))
self.layoutSubviews()
}
private func hideBorderColor() {
self.contentView.backgroundColor = .themeWhite
contentView.set(borderWidth: 2, of: .themeGray1)
self.layoutSubviews()
}
}

47
GME Remit/Modules/Home/User Interface/View/Cell/HomeRemainingLimitTableViewCell.swift

@ -11,22 +11,33 @@ import Hero
class HomeRemainingLimitTableViewCell: UITableViewCell {
static var identifier: String {
return String(describing: self)
}
struct StringConstant {
let yearlyLimit = "remaining_limit_text".localized()
}
//
@IBOutlet weak var accountTitleLabel: UILabel!
@IBOutlet weak var amountLabel: UILabel!
@IBOutlet weak var userNameLabel: UILabel!
@IBOutlet weak var balaceTitleLabel: UILabel!
@IBOutlet weak var walletNumberLabel: UILabel!
@IBOutlet weak var walletBankCodeLabel: UILabel!
@IBOutlet weak var copyButton: UIButton!
@IBOutlet weak var uploadSlipButton: UIButton!
@IBOutlet weak var mainContainerView: UIView!
// var stackView: UIStackView!
var user: User?
weak var sideMenuDelegate: SideMenuDelegate?
override func awakeFromNib() {
super.awakeFromNib()
setup()
configureText()
// Initialization code
NotificationCenter.default.addObserver(
self,
@ -36,34 +47,28 @@ class HomeRemainingLimitTableViewCell: UITableViewCell {
)
}
func setup() {
let availableBalance = GMEDB.shared.user.string(.availableBalance)
self.amountLabel.text = availableBalance
self.userNameLabel.text = user?.firstName?.capitalized
configureText()
amountLabel.textColor = .themeBlue
walletBankCodeLabel.textColor = .themeRed
balaceTitleLabel.textColor = .themeRed
self.amountLabel.text = "JYP" + " " + (availableBalance?.likeCommaMoney() ?? "")
let walletNumber = GMEDB.shared.user.string(.referralCode) ?? ""
walletNumberLabel.text = walletNumber == "" ? "N/A" : walletNumber
// walletBankCodeLabel.text = GMEDB.shared.user.string(.primaryBankName)
copyButton.setTitle("", for: .normal)
contentView.addShadow()
contentView.setupCornerRadius(20,maskedCorners: [.layerMinXMaxYCorner, .layerMaxXMaxYCorner])
}
private func configureText() {
walletBankCodeLabel.text = "jme_membership_id_text".localized()
balaceTitleLabel.text = "balance_with_jme_text".localized()
balaceTitleLabel.text = "domestic_available_balance_text".localized()
accountTitleLabel.text = "account_number_text".localized()
}
@objc private func getYearlyLimitNotificationName() -> Notification.Name {
return Notification.Name.init(AppConstants.yearlyLimitNotification)
}
private func updateYearlyLimit(sender: Notification) {
if let amount = sender.userInfo?[AppConstants.yearlyLimitNotification] as? String {
self.amountLabel.text = amount

184
GME Remit/Modules/Home/User Interface/View/Custom/HomeAccountDetailView.swift

@ -0,0 +1,184 @@
import UIKit
class HomeAccountDetailView: UIView {
private let accountDetailView: UIView = {
let view = UIView(frame: .zero)
view.backgroundColor = .themeWhite
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private let accountNumberTitleLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
private let accountNumberValueLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
private let balanceTitleLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
private var balanceValueLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
private let copyButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
private let uploadSlipButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
private let exchangeRateView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override init(frame: CGRect) {
super.init(frame: .zero)
setup()
}
// override func awakeFromNib() {
// super.awakeFromNib()
// setup()
// }
required init?(coder: NSCoder) {
super.init(coder: coder)
fatalError("init(coder:) has not been implemented")
}
func setup() {
uiSetup()
uiPropertiesSetup()
}
private func uiSetup() {
self.addSubview(accountDetailView)
accountDetailView.anchor(top: self.topAnchor,
paddingTop: 0,
bottom: self.bottomAnchor,
paddingBottom: 0,
left: self.leadingAnchor,
paddingLeft: 0,
right: self.trailingAnchor,
paddingRight: 0,
width: 0,
height: 0)
accountDetailView.addSubviews(accountNumberTitleLabel,
accountNumberValueLabel,
balanceTitleLabel,
balanceValueLabel,
copyButton,
uploadSlipButton)
accountDetailView.addShadow()
accountNumberTitleLabel.anchor(top: accountDetailView.topAnchor,
paddingTop: 16,
bottom: nil,
paddingBottom: 0,
left: accountDetailView.leadingAnchor, paddingLeft: 16,
right: accountDetailView.trailingAnchor, paddingRight: -16)
accountNumberValueLabel.anchor(top: accountNumberTitleLabel.bottomAnchor,
paddingTop: 4,
bottom: nil,
paddingBottom: 0,
left: accountDetailView.leadingAnchor,
paddingLeft: 16
)
copyButton.anchor(top: nil,
bottom: nil,
left: accountNumberValueLabel.trailingAnchor,
paddingLeft: 4,
width: 80,
height: 80
)
copyButton.center(centerX: nil,
paddingX: 0,
centerY: accountNumberValueLabel.centerYAnchor,
paddingY: 0)
copyButton.anchorLessThanEqualTo(right: accountDetailView.trailingAnchor,
paddingRight: -16)
balanceTitleLabel.anchor(top: accountNumberValueLabel.bottomAnchor,
paddingTop: 16,
left: accountDetailView.leadingAnchor,
paddingLeft: 16)
balanceValueLabel.anchor(top: balanceTitleLabel.bottomAnchor,
paddingTop: 4,
bottom: accountDetailView.bottomAnchor,
paddingBottom: -16,
left: accountDetailView.leadingAnchor,
paddingLeft: 16)
uploadSlipButton.anchor(top: balanceTitleLabel.topAnchor,
bottom: balanceValueLabel.bottomAnchor,
right: accountDetailView.trailingAnchor,
paddingRight: -16
)
}
func uiPropertiesSetup() {
accountDetailView.setupCornerRadius(20,maskedCorners: [.layerMinXMaxYCorner, .layerMaxXMaxYCorner])
accountNumberTitleLabel.text = "account_number_text".localized()
copyButton.setTitle("Copy", for: .normal)
copyButton.setTitleColor(.red, for: .normal)
balanceTitleLabel.text = "domestic_available_balance_text".localized()
balanceValueLabel.text = "6482682342"
uploadSlipButton.backgroundColor = .red
uploadSlipButton.set(cornerRadius: 5)
uploadSlipButton.setImage(UIImage(named: "chat"), for: .normal)
uploadSlipButton.setTitle("Upload", for: .normal)
uploadSlipButton.setTitleColor(.green, for: .normal)
uploadSlipButton.contentEdgeInsets = UIEdgeInsets(top: 10,
left: 10,
bottom: 10,
right: 20)
}
func setupData() {
let availableBalance = GMEDB.shared.user.string(.availableBalance)
balanceValueLabel.text = availableBalance
let walletNumber = GMEDB.shared.user.string(.referralCode) ?? ""
accountNumberValueLabel.text = walletNumber == "" ? "N/A" : walletNumber
}
func setAmount(_ amount: String) {
balanceValueLabel.text = amount
}
}

207
GME Remit/Modules/Home/User Interface/View/Custom/HomeCarouselView.swift

@ -0,0 +1,207 @@
//
import Foundation
import UIKit
class HomeCarouselView: UIView {
private var events: [String] = []
private var timer: Timer?
private let collectionView: UICollectionView = {
let flowlayout = UICollectionViewFlowLayout()
flowlayout.scrollDirection = .horizontal
let view = UICollectionView(frame: CGRect.zero, collectionViewLayout: flowlayout)
view.register(CarouselCollectionCell.self, forCellWithReuseIdentifier: CarouselCollectionCell.identifier)
view.backgroundColor = .white
view.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
view.showsHorizontalScrollIndicator = false
view.translatesAutoresizingMaskIntoConstraints = false
view.isPagingEnabled = true
return view
}()
private let pageControl: CustomPageControl = {
let view = CustomPageControl(frame: .zero)
view.currentPageIndicatorTintColor = .themeBlack
view.pageIndicatorTintColor = .themeGray2
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
static let identifier: String = "HomeCarouselCellID"
/// whether or not dragging has ended
fileprivate var endDragging = false
/// the current page
@objc open dynamic var currentIndex: Int = 0 {
didSet {
updateAccessoryViews()
}
}
func updateAccessoryViews() {
pageControl.currentPage = currentIndex
}
override init(frame: CGRect) {
super.init(frame: .zero)
setup()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setup(){
self.backgroundColor = .themeWhite
self.addSubview(pageControl)
pageControl.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
pageControl.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true
pageControl.heightAnchor.constraint(equalToConstant: 30).isActive = true
self.addSubview(collectionView)
collectionView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0).isActive = true
collectionView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 0).isActive = true
collectionView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
collectionView.bottomAnchor.constraint(equalTo: pageControl.topAnchor, constant: 0).isActive = true
collectionView.delegate = self
collectionView.dataSource = self
}
override open func layoutSubviews() {
super.layoutSubviews()
collectionView.performBatchUpdates(nil, completion: nil)
moveToPage(currentIndex, animated: false)
}
open func moveToPage(_ page: Int, animated: Bool) {
// outside the range
if page < 0 || page >= collectionView.numberOfItems(inSection: 0) {
return
}
currentIndex = page
collectionView.scrollToItem(at: IndexPath(item: currentIndex, section: 0),
at: .left, animated: animated)
}
func update(_ events: [String]){
self.events = events
pageControl.numberOfPages = events.count
self.collectionView.reloadData()
stopTimer()
startTimer()
}
/**
Scroll to Next Cell
*/
@objc func scrollToNextCell(){
let nextpage = self.currentIndex + 1
if nextpage >= self.events.count{
moveToPage(0, animated: true)
}else{
moveToPage(nextpage, animated: true)
}
}
/**
Invokes Timer to start Automatic Animation with repeat enabled
*/
private func startTimer() {
self.timer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(self.scrollToNextCell), userInfo: nil, repeats: true)
}
private func stopTimer(){
self.timer?.invalidate()
self.timer = nil
}
}
//MARK:- UICollectionViewDelegate
extension HomeCarouselView: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout{
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CarouselCollectionCell.identifier, for: indexPath) as! CarouselCollectionCell
cell.update(self.events[indexPath.row])
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.events.count
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width, height: collectionView.frame.height)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0.001
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0.001
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
//self.didSelect?(self.events[indexPath.row])
}
/**
size of the collection view
- parameter collectionView: the collection view
- parameter collectionViewLayout: the collection view flow layout
- parameter indexPath: the index path
*/
// public func collectionView(_ collectionView: UICollectionView,
// layout collectionViewLayout: UICollectionViewLayout,
// sizeForItemAt indexPath: IndexPath) -> CGSize {
// return collectionView.bounds.size
// }
/**
scroll view did end dragging
- parameter scrollView: the scroll view
- parameter decelerate: wether the view is decelerating or not.
*/
public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if !decelerate {
endScrolling(scrollView)
} else {
endDragging = true
}
}
/**
Scroll view did end decelerating
*/
public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
if endDragging {
endDragging = false
endScrolling(scrollView)
}
}
/**
end scrolling
*/
fileprivate func endScrolling(_ scrollView: UIScrollView) {
let width = scrollView.bounds.width
let page = (scrollView.contentOffset.x + (0.5 * width)) / width
currentIndex = Int(page)
self.stopTimer()
self.startTimer()
}
}

527
GME Remit/Modules/Home/User Interface/View/Custom/HomeExchangeRateView.swift

@ -0,0 +1,527 @@
//
import UIKit
class HomeExchangeRateView: UIView {
private let containerView: UIView = {
let view = UIView(frame: .zero)
view.backgroundColor = .themeWhite
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
var sendMoneyView: ExchangeRateCustomView = {
let view = ExchangeRateCustomView(isReciver: false)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
var recivedMoneyView: ExchangeRateCustomView = {
let view = ExchangeRateCustomView(isReciver: true)
view.isReciver = true
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private let collectionView: UICollectionView = {
let flowlayout = UICollectionViewFlowLayout()
flowlayout.scrollDirection = .horizontal
flowlayout.collectionView?.showsHorizontalScrollIndicator = false
let view = UICollectionView(frame: CGRect.zero, collectionViewLayout: flowlayout)
view.translatesAutoresizingMaskIntoConstraints = false
view.register(HomeExchangeRateCollectionViewCell.self, forCellWithReuseIdentifier: HomeExchangeRateCollectionViewCell.identifier)
view.backgroundColor = .white
view.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
return view
}()
private let transferFeeIncludedImageView: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "exchange_rate_transfer_fee")
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.heightAnchor.constraint(equalToConstant: 24).isActive = true
imageView.widthAnchor.constraint(equalToConstant: 24).isActive = true
return imageView
}()
private let transferFeeIncludedText: UILabel = {
let text = UILabel()
text.translatesAutoresizingMaskIntoConstraints = false
return text
}()
private let guranteedRateImageView: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "exchange_rate_guranteed")
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.heightAnchor.constraint(equalToConstant: 24).isActive = true
imageView.widthAnchor.constraint(equalToConstant: 24).isActive = true
return imageView
}()
private let guranteedRateText: UILabel = {
let text = UILabel()
text.translatesAutoresizingMaskIntoConstraints = false
return text
}()
private let continueButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.heightAnchor.constraint(equalToConstant: 55).isActive = true
return button
}()
private let exchangeButton: UIButton = {
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.heightAnchor.constraint(equalToConstant: 32).isActive = true
button.widthAnchor.constraint(equalToConstant: 32).isActive = true
return button
}()
//exRate
private var transferFeeIncluded: UIStackView!
private var guranteedView: UIStackView!
// MARK: Properties
private let edgeSpacing: CGFloat = 8.0
private let itemSpacing: CGFloat = 8.0
private var exchangeRateModels: [ExchangeRateModel]?
private var selectedExchangeRateModel: ExchangeRateModel? {
didSet {
selectedExchangeRateModel(selectedExchangeRateModel)
}
}
var calcBy = ""
var selectedPaymentModeIndex = 0
var openCountryList: (() -> ())?
var tappedCalculateExchangeRate: ((ExchangeRateRequestModel) ->())?
override init(frame: CGRect) {
super.init(frame: .zero)
setup()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setup() {
uiSetup()
uiPropertiesSetup()
textChanged()
}
func uiSetup() {
self.addSubview(containerView)
containerView.anchor(top: self.topAnchor,
paddingTop: 0,
bottom: self.bottomAnchor,
paddingBottom: 0,
left: self.leadingAnchor,
paddingLeft: 16,
right: self.trailingAnchor,
paddingRight: -16
)
transferFeeIncluded = UIStackView(arrangedSubviews: [transferFeeIncludedImageView,
transferFeeIncludedText])
transferFeeIncluded.translatesAutoresizingMaskIntoConstraints = false
transferFeeIncluded.axis = .horizontal
transferFeeIncluded.spacing = 3
transferFeeIncluded.distribution = .fill
guranteedView = UIStackView(arrangedSubviews: [guranteedRateImageView,
guranteedRateText])
guranteedView.translatesAutoresizingMaskIntoConstraints = false
guranteedView.axis = .horizontal
guranteedView.spacing = 3
guranteedView.distribution = .fill
containerView.addSubviews(collectionView,
sendMoneyView,
exchangeButton,
recivedMoneyView,
transferFeeIncluded,
guranteedView,
continueButton)
collectionView.anchor(
top: containerView.topAnchor,
paddingTop: 0,
left: containerView.leadingAnchor,
paddingLeft: 0,
right: containerView.trailingAnchor,
paddingRight: 0,
height: 30
)
sendMoneyView.anchor(
top: collectionView.bottomAnchor,
paddingTop: 20,
left: containerView.leadingAnchor,
paddingLeft: 0,
right: containerView.trailingAnchor,
paddingRight: 0
)
recivedMoneyView.anchor(
top: sendMoneyView.bottomAnchor,
paddingTop: 16,
left: containerView.leadingAnchor,
paddingLeft: 0,
right: containerView.trailingAnchor,
paddingRight: 0
)
exchangeButton.anchor(top: sendMoneyView.bottomAnchor,
paddingTop: -8,
bottom: recivedMoneyView.topAnchor,
paddingBottom: 8,
left: sendMoneyView.leadingAnchor,
paddingLeft: 16)
transferFeeIncluded.anchor(
top: recivedMoneyView.bottomAnchor,
paddingTop: 16,
left: containerView.leadingAnchor,
paddingLeft: 0,
right: containerView.trailingAnchor,
paddingRight: 0
)
guranteedView.anchor(
top: transferFeeIncluded.bottomAnchor,
paddingTop: 16,
left: containerView.leadingAnchor,
paddingLeft: 0,
right: containerView.trailingAnchor,
paddingRight: 0
)
continueButton.anchor(
top: guranteedView.bottomAnchor,
paddingTop: 16,
left: containerView.leadingAnchor,
paddingLeft: 0,
right: containerView.trailingAnchor,
paddingRight: 0
)
continueButton.anchorLessThanEqualTo(bottom: containerView.bottomAnchor, paddingBottom: -16)
}
func uiPropertiesSetup() {
transferFeeIncludedText.text = ""
guranteedRateText.text = ""
continueButton.setTitle("continue_text".localized(), for: .normal)
continueButton.backgroundColor = .theme2E89FF
continueButton.titleLabel?.font = .sanfrancisco(.semibold, size: 20)
collectionView.delegate = self
collectionView.dataSource = self
continueButton.addTarget(self, action: #selector(calculateExchangeRate), for: .touchUpInside)
continueButton.set(cornerRadius: 10)
sendMoneyView.set(borderWidth: 2, of: .black)
sendMoneyView.set(cornerRadius: 10)
sendMoneyView.title = "you_send_text".localized()
recivedMoneyView.set(borderWidth: 2, of: .black)
recivedMoneyView.set(cornerRadius: 10)
recivedMoneyView.title = "receipient_gets_text".localized()
exchangeButton.setTitle("", for: .normal)
exchangeButton.setImage(UIImage(named: "exchangeRateButton"), for: .normal)
exchangeButton.layer.cornerRadius = 10
exchangeButton.backgroundColor = .themeGray1
exchangeButton.layer.borderWidth = 2
exchangeButton.layer.borderColor = UIColor.black.cgColor
}
func textChanged() {
sendMoneyView.passTextFieldText = { [weak self] text in
self?.calcBy = "c"
self?.recivedMoneyView.updatedText = ""
}
recivedMoneyView.passTextFieldText = { [weak self] text in
self?.calcBy = "p"
self?.sendMoneyView.updatedText = ""
}
recivedMoneyView.didSelectCountry = { [weak self] in
self?.sendMoneyView.resignFirstResponder()
self?.recivedMoneyView.resignFirstResponder()
self?.openCountryList?()
}
}
func set(_ model: [ExchangeRateModel]?) {
self.exchangeRateModels = model
setExchangeRateModels(model)
}
func set(_ model: ExchangeRateDetailModel?) {
guard let model = model else {
return
}
sendMoneyView.updatedText = model.senderAmount?.likeCommaMoney()
recivedMoneyView.updatedText = model.recipientAmount?.likeCommaMoney()
let transferFee = ("\(model.transferFee?.likeCommaMoney() ?? "" ) JPY ")
.attributedText(color: .themeBlack, font: .sanfrancisco(.semibold, size: 14))
let transferInfo = "transfer_fee_included_text".localized().attributedText(color: .theme2E89FF, font: .sanfrancisco(.semibold, size: 14))
let transfer = NSMutableAttributedString()
transfer.append(transferFee)
transfer.append(transferInfo)
transferFeeIncludedText.attributedText = transfer
let exchangeRate = model.exchangeRate ?? ""
let exchangeRateAttributed = ("1000 JPY = \(exchangeRate) \(selectedExchangeRateModel?.currency ?? "") ").attributedText(color: .themeBlack, font: .sanfrancisco(.semibold, size: 14))
let exchangeRateInfo = ("Guranteed rate for 24 hr").attributedText(color: .theme2E89FF, font: .sanfrancisco(.semibold, size: 14))
let gurrantedText = NSMutableAttributedString()
gurrantedText.append(exchangeRateAttributed)
gurrantedText.append(exchangeRateInfo)
guranteedRateText.attributedText = gurrantedText
}
func set(_ model: ExchangeRateModel?) {
self.selectedExchangeRateModel = model
}
private func setExchangeRateModels(_ model: [ExchangeRateModel]?) {
let countryCode = GMEDB.shared.user.string(.countryCode)
if let defaultExchangeRate = model?.filter({
($0.countryCode ?? "").lowercased() == countryCode?.lowercased()
}).first {
selectedExchangeRateModel = defaultExchangeRate
} else {
selectedExchangeRateModel = model?.filter({
($0.countryCode ?? "").lowercased() == "az"
}).first
}
}
private func selectedExchangeRateModel(_ model: ExchangeRateModel?) {
let code = selectedExchangeRateModel?.countryCode?.lowercased() ?? "az"
let codeEnum = CountryEnum(rawValue: code)
recivedMoneyView.flag = codeEnum?.flag
recivedMoneyView.currency = selectedExchangeRateModel?.currency
guard let defaultAmount = codeEnum?.getDefaultRecipientAcount(
currency: selectedExchangeRateModel?.currency ?? ""
) else {
calcBy = "c"
sendMoneyView.updatedText = codeEnum?.defaultSenderAmount.likeCommaMoney()
recivedMoneyView.updatedText = ""
calculateExchangeRate()
return
}
calcBy = "p"
sendMoneyView.updatedText = ""
recivedMoneyView.updatedText = defaultAmount.likeCommaMoney()
calculateExchangeRate()
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
self.collectionView.reloadData()
}
}
@objc func calculateExchangeRate() {
let model = ExchangeRateRequestModel(
senderAmount: (sendMoneyView.text ?? sendMoneyView.updatedText ?? "").stringRemovingComma(),
senderCurrency: "JPY",
senderCountryID: "142",
recipientAmount: (recivedMoneyView.text ?? recivedMoneyView.updatedText ?? "").stringRemovingComma(),
recipientCurrency: selectedExchangeRateModel?.currency ?? "",
recipientCountryID: selectedExchangeRateModel?.countryId ?? "",
recipientCountry: selectedExchangeRateModel?.country ?? "",
serviceType: selectedExchangeRateModel?
.availableServices?
.elementAt(index: selectedPaymentModeIndex)?.id ?? "",
calcBy: calcBy
)
self.tappedCalculateExchangeRate?(model)
}
}
extension HomeExchangeRateView: UICollectionViewDelegate,
UICollectionViewDataSource,
UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.selectedExchangeRateModel?.availableServices?.count ?? 0
}
func collectionView(
_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath
) -> UICollectionViewCell {
let service = self.selectedExchangeRateModel?.availableServices?.elementAt(index: indexPath.row)
guard let index = PaymentMode.init(rawValue: service?.id ?? "") else {
return UICollectionViewCell()
}
switch index {
case .bankDeposite:
return configureBankDepositeCell(collectionView: collectionView, indexPath: indexPath)
case .cashDelivery:
return configureCashDeliveryCell(collectionView: collectionView, indexPath: indexPath)
case .homeDelivery:
return configureHomeDeliveryCell(collectionView: collectionView, indexPath: indexPath)
case .mobileWallet:
return configureWalletDeliveryCell(collectionView: collectionView, indexPath: indexPath)
case .cardPayment:
return configureCardPaymentCell(collectionView: collectionView, indexPath: indexPath)
}
}
func configureBankDepositeCell(
collectionView: UICollectionView,
indexPath: IndexPath
) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(
withReuseIdentifier: HomeExchangeRateCollectionViewCell.identifier,
for: indexPath
) as? HomeExchangeRateCollectionViewCell else {
return UICollectionViewCell()
}
cell.paymentServiceMethod = self.selectedExchangeRateModel?.availableServices?.elementAt(
index: indexPath.row
)
cell.image = UIImage(named: "bank_deposit")
cell.setup(cellSelected: self.selectedPaymentModeIndex == indexPath.row)
return cell
}
func configureCardPaymentCell(
collectionView: UICollectionView,
indexPath: IndexPath
) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(
withReuseIdentifier: HomeExchangeRateCollectionViewCell.identifier,
for: indexPath
) as? HomeExchangeRateCollectionViewCell else {
return UICollectionViewCell()
}
cell.paymentServiceMethod = self.selectedExchangeRateModel?.availableServices?.elementAt(
index: indexPath.row
)
cell.image = #imageLiteral(resourceName: "ic_card_payment")
cell.setup(cellSelected: self.selectedPaymentModeIndex == indexPath.row)
return cell
}
func configureWalletDeliveryCell(
collectionView: UICollectionView,
indexPath: IndexPath
) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(
withReuseIdentifier: HomeExchangeRateCollectionViewCell.identifier,
for: indexPath
) as? HomeExchangeRateCollectionViewCell else {
return UICollectionViewCell()
}
cell.paymentServiceMethod = self.selectedExchangeRateModel?.availableServices?.elementAt(
index: indexPath.row
)
cell.image = #imageLiteral(resourceName: "wallet-transfer")
cell.setup(cellSelected: self.selectedPaymentModeIndex == indexPath.row)
return cell
}
func configureCashDeliveryCell(
collectionView: UICollectionView,
indexPath: IndexPath
) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(
withReuseIdentifier: HomeExchangeRateCollectionViewCell.identifier,
for: indexPath
) as? HomeExchangeRateCollectionViewCell else {
return UICollectionViewCell()
}
cell.paymentServiceMethod = self.selectedExchangeRateModel?.availableServices?.elementAt(
index: indexPath.row
)
cell.image = UIImage(named: "cash_payment")
cell.setup(cellSelected: self.selectedPaymentModeIndex == indexPath.row)
return cell
}
func configureHomeDeliveryCell(
collectionView: UICollectionView,
indexPath: IndexPath
) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(
withReuseIdentifier: HomeExchangeRateCollectionViewCell.identifier,
for: indexPath
) as? HomeExchangeRateCollectionViewCell else {
return UICollectionViewCell()
}
cell.paymentServiceMethod = self.selectedExchangeRateModel?.availableServices?.elementAt(
index: indexPath.row
)
cell.image = #imageLiteral(resourceName: "ic_homeDelivery")
cell.setup(cellSelected: self.selectedPaymentModeIndex == indexPath.row)
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let element = self.selectedExchangeRateModel?.availableServices?.elementAt(
index: indexPath.row)?.subtitle ?? ""
return CGSize(width: element.size(withAttributes: [NSAttributedString.Key.font : UIFont.sanfrancisco(.semibold, size: 16)]).width + 25, height: collectionView.frame.height)
}
// func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
// let width = collectionView.frame.width
//
// let totalEdgeSpacing = edgeSpacing * 2
// let numberOfItemsInRow = 3
// let totalItemSpacing = CGFloat(numberOfItemsInRow - 1) * self.itemSpacing
// let size = (width - (totalEdgeSpacing + totalItemSpacing)) / CGFloat(numberOfItemsInRow)
// return CGSize(width: size, height: 60)
// }
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.selectedPaymentModeIndex = indexPath.row
self.collectionView.reloadData()
self.calculateExchangeRate()
}
}

457
GME Remit/Modules/Home/User Interface/View/Home.storyboard

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="ezt-uK-zb8">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="ezt-uK-zb8">
<device id="retina4_0" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
<capability name="Named colors" minToolsVersion="9.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@ -12,14 +12,11 @@
<array key="SanFranciscoDisplay-Bold.otf">
<string>SanFranciscoDisplay-Bold</string>
</array>
<array key="SanFranciscoDisplay-Medium.otf">
<string>SanFranciscoDisplay-Medium</string>
</array>
<array key="SanFranciscoDisplay-Regular.otf">
<string>SanFranciscoDisplay-Regular</string>
</array>
<array key="SanFranciscoText-Semibold.otf">
<string>SanFranciscoText-Semibold</string>
<array key="volte-semibold.otf">
<string>FONTSPRINGDEMO-VolteSemiboldRegular</string>
</array>
</customFonts>
<scenes>
@ -28,11 +25,11 @@
<objects>
<viewController storyboardIdentifier="HomeViewController" title="Home" id="HSb-ou-7T5" customClass="HomeViewController" customModule="JME_Remit" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="qRs-xH-5Fi">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<rect key="frame" x="0.0" y="0.0" width="400" height="1000"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="alB-Pe-T92">
<rect key="frame" x="0.0" y="44" width="320" height="100"/>
<rect key="frame" x="0.0" y="44" width="400" height="100"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Documents" translatesAutoresizingMaskIntoConstraints="NO" id="UD8-ap-8xD">
<rect key="frame" x="24" y="14" width="67" height="72"/>
@ -41,20 +38,20 @@
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Thank you for registering with us!" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="pcY-xj-hQb">
<rect key="frame" x="103" y="20" width="193" height="14.5"/>
<rect key="frame" x="103" y="20" width="273" height="14"/>
<fontDescription key="fontDescription" name="SanFranciscoDisplay-Bold" family="San Francisco Display" pointSize="12"/>
<color key="textColor" name="ThemeRed"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="17X-fv-KyB" userLabel="Seperator">
<rect key="frame" x="0.0" y="99.5" width="320" height="0.5"/>
<rect key="frame" x="0.0" y="99.5" width="400" height="0.5"/>
<color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="0.5" id="bf7-EA-sF4"/>
</constraints>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Your document is in verification process. This will not take long. Thereafter you can enjoy GME online service." lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" minimumFontSize="8" translatesAutoresizingMaskIntoConstraints="NO" id="rwJ-pQ-p9z">
<rect key="frame" x="103" y="42.5" width="193" height="36"/>
<rect key="frame" x="103" y="42" width="273" height="23.5"/>
<fontDescription key="fontDescription" name="SanFranciscoDisplay-Regular" family="San Francisco Display" pointSize="10"/>
<color key="textColor" name="ThemeText"/>
<nil key="highlightedColor"/>
@ -81,343 +78,159 @@
<outletCollection property="gestureRecognizers" destination="G3V-VT-9Qm" appends="YES" id="0RA-Gg-BgB"/>
</connections>
</view>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" dataMode="prototypes" style="plain" separatorStyle="none" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="wXh-zk-jWw">
<rect key="frame" x="0.0" y="144" width="320" height="375"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="HomeRemainingLimitTableViewCell" id="rcn-u6-1gx" customClass="HomeRemainingLimitTableViewCell" customModule="JME_Remit" customModuleProvider="target">
<rect key="frame" x="0.0" y="44.5" width="320" height="110"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="rcn-u6-1gx" id="ekT-Zr-ohe">
<rect key="frame" x="0.0" y="0.0" width="320" height="110"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="A2Y-eS-2d3">
<rect key="frame" x="0.0" y="0.0" width="320" height="110"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="10" translatesAutoresizingMaskIntoConstraints="NO" id="wLs-Rj-kxu">
<rect key="frame" x="20" y="10" width="280" height="90"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hZu-KN-tcd">
<rect key="frame" x="0.0" y="0.0" width="280" height="60"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="Ktu-2Y-ndo">
<rect key="frame" x="150.5" y="8" width="124.5" height="44"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="253" text="Avaliable Balance" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="xJH-zQ-Y2H">
<rect key="frame" x="12.5" y="0.0" width="99.5" height="16"/>
<fontDescription key="fontDescription" name="SanFranciscoDisplay-Medium" family="San Francisco Display" pointSize="13"/>
<color key="textColor" name="ThemeRedDark"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" spacing="2" translatesAutoresizingMaskIntoConstraints="NO" id="Hk9-Sd-1vf">
<rect key="frame" x="47.5" y="21" width="30" height="23"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="261" verticalHuggingPriority="251" text="N/A" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="M1e-cc-M1d">
<rect key="frame" x="0.0" y="0.0" width="30" height="23"/>
<fontDescription key="fontDescription" name="SanFranciscoDisplay-Medium" family="San Francisco Display" pointSize="19"/>
<color key="textColor" name="ThemeBlue"/>
<nil key="highlightedColor"/>
</label>
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" text="JPY" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uBk-0o-Pgj">
<rect key="frame" x="0.0" y="0.0" width="33" height="23"/>
<constraints>
<constraint firstAttribute="width" constant="33" id="0LO-Ay-wBw"/>
</constraints>
<fontDescription key="fontDescription" name="SanFranciscoDisplay-Regular" family="San Francisco Display" pointSize="17"/>
<color key="textColor" name="ThemeText"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
</subviews>
</stackView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="1vR-3P-txC">
<rect key="frame" x="139.5" y="-5" width="1" height="70"/>
<color key="backgroundColor" name="ThemeRedDark"/>
<constraints>
<constraint firstAttribute="width" constant="1" id="4d0-jt-IDL"/>
<constraint firstAttribute="height" constant="70" id="nWB-lJ-MxD"/>
</constraints>
</view>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="9Ft-mi-Ev0">
<rect key="frame" x="5" y="8" width="124.5" height="44"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="253" text="Kwangju(034)" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" minimumScaleFactor="0.84999999999999998" translatesAutoresizingMaskIntoConstraints="NO" id="IXG-rj-tyI">
<rect key="frame" x="22.5" y="0.0" width="80" height="16"/>
<fontDescription key="fontDescription" name="SanFranciscoDisplay-Medium" family="San Francisco Display" pointSize="13"/>
<color key="textColor" name="ThemeRedDark"/>
<nil key="highlightedColor"/>
</label>
<stackView opaque="NO" contentMode="scaleToFill" spacing="2" translatesAutoresizingMaskIntoConstraints="NO" id="jPc-HT-RBJ">
<rect key="frame" x="47.5" y="21" width="30" height="23"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="261" verticalHuggingPriority="251" text="N/A" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumScaleFactor="0.5" translatesAutoresizingMaskIntoConstraints="NO" id="FSQ-xU-CsJ">
<rect key="frame" x="0.0" y="0.0" width="30" height="23"/>
<fontDescription key="fontDescription" name="SanFranciscoDisplay-Medium" family="San Francisco Display" pointSize="19"/>
<color key="textColor" name="ThemeBlue"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="9Ft-mi-Ev0" firstAttribute="leading" secondItem="hZu-KN-tcd" secondAttribute="leading" constant="5" id="3KX-UM-8cn"/>
<constraint firstItem="Ktu-2Y-ndo" firstAttribute="top" relation="greaterThanOrEqual" secondItem="hZu-KN-tcd" secondAttribute="top" id="5Ko-fI-csW"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="9Ft-mi-Ev0" secondAttribute="bottom" id="Ch7-W5-ZyN"/>
<constraint firstItem="Ktu-2Y-ndo" firstAttribute="leading" secondItem="1vR-3P-txC" secondAttribute="trailing" constant="10" id="PIF-N7-VTV"/>
<constraint firstItem="1vR-3P-txC" firstAttribute="centerX" secondItem="hZu-KN-tcd" secondAttribute="centerX" id="Y54-J2-lTk"/>
<constraint firstItem="1vR-3P-txC" firstAttribute="centerY" secondItem="hZu-KN-tcd" secondAttribute="centerY" id="ZmI-3W-epg"/>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="Ktu-2Y-ndo" secondAttribute="bottom" id="ieP-Ql-Z8b"/>
<constraint firstItem="Ktu-2Y-ndo" firstAttribute="centerY" secondItem="hZu-KN-tcd" secondAttribute="centerY" id="jJP-UX-fI7"/>
<constraint firstItem="1vR-3P-txC" firstAttribute="top" secondItem="hZu-KN-tcd" secondAttribute="top" constant="-5" id="lNY-XX-sr2"/>
<constraint firstAttribute="bottom" secondItem="1vR-3P-txC" secondAttribute="bottom" constant="-5" id="lyb-S7-LJm"/>
<constraint firstItem="9Ft-mi-Ev0" firstAttribute="top" relation="greaterThanOrEqual" secondItem="hZu-KN-tcd" secondAttribute="top" id="oME-9b-tlV"/>
<constraint firstAttribute="trailing" secondItem="Ktu-2Y-ndo" secondAttribute="trailing" constant="5" id="rld-cP-Vtf"/>
<constraint firstItem="1vR-3P-txC" firstAttribute="leading" secondItem="9Ft-mi-Ev0" secondAttribute="trailing" constant="10" id="u0W-u6-Iuv"/>
<constraint firstItem="9Ft-mi-Ev0" firstAttribute="centerY" secondItem="hZu-KN-tcd" secondAttribute="centerY" id="vGJ-6Y-BOW"/>
</constraints>
</view>
<view hidden="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="4Ze-gK-s6z">
<rect key="frame" x="0.0" y="65" width="280" height="2"/>
<color key="backgroundColor" name="ThemeSubBackground"/>
<constraints>
<constraint firstAttribute="height" constant="2" id="h7h-4F-Ddy"/>
</constraints>
</view>
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Peb-Sn-rcC">
<rect key="frame" x="0.0" y="70" width="280" height="20"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="dzi-vM-GUm">
<rect key="frame" x="0.0" y="0.0" width="280" height="20"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="N/A" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="HSv-Iz-JvY">
<rect key="frame" x="0.0" y="0.0" width="280" height="20"/>
<fontDescription key="fontDescription" name="SanFranciscoDisplay-Bold" family="San Francisco Display" pointSize="15"/>
<color key="textColor" name="ThemeText"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
</subviews>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="20" id="7b7-7Q-oHt"/>
<constraint firstAttribute="height" constant="20" id="sD1-nP-ywn"/>
</constraints>
</stackView>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="wLs-Rj-kxu" secondAttribute="bottom" constant="10" id="Ser-A0-ROf"/>
<constraint firstItem="wLs-Rj-kxu" firstAttribute="leading" secondItem="A2Y-eS-2d3" secondAttribute="leading" constant="20" id="X51-PH-E20"/>
<constraint firstAttribute="trailing" secondItem="wLs-Rj-kxu" secondAttribute="trailing" constant="20" id="eto-qp-HU8"/>
<constraint firstItem="wLs-Rj-kxu" firstAttribute="top" secondItem="A2Y-eS-2d3" secondAttribute="top" constant="10" id="jqd-ks-cLz"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" name="ThemeMainBackground"/>
<constraints>
<constraint firstItem="A2Y-eS-2d3" firstAttribute="leading" secondItem="ekT-Zr-ohe" secondAttribute="leading" id="HtF-Kg-pSh"/>
<constraint firstItem="A2Y-eS-2d3" firstAttribute="top" secondItem="ekT-Zr-ohe" secondAttribute="top" id="IX1-BU-sQZ"/>
<constraint firstAttribute="trailing" secondItem="A2Y-eS-2d3" secondAttribute="trailing" id="UT7-18-JB5"/>
<constraint firstAttribute="bottom" secondItem="A2Y-eS-2d3" secondAttribute="bottom" id="jJp-6O-h2x"/>
</constraints>
</tableViewCellContentView>
<connections>
<outlet property="amountLabel" destination="M1e-cc-M1d" id="4sb-KT-Tbo"/>
<outlet property="balaceTitleLabel" destination="xJH-zQ-Y2H" id="8Hm-fT-tRH"/>
<outlet property="userNameLabel" destination="HSv-Iz-JvY" id="aE5-dT-TQa"/>
<outlet property="walletBankCodeLabel" destination="IXG-rj-tyI" id="Oae-9x-4IS"/>
<outlet property="walletNumberLabel" destination="FSQ-xU-CsJ" id="0tr-AF-lYp"/>
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="HomeCollectionTableViewCell" rowHeight="250" id="va0-Yj-PKZ" userLabel="CollectionTableCell" customClass="HomeCollectionTableViewCell" customModule="JME_Remit" customModuleProvider="target">
<rect key="frame" x="0.0" y="154.5" width="320" height="250"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="va0-Yj-PKZ" id="UgU-Jo-DQf">
<rect key="frame" x="0.0" y="0.0" width="320" height="250"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="b18-X5-UHi">
<rect key="frame" x="0.0" y="0.0" width="320" height="250"/>
<subviews>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="cS9-wt-rNH">
<rect key="frame" x="10" y="10" width="300" height="230"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="0.0" id="V5P-ja-etg">
<size key="itemSize" width="170" height="173"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
<inset key="sectionInset" minX="10" minY="10" maxX="10" maxY="10"/>
</collectionViewFlowLayout>
<cells>
<collectionViewCell opaque="NO" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="HomeCollectionCollectionViewCell" id="Etq-JH-rVI" customClass="HomeCollectionCollectionViewCell" customModule="JME_Remit" customModuleProvider="target">
<rect key="frame" x="65" y="10" width="170" height="173"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO">
<rect key="frame" x="0.0" y="0.0" width="170" height="173"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="B7x-OB-ICD">
<rect key="frame" x="72" y="75.5" width="26" height="22"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="22" id="SiW-h1-pYT"/>
<constraint firstAttribute="width" constant="26" id="Ymf-0X-IUa"/>
</constraints>
</view>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="2AS-0D-YqT">
<rect key="frame" x="45" y="36.5" width="80" height="80"/>
<color key="backgroundColor" name="ThemeMainBackground"/>
<constraints>
<constraint firstAttribute="width" secondItem="2AS-0D-YqT" secondAttribute="height" multiplier="1:1" id="5g2-sa-yq3"/>
<constraint firstAttribute="width" relation="lessThanOrEqual" constant="80" id="Ddx-6M-Xsk"/>
<constraint firstAttribute="width" priority="900" constant="80" id="F4U-Ej-SBB"/>
</constraints>
</imageView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="HFk-BX-gMN">
<rect key="frame" x="10" y="116.5" width="150" height="56.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ypi-Ft-V2u">
<rect key="frame" x="0.0" y="0.0" width="150" height="6.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" text="Send Money" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" minimumFontSize="7" translatesAutoresizingMaskIntoConstraints="NO" id="1gB-BN-h1P">
<rect key="frame" x="0.0" y="6.5" width="150" height="30"/>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="30" id="RMc-7w-A4h"/>
</constraints>
<fontDescription key="fontDescription" name="SanFranciscoText-Semibold" family="San Francisco Text" pointSize="15"/>
<color key="textColor" red="0.5490196078431373" green="0.58823529411764708" blue="0.62745098039215685" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vff-tE-cNy">
<rect key="frame" x="0.0" y="36.5" width="150" height="20"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstItem="ypi-Ft-V2u" firstAttribute="height" secondItem="vff-tE-cNy" secondAttribute="height" multiplier="1:3" id="aLq-bg-aq7"/>
</constraints>
</stackView>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="ic_dragNdrop" translatesAutoresizingMaskIntoConstraints="NO" id="Tto-II-gHc">
<rect key="frame" x="154" y="6" width="10" height="10"/>
<constraints>
<constraint firstAttribute="height" constant="10" id="Rdp-UH-v8r"/>
<constraint firstAttribute="width" constant="10" id="zk7-DA-GuA"/>
</constraints>
</imageView>
</subviews>
</view>
<color key="backgroundColor" name="ThemeMainBackground"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="HFk-BX-gMN" secondAttribute="bottom" id="1ix-kS-Lwd"/>
<constraint firstItem="2AS-0D-YqT" firstAttribute="centerY" secondItem="B7x-OB-ICD" secondAttribute="centerY" constant="-10" id="EIz-R7-J9H"/>
<constraint firstItem="HFk-BX-gMN" firstAttribute="leading" secondItem="Etq-JH-rVI" secondAttribute="leading" constant="10" id="TjT-df-EhA"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="2AS-0D-YqT" secondAttribute="trailing" constant="10" id="WCa-6N-p51"/>
<constraint firstAttribute="trailing" secondItem="HFk-BX-gMN" secondAttribute="trailing" constant="10" id="a0V-ol-B5N"/>
<constraint firstItem="2AS-0D-YqT" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Etq-JH-rVI" secondAttribute="leading" constant="10" id="a3w-rn-Okr"/>
<constraint firstAttribute="trailing" secondItem="Tto-II-gHc" secondAttribute="trailing" constant="6" id="aDQ-XP-G1H"/>
<constraint firstItem="2AS-0D-YqT" firstAttribute="centerX" secondItem="Etq-JH-rVI" secondAttribute="centerX" id="dcN-Y7-VS9"/>
<constraint firstItem="B7x-OB-ICD" firstAttribute="centerX" secondItem="Etq-JH-rVI" secondAttribute="centerX" id="e35-zO-9X2"/>
<constraint firstItem="2AS-0D-YqT" firstAttribute="top" relation="greaterThanOrEqual" secondItem="Etq-JH-rVI" secondAttribute="topMargin" constant="10" id="j4o-Xh-Xdd"/>
<constraint firstItem="Tto-II-gHc" firstAttribute="top" secondItem="Etq-JH-rVI" secondAttribute="top" constant="6" id="tqF-Pu-NfF"/>
<constraint firstItem="HFk-BX-gMN" firstAttribute="top" secondItem="2AS-0D-YqT" secondAttribute="bottom" id="vLl-YY-L4p"/>
<constraint firstItem="B7x-OB-ICD" firstAttribute="centerY" secondItem="Etq-JH-rVI" secondAttribute="centerY" id="znS-Pz-eoE"/>
</constraints>
<size key="customSize" width="170" height="173"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
<integer key="value" value="10"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
<connections>
<outlet property="dragButton" destination="Tto-II-gHc" id="b4Z-zb-4GB"/>
<outlet property="imageview" destination="2AS-0D-YqT" id="qh6-Um-7Yh"/>
<outlet property="titleLabel" destination="1gB-BN-h1P" id="fFK-Yt-6J0"/>
</connections>
</collectionViewCell>
</cells>
</collectionView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="cS9-wt-rNH" secondAttribute="trailing" constant="10" id="MGc-Wb-7td"/>
<constraint firstAttribute="bottom" secondItem="cS9-wt-rNH" secondAttribute="bottom" constant="10" id="PYN-P6-c2Q"/>
<constraint firstItem="cS9-wt-rNH" firstAttribute="leading" secondItem="b18-X5-UHi" secondAttribute="leading" constant="10" id="Qh0-ea-NQ8"/>
<constraint firstItem="cS9-wt-rNH" firstAttribute="top" secondItem="b18-X5-UHi" secondAttribute="top" constant="10" id="pVI-z3-ybA"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" name="ThemeMainBackground"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="b18-X5-UHi" secondAttribute="trailing" id="EPE-LI-LDL"/>
<constraint firstItem="b18-X5-UHi" firstAttribute="leading" secondItem="UgU-Jo-DQf" secondAttribute="leading" id="TTU-1J-qtU"/>
<constraint firstItem="b18-X5-UHi" firstAttribute="top" secondItem="UgU-Jo-DQf" secondAttribute="top" id="VH1-f0-TKU"/>
<constraint firstAttribute="bottom" secondItem="b18-X5-UHi" secondAttribute="bottom" id="rKM-B7-BPn"/>
</constraints>
</tableViewCellContentView>
<color key="backgroundColor" red="0.90588235289999997" green="0.92941176469999998" blue="0.94901960780000005" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
<connections>
<outlet property="collectionView" destination="cS9-wt-rNH" id="e9C-Lw-qxg"/>
</connections>
</tableViewCell>
</prototypes>
</tableView>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="rYg-o8-m3E">
<rect key="frame" x="0.0" y="144" width="400" height="807"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="32" translatesAutoresizingMaskIntoConstraints="NO" id="fsQ-oi-9f5">
<rect key="frame" x="0.0" y="0.0" width="400" height="134.5"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="A2Y-eS-2d3">
<rect key="frame" x="0.0" y="0.0" width="400" height="134.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Account Number" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FKd-wY-s9e" userLabel="accountTitle">
<rect key="frame" x="16" y="16" width="368" height="16"/>
<constraints>
<constraint firstAttribute="height" constant="16" id="sYn-Uo-aPT"/>
</constraints>
<fontDescription key="fontDescription" name="FONTSPRINGDEMO-VolteSemiboldRegular" family="FONTSPRING DEMO - Volte Semibold" pointSize="12"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="MOB000110" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2D3-BA-yV3">
<rect key="frame" x="16" y="36" width="113.5" height="23.5"/>
<fontDescription key="fontDescription" name="FONTSPRINGDEMO-VolteSemiboldRegular" family="FONTSPRING DEMO - Volte Semibold" pointSize="20"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0B9-0a-Jlt">
<rect key="frame" x="137.5" y="39.5" width="13" height="17"/>
<constraints>
<constraint firstAttribute="width" constant="13" id="PY1-YE-0vx"/>
<constraint firstAttribute="height" constant="17" id="a2I-Sr-5OW"/>
</constraints>
<inset key="contentEdgeInsets" minX="16" minY="3" maxX="16" maxY="5"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="plain" image="addAccount9">
<directionalEdgeInsets key="contentInsets" top="0.0" leading="0.0" bottom="0.0" trailing="0.0"/>
</buttonConfiguration>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" text="JPY 10,000" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="OeT-9p-3lL">
<rect key="frame" x="16" y="75.5" width="82.5" height="19"/>
<fontDescription key="fontDescription" name="FONTSPRINGDEMO-VolteSemiboldRegular" family="FONTSPRING DEMO - Volte Semibold" pointSize="16"/>
<color key="textColor" red="0.0" green="0.80000000000000004" blue="0.59999999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Available Balance" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="oy6-wk-dfr">
<rect key="frame" x="16" y="98.5" width="134.5" height="20"/>
<fontDescription key="fontDescription" name="FONTSPRINGDEMO-VolteSemiboldRegular" family="FONTSPRING DEMO - Volte Semibold" pointSize="17"/>
<color key="textColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="JYo-k5-OO8">
<rect key="frame" x="244" y="75.5" width="140" height="43"/>
<color key="backgroundColor" red="0.0" green="0.80000000000000004" blue="0.59999999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="width" constant="140" id="glh-UA-irf"/>
</constraints>
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
<state key="normal" title="UPLOAD SLIP" image="addAccount9">
<color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</state>
</button>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="FKd-wY-s9e" firstAttribute="leading" secondItem="A2Y-eS-2d3" secondAttribute="leading" constant="16" id="1x9-3Q-xjd"/>
<constraint firstAttribute="trailing" secondItem="JYo-k5-OO8" secondAttribute="trailing" constant="16" id="34f-WI-j8Z"/>
<constraint firstItem="oy6-wk-dfr" firstAttribute="leading" secondItem="A2Y-eS-2d3" secondAttribute="leading" constant="16" id="3m5-9G-7Q6"/>
<constraint firstAttribute="trailing" secondItem="FKd-wY-s9e" secondAttribute="trailing" constant="16" id="FhF-D6-X4p"/>
<constraint firstItem="0B9-0a-Jlt" firstAttribute="centerY" secondItem="2D3-BA-yV3" secondAttribute="centerY" id="GAW-7L-DLJ"/>
<constraint firstItem="2D3-BA-yV3" firstAttribute="leading" secondItem="A2Y-eS-2d3" secondAttribute="leading" constant="16" id="KUn-Ja-ACX"/>
<constraint firstItem="JYo-k5-OO8" firstAttribute="bottom" secondItem="oy6-wk-dfr" secondAttribute="bottom" id="LP1-PQ-sQE"/>
<constraint firstAttribute="bottom" secondItem="oy6-wk-dfr" secondAttribute="bottom" constant="16" id="RZB-zq-fp2"/>
<constraint firstItem="oy6-wk-dfr" firstAttribute="top" secondItem="OeT-9p-3lL" secondAttribute="bottom" constant="4" id="Req-pl-9UX"/>
<constraint firstItem="2D3-BA-yV3" firstAttribute="top" secondItem="FKd-wY-s9e" secondAttribute="bottom" constant="4" id="YSw-zr-mnJ"/>
<constraint firstItem="0B9-0a-Jlt" firstAttribute="leading" secondItem="2D3-BA-yV3" secondAttribute="trailing" constant="8" id="dgU-GC-bMi"/>
<constraint firstItem="OeT-9p-3lL" firstAttribute="top" secondItem="2D3-BA-yV3" secondAttribute="bottom" constant="16" id="ejh-sY-FiE"/>
<constraint firstItem="FKd-wY-s9e" firstAttribute="top" secondItem="A2Y-eS-2d3" secondAttribute="top" constant="16" id="fIC-hY-IK9"/>
<constraint firstItem="OeT-9p-3lL" firstAttribute="leading" secondItem="A2Y-eS-2d3" secondAttribute="leading" constant="16" id="gCn-EE-2bX"/>
<constraint firstItem="JYo-k5-OO8" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="OeT-9p-3lL" secondAttribute="trailing" constant="16" id="mE8-Tv-Ifq"/>
<constraint firstItem="JYo-k5-OO8" firstAttribute="top" secondItem="OeT-9p-3lL" secondAttribute="top" id="yfd-ee-SUt"/>
</constraints>
</view>
</subviews>
<color key="tintColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</stackView>
</subviews>
<constraints>
<constraint firstItem="fsQ-oi-9f5" firstAttribute="leading" secondItem="rYg-o8-m3E" secondAttribute="leading" id="4QT-HE-V82"/>
<constraint firstAttribute="trailing" secondItem="fsQ-oi-9f5" secondAttribute="trailing" id="VSP-cK-4XZ"/>
<constraint firstItem="fsQ-oi-9f5" firstAttribute="top" secondItem="rYg-o8-m3E" secondAttribute="top" id="gjV-R6-rbz"/>
<constraint firstItem="fsQ-oi-9f5" firstAttribute="width" secondItem="rYg-o8-m3E" secondAttribute="width" id="mOB-tT-pIl"/>
<constraint firstAttribute="bottom" secondItem="fsQ-oi-9f5" secondAttribute="bottom" id="ybz-wo-8X5"/>
</constraints>
</scrollView>
</subviews>
<viewLayoutGuide key="safeArea" id="0Kl-lY-qUa"/>
<color key="backgroundColor" name="ThemeMainBackground"/>
<constraints>
<constraint firstItem="rYg-o8-m3E" firstAttribute="leading" secondItem="0Kl-lY-qUa" secondAttribute="leading" id="23C-K1-6aA"/>
<constraint firstItem="rYg-o8-m3E" firstAttribute="top" secondItem="alB-Pe-T92" secondAttribute="bottom" id="2jX-nq-TG2"/>
<constraint firstItem="0Kl-lY-qUa" firstAttribute="trailing" secondItem="alB-Pe-T92" secondAttribute="trailing" id="44c-9q-5Zy"/>
<constraint firstItem="wXh-zk-jWw" firstAttribute="leading" secondItem="0Kl-lY-qUa" secondAttribute="leading" id="CtQ-HI-xXr"/>
<constraint firstItem="wXh-zk-jWw" firstAttribute="top" secondItem="alB-Pe-T92" secondAttribute="bottom" id="N4D-FN-dqe"/>
<constraint firstItem="0Kl-lY-qUa" firstAttribute="trailing" secondItem="wXh-zk-jWw" secondAttribute="trailing" id="OuN-dY-tYN"/>
<constraint firstItem="alB-Pe-T92" firstAttribute="leading" secondItem="0Kl-lY-qUa" secondAttribute="leading" id="Req-1D-gfY"/>
<constraint firstItem="0Kl-lY-qUa" firstAttribute="bottom" secondItem="wXh-zk-jWw" secondAttribute="bottom" id="Ro3-6E-ZmF"/>
<constraint firstItem="0Kl-lY-qUa" firstAttribute="bottom" secondItem="rYg-o8-m3E" secondAttribute="bottom" id="VSd-Q1-BEU"/>
<constraint firstItem="0Kl-lY-qUa" firstAttribute="trailing" secondItem="rYg-o8-m3E" secondAttribute="trailing" id="nbe-WI-gaa"/>
<constraint firstItem="alB-Pe-T92" firstAttribute="top" secondItem="0Kl-lY-qUa" secondAttribute="top" id="u2K-G9-1E9"/>
</constraints>
</view>
<navigationItem key="navigationItem" id="JSG-8j-YZS">
<leftBarButtonItems>
<barButtonItem image="camera" id="QET-jC-Ccs"/>
<barButtonItem title="HI TESTER" width="100" id="lAD-0d-rna"/>
</leftBarButtonItems>
<rightBarButtonItems>
<barButtonItem id="FVP-ju-TEK">
<barButtonItem image="notification_bell_new" id="V5p-kc-03o">
<connections>
<action selector="customerSupport:" destination="HSb-ou-7T5" id="txd-0O-g0j"/>
<action selector="notificationItemClicked:" destination="HSb-ou-7T5" id="Uvk-sq-iHq"/>
</connections>
</barButtonItem>
<barButtonItem image="bell.fill" catalog="system" id="V5p-kc-03o">
<barButtonItem id="FVP-ju-TEK">
<connections>
<action selector="notificationItemClicked:" destination="HSb-ou-7T5" id="Uvk-sq-iHq"/>
<action selector="customerSupport:" destination="HSb-ou-7T5" id="txd-0O-g0j"/>
</connections>
</barButtonItem>
</rightBarButtonItems>
</navigationItem>
<simulatedTabBarMetrics key="simulatedBottomBarMetrics"/>
<size key="freeformSize" width="400" height="1000"/>
<connections>
<outlet property="accountDetailView" destination="A2Y-eS-2d3" id="tV9-sS-LzC"/>
<outlet property="accountTitleLabel" destination="FKd-wY-s9e" id="BrQ-5j-t1I"/>
<outlet property="amountLabel" destination="OeT-9p-3lL" id="B1u-0i-JaH"/>
<outlet property="balaceTitleLabel" destination="oy6-wk-dfr" id="9UG-UH-Dkc"/>
<outlet property="copyButton" destination="0B9-0a-Jlt" id="R4O-qz-Buk"/>
<outlet property="mainContainerView" destination="A2Y-eS-2d3" id="gOv-83-23C"/>
<outlet property="messageLabel" destination="rwJ-pQ-p9z" id="40u-EV-EKU"/>
<outlet property="messageLeftImageview" destination="UD8-ap-8xD" id="VYm-DS-yTJ"/>
<outlet property="messageTitleLabel" destination="pcY-xj-hQb" id="TA6-79-Fl5"/>
<outlet property="messageView" destination="alB-Pe-T92" id="1Di-cQ-gdP"/>
<outlet property="messageViewHeightConstraint" destination="VxG-Dr-LRY" id="80H-Oh-yg2"/>
<outlet property="notificationItem" destination="V5p-kc-03o" id="CXv-cK-M0u"/>
<outlet property="profileImageButton" destination="QET-jC-Ccs" id="qDt-bU-RG4"/>
<outlet property="scrollView" destination="rYg-o8-m3E" id="M62-MC-gnY"/>
<outlet property="seperatorView" destination="17X-fv-KyB" id="dCf-y3-EMS"/>
<outlet property="stackView" destination="fsQ-oi-9f5" id="27r-gp-6Ah"/>
<outlet property="supportBarButton" destination="FVP-ju-TEK" id="Kpo-MA-q0M"/>
<outlet property="tableView" destination="wXh-zk-jWw" id="FZk-dJ-oM4"/>
<outlet property="tapMessageViewGestrueRecognizer" destination="G3V-VT-9Qm" id="XVK-LS-nug"/>
<outlet property="uploadSlipButton" destination="JYo-k5-OO8" id="W8d-uJ-vQn"/>
<outlet property="userName" destination="lAD-0d-rna" id="YCX-bo-C9X"/>
<outlet property="walletNumberLabel" destination="2D3-BA-yV3" id="jJz-yk-e3C"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="8je-5K-XuW" userLabel="First Responder" sceneMemberID="firstResponder"/>
<tapGestureRecognizer id="G3V-VT-9Qm"/>
</objects>
<point key="canvasLocation" x="611.25" y="230.28169014084509"/>
<point key="canvasLocation" x="802.5" y="169.01408450704224"/>
</scene>
<!--Home-->
<scene sceneID="ULq-iv-KTs">
@ -426,7 +239,7 @@
<tabBarItem key="tabBarItem" title="Home" image="branch" id="If6-UM-LN6"/>
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="NbY-y6-481">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<rect key="frame" x="0.0" y="0.0" width="320" height="50"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>
@ -442,24 +255,16 @@
<color key="tintColor" red="0.78177064659999995" green="0.55228364470000002" blue="0.018981300289999999" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<resources>
<image name="Documents" width="201" height="216"/>
<image name="bell.fill" catalog="system" width="128" height="124"/>
<image name="addAccount9" width="24" height="24"/>
<image name="branch" width="22" height="26"/>
<image name="ic_dragNdrop" width="10" height="10"/>
<namedColor name="ThemeBlue">
<color red="0.047058823529411764" green="0.12941176470588237" blue="0.41176470588235292" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<image name="camera" width="33" height="27"/>
<image name="notification_bell_new" width="24" height="24"/>
<namedColor name="ThemeMainBackground">
<color red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="ThemeRed">
<color red="0.86274509803921573" green="0.078431372549019607" blue="0.19215686274509805" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="ThemeRedDark">
<color red="0.86274509803921573" green="0.078431372549019607" blue="0.19215686274509805" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="ThemeSubBackground">
<color red="0.93300002813339233" green="0.93300002813339233" blue="0.93300002813339233" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
</namedColor>
<namedColor name="ThemeText">
<color red="0.5490196078431373" green="0.58823529411764708" blue="0.62745098039215685" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>

244
GME Remit/Modules/Home/User Interface/View/HomeViewController.swift

@ -20,6 +20,12 @@ class HomeViewController: UIViewController {
case collection
}
enum ExchangeResponseType: Int {
case exchangeRates = 0
case exchangeRate
case detailRate
}
struct Constants {
static let verificationNoticeHeight: CGFloat = 100
}
@ -35,19 +41,43 @@ class HomeViewController: UIViewController {
let soonToUseGmeServicesTitle = "verification_in_aproval_process_text".localized()
}
private let exchangeRateView: HomeExchangeRateView = {
let view = HomeExchangeRateView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private let homeCarouselView: HomeCarouselView = {
let view = HomeCarouselView()
view.translatesAutoresizingMaskIntoConstraints = false
view.heightAnchor.constraint(equalToConstant: 132).isActive = true
return view
}()
@IBOutlet weak var accountDetailView: UIView!
@IBOutlet weak var notificationItem: UIBarButtonItem!
@IBOutlet weak var profileImageButton: UIBarButtonItem!
@IBOutlet weak var userName: UIBarButtonItem!
@IBOutlet weak var scrollView: UIScrollView!
// MARK: IBOutlets
@IBOutlet private weak var supportBarButton: UIBarButtonItem!
@IBOutlet private weak var tableView: UITableView!
//@IBOutlet private weak var tableView: UITableView!
@IBOutlet private weak var messageViewHeightConstraint: NSLayoutConstraint!
@IBOutlet private weak var messageView: UIView!
@IBOutlet private weak var messageLabel: UILabel!
@IBOutlet private weak var messageTitleLabel: UILabel!
@IBOutlet private weak var messageLeftImageview: UIImageView!
@IBOutlet weak var accountTitleLabel: UILabel!
@IBOutlet weak var amountLabel: UILabel!
@IBOutlet weak var balaceTitleLabel: UILabel!
@IBOutlet weak var walletNumberLabel: UILabel!
@IBOutlet weak var copyButton: UIButton!
@IBOutlet weak var uploadSlipButton: UIButton!
@IBOutlet weak var mainContainerView: UIView!
@IBOutlet private var tapMessageViewGestrueRecognizer: UITapGestureRecognizer!
@IBOutlet weak var stackView: UIStackView!
@IBOutlet private weak var seperatorView: UIView!
// MARK: Properties
@ -85,15 +115,34 @@ class HomeViewController: UIViewController {
var presenter: HomeModuleInterface?
var updateCalled: Bool = false
var trustDockResponse: TrustDockResponse?
var exchangeRateModels: [ExchangeRateModel]? {
didSet {
exchangeResponseType = .exchangeRates
}
}
var exchangeRateModel: ExchangeRateModel? {
didSet {
exchangeResponseType = .exchangeRate
}
}
var exchangeRateDetailModel: ExchangeRateDetailModel? {
didSet {
exchangeResponseType = .detailRate
}
}
var exchangeResponseType: ExchangeResponseType = .exchangeRates
var user: User? {
didSet {
// update
self.save(user: user)
setMessageView()
self.tableView.reloadData()
// self.tableView.reloadData()
updateBalance()
setupUserInfo()
if hasUpdatedDefaultCredentials == 1 || hasUpdatedDefaultCredentials == 2 || hasUpdatedDefaultCredentials == 3 || hasUpdatedDefaultCredentials == 4 || hasVerifiedOTP == false || !didSubmitKycAndVerified {
self.addDimView()
} else {
@ -194,7 +243,7 @@ class HomeViewController: UIViewController {
var menuHeight: CGFloat? {
didSet {
self.tableView.reloadData()
//self.tableView.reloadData()
}
}
// MARK: VC's Life cycle
@ -212,18 +261,22 @@ class HomeViewController: UIViewController {
setupNotificationBadge()
let supportImage = UIImage(named: "customer_support")?.withRenderingMode(.alwaysOriginal)
let supportImage = UIImage(named: "customer_support_new")?.withRenderingMode(.alwaysOriginal)
supportBarButton.image = supportImage
NotificationCenter.default.addObserver(
self,
selector: #selector(self.getYearlyLimitNotificationName),
name: self.getYearlyLimitNotificationName(),
object: nil
)
// let notificationImage = UIImage(named: "customer_support")?.withRenderingMode(.alwaysOriginal)
// notificationItem.image = notificationImage
notificationItem.tintColor = UIColor.themeRed
self.navigationController?.navigationBar.setValue(true, forKey: "hidesShadow")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tableView.reloadData()
//self.tableView.reloadData()
NotificationCenter.default.addObserver(
self,
selector: #selector(updateTabBarTitle),
@ -237,6 +290,10 @@ class HomeViewController: UIViewController {
}
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.navigationItem.title = ""
@ -258,16 +315,43 @@ class HomeViewController: UIViewController {
// all setup should be done here
self.messageViewHeightConstraint.constant = 0
self.messageView.alpha = 0
setupHierachy()
setupDelegates()
setupNotifications()
addRefreshControlTableView()
userName.setTitleTextAttributes([
NSAttributedString.Key.font : UIFont.sanfrancisco(.bold, size: 20),
NSAttributedString.Key.foregroundColor : UIColor.themeBlack,
], for: .normal)
}
private func setupHierachy() {
accountDetailView.setupCornerRadius(20,maskedCorners: [.layerMinXMaxYCorner, .layerMaxXMaxYCorner])
accountDetailView.layer.addShadow(with: UIColor.gray, shadowRadius: 10.0, shadowOffset: CGSize(width: 0, height: 1))
uploadSlipButton.titleLabel?.font = .sanfrancisco(.bold, size: 12)
uploadSlipButton.set(cornerRadius: 20)
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.addArrangedSubview(exchangeRateView)
stackView.addArrangedSubview(homeCarouselView)
exchangeRateView.openCountryList = { [weak self] in
self?.showCountryList()
}
exchangeRateView.tappedCalculateExchangeRate = { [weak self] model in
self?.presenter?.exchangeCalculate(use: model)
}
}
func setupNotificationBadge() {
var badgeAppearance = BadgeAppearance()
badgeAppearance.textColor = UIColor.red
notificationItem.badge(text: "\(notificationCount)", appearance: badgeAppearance)
//var badgeAppearance = BadgeAppearance()
//badgeAppearance.textColor = UIColor.red
let notificationImage = UIImage(named: "ic_notification_dot_new")?.withRenderingMode(.alwaysOriginal)
notificationItem.image = notificationImage
// notificationItem.badge(text: "\(notificationCount)", appearance: badgeAppearance)
}
private func update() {
@ -315,12 +399,23 @@ class HomeViewController: UIViewController {
object: nil,
userInfo: userInfo
)
self.tableView.reloadData()
//self.tableView.reloadData()
}
@objc private func getYearlyLimitNotificationName() -> Notification.Name {
return Notification.Name.init(AppConstants.yearlyLimitNotification)
}
private func updateYearlyLimit(sender: Notification) {
if let amount = sender.userInfo?[AppConstants.yearlyLimitNotification] as? String {
self.amountLabel.text = amount
}
}
private func setupDelegates() {
tableView.delegate = self
tableView.dataSource = self
//tableView.delegate = self
//tableView.dataSource = self
}
private func addRefreshControlTableView() {
@ -334,14 +429,31 @@ class HomeViewController: UIViewController {
refreshControl.addTarget(self, action: #selector(self.refresh), for: .valueChanged)
self.refreshControl = refreshControl
if #available(iOS 10.0, *) {
tableView.refreshControl = self.refreshControl
scrollView.refreshControl = self.refreshControl
} else {
if let control = self.refreshControl {
tableView.addSubview(control)
scrollView.addSubview(control)
}
}
}
func setupUserInfo() {
let availableBalance = GMEDB.shared.user.string(.availableBalance)
self.amountLabel.text = "JYP" + " " + (availableBalance?.likeCommaMoney() ?? "")
let walletNumber = GMEDB.shared.user.string(.referralCode) ?? ""
walletNumberLabel.text = walletNumber == "" ? "N/A" : walletNumber
copyButton.setTitle("", for: .normal)
mainContainerView.setupCornerRadius(20,maskedCorners: [.layerMinXMaxYCorner, .layerMaxXMaxYCorner])
userName.title = " HI Rabin"//"HI" + " " + (GMEDB.shared.user.string(.userId) ?? "")
}
private func configureText() {
balaceTitleLabel.text = "domestic_available_balance_text".localized()
accountTitleLabel.text = "account_number_text".localized()
}
@IBAction func notificationItemClicked(_ sender: Any) {
presenter?.openNotification()
}
@ -385,6 +497,14 @@ class HomeViewController: UIViewController {
self.menuHeight = height
}
}
@objc func showCountryList() {
TablePresenterWireframe().openWith(
delegate: self,
model: exchangeRateModels,
source: self
)
}
}
extension HomeViewController: OtpDelegate {
@ -569,10 +689,10 @@ extension HomeViewController {
}
func setNavBar(isUseMenu: Bool) {
let selector = #selector(self.showSideMenu)
isUseMenu ? setupPicturedNavBar(sideMenuAction: selector) : setupPicturedNavBar(sideMenuAction: nil)
MainWireframe.shared?.isUseSwipeGesture = isUseMenu
// let selector = #selector(self.showSideMenu)
//
// isUseMenu ? setupPicturedNavBar(sideMenuAction: selector) : setupPicturedNavBar(sideMenuAction: nil)
// MainWireframe.shared?.isUseSwipeGesture = isUseMenu
}
}
@ -644,11 +764,23 @@ extension HomeViewController {
self.push(viewController, animated: true)
}
}
// MARK: HomeViewInterface
extension HomeViewController: HomeViewInterface {
func setModel(with model: [ExchangeRateModel]?) {
self.exchangeRateModels = model
self.exchangeRateView.set(model)
}
func setModel(with model: ExchangeRateDetailModel?) {
self.exchangeRateDetailModel = model
self.exchangeRateView.set(model)
self.homeCarouselView.update(["test1", "test2", "test3671"])
//reload(0, Sections.collection.rawValue)
}
func showOtpView() {
guard let viewController = UIStoryboard(name: "OtpVerification", bundle: nil)
.instantiateViewController(withIdentifier: "OtpVerificationViewController") as? OtpVerificationViewController else {
@ -669,8 +801,11 @@ extension HomeViewController: HomeViewInterface {
}
}
func show(model: User) {
func show(model: User,
with rates: [ExchangeRateModel]?) {
self.user = model
self.exchangeRateModels = rates
self.exchangeRateView.set(rates)
}
func show(error: String) {
@ -689,10 +824,15 @@ extension HomeViewController: HomeViewInterface {
func hideLoading() {
self.hideProgressHud()
if self.tableView.refreshControl?.isRefreshing ?? false {
self.tableView.refreshControl?.endRefreshing()
if self.scrollView.refreshControl?.isRefreshing ?? false {
self.scrollView.refreshControl?.endRefreshing()
}
}
private func reload(_ row: Int, _ section: Int) {
let indexPosition = IndexPath(row: row, section: section)
// tableView.reloadRows(at: [indexPosition], with: .none)
}
}
// MARK: - UITableViewDelegate
@ -711,6 +851,10 @@ extension HomeViewController: UITableViewDelegate {
return finalHeight
}
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
}
// MARK: - UITableViewDataSource
@ -735,14 +879,14 @@ extension HomeViewController: UITableViewDataSource {
func configureRemainingLimitCell(tableView: UITableView, indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(
withIdentifier: "HomeRemainingLimitTableViewCell"
withIdentifier: HomeRemainingLimitTableViewCell.identifier
) as? HomeRemainingLimitTableViewCell else {
return UITableViewCell()
}
cell.user = self.user
cell.setup()
cell.sideMenuDelegate = self
//cell.user = self.user
//cell.setup()
//cell.sideMenuDelegate = self
return cell
}
@ -753,8 +897,20 @@ extension HomeViewController: UITableViewDataSource {
return UITableViewCell()
}
cell.setup()
// switch exchangeResponseType {
// case .exchangeRates:
// cell.setup(exchangeRateModels)
// case .exchangeRate:
// cell.setup(exchangeRateModel)
// case .detailRate:
// cell.setup(self.exchangeRateDetailModel)
// }
cell.setup(exchangeRateModel)
cell.setup(self.exchangeRateModels)
cell.setup(self.exchangeRateDetailModel)
cell.homeCollectionDelegate = self
cell.parentViewController = self
return cell
}
@ -860,6 +1016,28 @@ extension HomeViewController: SideMenuDelegate {
}
}
}
extension HomeViewController: TablePresenterDelegate {
func tablePresenterView(_ viewController: TablePresenterViewController) -> TablePresenterConfiguration {
return TablePresenterConfiguration(
presenterTitle: "search_currency_text".localized(),
closeButtonTitle: "cancel_text".localized(),
notFoundTitle: "no_result_found_text".localized(),
searchBarPlaceHolder: "search_currency_text".localized()
)
}
func tablePresenterView(
_ viewController: TablePresenterViewController,
didSelectModel model: TablePresenterProtocol?
) {
if let exchangeRateModel = model as? ExchangeRateModel {
self.exchangeRateModel = exchangeRateModel
self.exchangeRateView.set(exchangeRateModel)
//reload(0, Sections.collection.rawValue)
}
}
}
extension HomeViewController {
fileprivate func initializeSDK() {
// Checking internet connectivity

221
GME Remit/Modules/Home/User Interface/View/HomeViewControllerNew.swift

@ -0,0 +1,221 @@
//
import UIKit
import Localize_Swift
import LGSideMenuController
class HomeViewControllerNew: UIViewController {
var user: User?
var presenter: HomeModuleInterface?
var exchangeRateModels: [ExchangeRateModel]?
// MARK: UIView
private let scrollView: UIScrollView = {
let view = UIScrollView(frame: .zero)
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .themeWhite
return view
}()
private let mainContainerView: UIView = {
let view = UIView(frame: .zero)
view.backgroundColor = .themeWhite
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private let accountDetailView: HomeAccountDetailView = {
let view = HomeAccountDetailView()
view.backgroundColor = .themeWhite
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private let exchangeRateView: HomeExchangeRateView = {
let view = HomeExchangeRateView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
init(){
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
self.setup()
self.presenter?.fetchExchangeRate()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.isNavigationBarHidden = true
self.navigationController?.setNavigationBarHidden(true, animated: animated)
}
private func setup() {
hierarchySetup()
layoutSetup()
setupCallback()
}
private func hierarchySetup() {
view.addSubview(scrollView)
scrollView.addSubview(mainContainerView)
mainContainerView.addSubviews(accountDetailView,
exchangeRateView)
}
func layoutSetup() {
scrollView.anchor(top: view.topAnchor,
paddingTop: 0,
bottom: view.bottomAnchor,
paddingBottom: 0,
left: view.leadingAnchor,
paddingLeft: 0,
right: view.trailingAnchor,
paddingRight: 0
)
mainContainerView.anchor(top: scrollView.topAnchor,
paddingTop: 0,
bottom: scrollView.bottomAnchor,
paddingBottom: 0,
left: scrollView.leadingAnchor,
paddingLeft: 0,
right: scrollView.trailingAnchor,
paddingRight: 0
)
mainContainerView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
accountDetailView.anchor(top: mainContainerView.topAnchor,
paddingTop: 0,
paddingBottom: 0,
left: mainContainerView.leadingAnchor,
paddingLeft: 0,
right: mainContainerView.trailingAnchor,
paddingRight: 0,
width: 0,
height: 0)
exchangeRateView.anchor(top: accountDetailView.bottomAnchor,
paddingTop: 16,
bottom: mainContainerView.bottomAnchor,
paddingBottom: 0,
left: mainContainerView.leadingAnchor,
paddingLeft: 16,
right: mainContainerView.trailingAnchor,
paddingRight: -16,
width: 0,
height: 0)
}
private func setupCallback() {
exchangeRateView.openCountryList = { [weak self] in
self?.showCountryList()
}
exchangeRateView.tappedCalculateExchangeRate = { [weak self] model in
self?.presenter?.exchangeCalculate(use: model)
}
}
@objc func showCountryList() {
TablePresenterWireframe().openWith(
delegate: self,
model: exchangeRateModels,
source: self
)
}
}
extension HomeViewControllerNew: HomeViewInterface {
func show(model: User, with rates: [ExchangeRateModel]?) {
}
func showOtpView() {
guard let viewController = UIStoryboard(name: "OtpVerification", bundle: nil)
.instantiateViewController(withIdentifier: "OtpVerificationViewController") as? OtpVerificationViewController else {
return
}
//viewController.delegate = self
self.present(viewController, animated: true, completion: nil)
}
func checkOtpError(error: String) {
self.alert(type: .error, message: error)
}
func success() {
self.alertWithOk(type: .success, message: "OTP Verification completed", title: "success_text".localized(), okTitle: "ok_text".localized()) {
//self.presenter?.viewIsReady()
}
}
func show(model: User) {
self.user = model
}
func show(error: String) {
self.alert(type: .error, message: error)
}
func show(panicError: String) {
self.alert(type: .error, message: panicError, title: "Warning") {
//self.presenter?.logout()
}
}
func showLoading() {
self.showProgressHud()
}
func hideLoading() {
self.hideProgressHud()
}
func setModel(with model: [ExchangeRateModel]?) {
self.exchangeRateModels = model
exchangeRateView.set(model)
}
func setModel(with model: ExchangeRateDetailModel?) {
exchangeRateView.set(model)
}
}
// MARK: - TablePresenterDelegate
extension HomeViewControllerNew: TablePresenterDelegate {
func tablePresenterView(_ viewController: TablePresenterViewController) -> TablePresenterConfiguration {
return TablePresenterConfiguration(
presenterTitle: "search_currency_text".localized(),
closeButtonTitle: "cancel_text".localized(),
notFoundTitle: "no_result_found_text".localized(),
searchBarPlaceHolder: "search_currency_text".localized()
)
}
func tablePresenterView(
_ viewController: TablePresenterViewController,
didSelectModel model: TablePresenterProtocol?
) {
if let exchangeRateModel = model as? ExchangeRateModel {
exchangeRateView.selectedPaymentModeIndex = 0
exchangeRateView.set(exchangeRateModel)
}
}
}

7
GME Remit/Modules/Home/User Interface/View/HomeViewInterface.swift

@ -6,8 +6,9 @@
//Copyright © 2018 Gobal Money Express Co. Ltd. All rights reserved.
//
protocol HomeViewInterface: class {
func show(model: User)
protocol HomeViewInterface: AnyObject {
func show(model: User,
with rates: [ExchangeRateModel]?)
func show(error: String)
func showLoading()
func hideLoading()
@ -15,4 +16,6 @@ protocol HomeViewInterface: class {
func success()
func showOtpView()
func checkOtpError(error: String)
func setModel(with model: [ExchangeRateModel]?)
func setModel(with model: ExchangeRateDetailModel?)
}

5
GME Remit/Modules/Home/User Interface/Wireframe/HomeWireframe.swift

@ -25,8 +25,11 @@ extension HomeWireframe: HomeWireframeInput {
func getMainView() -> UIViewController {
let service = HomeService()
let interactor = HomeInteractor(service: service)
let exchangeRateService = ExchangeRatesService()
let interactor = HomeInteractor(service: service,
exchangeRateService: exchangeRateService)
let presenter = HomePresenter()
//let viewController = HomeViewControllerNew()
let viewController = viewControllerFromStoryboard(of: HomeViewController.self)
viewController.setupTabItem()
viewController.presenter = presenter

21
GME Remit/Modules/Main/User Interface/View/MainViewController.swift

@ -35,7 +35,7 @@ class MainViewController: UITabBarController {
setupLayout()
setupProperties()
bind()
view.layoutIfNeeded()
// view.layoutIfNeeded()
}
@ -43,9 +43,9 @@ class MainViewController: UITabBarController {
super.viewWillAppear(animated)
navigationController?.isNavigationBarHidden = true
self.navigationController?.setNavigationBarHidden(true, animated: animated)
// tabBar.items?[0].title = "home_text".localized()
// tabBar.items?[1].title = "send_money_text".localized()
// tabBar.items?[2].title = "branch_text".localized()
// tabBar.items?[0].title = "home_text".localized()
//tabBar.items?[1].title = "send_money_text".localized()
//tabBar.items?[2].title = "profile_text".localized()
//
// guard UIStoryboard(name: "Profile", bundle: nil)
// .instantiateViewController(withIdentifier: "ProfileViewController") is ProfileViewController else {
@ -56,13 +56,13 @@ class MainViewController: UITabBarController {
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
self.title = ""
self.navigationController?.setNavigationBarHidden(false, animated: animated)
self.title = ""
self.navigationController?.setNavigationBarHidden(false, animated: animated)
}
func setup(viewControllers: [UIViewController]) {
// self.viewControllers = viewControllers
//self.setupTab()
// self.setupTab()
setupTabItem()
}
@ -71,15 +71,14 @@ class MainViewController: UITabBarController {
}
private func setupLayout() {
customTabBar.widthAnchor.constraint(equalToConstant: 200).isActive = true
customTabBar.heightAnchor.constraint(equalToConstant: 60).isActive = true
customTabBar.widthAnchor.constraint(equalToConstant: 168).isActive = true
customTabBar.heightAnchor.constraint(equalToConstant: 48).isActive = true
customTabBar.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
customTabBar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -24).isActive = true
customTabBar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -17).isActive = true
}
private func setupProperties() {
tabBar.isHidden = true
customTabBar.translatesAutoresizingMaskIntoConstraints = false
customTabBar.addShadow()

21
GME Remit/Supported Files/Assets.xcassets/customer_support_new.imageset/Contents.json

@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Group 10616.svg",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

14
GME Remit/Supported Files/Assets.xcassets/customer_support_new.imageset/Group 10616.svg

@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<g id="Group_10616" data-name="Group 10616" transform="translate(-320 -39)">
<g id="Group_10401" data-name="Group 10401" transform="translate(152 5)">
<rect id="Rectangle_2575" data-name="Rectangle 2575" width="24" height="24" transform="translate(168 34)" fill="none"/>
<g id="icons8-communication_2_" data-name="icons8-communication (2)" transform="translate(168.001 34)">
<path id="Path_47024" data-name="Path 47024" d="M9.5,2A7.488,7.488,0,0,0,2.782,12.82l-.754,3.014a.937.937,0,0,0,1.137,1.137l3.014-.754A7.5,7.5,0,1,0,9.5,2Z" opacity="0.35"/>
<path id="Path_47025" data-name="Path 47025" d="M20.85,16.35l1.121,4.484a.937.937,0,0,1-1.137,1.137L16.35,20.85Z"/>
<path id="Path_47026" data-name="Path 47026" d="M16.677,7.323a7.5,7.5,0,0,1-9.354,9.354,7.5,7.5,0,1,0,9.354-9.354Z"/>
<path id="Path_47027" data-name="Path 47027" d="M13,9H7A1,1,0,0,1,7,7h6a1,1,0,0,1,0,2Z"/>
<path id="Path_47028" data-name="Path 47028" d="M11,13H7a1,1,0,0,1,0-2h4a1,1,0,0,1,0,2Z"/>
</g>
</g>
</g>
</svg>

21
GME Remit/Supported Files/Assets.xcassets/exchangeRateButton.imageset/Contents.json

@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "exchangeRateButton.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

10
GME Remit/Supported Files/Assets.xcassets/exchangeRateButton.imageset/exchangeRateButton.svg

@ -0,0 +1,10 @@
<svg id="_24px_43_" data-name="24px (43)" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
<path id="Path_1000" data-name="Path 1000" d="M0,0H20V20H0Z" fill="none"/>
<g id="icons8-up-down-arrow" transform="translate(0.799 1.587)">
<path id="Path_38524" data-name="Path 38524" d="M.694,0A.693.693,0,0,0,.2,1.181l3.081,3.11a1,1,0,0,0,1.424,0l3.081-3.11A.693.693,0,0,0,7.3,0Z" transform="translate(10.413 12.022)"/>
<path id="Path_38525" data-name="Path 38525" d="M3.2,7.19V1.6A1.6,1.6,0,0,0,0,1.6V7.19Z" transform="translate(12.81 5.255)"/>
<circle id="Ellipse_1881" data-name="Ellipse 1881" cx="1.5" cy="1.5" r="1.5" transform="translate(12.457)"/>
<path id="Path_38526" data-name="Path 38526" d="M7.787,3.407,4.707.3A1,1,0,0,0,3.283.3L.2,3.407A.693.693,0,0,0,.694,4.588H2.4V9.381a1.6,1.6,0,0,0,3.2,0V4.588H7.3A.693.693,0,0,0,7.787,3.407Z" transform="translate(0 0.217)" opacity="0.35"/>
<circle id="Ellipse_1882" data-name="Ellipse 1882" cx="1.5" cy="1.5" r="1.5" transform="translate(2.947 13.826)" opacity="0.35"/>
</g>
</svg>

21
GME Remit/Supported Files/Assets.xcassets/exchange_rate_guranteed.imageset/Contents.json

@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "guranteed.svg",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

11
GME Remit/Supported Files/Assets.xcassets/exchange_rate_guranteed.imageset/guranteed.svg

@ -0,0 +1,11 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<g id="Group_10682" data-name="Group 10682" transform="translate(656 827.041) rotate(180)">
<rect id="Rectangle_2553" data-name="Rectangle 2553" width="24" height="24" transform="translate(632 803.041)" fill="none"/>
<g id="icons8-japanese-yen" transform="translate(656 827.041) rotate(180)">
<circle id="Ellipse_2033" data-name="Ellipse 2033" cx="10" cy="10" r="10" transform="translate(2 2)" fill="#2e89ff" opacity="0.35"/>
<path id="Path_47186" data-name="Path 47186" d="M15.5,12h-7a.5.5,0,0,0,0,1h7a.5.5,0,0,0,0-1Z" fill="#2e89ff"/>
<path id="Path_47187" data-name="Path 47187" d="M15.5,14h-7a.5.5,0,0,0,0,1h7a.5.5,0,0,0,0-1Z" fill="#2e89ff"/>
<path id="Path_47188" data-name="Path 47188" d="M13.214,13.538V16.28a1.22,1.22,0,0,1-1.22,1.22h0a1.22,1.22,0,0,1-1.22-1.22V13.538L8.636,8.126A1.188,1.188,0,0,1,9.741,6.5h.048a1.19,1.19,0,0,1,1.142.858L12,11.052h.032l1.085-3.7a1.187,1.187,0,0,1,1.14-.854h0a1.189,1.189,0,0,1,1.105,1.628Z" fill="#2e89ff"/>
</g>
</g>
</svg>

21
GME Remit/Supported Files/Assets.xcassets/exchange_rate_transfer_fee.imageset/Contents.json

@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "transfer.svg",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

14
GME Remit/Supported Files/Assets.xcassets/exchange_rate_transfer_fee.imageset/transfer.svg

@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<g id="Group_10682" data-name="Group 10682" transform="translate(656 827.041) rotate(180)">
<rect id="Rectangle_2553" data-name="Rectangle 2553" width="24" height="24" transform="translate(632 803.041)" fill="none"/>
<g id="icons8-stack-of-coins" transform="translate(656 827.041) rotate(180)">
<path id="Path_47189" data-name="Path 47189" d="M12,4.5C12,3.119,9.761,2,7,2S2,3.119,2,4.5v15C2,20.881,4.239,22,7,22s5-1.119,5-2.5Z" fill="#2e89ff" opacity="0.35"/>
<path id="Path_47190" data-name="Path 47190" d="M22,8.5C22,7.119,19.761,6,17,6s-5,1.119-5,2.5v9c0,1.381,2.239,2.5,5,2.5s5-1.119,5-2.5Z" fill="#2e89ff" opacity="0.35"/>
<path id="Path_47191" data-name="Path 47191" d="M17,17c-2.761,0-5-1.119-5-2.5v3c0,1.381,2.239,2.5,5,2.5s5-1.119,5-2.5v-3C22,15.881,19.761,17,17,17Z" fill="#2e89ff"/>
<path id="Path_47192" data-name="Path 47192" d="M7,19c-2.761,0-5-1.119-5-2.5v3C2,20.881,4.239,22,7,22s5-1.119,5-2.5v-3C12,17.881,9.761,19,7,19Z" fill="#2e89ff"/>
<path id="Path_47193" data-name="Path 47193" d="M7,13c-2.761,0-5-1.119-5-2.5v3C2,14.881,4.239,16,7,16s5-1.119,5-2.5v-3C12,11.881,9.761,13,7,13Z" fill="#2e89ff"/>
<path id="Path_47194" data-name="Path 47194" d="M7,7C4.239,7,2,5.881,2,4.5v3C2,8.881,4.239,10,7,10s5-1.119,5-2.5v-3C12,5.881,9.761,7,7,7Z" fill="#2e89ff"/>
<path id="Path_47195" data-name="Path 47195" d="M17,11c-2.761,0-5-1.119-5-2.5v3c0,1.381,2.239,2.5,5,2.5s5-1.119,5-2.5v-3C22,9.881,19.761,11,17,11Z" fill="#2e89ff"/>
</g>
</g>
</svg>

21
GME Remit/Supported Files/Assets.xcassets/ic_notification_dot_new.imageset/Contents.json

@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Group 10556.svg",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

15
GME Remit/Supported Files/Assets.xcassets/ic_notification_dot_new.imageset/Group 10556.svg

@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<g id="Group_10556" data-name="Group 10556" transform="translate(-320 -39)">
<g id="Group_10401" data-name="Group 10401" transform="translate(152 5)">
<rect id="Rectangle_2575" data-name="Rectangle 2575" width="24" height="24" transform="translate(168 34)" fill="none"/>
<g id="icons8-notification" transform="translate(168 33.999)">
<path id="Path_46976" data-name="Path 46976" d="M9,20a3,3,0,0,0,6,0Z"/>
<path id="Path_46977" data-name="Path 46977" d="M19,10.667V9.294A7.194,7.194,0,0,0,12.215,2,7,7,0,0,0,5,9v1.667a7,7,0,0,1-1.4,4.2L2.45,16.4A2.249,2.249,0,0,0,2,17.75H2A2.25,2.25,0,0,0,4.25,20h15.5A2.25,2.25,0,0,0,22,17.75h0a2.249,2.249,0,0,0-.45-1.35L20.4,14.867A7,7,0,0,1,19,10.667Z" opacity="0.35"/>
</g>
</g>
<g id="Group_10402" data-name="Group 10402" transform="translate(318 40)">
<circle id="Ellipse_1811" data-name="Ellipse 1811" cx="8" cy="8" r="8" transform="translate(10 -1)"/>
<text id="_12" data-name="12" transform="translate(13 10)" font-size="10" font-family="Volte-SemiBold, Volte" font-weight="600" letter-spacing="0.013em"><tspan x="0" y="0">12</tspan></text>
</g>
</g>
</svg>

21
GME Remit/Supported Files/Assets.xcassets/notification_bell_new.imageset/Contents.json

@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Group 10401.svg",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

9
GME Remit/Supported Files/Assets.xcassets/notification_bell_new.imageset/Group 10401.svg

@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<g id="Group_10401" data-name="Group 10401" transform="translate(-168 -34)">
<rect id="Rectangle_2575" data-name="Rectangle 2575" width="24" height="24" transform="translate(168 34)" fill="none"/>
<g id="icons8-notification" transform="translate(168 33.999)">
<path id="Path_46976" data-name="Path 46976" d="M9,20a3,3,0,0,0,6,0Z"/>
<path id="Path_46977" data-name="Path 46977" d="M19,10.667V9.294A7.194,7.194,0,0,0,12.215,2,7,7,0,0,0,5,9v1.667a7,7,0,0,1-1.4,4.2L2.45,16.4A2.249,2.249,0,0,0,2,17.75H2A2.25,2.25,0,0,0,4.25,20h15.5A2.25,2.25,0,0,0,22,17.75h0a2.249,2.249,0,0,0-.45-1.35L20.4,14.867A7,7,0,0,1,19,10.667Z" opacity="0.35"/>
</g>
</g>
</svg>

6
GME Remit/Supported Files/Assets.xcassets/tabbar/Contents.json

@ -1,6 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
}
}
}

21
GME Remit/Supported Files/Assets.xcassets/tabbar/tab-contact-selected.imageset/Contents.json

@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "style_black_24dp.svg",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

8
GME Remit/Supported Files/Assets.xcassets/tabbar/tab-contact-selected.imageset/style_black_24dp.svg

@ -0,0 +1,8 @@
<svg id="style_black_24dp" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path id="Path_43491" data-name="Path 43491" d="M0,0H24V24H0Z" fill="none"/>
<g id="icons8-contact">
<path id="Path_43619" data-name="Path 43619" d="M19,5H11L9.879,3.879A3,3,0,0,0,7.757,3H4A2,2,0,0,0,2,5V18a3,3,0,0,0,3,3H7a1,1,0,0,1,2,0h6a1,1,0,0,1,2,0h2a3,3,0,0,0,3-3V8A3,3,0,0,0,19,5Z" fill="#2e89ff" opacity="0.35"/>
<circle id="Ellipse_1910" data-name="Ellipse 1910" cx="2" cy="2" r="2" transform="translate(10 8)" fill="#2e89ff"/>
<path id="Path_43620" data-name="Path 43620" d="M14.5,14h-5a1.5,1.5,0,0,0,0,3h5a1.5,1.5,0,0,0,0-3Z" fill="#2e89ff"/>
</g>
</svg>

21
GME Remit/Supported Files/Assets.xcassets/tabbar/tab-contact.imageset/Contents.json

@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "style_black_24dp (1).svg",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

8
GME Remit/Supported Files/Assets.xcassets/tabbar/tab-contact.imageset/style_black_24dp (1).svg

@ -0,0 +1,8 @@
<svg id="style_black_24dp" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<path id="Path_43491" data-name="Path 43491" d="M0,0H24V24H0Z" fill="none"/>
<g id="icons8-contact">
<path id="Path_43619" data-name="Path 43619" d="M19,5H11L9.879,3.879A3,3,0,0,0,7.757,3H4A2,2,0,0,0,2,5V18a3,3,0,0,0,3,3H7a1,1,0,0,1,2,0h6a1,1,0,0,1,2,0h2a3,3,0,0,0,3-3V8A3,3,0,0,0,19,5Z" opacity="0.35"/>
<circle id="Ellipse_1910" data-name="Ellipse 1910" cx="2" cy="2" r="2" transform="translate(10 8)"/>
<path id="Path_43620" data-name="Path 43620" d="M14.5,14h-5a1.5,1.5,0,0,0,0,3h5a1.5,1.5,0,0,0,0-3Z"/>
</g>
</svg>

21
GME Remit/Supported Files/Assets.xcassets/tabbar/tab-home-selected.imageset/Contents.json

@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Group 10878.svg",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

10
GME Remit/Supported Files/Assets.xcassets/tabbar/tab-home-selected.imageset/Group 10878.svg

@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<g id="Group_10878" data-name="Group 10878" transform="translate(-632 -803.041)">
<rect id="Rectangle_2553" data-name="Rectangle 2553" width="24" height="24" transform="translate(632 803.041)" fill="none"/>
<g id="icons8-home-page" transform="translate(631.999 803.543)">
<path id="Path_43550" data-name="Path 43550" d="M18,21H6a3,3,0,0,1-3-3V8.765A3,3,0,0,1,4.543,6.143l6-3.333a3,3,0,0,1,2.914,0l6,3.333A3,3,0,0,1,21,8.765V18A3,3,0,0,1,18,21Z" fill="#0052ff" opacity="0.35"/>
<path id="Path_43551" data-name="Path 43551" d="M15,21H9V15a2,2,0,0,1,2-2h2a2,2,0,0,1,2,2Z" fill="#0052ff"/>
<path id="Path_43552" data-name="Path 43552" d="M20.5,9.23a1.494,1.494,0,0,1-.727-.189l-6.839-3.8a1.909,1.909,0,0,0-1.864,0L4.23,9.041A1.5,1.5,0,0,1,2.773,6.418l6.839-3.8a4.888,4.888,0,0,1,4.778,0l6.839,3.8A1.5,1.5,0,0,1,20.5,9.23Z" fill="#0052ff"/>
</g>
</g>
</svg>

21
GME Remit/Supported Files/Assets.xcassets/tabbar/tab-home.imageset/Contents.json

@ -0,0 +1,21 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Group 10877.svg",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

10
GME Remit/Supported Files/Assets.xcassets/tabbar/tab-home.imageset/Group 10877.svg

@ -0,0 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
<g id="Group_10877" data-name="Group 10877" transform="translate(-632 -803.041)">
<rect id="Rectangle_2553" data-name="Rectangle 2553" width="24" height="24" transform="translate(632 803.041)" fill="none"/>
<g id="icons8-home-page" transform="translate(631.999 803.543)">
<path id="Path_43550" data-name="Path 43550" d="M18,21H6a3,3,0,0,1-3-3V8.765A3,3,0,0,1,4.543,6.143l6-3.333a3,3,0,0,1,2.914,0l6,3.333A3,3,0,0,1,21,8.765V18A3,3,0,0,1,18,21Z" opacity="0.35"/>
<path id="Path_43551" data-name="Path 43551" d="M15,21H9V15a2,2,0,0,1,2-2h2a2,2,0,0,1,2,2Z"/>
<path id="Path_43552" data-name="Path 43552" d="M20.5,9.23a1.494,1.494,0,0,1-.727-.189l-6.839-3.8a1.909,1.909,0,0,0-1.864,0L4.23,9.041A1.5,1.5,0,0,1,2.773,6.418l6.839-3.8a4.888,4.888,0,0,1,4.778,0l6.839,3.8A1.5,1.5,0,0,1,20.5,9.23Z"/>
</g>
</g>
</svg>

27
GME Remit/Supported Files/Info.plist

@ -81,33 +81,36 @@
<key>NSCalendarsUsageDescription</key>
<string></string>
<key>NSCameraUsageDescription</key>
<string>Allow "JME Remittance" to use your camera to capture Identification documents, Deposit slips</string>
<string>Allow &quot;JME Remittance&quot; to use your camera to capture Identification documents, Deposit slips</string>
<key>NSContactsUsageDescription</key>
<string>Allow "JME Remittance" to use your contacts to get users contact</string>
<string>Allow &quot;JME Remittance&quot; to use your contacts to get users contact</string>
<key>NSFaceIDUsageDescription</key>
<string>Allow "JME Remittance" to use your biometrics to simplify and secure your app usage</string>
<string>Allow &quot;JME Remittance&quot; to use your biometrics to simplify and secure your app usage</string>
<key>NSHumanReadableCopyright</key>
<string></string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Allow "JME Remittance" to use your location?
Turning on location service allows us to show you nearby JME's branches.</string>
<string>Allow &quot;JME Remittance&quot; to use your location?
Turning on location service allows us to show you nearby JME&apos;s branches.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>Allow "JME Remittance" to use your location?
Turning on location service allows us to show you nearby JME's branches.</string>
<string>Allow &quot;JME Remittance&quot; to use your location?
Turning on location service allows us to show you nearby JME&apos;s branches.</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Allow "JME Remittance" to use your location?
Turning on location service allows us to show you nearby JME's branches.</string>
<string>Allow &quot;JME Remittance&quot; to use your location?
Turning on location service allows us to show you nearby JME&apos;s branches.</string>
<key>NSMicrophoneUsageDescription</key>
<string>Allow "JME Remittance" to use your microphone for access to your recorded voice </string>
<string>Allow &quot;JME Remittance&quot; to use your microphone for access to your recorded voice </string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Allow "JME Remittance" to use your gallery to use images of documents and depositslips</string>
<string>Allow &quot;JME Remittance&quot; to use your gallery to use images of documents and depositslips</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Allow "JME Remittance" to use your gallery to use images of documents and depositslips</string>
<string>Allow &quot;JME Remittance&quot; to use your gallery to use images of documents and depositslips</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string></string>
<key>UIAppFonts</key>
<array>
<string>SanFranciscoDisplay-Heavy.otf</string>
<string>volte-bold.otf</string>
<string>volte-semibold.otf</string>
<string>volte-medium.otf</string>
</array>
<key>UIBackgroundModes</key>
<array>

BIN
GME Remit/Supported Files/Volte/volte-bold.otf

BIN
GME Remit/Supported Files/Volte/volte-bolditalic.otf

BIN
GME Remit/Supported Files/Volte/volte-light.otf

BIN
GME Remit/Supported Files/Volte/volte-lightitalic.otf

BIN
GME Remit/Supported Files/Volte/volte-medium.otf

BIN
GME Remit/Supported Files/Volte/volte-mediumitalic.otf

BIN
GME Remit/Supported Files/Volte/volte-regular.otf

BIN
GME Remit/Supported Files/Volte/volte-regularitalic.otf

BIN
GME Remit/Supported Files/Volte/volte-semibold.otf

BIN
GME Remit/Supported Files/Volte/volte-semibolditalic.otf

95
GME Remit/Utilities/CustomUI/CurrencyTextField.swift

@ -0,0 +1,95 @@
//
// CurrencyTextField.swift
// WorkingWithCurrencies
//
// Created by Josh R on 9/8/20.
// Copyright © 2020 Josh R. All rights reserved.
//
import UIKit
class CurrencyTextField: UITextField {
var currencyType: String?
var passTextFieldText: ((String) -> Void)?
var keyBoardType: UIKeyboardType = .default
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
//If using in SBs
setup()
}
private func setup() {
self.keyboardType = keyBoardType
self.contentScaleFactor = 0.5
delegate = self
self.addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
}
//AFTER entered string is registered in the textField
@objc private func textFieldDidChange() {
updateTextField()
}
//Placed in separate method so when the user selects an account with a different currency, it will immediately be reflected
private func updateTextField() {
var cleanedAmount = ""
for character in self.text ?? "" {
if character.isNumber {
cleanedAmount.append(character)
}
}
self.text = getCommaLike3DigitMoneytext(cleanedAmount)
passTextFieldText?(self.text!)
}
func getCommaLike3DigitMoneytext( _ amount: String) -> String {
var numberOfArrayOfString: [Character] = []
var numbero3DigitsString: [String] = []
let textArray = Array(amount)
for (i, value) in textArray.enumerated() {
if let lastElement = textArray.elementAt(index:( textArray.count - 1) - i) {
numberOfArrayOfString.append(lastElement)
}
}
var concanetedText = ""
for (i, value) in numberOfArrayOfString.enumerated() {
let currentIndex = (textArray.count - 1) - i
if(currentIndex % 3 != 0) {
if let text = numberOfArrayOfString.elementAt(index: currentIndex) {
concanetedText = concanetedText + String(text)
}
} else {
if let text = numberOfArrayOfString.elementAt(index: currentIndex) {
concanetedText = concanetedText + String(text)
numbero3DigitsString.append(concanetedText)
concanetedText = ""
}
}
}
return numbero3DigitsString.joined(separator: ",")
}
}
extension CurrencyTextField: UITextFieldDelegate {
func textFieldDidEndEditing(_ textField: UITextField) {
let parsedText = textField.text?.replacingOccurrences(of: currencyType ?? "", with: "") ?? ""
textField.text = parsedText + (currencyType ?? "")
}
func textFieldDidBeginEditing(_ textField: UITextField) {
let parsedText = textField.text?.replacingOccurrences(of: currencyType ?? "", with: "") ?? ""
textField.text = parsedText
}
}

130
GME Remit/Utilities/CustomUI/CustomPageControl.swift

@ -0,0 +1,130 @@
//
import Foundation
import UIKit
@IBDesignable
class CustomPageControl: UIControl {
//MARK:- Properties
private var numberOfDots = [UIView]() {
didSet{
if numberOfDots.count == numberOfPages {
setupViews()
}
}
}
@IBInspectable var numberOfPages: Int = 0 {
didSet{
for tag in 0 ..< numberOfPages {
let dot = getDotView()
dot.tag = tag
dot.backgroundColor = pageIndicatorTintColor
self.numberOfDots.append(dot)
}
}
}
var currentPage: Int = 0 {
didSet{
onPageControlSwipe()
}
}
@IBInspectable var pageIndicatorTintColor: UIColor? = .blue
@IBInspectable var currentPageIndicatorTintColor: UIColor? = .green
private lazy var stackView = UIStackView.init(frame: self.bounds)
private lazy var constantSpace = ((stackView.spacing) * CGFloat(numberOfPages - 1) + ((self.bounds.height * 0.45) * CGFloat(numberOfPages)) - self.bounds.width)
override var bounds: CGRect {
didSet{
self.numberOfDots.forEach { (dot) in
self.setupDotAppearance(dot: dot)
}
}
}
//MARK:- Intialisers
convenience init() {
self.init(frame: .zero)
}
init(withNoOfPages pages: Int) {
self.numberOfPages = pages
self.currentPage = 0
super.init(frame: .zero)
setupViews()
}
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
private func setupViews() {
self.numberOfDots.forEach { (dot) in
self.stackView.addArrangedSubview(dot)
}
stackView.alignment = .center
stackView.axis = .horizontal
stackView.distribution = .fillEqually
stackView.spacing = 8
stackView.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(stackView)
self.addConstraints([
stackView.centerXAnchor.constraint(equalTo: self.centerXAnchor),
stackView.centerYAnchor.constraint(equalTo: self.centerYAnchor),
stackView.heightAnchor.constraint(equalTo: self.heightAnchor),
])
self.numberOfDots.forEach { dot in
self.addConstraints([
dot.centerYAnchor.constraint(equalTo: self.stackView.centerYAnchor),
dot.widthAnchor.constraint(equalToConstant: 7),
dot.heightAnchor.constraint(equalToConstant: 7),
])
}
self.numberOfDots.forEach { dot in
dot.layer.cornerRadius = dot.bounds.height / 2
}
}
@objc private func onPageControlSwipe() {
_ = numberOfDots.map { (dot) in
setupDotAppearance(dot: dot)
if dot.tag == currentPage {
UIView.animate(withDuration: 0.2, animations: {
dot.layer.cornerRadius = dot.bounds.height / 5
dot.transform = CGAffineTransform.init(scaleX: 2, y: 1)
dot.backgroundColor = self.currentPageIndicatorTintColor
})
}
}
}
//MARK: Helper methods...
private func getDotView() -> UIView {
let dot = UIView()
self.setupDotAppearance(dot: dot)
dot.translatesAutoresizingMaskIntoConstraints = false
return dot
}
private func setupDotAppearance(dot: UIView) {
dot.transform = .identity
dot.layer.cornerRadius = dot.bounds.height / 2
dot.layer.masksToBounds = true
dot.backgroundColor = pageIndicatorTintColor
}
}

172
GME Remit/Utilities/ExchangeRateCustomView.swift

@ -0,0 +1,172 @@
//
import UIKit
class ExchangeRateCustomView: UIView {
var passTextFieldText: ((String) -> Void)?
var didSelectCountry: (() -> ())?
var isReciver: Bool = false
var text: String?
var countryListTapGuesture: UITapGestureRecognizer?
var updatedText: String? {
didSet {
updateText()
}
}
var currency: String? {
didSet {
updateCurrency()
}
}
var flag: UIImage? {
didSet {
updateFlag()
}
}
var title: String? {
didSet {
titleLabel.text = title
}
}
private var textfield: CurrencyTextField = {
let textfield = CurrencyTextField()
textfield.tintColor = .theme2E89FF
textfield.textColor = .init(hex: "#2E89FF").withAlphaComponent(0.87)
textfield.font = .sanfrancisco(.semibold, size: 16)
textfield.translatesAutoresizingMaskIntoConstraints = false
return textfield
}()
private var titleLabel: UILabel = {
let label = UILabel()
label.font = .sanfrancisco(.semibold, size: 12)
label.textColor = .themeGray1
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
var currencyText: UILabel = {
let text = UILabel()
text.translatesAutoresizingMaskIntoConstraints = false
return text
}()
var flagImageView: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.heightAnchor.constraint(equalToConstant: 40).isActive = true
imageView.widthAnchor.constraint(equalToConstant: 40).isActive = true
return imageView
}()
private var leftStackView: UIStackView!
private var rightStackView: UIStackView!
init(isReciver: Bool) {
super.init(frame: .zero)
self.isReciver = isReciver
setup()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setup() {
uiSetup()
propertiesSetup()
}
private func uiSetup() {
leftStackView = UIStackView(arrangedSubviews: [titleLabel, textfield])
leftStackView.translatesAutoresizingMaskIntoConstraints = false
leftStackView.axis = .vertical
leftStackView.distribution = .fill
leftStackView.spacing = 4
rightStackView = UIStackView(arrangedSubviews: [currencyText,
flagImageView])
rightStackView.translatesAutoresizingMaskIntoConstraints = false
rightStackView.axis = .horizontal
rightStackView.distribution = .fillEqually
rightStackView.spacing = 8
self.addSubviews(leftStackView,
rightStackView
)
leftStackView.anchor(top: self.topAnchor,
paddingTop: isReciver ? 16 : 10,
bottom: self.bottomAnchor,
paddingBottom: -13,
left: self.leadingAnchor,
paddingLeft: 16
)
textfield.passTextFieldText = { [weak self] text in
self?.text = text
self?.passTextFieldText?(text)
}
rightStackView.anchor(right: self.trailingAnchor,
paddingRight: -8
)
rightStackView.center(centerX: nil,
paddingX: 0,
centerY: self.centerYAnchor,
paddingY: 0)
rightStackView.leadingAnchor.constraint(greaterThanOrEqualTo: leftStackView.trailingAnchor, constant: 8).isActive = true
let tap = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))
leftStackView.addGestureRecognizer(tap)
}
private func propertiesSetup() {
flagImageView.image = UIImage(named: "flag_japan")
currencyText.text = "JPY"
currencyText.textColor = .themeBlack
currencyText.font = .sanfrancisco(.semibold, size: 16)
titleLabel.textColor = .themeBlack.withAlphaComponent(0.6)
titleLabel.font = .sanfrancisco(.semibold, size: 14)
if(isReciver) {
countryListTapGuesture = UITapGestureRecognizer(target: self, action: #selector(showCurrencyCountryPickerview))
rightStackView.addGestureRecognizer(countryListTapGuesture ?? UITapGestureRecognizer())
} else {
countryListTapGuesture = nil
}
}
@objc func handleTap(_ sender: UITapGestureRecognizer? = nil) {
textfield.becomeFirstResponder()
}
@objc private func showCurrencyCountryPickerview() {
didSelectCountry?()
}
private func updateText() {
textfield.text = updatedText
}
private func updateCurrency() {
currencyText.text = currency
}
private func updateFlag() {
flagImageView.image = flag
}
}

6
GME Remit/Utilities/TabBar Helper/CustomItemTabView.swift

@ -57,13 +57,13 @@ final class CustomItemTabView: UIView {
containerView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
containerView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
containerView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
containerView.heightAnchor.constraint(equalToConstant: 80).isActive = true
containerView.heightAnchor.constraint(equalToConstant: 42).isActive = true
iconImageView.centerXAnchor.constraint(equalTo: containerView.centerXAnchor).isActive = true
iconImageView.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true
iconImageView.heightAnchor.constraint(equalToConstant: 40).isActive = true
iconImageView.heightAnchor.constraint(equalToConstant: 24).isActive = true
underlineView.leadingAnchor.constraint(equalTo: self.iconImageView.leadingAnchor).isActive = true
underlineView.trailingAnchor.constraint(equalTo: self.iconImageView.trailingAnchor).isActive = true
@ -72,7 +72,7 @@ final class CustomItemTabView: UIView {
}
private func setupProperties() {
underlineView.backgroundColor = .blue
underlineView.backgroundColor = .darkBlue
underlineView.set(cornerRadius: 2)
iconImageView.image = isSelected ? item.selectedIcon : item.icon

3
GME Remit/Utilities/TabBar Helper/CustomTabBar.swift

@ -29,7 +29,6 @@ final class CustomTabBar: UIStackView {
setupHierarchy()
setupProperties()
bind()
setNeedsLayout()
layoutIfNeeded()
selectItem(index: 0)
@ -48,7 +47,7 @@ final class CustomTabBar: UIStackView {
alignment = .top
backgroundColor = .themeWhite
setupCornerRadius(30)
setupCornerRadius(20)
customItemViews.forEach {
$0.translatesAutoresizingMaskIntoConstraints = false

8
GME Remit/Utilities/TabBar Helper/CustomTabItem.swift

@ -45,9 +45,9 @@ extension CustomTabItem {
var icon: UIImage? {
switch self {
case .home:
return UIImage(named: "home_new")?.withRenderingMode(.alwaysOriginal)
return UIImage(named: "tab-home")?.withRenderingMode(.alwaysOriginal)
case .sendMoney:
return UIImage(systemName: "heart.circle")?.withRenderingMode(.alwaysOriginal)
return UIImage(named: "tab-contact")?.withRenderingMode(.alwaysOriginal)
case .profile:
return UIImage(systemName: "person.crop.circle")?.withRenderingMode(.alwaysOriginal)
}
@ -56,9 +56,9 @@ extension CustomTabItem {
var selectedIcon: UIImage? {
switch self {
case .home:
return UIImage(named: "home_selected")?.withRenderingMode(.alwaysOriginal)
return UIImage(named: "tab-home-selected")?.withRenderingMode(.alwaysOriginal)
case .sendMoney:
return UIImage(systemName: "heart.circle.fill")?.withRenderingMode(.alwaysOriginal)
return UIImage(named: "tab-contact-selected")?.withRenderingMode(.alwaysOriginal)
case .profile:
return UIImage(systemName: "person.crop.circle.fill")?.withRenderingMode(.alwaysOriginal)
}

Loading…
Cancel
Save