From 8d13a9373fccd4fed19d9c2cca5d9c66c73d1fe2 Mon Sep 17 00:00:00 2001 From: zjx Date: Wed, 4 Jun 2025 17:20:33 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=8D=E9=A6=88=EF=BC=8C=E6=B4=BB=E5=8A=A8?= =?UTF-8?q?=EF=BC=8CH5=E4=BA=A4=E4=BA=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Podfile | 1 + Podfile.lock | 8 +- Veloria.xcodeproj/project.pbxproj | 18 ++++ Veloria/Base/Extension/UIColor+VPAdd.swift | 2 +- .../Base/Networking/API/VPRewardsAPI.swift | 25 +++++ Veloria/Base/WebView/VPWebScriptModel.swift | 25 +++++ .../WebView/VPWebViewController+Script.swift | 93 +++++++++++++++++- .../Controller/VPFeedbackViewController.swift | 28 ++++++ .../Me/Controller/VPMeViewController.swift | 6 +- Veloria/Class/Me/View/VPMeFooterView.swift | 3 +- Veloria/Class/Me/View/VPMeUserInfoCell.swift | 3 +- Veloria/Libs/Login/VPLoginManager.swift | 5 + .../feed_back_icon_01.imageset/Contents.json | 25 +++++ .../feed_back_icon_01.imageset/Vector@2x.png | Bin 0 -> 479 bytes .../feed_back_icon_01.imageset/Vector@3x.png | Bin 0 -> 617 bytes 15 files changed, 234 insertions(+), 8 deletions(-) create mode 100644 Veloria/Base/Networking/API/VPRewardsAPI.swift create mode 100644 Veloria/Base/WebView/VPWebScriptModel.swift create mode 100644 Veloria/Class/Me/Controller/VPFeedbackViewController.swift create mode 100644 Veloria/Source/Assets.xcassets/icon/feed_back_icon_01.imageset/Contents.json create mode 100644 Veloria/Source/Assets.xcassets/icon/feed_back_icon_01.imageset/Vector@2x.png create mode 100644 Veloria/Source/Assets.xcassets/icon/feed_back_icon_01.imageset/Vector@3x.png diff --git a/Podfile b/Podfile index 0e96da5..9c77f8a 100644 --- a/Podfile +++ b/Podfile @@ -29,6 +29,7 @@ target 'Veloria' do pod 'WMZPageController' #分页控制器 pod 'ZFPlayer/AVPlayer' #播放器 pod 'EmptyDataSet-Swift' #空数据页面 + pod 'ZLPhotoBrowser' #相册 end diff --git a/Podfile.lock b/Podfile.lock index 8344377..7a544a9 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -26,6 +26,9 @@ PODS: - ZFPlayer/AVPlayer (4.1.4): - ZFPlayer/Core - ZFPlayer/Core (4.1.4) + - ZLPhotoBrowser (4.6.0.1): + - ZLPhotoBrowser/Core (= 4.6.0.1) + - ZLPhotoBrowser/Core (4.6.0.1) DEPENDENCIES: - EmptyDataSet-Swift @@ -41,6 +44,7 @@ DEPENDENCIES: - WMZPageController - YYKit - ZFPlayer/AVPlayer + - ZLPhotoBrowser SPEC REPOS: trunk: @@ -59,6 +63,7 @@ SPEC REPOS: - WMZPageController - YYKit - ZFPlayer + - ZLPhotoBrowser SPEC CHECKSUMS: Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496 @@ -76,7 +81,8 @@ SPEC CHECKSUMS: WMZPageController: 87dd82d1e3528cd362de19b9a74fd6890d6e1906 YYKit: 7cda43304a8dc3696c449041e2cb3107b4e236e7 ZFPlayer: 5cf39e8d9f0c2394a014b0db4767b5b5a6bffe13 + ZLPhotoBrowser: 20f32e6429448cc1c008795a1b55472d5772939c -PODFILE CHECKSUM: e2712ae0c35ebb37af30822c851f06195b8f41d7 +PODFILE CHECKSUM: 4ec05325e0f82746c022a9c8ea6b1af5d1e5092f COCOAPODS: 1.16.2 diff --git a/Veloria.xcodeproj/project.pbxproj b/Veloria.xcodeproj/project.pbxproj index 7e264d8..12f7732 100644 --- a/Veloria.xcodeproj/project.pbxproj +++ b/Veloria.xcodeproj/project.pbxproj @@ -191,6 +191,9 @@ BFF5B2372DF013410044227A /* VPAlertWindowManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B2362DF013410044227A /* VPAlertWindowManager.swift */; }; BFF5B2392DF014520044227A /* VPBaseAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B2382DF014520044227A /* VPBaseAlertView.swift */; }; BFF5B23B2DF018900044227A /* VPAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B23A2DF018900044227A /* VPAlertView.swift */; }; + BFF5B23D2DF034420044227A /* VPFeedbackViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B23C2DF034420044227A /* VPFeedbackViewController.swift */; }; + BFF5B23F2DF0443B0044227A /* VPWebScriptModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B23E2DF0443B0044227A /* VPWebScriptModel.swift */; }; + BFF5B2412DF045BF0044227A /* VPRewardsAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B2402DF045BF0044227A /* VPRewardsAPI.swift */; }; F939C04AD4003BA127F15C28 /* Pods_Veloria.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34F57E87E765BF8D72A43DCA /* Pods_Veloria.framework */; }; /* End PBXBuildFile section */ @@ -389,6 +392,9 @@ BFF5B2362DF013410044227A /* VPAlertWindowManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPAlertWindowManager.swift; sourceTree = ""; }; BFF5B2382DF014520044227A /* VPBaseAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPBaseAlertView.swift; sourceTree = ""; }; BFF5B23A2DF018900044227A /* VPAlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPAlertView.swift; sourceTree = ""; }; + BFF5B23C2DF034420044227A /* VPFeedbackViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPFeedbackViewController.swift; sourceTree = ""; }; + BFF5B23E2DF0443B0044227A /* VPWebScriptModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPWebScriptModel.swift; sourceTree = ""; }; + BFF5B2402DF045BF0044227A /* VPRewardsAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPRewardsAPI.swift; sourceTree = ""; }; E0BDA3570E00C90877E45AA0 /* Pods-VideoPlayer.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-VideoPlayer.debug.xcconfig"; path = "Target Support Files/Pods-VideoPlayer/Pods-VideoPlayer.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -713,6 +719,7 @@ BF0FA6F82DDC64E700C9E5F2 /* VPHomeAPI.swift */, BF0FA73C2DDED2D000C9E5F2 /* VPVideoAPI.swift */, BF0FA7C22DE45DE300C9E5F2 /* VPUserAPI.swift */, + BFF5B2402DF045BF0044227A /* VPRewardsAPI.swift */, ); path = API; sourceTree = ""; @@ -943,6 +950,7 @@ BF0FA7AE2DE443E000C9E5F2 /* VPMeViewController.swift */, BF5E75AE2DE4632200DE9DFE /* VPAboutUsViewController.swift */, BFF5B22B2DEFE8A80044227A /* VPDeleteAccountViewController.swift */, + BFF5B23C2DF034420044227A /* VPFeedbackViewController.swift */, ); path = Controller; sourceTree = ""; @@ -983,6 +991,7 @@ BF0FA7B72DE44FCC00C9E5F2 /* VPWebViewController.swift */, BF5E75B02DE4656600DE9DFE /* VPCampaignWebViewController.swift */, BFF5B21B2DEEDE130044227A /* VPWebViewController+Script.swift */, + BFF5B23E2DF0443B0044227A /* VPWebScriptModel.swift */, ); path = WebView; sourceTree = ""; @@ -1310,6 +1319,7 @@ BF5E75CD2DE5692D00DE9DFE /* JXTransitionDelegateBridge.swift in Sources */, BF5E75CE2DE5692D00DE9DFE /* JXPushAnimatedTransition.swift in Sources */, BF5E75CF2DE5692D00DE9DFE /* UIViewController+JXTransition.swift in Sources */, + BFF5B23F2DF0443B0044227A /* VPWebScriptModel.swift in Sources */, BFF5B23B2DF018900044227A /* VPAlertView.swift in Sources */, BF5E75D02DE5692D00DE9DFE /* UIGestureRecognizer+JXTransition.swift in Sources */, BFF5AFA62DE700420044227A /* VPMeVipPrivilegeItemView.swift in Sources */, @@ -1392,6 +1402,7 @@ BF0FA7892DE161F200C9E5F2 /* VPSearchResultView.swift in Sources */, 1B056E792DDB365A007EE38D /* VPTabBarItemSelectedView.swift in Sources */, 1B056E722DDB022F007EE38D /* VPTabBarItem.swift in Sources */, + BFF5B23D2DF034420044227A /* VPFeedbackViewController.swift in Sources */, BFF5B2392DF014520044227A /* VPBaseAlertView.swift in Sources */, BFF5AFCC2DE98C7F0044227A /* VPOrderRecordsViewController.swift in Sources */, 1B056E412DDAC30A007EE38D /* VPModel.swift in Sources */, @@ -1420,6 +1431,7 @@ 1B056E492DDAC3DF007EE38D /* VPAppTool.swift in Sources */, BFF5AFE62DEEDB7F0044227A /* VPRewardsViewController.swift in Sources */, BF0FA74E2DDF067E00C9E5F2 /* VPVideoPlayViewModel.swift in Sources */, + BFF5B2412DF045BF0044227A /* VPRewardsAPI.swift in Sources */, BF0FA75B2DDF206000C9E5F2 /* VPExplorePlayerCell.swift in Sources */, BF0FA7412DDEFBC700C9E5F2 /* UIScrollView+VPRefresh.swift in Sources */, BF0FA70C2DDC6A3800C9E5F2 /* VPHomeBannerContentCell.swift in Sources */, @@ -1463,6 +1475,9 @@ DEVELOPMENT_TEAM = 394VH538M8; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = Veloria/Source/Info.plist; + INFOPLIST_KEY_NSCameraUsageDescription = "The APP needs to access your album to provide screenshots for feedback."; + INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "The APP needs to access your location to recommend better short dramas for you"; + INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "The APP needs to access your album to provide screenshots for feedback."; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UIMainStoryboardFile = ""; @@ -1501,6 +1516,9 @@ DEVELOPMENT_TEAM = 394VH538M8; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = Veloria/Source/Info.plist; + INFOPLIST_KEY_NSCameraUsageDescription = "The APP needs to access your album to provide screenshots for feedback."; + INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "The APP needs to access your location to recommend better short dramas for you"; + INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "The APP needs to access your album to provide screenshots for feedback."; INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen; INFOPLIST_KEY_UIMainStoryboardFile = ""; diff --git a/Veloria/Base/Extension/UIColor+VPAdd.swift b/Veloria/Base/Extension/UIColor+VPAdd.swift index f47b02a..55d32c8 100644 --- a/Veloria/Base/Extension/UIColor+VPAdd.swift +++ b/Veloria/Base/Extension/UIColor+VPAdd.swift @@ -9,7 +9,7 @@ import UIKit extension UIColor { static func backgroundColor() -> UIColor { - return color000000() + return color080B16() } static func placeholderColor() -> UIColor { diff --git a/Veloria/Base/Networking/API/VPRewardsAPI.swift b/Veloria/Base/Networking/API/VPRewardsAPI.swift new file mode 100644 index 0000000..4303a49 --- /dev/null +++ b/Veloria/Base/Networking/API/VPRewardsAPI.swift @@ -0,0 +1,25 @@ +// +// VPRewardsAPI.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/4. +// + +import UIKit + +class VPRewardsAPI: NSObject { + + ///开启通知领金币 + static func requestUploadOpenNotify(completer: ((_ finish: Bool) -> Void)?) { + + let param = VPNetworkParameters(path: "/openNotify") + + VPNetwork.request(parameters: param) { (response: VPNetworkResponse) in + if response.code == VPNetworkCodeSucceed { + completer?(true) + } else { + completer?(false) + } + } + } +} diff --git a/Veloria/Base/WebView/VPWebScriptModel.swift b/Veloria/Base/WebView/VPWebScriptModel.swift new file mode 100644 index 0000000..75af362 --- /dev/null +++ b/Veloria/Base/WebView/VPWebScriptModel.swift @@ -0,0 +1,25 @@ +// +// VPWebScriptModel.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/4. +// + +import UIKit +import SmartCodable + +class VPWebScriptModel: VPModel, SmartCodable { + + + var type: String? + + var data: VPWebScriptData? +} + +struct VPWebScriptData: SmartCodable { + + var activity_id: String? + var short_play_id: String? + var link: String? + +} diff --git a/Veloria/Base/WebView/VPWebViewController+Script.swift b/Veloria/Base/WebView/VPWebViewController+Script.swift index 3c977e2..2de958b 100644 --- a/Veloria/Base/WebView/VPWebViewController+Script.swift +++ b/Veloria/Base/WebView/VPWebViewController+Script.swift @@ -7,6 +7,7 @@ import UIKit import WebKit +import ZLPhotoBrowser typealias VPWebViewMessageName = String @@ -25,8 +26,98 @@ extension VPWebViewController { let name = message.name let body = message.body - + switch name { + case VPWebMessageOpenFeedbackList: + let vc = VPCampaignWebViewController() + vc.bgImageView.isHidden = true + vc.urlStr = kVPFeedBackListWebUrl + self.navigationController?.pushViewController(vc, animated: true) + + case VPWebMessageOpenFeedbackDetail: + let vc = VPCampaignWebViewController() + vc.bgImageView.isHidden = true + vc.urlStr = kVPFeedBackDetailWebUrl + self.navigationController?.pushViewController(vc, animated: true) + + case VPWebMessageOpenPhotoPicker: + openPhotoPicker() + + case VPWebMessageAPP: + guard let body = message.body as? [String : Any] else { return } + guard let model = VPWebScriptModel.deserialize(from: body) else { return } + let type = model.type + let data = model.data + + if type == "login" { + VPLoginManager.manager.openLogin() + + } else if type == "open_notify" { + openNotify() + + } else if type == "watch_video" { + let vc = VPDetailPlayerViewController() + vc.shortPlayId = data?.short_play_id + vc.activityId = data?.activity_id + self.navigationController?.pushViewController(vc, animated: true) + } else { + + guard let urlStr = data?.link else { return } + guard let url = URL(string: urlStr) else { return } + if UIApplication.shared.canOpenURL(url) { + UIApplication.shared.open(url) + } + } + + + default: + break + } } } + +extension VPWebViewController { + + ///打开相册 + private func openPhotoPicker() { + + ZLPhotoConfiguration.default().allowSelectOriginal = false + ZLPhotoConfiguration.default().maxSelectCount = 1 + ZLPhotoConfiguration.default().allowEditImage = false + ZLPhotoConfiguration.default().allowSelectVideo = false + ZLPhotoConfiguration.default().allowSelectGif = false + ZLPhotoConfiguration.default().allowTakePhotoInLibrary = false + + let picker = ZLPhotoPicker() + picker.selectImageBlock = { [weak self] (results, _) in + guard let self = self else { return } + guard let image = results.first?.image else { return } + guard let imageData = image.jpegData(compressionQuality: 0.8) else { return } + let imageDataStr = imageData.base64EncodedString(options: .endLineWithCarriageReturn) + + let js = "uploadConvertImage('\(imageDataStr)')" + self.webView.evaluateJavaScript(js) + } + + picker.showPhotoLibrary(sender: self) + } + + ///打开通知 + private func openNotify() { + UNUserNotificationCenter.current().getNotificationSettings { settings in + DispatchQueue.main.async { [weak self] in + guard let self = self else { return } + if settings.authorizationStatus != .authorized { + VPAppTool.openApnsSetting() + } else { + VPRewardsAPI.requestUploadOpenNotify { [weak self] finish in + if finish { + self?.reload() + } + } + } + } + } + } +} diff --git a/Veloria/Class/Me/Controller/VPFeedbackViewController.swift b/Veloria/Class/Me/Controller/VPFeedbackViewController.swift new file mode 100644 index 0000000..42ae1ce --- /dev/null +++ b/Veloria/Class/Me/Controller/VPFeedbackViewController.swift @@ -0,0 +1,28 @@ +// +// VPFeedbackViewController.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/4. +// + +import UIKit + +class VPFeedbackViewController: VPCampaignWebViewController { + + override func viewDidLoad() { + self.urlStr = kVPFeedBackHomeWebUrl + super.viewDidLoad() + self.bgImageView.isHidden = true + + self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "feed_back_icon_01"), style: .plain, target: self, action: #selector(handleRightButton)) + } + + + @objc private func handleRightButton() { + let vc = VPCampaignWebViewController() + vc.urlStr = kVPFeedBackListWebUrl + vc.bgImageView.isHidden = true + self.navigationController?.pushViewController(vc, animated: true) + } + +} diff --git a/Veloria/Class/Me/Controller/VPMeViewController.swift b/Veloria/Class/Me/Controller/VPMeViewController.swift index 297f819..f16152c 100644 --- a/Veloria/Class/Me/Controller/VPMeViewController.swift +++ b/Veloria/Class/Me/Controller/VPMeViewController.swift @@ -162,6 +162,10 @@ extension VPMeViewController: UITableViewDelegate, UITableViewDataSource { let vc = VPDeleteAccountViewController() self.navigationController?.pushViewController(vc, animated: true) + case .feedback: + let vc = VPFeedbackViewController() + self.navigationController?.pushViewController(vc, animated: true) + default: break } @@ -201,7 +205,7 @@ extension VPMeViewController { cellArr.append(VPMeItem(icon: UIImage(named: "me_item_icon_05"), title: "Language".localized, type: .language, cellKey: .normal)) cellArr.append(VPMeItem(icon: UIImage(named: "me_item_icon_01"), title: "Privacy Policy".localized, type: .privacyPolicy, cellKey: .normal)) cellArr.append(VPMeItem(icon: UIImage(named: "me_item_icon_02"), title: "User Agreement".localized, type: .userAgreement, cellKey: .normal)) -// cellArr.append(VPMeItem(icon: UIImage(named: "me_item_icon_04"), title: "Help Center".localized, type: .feedback, cellKey: .normal)) + cellArr.append(VPMeItem(icon: UIImage(named: "me_item_icon_04"), title: "Help Center".localized, type: .feedback, cellKey: .normal)) cellArr.append(VPMeItem(icon: UIImage(named: "me_item_icon_03"), title: "About Us".localized, type: .aboutUs, cellKey: .normal)) if VPLoginManager.manager.userInfo?.is_tourist == false { diff --git a/Veloria/Class/Me/View/VPMeFooterView.swift b/Veloria/Class/Me/View/VPMeFooterView.swift index 31d2b1e..f6be4a3 100644 --- a/Veloria/Class/Me/View/VPMeFooterView.swift +++ b/Veloria/Class/Me/View/VPMeFooterView.swift @@ -51,8 +51,7 @@ class VPMeFooterView: UIView { @objc private func handleButton() { if userInfo?.is_tourist == true { - let view = VPLoginContentView() - view.present(in: nil) + VPLoginManager.manager.openLogin() } else { let alert = VPAlertView(title: "kLogoutAlertTitle".localized, subtitle: "kLogoutAlertText".localized, icon: UIImage(named: "alert_icon_02"), normalButtonText: "Log Out".localized, highlightButtonText: "Cancel".localized).show() alert.clickNormalButton = { diff --git a/Veloria/Class/Me/View/VPMeUserInfoCell.swift b/Veloria/Class/Me/View/VPMeUserInfoCell.swift index 71ba3ec..fba0641 100644 --- a/Veloria/Class/Me/View/VPMeUserInfoCell.swift +++ b/Veloria/Class/Me/View/VPMeUserInfoCell.swift @@ -83,8 +83,7 @@ class VPMeUserInfoCell: VPTableViewCell { } @objc private func handleLoginButton() { - let view = VPLoginContentView() - view.present(in: nil) + VPLoginManager.manager.openLogin() } } diff --git a/Veloria/Libs/Login/VPLoginManager.swift b/Veloria/Libs/Login/VPLoginManager.swift index 3d583d2..83b6e83 100644 --- a/Veloria/Libs/Login/VPLoginManager.swift +++ b/Veloria/Libs/Login/VPLoginManager.swift @@ -38,6 +38,11 @@ class VPLoginManager: NSObject { UserDefaults.vp_setObject(token, forKey: kVPLoginTokenDefaultsKey) } + func openLogin() { + let view = VPLoginContentView() + view.present(in: nil) + } + func login(type: LoginType, presentingViewController: UIViewController?, completer: ((_ isFinish: Bool) -> Void)?) { switch type { diff --git a/Veloria/Source/Assets.xcassets/icon/feed_back_icon_01.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/feed_back_icon_01.imageset/Contents.json new file mode 100644 index 0000000..7445735 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/feed_back_icon_01.imageset/Contents.json @@ -0,0 +1,25 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Vector@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Vector@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "original" + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/feed_back_icon_01.imageset/Vector@2x.png b/Veloria/Source/Assets.xcassets/icon/feed_back_icon_01.imageset/Vector@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..32f77e439941682132359cd4d0f9ba473e1cf2f0 GIT binary patch literal 479 zcmV<50U-W~P)4s9r|yXtjeCNlf#ovLDhM9#Q!1}ZQAmce=l)`+x{Gd#LX$~4Q->Q z{Rr%7+m`PQRTHPBz2T7I)KT_f$Mdl6cwX@Nwl&Waelt4OR!CaS6vIe3fn?eN9%yGM z$8gHZywK8q$G5%3T&|940x5Q0*MJY9{m=-4G=d-v5mcwN!8DjopR^rL3y@(XZ1elm z((z|*3nZUo68ha$7Uerz5q^?VEyQHD^-m_yI95 VpS|mWQ&a!|002ovPDHLkV1h%3%EABu literal 0 HcmV?d00001 diff --git a/Veloria/Source/Assets.xcassets/icon/feed_back_icon_01.imageset/Vector@3x.png b/Veloria/Source/Assets.xcassets/icon/feed_back_icon_01.imageset/Vector@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..01eb04431565594273b478f915e823d16ffc80da GIT binary patch literal 617 zcmeAS@N?(olHy`uVBq!ia0vp^W+2SL1|)l2v+e>Z&H|6fVg?393lL^>oo1K-6l5$8 za(7}_cTVOdki(Mh=jjugS~f6BPw)x2 zv0!dP9)nMSq2q4G)TSlE48m7@9Lx;Ldsix%UzlOBO8?X3b%8PFyW;0h{(Q8-G22#I zyCgy+#rTi-ua80PXPIR@OaAt+5wNSAq>_65oX(rxzUv(GC$&6{wcc!yyY=i(B@27w zO=%ojLS?P%wj3$$VoG%2uL5mDBT@o*K99kmS>Z!~%*-b>P*L(W8DT)3s z3jC)nvX72xTVp8Tcc?@4Rp})D9mgh3+TqUAkgbvS;j{?zL#;QWbsuZ@GW#v`NZh>O zLuLDX%Vkcpk|i$94E__iZN-W8r{3u-eOA~tH%}z|_!k-PlVK`(@yexqu8bd&pCqrD zc|7D&hvugHS_flJ)@9B~KX)i&hIq-01@`B*SHD_+>sEjF&38MMmWOaxC@q=tO014k zZE4Vl(_+jIt&YD7=)cAL>$7EugwZ;n65Z@%M`3SfRDW#bu#S@7wBc0NX#uuVR{m#q zH=DiLn;@$Ht!tXmw0_Z|{1g59r?-cC&+q)W^JJTOXX=;Q#INBg{wXnE*B03QINP^3 z>HY-U#or8__fFK=`sQvm)8GmHO)FF0w$6Oz&v)~Y*OlD? zqVr|)zTZhOv-