Compare commits

..

No commits in common. "94c2315894ce78725b38f594cd3f596834f2bee8" and "6163dd1ca8d1a0dc848c62ec369b42e2c1595eb9" have entirely different histories.

62 changed files with 334 additions and 1418 deletions

47
.gitignore vendored
View File

@ -1,47 +0,0 @@
# Xcode 编译产物
DerivedData/
build/
*.xcworkspace/
*.xcuserstate
*.xcuserdatad/
xcuserdata/
UserInterfaceState.xcuserstate
*.xccheckout
*.xcscmblueprint
*.xcscmblueprint
*.xcbkptn
*.xcbkptn/
# 模拟器缓存
~/Library/Developer/CoreSimulator/
CoreSimulator/
# Pods / Carthage / Swift Package Manager
Pods/
Podfile.lock
Carthage/Build/
Package/.build/
Package.resolved
# 隐私配置、密钥、本地环境文件
*.env
*.plist.local
*.entitlements.local
secret*.txt
key*.pem
*.p12
*.mobileprovision
# 本地缓存、日志
*.log
*.swp
*.DS_Store
.DS_Store
Thumbs.db
node_modules/
npm-debug.log
# 图片临时导出、截图
*.png.orig
*.jpg.orig
screenshot/

View File

@ -295,8 +295,6 @@
30EFF3E22FDA9DEE00EB35D4 /* EmergencyContactVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30EFF3E12FDA9DEE00EB35D4 /* EmergencyContactVM.swift */; }; 30EFF3E22FDA9DEE00EB35D4 /* EmergencyContactVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30EFF3E12FDA9DEE00EB35D4 /* EmergencyContactVM.swift */; };
30EFF3E52FDAA93400EB35D4 /* PrivacyPolicyVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30EFF3E42FDAA93300EB35D4 /* PrivacyPolicyVC.swift */; }; 30EFF3E52FDAA93400EB35D4 /* PrivacyPolicyVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30EFF3E42FDAA93300EB35D4 /* PrivacyPolicyVC.swift */; };
30EFF3E72FDAA93D00EB35D4 /* PrivacyPolicyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30EFF3E62FDAA93D00EB35D4 /* PrivacyPolicyView.swift */; }; 30EFF3E72FDAA93D00EB35D4 /* PrivacyPolicyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30EFF3E62FDAA93D00EB35D4 /* PrivacyPolicyView.swift */; };
30EFF3E82FCA8C7000227D26 /* AuthenticationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 30EFF3E92FCA8C7000227D26 /* AuthenticationServices.framework */; };
55BF752D2FFE53F70055DA57 /* LocationPermissionPopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55BF752C2FFE53F70055DA57 /* LocationPermissionPopView.swift */; };
D698E9C56D6F2C152772131D /* Pods_QuickLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 475D33CAFA1E1911EB1F8D9F /* Pods_QuickLocation.framework */; }; D698E9C56D6F2C152772131D /* Pods_QuickLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 475D33CAFA1E1911EB1F8D9F /* Pods_QuickLocation.framework */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
@ -600,10 +598,8 @@
30EFF3E12FDA9DEE00EB35D4 /* EmergencyContactVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmergencyContactVM.swift; sourceTree = "<group>"; }; 30EFF3E12FDA9DEE00EB35D4 /* EmergencyContactVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmergencyContactVM.swift; sourceTree = "<group>"; };
30EFF3E42FDAA93300EB35D4 /* PrivacyPolicyVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyPolicyVC.swift; sourceTree = "<group>"; }; 30EFF3E42FDAA93300EB35D4 /* PrivacyPolicyVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyPolicyVC.swift; sourceTree = "<group>"; };
30EFF3E62FDAA93D00EB35D4 /* PrivacyPolicyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyPolicyView.swift; sourceTree = "<group>"; }; 30EFF3E62FDAA93D00EB35D4 /* PrivacyPolicyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyPolicyView.swift; sourceTree = "<group>"; };
30EFF3E92FCA8C7000227D26 /* AuthenticationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AuthenticationServices.framework; path = System/Library/Frameworks/AuthenticationServices.framework; sourceTree = SDKROOT; };
3E4359082FC48D26003470A5 /* QuickLocation.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = QuickLocation.app; sourceTree = BUILT_PRODUCTS_DIR; }; 3E4359082FC48D26003470A5 /* QuickLocation.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = QuickLocation.app; sourceTree = BUILT_PRODUCTS_DIR; };
475D33CAFA1E1911EB1F8D9F /* Pods_QuickLocation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_QuickLocation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 475D33CAFA1E1911EB1F8D9F /* Pods_QuickLocation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_QuickLocation.framework; sourceTree = BUILT_PRODUCTS_DIR; };
55BF752C2FFE53F70055DA57 /* LocationPermissionPopView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationPermissionPopView.swift; sourceTree = "<group>"; };
DA16D49AA46D4F6838340B55 /* Pods-QuickLocation.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-QuickLocation.debug.xcconfig"; path = "Target Support Files/Pods-QuickLocation/Pods-QuickLocation.debug.xcconfig"; sourceTree = "<group>"; }; DA16D49AA46D4F6838340B55 /* Pods-QuickLocation.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-QuickLocation.debug.xcconfig"; path = "Target Support Files/Pods-QuickLocation/Pods-QuickLocation.debug.xcconfig"; sourceTree = "<group>"; };
E483B9929C03809ADEDE8341 /* Pods-QuickLocation.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-QuickLocation.release.xcconfig"; path = "Target Support Files/Pods-QuickLocation/Pods-QuickLocation.release.xcconfig"; sourceTree = "<group>"; }; E483B9929C03809ADEDE8341 /* Pods-QuickLocation.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-QuickLocation.release.xcconfig"; path = "Target Support Files/Pods-QuickLocation/Pods-QuickLocation.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
@ -636,7 +632,6 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
30EFF3E82FCA8C7000227D26 /* AuthenticationServices.framework in Frameworks */,
D698E9C56D6F2C152772131D /* Pods_QuickLocation.framework in Frameworks */, D698E9C56D6F2C152772131D /* Pods_QuickLocation.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -1012,7 +1007,6 @@
30A7A9102FCAEE3D00105780 /* GroupListPopView.swift */, 30A7A9102FCAEE3D00105780 /* GroupListPopView.swift */,
30D87CDE2FDFF1A100E958FD /* QuickMessageView.swift */, 30D87CDE2FDFF1A100E958FD /* QuickMessageView.swift */,
30D87CDC2FDFF07500E958FD /* InteractionView.swift */, 30D87CDC2FDFF07500E958FD /* InteractionView.swift */,
55BF752C2FFE53F70055DA57 /* LocationPermissionPopView.swift */,
30A87A692FEF59E60095E7C6 /* SearchLocation */, 30A87A692FEF59E60095E7C6 /* SearchLocation */,
30A87A5C2FEE711C0095E7C6 /* Bubble */, 30A87A5C2FEE711C0095E7C6 /* Bubble */,
30CCDE4F2FE2782700F5214A /* SignIn */, 30CCDE4F2FE2782700F5214A /* SignIn */,
@ -1654,7 +1648,6 @@
47CD8471BE2146A2656CF27E /* Frameworks */ = { 47CD8471BE2146A2656CF27E /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
30EFF3E92FCA8C7000227D26 /* AuthenticationServices.framework */,
475D33CAFA1E1911EB1F8D9F /* Pods_QuickLocation.framework */, 475D33CAFA1E1911EB1F8D9F /* Pods_QuickLocation.framework */,
); );
name = Frameworks; name = Frameworks;
@ -2074,7 +2067,6 @@
30BF30102FED0C8E00D9CB52 /* ScheduleDetailVM.swift in Sources */, 30BF30102FED0C8E00D9CB52 /* ScheduleDetailVM.swift in Sources */,
30DA36BD2FECC5AB008D5A2C /* CreateScheduleVipPopView.swift in Sources */, 30DA36BD2FECC5AB008D5A2C /* CreateScheduleVipPopView.swift in Sources */,
305A77082FCA8C7000227D26 /* PageCollectionViewFlowLayout.swift in Sources */, 305A77082FCA8C7000227D26 /* PageCollectionViewFlowLayout.swift in Sources */,
55BF752D2FFE53F70055DA57 /* LocationPermissionPopView.swift in Sources */,
3062E8C42FCFC90F00CEF511 /* CreateGroupVipPopView.swift in Sources */, 3062E8C42FCFC90F00CEF511 /* CreateGroupVipPopView.swift in Sources */,
30D74ABA2FEA37AD0050EB2C /* ScheduleModel.swift in Sources */, 30D74ABA2FEA37AD0050EB2C /* ScheduleModel.swift in Sources */,
30CCDE512FE2785D00F5214A /* SignInVC.swift in Sources */, 30CCDE512FE2785D00F5214A /* SignInVC.swift in Sources */,
@ -2138,11 +2130,9 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = QuickLocation/QuickLocation.entitlements; CODE_SIGN_ENTITLEMENTS = QuickLocation/QuickLocation.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic;
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = XSJJKSY9FB;
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = LRDLWZ2Y83;
ENABLE_USER_SCRIPT_SANDBOXING = "$(inherited)"; ENABLE_USER_SCRIPT_SANDBOXING = "$(inherited)";
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = QuickLocation/Info.plist; INFOPLIST_FILE = QuickLocation/Info.plist;
@ -2163,10 +2153,9 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = cn.zuomeng.jisuloca; PRODUCT_BUNDLE_IDENTIFIER = cn.zuom8.jisuloca;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = jsdw_dev;
STRING_CATALOG_GENERATE_SYMBOLS = YES; STRING_CATALOG_GENERATE_SYMBOLS = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO; SUPPORTS_MACCATALYST = NO;
@ -2190,11 +2179,9 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = QuickLocation/QuickLocation.entitlements; CODE_SIGN_ENTITLEMENTS = QuickLocation/QuickLocation.entitlements;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic;
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = XSJJKSY9FB;
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = LRDLWZ2Y83;
ENABLE_USER_SCRIPT_SANDBOXING = "$(inherited)"; ENABLE_USER_SCRIPT_SANDBOXING = "$(inherited)";
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = QuickLocation/Info.plist; INFOPLIST_FILE = QuickLocation/Info.plist;
@ -2215,10 +2202,9 @@
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = cn.zuomeng.jisuloca; PRODUCT_BUNDLE_IDENTIFIER = cn.zuom8.jisuloca;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = jsdw_dev;
STRING_CATALOG_GENERATE_SYMBOLS = YES; STRING_CATALOG_GENERATE_SYMBOLS = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO; SUPPORTS_MACCATALYST = NO;

View File

@ -70,16 +70,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
print("📱 application open url: \(url.absoluteString) host: \(url.host ?? "")") print("📱 application open url: \(url.absoluteString) host: \(url.host ?? "")")
// OAuth URL code SDK onResp
if let scheme = url.scheme, scheme == "wx\(AppSettings.kAppsWXApiAppId)" || scheme == AppSettings.kAppsWXApiAppId {
if let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
let code = components.queryItems?.first(where: { $0.name == "code" })?.value {
handleWechatLoginCode(code)
return true
}
}
// host SDK // host SDK
if url.scheme?.hasPrefix("Alipay") == true || url.host == "safepay" { if url.scheme?.hasPrefix("Alipay") == true || url.host == "safepay" {
AlipaySDK.defaultService().processOrder(withPaymentResult: url) { resultDic in AlipaySDK.defaultService().processOrder(withPaymentResult: url) { resultDic in
@ -91,18 +81,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
} }
return true return true
} }
// else if url.host == "pay" { else if url.host == "pay" {
return WXApi.handleOpen(url, delegate: self) return WXApi.handleOpen(url, delegate: self)
// }
//
// return true
} }
func application(_ application: UIApplication, return true
continue userActivity: NSUserActivity,
restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
print("📱 continue userActivity: \(userActivity.webpageURL?.absoluteString ?? "")")
return WXApi.handleOpenUniversalLink(userActivity, delegate: self)
} }
func setupLocation() { func setupLocation() {
@ -157,37 +140,11 @@ extension AppDelegate {
} }
extension AppDelegate: WXApiDelegate { extension AppDelegate: WXApiDelegate {
private var handledWechatLoginCode: String? {
get { objc_getAssociatedObject(self, &AssociatedKeys.handledWechatLoginCode) as? String }
set { objc_setAssociatedObject(self, &AssociatedKeys.handledWechatLoginCode, newValue, .OBJC_ASSOCIATION_COPY_NONATOMIC) }
}
private struct AssociatedKeys {
static var handledWechatLoginCode: Void?
}
private func handleWechatLoginCode(_ code: String) {
guard code != handledWechatLoginCode else {
return
}
handledWechatLoginCode = code
LoginSessionHandler.login(type: "weixin", data: ["code": code, "code_type": ""])
}
func onReq(_ req: BaseReq) { func onReq(_ req: BaseReq) {
print(req) print(req)
} }
func onResp(_ resp: BaseResp) { func onResp(_ resp: BaseResp) {
if let authResp = resp as? SendAuthResp, authResp.errCode == 0, let code = authResp.code {
handleWechatLoginCode(code)
return
}
if resp.isKind(of: SendAuthResp.self) {
NotificationCenter.default.post(name: .resumePopupQueue, object: nil)
}
if resp.isKind(of: PayResp.self), if resp.isKind(of: PayResp.self),
let response: PayResp = resp as? PayResp { let response: PayResp = resp as? PayResp {
print("===================== WxPay =====================") print("===================== WxPay =====================")

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 KiB

View File

@ -20,9 +20,7 @@ extension DefaultsKeys {
/// IMid /// IMid
var isReLogin: DefaultsKey<Bool> { .init("isReLogin", defaultValue: false) } var isReLogin: DefaultsKey<Bool> { .init("isReLogin", defaultValue: false) }
/// ///
var isShowGuide: DefaultsKey<Bool> { .init("isShowGuide", defaultValue: true) } var guideShowVersion: DefaultsKey<Int?> { .init("guideShowVersion") }
///
var bubbleKeepTimes: DefaultsKey<Date?> { .init("bubbleKeepTimes") }
} }
/// ///
@ -37,12 +35,6 @@ extension Notification.Name {
static let ShowMemberLocationNotification = Notification.Name("ShowMemberLocationNotification") static let ShowMemberLocationNotification = Notification.Name("ShowMemberLocationNotification")
/// / /// /
static let RequestOrderPayStatusNotification = Notification.Name("RequestOrderPayStatusNotification") static let RequestOrderPayStatusNotification = Notification.Name("RequestOrderPayStatusNotification")
/// /
static let pausePopupQueue = Notification.Name("pausePopupQueue")
/// /
static let resumePopupQueue = Notification.Name("resumePopupQueue")
///
static let invalidatePopupQueue = Notification.Name("invalidatePopupQueue")
} }

View File

@ -33,7 +33,8 @@ class BaseViewController: UIViewController {
/// ///
var navTitle: String = "" { var navTitle: String = "" {
didSet { didSet {
navigationItem.title = navTitle backButton.setTitle(" \(navTitle)", for: .normal)
// navigationItem.title = navTitle
} }
} }
@ -101,13 +102,32 @@ class BaseViewController: UIViewController {
dismissItem.tintColor = .white dismissItem.tintColor = .white
navigationItem.leftBarButtonItem = dismissItem navigationItem.leftBarButtonItem = dismissItem
} else if let count = navigationController?.viewControllers.count, count > 1 { } else if let count = navigationController?.viewControllers.count, count > 1 {
let leftBackItem = UIBarButtonItem(image: UIImage(named: "Common/back"), let leftBarBtn = UIBarButtonItem (customView: backButton)
style: .plain,
target: self, //
action: #selector(leftBackClicked(_:))) let spacer = UIBarButtonItem (barButtonSystemItem: .fixedSpace, target: nil, action: nil)
navigationItem.leftBarButtonItem = leftBackItem spacer.width = -10
navigationItem.leftBarButtonItem = leftBarBtn
// navigationItem.leftBarButtonItems = [spacer, leftBarBtn]
// let leftBackItem = UIBarButtonItem(image: UIImage(named: "Common/back"),
// style: .plain,
// target: self, action: #selector(leftBackClicked(_:)))
// leftBackItem.tintColor = .white
// navigationItem.leftBarButtonItem = leftBackItem
} }
} }
lazy var backButton: UIButton = {
let button = UIButton (type: .custom)
button.frame = CGRectMake (0, 0, 200, 30)
button.setImage(UIImage(named: "Common/back"), for: .normal)
button.titleLabel?.font = .systemFont(ofSize: 18, weight: .medium)
button.contentHorizontalAlignment = .left
button.setTitleColor(ThemeManager.shared.color.titleColor, for: .normal)
button.addTarget(self, action: #selector(leftBackClicked(_:)), for: .touchUpInside)
return button
}()
} }
// MARK: - // MARK: -

View File

@ -50,7 +50,6 @@ final class MainTabBarController: UITabBarController {
viewControllers = navControllers viewControllers = navControllers
tabBar.isHidden = true tabBar.isHidden = true
tabBar.removeFromSuperview()
for nav in navControllers { for nav in navControllers {
nav.delegate = self nav.delegate = self
@ -72,7 +71,7 @@ final class MainTabBarController: UITabBarController {
NSLayoutConstraint.activate([ NSLayoutConstraint.activate([
customTabBar.leadingAnchor.constraint(equalTo: view.leadingAnchor), customTabBar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
customTabBar.trailingAnchor.constraint(equalTo: view.trailingAnchor), customTabBar.trailingAnchor.constraint(equalTo: view.trailingAnchor),
customTabBar.bottomAnchor.constraint(equalTo: view.bottomAnchor), customTabBar.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -41),
customTabBar.heightAnchor.constraint(equalToConstant: tabBarHeight) customTabBar.heightAnchor.constraint(equalToConstant: tabBarHeight)
]) ])
} }

View File

@ -92,20 +92,6 @@ class AppContextManager: NSObject {
Defaults[\.loginToken] = token Defaults[\.loginToken] = token
} }
/// 0 1SOS 2
public func updateAccountStatus(_ status: Int) {
guard var account = self.account else { return }
account.status = status
saveAccount(account)
}
/// 0 1 2
public func updateAccountMood(_ mood: Int) {
guard var account = self.account else { return }
account.mood = mood
saveAccount(account)
}
public func deleteAccount() { public func deleteAccount() {
Defaults[\.loginToken] = nil Defaults[\.loginToken] = nil
Defaults[\.userConfig] = nil Defaults[\.userConfig] = nil

View File

@ -68,8 +68,6 @@ struct SystemConfigModel: Mappable {
var popupConfig: PopupWindowConfigModel? var popupConfig: PopupWindowConfigModel?
/// ///
var timeConfig: PopupWindowTimeModel? var timeConfig: PopupWindowTimeModel?
///
var shareConfig: WxShareConfigModel?
/// ///
var chatWarning: String = "" var chatWarning: String = ""
@ -77,12 +75,6 @@ struct SystemConfigModel: Mappable {
/// banner /// banner
var groupBannerList: [String] = [] var groupBannerList: [String] = []
///
var guideDisplay: Bool = true
///
var globalDisplay: Bool = true
init?(map: Map) { init?(map: Map) {
} }
@ -92,18 +84,15 @@ struct SystemConfigModel: Mappable {
groupBannerList <- map["client.team.ad", nested: false] groupBannerList <- map["client.team.ad", nested: false]
popupConfig <- map["client.popup.display", nested: false] popupConfig <- map["client.popup.display", nested: false]
timeConfig <- map["client.time.setting", nested: false] timeConfig <- map["client.time.setting", nested: false]
shareConfig <- map["client.weixin.share", nested: false]
guideDisplay <- map["client.guide_display", nested: false]
globalDisplay <- map["client.global_display", nested: false]
} }
} }
struct PopupWindowConfigModel: Mappable { struct PopupWindowConfigModel: Mappable {
/// vip /// vip
var pay_pop: Bool = true var pay_pop: Bool = false
/// ///
var search_phone: Bool = true var search_phone: Bool = false
init?(map: Map) { init?(map: Map) {
@ -143,28 +132,3 @@ struct PopupWindowTimeModel: Mappable {
pay_pop_type <- map["pay_pop_type"] pay_pop_type <- map["pay_pop_type"]
} }
} }
struct WxShareConfigModel: Mappable {
///
var link: String = ""
///
var title: String = ""
///
var content: String = ""
///
var image: String = ""
init?(map: Map) {
}
mutating func mapping(map: Map) {
link <- map["link"]
title <- map["title"]
content <- map["content"]
image <- map["image"]
}
}

View File

@ -10,9 +10,6 @@ import Moya
import SwiftyJSON import SwiftyJSON
import RxSwift import RxSwift
import CommonCrypto import CommonCrypto
#if !targetEnvironment(simulator)
import GeYanSdk
#endif
class ApiManager: NSObject { class ApiManager: NSObject {
@ -160,8 +157,6 @@ extension ApiManager {
// MARK: - Token // MARK: - Token
private func handleTokenExpired(msg: String?) { private func handleTokenExpired(msg: String?) {
MainAsync { MainAsync {
NotificationCenter.default.post(name: .invalidatePopupQueue, object: nil)
GeYanSdk.deletePreResultCache()
AppContextManager.shared.deleteAccount() AppContextManager.shared.deleteAccount()
GroupIMService.shared.logout() GroupIMService.shared.logout()
DLToast.showError(text: msg ?? "登录失效,请重新登录!") { DLToast.showError(text: msg ?? "登录失效,请重新登录!") {

View File

@ -183,8 +183,6 @@ struct GroupMemberModel: Mappable, Equatable {
} }
return UIImage(named: "VipIcon/\(level)") ?? UIImage() return UIImage(named: "VipIcon/\(level)") ?? UIImage()
} }
/// 0 1SOS 2
var status: Int = 0
/// 线 /// 线
var is_online: Bool = false var is_online: Bool = false
/// ///
@ -230,7 +228,6 @@ struct GroupMemberModel: Mappable, Equatable {
last_position <- map["last_position"] last_position <- map["last_position"]
is_online <- map["is_online"] is_online <- map["is_online"]
last_active_time <- map["last_active_time"] last_active_time <- map["last_active_time"]
status <- map["status"]
} }
} }

View File

@ -2,10 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>com.apple.developer.applesignin</key>
<array>
<string>Default</string>
</array>
<key>com.apple.developer.associated-domains</key> <key>com.apple.developer.associated-domains</key>
<array> <array>
<string>applinks:smartdrive.zuom8.cn</string> <string>applinks:smartdrive.zuom8.cn</string>

View File

@ -398,9 +398,9 @@ class CreateGroupView: UIView {
lazy var submitBtn: UIButton = { lazy var submitBtn: UIButton = {
let btn = UIButton(type: .custom) let btn = UIButton(type: .custom)
btn.setTitle("创建", for: .normal) btn.setTitle("创建", for: .normal)
btn.setTitleColor(.white, for: .normal) btn.setTitleColor(UIColor(hexStr: "#0F2846"), for: .normal)
btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium) btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
btn.setBackgroundImage(UIImage(named: "Common/button_bg_2"), for: .normal) btn.setBackgroundImage(UIImage(named: "Common/gradient_bg"), for: .normal)
btn.cornerRadius = 25 btn.cornerRadius = 25
return btn return btn

View File

@ -87,8 +87,6 @@ class CreateGroupViewModel {
} }
}, onError: { (error) in }, onError: { (error) in
guard let code = error.underlyingError?.code else { return } guard let code = error.underlyingError?.code else { return }
guard let systemConfig = AppContextManager.shared.systemConfig, systemConfig.globalDisplay else { return }
if code == 20009 { // "" if code == 20009 { // ""
CreateGroupVipPopView.show() CreateGroupVipPopView.show()
} }

View File

@ -49,10 +49,7 @@ final class GroupChatVC: BaseViewController {
// + IM SDK // + IM SDK
requestGroupInfoByKey() requestGroupInfoByKey()
GroupIMService.shared.ensureLogin { [weak self] success in viewModel.loadMessages()
guard let self = self, success else { return }
self.viewModel.loadMessages()
}
// //
guard let config = AppContextManager.shared.systemConfig else { return } guard let config = AppContextManager.shared.systemConfig else { return }
@ -99,7 +96,7 @@ final class GroupChatVC: BaseViewController {
// / // /
self.rootView.dismissAllPanels(excludeTextField: true) self.rootView.dismissAllPanels(excludeTextField: true)
UIView.animate(withDuration: duration) { UIView.animate(withDuration: duration) {
self.rootView.bottomBar.layoutChain.bottom(height + 20) self.rootView.bottomBar.layoutChain.bottom(height + kSafeBottomMargin + 20)
} }
self.scrollToBottom() self.scrollToBottom()
}) })
@ -154,7 +151,7 @@ final class GroupChatVC: BaseViewController {
private func scrollToBottom() { private func scrollToBottom() {
let count = dataSource.sectionModels.first?.items.count ?? 0 let count = dataSource.sectionModels.first?.items.count ?? 0
guard count > 0 else { return } guard count > 0 else { return }
DispatchQueue.main.async { DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.rootView.tableView.layoutIfNeeded() self.rootView.tableView.layoutIfNeeded()
let indexPath = IndexPath(row: count - 1, section: 0) let indexPath = IndexPath(row: count - 1, section: 0)
self.rootView.tableView.scrollToRow(at: indexPath, at: .bottom, animated: false) self.rootView.tableView.scrollToRow(at: indexPath, at: .bottom, animated: false)
@ -295,7 +292,7 @@ final class GroupChatVC: BaseViewController {
let offset: CGFloat = show ? 252 : 0 let offset: CGFloat = show ? 252 : 0
UIView.animate(withDuration: 0.25) { UIView.animate(withDuration: 0.25) {
self.rootView.bottomBar.layoutChain.bottom(show ? offset - self.rootView.bottomBar.dl.height : kSafeBottomMargin + 20) self.rootView.bottomBar.layoutChain.bottom(show ? offset - self.rootView.bottomBar.dl.height : kSafeBottomMargin + 20)
self.rootView.voiceRecordView.layoutChain.bottom(offset - 252) self.rootView.voiceRecordView.layoutChain.bottom(offset - 252 + kSafeBottomMargin)
} }
scrollToBottom() scrollToBottom()
} }
@ -309,7 +306,7 @@ final class GroupChatVC: BaseViewController {
self.rootView.emojiPanelView.isHidden = !show self.rootView.emojiPanelView.isHidden = !show
let offset: CGFloat = show ? 220 : 0 let offset: CGFloat = show ? 220 : 0
UIView.animate(withDuration: 0.25) { UIView.animate(withDuration: 0.25) {
self.rootView.bottomBar.layoutChain.bottom(20 + offset) self.rootView.bottomBar.layoutChain.bottom(kSafeBottomMargin + 20 + offset)
} }
// completion: { _ in // completion: { _ in
// let offset: CGFloat = self.rootView.tableView.contentSize.height // let offset: CGFloat = self.rootView.tableView.contentSize.height

View File

@ -33,8 +33,6 @@ class GroupMemberListVC: BaseViewController {
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
guard let systemConfig = AppContextManager.shared.systemConfig, systemConfig.globalDisplay else { return }
rootView.unlockVipMaskView.isHidden = AppContextManager.shared.vip > 1 rootView.unlockVipMaskView.isHidden = AppContextManager.shared.vip > 1
} }

View File

@ -220,9 +220,7 @@ final class GroupViewController: BaseViewController {
GroupService.groupInfo().subscribe { response in GroupService.groupInfo().subscribe { response in
guard let model = response.model else { return } guard let model = response.model else { return }
self.viewModel.groupList = model.groups self.viewModel.groupList = model.groups
DispatchQueue.global(qos: .default).async { [weak self] in self.loadIMData()
self?.loadIMData()
}
}.disposed(by: disposeBag) }.disposed(by: disposeBag)
} }
} }

View File

@ -9,7 +9,6 @@ import UIKit
import ObjectMapper import ObjectMapper
import RxSwift import RxSwift
import RxCocoa import RxCocoa
import Kingfisher
class InviteJoinVC: BaseViewController { class InviteJoinVC: BaseViewController {
@ -29,64 +28,8 @@ class InviteJoinVC: BaseViewController {
// //
rootView.shareAppBtn.rx.tap.subscribe(onNext: { _ in rootView.shareAppBtn.rx.tap.subscribe(onNext: { _ in
SharePopView.show() let url = "https://smartdrive.zuom8.cn/jisu/share/user/"
}).disposed(by: disposeBag) SharePopView.show(shareURL: url)
//
rootView.shareCodeBtn.rx.tap.subscribe(onNext: { [weak self] in
guard let self = self else { return }
guard let config = AppContextManager.shared.systemConfig,
let shareConfig = config.shareConfig else { return }
DLToast.showLoading()
let fallbackImage = UIImage(named: "Common/logo108")
let imageURL: URL? = {
if shareConfig.image.isEmpty { return nil }
return URL(string: shareConfig.image)
}()
let sendMessage: (UIImage?) -> Void = { [weak self] thumbImage in
guard let self = self else { return }
DLToast.dismiss()
guard let screenshot = self.rootView.inviteInfoView.takeScreenshot(),
let imageData = screenshot.pngData() else {
DLToast.showError(text: "分享失败")
return
}
let message = WXMediaMessage()
message.title = "邀请加入圈子"
message.description = shareConfig.content
if let thumb = thumbImage {
message.setThumbImage(thumb)
}
let imageObject = WXImageObject()
imageObject.imageData = imageData
message.mediaObject = imageObject
let req = SendMessageToWXReq()
req.bText = false
req.message = message
req.scene = 0
WXApi.send(req)
}
if let url = imageURL {
KingfisherManager.shared.retrieveImage(with: url) { result in
switch result {
case .success(let value):
sendMessage(value.image)
case .failure:
sendMessage(fallbackImage)
}
}
} else {
sendMessage(fallbackImage)
}
}).disposed(by: disposeBag) }).disposed(by: disposeBag)
guard let model = groupInModel else { return } guard let model = groupInModel else { return }

View File

@ -91,7 +91,7 @@ class InviteJoinView: UIView {
inviteInfoView.layoutChain inviteInfoView.layoutChain
.topToBottomOfView(groupIcon, offset: 50) .topToBottomOfView(groupIcon, offset: 50)
.edgesHorzontal(30) .edgesHorzontal(30)
// .bottomToTopOfView(shareAppBtn, offset: -32) .bottomToTopOfView(shareAppBtn, offset: -32)
inviteInfoTitleLab.layoutChain inviteInfoTitleLab.layoutChain
.top(20) .top(20)
@ -265,9 +265,10 @@ class InviteJoinView: UIView {
lazy var shareCodeBtn: UIButton = { lazy var shareCodeBtn: UIButton = {
let btn = UIButton(type: .custom) let btn = UIButton(type: .custom)
btn.setTitle("分享邀请码", for: .normal) btn.setTitle("分享邀请码", for: .normal)
btn.setTitleColor(.white, for: .normal)
btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium) btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
btn.setBackgroundImage(UIImage(named: "Common/button_bg_2"), for: .normal) btn.setTitleColor(UIColor(hexStr: "#0F2846"), for: .normal)
btn.backgroundColor = .clear
btn.setBackgroundImage(UIImage(named: "Common/gradient_bg"), for: .normal)
btn.cornerRadius = 25 btn.cornerRadius = 25
return btn return btn
}() }()

View File

@ -8,7 +8,6 @@
import UIKit import UIKit
import RxSwift import RxSwift
import RxCocoa import RxCocoa
import SwiftyUserDefaults
class CreateBubbleVC: BaseViewController { class CreateBubbleVC: BaseViewController {
@ -32,13 +31,6 @@ class CreateBubbleVC: BaseViewController {
doneBtn.rx.tap.subscribe(onNext: { [weak self] in doneBtn.rx.tap.subscribe(onNext: { [weak self] in
guard let self = self else { return } guard let self = self else { return }
guard let systemConfig = AppContextManager.shared.systemConfig, systemConfig.globalDisplay else {
let hours = self.rootView.createBubbleTiemView.selectedHour.value
requestSetBubble(enable: true, keep_time: hours)
return
}
if AppContextManager.shared.vip > 1 { if AppContextManager.shared.vip > 1 {
let hours = self.rootView.createBubbleTiemView.selectedHour.value let hours = self.rootView.createBubbleTiemView.selectedHour.value
requestSetBubble(enable: true, keep_time: hours) requestSetBubble(enable: true, keep_time: hours)
@ -57,13 +49,6 @@ class CreateBubbleVC: BaseViewController {
self.requestSetBubble(enable: false, keep_time: -1) self.requestSetBubble(enable: false, keep_time: -1)
}, cancelText: "取消") }, cancelText: "取消")
}).disposed(by: disposeBag) }).disposed(by: disposeBag)
guard AppContextManager.shared.status == 2, let endDate = Defaults[\.bubbleKeepTimes] else { return }
self.rootView.navTitleLabel.text = "活动气泡"
self.rootView.createBubbleDoneView.messageLab.text = self.rootView.createBubbleTipsView.messageText
self.rootView.createBubbleTipsView.isHidden = true
self.rootView.createBubbleDoneView.isHidden = false
self.rootView.createBubbleDoneView.startCountdown(endDate: endDate)
} }
private func requestSetBubble(enable: Bool, keep_time: Int) { private func requestSetBubble(enable: Bool, keep_time: Int) {
@ -72,17 +57,13 @@ class CreateBubbleVC: BaseViewController {
DLToast.dismiss() DLToast.dismiss()
guard enable else { guard enable else {
DLToast.show(text: "气泡已弹出") { DLToast.show(text: "气泡已弹出") {
Defaults[\.bubbleKeepTimes] = nil
AppContextManager.shared.updateAccountStatus(0)
AppRouter.shared.popOrDismiss() AppRouter.shared.popOrDismiss()
} }
return return
} }
AppContextManager.shared.updateAccountStatus(2)
self.rootView.navTitleLabel.text = "活动气泡" self.rootView.navTitleLabel.text = "活动气泡"
self.rootView.createBubbleDoneView.messageLab.text = self.rootView.createBubbleTipsView.messageText self.rootView.createBubbleDoneView.messageLab.text = self.rootView.createBubbleTipsView.messageText
let endDate = Calendar.current.date(byAdding: .hour, value: keep_time, to: Date()) ?? Date() let endDate = Calendar.current.date(byAdding: .hour, value: keep_time, to: Date()) ?? Date()
Defaults[\.bubbleKeepTimes] = endDate
self.rootView.createBubbleDoneView.startCountdown(endDate: endDate) self.rootView.createBubbleDoneView.startCountdown(endDate: endDate)
self.rootView.createBubbleTipsView.isHidden = true self.rootView.createBubbleTipsView.isHidden = true
self.rootView.createBubbleDoneView.isHidden = false self.rootView.createBubbleDoneView.isHidden = false

View File

@ -9,7 +9,6 @@ import UIKit
import UIKit import UIKit
import RxSwift import RxSwift
import RxCocoa import RxCocoa
import Lottie
class GroupMemberView: UIView { class GroupMemberView: UIView {
@ -185,13 +184,6 @@ class GroupMemberCell: UITableViewCell {
onlineStatusLab.text = model.lastUpdateText onlineStatusLab.text = model.lastUpdateText
onlineStatusLab.textColor = UIColor(hexStr: "#999999") onlineStatusLab.textColor = UIColor(hexStr: "#999999")
} }
// sos
sosLottieView.isHidden = model.status != 1
model.status == 1 ? sosLottieView.play() : sosLottieView.stop()
//
shieldIconView.isHidden = model.status != 2
} }
private func setupSubviews() { private func setupSubviews() {
@ -271,7 +263,7 @@ class GroupMemberCell: UITableViewCell {
tagView.layoutChain tagView.layoutChain
.leftToRightOfView(nameLab, offset: 4) .leftToRightOfView(nameLab, offset: 4)
.centerY(nameLab) .centerY(nameLab)
.height(30) .height(20)
ownView.layoutChain.height(15) ownView.layoutChain.height(15)
@ -362,10 +354,10 @@ class GroupMemberCell: UITableViewCell {
}() }()
lazy var tagView: UIStackView = { lazy var tagView: UIStackView = {
let view = UIStackView(arrangedSubviews: [ownView, offlineView, sosLottieView, shieldIconView]) let view = UIStackView(arrangedSubviews: [ownView, offlineView])
view.axis = .horizontal view.axis = .horizontal
view.alignment = .center view.alignment = .center
view.spacing = 5 view.spacing = 0
view.backgroundColor = .clear view.backgroundColor = .clear
return view return view
}() }()
@ -409,28 +401,6 @@ class GroupMemberCell: UITableViewCell {
return view return view
}() }()
// sos
lazy var sosLottieView: LottieAnimationView = {
let view = LottieAnimationView(name: "siren")
view.loopMode = .loop
view.isHidden = true
view.layoutChain.width(26).height(26)
return view
}()
//
lazy var shieldIconView: UIImageView = {
let view = UIImageView(image: UIImage(named: "Home/shield"))
view.contentMode = .scaleAspectFill
view.isHidden = true
view.layoutChain.width(20).height(20)
return view
}()
// 线 // 线
lazy var onlineView: UIView = { lazy var onlineView: UIView = {
let view = UIView() let view = UIView()

View File

@ -58,7 +58,7 @@ class HomeView: UIView {
mv.showsScale = false mv.showsScale = false
mv.isRotateEnabled = false mv.isRotateEnabled = false
mv.isRotateCameraEnabled = false mv.isRotateCameraEnabled = false
DispatchQueue.main.async { mv.logoCenter = CGPoint(x: kScreenWidth - 50, y: kScreenHeight / 2 + 65) } DispatchQueue.main.async { mv.logoCenter = CGPoint(x: 15, y: mv.bounds.height / 2) }
return mv return mv
}() }()
#else #else
@ -92,6 +92,7 @@ class HomeView: UIView {
}) })
.disposed(by: disposeBag) .disposed(by: disposeBag)
groupMemberView.tableView.rx.setDelegate(self) groupMemberView.tableView.rx.setDelegate(self)
.disposed(by: disposeBag) .disposed(by: disposeBag)
@ -99,11 +100,6 @@ class HomeView: UIView {
searchLottieView.rx.tapGesture.subscribe { _ in searchLottieView.rx.tapGesture.subscribe { _ in
AppRouter.push(Route.searchLocation) AppRouter.push(Route.searchLocation)
}.disposed(by: disposeBag) }.disposed(by: disposeBag)
//
warningIconView.rx.tapGesture.subscribe { _ in
LocationPermissionPopView.show()
}.disposed(by: disposeBag)
} }
private func setupUI() { private func setupUI() {
@ -122,7 +118,6 @@ class HomeView: UIView {
addSubview(messageView) addSubview(messageView)
addSubview(messageStackView) addSubview(messageStackView)
addSubview(toolsView) addSubview(toolsView)
addSubview(warningIconView)
addSubview(searchLottieView) addSubview(searchLottieView)
addSubview(locationView) addSubview(locationView)
locationView.addSubview(locationIconView) locationView.addSubview(locationIconView)
@ -188,12 +183,6 @@ class HomeView: UIView {
.width(40) .width(40)
.centerY(self, offset: -50) .centerY(self, offset: -50)
warningIconView.layoutChain
.bottomToTopOfView(toolsView, offset: -10)
.centerX(toolsView)
.width(28)
.heightToWidth(1)
searchLottieView.layoutChain searchLottieView.layoutChain
.centerY(toolsView) .centerY(toolsView)
.right() .right()
@ -202,7 +191,7 @@ class HomeView: UIView {
locationView.layoutChain locationView.layoutChain
.right(15) .right(15)
.bottomToView(toolsView, offset: -10) .bottomToView(toolsView)
.width(40) .width(40)
.height(40) .height(40)
@ -247,7 +236,6 @@ class HomeView: UIView {
quickMessageView.isHidden = false quickMessageView.isHidden = false
interactionView.isHidden = false interactionView.isHidden = false
toolsView.isHidden = true toolsView.isHidden = true
searchLottieView.isHidden = true
quickMessageView.frame.origin.y = kScreenHeight - 384 - 93 quickMessageView.frame.origin.y = kScreenHeight - 384 - 93
interactionView.frame.origin.y = kScreenHeight - 384 interactionView.frame.origin.y = kScreenHeight - 384
} }
@ -258,7 +246,6 @@ class HomeView: UIView {
quickMessageView.isHidden = true quickMessageView.isHidden = true
interactionView.isHidden = true interactionView.isHidden = true
toolsView.isHidden = false toolsView.isHidden = false
searchLottieView.isHidden = AppContextManager.shared.systemConfig?.globalDisplay == false
onDismissPanel?() onDismissPanel?()
} }
@ -648,15 +635,6 @@ class HomeView: UIView {
return view return view
}() }()
// MARK: - warning
lazy var warningIconView: UIImageView = {
let view = UIImageView()
view.image = UIImage(named: "Home/warning")
view.contentMode = .scaleAspectFill
view.isHidden = true
return view
}()
// MARK: - // MARK: -
lazy var toolsView: UIStackView = { lazy var toolsView: UIStackView = {
let view = UIStackView(arrangedSubviews: [bubbleView, signInView, sosView, scheduleView]) let view = UIStackView(arrangedSubviews: [bubbleView, signInView, sosView, scheduleView])

View File

@ -46,14 +46,13 @@ class HomeViewController: BaseViewController {
private var subscribedMemberIds: [String] = [] private var subscribedMemberIds: [String] = []
/// ///
private var isMemberPanelShown = false private var isMemberPanelShown = false
private var isSOSPlaying = false
/// MQTT userId Date /// MQTT userId Date
private var lastUpdateTimes: [String: Date] = [:] private var lastUpdateTimes: [String: Date] = [:]
/// 线 /// 线
private var offlineCheckTimer: Timer? private var offlineCheckTimer: Timer?
private var popupQueue: PopupQueueManager? private var popupQueue: PopupQueueManager?
private static var sosPlayerKey: UInt8 = 0 private var sosPlayerKey: UInt8 = 0
private var groupRefreshWorkItem: DispatchWorkItem? private var groupRefreshWorkItem: DispatchWorkItem?
private var groupSwitchWorkItem: DispatchWorkItem? private var groupSwitchWorkItem: DispatchWorkItem?
@ -74,6 +73,8 @@ class HomeViewController: BaseViewController {
setupHeading() setupHeading()
reactiveAction() reactiveAction()
requestUserConfig()
rootView.quickMessageView.tagListView.delegate = self rootView.quickMessageView.tagListView.delegate = self
// MQTT // MQTT
UIDevice.current.isBatteryMonitoringEnabled = true UIDevice.current.isBatteryMonitoringEnabled = true
@ -83,13 +84,6 @@ class HomeViewController: BaseViewController {
override func viewDidAppear(_ animated: Bool) { override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated) super.viewDidAppear(animated)
let manager = AuthorizeManager.manager(type: .locationAlways)
rootView.warningIconView.isHidden = manager?.authorizeStatus() == .authorized
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
// sosPlayer?.stop()
} }
// MARK: - MQTT // MARK: - MQTT
@ -195,27 +189,9 @@ class HomeViewController: BaseViewController {
// User Config // User Config
NotificationCenter.default.rx.notification(.RefreshUserConfigNotification, object: nil) NotificationCenter.default.rx.notification(.RefreshUserConfigNotification, object: nil)
.startWith(Notification(name: .RefreshUserConfigNotification)) .subscribe { [weak self] notification in
.do(onNext: { [weak self] _ in self?.requestUserConfig()
self?.popupQueue = nil }.disposed(by: disposeBag)
})
.flatMapLatest { _ in
SystemService.userConfig()
}
.subscribe(onNext: { [weak self] response in
guard let self = self, let model = response.model else { return }
Defaults[\.loginToken] = model.token
AppContextManager.shared.systemConfig = model.config
rootView.searchLottieView.isHidden = model.config?.globalDisplay == false
self.getUserIMToken()
self.requestUserInfo { [weak self] in
self?.requestGroupInfo()
}
self.requestNotice()
self.popupQueue = nil
self.popupQueue = PopupQueueManager()
self.popupQueue?.start(from: self)
}).disposed(by: disposeBag)
// //
NotificationCenter.default.rx.notification(.RefreshGroupInfoNotification, object: nil) NotificationCenter.default.rx.notification(.RefreshGroupInfoNotification, object: nil)
@ -272,8 +248,10 @@ class HomeViewController: BaseViewController {
} }
// //
rootView.interactionView.onShare = { rootView.interactionView.onShare = { [weak self] in
SharePopView.show() guard let self = self, let member = self.rootView.interactionView.currentMember else { return }
let url = "https://smartdrive.zuom8.cn/jisu/share/user/\(member.id)"
SharePopView.show(shareURL: url)
} }
} }
@ -312,6 +290,25 @@ class HomeViewController: BaseViewController {
// MARK: - API // MARK: - API
///
func requestUserConfig() {
SystemService.userConfig().subscribe(onNext: { response in
guard let model = response.model else { return }
Defaults[\.loginToken] = model.token
AppContextManager.shared.systemConfig = model.config
self.getUserIMToken()
//
self.requestUserInfo { [weak self] in
self?.requestGroupInfo()
}
//
self.requestNotice()
//
self.popupQueue = PopupQueueManager()
self.popupQueue?.start(from: self)
}).disposed(by: disposeBag)
}
/// IM Token /// IM Token
func getUserIMToken() { func getUserIMToken() {
DLToast.showLoading() DLToast.showLoading()
@ -469,8 +466,8 @@ class HomeViewController: BaseViewController {
let newMembers = others + [me] let newMembers = others + [me]
members = newMembers members = newMembers
currentUserMember = me currentUserMember = me
// members 线 GPS // members 线
let onlineMembers = newMembers.filter { $0.isOnline && !$0.isCurrentUser } let onlineMembers = newMembers.filter { $0.isOnline }
guard let mapView = rootView.mapView else { return } guard let mapView = rootView.mapView else { return }
@ -480,33 +477,10 @@ class HomeViewController: BaseViewController {
let toRemove = existing.filter { !onlineIDs.contains($0.member.id) } let toRemove = existing.filter { !onlineIDs.contains($0.member.id) }
mapView.removeAnnotations(toRemove) mapView.removeAnnotations(toRemove)
if toRemove.contains(where: { $0 === currentUserAnnotation }) {
currentUserAnnotation = nil
}
let toAdd = onlineMembers.filter { !existingIDs.contains($0.id) } let toAdd = onlineMembers.filter { !existingIDs.contains($0.id) }
let annotations = toAdd.map { MemberAnnotation(member: $0) } let annotations = toAdd.map { MemberAnnotation(member: $0) }
mapView.addAnnotations(annotations) mapView.addAnnotations(annotations)
if currentUserAnnotation == nil,
let me = currentUserMember,
let loc = lastLocation,
CLLocationCoordinate2DIsValid(loc.coordinate) {
let updatedMe = CircleMember(
id: "current",
name: me.name,
avatar: me.avatar,
isOnline: true,
isOwner: false,
coordinate: loc.coordinate,
address: me.address,
heading: me.heading,
lastUpdateTime: me.lastUpdateTime,
battery: me.battery
)
currentUserMember = updatedMe
mapView.addAnnotation(MemberAnnotation(member: updatedMe))
}
#endif #endif
} }
@ -664,37 +638,17 @@ extension HomeViewController {
} }
} }
} }
case "bubble": //
guard let userId = msg.data?.user_id else { return }
DispatchQueue.main.async { [weak self] in
self?.viewModel.updateMemberStatus(userId: userId, status: 2)
self?.removeAnnotation(userId: userId)
}
case "sos": // case "sos": //
self.requestGroupInfo(isDefaultGroup: false)
guard let userId = msg.data?.user_id, guard let userId = msg.data?.user_id,
userId != AppContextManager.shared.userId, userId != AppContextManager.shared.userId else { return }
topic.contains(userId) else { return } playSOSAlarm()
DispatchQueue.main.async { [weak self] in rootView.sosPopView.isHidden = false
guard let self = self else { return } rootView.sosPopView.play(toFrame: 30.0) { completed in
self.viewModel.updateMemberStatus(userId: userId, status: 1) guard completed else { return }
guard !self.isSOSPlaying else { return }
self.isSOSPlaying = true
self.playSOSAlarm()
self.rootView.sosPopView.isHidden = false
self.rootView.sosPopView.play { completed in
self.rootView.sosPopView.stop() self.rootView.sosPopView.stop()
self.rootView.sosPopView.isHidden = true self.rootView.sosPopView.isHidden = true
} }
DispatchQueue.main.asyncAfter(deadline: .now() + 15) { [weak self] in
self?.sosPlayer?.stop()
self?.sosPlayer = nil
self?.rootView.sosPopView.stop()
self?.rootView.sosPopView.isHidden = true
self?.isSOSPlaying = false
}
}
case "join": // case "join": //
guard let gk = msg.data?.group_key, guard let gk = msg.data?.group_key,
let defaultGk = self.viewModel.groupModel?.default_group_key, let defaultGk = self.viewModel.groupModel?.default_group_key,
@ -844,22 +798,6 @@ extension HomeViewController: MAMapViewDelegate {
if let ann = currentUserAnnotation { if let ann = currentUserAnnotation {
ann.coordinate = coordinate ann.coordinate = coordinate
} else if let me = currentUserMember {
let updatedMe = CircleMember(
id: "current",
name: me.name,
avatar: me.avatar,
isOnline: true,
isOwner: false,
coordinate: coordinate,
address: me.address,
heading: me.heading,
lastUpdateTime: me.lastUpdateTime,
battery: me.battery
)
currentUserMember = updatedMe
let annotation = MemberAnnotation(member: updatedMe)
mapView.addAnnotation(annotation)
} }
if !isMemberPanelShown { if !isMemberPanelShown {
@ -873,8 +811,8 @@ extension HomeViewController: MAMapViewDelegate {
extension HomeViewController { extension HomeViewController {
private var sosPlayer: AVAudioPlayer? { private var sosPlayer: AVAudioPlayer? {
get { return objc_getAssociatedObject(self, &HomeViewController.sosPlayerKey) as? AVAudioPlayer } get { return objc_getAssociatedObject(self, &sosPlayerKey) as? AVAudioPlayer }
set { objc_setAssociatedObject(self, &HomeViewController.sosPlayerKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } set { objc_setAssociatedObject(self, &sosPlayerKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) }
} }
private func playSOSAlarm() { private func playSOSAlarm() {
@ -897,10 +835,14 @@ extension HomeViewController {
return return
} }
print("✅ SOS: playing alarm") print("✅ SOS: playing alarm")
player.numberOfLoops = -1 player.numberOfLoops = 0
player.volume = 1.0 player.volume = 1.0
player.play() player.play()
self.sosPlayer = player self.sosPlayer = player
DispatchQueue.main.asyncAfter(deadline: .now() + 15) { [weak self] in
self?.sosPlayer?.stop()
self?.sosPlayer = nil
}
} }
} }

View File

@ -144,12 +144,6 @@ class HomeViewModel {
setMemberList(updated) setMemberList(updated)
} }
func updateMemberStatus(userId: String, status: Int) {
guard let index = memberList.firstIndex(where: { $0.user_id == userId }) else { return }
memberList[index].status = status
sectionedItems.onNext(memberList.mapSection())
}
// MARK: - Init // MARK: - Init
init() { init() {
output = Output( output = Output(

View File

@ -108,10 +108,7 @@ class InteractionView: UIView {
let pages = (items.count + InteractionView.emojiPerPage - 1) / InteractionView.emojiPerPage let pages = (items.count + InteractionView.emojiPerPage - 1) / InteractionView.emojiPerPage
self.emojiPageControl.numberOfPages = max(pages, 1) self.emojiPageControl.numberOfPages = max(pages, 1)
self.emojiPageControl.currentPage = 0 self.emojiPageControl.currentPage = 0
self.emojiCollectionView.layoutIfNeeded()
DispatchQueue.main.async {
self.emojiCollectionView.setContentOffset(.zero, animated: false) self.emojiCollectionView.setContentOffset(.zero, animated: false)
}
}) })
.disposed(by: disposeBag) .disposed(by: disposeBag)
} }
@ -520,11 +517,6 @@ extension InteractionView: UICollectionViewDelegate {
emojiPageControl.currentPage = page emojiPageControl.currentPage = page
} }
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
guard collectionView == emojiCollectionView else { return }
(cell as? EmojiPanelCell)?.playAnimation()
}
func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
guard collectionView == emojiCollectionView else { return } guard collectionView == emojiCollectionView else { return }
(cell as? EmojiPanelCell)?.stopAnimation() (cell as? EmojiPanelCell)?.stopAnimation()
@ -536,46 +528,29 @@ final class EmojiPanelCell: UICollectionViewCell {
private static var animationCache: [String: LottieAnimation] = [:] private static var animationCache: [String: LottieAnimation] = [:]
private static var loadingCompletions: [String: [(LottieAnimation?) -> Void]] = [:] private static var loadingCompletions: [String: [(LottieAnimation?) -> Void]] = [:]
private static let cacheLock = NSLock() private static let animationQueue = DispatchQueue(label: "com.quicklocation.emoji.animation", qos: .userInitiated)
private static let animationQueue = DispatchQueue(label: "com.quicklocation.emoji.animation", qos: .userInitiated, attributes: .concurrent)
private static let emojiPathMap: [String: String] = {
Bundle.main.paths(forResourcesOfType: "json", inDirectory: nil).reduce(into: [:]) { map, path in
let name = (path as NSString).lastPathComponent.replacingOccurrences(of: ".json", with: "")
map[name] = path
}
}()
static func loadAnimation(for name: String, completion: @escaping (LottieAnimation?) -> Void) { static func loadAnimation(for name: String, completion: @escaping (LottieAnimation?) -> Void) {
animationQueue.async { animationQueue.async {
Self.cacheLock.lock() if let cached = animationCache[name] {
if let cached = Self.animationCache[name] {
Self.cacheLock.unlock()
DispatchQueue.main.async { completion(cached) } DispatchQueue.main.async { completion(cached) }
return return
} }
if Self.loadingCompletions[name] != nil { if loadingCompletions[name] != nil {
Self.loadingCompletions[name]?.append(completion) loadingCompletions[name]?.append(completion)
Self.cacheLock.unlock()
return return
} }
Self.loadingCompletions[name] = [completion] loadingCompletions[name] = [completion]
Self.cacheLock.unlock()
let animation: LottieAnimation? let animation: LottieAnimation?
if let path = Self.emojiPathMap[name] { if let path = Bundle.main.path(forResource: name, ofType: "json") {
animation = LottieAnimation.filepath(path) animation = LottieAnimation.filepath(path)
} else { } else {
animation = nil animation = nil
} }
animationCache[name] = animation
Self.cacheLock.lock() let completions = loadingCompletions.removeValue(forKey: name) ?? []
Self.animationCache[name] = animation
let completions = Self.loadingCompletions.removeValue(forKey: name) ?? []
Self.cacheLock.unlock()
DispatchQueue.main.async { DispatchQueue.main.async {
completions.forEach { $0(animation) } completions.forEach { $0(animation) }
} }
@ -583,6 +558,7 @@ final class EmojiPanelCell: UICollectionViewCell {
} }
private var animationName: String? private var animationName: String?
private var shouldPlayAnimation = false
private let lottieView: LottieAnimationView = { private let lottieView: LottieAnimationView = {
let v = LottieAnimationView() let v = LottieAnimationView()
@ -622,28 +598,36 @@ final class EmojiPanelCell: UICollectionViewCell {
func configure(name: String) { func configure(name: String) {
animationName = name animationName = name
shouldPlayAnimation = false
lottieView.stop() lottieView.stop()
lottieView.animation = nil
lottieView.currentProgress = 0
Self.loadAnimation(for: name) { [weak self] animation in Self.loadAnimation(for: name) { [weak self] animation in
guard let self = self, self.animationName == name else { return } guard let self = self, self.animationName == name else { return }
self.lottieView.animation = animation self.lottieView.animation = animation
self.lottieView.currentProgress = 0 self.lottieView.currentProgress = 0
if self.shouldPlayAnimation {
self.lottieView.play() self.lottieView.play()
} }
}
lockView.isHidden = AppContextManager.shared.vip > 1 lockView.isHidden = AppContextManager.shared.vip > 1
} }
func playAnimation() { func playAnimation() {
shouldPlayAnimation = true
lottieView.play() lottieView.play()
} }
func stopAnimation() { func stopAnimation() {
shouldPlayAnimation = false
lottieView.stop() lottieView.stop()
} }
override func prepareForReuse() { override func prepareForReuse() {
super.prepareForReuse() super.prepareForReuse()
animationName = nil animationName = nil
shouldPlayAnimation = false
lottieView.stop() lottieView.stop()
lottieView.animation = nil lottieView.animation = nil
} }

View File

@ -1,177 +0,0 @@
//
// LocationPermissionPopView.swift
// QuickLocation
//
// Created by on 2026/7/8.
//
import UIKit
import RxSwift
import RxCocoa
class LocationPermissionPopView: UIView {
private static let shared = LocationPermissionPopView(frame: CGRect(origin: .zero, size: kScreenSize))
var disposeBag = DisposeBag()
static func show() {
guard let superView = kKeyWindow else {
return
}
if LocationPermissionPopView.shared.superview != nil {
LocationPermissionPopView.shared.removeFromSuperview()
LocationPermissionPopView.shared.bgView.frame = .zero
}
LocationPermissionPopView.shared.bgView.alpha = 1
LocationPermissionPopView.shared.bgView.frame = CGRect(x: 0, y: 0, width: kScreenWidth, height: kScreenHeight)
superView.addSubview(LocationPermissionPopView.shared)
superView.bringSubviewToFront(LocationPermissionPopView.shared)
UIView.animate(withDuration: 0.25) {
LocationPermissionPopView.shared.bgView.alpha = 1
}
}
///
static func dismiss() {
guard LocationPermissionPopView.shared.superview != nil else { return }
UIView.animate(withDuration: 0.25, delay: 0, options: [.curveEaseIn]) {
LocationPermissionPopView.shared.bgView.alpha = 0
} completion: { _ in
LocationPermissionPopView.shared.removeFromSuperview()
}
}
private func setupRx() {
settingBtn.rx.tap.subscribe(onNext: { _ in
guard let settingsURL = URL(string: UIApplication.openSettingsURLString) else { return }
LocationPermissionPopView.dismiss()
if UIApplication.shared.canOpenURL(settingsURL) {
UIApplication.shared.open(settingsURL, options: [:], completionHandler: nil)
}
}).disposed(by: disposeBag)
closeBtn.rx.tap.subscribe(onNext: { _ in
LocationPermissionPopView.dismiss()
}).disposed(by: disposeBag)
}
private lazy var bgView: UIView = {
let view = UIView()
view.backgroundColor = .black.withAlphaComponent(0.5)
return view
}()
lazy var popView: UIView = {
let view = UIView()
view.backgroundColor = .clear
return view
}()
lazy var popBgView: UIView = {
let view = UIView()
view.backgroundColor = .white
view.cornerRadius = 30
return view
}()
lazy var logoImgView: UIImageView = {
let view = UIImageView(image: UIImage(named: "Popup/bell"))
return view
}()
lazy var headerBgImg: UIImageView = {
let view = UIImageView(image: UIImage(named: "Popup/header_bg"))
view.contentMode = .scaleAspectFill
return view
}()
lazy var textImgView: UIImageView = {
let view = UIImageView()
view.contentMode = .scaleAspectFill
view.image = UIImage(named: "Home/permission_text")
return view
}()
lazy var settingBtn: UIButton = {
let btn = UIButton(type: .custom)
btn.setTitle("马上开启", for: .normal)
btn.setTitleColor(.white, for: .normal)
btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
btn.setBackgroundImage(UIImage(named: "Common/button_bg_2"), for: .normal)
btn.cornerRadius = 25
return btn
}()
lazy var closeBtn: UIButton = {
let btn = UIButton(type: .custom)
btn.setTitle("取消", for: .normal)
btn.setTitleColor(UIColor(hexStr: "#16B3FF"), for: .normal)
btn.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
btn.backgroundColor = .clear
return btn
}()
// MARK: - Init
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .clear
addSubview(bgView)
bgView.addSubview(popView)
popView.addSubview(popBgView)
popView.addSubview(logoImgView)
popBgView.addSubview(headerBgImg)
popBgView.addSubview(textImgView)
popBgView.addSubview(settingBtn)
popBgView.addSubview(closeBtn)
popView.layoutChain
.centerX()
.centerY()
.width(315)
.height(362)
popBgView.layoutChain.edges()
logoImgView.layoutChain
.left(16)
.top(-45)
.width(109)
.height(109)
headerBgImg.layoutChain
.edges(excludingEdge: .bottom)
.heightToWidth(100/315)
textImgView.layoutChain
.top(70)
.centerX()
.width(275)
.height(173)
closeBtn.layoutChain
.bottom()
.height(50)
.edgesHorzontal(20)
settingBtn.layoutChain
.bottomToTopOfView(closeBtn)
.height(50)
.edgesHorzontal(20)
setupRx()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
}
}

View File

@ -23,12 +23,19 @@ class SOSViewController: BaseViewController {
// Do any additional setup after loading the view. // Do any additional setup after loading the view.
fd_interactivePopDisabled = true fd_interactivePopDisabled = true
// requestUserInfo()
rootView.didSendSOS = { status in rootView.didSendSOS = { status in
self.requestSOS(status) self.requestSOS(status)
} }
}
guard AppContextManager.shared.status == 1 else { return } private func requestUserInfo(completion: (() -> Void)? = nil) {
UserService.userInfo().subscribe { response in
guard let model = response.model else { return }
AppContextManager.shared.saveAccount(model)
guard model.status == 1 else { return }
self.rootView.countDownView.alpha = 1 self.rootView.countDownView.alpha = 1
self.rootView.countDownFinish = true self.rootView.countDownFinish = true
if let path = Bundle.main.path(forResource: "red-exclamation", ofType: "json") { if let path = Bundle.main.path(forResource: "red-exclamation", ofType: "json") {
@ -37,13 +44,14 @@ class SOSViewController: BaseViewController {
self.rootView.countDownLottieView.play() self.rootView.countDownLottieView.play()
self.rootView.countDownTipsLab.text = "已将你的SOS和位置发送到你的圈子和紧急联系人。\n\n您的 SOS 将发送给5个人" self.rootView.countDownTipsLab.text = "已将你的SOS和位置发送到你的圈子和紧急联系人。\n\n您的 SOS 将发送给5个人"
} }
}.disposed(by: disposeBag)
} }
private func requestSOS(_ enable: Bool) { private func requestSOS(_ enable: Bool) {
dl.showLoading() dl.showLoading()
SystemService.sos(enable: enable).subscribe(onNext: { response in SystemService.sos(enable: enable).subscribe(onNext: { response in
self.dl.show(text: enable ? "发送成功" : "取消成功") { self.dl.show(text: enable ? "发送成功" : "取消成功") {
AppContextManager.shared.updateAccountStatus(enable ? 1 : 0)
AppRouter.shared.popOrDismiss() AppRouter.shared.popOrDismiss()
} }
}, onError: { (error) in }).disposed(by: disposeBag) }, onError: { (error) in }).disposed(by: disposeBag)

View File

@ -30,29 +30,39 @@ class LaunchViewController: BaseViewController {
setupLayout() setupLayout()
experienceBtn.rx.tap.subscribe(onNext: { _ in experienceBtn.rx.tap.subscribe(onNext: { _ in
Defaults[\.isShowGuide] = false // Defaults[\.guideShowVersion] = self.showVersion
AppDelegate.shared.showMainViewController() AppDelegate.shared.showMainViewController()
}).disposed(by: disposeBag) }).disposed(by: disposeBag)
getUserConfig() getUserConfig()
navigateAfterDelay()
} }
private func navigateAfterDelay() { private func navigateAfterDelay() {
Observable.just(()) Observable.just(())
.delay(.milliseconds(2500), scheduler: MainScheduler.instance) .delay(.milliseconds(2500), scheduler: MainScheduler.instance)
.subscribe(onNext: { [weak self] in .subscribe(onNext: { [weak self] in
guard let systemConfig = AppContextManager.shared.systemConfig else { return } self?.navigateToNext()
if systemConfig.guideDisplay, Defaults[\.isShowGuide] {
self?.collectionView.isHidden = false
self?.pageControl.isHidden = false
self?.experienceBtn.isHidden = false
} else {
AppDelegate.shared.showMainViewController()
}
}) })
.disposed(by: disposeBag) .disposed(by: disposeBag)
} }
private func navigateToNext() {
let hasShownGuide = UserDefaults.standard.bool(forKey: "hasShownGuide")
if hasShownGuide {
let loginVC = LoginViewController()
UIView.transition(with: view.window!, duration: 0.4, options: .transitionCrossDissolve) {
self.view.window?.rootViewController = UINavigationController(rootViewController: loginVC)
}
} else {
collectionView.isHidden = false
pageControl.isHidden = false
experienceBtn.isHidden = false
}
}
/// ///
func getUserConfig() { func getUserConfig() {
SystemService.userConfig().subscribe(onNext: { response in SystemService.userConfig().subscribe(onNext: { response in
@ -72,11 +82,11 @@ class LaunchViewController: BaseViewController {
/// IM Token /// IM Token
func getUserIMToken() { func getUserIMToken() {
DLToast.showLoading()
UserService.imToken().subscribe(onNext: { response in UserService.imToken().subscribe(onNext: { response in
guard let data = response.data, let token = data["token"] as? String else { return } guard let data = response.data, let token = data["token"] as? String else { return }
AppContextManager.shared.imToken = token AppContextManager.shared.imToken = token
GroupIMService.shared.login { _ in } GroupIMService.shared.login { _ in }
self.navigateAfterDelay()
}).disposed(by: disposeBag) }).disposed(by: disposeBag)
} }

View File

@ -68,14 +68,13 @@ class LoginView: UIView {
addSubview(bgMaskImage) addSubview(bgMaskImage)
addSubview(backBtn) addSubview(backBtn)
addSubview(guestLoginButton) addSubview(guestLoginButton)
addSubview(inputContainerView) addSubview(welcomeLabel)
inputContainerView.addSubview(welcomeLabel) addSubview(phoneNumberLabel)
inputContainerView.addSubview(phoneNumberLabel) addSubview(carrierLabel)
inputContainerView.addSubview(carrierLabel) addSubview(otherPhoneView)
inputContainerView.addSubview(otherPhoneView)
otherPhoneView.addSubview(phoneInputView) otherPhoneView.addSubview(phoneInputView)
otherPhoneView.addSubview(smsCodeInputView) otherPhoneView.addSubview(smsCodeInputView)
inputContainerView.addSubview(loginButton) addSubview(loginButton)
addSubview(appleLoginBtn) addSubview(appleLoginBtn)
addSubview(wechatLoginBtn) addSubview(wechatLoginBtn)
addSubview(phoneLoginBtn) addSubview(phoneLoginBtn)
@ -99,14 +98,8 @@ class LoginView: UIView {
.width(85) .width(85)
.height(29) .height(29)
inputContainerView.layoutChain
.centerX()
.centerY(self, offset: -17)
.edgesHorzontal()
.height(306)
welcomeLabel.layoutChain welcomeLabel.layoutChain
.top(0) .top(202 - kNaviHeight)
.centerX() .centerX()
.edgesHorzontal() .edgesHorzontal()
@ -168,7 +161,7 @@ class LoginView: UIView {
agreementView.layoutChain agreementView.layoutChain
.leftToView(loginButton) .leftToView(loginButton)
.rightToView(loginButton) .rightToView(loginButton)
.bottom(kSafeBottomMargin + 20) .bottom(55)
.height(30) .height(30)
agreementLabel.layoutChain.edges() agreementLabel.layoutChain.edges()
@ -185,7 +178,7 @@ class LoginView: UIView {
.top() .top()
phoneLoginBtn.layoutChain phoneLoginBtn.layoutChain
.bottomToTopOfView(agreementView, offset: -30) .bottomToTopOfView(agreementView, offset: -81)
.centerX() .centerX()
.width(38) .width(38)
.heightToWidth(1) .heightToWidth(1)
@ -265,13 +258,6 @@ class LoginView: UIView {
return label return label
}() }()
//
lazy var inputContainerView: UIView = {
let view = UIView()
view.backgroundColor = .clear
return view
}()
// //
lazy var otherPhoneView: UIView = { lazy var otherPhoneView: UIView = {
let view = UIView() let view = UIView()
@ -408,6 +394,7 @@ class LoginView: UIView {
textView.backgroundColor = .clear textView.backgroundColor = .clear
textView.isEditable = false textView.isEditable = false
textView.isScrollEnabled = false textView.isScrollEnabled = false
textView.isSelectable = false
textView.linkTextAttributes = [:] textView.linkTextAttributes = [:]
return textView return textView

View File

@ -9,7 +9,6 @@ import UIKit
import SnapKit import SnapKit
import RxSwift import RxSwift
import RxCocoa import RxCocoa
import AuthenticationServices
#if !targetEnvironment(simulator) #if !targetEnvironment(simulator)
import GeYanSdk import GeYanSdk
#endif #endif
@ -91,67 +90,27 @@ class LoginViewController: BaseViewController {
rootView.wechatLoginBtn.rx.tap rootView.wechatLoginBtn.rx.tap
.subscribe(onNext: { [weak self] in .subscribe(onNext: { [weak self] in
guard self?.isAgreed == true else {
DLToast.showError(text: "请先同意用户协议")
return
}
self?.viewModel.performWechatLogin() self?.viewModel.performWechatLogin()
}) })
.disposed(by: disposeBag) .disposed(by: disposeBag)
rootView.appleLoginBtn.rx.tap rootView.appleLoginBtn.rx.tap
.subscribe(onNext: { [weak self] in .subscribe(onNext: { [weak self] in
guard self?.isAgreed == true else {
DLToast.showError(text: "请先同意用户协议")
return
}
self?.viewModel.performAppleLogin() self?.viewModel.performAppleLogin()
}) })
.disposed(by: disposeBag) .disposed(by: disposeBag)
viewModel.onAppleLoginRequest = { [weak self] controller in
guard let self = self else { return }
controller.delegate = self
controller.presentationContextProvider = self
controller.performRequests()
}
rootView.phoneLoginBtn.rx.tap rootView.phoneLoginBtn.rx.tap
.subscribe(onNext: { [weak self] in .subscribe(onNext: { [weak self] in
#if !targetEnvironment(simulator)
if GeYanSdk.getCurrentCarrierCount() == 0 {
DLToast.show(text: "请插入SIM卡后重试")
return
}
if GeYanSdk.isPreGettedTokenValidate() { //
let oneTapView = OneTapLoginView(frame: UIScreen.main.bounds)
self?.viewModel.performOneTapLogin(from: self!, contentView: oneTapView)
return
}
//
GeYanSdk.preGetToken { preDic in
guard GeYanSdk.isPreGettedTokenValidate() else {
var message = ""
if let dict = preDic as? [String: Any] {
message = dict["msg"] as? String ?? "获取手机号失败,请使用验证码登录"
}
DLToast.show(text: message)
return
}
let oneTapView = OneTapLoginView(frame: UIScreen.main.bounds)
self?.viewModel.performOneTapLogin(from: self!, contentView: oneTapView)
}
#endif
}) })
.disposed(by: disposeBag) .disposed(by: disposeBag)
// viewModel.loginSuccess viewModel.loginSuccess
// .subscribe(onNext: { [weak self] in .subscribe(onNext: { [weak self] in
//
// }) })
// .disposed(by: disposeBag) .disposed(by: disposeBag)
} }
// MARK: - API // MARK: - API
@ -191,40 +150,3 @@ extension LoginViewController: UITextViewDelegate {
private func openURL(_ url: String) {} private func openURL(_ url: String) {}
} }
// MARK: - Apple Sign In
extension LoginViewController: ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding {
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
view.window ?? UIWindow()
}
func authorizationController(controller: ASAuthorizationController,
didCompleteWithAuthorization authorization: ASAuthorization) {
guard let credential = authorization.credential as? ASAuthorizationAppleIDCredential else { return }
let userId = credential.user
let userName: String = {
if let name = credential.fullName {
let parts = [name.givenName, name.familyName].compactMap { $0 }
if !parts.isEmpty { return parts.joined(separator: " ") }
}
return ""
}()
let identityToken = credential.identityToken.flatMap { String(data: $0, encoding: .utf8) } ?? ""
let authCode = credential.authorizationCode.flatMap { String(data: $0, encoding: .utf8) } ?? ""
viewModel.loginAction(type: "apple", data: [
"user_id": userId,
"user_name": userName,
"identify_code": authCode,
"identify_token": identityToken
])
}
func authorizationController(controller: ASAuthorizationController,
didCompleteWithError error: Error) {
NotificationCenter.default.post(name: .resumePopupQueue, object: nil)
DLToast.showError(text: "Apple 登录失败")
}
}

View File

@ -6,43 +6,10 @@
import Foundation import Foundation
import RxSwift import RxSwift
import SwiftyUserDefaults import SwiftyUserDefaults
import AuthenticationServices
#if !targetEnvironment(simulator) #if !targetEnvironment(simulator)
import GeYanSdk import GeYanSdk
#endif #endif
enum LoginSessionHandler {
private static let disposeBag = DisposeBag()
static func login(type: String, data: [String: Any]) {
DLToast.showLoading()
UserService.login(type: type, data: data)
.delaySubscription(.seconds(1), scheduler: MainScheduler.instance)
.retry(1)
.subscribe(onNext: { response in
GroupIMService.shared.logout()
DLToast.dismiss()
guard let model = response.model else { return }
NotificationCenter.default.post(name: .invalidatePopupQueue, object: nil)
Defaults[\.loginToken] = model.token
DLToast.showSuccess(text: "登录成功") {
if let userId = model.uid {
MQTTService.shared.updateClientID("smartdrive_\(userId)")
}
NotificationCenter.default.post(name: .RefreshUserConfigNotification, object: nil)
if let nav = AppRouter.shared.navigationController, nav.viewControllers.count > 1 {
AppRouter.shared.popOrDismiss()
} else {
AppDelegate.shared.showMainViewController()
}
}
}, onError: { error in
DLToast.dismiss()
DLToast.showError(text: "登录失败,请重试")
}).disposed(by: disposeBag)
}
}
final class LoginViewModel: BaseViewModel { final class LoginViewModel: BaseViewModel {
/// ///
@ -51,86 +18,47 @@ final class LoginViewModel: BaseViewModel {
let oneClickLoginResult = PublishSubject<Bool>() let oneClickLoginResult = PublishSubject<Bool>()
let loginSuccess = PublishSubject<Void>() let loginSuccess = PublishSubject<Void>()
var onAppleLoginRequest: ((ASAuthorizationController) -> Void)? var gyAuthVM: GyAuthViewModel {
#if !targetEnvironment(simulator)
lazy var gyAuthVM: GyAuthViewModel = {
let viewModel = GyAuthViewModel() let viewModel = GyAuthViewModel()
viewModel.statusBarStyle = .default viewModel.statusBarStyle = .default
viewModel.userInterfaceStyle = 0 viewModel.userInterfaceStyle = 0
viewModel.pullAuthVCStyle = .modal viewModel.pullAuthVCStyle = .push
viewModel.viewLifeCycleBlock = { (str, bool) in
}
viewModel.clickAuthButtonBlock = { viewModel.clickAuthButtonBlock = {
return true return true
} }
return viewModel return viewModel
}() }
#endif
/// ///
func loginAction(type: String, data: [String : Any]) { func loginAction(type: String, data: [String : Any]) {
LoginSessionHandler.login(type: type, data: data) DLToast.showLoading()
UserService.login(type: type, data: data).subscribe { response in
GroupIMService.shared.logout()
DLToast.dismiss()
guard let model = response.model else { return }
Defaults[\.loginToken] = model.token
DLToast.showSuccess(text: "登录成功") {
if let userId = model.uid {
MQTTService.shared.updateClientID("smartdrive_\(userId)")
}
NotificationCenter.default.post(name: .RefreshUserConfigNotification, object: nil)
AppRouter.shared.popOrDismiss()
}
}.disposed(by: disposeBag)
} }
func performGuestLogin() { func performGuestLogin() {
loginSuccess.onNext(()) loginSuccess.onNext(())
} }
#if !targetEnvironment(simulator)
func performOneTapLogin(from vc: UIViewController, contentView: OneTapLoginView) {
NotificationCenter.default.post(name: .pausePopupQueue, object: nil)
let subViews: [UIView] = [
contentView.phoneNumberLabel,
contentView.carrierLabel,
contentView.loginButton,
contentView.checkBox,
contentView.agreementLabel
]
GeYanSdk.oneTapLogin(vc, viewModel: gyAuthVM, contentView: contentView,
subViewList: subViews) { [weak self] result in
guard let dict = result as? [String: Any],
let code = dict["code"] as? Int else { return }
print(dict)
if code == 30000, //
let gyuid = dict["gyuid"],
let token = dict["token"] {
// let opType: String = {
// switch dict["operatorType"] as? Int {
// case 1: return "CM"
// case 2: return "CU"
// case 3: return "CT"
// default: return ""
// }
// }()
GeYanSdk.closeAuthVC(true) {
self?.loginAction(type: "onekey", data: [
"gyuid": gyuid,
"token": token
])
}
}
else {
DLToast.show(text: dict["msg"] as? String ?? "运营商返回失败")
}
}
}
#endif
func performWechatLogin() { func performWechatLogin() {
NotificationCenter.default.post(name: .pausePopupQueue, object: nil) // TODO: Integrate WeChat SDK
let req = SendAuthReq()
req.scope = "snsapi_userinfo"
req.state = "login"
WXApi.send(req)
} }
func performAppleLogin() { func performAppleLogin() {
NotificationCenter.default.post(name: .pausePopupQueue, object: nil) // TODO: Integrate Sign in with Apple
let provider = ASAuthorizationAppleIDProvider()
let request = provider.createRequest()
request.requestedScopes = [.fullName, .email]
let controller = ASAuthorizationController(authorizationRequests: [request])
onAppleLoginRequest?(controller)
} }
} }

View File

@ -19,17 +19,13 @@ class OneTapLoginView: UIView {
private func setupRx() { private func setupRx() {
backBtn.rx.tap.subscribe(onNext: { _ in backBtn.rx.tap.subscribe(onNext: { _ in
#if !targetEnvironment(simulator) AppRouter.shared.popOrDismiss()
GeYanSdk.closeAuthVC(true, completion: nil)
#endif
}).disposed(by: disposeBag) }).disposed(by: disposeBag)
checkBox.rx.tap.subscribe(onNext: { [weak self] in checkBox.rx.tap.subscribe(onNext: { [weak self] in
guard let self = self else { return } guard let self = self else { return }
self.checkBox.isSelected = !self.checkBox.isSelected self.checkBox.isSelected = !self.checkBox.isSelected
}).disposed(by: disposeBag) }).disposed(by: disposeBag)
agreementTV.delegate = self
} }
func setupAgreementTextWithCarrier(carrier: String) { func setupAgreementTextWithCarrier(carrier: String) {
@ -59,16 +55,15 @@ class OneTapLoginView: UIView {
private func setupUI() { private func setupUI() {
addSubview(bgMaskImage) addSubview(bgMaskImage)
addSubview(backBtn) addSubview(backBtn)
addSubview(inputContainerView) addSubview(welcomeLabel)
inputContainerView.addSubview(welcomeLabel) addSubview(phoneNumberLabel)
inputContainerView.addSubview(phoneNumberLabel) addSubview(carrierLabel)
inputContainerView.addSubview(carrierLabel) addSubview(loginButton)
inputContainerView.addSubview(loginButton)
addSubview(agreementView) addSubview(agreementView)
agreementView.addSubview(checkBox) agreementView.addSubview(checkBox)
agreementView.addSubview(agreementLabel)
agreementView.addSubview(agreementTV) agreementView.addSubview(agreementTV)
agreementView.addSubview(agreementLabel)
bgMaskImage.layoutChain.edges() bgMaskImage.layoutChain.edges()
@ -78,14 +73,8 @@ class OneTapLoginView: UIView {
.width(24) .width(24)
.height(24) .height(24)
inputContainerView.layoutChain
.centerX()
.centerY()
.edgesHorzontal()
.height(301)
welcomeLabel.layoutChain welcomeLabel.layoutChain
.top(0) .top(202 - kNaviHeight)
.centerX() .centerX()
.edgesHorzontal() .edgesHorzontal()
@ -104,26 +93,23 @@ class OneTapLoginView: UIView {
.height(50) .height(50)
agreementView.layoutChain agreementView.layoutChain
.edgesHorzontal(30) .leftToView(loginButton)
.bottom(kSafeBottomMargin + 20) .rightToView(loginButton)
.bottom(55)
.height(30)
agreementLabel.layoutChain.edges()
checkBox.layoutChain checkBox.layoutChain
.left() .left()
.top(10) .centerY()
.width(12) .width(12)
.height(12) .height(12)
agreementLabel.layoutChain
.leftToRightOfView(checkBox, offset: 0)
.right()
.top()
.bottom()
agreementTV.layoutChain agreementTV.layoutChain
.leftToRightOfView(checkBox, offset: 0) .leftToRightOfView(checkBox, offset: 0)
.right() .right()
.top() .top()
.bottom()
} }
override init(frame: CGRect) { override init(frame: CGRect) {
@ -144,12 +130,6 @@ class OneTapLoginView: UIView {
} }
// MARK: - UI Components // MARK: - UI Components
lazy var inputContainerView: UIView = {
let view = UIView()
view.backgroundColor = .clear
return view
}()
lazy var bgMaskImage: UIImageView = { lazy var bgMaskImage: UIImageView = {
let iv = UIImageView() let iv = UIImageView()
iv.image = UIImage(named: "Login/bg") iv.image = UIImage(named: "Login/bg")
@ -198,12 +178,6 @@ class OneTapLoginView: UIView {
return btn return btn
}() }()
lazy var label: UILabel = {
let label = UILabel()
return label
}()
lazy var agreementView: UIView = { lazy var agreementView: UIView = {
let view = UIView() let view = UIView()
view.backgroundColor = .clear view.backgroundColor = .clear
@ -214,16 +188,15 @@ class OneTapLoginView: UIView {
let btn = UIButton(type: .custom) let btn = UIButton(type: .custom)
btn.setImage(UIImage(named: "Login/checkbox"), for: .normal) btn.setImage(UIImage(named: "Login/checkbox"), for: .normal)
btn.setImage(UIImage(named: "Login/selected"), for: .selected) btn.setImage(UIImage(named: "Login/selected"), for: .selected)
btn.extendEdgeInsets = UIEdgeInsets(top: 50, left: 50, bottom: 50, right: 20) btn.extendEdgeInsets = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)
btn.isSelected = true
return btn return btn
}() }()
lazy var agreementLabel: UILabel = { lazy var agreementLabel: UILabel = {
let label = UILabel() let label = UILabel()
label.textColor = .clear label.textColor = .clear
label.numberOfLines = 0 label.numberOfLines = 1
// label.textAlignment = .center label.textAlignment = .center
label.font = .systemFont(ofSize: 10) label.font = .systemFont(ofSize: 10)
return label return label
}() }()
@ -234,34 +207,9 @@ class OneTapLoginView: UIView {
textView.backgroundColor = .clear textView.backgroundColor = .clear
textView.isEditable = false textView.isEditable = false
textView.isScrollEnabled = false textView.isScrollEnabled = false
textView.isSelectable = true textView.isSelectable = false
textView.linkTextAttributes = [:] textView.linkTextAttributes = [:]
return textView return textView
}() }()
} }
#if !targetEnvironment(simulator)
extension OneTapLoginView: UITextViewDelegate {
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
var urlStr: String?
if URL.absoluteString == "Carrier", let model = GyContentModel.current(), let link = model.link {
urlStr = link
}
if URL.absoluteString == "UserAgreement" {
urlStr = URLManager.shared.userAgreementUrl
}
if URL.absoluteString == "PrivacyPolicy" {
urlStr = URLManager.shared.privacyPolicyUrl
}
guard let urlString = urlStr else { return true }
let vc = WebViewController(url: urlString, isShare: false, fullscreen: false, style: "default")
AppRouter.present(UINavigationController(rootViewController: vc))
return true
}
func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
false
}
}
#endif

View File

@ -9,9 +9,6 @@ import UIKit
import RxSwift import RxSwift
import RxCocoa import RxCocoa
import RxDataSources import RxDataSources
#if !targetEnvironment(simulator)
import GeYanSdk
#endif
class AccountVC: BaseViewController { class AccountVC: BaseViewController {
@ -62,8 +59,6 @@ class AccountVC: BaseViewController {
DLToast.showLoading() DLToast.showLoading()
UserService.logout().subscribe(onNext: { response in UserService.logout().subscribe(onNext: { response in
DLToast.dismiss() DLToast.dismiss()
NotificationCenter.default.post(name: .invalidatePopupQueue, object: nil)
GeYanSdk.deletePreResultCache()
AppContextManager.shared.deleteAccount() AppContextManager.shared.deleteAccount()
GroupIMService.shared.logout() GroupIMService.shared.logout()
AppDelegate.shared.showMainViewController() AppDelegate.shared.showMainViewController()

View File

@ -29,11 +29,7 @@ final class MineView: UIView {
private let vipBtnTextColor = UIColor(hexStr: "#00343B") private let vipBtnTextColor = UIColor(hexStr: "#00343B")
func setupData(_ model: UserConfigModel) { func setupData(_ model: UserConfigModel) {
guard AppContextManager.shared.systemConfig?.globalDisplay == true else {
maskBgView.isHidden = false
return
}
maskBgView.isHidden = true
guard model.vip > 1 else { guard model.vip > 1 else {
vipTitleLab.text = "开通会员" vipTitleLab.text = "开通会员"
vipContentLab.text = "会员尊享10+VIP特权" vipContentLab.text = "会员尊享10+VIP特权"
@ -125,19 +121,11 @@ final class MineView: UIView {
return iv return iv
}() }()
lazy var maskBgView: UIImageView = {
let iv = UIImageView()
iv.image = UIImage(named: "Mine/mask_bg")
iv.contentMode = .scaleToFill
iv.isHidden = true
return iv
}()
lazy var vipTitleLab: UILabel = { lazy var vipTitleLab: UILabel = {
let label = UILabel() let label = UILabel()
label.font = .systemFont(ofSize: 18, weight: .bold) label.font = .systemFont(ofSize: 18, weight: .bold)
label.textColor = .white label.textColor = .white
label.text = " " label.text = "开通会员"
return label return label
}() }()
@ -145,7 +133,7 @@ final class MineView: UIView {
let label = UILabel() let label = UILabel()
label.font = .systemFont(ofSize: 12, weight: .medium) label.font = .systemFont(ofSize: 12, weight: .medium)
label.textColor = .white label.textColor = .white
label.text = " " label.text = "会员尊享10+VIP特权"
return label return label
}() }()
@ -200,10 +188,6 @@ final class MineView: UIView {
// MARK: - Callbacks // MARK: - Callbacks
var onMenuTap: ((Int) -> Void)? var onMenuTap: ((Int) -> Void)?
// MARK: - Dynamic Height
private var settingsCardHeightConstraint: NSLayoutConstraint?
private var contentSizeObservation: NSKeyValueObservation?
// MARK: - Init // MARK: - Init
override init(frame: CGRect) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
@ -232,7 +216,6 @@ final class MineView: UIView {
vipCardView.addSubview(vipActivateButton) vipCardView.addSubview(vipActivateButton)
vipCardView.addSubview(vipTitleLab) vipCardView.addSubview(vipTitleLab)
vipCardView.addSubview(vipContentLab) vipCardView.addSubview(vipContentLab)
vipCardView.addSubview(maskBgView)
addSubview(profileBgImageView) addSubview(profileBgImageView)
addSubview(bottomFillView) addSubview(bottomFillView)
@ -295,8 +278,6 @@ final class MineView: UIView {
.right(19).centerY() .right(19).centerY()
.width(70).height(28) .width(70).height(28)
maskBgView.layoutChain.edges()
// Profile transition background (100pt, overlaps VIP card bottom half) // Profile transition background (100pt, overlaps VIP card bottom half)
profileBgImageView.layoutChain profileBgImageView.layoutChain
.topToView(vipCardView, offset: 32) .topToView(vipCardView, offset: 32)
@ -308,42 +289,14 @@ final class MineView: UIView {
.topToBottomOfView(profileBgImageView) .topToBottomOfView(profileBgImageView)
.left().right().bottom() .left().right().bottom()
// Settings Card (dynamic height, scrolls when exceeds area above tabbar) // Settings Card (fixed height, not stretched)
settingsCardView.layoutChain settingsCardView.layoutChain
.topToBottomOfView(vipCardView, offset: 20) .topToBottomOfView(vipCardView, offset: 20)
.left(16).right(16) .left(16).right(16)
.height(312)
settingsCardHeightConstraint = settingsCardView.heightAnchor.constraint(equalToConstant: 312)
settingsCardHeightConstraint?.isActive = true
settingsTableView.layoutChain settingsTableView.layoutChain
.edges() .edges()
contentSizeObservation = settingsTableView.observe(\.contentSize, options: [.new, .initial]) { [weak self] _, _ in
self?.refreshTableViewHeight()
}
}
// MARK: - Layout
override func layoutSubviews() {
super.layoutSubviews()
refreshTableViewHeight()
}
func refreshTableViewHeight() {
let contentHeight = settingsTableView.contentSize.height
guard contentHeight > 0 else { return }
let tabBarHeight: CGFloat = 56 + kSafeBottomMargin
let maxHeight = bounds.height - tabBarHeight - settingsCardView.frame.minY
if contentHeight <= maxHeight {
settingsCardHeightConstraint?.constant = contentHeight
settingsTableView.isScrollEnabled = false
} else {
settingsCardHeightConstraint?.constant = maxHeight
settingsTableView.isScrollEnabled = true
}
} }
} }

View File

@ -11,28 +11,7 @@ class PopupQueueManager {
private weak var sourceVC: UIViewController? private weak var sourceVC: UIViewController?
private var currentStep = 0 private var currentStep = 0
private var stepGeneration = 0
private var countdownTimer: Timer? private var countdownTimer: Timer?
private var isPaused = false
init() {
NotificationCenter.default.addObserver(self,
selector: #selector(handlePause),
name: .pausePopupQueue,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(handleResume),
name: .resumePopupQueue,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(handleInvalidate),
name: .invalidatePopupQueue,
object: nil)
}
deinit {
NotificationCenter.default.removeObserver(self)
}
func start(from vc: UIViewController) { func start(from vc: UIViewController) {
sourceVC = vc sourceVC = vc
@ -40,27 +19,7 @@ class PopupQueueManager {
executeNextStep() executeNextStep()
} }
@objc private func handlePause() {
countdownTimer?.invalidate()
countdownTimer = nil
isPaused = true
}
@objc private func handleResume() {
guard isPaused else { return }
isPaused = false
executeNextStep()
}
@objc private func handleInvalidate() {
countdownTimer?.invalidate()
countdownTimer = nil
isPaused = true
currentStep = 3
}
private func executeNextStep() { private func executeNextStep() {
guard AppContextManager.shared.systemConfig?.globalDisplay == true else { return }
switch currentStep { switch currentStep {
case 0: case 0:
tryStartPromotionalActivities() tryStartPromotionalActivities()
@ -86,14 +45,12 @@ class PopupQueueManager {
skipToNext() skipToNext()
return return
} }
let gen = stepGeneration
startCountdown(seconds: timeConfig.pay_pop_time) { [weak self] in startCountdown(seconds: timeConfig.pay_pop_time) { [weak self] in
guard let self = self, self.currentStep == 0, self.stepGeneration == gen else { return }
let vc = PromotionalActivitiesVC() let vc = PromotionalActivitiesVC()
vc.onDismiss = { [weak self] in vc.onDismiss = { [weak self] in
self?.skipToNext() self?.skipToNext()
} }
self.push(vc) self?.push(vc)
} }
} }
@ -109,11 +66,9 @@ class PopupQueueManager {
skipToNext() skipToNext()
return return
} }
let gen = stepGeneration startCountdown(seconds: timeConfig.search_phone) { [weak self] in
startCountdown(seconds: timeConfig.search_phone) {
guard self.currentStep == 1, self.stepGeneration == gen else { return }
PopupWindow.show(popupType: .search) { PopupWindow.show(popupType: .search) {
self.skipToNext() self?.skipToNext()
} }
} }
} }
@ -127,17 +82,13 @@ class PopupQueueManager {
} }
if AppContextManager.shared.isGuest { if AppContextManager.shared.isGuest {
let gen = stepGeneration startCountdown(seconds: timeConfig.signup_tip) { [weak self] in
startCountdown(seconds: timeConfig.signup_tip) {
guard self.currentStep == 2, self.stepGeneration == gen else { return }
PopupWindow.show(popupType: .register) { PopupWindow.show(popupType: .register) {
// done // done
} }
} }
} else if AppContextManager.shared.vip == 1 { } else if AppContextManager.shared.vip == 1 {
let gen = stepGeneration startCountdown(seconds: timeConfig.buy_vip_tip) { [weak self] in
startCountdown(seconds: timeConfig.buy_vip_tip) {
guard self.currentStep == 2, self.stepGeneration == gen else { return }
PopupWindow.show(popupType: .vip) { PopupWindow.show(popupType: .vip) {
// done // done
} }
@ -148,7 +99,6 @@ class PopupQueueManager {
// MARK: - Helpers // MARK: - Helpers
private func skipToNext() { private func skipToNext() {
stepGeneration += 1
currentStep += 1 currentStep += 1
executeNextStep() executeNextStep()
} }
@ -172,11 +122,7 @@ class PopupQueueManager {
private func push(_ vc: UIViewController) { private func push(_ vc: UIViewController) {
let topVC = topViewController() let topVC = topViewController()
guard let nav = topVC?.navigationController else { return } topVC?.navigationController?.pushViewController(vc, animated: true)
if nav.viewControllers.contains(where: { type(of: $0) == type(of: vc) }) {
return
}
nav.pushViewController(vc, animated: true)
} }
private func topViewController() -> UIViewController? { private func topViewController() -> UIViewController? {

View File

@ -151,12 +151,8 @@ class PopupWindow: UIView {
registerBtn.rx.tap registerBtn.rx.tap
.subscribe(onNext: { [weak self] _ in .subscribe(onNext: { [weak self] _ in
NotificationCenter.default.post(name: .pausePopupQueue, object: nil)
self?.activePopupView == 2 ? self?.slideOutRegister2Popup() : self?.slideOutRegisterPopup() self?.activePopupView == 2 ? self?.slideOutRegister2Popup() : self?.slideOutRegisterPopup()
let topVC = UIViewController.currentViewController()
if !(topVC is LoginViewController) {
AppRouter.push(Route.login) AppRouter.push(Route.login)
}
}) })
.disposed(by: disposeBag) .disposed(by: disposeBag)
@ -168,12 +164,8 @@ class PopupWindow: UIView {
register2Btn.rx.tap register2Btn.rx.tap
.subscribe(onNext: { [weak self] _ in .subscribe(onNext: { [weak self] _ in
NotificationCenter.default.post(name: .pausePopupQueue, object: nil)
self?.slideOutRegister2Popup() self?.slideOutRegister2Popup()
let topVC = UIViewController.currentViewController()
if !(topVC is LoginViewController) {
AppRouter.push(Route.login) AppRouter.push(Route.login)
}
}) })
.disposed(by: disposeBag) .disposed(by: disposeBag)
@ -186,10 +178,6 @@ class PopupWindow: UIView {
vip1UnlockBtn.rx.tap vip1UnlockBtn.rx.tap
.subscribe(onNext: { [weak self] _ in .subscribe(onNext: { [weak self] _ in
self?.slideOutUnlockVip1Popup() self?.slideOutUnlockVip1Popup()
let topVC = UIViewController.currentViewController()
if !(topVC is VipRechargeVC) {
AppRouter.push(Route.vipRecharge)
}
}) })
.disposed(by: disposeBag) .disposed(by: disposeBag)
@ -202,10 +190,6 @@ class PopupWindow: UIView {
unlockVip2Btn.rx.tap unlockVip2Btn.rx.tap
.subscribe(onNext: { [weak self] _ in .subscribe(onNext: { [weak self] _ in
self?.slideOutUnlockVip2Popup() self?.slideOutUnlockVip2Popup()
let topVC = UIViewController.currentViewController()
if !(topVC is VipRechargeVC) {
AppRouter.push(Route.vipRecharge)
}
}) })
.disposed(by: disposeBag) .disposed(by: disposeBag)
@ -218,10 +202,6 @@ class PopupWindow: UIView {
unlockVip3Btn.rx.tap unlockVip3Btn.rx.tap
.subscribe(onNext: { [weak self] _ in .subscribe(onNext: { [weak self] _ in
self?.slideOutUnlockVip3Popup() self?.slideOutUnlockVip3Popup()
let topVC = UIViewController.currentViewController()
if !(topVC is VipRechargeVC) {
AppRouter.push(Route.vipRecharge)
}
}) })
.disposed(by: disposeBag) .disposed(by: disposeBag)
@ -234,10 +214,6 @@ class PopupWindow: UIView {
unlockVip4Btn.rx.tap unlockVip4Btn.rx.tap
.subscribe(onNext: { [weak self] _ in .subscribe(onNext: { [weak self] _ in
self?.slideOutUnlockVip4Popup() self?.slideOutUnlockVip4Popup()
let topVC = UIViewController.currentViewController()
if !(topVC is VipRechargeVC) {
AppRouter.push(Route.vipRecharge)
}
}) })
.disposed(by: disposeBag) .disposed(by: disposeBag)
} }

View File

@ -49,7 +49,7 @@ class PromotionalActivitiesVC: BaseViewController {
override func viewDidLoad() { override func viewDidLoad() {
super.viewDidLoad() super.viewDidLoad()
fd_interactivePopDisabled = true
setupTableView() setupTableView()
requestRechargeInfo() requestRechargeInfo()
@ -103,11 +103,6 @@ class PromotionalActivitiesVC: BaseViewController {
} }
} }
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
navigationController?.setNavigationBarHidden(true, animated: false)
}
// MARK: - API // MARK: - API
private func requestRechargeInfo() { private func requestRechargeInfo() {
DLToast.showLoading() DLToast.showLoading()
@ -131,29 +126,29 @@ class PromotionalActivitiesVC: BaseViewController {
return return
} }
// if timeConfig.pay_pop_type == 3 { if timeConfig.pay_pop_type == 3 {
// IAPManager.shared.purchase(goodsId: selectedGoodsId) { [weak self] success, msg in IAPManager.shared.purchase(goodsId: selectedGoodsId) { [weak self] success, msg in
// guard let self = self else { return } guard let self = self else { return }
// if success { if success {
// self.showPayResultPop(showCloseBtn: false, self.showPayResultPop(showCloseBtn: false,
// status: true, status: true,
// title: "", title: "支付成功",
// message: "!", message: "恭喜您!成功开通!",
// confirmText: "", confirmBlock: { confirmText: "确定", confirmBlock: {
// AppRouter.shared.popOrDismiss() AppRouter.shared.popOrDismiss()
// }, cancelBlock: { }) }, cancelBlock: { })
// } else { } else {
// self.showPayResultPop(status: false, self.showPayResultPop(status: false,
// title: "", title: "支付失败",
// message: msg ?? "", message: msg ?? "很抱歉,请您重新支付!",
// confirmText: "", confirmBlock: { }, confirmText: "重新支付", confirmBlock: { },
// cancelText: "", cancelBlock: { cancelText: "取消", cancelBlock: {
// AppRouter.shared.popOrDismiss() AppRouter.shared.popOrDismiss()
// }) })
// } }
// } }
// return return
// } }
let payType = timeConfig.pay_pop_type == 1 ? "alipay" : "weixin" let payType = timeConfig.pay_pop_type == 1 ? "alipay" : "weixin"
dl.showLoading() dl.showLoading()
@ -163,20 +158,16 @@ class PromotionalActivitiesVC: BaseViewController {
guard let data = response.data else { return } guard let data = response.data else { return }
if payType == "weixin" { // if payType == "weixin" { //
guard let partnerId = data["partnerId"] as? String, // WXApi.registerApp(model.appId, universalLink: AppSettings.kAppsUniversalLink)
let prepayId = data["prepayId"] as? String, //
let package = data["package"] as? String, // let request: PayReq = PayReq()
let nonceStr = data["nonceStr"] as? String, // request.partnerId = model.partnerId
let timeStamp = data["timeStamp"] as? String, // request.prepayId = model.prepayId
let sign = data["sign"] as? String else { return } // request.package = model.packageValue
let request: PayReq = PayReq() // request.nonceStr = model.nonceStr
request.partnerId = partnerId // request.timeStamp = UInt32(model.timeStamp) ?? 0
request.prepayId = prepayId // request.sign = model.sign
request.package = package // WXApi.send(request)
request.nonceStr = nonceStr
request.timeStamp = UInt32(timeStamp) ?? 0
request.sign = sign
WXApi.send(request)
} }
else if payType == "alipay" { // else if payType == "alipay" { //
if let payParam = data["payParam"] as? String, let appId = data["payParam"] as? String { if let payParam = data["payParam"] as? String, let appId = data["payParam"] as? String {

View File

@ -533,7 +533,7 @@ class PromotionalRecommendCell: UITableViewCell {
tipsTitleLab.layoutChain tipsTitleLab.layoutChain
.centerX() .centerX()
.top(7) .top(5)
priceLab.layoutChain priceLab.layoutChain
.leftToRightOfView(unitLab, offset: 0) .leftToRightOfView(unitLab, offset: 0)

View File

@ -110,9 +110,6 @@ class CreateScheduleVC: BaseViewController, MAMapViewDelegate {
} }
}, onError: { error in }, onError: { error in
guard let code = error.underlyingError?.code else { return } guard let code = error.underlyingError?.code else { return }
guard let systemConfig = AppContextManager.shared.systemConfig, systemConfig.globalDisplay else { return }
if code == 20010 { // "" if code == 20010 { // ""
CreateScheduleVipPopView.show() CreateScheduleVipPopView.show()
} }
@ -238,7 +235,7 @@ class CreateScheduleVC: BaseViewController, MAMapViewDelegate {
.observe(on: MainScheduler.asyncInstance) .observe(on: MainScheduler.asyncInstance)
.subscribe(onNext: { [weak self] items in .subscribe(onNext: { [weak self] items in
guard let self = self else { return } guard let self = self else { return }
let h = max(CGFloat(items.count) * 129, 129) let h = max(CGFloat(items.count) * 122, 122)
self.popView.tableView.layoutChain.height(h) self.popView.tableView.layoutChain.height(h)
self.refreshMapPoints() self.refreshMapPoints()
}) })
@ -363,9 +360,7 @@ class CreateScheduleVC: BaseViewController, MAMapViewDelegate {
// //
if !pointAnnotations.isEmpty { if !pointAnnotations.isEmpty {
rootView.mapView.showAnnotations(pointAnnotations, rootView.mapView.showAnnotations(pointAnnotations, animated: true)
edgePadding: UIEdgeInsets(top: kNaviHeight + 20, left: 30, bottom: kScreenHeight / 3 + 20, right: 30),
animated: true)
} }
#endif #endif
} }

View File

@ -217,7 +217,7 @@ class CreateScheduleView: UIView {
mv.showsUserLocation = false mv.showsUserLocation = false
mv.showsCompass = false mv.showsCompass = false
mv.userTrackingMode = .none mv.userTrackingMode = .none
DispatchQueue.main.async { mv.logoCenter = CGPoint(x: kScreenWidth - 50, y: kScreenHeight / 3 * 2 - 20) } DispatchQueue.main.async { mv.logoCenter = CGPoint(x: mv.bounds.width - 55, y: kNaviHeight) }
return mv return mv
}() }()
#endif #endif

View File

@ -85,7 +85,7 @@ class ItineraryDetailView: UIView {
mv.showsUserLocation = false mv.showsUserLocation = false
mv.showsCompass = false mv.showsCompass = false
mv.userTrackingMode = .none mv.userTrackingMode = .none
// DispatchQueue.main.async { mv.logoCenter = CGPoint(x: mv.bounds.width - 55, y: kNaviHeight) } DispatchQueue.main.async { mv.logoCenter = CGPoint(x: mv.bounds.width - 55, y: kNaviHeight) }
return mv return mv
}() }()

View File

@ -59,7 +59,7 @@ class LocationPickerView: UIView {
bottomView.layoutChain bottomView.layoutChain
.edgesHorzontal() .edgesHorzontal()
.bottom() .bottom()
.height(160 + kSafeBottomMargin) .height(160)
poiNameLab.layoutChain poiNameLab.layoutChain
.top(16).left(16).right(16) .top(16).left(16).right(16)
@ -81,7 +81,7 @@ class LocationPickerView: UIView {
mv.zoomLevel = 18 mv.zoomLevel = 18
mv.showsUserLocation = false mv.showsUserLocation = false
mv.showsCompass = false mv.showsCompass = false
// DispatchQueue.main.async { mv.logoCenter = CGPoint(x: mv.bounds.width - 55, y: kNaviHeight) } DispatchQueue.main.async { mv.logoCenter = CGPoint(x: mv.bounds.width - 55, y: 25) }
return mv return mv
}() }()
#endif #endif

View File

@ -36,9 +36,6 @@ class ScheduleDetailVC: BaseViewController {
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
guard let systemConfig = AppContextManager.shared.systemConfig, systemConfig.globalDisplay else { return }
rootView.vipTipsLab.text = AppContextManager.shared.vip > 1 ? "" : "升级 VIP可查看具体人员与节点" rootView.vipTipsLab.text = AppContextManager.shared.vip > 1 ? "" : "升级 VIP可查看具体人员与节点"
} }

View File

@ -55,16 +55,6 @@ class ScheduleVC: BaseViewController {
self.rootView.tableView.refresh(status: status, isEmpty: isEmpty) self.rootView.tableView.refresh(status: status, isEmpty: isEmpty)
}).disposed(by: disposeBag) }).disposed(by: disposeBag)
viewModel.output.sectionedItems
.map { !($0.first?.items.isEmpty ?? true) }
.bind(to: rootView.emptyVisitorsLabel.rx.isHidden)
.disposed(by: disposeBag)
viewModel.output.scheduleSectionedItems
.map { !($0.first?.items.isEmpty ?? true) }
.bind(to: rootView.emptyScheduleLabel.rx.isHidden)
.disposed(by: disposeBag)
rootView.collectionView.rx.modelSelected(ViewedModel.self) rootView.collectionView.rx.modelSelected(ViewedModel.self)
.subscribe(viewModel.viewedCellAction.inputs) .subscribe(viewModel.viewedCellAction.inputs)
.disposed(by: disposeBag) .disposed(by: disposeBag)

View File

@ -129,12 +129,6 @@ class ScheduleView: UIView {
.height(80) .height(80)
.bottom(15) .bottom(15)
// 访
view.addSubview(emptyVisitorsLabel)
emptyVisitorsLabel.layoutChain
.centerY(collectionView)
.centerX()
return view return view
}() }()
@ -151,16 +145,6 @@ class ScheduleView: UIView {
return cv return cv
}() }()
lazy var emptyVisitorsLabel: UILabel = {
let label = UILabel()
label.text = "暂无访客"
label.font = .systemFont(ofSize: 14)
label.textColor = UIColor(hexStr: "#999999")
label.textAlignment = .center
label.isHidden = true
return label
}()
/// 线 /// 线
lazy var travelRouteView: UIView = { lazy var travelRouteView: UIView = {
let view = UIView() let view = UIView()
@ -229,20 +213,9 @@ class ScheduleView: UIView {
tableView.showsVerticalScrollIndicator = false tableView.showsVerticalScrollIndicator = false
tableView.register(ScheduleListPopCell.self) tableView.register(ScheduleListPopCell.self)
tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 97 + kSafeBottomMargin, right: 0) tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 97 + kSafeBottomMargin, right: 0)
tableView.backgroundView = emptyScheduleLabel
return tableView return tableView
}() }()
lazy var emptyScheduleLabel: UILabel = {
let label = UILabel()
label.text = "暂无行程"
label.font = .systemFont(ofSize: 14)
label.textColor = UIColor(hexStr: "#999999")
label.textAlignment = .center
label.isHidden = true
return label
}()
lazy var createBtn: UIButton = { lazy var createBtn: UIButton = {
let btn = UIButton() let btn = UIButton()
btn.setImage(UIImage(named: "Schedule/create"), for: .normal) btn.setImage(UIImage(named: "Schedule/create"), for: .normal)

View File

@ -6,7 +6,6 @@
// //
import UIKit import UIKit
import Kingfisher
class SharePopView: UIView { class SharePopView: UIView {
@ -15,13 +14,14 @@ class SharePopView: UIView {
private let contentHeight: CGFloat = 191 + kSafeBottomMargin private let contentHeight: CGFloat = 191 + kSafeBottomMargin
static func show() { static func show(shareURL: String) {
guard let superView = kKeyWindow else { return } guard let superView = kKeyWindow else { return }
if SharePopView.shared.superview != nil { if SharePopView.shared.superview != nil {
SharePopView.shared.dismiss(animated: false) SharePopView.shared.dismiss(animated: false)
} }
SharePopView.shared.shareURL = shareURL
SharePopView.shared.bgView.alpha = 0 SharePopView.shared.bgView.alpha = 0
superView.addSubview(SharePopView.shared) superView.addSubview(SharePopView.shared)
superView.bringSubviewToFront(SharePopView.shared) superView.bringSubviewToFront(SharePopView.shared)
@ -65,29 +65,10 @@ class SharePopView: UIView {
} }
private func shareToWeChat(scene: Int32) { private func shareToWeChat(scene: Int32) {
guard let config = AppContextManager.shared.systemConfig,
let shareConfig = config.shareConfig else { return }
DLToast.showLoading()
let fallbackImage = UIImage(named: "Common/logo108")
let imageURL: URL? = {
if shareConfig.image.isEmpty { return nil }
return URL(string: shareConfig.image)
}()
let sendMessage: (UIImage?) -> Void = { [weak self] thumbImage in
guard let self = self else { return }
DLToast.dismiss()
let message = WXMediaMessage() let message = WXMediaMessage()
message.title = shareConfig.title message.title = kAppName
message.description = shareConfig.content
if let thumb = thumbImage {
message.setThumbImage(thumb)
}
let webpage = WXWebpageObject() let webpage = WXWebpageObject()
webpage.webpageUrl = shareConfig.link webpage.webpageUrl = shareURL
message.mediaObject = webpage message.mediaObject = webpage
let req = SendMessageToWXReq() let req = SendMessageToWXReq()
@ -96,21 +77,7 @@ class SharePopView: UIView {
req.scene = scene req.scene = scene
WXApi.send(req) WXApi.send(req)
self.dismiss() dismiss()
}
if let url = imageURL {
KingfisherManager.shared.retrieveImage(with: url) { result in
switch result {
case .success(let value):
sendMessage(value.image)
case .failure:
sendMessage(fallbackImage)
}
}
} else {
sendMessage(fallbackImage)
}
} }
// MARK: - UI // MARK: - UI

View File

@ -29,11 +29,6 @@ class VipRechargeVC: BaseViewController {
requestRechargeInfo() requestRechargeInfo()
} }
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
navigationController?.setNavigationBarHidden(true, animated: false)
}
private func bindViewModel() { private func bindViewModel() {
viewModel.output.sectionedItems viewModel.output.sectionedItems
.bind(to: rootView.expenseCollectionView.rx.items(dataSource: dataSource)) .bind(to: rootView.expenseCollectionView.rx.items(dataSource: dataSource))
@ -107,29 +102,29 @@ class VipRechargeVC: BaseViewController {
let types = viewModel.payType.components(separatedBy: ",").map { $0.trimmingCharacters(in: .whitespaces) } let types = viewModel.payType.components(separatedBy: ",").map { $0.trimmingCharacters(in: .whitespaces) }
let payType = types[rootView.selectedPayTypeTag] let payType = types[rootView.selectedPayTypeTag]
// if payType == "apple" { if payType == "apple" {
// IAPManager.shared.purchase(goodsId: viewModel.goodsId) { [weak self] success, msg in IAPManager.shared.purchase(goodsId: viewModel.goodsId) { [weak self] success, msg in
// guard let self = self else { return } guard let self = self else { return }
// if success { if success {
// self.showPayResultPop(showCloseBtn: false, self.showPayResultPop(showCloseBtn: false,
// status: true, status: true,
// title: "", title: "支付成功",
// message: "\(self.viewModel.goodsName)", message: "恭喜您!成功开通\(self.viewModel.goodsName)",
// confirmText: "", confirmBlock: { confirmText: "确定", confirmBlock: {
// AppRouter.shared.popOrDismiss() AppRouter.shared.popOrDismiss()
// }, cancelBlock: { }) }, cancelBlock: { })
// } else { } else {
// self.showPayResultPop(status: false, self.showPayResultPop(status: false,
// title: "", title: "支付失败",
// message: msg ?? "", message: msg ?? "很抱歉,请您重新支付!",
// confirmText: "", confirmBlock: { }, confirmText: "重新支付", confirmBlock: { },
// cancelText: "", cancelBlock: { cancelText: "取消", cancelBlock: {
// AppRouter.shared.popOrDismiss() AppRouter.shared.popOrDismiss()
// }) })
// } }
// } }
// return return
// } }
DLToast.showLoading() DLToast.showLoading()
OrderService.orderPayParams(goodsId: viewModel.goodsId, OrderService.orderPayParams(goodsId: viewModel.goodsId,
@ -138,20 +133,16 @@ class VipRechargeVC: BaseViewController {
let payType = types[self.rootView.selectedPayTypeTag] let payType = types[self.rootView.selectedPayTypeTag]
if payType == "weixin" { // if payType == "weixin" { //
guard let partnerId = data["partnerId"] as? String, // WXApi.registerApp(model.appId, universalLink: AppSettings.kAppsUniversalLink)
let prepayId = data["prepayId"] as? String, //
let package = data["package"] as? String, // let request: PayReq = PayReq()
let nonceStr = data["nonceStr"] as? String, // request.partnerId = model.partnerId
let timeStamp = data["timeStamp"] as? String, // request.prepayId = model.prepayId
let sign = data["sign"] as? String else { return } // request.package = model.packageValue
let request: PayReq = PayReq() // request.nonceStr = model.nonceStr
request.partnerId = partnerId // request.timeStamp = UInt32(model.timeStamp) ?? 0
request.prepayId = prepayId // request.sign = model.sign
request.package = package // WXApi.send(request)
request.nonceStr = nonceStr
request.timeStamp = UInt32(timeStamp) ?? 0
request.sign = sign
WXApi.send(request)
} }
else if payType == "alipay" { // else if payType == "alipay" { //
if let payParam = data["payParam"] as? String, let appId = data["payParam"] as? String { if let payParam = data["payParam"] as? String, let appId = data["payParam"] as? String {

View File

@ -99,7 +99,7 @@ class VipRechargeView: UIView {
.heightToWidth(267/375) .heightToWidth(267/375)
vipRightsDetailView.layoutChain vipRightsDetailView.layoutChain
.top(36 + kStatusBarHeight) .top(36)
.right() .right()
.height(24) .height(24)
@ -562,7 +562,7 @@ class VipRechargeView: UIView {
let payTypeMap: [(String, String)] = types.compactMap { let payTypeMap: [(String, String)] = types.compactMap {
if $0 == "weixin" { return ("wechat", "微信支付") } if $0 == "weixin" { return ("wechat", "微信支付") }
if $0 == "alipay" { return ("alipay", "支付宝支付") } if $0 == "alipay" { return ("alipay", "支付宝支付") }
// if $0 == "apple" { return ("apple", "") } if $0 == "apple" { return ("apple", "苹果支付") }
return nil return nil
} }
guard !payTypeMap.isEmpty else { return } guard !payTypeMap.isEmpty else { return }

View File

@ -168,11 +168,7 @@ class FullscreenWebView: WKWebView {
super.viewDidLoad() super.viewDidLoad()
fd_interactivePopDisabled = true fd_interactivePopDisabled = true
if style == "default" { if style == "default" {
let btn = UIButton(type: .system) // setupLeftBarButtonItem(iconColor: "gray")
btn.setImage(UIImage(named: "Common/back"), for: .normal)
btn.tintColor = UIColor(hexStr: "#0F2846")
btn.addTarget(self, action: #selector(leftBackClicked(_:)), for: .touchUpInside)
navigationItem.leftBarButtonItem = UIBarButtonItem(customView: btn)
} }
// setupErrorView() // setupErrorView()
setupView() setupView()
@ -316,16 +312,16 @@ class FullscreenWebView: WKWebView {
// backItem.tag = 1 // backItem.tag = 1
let backBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 19, height: 19)) let backBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 19, height: 19))
backBtn.setImage(UIImage(named: "Common/back"), for: .normal) backBtn.setImage(UIImage(named: "Common/back_\(iconColor)"), for: .normal)
backBtn.addTarget(self, action: #selector(leftBackClicked(_:)), for: .touchUpInside) backBtn.addTarget(self, action: #selector(leftBackClicked(_:)), for: .touchUpInside)
backBtn.tintColor = .black backBtn.tintColor = iconColor=="white" ? .white : .black
backBtn.tag = 1 backBtn.tag = 1
let backItem = UIBarButtonItem(customView: backBtn) let backItem = UIBarButtonItem(customView: backBtn)
let popBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 19, height: 19)) let popBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 19, height: 19))
popBtn.setImage(UIImage(named: "Common/x_black"), for: .normal) popBtn.setImage(UIImage(named: "Common/close_black"), for: .normal)
popBtn.addTarget(self, action: #selector(leftBackClicked(_:)), for: .touchUpInside) popBtn.addTarget(self, action: #selector(leftBackClicked(_:)), for: .touchUpInside)
popBtn.tintColor = .black popBtn.tintColor = iconColor=="white" ? .white : .black
popBtn.tag = 2 popBtn.tag = 2
let popItem = UIBarButtonItem(customView: popBtn) let popItem = UIBarButtonItem(customView: popBtn)