diff --git a/Veloria.xcodeproj/project.pbxproj b/Veloria.xcodeproj/project.pbxproj index aadeadd..7e264d8 100644 --- a/Veloria.xcodeproj/project.pbxproj +++ b/Veloria.xcodeproj/project.pbxproj @@ -178,6 +178,19 @@ BFF5AFE22DEED2960044227A /* VPPlayerCoinBuyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5AFE12DEED2960044227A /* VPPlayerCoinBuyView.swift */; }; BFF5AFE62DEEDB7F0044227A /* VPRewardsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5AFE52DEEDB7F0044227A /* VPRewardsViewController.swift */; }; BFF5B21C2DEEDE130044227A /* VPWebViewController+Script.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B21B2DEEDE130044227A /* VPWebViewController+Script.swift */; }; + BFF5B2202DEEE2C50044227A /* VPLoginContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B21F2DEEE2C50044227A /* VPLoginContentView.swift */; }; + BFF5B2232DEEF8DA0044227A /* VPLoginButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B2222DEEF8DA0044227A /* VPLoginButton.swift */; }; + BFF5B2252DEF02080044227A /* VPLoginManager+Apple.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B2242DEF02080044227A /* VPLoginManager+Apple.swift */; }; + BFF5B2272DEF022F0044227A /* VPThirdSignModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B2262DEF022F0044227A /* VPThirdSignModel.swift */; }; + BFF5B22A2DEFDDF10044227A /* VPMeFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B2292DEFDDF10044227A /* VPMeFooterView.swift */; }; + BFF5B22C2DEFE8A80044227A /* VPDeleteAccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B22B2DEFE8A80044227A /* VPDeleteAccountViewController.swift */; }; + BFF5B22E2DEFEEAF0044227A /* VPDeleteAccountContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B22D2DEFEEAF0044227A /* VPDeleteAccountContentView.swift */; }; + BFF5B2302DEFEF0C0044227A /* VPDeleteAccountNormalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B22F2DEFEF0C0044227A /* VPDeleteAccountNormalView.swift */; }; + BFF5B2322DEFF1220044227A /* VPDeleteAccountDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B2312DEFF1220044227A /* VPDeleteAccountDetailView.swift */; }; + BFF5B2342DEFF2030044227A /* VPDeleteAccountTipView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFF5B2332DEFF2030044227A /* VPDeleteAccountTipView.swift */; }; + 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 */; }; F939C04AD4003BA127F15C28 /* Pods_Veloria.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 34F57E87E765BF8D72A43DCA /* Pods_Veloria.framework */; }; /* End PBXBuildFile section */ @@ -362,6 +375,20 @@ BFF5AFE12DEED2960044227A /* VPPlayerCoinBuyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPPlayerCoinBuyView.swift; sourceTree = ""; }; BFF5AFE52DEEDB7F0044227A /* VPRewardsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPRewardsViewController.swift; sourceTree = ""; }; BFF5B21B2DEEDE130044227A /* VPWebViewController+Script.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VPWebViewController+Script.swift"; sourceTree = ""; }; + BFF5B21F2DEEE2C50044227A /* VPLoginContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPLoginContentView.swift; sourceTree = ""; }; + BFF5B2222DEEF8DA0044227A /* VPLoginButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPLoginButton.swift; sourceTree = ""; }; + BFF5B2242DEF02080044227A /* VPLoginManager+Apple.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VPLoginManager+Apple.swift"; sourceTree = ""; }; + BFF5B2262DEF022F0044227A /* VPThirdSignModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPThirdSignModel.swift; sourceTree = ""; }; + BFF5B2282DEFDAF00044227A /* Veloria.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Veloria.entitlements; sourceTree = ""; }; + BFF5B2292DEFDDF10044227A /* VPMeFooterView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPMeFooterView.swift; sourceTree = ""; }; + BFF5B22B2DEFE8A80044227A /* VPDeleteAccountViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPDeleteAccountViewController.swift; sourceTree = ""; }; + BFF5B22D2DEFEEAF0044227A /* VPDeleteAccountContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPDeleteAccountContentView.swift; sourceTree = ""; }; + BFF5B22F2DEFEF0C0044227A /* VPDeleteAccountNormalView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPDeleteAccountNormalView.swift; sourceTree = ""; }; + BFF5B2312DEFF1220044227A /* VPDeleteAccountDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPDeleteAccountDetailView.swift; sourceTree = ""; }; + BFF5B2332DEFF2030044227A /* VPDeleteAccountTipView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPDeleteAccountTipView.swift; sourceTree = ""; }; + 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 = ""; }; 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 */ @@ -398,6 +425,7 @@ 1B056E2A2DDAC0FD007EE38D /* Veloria */ = { isa = PBXGroup; children = ( + BFF5B2282DEFDAF00044227A /* Veloria.entitlements */, 1B056E322DDAC18C007EE38D /* AppDelegate */, 1B056E372DDAC1EF007EE38D /* Base */, 1B056E362DDAC1E8007EE38D /* Class */, @@ -434,6 +462,7 @@ 1B056E352DDAC1DE007EE38D /* Libs */ = { isa = PBXGroup; children = ( + BFF5B2352DF013020044227A /* Alert */, BF5E75D92DE5B89300DE9DFE /* MarqueeView */, BF5E75B42DE46D9500DE9DFE /* Empty */, BF0FA7BF2DE45D4500C9E5F2 /* User */, @@ -456,6 +485,7 @@ 1B056E522DDACBF4007EE38D /* Home */, BF0FA7422DDF024400C9E5F2 /* Explore */, BF0FA6FD2DDC65F300C9E5F2 /* Player */, + BFF5B21D2DEEE28B0044227A /* Login */, ); path = Class; sourceTree = ""; @@ -637,7 +667,9 @@ isa = PBXGroup; children = ( BF0FA6D92DDC5CB600C9E5F2 /* VPLoginManager.swift */, + BFF5B2242DEF02080044227A /* VPLoginManager+Apple.swift */, BF0FA6DB2DDC5CD700C9E5F2 /* VPTokenModel.swift */, + BFF5B2262DEF022F0044227A /* VPThirdSignModel.swift */, ); path = Login; sourceTree = ""; @@ -910,6 +942,7 @@ children = ( BF0FA7AE2DE443E000C9E5F2 /* VPMeViewController.swift */, BF5E75AE2DE4632200DE9DFE /* VPAboutUsViewController.swift */, + BFF5B22B2DEFE8A80044227A /* VPDeleteAccountViewController.swift */, ); path = Controller; sourceTree = ""; @@ -926,6 +959,11 @@ BFF5AFA72DE704DC0044227A /* VPMeCoinCell.swift */, BFF5AFA92DE7070A0044227A /* VPMeCoinItemView.swift */, BFF5AFAB2DE70CE20044227A /* VPMeToolCell.swift */, + BFF5B2292DEFDDF10044227A /* VPMeFooterView.swift */, + BFF5B22D2DEFEEAF0044227A /* VPDeleteAccountContentView.swift */, + BFF5B22F2DEFEF0C0044227A /* VPDeleteAccountNormalView.swift */, + BFF5B2312DEFF1220044227A /* VPDeleteAccountDetailView.swift */, + BFF5B2332DEFF2030044227A /* VPDeleteAccountTipView.swift */, ); path = View; sourceTree = ""; @@ -1052,6 +1090,41 @@ path = Controller; sourceTree = ""; }; + BFF5B21D2DEEE28B0044227A /* Login */ = { + isa = PBXGroup; + children = ( + BFF5B21E2DEEE2A50044227A /* Controller */, + BFF5B2212DEEEB0C0044227A /* View */, + ); + path = Login; + sourceTree = ""; + }; + BFF5B21E2DEEE2A50044227A /* Controller */ = { + isa = PBXGroup; + children = ( + ); + path = Controller; + sourceTree = ""; + }; + BFF5B2212DEEEB0C0044227A /* View */ = { + isa = PBXGroup; + children = ( + BFF5B21F2DEEE2C50044227A /* VPLoginContentView.swift */, + BFF5B2222DEEF8DA0044227A /* VPLoginButton.swift */, + ); + path = View; + sourceTree = ""; + }; + BFF5B2352DF013020044227A /* Alert */ = { + isa = PBXGroup; + children = ( + BFF5B23A2DF018900044227A /* VPAlertView.swift */, + BFF5B2382DF014520044227A /* VPBaseAlertView.swift */, + BFF5B2362DF013410044227A /* VPAlertWindowManager.swift */, + ); + path = Alert; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -1191,10 +1264,12 @@ BF0FA7C32DE45DE300C9E5F2 /* VPUserAPI.swift in Sources */, BF0FA78B2DE164C100C9E5F2 /* VPSearchResultCell.swift in Sources */, BF0FA71D2DDC807200C9E5F2 /* UIImageView+VPAdd.swift in Sources */, + BFF5B22C2DEFE8A80044227A /* VPDeleteAccountViewController.swift in Sources */, BF0FA6DC2DDC5CD700C9E5F2 /* VPTokenModel.swift in Sources */, BF0FA7572DDF159B00C9E5F2 /* VPExploreViewController.swift in Sources */, 1B056E772DDB3641007EE38D /* VPTabBarItemNormalVew.swift in Sources */, 1B056E4B2DDAC6BA007EE38D /* VPDefine.swift in Sources */, + BFF5B2302DEFEF0C0044227A /* VPDeleteAccountNormalView.swift in Sources */, 1B056E702DDB019B007EE38D /* VPTabBarItemContainer.swift in Sources */, BF0FA7752DE071B500C9E5F2 /* VPSearchViewController.swift in Sources */, BF0FA78D2DE16A8B00C9E5F2 /* VPSearchViewModel.swift in Sources */, @@ -1208,6 +1283,7 @@ BF0FA79B2DE1984B00C9E5F2 /* VPCollectListViewController.swift in Sources */, BF0FA7A32DE1AB1800C9E5F2 /* VPWatchHistoryCell.swift in Sources */, BF0FA76D2DE053C100C9E5F2 /* VPScrollView.swift in Sources */, + BFF5B2202DEEE2C50044227A /* VPLoginContentView.swift in Sources */, 1B056E5D2DDACD8E007EE38D /* UIFont+VPAdd.swift in Sources */, BF0FA7282DDC91F800C9E5F2 /* VPCollectionViewCell.swift in Sources */, BF0FA7672DE0469300C9E5F2 /* VPEpisodeView.swift in Sources */, @@ -1234,15 +1310,18 @@ BF5E75CD2DE5692D00DE9DFE /* JXTransitionDelegateBridge.swift in Sources */, BF5E75CE2DE5692D00DE9DFE /* JXPushAnimatedTransition.swift in Sources */, BF5E75CF2DE5692D00DE9DFE /* UIViewController+JXTransition.swift in Sources */, + BFF5B23B2DF018900044227A /* VPAlertView.swift in Sources */, BF5E75D02DE5692D00DE9DFE /* UIGestureRecognizer+JXTransition.swift in Sources */, BFF5AFA62DE700420044227A /* VPMeVipPrivilegeItemView.swift in Sources */, BF5E75D12DE5692D00DE9DFE /* JXPopAnimatedTransition.swift in Sources */, BF5E75D22DE5692D00DE9DFE /* JXNavigationInteractiveTransition.swift in Sources */, + BFF5B2342DEFF2030044227A /* VPDeleteAccountTipView.swift in Sources */, BF5E75D32DE5692D00DE9DFE /* JXBaseAnimatedTransition.swift in Sources */, 1B056E462DDAC370007EE38D /* UIScreen+VPAdd.swift in Sources */, BFF5AFDE2DEEBF370044227A /* VPPlayerRechargeView.swift in Sources */, BFF5AFAA2DE7070A0044227A /* VPMeCoinItemView.swift in Sources */, BF0FA7692DE0502900C9E5F2 /* VPEpisodeCell.swift in Sources */, + BFF5B2372DF013410044227A /* VPAlertWindowManager.swift in Sources */, BF5E75BE2DE54B2800DE9DFE /* VPAboutUsHeaderView.swift in Sources */, BFF5AFB22DE7FC130044227A /* CGMutablePath+VPAdd.swift in Sources */, BF0FA73D2DDED2D000C9E5F2 /* VPVideoAPI.swift in Sources */, @@ -1276,11 +1355,14 @@ BF0FA7A52DE4384100C9E5F2 /* AttributedString+VPAdd.swift in Sources */, BF0FA7652DE00A0E00C9E5F2 /* VPDetailPlayerControlView.swift in Sources */, BF0FA7342DDEC74500C9E5F2 /* VPCategoryModel.swift in Sources */, + BFF5B2322DEFF1220044227A /* VPDeleteAccountDetailView.swift in Sources */, 1B056E4F2DDAC7FC007EE38D /* VPNavigationController.swift in Sources */, 1B056E3F2DDAC2DB007EE38D /* VPCryptorService.swift in Sources */, BF0FA7202DDC83AE00C9E5F2 /* JXButton.swift in Sources */, BF0FA7912DE16CBF00C9E5F2 /* VPSearchHistoryView.swift in Sources */, BFF5AFE22DEED2960044227A /* VPPlayerCoinBuyView.swift in Sources */, + BFF5B2272DEF022F0044227A /* VPThirdSignModel.swift in Sources */, + BFF5B22A2DEFDDF10044227A /* VPMeFooterView.swift in Sources */, BF0FA7992DE1951A00C9E5F2 /* VPMyListViewController.swift in Sources */, BF0FA7452DDF027900C9E5F2 /* VPPlayer.swift in Sources */, BFF5AFC62DE863C00044227A /* VPGradientButton.swift in Sources */, @@ -1300,13 +1382,17 @@ BF0FA7022DDC667C00C9E5F2 /* VPVideoInfoModel.swift in Sources */, BF0FA77B2DE0788A00C9E5F2 /* UIStackView+VPAdd.swift in Sources */, BF0FA7BE2DE4592A00C9E5F2 /* UserDefaults+VPAdd.swift in Sources */, + BFF5B2232DEEF8DA0044227A /* VPLoginButton.swift in Sources */, BF0FA76F2DE062A700C9E5F2 /* VPRateSelectedView.swift in Sources */, BF0FA7772DE0735800C9E5F2 /* VPSearchInputView.swift in Sources */, BFF5AFB62DE803A30044227A /* VPVipPrivilegeItemView.swift in Sources */, BFF5AFB82DE832580044227A /* VPVipBuyCell.swift in Sources */, + BFF5B22E2DEFEEAF0044227A /* VPDeleteAccountContentView.swift in Sources */, + BFF5B2252DEF02080044227A /* VPLoginManager+Apple.swift in Sources */, BF0FA7892DE161F200C9E5F2 /* VPSearchResultView.swift in Sources */, 1B056E792DDB365A007EE38D /* VPTabBarItemSelectedView.swift in Sources */, 1B056E722DDB022F007EE38D /* VPTabBarItem.swift in Sources */, + BFF5B2392DF014520044227A /* VPBaseAlertView.swift in Sources */, BFF5AFCC2DE98C7F0044227A /* VPOrderRecordsViewController.swift in Sources */, 1B056E412DDAC30A007EE38D /* VPModel.swift in Sources */, BF0FA70A2DDC69C800C9E5F2 /* VPTableViewCell.swift in Sources */, @@ -1370,6 +1456,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Veloria/Veloria.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; @@ -1407,6 +1494,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Veloria/Veloria.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; diff --git a/Veloria/Base/Extension/UIColor+VPAdd.swift b/Veloria/Base/Extension/UIColor+VPAdd.swift index 3797272..f47b02a 100644 --- a/Veloria/Base/Extension/UIColor+VPAdd.swift +++ b/Veloria/Base/Extension/UIColor+VPAdd.swift @@ -193,4 +193,45 @@ extension UIColor { static func color00211A(alpha: CGFloat = 1) -> UIColor { return UIColor(rgb: 0x00211A, alpha: alpha) } + + static func color333333(alpha: CGFloat = 1) -> UIColor { + return UIColor(rgb: 0x333333, alpha: alpha) + } + + static func color585858(alpha: CGFloat = 1) -> UIColor { + return UIColor(rgb: 0x585858, alpha: alpha) + } + + static func colorB3B3B3(alpha: CGFloat = 1) -> UIColor { + return UIColor(rgb: 0xB3B3B3, alpha: alpha) + } + + static func color080B16(alpha: CGFloat = 1) -> UIColor { + return UIColor(rgb: 0x080B16, alpha: alpha) + } + + static func color272A30(alpha: CGFloat = 1) -> UIColor { + return UIColor(rgb: 0x272A30, alpha: alpha) + } + + static func color8B8B8B(alpha: CGFloat = 1) -> UIColor { + return UIColor(rgb: 0x8B8B8B, alpha: alpha) + } + + static func color126B4E(alpha: CGFloat = 1) -> UIColor { + return UIColor(rgb: 0x126B4E, alpha: alpha) + } + + static func color1A2D22(alpha: CGFloat = 1) -> UIColor { + return UIColor(rgb: 0x1A2D22, alpha: alpha) + } + + static func colorC8C8C8(alpha: CGFloat = 1) -> UIColor { + return UIColor(rgb: 0xC8C8C8, alpha: alpha) + } + + static func color024E3D(alpha: CGFloat = 1) -> UIColor { + return UIColor(rgb: 0x024E3D, alpha: alpha) + } + } diff --git a/Veloria/Base/Networking/API/VPUserAPI.swift b/Veloria/Base/Networking/API/VPUserAPI.swift index a740cd4..509b226 100644 --- a/Veloria/Base/Networking/API/VPUserAPI.swift +++ b/Veloria/Base/Networking/API/VPUserAPI.swift @@ -6,6 +6,7 @@ // import UIKit +import SmartCodable class VPUserAPI: NSObject { @@ -19,4 +20,39 @@ class VPUserAPI: NSObject { completer?(response.data) } } + + ///登录 + static func requestThirdLogin(model: VPThirdSignModel, completer: ((_ token: VPTokenModel?) -> Void)?) { + + var param = VPNetworkParameters(path: "/customer/login") + param.parameters = model.toDictionary() + + VPNetwork.request(parameters: param) { (response: VPNetworkResponse) in + completer?(response.data) + } + } + + ///退出登录 + static func requestLogout(completer: ((_ token: VPTokenModel?) -> Void)?) { + var param = VPNetworkParameters(path: "/customer/signout") + param.isLoding = true + + VPNetwork.request(parameters: param) { (response: VPNetworkResponse) in + completer?(response.data) + } + } + + ///注销账户 + static func requestDelete(completer: ((_ isFinish: Bool) -> Void)?) { + var param = VPNetworkParameters(path: "/customer/logoff") + param.isLoding = true + + VPNetwork.request(parameters: param) { (response: VPNetworkResponse) in + if response.code == VPNetworkCodeSucceed { + completer?(true) + } else { + completer?(false) + } + } + } } diff --git a/Veloria/Base/View/VPGradientLabel.swift b/Veloria/Base/View/VPGradientLabel.swift index a240f98..b26ad31 100644 --- a/Veloria/Base/View/VPGradientLabel.swift +++ b/Veloria/Base/View/VPGradientLabel.swift @@ -48,8 +48,21 @@ class VPGradientLabel: UILabel { let textLayer = CATextLayer() textLayer.string = string textLayer.frame = bounds - textLayer.alignmentMode = .center + switch self.textAlignment { + case .left: + textLayer.alignmentMode = .left + case .center: + textLayer.alignmentMode = .center + case .right: + textLayer.alignmentMode = .right + case .justified: + textLayer.alignmentMode = .justified + case .natural: + textLayer.alignmentMode = .natural + default: break + } textLayer.contentsScale = UIScreen.main.scale + textLayer.isWrapped = true gradientLayer.mask = textLayer CATransaction.commit() diff --git a/Veloria/Class/Login/View/VPLoginButton.swift b/Veloria/Class/Login/View/VPLoginButton.swift new file mode 100644 index 0000000..5031b20 --- /dev/null +++ b/Veloria/Class/Login/View/VPLoginButton.swift @@ -0,0 +1,72 @@ +// +// VPLoginButton.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/3. +// + +import UIKit + +class VPLoginButton: UIControl { + + var icon: UIImage? { + didSet { + iconImageView.image = icon + } + } + + var title: String? { + didSet { + titleLabel.text = title + } + } + + override var intrinsicContentSize: CGSize { + return .init(width: UIScreen.width, height: 48) + } + + private lazy var iconImageView: UIImageView = { + let imageView = UIImageView() + return imageView + }() + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.font = .fontRegular(ofSize: 14) + label.textColor = .color333333() + return label + }() + + + override init(frame: CGRect) { + super.init(frame: frame) + layer.cornerRadius = 24 + layer.masksToBounds = true + backgroundColor = .colorFFFFFF() + vp_setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + +extension VPLoginButton { + + private func vp_setupUI() { + addSubview(iconImageView) + addSubview(titleLabel) + + + iconImageView.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.left.equalToSuperview().offset(40) + } + + titleLabel.snp.makeConstraints { make in + make.center.equalToSuperview() + } + } + +} diff --git a/Veloria/Class/Login/View/VPLoginContentView.swift b/Veloria/Class/Login/View/VPLoginContentView.swift new file mode 100644 index 0000000..da6ffc2 --- /dev/null +++ b/Veloria/Class/Login/View/VPLoginContentView.swift @@ -0,0 +1,203 @@ +// +// VPLoginContentView.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/3. +// + +import UIKit + +class VPLoginContentView: HWPanModalContentView { + + private lazy var bgView: UIImageView = { + let imageView = UIImageView(image: UIImage(named: "bg_image_01")) + return imageView + }() + + private lazy var closeButton: UIButton = { + let button = UIButton(type: .custom) + button.setImage(UIImage(named: "close_icon_02"), for: .normal) + button.addTarget(self, action: #selector(handleCloseButton), for: .touchUpInside) + return button + }() + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.font = .fontMedium(ofSize: 16) + label.textColor = .colorFFFFFF() + label.text = String(format: "Welcome to %@".localized, "kAppName".localized) + return label + }() + + private lazy var agreementLabel: YYLabel = { + let userAgreementText = "User Agreement".localized + let privacyPolicyText = "Privacy Policy".localized + let text = String(format: "kLoginAgreementText".localized, userAgreementText, privacyPolicyText) + + let range1 = text.ocString().range(of: userAgreementText) + let range2 = text.ocString().range(of: privacyPolicyText) + + let string = NSMutableAttributedString(string: text) + string.font = .fontRegular(ofSize: 12) + string.color = .colorB5B5B5() + string.alignment = .center + string.setUnderlineColor(string.color, range: range1) + string.setUnderlineColor(string.color, range: range2) + string.setUnderlineStyle(.single, range: range1) + string.setUnderlineStyle(.single, range: range2) + string.setTextHighlight(range1, color: nil, backgroundColor: nil) { [weak self] _, _, _, _ in + self?.openWebPage(url: kVPUserAgreementWebUrl) + } + + string.setTextHighlight(range2, color: nil, backgroundColor: nil) { [weak self] _, _, _, _ in + self?.openWebPage(url: kVPPrivacyPolicyWebUrl) + } + + let textLayout = YYTextLayout(containerSize: .init(width: UIScreen.width - 30, height: 100), text: string) + + let label = YYLabel() + label.textLayout = textLayout + return label + }() + + private lazy var stackView: UIStackView = { + let stackView = UIStackView(arrangedSubviews: [appleButton]) + stackView.axis = .vertical + stackView.spacing = 20 + return stackView + }() + + private lazy var appleButton: VPLoginButton = { + let button = VPLoginButton() + button.icon = UIImage(named: "apple_icon_01") + button.title = "Login with Apple".localized + button.addTarget(self, action: #selector(handleAppleButton), for: .touchUpInside) + return button + }() + + override init(frame: CGRect) { + super.init(frame: frame) + + vp_setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func handleCloseButton() { + self.dismiss(animated: true) { + + } + } + + + //MARK: HWPanModalPresentable + override func panScrollable() -> UIScrollView? { + return nil + } + + override func longFormHeight() -> PanModalHeight { + return PanModalHeightMake(.content, UIScreen.height * (2 / 3)) + } + + override func showDragIndicator() -> Bool { + return false + } + + override func backgroundConfig() -> HWBackgroundConfig { + let config = HWBackgroundConfig() + config.backgroundAlpha = 0.6 + return config + } + + override func allowsDragToDismiss() -> Bool { + return false + } + + override func allowsTapBackgroundToDismiss() -> Bool { + return false + } + + override func allowsPullDownWhenShortState() -> Bool { + return false + } + + override func minVerticalVelocityToTriggerDismiss() -> CGFloat { + return 0 + } + + override func showsScrollableVerticalScrollIndicator() -> Bool { + return false + } + +} + +extension VPLoginContentView { + private func openWebPage(url: String) { + let vc = VPWebViewController() + vc.configNavigationBack() + vc.urlStr = url + let nav = VPNavigationController(rootViewController: vc) + nav.modalPresentationStyle = .fullScreen + VPAppTool.rootViewController?.present(nav, animated: true) + } + + @objc private func handleAppleButton() { + login(type: .apple) + } + + private func login(type: VPLoginManager.LoginType) { + VPHUD.show() + VPLoginManager.manager.login(type: type, presentingViewController: nil) { [weak self] isFinish in + VPHUD.dismiss() + guard let self = self else { return } + if isFinish { + self.dismiss(animated: true) { + + } + } else { + + } + } + } +} + +extension VPLoginContentView { + + private func vp_setupUI() { + addSubview(bgView) + addSubview(closeButton) + addSubview(titleLabel) + addSubview(agreementLabel) + addSubview(stackView) + + bgView.snp.makeConstraints { make in + make.left.right.top.equalToSuperview() + } + + closeButton.snp.makeConstraints { make in + make.right.equalToSuperview().offset(-15) + make.top.equalToSuperview().offset(15) + } + + titleLabel.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.centerY.equalTo(closeButton) + } + + agreementLabel.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.bottom.equalToSuperview().offset(-(UIScreen.tabbarSafeBottomMargin + 10)) + make.width.equalTo(agreementLabel.textLayout?.textBoundingSize.width ?? 0) + make.height.equalTo(agreementLabel.textLayout?.textBoundingSize.height ?? 0) + } + + stackView.snp.makeConstraints { make in + make.center.equalToSuperview() + make.left.equalToSuperview().offset(15) + } + + } + +} diff --git a/Veloria/Class/Me/Controller/VPDeleteAccountViewController.swift b/Veloria/Class/Me/Controller/VPDeleteAccountViewController.swift new file mode 100644 index 0000000..52d4f10 --- /dev/null +++ b/Veloria/Class/Me/Controller/VPDeleteAccountViewController.swift @@ -0,0 +1,202 @@ +// +// VPDeleteAccountViewController.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/4. +// + +import UIKit + +class VPDeleteAccountViewController: VPViewController { + + private lazy var scrollView: VPScrollView = { + let scrollView = VPScrollView() + return scrollView + }() + + private lazy var iconImageView: UIImageView = { + let imageView = UIImageView(image: UIImage(named: "warning_icon_01")) + return imageView + }() + + private lazy var iconTextLabel: UILabel = { + let label = UILabel() + label.font = .fontRegular(ofSize: 14) + label.textColor = .colorBE0069() + label.text = "DeleteAccount_tips_1".localized + return label + }() + + private lazy var stackView: UIStackView = { + let view = UIStackView() + view.axis = .vertical + view.spacing = 18 + + + view.addArrangedSubview(contentView1) + view.addArrangedSubview(contentView3) + view.addArrangedSubview(contentView2) + + return view + }() + + private lazy var contentView1: VPDeleteAccountNormalView = { + let view = VPDeleteAccountNormalView() + view.text = "DeleteAccount_tips_2".localized + return view + }() + + private lazy var contentView2: VPDeleteAccountNormalView = { + let view = VPDeleteAccountNormalView() + view.text = "DeleteAccount_tips_3".localized + return view + }() + + private lazy var contentView3: VPDeleteAccountDetailView = { + let view = VPDeleteAccountDetailView() + return view + }() + + private lazy var checkButton: UIButton = { + let button = UIButton(type: .custom) + button.setImage(UIImage(named: "choice_icon_01"), for: .normal) + button.setImage(UIImage(named: "choice_icon_01_selected"), for: .selected) + button.setImage(UIImage(named: "choice_icon_01_selected"), for: [.selected, .highlighted]) + button.addTarget(self, action: #selector(handleCheckButton), for: .touchUpInside) + button.setContentHuggingPriority(.required, for: .horizontal) + button.setContentCompressionResistancePriority(.required, for: .horizontal) + return button + }() + + private lazy var checkLabel: UILabel = { + let label = UILabel() + label.font = .fontMedium(ofSize: 14) + label.textColor = .colorFFFFFF() + label.numberOfLines = 0 + label.text = "DeleteAccount_tips_4".localized + return label + }() + + private lazy var deleteButton: UIButton = { + let config = UIButton.Configuration.plain() + let button = VPGradientButton(configuration: config) + button.layer.cornerRadius = 24 + button.layer.masksToBounds = true + button.isEnabled = false + button.locations = [0, 1] + button.startPoint = .init(x: 0, y: 0.3) + button.endPoint = .init(x: 1, y: 0.8) + button.addTarget(self, action: #selector(handleDeleteButton), for: .touchUpInside) + + button.configurationUpdateHandler = { button in + guard let button = button as? VPGradientButton else { return } + let title = "Delete Account".localized + + if button.isEnabled { + button.configuration?.attributedTitle = .createAttributedString(string: title, color: .colorFFFFFF(), font: .fontRegular(ofSize: 14)) + button.bt_setGradientBorder() + button.colors = [UIColor.color05CEA0(alpha: 0.3).cgColor, UIColor.color7C174F(alpha: 0.3).cgColor] + } else { + button.configuration?.attributedTitle = .createAttributedString(string: title, color: .color8B8B8B(), font: .fontRegular(ofSize: 14)) + button.bt_removeGradientBorder() + button.colors = [UIColor.color272A30().cgColor, UIColor.color272A30().cgColor] + } + } + + return button + }() + + override func viewDidLoad() { + super.viewDidLoad() + self.bgImageView.isHidden = true + self.view.backgroundColor = .color080B16() + self.title = "Account Deletion".localized + + vp_setupUI() + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.navigationController?.setNavigationBarHidden(false, animated: true) + self.setNavigationNormalStyle() + } + + +} + +extension VPDeleteAccountViewController { + + @objc private func handleCheckButton() { + self.checkButton.isSelected = !self.checkButton.isSelected + self.deleteButton.isEnabled = self.checkButton.isSelected + } + + @objc private func handleDeleteButton() { + let alert = VPAlertView(title: "kDeleteAccountAlertTitle".localized, subtitle: "kDeleteAccountAlertText".localized, icon: UIImage(named: "alert_icon_01"), normalButtonText: "Delete Forever".localized, highlightButtonText: "Cancel".localized) + alert.show() + + alert.clickNormalButton = { + VPLoginManager.manager.deleteAccount { [weak self] isFinish in + guard let self = self else { return } + if isFinish { + self.navigationController?.popViewController(animated: true) + } + } + } + } + +} + +extension VPDeleteAccountViewController { + + private func vp_setupUI() { + view.addSubview(scrollView) + scrollView.addSubview(iconImageView) + scrollView.addSubview(iconTextLabel) + scrollView.addSubview(stackView) + scrollView.addSubview(checkButton) + scrollView.addSubview(checkLabel) + scrollView.addSubview(deleteButton) + + scrollView.snp.makeConstraints { make in + make.left.right.bottom.equalToSuperview() + make.top.equalToSuperview().offset(UIScreen.navBarHeight) + } + + iconImageView.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.top.equalToSuperview().offset(10) + } + + iconTextLabel.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.top.equalTo(iconImageView.snp.bottom).offset(12) + } + + stackView.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16) + make.centerX.equalToSuperview() + make.top.equalTo(iconTextLabel.snp.bottom).offset(18) + } + + checkButton.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16) + make.top.equalTo(stackView.snp.bottom).offset(25) + } + + checkLabel.snp.makeConstraints { make in + make.left.equalTo(checkButton.snp.right).offset(10) + make.right.lessThanOrEqualTo(stackView) + make.top.equalTo(checkButton).offset(2) + } + + deleteButton.snp.makeConstraints { make in + make.left.equalTo(stackView) + make.right.equalTo(stackView) + make.top.equalTo(checkLabel.snp.bottom).offset(20) + make.height.equalTo(48) + make.bottom.equalToSuperview().offset(-(UIScreen.tabbarSafeBottomMargin + 20)) + } + } + +} diff --git a/Veloria/Class/Me/Controller/VPMeViewController.swift b/Veloria/Class/Me/Controller/VPMeViewController.swift index 0a026de..297f819 100644 --- a/Veloria/Class/Me/Controller/VPMeViewController.swift +++ b/Veloria/Class/Me/Controller/VPMeViewController.swift @@ -10,28 +10,7 @@ import UIKit class VPMeViewController: VPViewController { private lazy var dataArr: [[VPMeItem]] = { - let arr = [ - [ - VPMeItem(cellKey: .userInfo), - ], - [ - VPMeItem(cellKey: .vip) - ], - [ - VPMeItem(cellKey: .coin) - ], - [ - VPMeItem(cellKey: .tool) - ], - [ - VPMeItem(icon: UIImage(named: "me_item_icon_05"), title: "Language".localized, type: .language, cellKey: .normal), - VPMeItem(icon: UIImage(named: "me_item_icon_01"), title: "Privacy Policy".localized, type: .privacyPolicy, cellKey: .normal), - VPMeItem(icon: UIImage(named: "me_item_icon_02"), title: "User Agreement".localized, type: .userAgreement, cellKey: .normal), -// VPMeItem(icon: UIImage(named: "me_item_icon_04"), title: "Help Center".localized, type: .feedback, cellKey: .normal), - VPMeItem(icon: UIImage(named: "me_item_icon_03"), title: "About Us".localized, type: .aboutUs, cellKey: .normal), - ] - ] - return arr + return self.createDataArr() }() @@ -53,8 +32,20 @@ class VPMeViewController: VPViewController { return tableView }() + private lazy var footerView: VPMeFooterView = { + let view = VPMeFooterView(frame: .init(x: 0, y: 0, width: UIScreen.width, height: 80)) + view.userInfo = VPLoginManager.manager.userInfo + return view + }() + + deinit { + NotificationCenter.default.removeObserver(self) + } + override func viewDidLoad() { super.viewDidLoad() + NotificationCenter.default.addObserver(self, selector: #selector(userInfoUpdateNotification), name: VPLoginManager.userInfoUpdateNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(loginStateDidChangeNotification), name: VPLoginManager.loginStateDidChangeNotification, object: nil) vp_setupUI() @@ -80,11 +71,28 @@ class VPMeViewController: VPViewController { } } + +} + +extension VPMeViewController { + + @objc private func userInfoUpdateNotification() { + self.footerView.userInfo = VPLoginManager.manager.userInfo + self.tableView.reloadData() + } + + @objc private func loginStateDidChangeNotification() { + self.dataArr = createDataArr() + self.tableView.reloadData() + } + } extension VPMeViewController { private func vp_setupUI() { + tableView.tableFooterView = self.footerView + view.addSubview(tableView) tableView.snp.makeConstraints { make in @@ -150,6 +158,10 @@ extension VPMeViewController: UITableViewDelegate, UITableViewDataSource { let vc = VPAboutUsViewController() self.navigationController?.pushViewController(vc, animated: true) + case .deleteAccount: + let vc = VPDeleteAccountViewController() + self.navigationController?.pushViewController(vc, animated: true) + default: break } @@ -163,10 +175,42 @@ extension VPMeViewController { ///获取用户信息 private func requestUserInfo(completer: (() -> Void)? = nil) { - VPLoginManager.manager.updateUserInfo { [weak self] in - self?.tableView.reloadData() - + VPLoginManager.manager.updateUserInfo { completer?() } } + + + private func createDataArr() -> [[VPMeItem]] { + var dataArr = [ + [ + VPMeItem(cellKey: .userInfo), + ], + [ + VPMeItem(cellKey: .vip) + ], + [ + VPMeItem(cellKey: .coin) + ], + [ + VPMeItem(cellKey: .tool) + ] + ] + + var cellArr: [VPMeItem] = [] + 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_03"), title: "About Us".localized, type: .aboutUs, cellKey: .normal)) + + if VPLoginManager.manager.userInfo?.is_tourist == false { + cellArr.append(VPMeItem(icon: UIImage(named: "me_item_icon_06"), title: "Delet Account".localized, type: .deleteAccount, cellKey: .normal)) + } + + dataArr.append(cellArr) + + + return dataArr + } } diff --git a/Veloria/Class/Me/Model/VPMeItem.swift b/Veloria/Class/Me/Model/VPMeItem.swift index 7c86c08..4470055 100644 --- a/Veloria/Class/Me/Model/VPMeItem.swift +++ b/Veloria/Class/Me/Model/VPMeItem.swift @@ -13,6 +13,7 @@ struct VPMeItem { case userAgreement case aboutUs case feedback + case deleteAccount case informationProtection case civizatioConvention case informationSharing diff --git a/Veloria/Class/Me/View/VPDeleteAccountContentView.swift b/Veloria/Class/Me/View/VPDeleteAccountContentView.swift new file mode 100644 index 0000000..dffbdbd --- /dev/null +++ b/Veloria/Class/Me/View/VPDeleteAccountContentView.swift @@ -0,0 +1,23 @@ +// +// VPDeleteAccountContentView.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/4. +// + +import UIKit + +class VPDeleteAccountContentView: UIView { + + override init(frame: CGRect) { + super.init(frame: frame) + backgroundColor = .color272A30() + layer.cornerRadius = 8 + layer.masksToBounds = true + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} diff --git a/Veloria/Class/Me/View/VPDeleteAccountDetailView.swift b/Veloria/Class/Me/View/VPDeleteAccountDetailView.swift new file mode 100644 index 0000000..9a397f1 --- /dev/null +++ b/Veloria/Class/Me/View/VPDeleteAccountDetailView.swift @@ -0,0 +1,87 @@ +// +// VPDeleteAccountDetailView.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/4. +// + +import UIKit + +class VPDeleteAccountDetailView: VPDeleteAccountContentView { + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.font = .fontRegular(ofSize: 14) + label.textColor = .colorFFFFFF() + label.numberOfLines = 0 + label.text = "DeleteAccount_tips_5".localized + return label + }() + + private lazy var stackView: UIStackView = { + let view = UIStackView(arrangedSubviews: [tipView1, tipView2, tipView3, tipView4]) + view.axis = .vertical + view.spacing = 12 + + return view + }() + + private lazy var tipView1: VPDeleteAccountTipView = { + let view = VPDeleteAccountTipView() + view.title = "DeleteAccount_tips_title_1".localized + view.text = "DeleteAccount_tips_text_1".localized + return view + }() + + private lazy var tipView2: VPDeleteAccountTipView = { + let view = VPDeleteAccountTipView() + view.title = "DeleteAccount_tips_title_2".localized + view.text = "DeleteAccount_tips_text_2".localized + return view + }() + + private lazy var tipView3: VPDeleteAccountTipView = { + let view = VPDeleteAccountTipView() + view.title = "DeleteAccount_tips_title_3".localized + view.text = "DeleteAccount_tips_text_3".localized + return view + }() + + private lazy var tipView4: VPDeleteAccountTipView = { + let view = VPDeleteAccountTipView() + view.title = "DeleteAccount_tips_title_4".localized +// view.text = "DeleteAccount_tips_text_1".localized + return view + }() + + override init(frame: CGRect) { + super.init(frame: frame) + vp_setupUI() + } + + @MainActor required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + +extension VPDeleteAccountDetailView { + + private func vp_setupUI() { + addSubview(titleLabel) + addSubview(stackView) + + titleLabel.snp.makeConstraints { make in + make.left.equalToSuperview().offset(13) + make.top.equalToSuperview().offset(12) + make.right.lessThanOrEqualToSuperview().offset(-13) + } + + stackView.snp.makeConstraints { make in + make.left.right.equalToSuperview() + make.top.equalTo(titleLabel.snp.bottom).offset(12) + make.bottom.equalToSuperview().offset(-10) + } + } + +} diff --git a/Veloria/Class/Me/View/VPDeleteAccountNormalView.swift b/Veloria/Class/Me/View/VPDeleteAccountNormalView.swift new file mode 100644 index 0000000..faeea3f --- /dev/null +++ b/Veloria/Class/Me/View/VPDeleteAccountNormalView.swift @@ -0,0 +1,45 @@ +// +// VPDeleteAccountNormalView.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/4. +// + +import UIKit + +class VPDeleteAccountNormalView: VPDeleteAccountContentView { + + var text: String? { + didSet { + let str = NSMutableAttributedString(string: text ?? "") + str.lineSpacing = 4 + label.attributedText = str + } + } + + private lazy var label: UILabel = { + let label = UILabel() + label.numberOfLines = 0 + label.font = .fontRegular(ofSize: 14) + label.textColor = .colorFFFFFF() + return label + }() + + override init(frame: CGRect) { + super.init(frame: frame) + + addSubview(label) + + label.snp.makeConstraints { make in + make.left.equalToSuperview().offset(12) + make.centerY.equalToSuperview() + make.top.equalToSuperview().offset(12) + make.right.lessThanOrEqualToSuperview().offset(-12) + } + } + + @MainActor required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} diff --git a/Veloria/Class/Me/View/VPDeleteAccountTipView.swift b/Veloria/Class/Me/View/VPDeleteAccountTipView.swift new file mode 100644 index 0000000..371f597 --- /dev/null +++ b/Veloria/Class/Me/View/VPDeleteAccountTipView.swift @@ -0,0 +1,89 @@ +// +// VPDeleteAccountTipView.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/4. +// + +import UIKit + +class VPDeleteAccountTipView: UIView { + + var title: String? { + didSet { + titleLabel.text = title + } + } + + var text: String? { + didSet { + let str = NSMutableAttributedString(string: text ?? "") + str.lineSpacing = 4 + textLabel.attributedText = str + } + } + + private lazy var dotView: UIView = { + let view = UIView() + view.backgroundColor = .colorFFFFFF() + view.layer.cornerRadius = 2 + view.layer.masksToBounds = true + return view + }() + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.font = .fontRegular(ofSize: 12) + label.textColor = .colorFFFFFF() + return label + }() + + private lazy var textLabel: UILabel = { + let label = UILabel() + label.font = .fontRegular(ofSize: 12) + label.textColor = .color8B8B8B() + label.numberOfLines = 0 + return label + }() + + override init(frame: CGRect) { + super.init(frame: frame) + + vp_setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + +} + +extension VPDeleteAccountTipView { + + private func vp_setupUI() { + addSubview(dotView) + addSubview(titleLabel) + addSubview(textLabel) + + dotView.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16) + make.centerY.equalTo(titleLabel) + make.width.height.equalTo(4) + } + + titleLabel.snp.makeConstraints { make in + make.top.equalToSuperview() + make.left.equalToSuperview().offset(24) + make.right.lessThanOrEqualToSuperview().offset(-24) + } + + textLabel.snp.makeConstraints { make in + make.left.equalTo(titleLabel) + make.top.equalTo(titleLabel.snp.bottom).offset(4) + make.right.lessThanOrEqualToSuperview().offset(-24) + make.bottom.equalToSuperview() + } + } + +} diff --git a/Veloria/Class/Me/View/VPMeCoinCell.swift b/Veloria/Class/Me/View/VPMeCoinCell.swift index 4ce509d..3509dc8 100644 --- a/Veloria/Class/Me/View/VPMeCoinCell.swift +++ b/Veloria/Class/Me/View/VPMeCoinCell.swift @@ -50,9 +50,9 @@ class VPMeCoinCell: VPTableViewCell { extension VPMeCoinCell { private func vp_setupUI() { - addSubview(lineView) - addSubview(coinView1) - addSubview(coinView2) + contentView.addSubview(lineView) + contentView.addSubview(coinView1) + contentView.addSubview(coinView2) lineView.snp.makeConstraints { make in make.centerX.equalToSuperview() diff --git a/Veloria/Class/Me/View/VPMeFooterView.swift b/Veloria/Class/Me/View/VPMeFooterView.swift new file mode 100644 index 0000000..31d2b1e --- /dev/null +++ b/Veloria/Class/Me/View/VPMeFooterView.swift @@ -0,0 +1,65 @@ +// +// VPMeFooterView.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/4. +// + +import UIKit + +class VPMeFooterView: UIView { + + var userInfo: VPUserInfo? { + didSet { + button.isSelected = !(userInfo?.is_tourist ?? true) + } + } + + private lazy var button: UIButton = { + let button = UIButton(type: .custom) + button.layer.cornerRadius = 20 + button.layer.masksToBounds = true + button.layer.borderColor = UIColor.color585858().cgColor + button.layer.borderWidth = 1 + button.setTitle("Log In".localized, for: .normal) + button.setTitle("Sign Out".localized, for: .selected) + button.setTitle("Sign Out".localized, for: [.selected, .highlighted]) + button.setTitleColor(.colorB3B3B3(), for: .normal) + button.titleLabel?.font = .fontRegular(ofSize: 14) + button.addTarget(self, action: #selector(handleButton), for: .touchUpInside) + return button + }() + + override init(frame: CGRect) { + super.init(frame: frame) + + addSubview(button) + + button.snp.makeConstraints { make in + make.left.equalToSuperview().offset(15) + make.centerX.equalToSuperview() + make.top.equalToSuperview().offset(20) + make.height.equalTo(40) + } + + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func handleButton() { + + if userInfo?.is_tourist == true { + let view = VPLoginContentView() + view.present(in: nil) + } 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 = { + VPLoginManager.manager.logout(completer: nil) + } + + } + } + +} diff --git a/Veloria/Class/Me/View/VPMeUserInfoCell.swift b/Veloria/Class/Me/View/VPMeUserInfoCell.swift index 409a73a..71ba3ec 100644 --- a/Veloria/Class/Me/View/VPMeUserInfoCell.swift +++ b/Veloria/Class/Me/View/VPMeUserInfoCell.swift @@ -21,6 +21,9 @@ class VPMeUserInfoCell: VPTableViewCell { } idLabel.text = "ID \(userInfo?.customer_id ?? "")" + + loginButton.isHidden = !(userInfo?.is_tourist ?? true) + } } @@ -47,6 +50,28 @@ class VPMeUserInfoCell: VPTableViewCell { return label }() + private lazy var loginButton: VPGradientButton = { + let title = AttributedString.createAttributedString(string: "Check in".localized, color: .colorFFFFFF(), font: .fontRegular(ofSize: 12)) + + var config = UIButton.Configuration.plain() + config.imagePlacement = .leading + config.imagePadding = 6 + config.image = UIImage(named: "login_icon_01") + config.attributedTitle = title + config.contentInsets = .init(top: 0, leading: 12, bottom: 0, trailing: 12) + + let button = VPGradientButton(configuration: config) + button.colors = [UIColor.color05CEA0(alpha: 0.3).cgColor, UIColor.color7C174F(alpha: 0.3).cgColor] + button.locations = [0, 1] + button.startPoint = .init(x: 0, y: 0.3) + button.endPoint = .init(x: 1, y: 0.8) + button.layer.cornerRadius = 17 + button.layer.masksToBounds = true + button.bt_setGradientBorder() + button.addTarget(self, action: #selector(handleLoginButton), for: .touchUpInside) + return button + }() + override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) @@ -57,6 +82,11 @@ class VPMeUserInfoCell: VPTableViewCell { fatalError("init(coder:) has not been implemented") } + @objc private func handleLoginButton() { + let view = VPLoginContentView() + view.present(in: nil) + } + } extension VPMeUserInfoCell { @@ -65,6 +95,7 @@ extension VPMeUserInfoCell { contentView.addSubview(avatarImageView) contentView.addSubview(nicknameLabel) contentView.addSubview(idLabel) + contentView.addSubview(loginButton) avatarImageView.snp.makeConstraints { make in make.left.equalToSuperview() @@ -84,6 +115,12 @@ extension VPMeUserInfoCell { make.bottom.equalTo(avatarImageView).offset(-3) } + loginButton.snp.makeConstraints { make in + make.centerY.equalTo(avatarImageView) + make.right.equalToSuperview() + make.height.equalTo(34) + } + } } diff --git a/Veloria/Libs/Alert/VPAlertView.swift b/Veloria/Libs/Alert/VPAlertView.swift new file mode 100644 index 0000000..4d5e3f4 --- /dev/null +++ b/Veloria/Libs/Alert/VPAlertView.swift @@ -0,0 +1,206 @@ +// +// VPAlertView.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/4. +// + +import UIKit + +class VPAlertView: VPBaseAlertView { + + var clickNormalButton: (() -> Void)? + var clickHighlightButton: (() -> Void)? + + + private lazy var bgView: UIImageView = { + let imageView = UIImageView(image: UIImage(named: "alert_bg_image_01")) + imageView.backgroundColor = .colorFFFFFF() + imageView.layer.cornerRadius = 18 + imageView.layer.masksToBounds = true + imageView.isUserInteractionEnabled = true + return imageView + }() + + private lazy var iconImageView: UIImageView = { + let imageView = UIImageView() + return imageView + }() + + private lazy var titleIconImageView: UIImageView = { + let imageView = UIImageView(image: UIImage(named: "alert_title_icon_01")) + return imageView + }() + + private lazy var titleLabel: VPGradientLabel = { + let label = VPGradientLabel() + label.gradientLayer.colors = [UIColor.color126B4E().cgColor, UIColor.color1A2D22().cgColor] + label.gradientLayer.startPoint = .init(x: 0.5, y: 0) + label.gradientLayer.endPoint = .init(x: 0.5, y: 1) + label.numberOfLines = 0 + return label + }() + + private lazy var textLabel: VPGradientLabel = { + let label = VPGradientLabel() + label.gradientLayer.colors = [UIColor.color126B4E().cgColor, UIColor.color1A2D22().cgColor] + label.gradientLayer.startPoint = .init(x: 0.5, y: 0) + label.gradientLayer.endPoint = .init(x: 0.5, y: 1) + label.numberOfLines = 0 + return label + }() + + private lazy var normalButton: UIButton = { + let button = UIButton(type: .custom) + button.setTitleColor(.colorC8C8C8(), for: .normal) + button.titleLabel?.font = .fontMedium(ofSize: 14) + button.layer.cornerRadius = 24 + button.layer.masksToBounds = true + button.layer.borderWidth = 1 + button.layer.borderColor = UIColor.colorC8C8C8().cgColor + button.addTarget(self, action: #selector(handleNormalButton), for: .touchUpInside) + return button + }() + + private lazy var highlightButton: UIButton = { + let button = VPGradientButton(type: .custom) + button.setTitleColor(.colorFFFFFF(), for: .normal) + button.titleLabel?.font = .fontMedium(ofSize: 14) + button.locations = [0, 1] + button.startPoint = .init(x: 0, y: 0.3) + button.endPoint = .init(x: 1, y: 0.8) + button.colors = [UIColor.color05CEA0().cgColor, UIColor.color7C174F().cgColor] + button.layer.cornerRadius = 24 + button.layer.borderWidth = 1.5 + button.layer.borderColor = UIColor.colorFFFFFF().cgColor + button.layer.shadowColor = UIColor.color024E3D(alpha: 0.4).cgColor + button.layer.shadowOpacity = 1 + button.layer.shadowOffset = .init(width: 0, height: 4) + button.addTarget(self, action: #selector(handleHighlightButton), for: .touchUpInside) + return button + }() + + private lazy var buttonStackView: UIStackView = { + let view = UIStackView() + view.axis = .horizontal + view.spacing = 10 + view.alignment = .fill + view.distribution = .fillEqually + return view + }() + + private lazy var closeButton: UIButton = { + let button = UIButton(type: .custom) + button.setImage(UIImage(named: "close_icon_02"), for: .normal) + button.addTarget(self, action: #selector(dismiss), for: .touchUpInside) + return button + }() + + + init(title: String, subtitle: String, icon: UIImage?, normalButtonText: String?, highlightButtonText: String?) { + super.init(frame: UIScreen.main.bounds) + iconImageView.image = icon + + let titleStr = NSMutableAttributedString(string: title) + titleStr.lineSpacing = 4 + titleStr.font = .fontMedium(ofSize: 20) + titleLabel.attributedText = titleStr + + let textStr = NSMutableAttributedString(string: subtitle) + textStr.lineSpacing = 4 + textStr.font = .fontRegular(ofSize: 15) + textLabel.attributedText = textStr + + normalButton.setTitle(normalButtonText, for: .normal) + highlightButton.setTitle(highlightButtonText, for: .normal) + + + vp_setupUI() + } + + @MainActor required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} + +extension VPAlertView { + + @objc private func handleHighlightButton() { + self.clickHighlightButton?() + self.dismiss() + } + + @objc private func handleNormalButton() { + self.clickNormalButton?() + self.dismiss() + } +} + +extension VPAlertView { + + private func vp_setupUI() { + contentView.addSubview(bgView) + contentView.addSubview(iconImageView) + bgView.addSubview(titleLabel) + bgView.addSubview(titleIconImageView) + bgView.addSubview(textLabel) + bgView.addSubview(buttonStackView) + contentView.addSubview(closeButton) + + bgView.snp.makeConstraints { make in + make.left.right.top.equalToSuperview() + make.height.equalTo(290) + make.width.equalTo(UIScreen.width - 70) + make.bottom.equalToSuperview().offset(-50) + } + + iconImageView.snp.makeConstraints { make in + make.top.equalToSuperview().offset(-43) + make.right.equalToSuperview() + } + + titleLabel.snp.makeConstraints { make in + make.left.equalToSuperview().offset(33) + make.top.equalToSuperview().offset(36) + make.right.lessThanOrEqualToSuperview().offset(-100) + } + + titleIconImageView.snp.makeConstraints { make in + make.left.equalTo(titleLabel).offset(-13) + make.top.equalTo(titleLabel).offset(-8) + } + + textLabel.snp.makeConstraints { make in + make.left.equalToSuperview().offset(33) + make.right.lessThanOrEqualToSuperview().offset(-33) + make.centerY.equalTo(bgView.snp.top).offset(150) + } + + buttonStackView.snp.makeConstraints { make in + make.left.equalToSuperview().offset(10) + make.centerX.equalToSuperview() + make.bottom.equalToSuperview().offset(-30) + make.height.equalTo(48) + } + + closeButton.snp.makeConstraints { make in + make.centerX.equalToSuperview() + make.bottom.equalToSuperview() + } + + var buttons: [UIButton] = [] + + if let title = normalButton.title(for: .normal), title.count > 0 { + buttons.append(normalButton) + } + if let title = highlightButton.title(for: .normal), title.count > 0 { + buttons.append(highlightButton) + } + + buttons.forEach { + buttonStackView.addArrangedSubview($0) + } + } + +} diff --git a/Veloria/Libs/Alert/VPAlertWindowManager.swift b/Veloria/Libs/Alert/VPAlertWindowManager.swift new file mode 100644 index 0000000..31ec5e3 --- /dev/null +++ b/Veloria/Libs/Alert/VPAlertWindowManager.swift @@ -0,0 +1,44 @@ +// +// VPAlertWindowManager.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/4. +// + +import UIKit + +class VPAlertWindowManager { + + static let manager = VPAlertWindowManager() + + private var window: UIWindow? + + private var count = 0 + + func createWindow() -> UIWindow { + count += 1 + guard let window = window else { + let window = UIWindow(windowScene: VPAppTool.windowScene!) + window.backgroundColor = .clear + window.windowLevel = .alert + window.isHidden = false + self.window = window + return window + } + return window + } + + func dismissWindow() { +// count -= 1 + guard let window = self.window else { return } + if window.subviews.count <= 0 { + window.isHidden = true + self.window = nil + } + +// if count == 0 { +// window?.isHidden = true +// window = nil +// } + } +} diff --git a/Veloria/Libs/Alert/VPBaseAlertView.swift b/Veloria/Libs/Alert/VPBaseAlertView.swift new file mode 100644 index 0000000..d40bcff --- /dev/null +++ b/Veloria/Libs/Alert/VPBaseAlertView.swift @@ -0,0 +1,67 @@ +// +// VPBaseAlertView.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/4. +// + +import UIKit + +class VPBaseAlertView: UIView { + + + private(set) var contentView: UIView = { + let view = UIView() + return view + }() + + override init(frame: CGRect) { + super.init(frame: frame) + backgroundColor = .color000000(alpha: 0.5) + + addSubview(contentView) + contentView.snp.makeConstraints { make in + make.center.equalToSuperview() + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @discardableResult + @objc func show(in view: UIView? = nil) -> Self { + var inView: UIView + if let view = view { + inView = view + } else { + inView = VPAlertWindowManager.manager.createWindow() + } + + inView.addSubview(self) + self.frame = inView.bounds + creatShowAnimation() + + return self + } + @objc func dismiss() { + removeFromSuperview() + VPAlertWindowManager.manager.dismissWindow() + } + +} + +extension VPBaseAlertView { + + private func creatShowAnimation() { + contentView.layer.position = center + contentView.transform = CGAffineTransform(scaleX: 0.9, y: 0.9) + UIView.animate(withDuration: 0.2, animations: { + self.contentView.transform = CGAffineTransform(scaleX: 1.2, y: 1.2) + }) { finished in + UIView.animate(withDuration: 0.1, animations: { + self.contentView.transform = CGAffineTransform.identity + }) + } + } +} diff --git a/Veloria/Libs/Login/VPLoginManager+Apple.swift b/Veloria/Libs/Login/VPLoginManager+Apple.swift new file mode 100644 index 0000000..b525861 --- /dev/null +++ b/Veloria/Libs/Login/VPLoginManager+Apple.swift @@ -0,0 +1,112 @@ +// +// VPLoginManager+Apple.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/3. +// + +import UIKit +import AuthenticationServices + +extension VPLoginManager { + + private struct AssociatedKeys { + static var signAppleHandle: Int? + } + + private var signAppleHandle: ((_ model: VPThirdSignModel?) -> Void)? { + set { + objc_setAssociatedObject(self, &AssociatedKeys.signAppleHandle, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC) + } + get { + return objc_getAssociatedObject(self, &AssociatedKeys.signAppleHandle) as? ((_ model: VPThirdSignModel?) -> Void) + } + } + + + ///苹果登录 + func appleSignLogin(completer: ((_ model: VPThirdSignModel?) -> Void)?) { + self.signAppleHandle = completer + + let appleIDProvider = ASAuthorizationAppleIDProvider() + let request = appleIDProvider.createRequest() + request.requestedScopes = [.fullName, .email] + + let authorizationController = ASAuthorizationController(authorizationRequests: [request]) + authorizationController.delegate = self + authorizationController.presentationContextProvider = self + authorizationController.performRequests() + } +} + +//MARK:-------------- ASAuthorizationControllerDelegate -------------- +extension VPLoginManager: ASAuthorizationControllerDelegate { + + func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { + if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential { + + let userIdentifier = appleIDCredential.user + let fullName = appleIDCredential.fullName + let email = appleIDCredential.email + + let identityToken = appleIDCredential.identityToken.flatMap { String(data: $0, encoding: .utf8) } + let identityTokenParams = self.jwtDecode(jwtStr: identityToken ?? "") + + + let model = VPThirdSignModel() + model.platform = .apple + model.third_id = userIdentifier + model.giving_name = fullName?.givenName + model.family_name = fullName?.familyName + model.avator = identityTokenParams?["picture"] as? String + model.email = identityTokenParams?["email"] as? String + + signAppleHandle?(model) + } + } + + func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) { + signAppleHandle?(nil) + } + +} + +extension VPLoginManager: ASAuthorizationControllerPresentationContextProviding { + + func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor { + return VPAppTool.keyWindow! + } + +} + +extension VPLoginManager { + + private func jwtDecode(jwtStr: String) -> [String: Any]? { + let segments = jwtStr.components(separatedBy: ".") + guard segments.count > 1 else { return nil } + + var base64String = segments[1] + + // 处理 Base64 补齐 + let requiredLength = 4 * Int(ceil(Double(base64String.count) / 4.0)) + let paddingLength = requiredLength - base64String.count + if paddingLength > 0 { + base64String += String(repeating: "=", count: paddingLength) + } + + // 替换 URL 安全字符 + base64String = base64String.replacingOccurrences(of: "-", with: "+") + base64String = base64String.replacingOccurrences(of: "_", with: "/") + + // 解码 Base64 数据 + guard let data = Data(base64Encoded: base64String), + let jsonObject = try? JSONSerialization.jsonObject(with: data, options: []), + let payload = jsonObject as? [String: Any] else { + return nil + } + + return payload + } + +} + diff --git a/Veloria/Libs/Login/VPLoginManager.swift b/Veloria/Libs/Login/VPLoginManager.swift index 674f7ee..3d583d2 100644 --- a/Veloria/Libs/Login/VPLoginManager.swift +++ b/Veloria/Libs/Login/VPLoginManager.swift @@ -6,9 +6,17 @@ // import UIKit +import SmartCodable class VPLoginManager: NSObject { + enum LoginType: String, SmartCaseDefaultable { + case apple = "Apple" + case faceBook = "Facebook" + case google = "Google" + case tiktok = "Tiktok" + } + static let manager = VPLoginManager() @@ -30,6 +38,52 @@ class VPLoginManager: NSObject { UserDefaults.vp_setObject(token, forKey: kVPLoginTokenDefaultsKey) } + func login(type: LoginType, presentingViewController: UIViewController?, completer: ((_ isFinish: Bool) -> Void)?) { + + switch type { + case .apple: + appleSignLogin { [weak self] model in + self?.requestThirdLogin(thirdSignModel: model, completer: completer) + } + default: break + } + + } + + ///退出登录 + func logout(completer: ((_ isFinish: Bool) -> Void)?) { + VPUserAPI.requestLogout { [weak self] token in + guard let self = self else { return } + if let token = token { + self.setLoginToken(token: token) + self.userInfo?.is_tourist = true + self.updateUserInfo(completer: nil) + completer?(true) + NotificationCenter.default.post(name: VPLoginManager.userInfoUpdateNotification, object: nil) + NotificationCenter.default.post(name: VPLoginManager.loginStateDidChangeNotification, object: nil) + } else { + completer?(false) + } + } + } + + ///删除账号 + func deleteAccount(completer: ((_ isFinish: Bool) -> Void)?) { + VPUserAPI.requestDelete { [weak self] isFinish in + guard let self = self else { return } + if isFinish { + self.setLoginToken(token: nil) + self.userInfo?.is_tourist = true + self.updateUserInfo(completer: nil) + completer?(true) + NotificationCenter.default.post(name: VPLoginManager.userInfoUpdateNotification, object: nil) + NotificationCenter.default.post(name: VPLoginManager.loginStateDidChangeNotification, object: nil) + } else { + completer?(false) + } + } + } + ///更新用户信息 func updateUserInfo(completer: (() -> Void)?) { @@ -39,9 +93,47 @@ class VPLoginManager: NSObject { if let userInfo = userInfo { self.userInfo = userInfo UserDefaults.vp_setObject(userInfo, forKey: kVPLoginUserInfoDefaultsKey) + NotificationCenter.default.post(name: VPLoginManager.userInfoUpdateNotification, object: nil) } completer?() } } } + +extension VPLoginManager { + + ///请求第三方登录 + private func requestThirdLogin(thirdSignModel: VPThirdSignModel?, completer: ((_ isFinish: Bool) -> Void)?) { + guard let thirdSignModel = thirdSignModel else { + completer?(false) + return + } + + VPUserAPI.requestThirdLogin(model: thirdSignModel) { [weak self] token in + guard let self = self else { return } + guard let token = token else { + completer?(false) + return + } + self.setLoginToken(token: token) + self.userInfo?.is_tourist = false + self.updateUserInfo(completer: nil) + completer?(true) + NotificationCenter.default.post(name: VPLoginManager.userInfoUpdateNotification, object: nil) + NotificationCenter.default.post(name: VPLoginManager.loginStateDidChangeNotification, object: nil) + } + + } + +} + +extension VPLoginManager { + + ///登录状态发生变化 + @objc static let loginStateDidChangeNotification = NSNotification.Name(rawValue: "VPLoginManager.loginStateDidChangeNotification") + ///用户信息更新 + @objc static let userInfoUpdateNotification = NSNotification.Name(rawValue: "VPLoginManager.userInfoUpdateNotification") + +} + diff --git a/Veloria/Libs/Login/VPThirdSignModel.swift b/Veloria/Libs/Login/VPThirdSignModel.swift new file mode 100644 index 0000000..d14aaee --- /dev/null +++ b/Veloria/Libs/Login/VPThirdSignModel.swift @@ -0,0 +1,24 @@ +// +// VPThirdSignModel.swift +// Veloria +// +// Created by 湖南秦九 on 2025/6/3. +// + +import UIKit +import SmartCodable + +class VPThirdSignModel: VPModel, SmartCodable { + + var third_id: String? + var email: String? + + //姓 + var family_name: String? + //名 + var giving_name: String? + + var avator: String? + + var platform: VPLoginManager.LoginType? +} diff --git a/Veloria/Source/Assets.xcassets/icon/alert_icon_01.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/alert_icon_01.imageset/Contents.json new file mode 100644 index 0000000..1f805f6 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/alert_icon_01.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "提示1 1@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "提示1 1@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/alert_icon_01.imageset/提示1 1@2x.png b/Veloria/Source/Assets.xcassets/icon/alert_icon_01.imageset/提示1 1@2x.png new file mode 100644 index 0000000..bdfc71c Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/alert_icon_01.imageset/提示1 1@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/alert_icon_01.imageset/提示1 1@3x.png b/Veloria/Source/Assets.xcassets/icon/alert_icon_01.imageset/提示1 1@3x.png new file mode 100644 index 0000000..077ed63 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/alert_icon_01.imageset/提示1 1@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/alert_icon_02.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/alert_icon_02.imageset/Contents.json new file mode 100644 index 0000000..d7583b3 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/alert_icon_02.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "通知图标-切图图层@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "通知图标-切图图层@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/alert_icon_02.imageset/通知图标-切图图层@2x.png b/Veloria/Source/Assets.xcassets/icon/alert_icon_02.imageset/通知图标-切图图层@2x.png new file mode 100644 index 0000000..13ce138 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/alert_icon_02.imageset/通知图标-切图图层@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/alert_icon_02.imageset/通知图标-切图图层@3x.png b/Veloria/Source/Assets.xcassets/icon/alert_icon_02.imageset/通知图标-切图图层@3x.png new file mode 100644 index 0000000..e933332 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/alert_icon_02.imageset/通知图标-切图图层@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/alert_title_icon_01.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/alert_title_icon_01.imageset/Contents.json new file mode 100644 index 0000000..a71aa54 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/alert_title_icon_01.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Frame 6@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Frame 6@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/alert_title_icon_01.imageset/Frame 6@2x.png b/Veloria/Source/Assets.xcassets/icon/alert_title_icon_01.imageset/Frame 6@2x.png new file mode 100644 index 0000000..c5bc83a Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/alert_title_icon_01.imageset/Frame 6@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/alert_title_icon_01.imageset/Frame 6@3x.png b/Veloria/Source/Assets.xcassets/icon/alert_title_icon_01.imageset/Frame 6@3x.png new file mode 100644 index 0000000..e022c43 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/alert_title_icon_01.imageset/Frame 6@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/apple_icon_01.imageset/Apple@2x.png b/Veloria/Source/Assets.xcassets/icon/apple_icon_01.imageset/Apple@2x.png new file mode 100644 index 0000000..1e85632 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/apple_icon_01.imageset/Apple@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/apple_icon_01.imageset/Apple@3x.png b/Veloria/Source/Assets.xcassets/icon/apple_icon_01.imageset/Apple@3x.png new file mode 100644 index 0000000..e7fc413 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/apple_icon_01.imageset/Apple@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/apple_icon_01.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/apple_icon_01.imageset/Contents.json new file mode 100644 index 0000000..e1641ae --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/apple_icon_01.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Apple@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Apple@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/avatar_placeholder_icon_01.imageset/头像@2x.png b/Veloria/Source/Assets.xcassets/icon/avatar_placeholder_icon_01.imageset/头像@2x.png index 979d53c..257d64a 100644 Binary files a/Veloria/Source/Assets.xcassets/icon/avatar_placeholder_icon_01.imageset/头像@2x.png and b/Veloria/Source/Assets.xcassets/icon/avatar_placeholder_icon_01.imageset/头像@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/avatar_placeholder_icon_01.imageset/头像@3x.png b/Veloria/Source/Assets.xcassets/icon/avatar_placeholder_icon_01.imageset/头像@3x.png index c127c33..cdd481c 100644 Binary files a/Veloria/Source/Assets.xcassets/icon/avatar_placeholder_icon_01.imageset/头像@3x.png and b/Veloria/Source/Assets.xcassets/icon/avatar_placeholder_icon_01.imageset/头像@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/choice_icon_01.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/choice_icon_01.imageset/Contents.json index d9e95f1..7978ebd 100644 --- a/Veloria/Source/Assets.xcassets/icon/choice_icon_01.imageset/Contents.json +++ b/Veloria/Source/Assets.xcassets/icon/choice_icon_01.imageset/Contents.json @@ -5,12 +5,12 @@ "scale" : "1x" }, { - "filename" : "未选中@2x.png", + "filename" : "Ellipse 45@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "未选中@3x.png", + "filename" : "Ellipse 45@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/Veloria/Source/Assets.xcassets/icon/choice_icon_01.imageset/Ellipse 45@2x.png b/Veloria/Source/Assets.xcassets/icon/choice_icon_01.imageset/Ellipse 45@2x.png new file mode 100644 index 0000000..e9f12f4 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/choice_icon_01.imageset/Ellipse 45@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/choice_icon_01.imageset/Ellipse 45@3x.png b/Veloria/Source/Assets.xcassets/icon/choice_icon_01.imageset/Ellipse 45@3x.png new file mode 100644 index 0000000..af7f56e Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/choice_icon_01.imageset/Ellipse 45@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/choice_icon_01.imageset/未选中@2x.png b/Veloria/Source/Assets.xcassets/icon/choice_icon_01.imageset/未选中@2x.png deleted file mode 100644 index 1267d65..0000000 Binary files a/Veloria/Source/Assets.xcassets/icon/choice_icon_01.imageset/未选中@2x.png and /dev/null differ diff --git a/Veloria/Source/Assets.xcassets/icon/choice_icon_01.imageset/未选中@3x.png b/Veloria/Source/Assets.xcassets/icon/choice_icon_01.imageset/未选中@3x.png deleted file mode 100644 index ea2a209..0000000 Binary files a/Veloria/Source/Assets.xcassets/icon/choice_icon_01.imageset/未选中@3x.png and /dev/null differ diff --git a/Veloria/Source/Assets.xcassets/icon/close_icon_02.imageset/Close.png b/Veloria/Source/Assets.xcassets/icon/close_icon_02.imageset/Close.png new file mode 100644 index 0000000..ac4c49b Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/close_icon_02.imageset/Close.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/close_icon_02.imageset/Close@3x.png b/Veloria/Source/Assets.xcassets/icon/close_icon_02.imageset/Close@3x.png new file mode 100644 index 0000000..d15f7ac Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/close_icon_02.imageset/Close@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/close_icon_02.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/close_icon_02.imageset/Contents.json new file mode 100644 index 0000000..7f10a63 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/close_icon_02.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Close.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Close@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/login_icon_01.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/login_icon_01.imageset/Contents.json new file mode 100644 index 0000000..a5d957a --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/login_icon_01.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Frame 74@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Frame 74@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/login_icon_01.imageset/Frame 74@2x.png b/Veloria/Source/Assets.xcassets/icon/login_icon_01.imageset/Frame 74@2x.png new file mode 100644 index 0000000..da0fb54 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/login_icon_01.imageset/Frame 74@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/login_icon_01.imageset/Frame 74@3x.png b/Veloria/Source/Assets.xcassets/icon/login_icon_01.imageset/Frame 74@3x.png new file mode 100644 index 0000000..1333d52 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/login_icon_01.imageset/Frame 74@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/me_item_icon_06.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/me_item_icon_06.imageset/Contents.json new file mode 100644 index 0000000..5c4d3b1 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/me_item_icon_06.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Frame@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Frame@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/me_item_icon_06.imageset/Frame@2x.png b/Veloria/Source/Assets.xcassets/icon/me_item_icon_06.imageset/Frame@2x.png new file mode 100644 index 0000000..2182ca0 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/me_item_icon_06.imageset/Frame@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/me_item_icon_06.imageset/Frame@3x.png b/Veloria/Source/Assets.xcassets/icon/me_item_icon_06.imageset/Frame@3x.png new file mode 100644 index 0000000..61743f5 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/me_item_icon_06.imageset/Frame@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/warning_icon_01.imageset/Contents.json b/Veloria/Source/Assets.xcassets/icon/warning_icon_01.imageset/Contents.json new file mode 100644 index 0000000..6a4d508 --- /dev/null +++ b/Veloria/Source/Assets.xcassets/icon/warning_icon_01.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "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 + } +} diff --git a/Veloria/Source/Assets.xcassets/icon/warning_icon_01.imageset/Vector@2x.png b/Veloria/Source/Assets.xcassets/icon/warning_icon_01.imageset/Vector@2x.png new file mode 100644 index 0000000..fba1cb5 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/warning_icon_01.imageset/Vector@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/icon/warning_icon_01.imageset/Vector@3x.png b/Veloria/Source/Assets.xcassets/icon/warning_icon_01.imageset/Vector@3x.png new file mode 100644 index 0000000..d681dc6 Binary files /dev/null and b/Veloria/Source/Assets.xcassets/icon/warning_icon_01.imageset/Vector@3x.png differ diff --git a/Veloria/Source/Assets.xcassets/image/alert_bg_image_01.imageset/Contents.json b/Veloria/Source/Assets.xcassets/image/alert_bg_image_01.imageset/Contents.json new file mode 100644 index 0000000..04d740b --- /dev/null +++ b/Veloria/Source/Assets.xcassets/image/alert_bg_image_01.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "bg装饰@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "bg装饰@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Veloria/Source/Assets.xcassets/image/alert_bg_image_01.imageset/bg装饰@2x.png b/Veloria/Source/Assets.xcassets/image/alert_bg_image_01.imageset/bg装饰@2x.png new file mode 100644 index 0000000..337feec Binary files /dev/null and b/Veloria/Source/Assets.xcassets/image/alert_bg_image_01.imageset/bg装饰@2x.png differ diff --git a/Veloria/Source/Assets.xcassets/image/alert_bg_image_01.imageset/bg装饰@3x.png b/Veloria/Source/Assets.xcassets/image/alert_bg_image_01.imageset/bg装饰@3x.png new file mode 100644 index 0000000..33ea07d Binary files /dev/null and b/Veloria/Source/Assets.xcassets/image/alert_bg_image_01.imageset/bg装饰@3x.png differ diff --git a/Veloria/Source/en.lproj/Localizable.strings b/Veloria/Source/en.lproj/Localizable.strings index 90bc69f..e7c32f6 100644 --- a/Veloria/Source/en.lproj/Localizable.strings +++ b/Veloria/Source/en.lproj/Localizable.strings @@ -6,6 +6,8 @@ */ +"kAppName" = "Veloria"; + "Home" = "Home"; "Me" = "Me"; "All" = "All"; @@ -64,6 +66,17 @@ "Recharge" = "Recharge"; "Unlocking costs %@ coins" = "Unlocking costs %@ coins"; "Balance: %@ Coins | %@ Bonus" = "Balance: %@ Coins | %@ Bonus"; +"Check in" = "Check in"; +"Welcome to %@" = "Welcome to %@"; +"Login with Apple" = "Login with Apple"; +"Log In" = "Log In"; +"Sign Out" = "Sign Out"; +"Delet Account" = "Delet Account"; +"Account Deletion" = "Account Deletion"; +"Delete Account" = "Delete Account"; +"Delete Forever" = "Delete Forever"; +"Cancel" = "Cancel"; +"Log Out" = "Log Out"; "kHomeTitleText" = "10,000+ addictive shorts await!"; @@ -77,6 +90,7 @@ "kVipPrivilegeText4" = "Unlimited access to all series for %@ (No Ads)"; "kVipPrivilegeText5" = "The donate coins will expire in %@"; "kVipPrivilegeText6" = "Auto renew, cancel anytime"; +"kLoginAgreementText" = "By logging in you agree to: %@ & %@"; //无网提示 "kNetworkToast01" = "The service is abnormal. Check the network."; //解锁上一集提示 @@ -85,6 +99,7 @@ "kLockFailText" = "Purchase failed, please try again later!"; + "kStoreTips" = "1. Coins are virtual items and cannot be refunded. Use it for this product. 2. Gold coins will never expire, the reward coins will expire 24 hours a day. 3. Coins will be used first when unlocking episodes. If the amount is insufficient, reward coins will automatically be used. @@ -93,3 +108,21 @@ //请选择需要删除的短剧 "kToastText1" = "Please select the short plays that need to be deleted"; + +"kDeleteAccountAlertTitle" = "Confirm Account Deletion"; +"kDeleteAccountAlertText" = "This action cannot be undone."; +"kLogoutAlertTitle" = "Ready to Leave?"; +"kLogoutAlertText" = "when you sign out, your watch history will not be synced to your account."; + +"DeleteAccount_tips_1" = "Your account will be permanently deleted"; +"DeleteAccount_tips_2" = "You will not be able to log in with this user ID"; +"DeleteAccount_tips_3" = "Please log out of the account on other devices in time, otherwise the App on other devices will be unavailable."; +"DeleteAccount_tips_4" = "I accept the deletion risk and agree to delete my account"; +"DeleteAccount_tips_5" = "All the following information will be deleted"; +"DeleteAccount_tips_title_1" = "Account Data"; +"DeleteAccount_tips_text_1" = "All your personal data will be deleted including username、Email address."; +"DeleteAccount_tips_title_2" = "Balance&VIP"; +"DeleteAccount_tips_text_2" = "All your coins have been consumed and you can delete your account."; +"DeleteAccount_tips_title_3" = "History"; +"DeleteAccount_tips_text_3" = "Consumption History, Recharge History, Chapter Unlock History, My Favorite."; +"DeleteAccount_tips_title_4" = "Third Party Account Information"; diff --git a/Veloria/Veloria.entitlements b/Veloria/Veloria.entitlements new file mode 100644 index 0000000..a812db5 --- /dev/null +++ b/Veloria/Veloria.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.developer.applesignin + + Default + + +